JSON and Objectify Keys exceptions

1,972 views
Skip to first unread message

naeger

unread,
Jan 14, 2011, 6:43:04 AM1/14/11
to objectify-appengine
Hi all,

I have problems when trying to serialize Objectify Keys with JSON (via
Spring as return values of a REST API).

@Entity
public class Person {
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Id
private Long id;
private String name;
private List<Key<Account>> accounts;

...
}

Gives:

(was java.lang.NullPointerException) (through reference chain:
org.naeger.itimelog.model.Person["accounts"])
Caused by: org.codehaus.jackson.map.JsonMappingException: (was
java.lang.NullPointerException) (through reference chain:
org.naeger.itimelog.model.Person["accounts"])
at
org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:
215)
at
org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:
180)
at
org.codehaus.jackson.map.ser.SerializerBase.wrapAndThrow(SerializerBase.java:
128)
at
org.codehaus.jackson.map.ser.BeanSerializer.serializeFields(BeanSerializer.java:
253)
at
org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:
212)
at
org.codehaus.jackson.map.ser.StdSerializerProvider._serializeValue(StdSerializerProvider.java:
587)
...

and:

@Entity
public class Person {
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Id
private Long id;
private String name;
private Key<Account> test;
...
}

gives:
org.codehaus.jackson.map.JsonMappingException: Type variable 'V' can
not be resolved (with context of class com.googlecode.objectify.Key)
(through reference chain: org.naeger.itimelog.model.Person["test"])

According to this list, there are people who successfully serialize
Objectify Entities incl. Keys. Any idea what I am doing wrong? (I am
using the latest versions of Objectify, Jackson and Spring)

Thanks in advance, Chris

Jeff Schnitzer

unread,
Jan 14, 2011, 10:17:14 AM1/14/11
to objectify...@googlegroups.com
This sounds like a question for the Jackson mailing list. Create a
test case serializing just a Key<?> object.

Jeff

naeger

unread,
Jan 14, 2011, 4:13:11 PM1/14/11
to objectify-appengine
Thank you. I just posted my problem to the Jackson mailing list as
well:
http://markmail.org/search/?q=list%3Aorg.codehaus.jackson.user#query:list%3Aorg.codehaus.jackson.user+page:1+mid:aqgquad6rlyfa3qh+state:results

I was just wondering. Searching this group I can find a few messages
where it seems like people are using Jackson to serlialize Objectify
Entities (with its Keys?). So I thought it works for some people
here ...

Chris

Peter Knego

unread,
Jan 14, 2011, 5:32:58 PM1/14/11
to objectify...@googlegroups.com
I use Objectify with Jackson and I'm geting the same exception (and
reason) as you. The workaround is to instead save the Id that is
inside the Key (my keys don't have a parent so Id is the only valuable
info).

Peter

scott

unread,
Jan 15, 2011, 9:47:49 AM1/15/11
to objectify-appengine
The problem is that Jackson has problems with the method generics used
in Key.class.

The fix is to tell Jackson to serialize/deserialize based on fields
rather than properties. But the Key fields are not public (and you
don't have access to the Key source to add Jackson annotations).

There are 2 ways to do this:

1. In current versions of Jackson you can use the VisabilityMapper
funtionality like:

mapper.setVisibilityChecker(
new VisibilityChecker.Std(
Visibility.PUBLIC_ONLY, // getter
Visibility.PUBLIC_ONLY, // isgetter
Visibility.ANY, // setter
Visibility.ANY, // constructor
Visibility.ANY)); // field

2. You can also use the MixIn Annotation feature like:

// used to custom annotate com.googlecode.objectify.Key.class
class KeyAnnotationMixin
{
@JsonProperty
String kindClassName;
@JsonProperty
Key<?> parent;
@JsonProperty
long id; // this was the problem
@JsonProperty
String name;
}

mapper.getSerializationConfig().addMixInAnnotations(
com.googlecode.objectify.Key.class, KeyAnnotationMixin.class);
mapper.getDeserializationConfig().addMixInAnnotations(
com.googlecode.objectify.Key.class, KeyAnnotationMixin.class);


Enjoy, scott

On Jan 14, 3:32 pm, Peter Knego <pe...@knego.net> wrote:
> I use Objectify with Jackson and I'm geting the same exception (and
> reason) as you. The workaround is to instead save the Id that is
> inside the Key (my keys don't have a parent so Id is the only valuable
> info).
>
> PeterOn Fri, Jan 14, 2011 at 10:13 PM, naeger <nae...@web.de> wrote:
> > Thank you. I just posted my problem to the Jackson mailing list as
> > well:
> >http://markmail.org/search/?q=list%3Aorg.codehaus.jackson.user#query:...

