users@jersey.java.net

Re: [Jersey] not-working custom provider in Jersey 1.1 (?)

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Wed, 24 Jun 2009 18:32:43 +0200

Hi Bruno,

The media "browser/xml" is not an appropriate media type for JAX-RS
support of JAXB. The following are supported:

   text/xml, application/xml and application/⋆+xml

in an earlier release, i think 1.0.2 and earlier, the JAXB support was
open to any media type, which was a bug, and it was fixed to support
just the above list.

I cannot explain why if you change the value of @Produces on
JAXBXSLResolver that you encounter that error. Such an error should be
independent of that class.

I created a simple project to do something similar to what you are
doing and i cannot reproduce (see attached).

Your JAXBXSLResolver class looks fine. BTW you can define a resolver
for just the Marshaller if you want to avoid extending JAXBContext,
which is what i did in the attached maven project (it formats the
output for a bean).

Maybe we can work from the attached project to see if we can reproduce
things ?

Paul.







On Jun 24, 2009, at 4:55 PM, Bruno De Nys wrote:

> Hi,
>
> I am exploring the possibilities of Jersey and JAX-RS. I want to
> produce an XML-representation of my domain-objects. The XML-should
> contain a "<xsl-stylesheet..." header.
>
> As suggested at http://blogs.sun.com/enterprisetechtips/entry/configuring_json_for_restful_web
> , I created a custom resolver as follows:
>
> package be.kvvcr.thesauri.rest;
>
> import java.util.Arrays;
> import java.util.HashMap;
> import java.util.List;
> import java.util.Map;
>
> import javax.ws.rs.Produces;
> import javax.ws.rs.ext.ContextResolver;
> import javax.ws.rs.ext.Provider;
> import javax.xml.bind.JAXBContext;
>
> import be.kvvcr.thesauri.Attribute;
> import be.kvvcr.thesauri.DescLabel;
> import be.kvvcr.thesauri.Descriptor;
> import be.kvvcr.thesauri.Domain;
> import be.kvvcr.thesauri.Label;
> import be.kvvcr.thesauri.MicroThesaurus;
> import be.kvvcr.thesauri.MultiLingualConcept;
> import be.kvvcr.thesauri.NonDescLabel;
> import be.kvvcr.thesauri.Perm;
> import be.kvvcr.thesauri.ScopeNote;
>
> @Produces({"text/xml"})
> @Provider
> public class JAXBXSLResolver implements ContextResolver<JAXBContext> {
>
> private JAXBContext context;
> private Class[] types = {MultiLingualConcept.class,
> Descriptor.class, Label.class, Attribute.class, DescLabel.class,
> MicroThesaurus.class, Domain.class, ScopeNote.class, Perm.class,
> NonDescLabel.class };
>
> public JAXBXSLResolver() throws Exception {
> Map<String, Object> props = new HashMap<String, Object>();
> System.out.println("instantiating the JAXBXSLResolver");
> this.context = MyJAXBContext.newInstance(types,props);
> }
>
> @Override
> public JAXBContext getContext(Class<?> objectType) {
> JAXBContext returnCtxt = null;
> List<Class> typesList = Arrays.asList(types);
> System.out.println("testing whether " + objectType + " is
> supported...");
> if(typesList.contains(objectType)){
> System.out.println("yes it is...");
> returnCtxt = this.context;
> }
> System.err.println("nope it isn't...");
> return returnCtxt;
> }
> }
>
> And this custom JAXBResolver makes use of the context defined in
> MyJAXBContext:
>
> package be.kvvcr.thesauri.rest;
>
> import java.util.HashMap;
> import java.util.Map;
>
> import javax.xml.bind.JAXBContext;
> import javax.xml.bind.JAXBException;
> import javax.xml.bind.Marshaller;
> import javax.xml.bind.Unmarshaller;
> import javax.xml.bind.Validator;
>
> public final class MyJAXBContext extends JAXBContext{
>
> private final JAXBContext context;
>
> public MyJAXBContext(Class[] classes) throws JAXBException{
> Map<String, Object> props = new HashMap<String, Object>();
> props.put("com.sun.xml.bind.xmlHeaders", "<?xml-stylesheet
> type='text/xsl' href='foobar.xsl' ?>");
> this.context = JAXBContext.newInstance(classes,props);
> }
>
> public JAXBContext getContext(){
> return this.context;
> }
>
>
> @Override
> public Marshaller createMarshaller() throws JAXBException {
> Marshaller marshaller = context.createMarshaller();
> marshaller.setProperty("com.sun.xml.bind.xmlHeaders", "<?xml-
> stylesheet type='text/xsl' href='foobar.xsl' ?>");
> return marshaller;
> }
>
> @Override
> public Unmarshaller createUnmarshaller() throws JAXBException {
> Unmarshaller unmarshaller = context.createUnmarshaller();
> return unmarshaller;
> }
>
> @Override
> public Validator createValidator() throws JAXBException {
> return null;
> }
> }
>
> Now, when I startup my appserver (Tomcat 6.0), I see encouraging
> messages in the console:
> 24-jun-2009 16:06:58 com.sun.jersey.api.core.ClasspathResourceConfig
> init
> INFO: Provider classes found:
> class be.kvvcr.thesauri.rest.JAXBXSLResolver
> 24-jun-2009 16:06:58
> com.sun.jersey.server.impl.application.WebApplicationImpl initiate
> INFO: Initiating Jersey application, version 'Jersey: 1.1.0-ea
> 04/30/2009 04:46 PM'
> instantiating the JAXBXSLResolver
>
> However, I notice that my custom Provider is not used when invoking
> my resources... It is the default resolver which is used (as far as
> a default resolver exists). If I change the value of the @Produces
> annotation for my custom Resolver from "text/xml" into, say,
> "browser/xml", I get an errormessage (upon requesting a resource):
>
> 24-jun-2009 16:43:33 com.sun.jersey.spi.container.ContainerResponse
> write
> SEVERE: A message body writer for Java type, class
> be.kvvcr.thesauri.Descriptor, and MIME media type, browser/xml, was
> not found
> 24-jun-2009 16:43:33
> com.sun.jersey.server.impl.application.WebApplicationImpl onException
> SEVERE: Internal server error
> javax.ws.rs.WebApplicationException
> at
> com
> .sun
> .jersey.spi.container.ContainerResponse.write(ContainerResponse.java:
> 241)
> at
> com
> .sun
> .jersey
> .server
> .impl
> .application
> .WebApplicationImpl._handleRequest(WebApplicationImpl.java:693)
> at
> com
> .sun
> .jersey
> .server
> .impl
> .application
> .WebApplicationImpl.handleRequest(WebApplicationImpl.java:616)
> at
> com
> .sun
> .jersey
> .server
> .impl
> .application
> .WebApplicationImpl.handleRequest(WebApplicationImpl.java:607)
> at
> com
> .sun
> .jersey.spi.container.servlet.WebComponent.service(WebComponent.java:
> 309)
> at
> com
> .sun
> .jersey
> .spi
> .container.servlet.ServletContainer.service(ServletContainer.java:425)
> at
> com
> .sun
> .jersey
> .spi
> .container.servlet.ServletContainer.service(ServletContainer.java:590)
> at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
> at
> org
> .apache
> .catalina
> .core
> .ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:
> 290)
> at
> org
> .apache
> .catalina
> .core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
> at
> org
> .apache
> .catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:
> 233)
> at
> org
> .apache
> .catalina.core.StandardContextValve.invoke(StandardContextValve.java:
> 175)
> at
> org
> .apache
> .catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
> at
> org
> .apache
> .catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
> at
> org
> .apache
> .catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:
> 109)
> at
> org
> .apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:
> 263)
> at
> org
> .apache.coyote.http11.Http11Processor.process(Http11Processor.java:
> 844)
> at org.apache.coyote.http11.Http11Protocol
> $Http11ConnectionHandler.process(Http11Protocol.java:584)
> at org.apache.tomcat.util.net.JIoEndpoint
> $Worker.run(JIoEndpoint.java:447)
> at java.lang.Thread.run(Unknown Source)
>
> I have been looking around with my (eclipse-) debugger in the source
> code. I noticed that the "browser/xml" mime-type which I provided
> in the annotation of my resolver, could not be found when requesting
> my resource... Please note that my Resource-class contains the
> annotation @Produces({"text/xml", "browser/xml"}). I guess
> something went wrong during the registration of the resolver/
> provider. But I have no clue what. Moreover, the api changed
> slightly during the upgrade to 1.1. Perhaps I mixed something up?
>
> As a consequence, I'm a bit stuck. I guess I miss something...
> Should I explicitly define a new MessageBodyWriter? Should I
> register something? I've found a few hints via Google, but none
> were for Jersey.
>
> regards,
> Bruno.