users@jersey.java.net

Re: [Jersey] Issue with Provider redirection

From: Pavel Bucek <Pavel.Bucek_at_Sun.COM>
Date: Mon, 09 Aug 2010 16:53:18 +0200

On 8/9/10 3:26 PM, Paul Sandoz wrote:
>
> On Aug 9, 2010, at 2:58 PM, Pavel Bucek wrote:
>
>> Hello,
>>
>> I took a look into this problem and.. if you declare which mime types
>> your message writer produces, it works as expected:
>>
>> @Provider
>> @Produces("application/xml,text/xml,*/*")
>> public class MyProvider<T extends Apple> implements MessageBodyWriter<T>
>>
>> (consider this as a quick workaround, I'm still investigating about
>> this..)
>>
>
> This looks like a bug as user registered providers should override any
> of those supplied by Jersey regardless of the @Produces annotation.

I don't see any place where Jersey implementation somehow differs in
handling user registered providers versus jersey provided.

See ProviderServices.java
private Set<ProviderClass> getProviderAndServiceClasses(Class<?> service)

Do we need to change that? Or add method which will decide whether some
particular provider is user provided? And if is, put it on top of
matching queue in all media types?

Pavel

>
> Paul.
>
>> Pavel
>>
>> On 8/9/10 10:47 AM, Guilhem wrote:
>>> Hi paul,
>>>
>>> i'm using jersey 1.3, I have made a little error in my previous that
>>> i realize while creating a simple test case : my problem don't
>>> happen when i use a non-standard MIME Type like:
>>>
>>> application/vnd.ogc.xml
>>>
>>> This problem happen when i use application/xml or text/xml, this is
>>> probably a way to search.
>>>
>>> so I create a simple case and reproduce the bug, here are my classes :
>>>
>>> _my singleton _
>>>
>>> package test.provider;
>>>
>>> import com.sun.jersey.spi.resource.Singleton;
>>> import javax.ws.rs.GET;
>>> import javax.ws.rs.Path;
>>> import javax.ws.rs.core.Context;
>>> import javax.ws.rs.core.Response;
>>> import javax.ws.rs.core.UriInfo;
>>> import test.model.Apple;
>>>
>>> @Path("sos")
>>> @Singleton
>>> public class MySingleton {
>>>
>>> @Context
>>> private volatile UriInfo uriContext;
>>>
>>> @GET
>>> public Response doGET() {
>>> String outputFormat =
>>> uriContext.getQueryParameters().getFirst("output");
>>> if (outputFormat == null) {
>>> outputFormat = "text/xml";
>>> }
>>> Apple a = new Apple();
>>> return Response.ok(a, outputFormat).build();
>>> }
>>> }
>>>
>>>
>>> _my message body writer:_
>>>
>>> package test.provider;
>>>
>>> import java.io.IOException;
>>> import java.io.OutputStream;
>>> import java.lang.annotation.Annotation;
>>> import java.lang.reflect.Type;
>>> import java.util.logging.Logger;
>>> import javax.ws.rs.WebApplicationException;
>>> import javax.ws.rs.core.MediaType;
>>> import javax.ws.rs.core.MultivaluedMap;
>>> import javax.ws.rs.ext.MessageBodyWriter;
>>> import javax.ws.rs.ext.Provider;
>>> import javax.xml.bind.JAXBContext;
>>> import javax.xml.bind.JAXBException;
>>> import javax.xml.bind.Marshaller;
>>> import test.model.Apple;
>>>
>>> @Provider
>>> public class MyProvider<T extends Apple> implements
>>> MessageBodyWriter<T> {
>>>
>>> private static final Logger LOGGER =
>>> Logger.getLogger("test.provider");
>>>
>>>
>>> @Override
>>> public boolean isWriteable(Class<?> type, Type type1,
>>> Annotation[] antns, MediaType mt) {
>>> System.out.println("isWritable:" +
>>> Apple.class.isAssignableFrom(type));
>>> return Apple.class.isAssignableFrom(type);
>>> }
>>>
>>> @Override
>>> public long getSize(T t, Class<?> type, Type type1, Annotation[]
>>> antns, MediaType mt) {
>>> System.out.println("get size");
>>> return -1;
>>> }
>>>
>>> @Override
>>> public void writeTo(T t, Class<?> type, Type type1, Annotation[]
>>> antns, MediaType mt, MultivaluedMap<String, Object> mm, OutputStream
>>> out) throws IOException, WebApplicationException {
>>> System.out.println("write to");
>>> try {
>>> Marshaller m =
>>> JAXBContext.newInstance(Apple.class).createMarshaller();
>>> m.marshal(t, out);
>>> } catch (JAXBException ex) {
>>> LOGGER.severe("JAXB exception while writing the
>>> capabilities File");
>>> }
>>> }
>>>
>>> }
>>>
>>> and a simple model object
>>>
>>> package test.model;
>>>
>>> import javax.xml.bind.annotation.XmlElement;
>>> import javax.xml.bind.annotation.XmlRootElement;
>>>
>>> @XmlRootElement(name="Apple")
>>> public class Apple {
>>>
>>> @XmlElement
>>> public String colour;
>>>
>>> }
>>>
>>> I use the system.out to see if i enter the messageBodyWriter
>>>
>>> if i make a request :
>>> http://localhost:8080/Test-provider/sos?output=application/xml or
>>> http://localhost:8080/Test-provider/sos?output=text/xml or
>>> http://localhost:8080/Test-provider/sos
>>>
>>> ==> nothing in the log
>>>
>>> if i make a request :
>>> http://localhost:8080/Test-provider/sos?output=app/xml
>>>
>>> ==> in the log :
>>> isWritable:true
>>> get size
>>> write to
>>>
>>> So the problem here i think is relative to unrecognized mime Type.
>>>
>>> Guilhem Legal
>>>
>>>
>>> On 09/08/2010 08:06, Paul Sandoz wrote:
>>>> Hi Guilhem,
>>>>
>>>> What version of Jersey are you using?
>>>>
>>>> It seems like when you use text/xml Jersey is processing and that
>>>> results in an exception due to some JAXB error, possibly because by
>>>> default Jersey will create a JAXBContext from the class and that
>>>> may be lacking some additional information than if you created the
>>>> JAXBContext.
>>>>
>>>> The code to process text/xml and application/xml goes through the
>>>> same path so you should be able to override both or indeed any JAXB
>>>> support supplied by Jersey if your own MessageBodyWriter
>>>> implementation is registered. Would it be possible to send a simple
>>>> reproducible test case?
>>>>
>>>> Note that you can also define your own ContextResolver<Marshaller>
>>>> that can pool Marshaller instances per-thread (as they are not
>>>> thread safe and reuse the existing JAXB support.
>>>>
>>>> Paul.
>>>>
>>>> On Aug 6, 2010, at 5:58 PM, Guilhem wrote:
>>>>
>>>>> Hello,
>>>>>
>>>>> I'm using jersey in a WebService to produce XML object marshalled
>>>>> with JAXB.
>>>>> I want to use my own JAXBContext so i create a Jersey provider to
>>>>> handle the marshalling of my object.
>>>>>
>>>>> My problem is that when i use the MIME type aplication/xml, my
>>>>> provider is well used, but when i use the MIME type text/XML
>>>>> jersey generate his own marshaller and so failed to create the
>>>>> JAXBContext (because it is a little hard).
>>>>>
>>>>>
>>>>> here is my provider (simplified) :
>>>>>
>>>>> import**;
>>>>>
>>>>> @Provider
>>>>> public class CapabilitiesWriter<T extends Capabilities> implements
>>>>> MessageBodyWriter<T> {
>>>>>
>>>>> private static final MarshallerPool pool;
>>>>> static {
>>>>> MarshallerPool pool = // here i build a sort of marshaller
>>>>> }
>>>>>
>>>>> @Override
>>>>> public boolean isWriteable(Class<?> type, Type type1,
>>>>> Annotation[] antns, MediaType mt) {
>>>>> return Capabilities.class.isAssignableFrom(type);
>>>>> }
>>>>>
>>>>> @Override
>>>>> public long getSize(T t, Class<?> type, Type type1,
>>>>> Annotation[] antns, MediaType mt) {
>>>>> return -1;
>>>>> }
>>>>>
>>>>> @Override
>>>>> public void writeTo(T t, Class<?> type, Type type1,
>>>>> Annotation[] antns, MediaType mt, MultivaluedMap<String, Object>
>>>>> mm, OutputStream out) throws IOException, WebApplicationException {
>>>>> Marshaller m = // here i get my marshaller;
>>>>> m.marshal(t, out);
>>>>> }
>>>>>
>>>>> }
>>>>>
>>>>> and in my singleton I return a Response object like this :
>>>>>
>>>>> @GET
>>>>> public Response doGET() throws JAXBException {
>>>>> String currentMIME_Type = "something"; // here i have some
>>>>> process to choose the MIME type
>>>>> Capabilities capa = something; // again i
>>>>> have some process building the object
>>>>>
>>>>> return Response.ok(capa, currentMIME_Type).build();
>>>>> }
>>>>>
>>>>>
>>>>> if "currentMIME_Type"=application/xml allright everything is
>>>>> fine, i enter in the method writeTo of my provider
>>>>> CapabilitiesWriter.
>>>>>
>>>>> if "currentMIME_Type"=text/xml i get a JAXB Exception at (I have
>>>>> 2 stack trace, don't know why) :
>>>>>
>>>>> at
>>>>> com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider.writeTo(AbstractRootElementProvider.java:152)
>>>>>
>>>>> at
>>>>> com.sun.jersey.spi.container.ContainerResponse.write(ContainerResponse.java:294)
>>>>>
>>>>> at
>>>>> com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1140)
>>>>>
>>>>> at
>>>>> com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1053)
>>>>>
>>>>> at
>>>>> com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1043)
>>>>>
>>>>> at
>>>>> com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:406)
>>>>>
>>>>> at
>>>>> com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:477)
>>>>>
>>>>> at
>>>>> com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:662)
>>>>>
>>>>> at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
>>>>> at
>>>>> org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
>>>>>
>>>>> at
>>>>> org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
>>>>>
>>>>> at
>>>>> org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:243)
>>>>>
>>>>> at
>>>>> org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:201)
>>>>>
>>>>> at
>>>>> org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:163)
>>>>>
>>>>> at
>>>>> org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:108)
>>>>>
>>>>> at
>>>>> org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:556)
>>>>>
>>>>> at
>>>>> org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
>>>>>
>>>>> at
>>>>> org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:402)
>>>>>
>>>>> at
>>>>> org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:249)
>>>>>
>>>>> at
>>>>> org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:267)
>>>>>
>>>>> at
>>>>> org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:245)
>>>>>
>>>>> at
>>>>> org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:260)
>>>>>
>>>>> at
>>>>> java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
>>>>>
>>>>> at
>>>>> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
>>>>>
>>>>> at java.lang.Thread.run(Thread.java:619)
>>>>>
>>>>>
>>>>> at
>>>>> com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:91)
>>>>>
>>>>> at
>>>>> com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:436)
>>>>>
>>>>> at
>>>>> com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:277)
>>>>>
>>>>> at
>>>>> com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1100)
>>>>>
>>>>> at
>>>>> com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:143)
>>>>>
>>>>> at
>>>>> com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:110)
>>>>>
>>>>> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>>>>> at
>>>>> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
>>>>>
>>>>> at
>>>>> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
>>>>>
>>>>> at java.lang.reflect.Method.invoke(Method.java:597)
>>>>> at
>>>>> javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:202)
>>>>> at javax.xml.bind.ContextFinder.find(ContextFinder.java:376)
>>>>> at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:574)
>>>>> at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:522)
>>>>> at
>>>>> com.sun.jersey.core.provider.jaxb.AbstractJAXBProvider.getStoredJAXBContext(AbstractJAXBProvider.java:184)
>>>>>
>>>>> at
>>>>> com.sun.jersey.core.provider.jaxb.AbstractJAXBProvider.getJAXBContext(AbstractJAXBProvider.java:177)
>>>>>
>>>>> at
>>>>> com.sun.jersey.core.provider.jaxb.AbstractJAXBProvider.getMarshaller(AbstractJAXBProvider.java:155)
>>>>>
>>>>> at
>>>>> com.sun.jersey.core.provider.jaxb.AbstractJAXBProvider.getMarshaller(AbstractJAXBProvider.java:134)
>>>>>
>>>>> at
>>>>> com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider.writeTo(AbstractRootElementProvider.java:145)
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> so my question is, why the MIME type change the way of using
>>>>> provider? and how redirect all mime type to my provider?
>>>>>
>>>>> Thanks,
>>>>>
>>>>> Guilhem legal
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>>>>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>>>>
>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>>>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>>>
>>>>
>>>>
>>>
>>
>