users@jersey.java.net

Re: [Jersey] Date format based on request parameter

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Fri, 02 Apr 2010 11:00:16 +0200

Hi Chris,

If you want to share the JSONJAXBContext instance between multiple
ContextResolver classes then you could do the following:

public class MyApp extends PackagesResourceConfig {
   public MyApp() {
     super("my.package", "my.other.package");

     JSONJAXBContext c = ...
     getSingletons().add(new MarshallingCR(c));
     getSingletons().add(new JAXBContextCR(c));
   }
}

public class Base {
   protected final JAXBContext c;
   protected final et<Class<?>> types;

   protected Base(JAXBContext c, Set<Class<?>> types) {
     this.c = c;
     this.types = types;
   }

   protected boolean supports(Class<?> type) {
     return types.contains(type);
   }
}

public class MarshallingCR implements ContextResolver<Marshaller>
extends Base {

    @Override
    public Marshaller getContext(Class<?> type) {
      if (!supports(type)) return null;

      ...
    }
}

public class JAXBContextCR implements ContextResolver<JAXBContext>
extends Base {
    @Override
    public JAXBContext getContext(Class<?> type) {
      if (!supports(type)) return null;

      ...
    }
}

and register your MyApp. That makes things quite clear.


I have not tested it, but i think it should be possible to do the
following:

@Provider
public class MarshallingCR extends ContextResolver<Marshaller> {
   @Context
   private ContextResolver<JAXBContext> cr;

   private final DateAdapter da = new DateAdapter();

   @Override
    public Marshaller getContext(Class<?> type) {
       JAXBContext c = cr,getContext(type);
       if (c == null) return null;
       Mashaller marshaller = jaxbContext.createMarshaller();
       marshaller.setAdapter(da);
       return marshaller;
    }
}

but note that the above injected ContextResolver<JAXBContext> will be
an aggregation of all such declared providers so the above
ContextResolver<Marshaller> will not restrict according to a set of
types.

Also note that a Marshaler instance is not thread safe so it is not
safe to store it. To make things safe you need to store thread local
instances.

Paul.

On Apr 1, 2010, at 7:18 PM, Chris Carrier wrote:

> Yeah that's what I was thinking. So I have a Marshaller Provider that
> looks something like:
>
> public class JaxbMarshallerConfig implements
> ContextResolver<Marshaller> {
>
> Marshaller marshaller;
>
> JAXBContext jaxbContext;
>
> public JaxbMarshallerConfig() throws JAXBException {
> this.marshaller = jaxbContext.createMarshaller();
> marshaller.setAdapter(new DateAdapter());
> }
>
> @Override
> public Marshaller getContext(Class<?> type) {
> return null;
> }
> }
>
> Now is there a suggestion for how to get my JAXBContext into this
> provider? Should I use Jersey's internal injection stuff or is that
> not really meant for end users? Like there must be some call that
> retrieves a Provider based on type right? Or should I just use Spring
> to inject the instance of my JaxbContextResolver into my
> MarshallerProvider? I THINK that should work but I'm getting a bit
> confused by how all these Providers work.
>
> Like somewhere in the depths of Jersey there is a call being made to
> get an instance of a Marshaller to marshal my objects. What does that
> call look like? Is it like (warning pseudocode incoming):
>
> Marshaller marshaller =
> ContextResolver<JAXBContext>.giveMeAJaxbContext.createMarshaller();
>
> In which case my new Marshaller provider would get ignored anyway. Or
> is it like:
>
> Marshaller marshaller =
> ContextResolver<Marshaller>.giveMeAMarshaller();
>
> In which case I don't see how my JaxbContextResolver was ever used (in
> reality it is used obviously). It seems like all i can do is
> implement these Providers and throw them against the wall and hope
> they stick how I want. But really I have no control over whether they
> are used in any particular way or not. Am I just confusing myself at
> this point?
>
> Chris
>
>
>
> On Thu, Apr 1, 2010 at 10:03 AM, Paul Sandoz <Paul.Sandoz_at_sun.com>
> wrote:
>>
>> On Apr 1, 2010, at 6:40 PM, Chris Carrier wrote:
>>
>>> Also I'm a bit confused on how these Providers will interact with
>>> each
>>> other. So I already have a JAXBContext Provider that configures my
>>> JSON format via JSONJAXBContext like:
>>>
>>> this.context = new
>>> JSONJAXBContext(JSONConfiguration.mapped().arrays(...);
>>>
>>> And returns it in the getContext method. Now I am implementing a
>>> Marshaller provider that also has a getContext method but this one
>>> returns a Marshaller object. If I define both of these Providers
>>> will
>>> they play well together? Or am I only able to use one or the other?
>>>
>>
>> Hmm... i have not tried it but i think it will result in ignoring
>> the json
>> configuration for marshaling unless you create the Marshaller from
>> the
>> JSONJAXBContext. As long as you do that you should be OK.
>>
>> Paul.
>>
>>> Chris
>>>
>>> On Thu, Apr 1, 2010 at 9:28 AM, Chris Carrier
>>> <ctcarrier_at_gmail.com> wrote:
>>>>
>>>> Great guys thanks for the tips that looks like what I was looking
>>>> for.
>>>> Is there a master list of available @Providers anywhere? I
>>>> swear I
>>>> had seen one once in the JAXRS docs but I just spent some time
>>>> looking
>>>> and now can't find it.
>>>>
>>>> Thanks!
>>>> Chris
>>>>
>>>> On Thu, Apr 1, 2010 at 3:48 AM, Paul Sandoz <Paul.Sandoz_at_sun.com>
>>>> wrote:
>>>>>
>>>>> Hi Chris,
>>>>>
>>>>> You can modify your context resolver to be
>>>>> ContextResolver<Marshaller>
>>>>>
>>>>> And then use the following methods:
>>>>>
>>>>>
>>>>> http://java.sun.com/javase/6/docs/api/javax/xml/bind/Marshaller.html#setAdapter%28java.lang.Class,%20A%29
>>>>>
>>>>> http://java.sun.com/javase/6/docs/api/javax/xml/bind/Marshaller.html#setAdapter%28javax.xml.bind.annotation.adapters.XmlAdapter%29
>>>>>
>>>>> In your context resolver you can inject UriInfo and thus obtain
>>>>> the
>>>>> query
>>>>> parameter when the request is in scope.
>>>>>
>>>>> Paul.
>>>>>
>>>>> On Apr 1, 2010, at 3:03 AM, Chris Carrier wrote:
>>>>>
>>>>>> Hey folks,
>>>>>>
>>>>>> A little while ago I toiled to find a way to deal with dates
>>>>>> being
>>>>>> represented as Java timestamps. I finally discovered the
>>>>>> ability to
>>>>>> use package level annotations to define custom JAXB adapters
>>>>>> based on
>>>>>> type that I could use to format Dates however I wanted. Well
>>>>>> now I
>>>>>> have a new requirement to return Date representations based on a
>>>>>> parameter in the get request. Like a parameter might be passed
>>>>>> into
>>>>>> GET calls like
>>>>>>
>>>>>> ...?humanReadableDates=true
>>>>>>
>>>>>> And then I return GMT dates or whatever. Otherwise I return
>>>>>> timestamps. So I would love to be able to just use my central
>>>>>> XmlJavaTypeAdapter so that I can apply this easily to any
>>>>>> pojo's I
>>>>>> want but the annotation syntax:
>>>>>>
>>>>>> @XmlJavaTypeAdapter(value = DateAdapter.class, type = Date.class)
>>>>>>
>>>>>> Suggests that JAXB will instantiate a new DateAdapter whenever it
>>>>>> needs one and I have no idea how to get a handle on that
>>>>>> instance to
>>>>>> do anything with it based on request parameters.
>>>>>>
>>>>>> So basically I was wondering if anyone has any suggestions for
>>>>>> a good
>>>>>> way to do this. If there's some trick to get a handle on an
>>>>>> XmlJavaTypeAdapter that would work. I could just put some
>>>>>> logic in my
>>>>>> domain classes so that i can set some Date format instance
>>>>>> variable in
>>>>>> them to affect the way they represent Dates but that really seems
>>>>>> pretty crappy. I would much prefer to keep my marshalling config
>>>>>> stuff centralized and out of my pojo's. I've got a Provider that
>>>>>> 'implements ContextResolver<JAXBContext>' but I see no way to
>>>>>> configure my Date format from here.
>>>>>>
>>>>>> If I was using plain Jackson I could do
>>>>>> 'mapper.getSerializationConfig().setDateFormat(FORMAT)' but at
>>>>>> this
>>>>>> point we've gone done the road of using JAXB and it would be a
>>>>>> bit of
>>>>>> a pain to switch.
>>>>>>
>>>>>> Suggestions very welcome.
>>>>>>
>>>>>> Thanks!
>>>>>> Chris
>>>>>>
>>>>>> ---------------------------------------------------------------------
>>>>>> 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
>>>
>>
>>
>> ---------------------------------------------------------------------
>> 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
>