naeger

unread,
Jan 17, 2011, 6:45:50 PM1/17/11
to objectify-appengine
Hi Peter,

thank you, I was thinking in the same direction. Are you replacing the
Keys with Ids only before serializing with Jackson or do you remove
the Keys altogether? I don't have parents either and without parents
(and thus without entity groups/transactions) I am thinking about
eliminating the Keys altogether and only use Long ids in my whole
domain model. Or is there a disadvantage (possibly future extensions
and maintainability of my domain model?) of not using OKeys?

Chris

On 14 Jan., 23:32, Peter Knego <pe...@knego.net> wrote:
> I use Objectify with Jackson and I'm geting the same exception (and
> reason) as you. The workaround is to instead save the Id that is
> inside the Key (my keys don't have a parent so Id is the only valuable
> info).
>
> Peter
>
>
>
> On Fri, Jan 14, 2011 at 10:13 PM, naeger <nae...@web.de> wrote:
> > Thank you. I just posted my problem to the Jackson mailing list as
> > well:
> >http://markmail.org/search/?q=list%3Aorg.codehaus.jackson.user#query:...

naeger

unread,
Jan 17, 2011, 6:50:23 PM1/17/11
to objectify-appengine
Hi Scott,

thank you for your detailed help. I found the corresponding chapters
in the Jackson documentation but never brought it to work myself. So,
thank you! However, I am currently thinking of a more simple
"solution" (like Peter said): simply dump the OKeys altogether and
only work with Long Ids.

You might want to follow my thread on the Jackson mailing list (linked
in my first post). The jackson developers are very friendly and seem
to have a look at this case.

Thank you!
Chris

Jeff Schnitzer

unread,
Jan 17, 2011, 9:07:43 PM1/17/11
to objectify...@googlegroups.com
This is not a bad approach - sometimes it's handy to just store IDs.

I'm somewhat surprised that Jackson has issues serializing generic
types, so if you want to keep using Key<?> you can probably get it
fixed. You're right, the Jackson devs are very responsive and they've
been fast to fix every issue I've run across.

Jeff

Peter Knego

unread,
Jan 18, 2011, 5:18:06 AM1/18/11
to objectify...@googlegroups.com
I lost quite a few hours trying to make Jackson serialize Key. The
problem is in the 'parent' field accessor. As Scott pointed out this
can be remedied by telling Jackson to serialize the field directly
instead of going thorough accessor methods.

Now, my problem it that I use Jersey (also tried Resteasy) as a REST
layer where Jackson is used automatically. I found no way to manually
configure Jackson.

I know this is not the right mailing list, but has anyone been able to
manually configure Jackson when used with a REST layer (Jackson,
Resteasy, etc..)?

Peter

naeger

unread,
Jan 18, 2011, 9:20:47 AM1/18/11
to objectify-appengine
Hi Peter,

yes, I am using the REST framework of Spring 3. Spring also uses
Jackson under the hood but you are somehow able to configure the
Jackson mapper (I read something about that in the Spring
documentation or Spring forums). However, I haven't tried it myself so
far as I am thinking of moving away from OKeys to Long ids only.

I am also thinking about moving away from Spring to something more
lightweight (Guice for dependency injection?, Resteasy/Jersey for
REST?) in order to reduce the startup times (but unsure as I do have
some experience with Spring but none with Guice nor Resteasy/Jersey).
Do you think it is worth the hassle to learn the new frameworks just
to be able to ditch Spring for better startup times?

Thanks, Chris
> >>> > >> > Thanks in advance, Chris- Zitierten Text ausblenden -
>
> - Zitierten Text anzeigen -

Jeff Schnitzer

