You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@Override
protected boolean hasMatchingMediaType(MediaType mediaType)
{
/* As suggested by Stephen D, there are 2 ways to check: either
* being as inclusive as possible (if subtype is "json"), or
* exclusive (major type "application", minor type "json").
* Let's start with inclusive one, hard to know which major
* types we should cover aside from "application".
*/
if (mediaType != null) {
// Ok: there are also "xxx+json" subtypes, which count as well
String subtype = mediaType.getSubtype();
// [Issue#14]: also allow 'application/javascript'
return "json".equalsIgnoreCase(subtype) || subtype.endsWith("+json")
|| "javascript".equals(subtype)
// apparently Microsoft once again has interesting alternative types?
|| "x-javascript".equals(subtype)
|| "x-json".equals(subtype) // [Issue#40]
;
}
/* Not sure if this can happen; but it seems reasonable
* that we can at least produce JSON without media type?
*/
return true;
}
and so when MediaType.WILDCARD, that literally comes from the annotation (picked up here) of the very same class gets passed back into its hasMatchingMediaType, it returns false, basically saying it cant be used to produce the very thing it says it can handle producing.
so it never gets picked up in situations when it SHOULD be getting picked up.
example situation is if we want to return a random class that have nothing setup for content-type, this can happen when we are using a ErrorHandler from a lib, and the lib does not know if the service will want json or xml, so it cant specify the content-type, but it should get encoded by the default the service has setup, and this case json. but instead of trying to encode this object in json, something JacksonJaxbJsonProvider can do, it falls through to the next encoder, text and that fails.
to demonstrate the issue i have made 2 exactly the same apps, one uses jackson, the other one uses jsonb
the jsonb one works, the jackson one fails
jackson_vs_jsonb.zip
to run, open both projects in intellij and then run all the tests, in the jackson one there will be one test failure
this is because the jsonb one correctly has @Produces({"application/json", "text/json", "*/*"}) on its JsonBindingProvider
here is the stack trace of it calling hasMatchingMediaType with the MediaType specified in @Produces(MediaType.WILDCARD)
java.lang.Exception: Stack trace
at java.base/java.lang.Thread.dumpStack(Thread.java:2209)
at org.glassfish.jersey.jackson.internal.jackson.jaxrs.json.JacksonJsonProvider.hasMatchingMediaType(JacksonJsonProvider.java:189)
at org.glassfish.jersey.jackson.internal.jackson.jaxrs.base.ProviderBase.isWriteable(ProviderBase.java:551)
at org.glassfish.jersey.message.internal.MessageBodyFactory.isWriteable(MessageBodyFactory.java:1146)
at org.glassfish.jersey.message.WriterModel.isWriteable(WriterModel.java:63)
at org.glassfish.jersey.internal.routing.ContentTypeDeterminer.determineResponseMediaType(ContentTypeDeterminer.java:94)
at org.glassfish.jersey.server.internal.routing.AbstractMethodSelectingRouter.determineResponseMediaType(AbstractMethodSelectingRouter.java:495)
at org.glassfish.jersey.server.internal.routing.AbstractMethodSelectingRouter$3.apply(AbstractMethodSelectingRouter.java:437)
at org.glassfish.jersey.server.internal.routing.AbstractMethodSelectingRouter$3.apply(AbstractMethodSelectingRouter.java:428)
at org.glassfish.jersey.process.internal.Stages$LinkedStage.apply(Stages.java:284)
at org.glassfish.jersey.process.internal.Stages.process(Stages.java:147)
at org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.java:396)
at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:450)
at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:282)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)
at org.glassfish.jersey.internal.Errors.process(Errors.java:292)
at org.glassfish.jersey.internal.Errors.process(Errors.java:274)
at org.glassfish.jersey.internal.Errors.process(Errors.java:244)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:266)
at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:253)
at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:696)
at io.helidon.microprofile.server.JaxRsService.doHandle(JaxRsService.java:228)
at io.helidon.microprofile.server.JaxRsService.lambda$handle$2(JaxRsService.java:185)
at io.helidon.common.context.Contexts.runInContext(Contexts.java:117)
at io.helidon.microprofile.server.JaxRsService.handle(JaxRsService.java:185)
at io.helidon.webserver.http.HttpRoutingImpl$RoutingExecutor.doRoute(HttpRoutingImpl.java:165)
at io.helidon.webserver.http.HttpRoutingImpl$RoutingExecutor.call(HttpRoutingImpl.java:124)
at io.helidon.webserver.http.HttpRoutingImpl$RoutingExecutor.call(HttpRoutingImpl.java:102)
at io.helidon.webserver.http.ErrorHandlers.runWithErrorHandling(ErrorHandlers.java:76)
at io.helidon.webserver.http.Filters$FilterChainImpl.proceed(Filters.java:121)
at io.helidon.webserver.observe.metrics.MetricsFeature.lambda$configureVendorMetrics$2(MetricsFeature.java:90)
at io.helidon.webserver.http.Filters$FilterChainImpl.proceed(Filters.java:119)
at io.helidon.common.context.Contexts.runInContext(Contexts.java:117)
at io.helidon.webserver.context.ContextRoutingFeature.filter(ContextRoutingFeature.java:50)
at io.helidon.webserver.http.Filters$FilterChainImpl.proceed(Filters.java:119)
at io.helidon.webserver.http.Filters.executeFilters(Filters.java:87)
at io.helidon.webserver.http.Filters.lambda$filter$0(Filters.java:83)
at io.helidon.webserver.http.ErrorHandlers.runWithErrorHandling(ErrorHandlers.java:76)
at io.helidon.webserver.http.Filters.filter(Filters.java:83)
at io.helidon.webserver.http.HttpRoutingImpl.route(HttpRoutingImpl.java:73)
at io.helidon.webserver.http1.Http1Connection.route(Http1Connection.java:356)
at io.helidon.webserver.http1.Http1Connection.handle(Http1Connection.java:194)
at io.helidon.webserver.ConnectionHandler.run(ConnectionHandler.java:165)
at io.helidon.common.task.InterruptableTask.call(InterruptableTask.java:47)
at io.helidon.webserver.ThreadPerTaskExecutor$ThreadBoundFuture.run(ThreadPerTaskExecutor.java:239)
at java.base/java.lang.VirtualThread.run(VirtualThread.java:309)
resulting error in app:
Caused by: org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=text/plain, type=class my.package.errors.ErrorResponse, genericType=class my.package.errors.ErrorResponse.
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.java:224) ~[jersey-common-3.1.7.jar:?]
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:139) ~[jersey-common-3.1.7.jar:?]
at org.glassfish.jersey.server.internal.JsonWithPaddingInterceptor.aroundWriteTo(JsonWithPaddingInterceptor.java:85) ~[jersey-server-3.1.7.jar:?]
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:139) ~[jersey-common-3.1.7.jar:?]
at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundWriteTo(MappableExceptionWrapperInterceptor.java:61) ~[jersey-server-3.1.7.jar:?]
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:139) ~[jersey-common-3.1.7.jar:?]
at org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.java:1116) ~[jersey-common-3.1.7.jar:?]
at org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.java:691) ~[jersey-server-3.1.7.jar:?]
at org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.java:398) ~[jersey-server-3.1.7.jar:?]
at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:450) ~[jersey-server-3.1.7.jar:?]
at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:282) ~[jersey-server-3.1.7.jar:?]
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:248) ~[jersey-common-3.1.7.jar:?]
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:244) ~[jersey-common-3.1.7.jar:?]
at org.glassfish.jersey.internal.Errors.process(Errors.java:292) ~[jersey-common-3.1.7.jar:?]
at org.glassfish.jersey.internal.Errors.process(Errors.java:274) ~[jersey-common-3.1.7.jar:?]
at org.glassfish.jersey.internal.Errors.process(Errors.java:244) ~[jersey-common-3.1.7.jar:?]
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:266) ~[jersey-common-3.1.7.jar:?]
at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:253) ~[jersey-server-3.1.7.jar:?]
at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:696) ~[jersey-server-3.1.7.jar:?]
at io.helidon.microprofile.server.JaxRsService.doHandle(JaxRsService.java:228) ~[helidon-microprofile-server-4.0.11.jar:4.0.11]
at io.helidon.microprofile.server.JaxRsService.lambda$handle$2(JaxRsService.java:185) ~[helidon-microprofile-server-4.0.11.jar:4.0.11]
at io.helidon.common.context.Contexts.runInContext(Contexts.java:117) ~[helidon-common-context-4.0.11.jar:4.0.11]
at io.helidon.microprofile.server.JaxRsService.handle(JaxRsService.java:185) ~[helidon-microprofile-server-4.0.11.jar:4.0.11]
at io.helidon.webserver.http.HttpRoutingImpl$RoutingExecutor.doRoute(HttpRoutingImpl.java:165) ~[helidon-webserver-4.0.11.jar:4.0.11]
at io.helidon.webserver.http.HttpRoutingImpl$RoutingExecutor.call(HttpRoutingImpl.java:124) ~[helidon-webserver-4.0.11.jar:4.0.11]
at io.helidon.webserver.http.HttpRoutingImpl$RoutingExecutor.call(HttpRoutingImpl.java:102) ~[helidon-webserver-4.0.11.jar:4.0.11]
at io.helidon.webserver.http.ErrorHandlers.runWithErrorHandling(ErrorHandlers.java:76) ~[helidon-webserver-4.0.11.jar:4.0.11]
... 17 more
The text was updated successfully, but these errors were encountered:
cowtowncoder
changed the title
JacksonJaxbJsonProvider has @Produces(MediaType.WILDCARD) and yet hasMatchingMediaType(MediaType.WILDCARD) return false
JacksonJsonProvider has @Produces(MediaType.WILDCARD) and yet hasMatchingMediaType(MediaType.WILDCARD) return false
Aug 23, 2024
the class JacksonJaxbJsonProvider has
@Produces(MediaType.WILDCARD)
but then because JacksonJaxbJsonProvider extends JacksonJsonProvider (that ALSO has
@Produces(MediaType.WILDCARD)
)and JacksonJsonProvider implements the method:
and so when MediaType.WILDCARD, that literally comes from the annotation (picked up here) of the very same class gets passed back into its
hasMatchingMediaType
, it returns false, basically saying it cant be used to produce the very thing it says it can handle producing.so it never gets picked up in situations when it SHOULD be getting picked up.
example situation is if we want to return a random class that have nothing setup for content-type, this can happen when we are using a ErrorHandler from a lib, and the lib does not know if the service will want json or xml, so it cant specify the content-type, but it should get encoded by the default the service has setup, and this case json. but instead of trying to encode this object in json, something JacksonJaxbJsonProvider can do, it falls through to the next encoder, text and that fails.
if we change
@Produces(MediaType.WILDCARD)
to@Produces(MediaType.APPLICATION_JSON)
on JacksonJaxbJsonProvider then it works correctly. here is a PR demonstrating the fix: #194 (also FasterXML/jackson-jakarta-rs-providers#31)to demonstrate the issue i have made 2 exactly the same apps, one uses jackson, the other one uses jsonb
the jsonb one works, the jackson one fails
jackson_vs_jsonb.zip
to run, open both projects in intellij and then run all the tests, in the jackson one there will be one test failure
this is because the jsonb one correctly has
@Produces({"application/json", "text/json", "*/*"})
on its JsonBindingProviderhere is the stack trace of it calling hasMatchingMediaType with the MediaType specified in
@Produces(MediaType.WILDCARD)
resulting error in app:
The text was updated successfully, but these errors were encountered: