users@jersey.java.net

Re: [Jersey] Date format based on request parameter

From: Chris Carrier <ctcarrier_at_gmail.com>
Date: Fri, 2 Apr 2010 09:21:26 -0700

Wow Paul thanks for the extensive example. I'm gonna have to absorb
that and give it a shot but I'll let you know how it works.

Chris

On Fri, Apr 2, 2010 at 2:00 AM, Paul Sandoz <Paul.Sandoz_at_sun.com> wrote:
> 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
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>
>