unread,
Jan 18, 2011, 10:05:04 AM1/18/11
to objectify...@googlegroups.com
On Tue, Jan 18, 2011 at 2:18 AM, Peter Knego <pe...@knego.net> wrote:
> I lost quite a few hours trying to make Jackson serialize Key. The
> problem is in the 'parent' field accessor. As Scott pointed out this
> can be remedied by telling Jackson to serialize the field directly
> instead of going thorough accessor methods.
>
> Now, my problem it that I use Jersey (also tried Resteasy) as a REST
> layer where Jackson is used automatically. I found no way to manually
> configure Jackson.
>
> I know this is not the right mailing list, but has anyone been able to
> manually configure Jackson when used with a REST layer (Jackson,
> Resteasy, etc..)?

Here's the RESTEasy code I use in Mobcast to customize the
serialization of GeoPt. If you have RESTEasy's classpath scanning
turned on (the default), all you need to do is put this class in your
project. RESTEasy will use it to obtain the ObjectMapper, and you can
customize Jackson to your heart's content. It should be pretty
self-explanatory:

package us.mobcasting.server.rest.provider;

import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;

import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.map.ObjectMapper;

import com.google.appengine.api.datastore.GeoPt;

/**
* We customize the serialization of a few items using a Jackson MixIn class
* as per: http://wiki.fasterxml.com/JacksonMixInAnnotations
*
* @author Jeff Schnitzer <je...@infohazard.org>
*/
@Provider
public class ObjectMapperProvider implements ContextResolver<ObjectMapper>
{
static abstract class GeoPtMixIn // doesn't extend GeoPt since it is final
{
@JsonProperty("t") abstract float getLatitude();
@JsonProperty("g") abstract float getLongitude();
}

public final static ObjectMapper OBJECT_MAPPER = new ObjectMapper();
static {
OBJECT_MAPPER.getSerializationConfig().addMixInAnnotations(GeoPt.class,
GeoPtMixIn.class);
}

@Override
public ObjectMapper getContext(Class<?> type)
{
return OBJECT_MAPPER;
}
}

Peter Knego

unread,
Jan 18, 2011, 4:41:06 PM1/18/11
to objectify...@googlegroups.com
I have no experience with Spring Rest so I can give you no advice here.

I tried Jersey, Resteasy and Restlet.
Restlet was giving me trouble and docs are no good.
Resteasy has imho the best docs, but it won't work in GWT Dev mode from my IDE - complains about classes not found. It works perfectly on production  GAE or as GAE project under IDE, but then GWT debuging is not available, which is a deal-breaker for me. 
So now I'm using Jersey and I'm happy with it, except for the Jackson/Key issue, which isn't Jersey's fault anyway (and is the same under Resteasy).

If cold loading is an issue for your app then you might look into warming requests (automatic request made after instance is loaded, does not affect first instance) and reserved instances (instance always alive, a paid feature).

Peter

Peter Knego

unread,
Jan 18, 2011, 5:08:41 PM1/18/11
to objectify...@googlegroups.com
@Jeff - thank you very much for this code - I'll test it out first thing in the morning - past bedtime now ;)

Peter

aswath satrasala

unread,
Jan 18, 2011, 9:56:42 PM1/18/11
to objectify...@googlegroups.com
Hi,
I really want to use JSON.  I don't know anything on Jackson.  Am I hearing that, Jackson can be used with Objectify with the options/workarounds proposed by Scott.

Please clarify.  Any pointers to small working examples will be great

-Aswath

Peter Knego

unread,
Jan 19, 2011, 3:17:51 AM1/19/11
to objectify...@googlegroups.com
@Aswath: you probably need JSON to communicate it over the network? In
this case it's best to use some kind of REST library. Resteasy is a
great one and workarounds have been posted here for the Key and GeoPt
issues: http://www.jboss.org/resteasy

Resteasy handles JSON conversion automatically for you, just annotate
the service classes accordingly. There are many examples on their
site.

Peter

David Keyes

unread,
Apr 11, 2012, 1:49:30 AM4/11/12
to objectify...@googlegroups.com
I've gotten Jackson serialization of Objectify keys to work when using Restlet on GAE.  You can see a write-up of how I got things to work here: http://keyeslabs.com/joomla/blogs/i-think-im-becoming-an-android/431-serializing-objectify-keys-with-restletjacksongwt.  The basic concept should work whether you're using Restlet or not.  

Hope this helps...
Reply all
Reply to author
Forward
0 new messages