users@jersey.java.net

[Jersey] Re: Customizing the JAXB XML declaration as unintrusively as possible

From: Jakub Podlesak <jakub.podlesak_at_oracle.com>
Date: Mon, 27 Jan 2014 14:28:32 +0100

Hi Owen,

I apologize for late response.

You understood correctly, only Jersey does not provide a default resolver provider for JAXB context.
It means if you get null there, it is up to you to either supply your own JAXB resolver (and then you will
end up with a non-null value in “THIS STATEMENT” bellow. Or you can just create an appropriate JAXB
context in your JAXB Marshaller provider.

HTH,

~Jakub

On 17 Jan 2014, at 21:32, Owen Jacobson <owen.jacobson_at_grimoire.ca> wrote:

> Thanks Jakub.
>
> I got as far as
>
> package com.unreasonent.ds.jersey.jaxb;
>
> import javax.ws.rs.core.Context;
> import javax.ws.rs.core.MediaType;
> import javax.ws.rs.ext.ContextResolver;
> import javax.ws.rs.ext.Provider;
> import javax.ws.rs.ext.Providers;
> import javax.xml.bind.JAXBContext;
> import javax.xml.bind.JAXBException;
> import javax.xml.bind.Marshaller;
>
> /**
> * Generates JAXB {_at_link Marshaller}s configured to emit fragments, rather than
> * standalone XML documents. This suppresses the <code>&lt;?xml ... &gt;</code>
> * declaration in generated XML, which otherwise would consume considerable
> * bandwidth.
> */
> @Provider
> public class FragmentMarshallerProvider implements ContextResolver<Marshaller> {
>
> private final Providers providers;
>
> public FragmentMarshallerProvider(@Context Providers providers) {
> this.providers = providers;
> }
>
> @Override
> public Marshaller getContext(Class<?> type) {
> ContextResolver<JAXBContext> jaxbResolver = obtainContextResolver();
> JAXBContext context = jaxbResolver.getContext(type);
> try {
> Marshaller marshaller = context.createMarshaller();
> marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
> return marshaller;
> } catch (JAXBException je) {
> // XXX Log?
> return null;
> }
> }
>
> private ContextResolver<JAXBContext> obtainContextResolver() {
> ContextResolver<JAXBContext> jaxbResolver = providers
> .getContextResolver(
> JAXBContext.class,
> MediaType.APPLICATION_XML_TYPE); // THIS STATEMENT
> return jaxbResolver;
> }
>
> }
>
> However, the statement marked “THIS STATEMENT” in obtainContextResolver returns `null` and it’s not clear to me why that is. What have I misunderstood?
>
> -o
>
> On Jan 17, 2014, at 11:29, Jakub Podlesak <jakub.podlesak_at_oracle.com> wrote:
>
>> Hi Owen,
>>
>> You should be able to inject JAX-RS Providers [1] into your marshaller resolver
>> and use the getContextResolver method in order to retrieve the actual JAXBContext resolver.
>> Then you call that one to finally get the actual JAXBContext for desired class:
>>
>> @Context Providers providers;
>>
>> …
>>
>> providers.getContextResolver(JAXBContext.class, mediaType).getContext(type);
>>
>> HTH,
>>
>> ~Jakub
>>
>>
>> [1]https://jersey.java.net/apidocs/latest/jersey/javax/ws/rs/ext/Providers.html
>>
>>
>> On 17 Jan 2014, at 17:12, Owen Jacobson <owen.jacobson_at_grimoire.ca> wrote:
>>
>>> Is there a good way to obtain the JAXBContext that Jersey creates, inside my custom ContextResolver<Marshaller>?
>>>
>>> -o
>>>
>>> On Jan 17, 2014, at 3:53, Jakub Podlesak <jakub.podlesak_at_oracle.com> wrote:
>>>
>>>> Hi Owen,
>>>>
>>>> You can use the same principle as for the JAXBContext resolver,
>>>> i.e. you can also implement your own custom Marshaller resolver provider,
>>>> ContextResolver<Marshaller>, that Jersey will use internally to create
>>>> JAXB marshaller.
>>>>
>>>> HTH,
>>>>
>>>> ~Jakub
>>>>
>>>> On 17 Jan 2014, at 04:40, Owen Jacobson <owen.jacobson_at_grimoire.ca> wrote:
>>>>
>>>>> Hi there,
>>>>>
>>>>> I’d like to suppress the XML declaration generated by JAXB in XML documents generated by my Jersey 2.5 application. It seems like this means I need to set the “jaxb.fragment” property on the JAXB Marshaller… but Jersey doesn’t give me any obvious ways to manipulate Marshallers it creates. I’d like to do this without intruding too deeply into Jersey’s provider mechanism, since JAXB and Jersey are both rather complex pieces of machinery.
>>>>>
>>>>> In decreasing order of perceived intrusiveness, can I
>>>>>
>>>>> 1. insert some code between the point where Jersey creates a Marshaller and where it uses it to serialize objects?
>>>>> 2. write a provider for Marshaller that uses the Jersey-created JAXBContext, so that I can configure it without having to configure the entire JAXB setup?
>>>>> 3. something else I’ve not considered?
>>>>>
>>>>> I’ve found a number of examples for Jersey 2 that create the whole JAXBContext, but the “jaxb.fragment” property must be set on individual Marshallers, not on the JAXBContext itself.
>>>>>
>>>>> -o
>>>>>
>>>>
>>>
>>
>