users@jersey.java.net

Re: [Jersey] RE: Custom Natural JAXBContextResolver Problem - Single Element Arrays

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Wed, 07 Oct 2009 21:05:22 +0200

Hi James,

Sorry, we have been really busy with the Jersey integration into
GlassFish.

Hopefully Jakub may have time to respond tomorrow.

Paul.

On Oct 7, 2009, at 6:38 PM, James Allchin wrote:

> Hi All,
>
> Sorry for the follow-up... I still have this issue but wanted to add
> a little more info.
>
> I have also explicitly set the location of the config package within
> my web.xml.
>
> This also does not help - because as described I know that the
> JAXBContextResolver is being loaded at startup (it's confirmed in
> the JVM logs).
>
> Any thoughts?
>
> Cheers
>
> James
>
> ________________________________________
> From: James Allchin
> Sent: 05 October 2009 20:25
> To: users_at_jersey.dev.java.net
> Subject: Custom Natural JAXBContextResolver Problem - Single Element
> Arrays
>
> Hi All,
>
> I have a ContextResolver so that I can use Natural JSON notation:
>
> package com.knowledgemill.rest.main;
>
> import com.knowledgemill.entities.*;
>
> import com.sun.jersey.api.json.JSONJAXBContext;
> import com.sun.jersey.api.json.JSONConfiguration;
> import java.util.HashMap;
> import java.util.HashSet;
> import java.util.Map;
> import javax.ws.rs.ext.ContextResolver;
> import javax.ws.rs.ext.Provider;
> import javax.xml.bind.JAXBContext;
>
> /*
> * This class is used to make sure that when using JSON when an array
> contains a single
> * element it still comes back as an array - makes it much easier to
> deal with
> */
>
>
> @Provider
> public class JAXBContextResolver implements
> ContextResolver<JAXBContext> {
>
> private JAXBContext context;
>
> private Class<?>[] types = {
> Artifact.class
> , ArtifactPermission.class
> , AttachedDoc.class
> , AttachedDocArtifact.class
> , AuditMessage.class
> , Container.class
> , ContainerPermission.class
> , Context.class
> , ContextFolder.class
> , Credential.class
> , DBLogMessage.class
> , EmailArtifact.class
> , EmailRecipient.class
> , ExtendedAttribute.class
> , ExtendedEmail.class
> , Group.class
> , InternalArtifact.class
> , InternalUser.class
> , ManagedDocArtifact.class
> , StorageTier.class
> , SystemAttribute.class
> , TreeNode.class
> , User.class
> , UserEmailAddress.class
> };
>
>
> public JAXBContextResolver() throws Exception {
> Map props = new HashMap<String, Object>();
> this.context = new
> JSONJAXBContext(JSONConfiguration.natural().build(), types);
> }
>
> public JAXBContext getContext(Class<?> objectType) {
> for (Class<?> type : types) {
> if (type == objectType) {
> return context;
> }
> }
> return null;
> }
>
>
> }
>
>
> As you can see I have a number of classes which I have specified
> should be targeted by the this ContextResolver.
>
> Now according to the documentation, the NATURAL configuration should
> mean that single element arrays will indeed be respected as a array
> within JSON (instead of returning a single object).
>
> If I take one of my methods which returns List<UserEmailAddress>:
>
> @GET
> @Path("user/{userId}/users/{targetUserId}/emailaddresses/")
> @Produces({"application/xml","application/json"})
> public List<UserEmailAddress> getUserEmailAddresses
> (@PathParam("userId") String userId
> ,
> @PathParam("targetUserId") String targetUserId
> ) {
>
> List<UserEmailAddress> returnedEmailAddresses = null;
> try {
> logger.debug("userId value is " + userId);
> returnedEmailAddresses =
> dA.getUserEmailAddresses( targetUserId);
> }
> catch (Exception e) {
> e.printStackTrace();
> }
> return returnedEmailAddresses;
> }
>
> If I exercise this call (using JSON) where it returns multiple
> elements – I end up with a response shown below:
>
> {"UserEmailAddress": [
> {
> "userId": "7452272EBA160D9AE040A8C048010EEB",
> "smtpAddress": "david.campbell_at_knowledgemill.com",
> "primary": "false",
> "legacy": "true"
> },
> {
> "userId": "7452272EBA160D9AE040A8C048010EEB",
> "smtpAddress": "dcampbell_at_knowledgemill.com",
> "primary": "true",
> "legacy": "false"
> }
> ]}
>
> This looks good – I can see the array notation in the JSON.
>
> If I exercise this call (using JSON) where it returns a single
> element – I end up with a response shown below:
>
> {"UserEmailAddress": {
> "userId": "7452272EBA160D9AE040A8C048230EEB",
> "smtpAddress": "john_at_knowledgemill.com",
> "primary": "true",
> "legacy": "false"
> }}
>
> This is bad – the single element is not coming back as an array.
>
> From my understanding this should have been rectified when using a
> NATURAL JSON notation. It does not work for me.
>
> I have also tried fixing the arrays specifically with the default
> MAPPED notation e.g.:
>
> JSONConfiguration.mapped().arrays( NAMES OF ARRAYS HERE).build()
>
> This also does not work.
>
> It appears that the ContextResolver is having no effect. However, I
> have confirmed that the Provider is being loaded on startup.
>
> Any help – much appreciated.
>
> Cheers.
>
> James
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>