users@jersey.java.net

Re: [Jersey] Resource and XML Schema versioning...

From: Marc Hadley <Marc.Hadley_at_Sun.COM>
Date: Thu, 26 Feb 2009 15:19:03 -0500

There are a couple of things you could try:

(i) Simplest. Change your media type to application/v1+xml. JAX-RS
requires the JAXB message body writer to support application/xml, text/
xml and application/*+xml but its allowed to ignore other media types.

(ii) More complex. Write your own message body writer that defers to
the built-in JAXB one. You'll need to implement
MessageBodyWriter<NodeV1>, have javax.ws.rs.ext.Providers injected and
use the getMessageBodyWriter method to get yourself a reference to the
built-in JAXB writer that you can then call.

Marc.

On Feb 26, 2009, at 2:58 PM, Rabick, Mark A (MS) wrote:

> I'm getting an exception trying to configure a custom media type:
>
> SEVERE: A message body writer for Java type, class
> mil.cnodb.rs.model.v1.NodeV1, and MIME media type,
> application/v1-xml, was not found
> Feb 26, 2009 1:50:35 PM
> 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.j
> ava:241)
> at
> com
> .sun.jersey.server.impl.application.WebApplicationImpl._handleRequest
> (WebApplicationImpl.java:578)
> at
> com
> .sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(
> WebApplicationImpl.java:502)
> at
> com
> .sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(
> WebApplicationImpl.java:493)
> at
> com
> .sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.j
> ava:308)
> at
> com
> .sun.jersey.spi.container.servlet.ServletContainer.service(ServletCon
> tainer.java:314)
>
> How can I map application/v1-xml to application/xml? Similarly with
> application/v1-json. Is there a way to avoid writing a custom
> messageWriter for the media type?
>
> I've configured a context resolver:
>
> /**
> *
> */
> @Provider
> @Produces({"application/v1-xml","application/v1-json"})
> public final class Version1ContextResolver implements
> ContextResolver<JAXBContext> {
>
> private final JAXBContext context;
>
> private final Set<Class> types;
>
> /*
> * The list of JAXB class types (top-level) need to be listed here.
> */
> private final Class[] cTypes = {NodeV1.class};
>
> public Version1ContextResolver() throws Exception {
>
> this.types = new HashSet(Arrays.asList(cTypes));
> this.context = new JSONJAXBContext(
> JSONConfiguration.natural().build(), cTypes);
> }
>
> public JAXBContext getContext(Class<?> objectType) {
> return (types.contains(objectType)) ? context : null;
> }
> }
>
> Created a Resource that
> Produces("application/v1-xml","application/v1-json")
>
> @GET
> @Produces({"application/v1-xml","application/v1-json"})
> public NodeV1 getNode(
> @QueryParam("id") String nodeId,
> @QueryParam("name") String nodeName,
> @QueryParam("level") String nodeLevel,
> @QueryParam("allegiance") String allegiance,
> @QueryParam("cc") String cc,
> @QueryParam("typeGeneral") String
> nodeTypeGeneral,
> @QueryParam("typeSpecific") String
> nodeTypeSpecific) {
>
>
> NodeV1 nodeV1 = new NodeV1();
> nodeV1.setNodeName("Nodes Name is");
>
> return nodeV1;
> }
>
> Extended PackagesResourceConfig:
>
> public class CnodbRestResourceConfig extends PackagesResourceConfig {
>
> public CnodbRestResourceConfig() {
> super(createProperties());
> }
>
> public Map<String, MediaType> getMediaTypeMappings() {
> Map<String, MediaType> m = new HashMap<String, MediaType>();
> m.put("v1-xml", CnodbMediaType.APPLICATION_V1XML_TYPE);
> m.put("v1-json", CnodbMediaType.APPLICATION_V1JSON_TYPE);
> return m;
> }
>
> protected static Map<String,Object> createProperties() {
> Map<String, Object> properties = new HashMap<String,
> Object>();
>
> properties.put(PackagesResourceConfig.PROPERTY_PACKAGES,
> "mil.cnodb.rs.resources.v1");
>
> WadlGeneratorConfig config = WadlGeneratorConfig
> .generator(WadlGeneratorApplicationDoc.class)
> .prop("applicationDocsFile",
> "classpath:/application-doc.xml")
> .generator(WadlGeneratorGrammarsSupport.class)
> .prop("grammarsFile",
> "classpath:/application-grammars.xml")
> .generator(WadlGeneratorResourceDocSupport.class)
> .prop("resourceDocFile", "classpath:/resourcedoc.xml")
> .build();
>
> properties.put(ResourceConfig.PROPERTY_WADL_GENERATOR_CONFIG,
> config);
> return properties;
> }
>
> }
>
> And edited web.xml
>
> <servlet>
> <servlet-name>CNODB Web Application</servlet-name>
>
> <servlet-
> class>com.sun.jersey.spi.container.servlet.ServletContainer</se
> rvlet-class>
> <init-param>
>
> <param-name>com.sun.jersey.config.property.resourceConfigClass</
> param-na
> me>
>
> <param-value>com.sun.jersey.api.core.PackagesResourceConfig</param-
> value
>>
> </init-param>
> <init-param>
>
> <param-name>com.sun.jersey.config.property.packages</param-name>
> <param-value>mil.cnodb.rs</param-value>
> </init-param>
> <load-on-startup>1</load-on-startup>
> </servlet>
>
>> -----Original Message-----
>> From: Paul.Sandoz_at_Sun.COM [mailto:Paul.Sandoz_at_Sun.COM]
>> Sent: Thursday, February 26, 2009 11:12 AM
>> To: users_at_jersey.dev.java.net
>> Subject: Re: [Jersey] Resource and XML Schema versioning...
>>
>>
>> On Feb 26, 2009, at 5:51 PM, Rabick, Mark A (MS) wrote:
>>
>>>> On Feb 25, 2009, at 6:08 PM, Rabick, Mark A (MS) wrote:
>
>>>> A suffix at the end of the URI path, but not part of the
>> application
>>>> and @Path.
>>>
>>> Not part of the application I assume would be not in the 'context-
>>> root'
>>> of the web app. Sorry to belabor this but how can a suffix
>> be at the
>>> end of the URI path, but NOT Included in an @Path?
>>> Can you give an example?
>>
>> Here is a specific example from the camel web component:
>>
>> https://svn.apache.org/repos/asf/camel/trunk/components/camel-
>> web/src/main/java/org/apache/camel/web/util/CamelResourceConfig.java
>>
>> public class CamelResourceConfig extends PackagesResourceConfig {
>> public CamelResourceConfig() {
>> super(createProperties());
>> }
>>
>> protected static Map<String, Object> createProperties() {
>> Map<String, Object> properties = new HashMap<String,
>> Object>();
>>
>> properties.put(PackagesResourceConfig.PROPERTY_PACKAGES,
>> "org.apache.camel.web");
>>
>> WadlGeneratorConfig config = WadlGeneratorConfig
>> .generator(WadlGeneratorApplicationDoc.class)
>> .prop("applicationDocsFile", "classpath:/application-
>> doc.xml")
>> .generator(WadlGeneratorGrammarsSupport.class)
>> .prop("grammarsFile", "classpath:/application-
>> grammars.xml")
>> .generator(WadlGeneratorResourceDocSupport.class)
>> .prop("resourceDocFile",
>> "classpath:/resourcedoc.xml")
>> .build();
>>
>> properties.put(ResourceConfig.PROPERTY_WADL_GENERATOR_CONFIG,
>> config);
>> return properties;
>> }
>>
>> public Map<String, MediaType> getMediaTypeMappings() {
>> Map<String, MediaType> m = new HashMap<String, MediaType>();
>> m.put("html", MediaType.TEXT_HTML_TYPE);
>> m.put("xml", MediaType.APPLICATION_XML_TYPE);
>> m.put("json", MediaType.APPLICATION_JSON_TYPE);
>> m.put("dot", MediaType.valueOf(Constants.DOT_MIMETYPE));
>> return m;
>> }
>> }
>>
>> See the method "getMediaTypeMappings". Notice that it
>> declares a mapping of suffix to media type.
>>
>> Thus whenever there is say a request URI:
>>
>> http://localhost:8080/path/foo.html
>>
>> Jersey will modify the request URI to be:
>>
>> http://localhost:8080/path/foo
>>
>> and modify the Accept header to be:
>>
>> Accept: text/html
>>
>> The above modifications will occur *before* Jersey processes
>> the request and dispatches to a methods on a resource class.
>> It is essentially a request filter.
>>
>> Hope that helps,
>> Paul.
>>
>>
>>
>>
>>
>>
>>>
>>>
>>>
>>>>> Ie. http://host:8080/fooapplication/foo.foo-v1/
>>>>>
>>>>> public class FooV1Resource {
>>>>>
>>>>> @GET @Path("/foo.foo-v1/{id}")
>>>>> @Produces("application/foo-v1")
>>>>> public FooV1(String @PathParam("id") String fooId) {
>>>>>
>>>>> FooV2 foo2 = FooDatabase.getFooById(fooId);
>>>>> FooV1 foo1 = convertFoo2ToFoo1(foo2)
>>>>> return foo1;
>>>>> }
>>>>> }
>>>>>
>>>>> Ie. http://host:8080/fooapplication/foo.foo-v2/
>>>>>
>>>>> public class FooV2Resource {
>>>>>
>>>>> @GET @Path("/foo.foo-v2/{id}")
>>>>> @Produces("application/foo-v2")
>>>>> public FooV2(String @PathParam("id") String fooId) {
>>>>> FooV2 foo2 = FooDatabase.getFooById(fooId);
>>>>> return foo2;
>>>>> }
>>>>> }
>>>>>
>>>>> With the appropriate ContextResolvers based on the media
>> types, of
>>>>> course...
>>>>>
>>>>> What 'existing Jersey functionality' are you referring to that
>>>>> suffixes would help with?
>>>>>
>>>>
>>>> See:
>>>>
>>>>
>>>
>> https://jersey.dev.java.net/source/browse/*checkout*/jersey/tags/
>> jerse
>>> y- 1.0.2/api/jersey/com/sun/jersey/api/core/
>>> ResourceConfig.html#getMediaTyp
>>> eMappings()
>>>>
>>>> Paul.
>>>>
>>>>
>>>
>>>
>> ---------------------------------------------------------------------
>>> 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
>>
>>
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>