JsonMappingException: Infinite recursion on OneToMany Relationship in Objectify - android

To serve a backend for an Android App i am using Google App Engine together with Objectify (4.0.3b).
On the backend I have a simple User Entity, which has a list of Users (friends) as relationship.
#Entity
public class User {
#Id
private String email;
#Load
private List<Ref<User>> friends = new ArrayList<Ref<User>>();
private User() {
}
public List<User> getFriends() {
ArrayList<User> friendList = new ArrayList<User>();
for (Ref<User> ref : this.friends) {
friendList.add(ref.get());
}
return friendList;
}
public void setFriends(List<User> friends) {
List<Ref<User>> refs = new ArrayList<Ref<User>>();
for (User user : friends) {
refs.add(Ref.create(user));
}
this.friends = refs;
}
}
Now when I have following Users stored in the Database for instance : user1 and user2:
user1 has user2 in his friend list and vice versa
When trying to fetch a User object (that has the above cycle reference) from my Endpoint, the Android client throws the following exception:
com.google.appengine.repackaged.org.codehaus.jackson.map.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: java.util.ArrayList[0]...
In this post Infinite Recursion with Jackson JSON and Hibernate JPA issue they recommend to use #JsonIgnore on the field or the getter/setter method.
But on the client side i need to access the friends list by these getter/setter methods (from the generated client library object), so this doesn't help me.
Another tip is to use #JsonManagedReference and #JsonBackReference, which in my case can't be applied since ManagedReference and BackReference would pointto the same friends field.
What I think could solve my Problem is the #JsonIdentityInfo Annotation which is available since Jackson 2.0.
My problem now is that I don't know how I can use this Annotation with Google App Engine.
GAE uses jackson-core-asl-1.9.11, which unfortunately does not have the #JsonIdentityInfo, as it obviously is depending on a version below 2.0.
Does anybody know, how I can use the latest Jackson Version (2.4) in Google App Engine to use the #JsonIdentityInfo feature?
Or is there a better approach for my problem?

The best approach would be to define a DTO class to use as a return parameter for your endpoint and use that to flatten the JSON response (meaning not sending the infinite loop of friend's friends).

Related

populate app with dummy endpoint retrofit values without having Json responses but only data Classes

I have an app with a lot of Retrofit endpoints. I need to run this app in the emulator without internet because I do not have access anymore to the server, I am happy with fake data, so for instance if is an Int I would be happy with a random number, if is a string with whatever string.
Also I want to be able to test this app, how can I create dummy json files on the basis of the data classes in moshi, interface endpoints?
In theory on the base of all the moshi data classes, I could write some fake data, but it will take me weeks
I know there are a number of nice tools as RESTMock, but they always follow an implementation as
RESTMockServer.whenGET(RequestMatchers.pathEndsWith("/data/example.json")).thenReturnFile(
"users/example.json");
but I want to know how to automate the process, without writing a json file myself
It should be your choice of the level on which to mock. You can mock jsons if you use rest mock server, but you can go at the higher level and mock entity that actually uses your retrofit interface, or actually mock rest interface itself:
public interface RESTApiService {
#POST("user/doSomething")
Single<MyJsonResponse> userDoSomething(
#Body JsonUserDoSomething request
);
}
public class RestApiServiceImpl {
private final RESTApiService restApiService;
#Inject
public RestApiServiceImpl(RESTApiService restApiService) {
this.restApiService = restApiService;
}
public Single<MyUserDoSomethingResult> userDoSomething(User user) {
return restApiService.userDoSomething(new JsonUserDoSomething(user))
.map(jsonResponse -> jsonResponse.toMyUserDoSomethingResult());
}
}
Clearly you can pass mock version of RESTApiService into RestApiServiceImpl and let it return hand-mocked responses. Or moving same direction you could mock RestApiServiceImpl itself and thus mock not at the json models level, but entities level.

How do I make a a java object to recieve a model from my rails api?

I've just started learning about Android Spring through a library called RoboSpice which is used for asynchronous RESTFUL tasks. I'm aiming to connect an android app to a rails api. It also uses Jackson. I'm getting the hang of it, but the main thing I can't wrap my head around is how I make an object class in java and then perform a POST or GET and expect to get the correct object back from the rails model or how it could know how to save posted data in the model. For example, if I have a model called Interview that belongs to a user (who has many) which contains info like job, date, time, company.
How would I write that object? Is there a very specific structure I need for that object class? How could I use get to retrieve the interviews from a user? Any explanations or links to a good tutorial would be a big help.
thanks
I have used Retrofit to communicate between my rails app and android app. I thought it was json only, but apparently it works with XML as well.
Here is the link to the main web page, and here is the link to the page that talks about supporting xml.
Retrofit makes communicating between android and a Restful API, pretty easy. You can get all the details in the first link above.
One last excellent resource for Android RestFul API access. This Blog post combines using Retrofit and Otto (also from square). This was actually how I setup my link. Since retrofit supports xml, I think everything in this blog post will also apply to a XML based API.
I think the big part of your question was on the conversion process. Retrofit uses Simple, for xml, it uses gson for json by default, but the process for converting is pretty similar. The main thing you need to do is to define a java class that has fields that match the xml nodes in the xml that is sent / expected by the api. the converter will map those nodes to the java object fields and vise versa.
Here is an example (directly from the Simple tutorial link above). The java class is basically just the fields you want to send back and forth and getters and setters for those fields.
Nested Java class "template" that will be filled in by the converter when it does the de-serialization
#Root
public class Configuration {
#Element
private Server server;
#Attribute
private int id;
public int getIdentity() {
return id;
}
public Server getServer() {
return server;
}
}
public class Server {
#Attribute
private int port;
#Element
private String host;
#Element
private Security security;
public int getPort() {
return port;
}
public String getHost() {
return host;
}
public Security getSecurity() {
return security;
}
}
public class Security {
#Attribute
private boolean ssl;
#Element
private String keyStore;
public boolean isSSL() {
return ssl;
}
public String getKeyStore() {
return keyStore;
}
}
and the xml that it would serialize
<configuration id="1234">
<server port="80">
<host>www.domain.com</host>
<security ssl="true">
<keyStore>example keystore</keyStore>
</security>
</server>
</configuration>

Getting Data from REST Api

I have a node.js application with an Angular Webfrontend and an Android App connecting to the backend via rest. Now I'm not sure how to return objects from node to the clients:
Way 1:
res.send(req.user);
If I'll do it like this I can load the user object from angular like:
return $http.post('/api/login', user)
.success(function (data) {
$rootScope.currentUser = data;
and in my Android app (simplyfied call, I use Spring and Gson):
user = SpringRestTemplate.getRestTemplate().postForObject(Routes.getLogin(), user, User.class);
This works fine, but what I actually would like to return from node would be my
Way 2:
res.send({user: req.user });
for angular everything pretty much stays the same:
$rootScope.currentUser = data.user;
but for android I didn't found any other way than to write the json conversion myself:
ResponseEntity<Map> map = SpringRestTemplate.getRestTemplate().postForEntity(Routes.getLogin(), dUser, Map.class);
LinkedTreeMap<String, User> map2 = (LinkedTreeMap<String, User>) map.getBody();
Map ltm = (Map) map.get("user");
String id = (String) ltm.get("_id");
String userName = (String) ltm.get("userName");
// ... and so on
I get, why this is the case (except why I had to use a second map), but I wonder if there's any simplier way to achieve my second way.
I left the Models and the SpringRestTemplate Code out, since this is more a general question on how to handle JSON with the following structure:
{ user : { _id: "1", userName: "foo", ...}}
Any guidance on how to deal with this problem would be much appreciated!
This is simplified, but this will solve your issue.
Create a POJO that matches the JSON Schema using Json Schema to POJO
If you can, use Retrofit or something more easily suited for Android to consume the API.
Create a retrofit service (look at the retrofit link above) and then connect to the API and you'll have a User object.
Option B:
Use GSON to deserialize your object into a POJO from your spring stuff. But I recommend using Retrofit or something similar as its easier and cleaner.

Couchbase lite on Android - General architecture?

We are building a project using couchbase. On Android, I use couchbase lite. Usually, I've been working with relational databases and because I am new to couchbase I am having trouble finding the "correct" architecture. I do understand the core concepts I think, but all the samples and guides seem to stick to some kind of easy setup where they access the database right in the Activities.
I am more used to having some database abstraction where the business logic only get's to see POJO DTO's that are delivered through a database interface or some DAO or something. So I've now annotated my model classes and started writing a simple OR mapper, but with different types of data, foreign keys etc. this is getting quite time consuming quite fast.
Am I completely missing the point here somehow? I can't imagine everyone doing it this way? I everyone writing methods that convert Documents to POJO model classes for each class seperately? Or using a json parser to do that (But that won't work for foreign keys if I wan't to load them too, does it)?
Sorry for the load of questions, but I feel I am missing something obvious here. Thanks!
Will try answering your questions:
Am I completely missing the point here somehow?
No. You can treat noSQL CB as a persistent distributed object cache. So its not RDBMS. However, DAO pattern perfectly fits into this model...since you are dealing with DTOs/ValueObjects/POJOs on DAO level and on noSQL level.
I can't imagine everyone doing it this way?
I suggest write one universal Couchbase manager class that can persist/retrieve a POJO. Then you can re-use it in your DAOs.
Everyone writing methods that convert Documents to POJO model classes
for each class separately? Or using a json parser to do that (But that
won't work for foreign keys if I wan't to load them too, does it)?
You can have one common code in your Couchbase manager class that does conversion from/to json to POJO. So you work with only POJOs and don't see any json in your application code (outside of Couchbase manager class)
Here is an example of such class:
public class CouchbaseManager<K, V>
{
private final Class<V> valueTypeParameterClass;
#Inject
private CouchbaseClient cbClient;
#Inject
private Gson gson;
public CouchbaseManager(final Class<V> valueClass)
{
this.valueTypeParameterClass = valueClass;
}
public V get(K key)
{
V res = null;
String jsonValue = null;
if (key != null)
{
jsonValue = (String) cbClient.get(key);
if (jsonValue != null)
{
res = gson.fromJson(jsonValue, valueTypeParameterClass);
}
}
return res;
}
public void put(K key, V value)
{
int ttl = 0;
cbClient.set(key, ttl, gson.toJson(value, valueTypeParameterClass));
}
}
Then in your DAO code you create instance of CouchbaseManager for each type:
CouchbaseManager<String,Customer> cbmCustomer = new CouchbaseManager<String,Customer>(Customer.class);
CouchbaseManager<String,Account> cbmAccount = new CouchbaseManager<String,Account>(Account.class);
// and so on for other POJOs you have.
// then get/put operations look simple
Customer cust = cbmCustomer.get("cust-1234");
cust.setName("New Name"); // mutate value
// store changes
cbmCustomer.put(cust.getId(), cust);
Now regarding "foreign keys". Remember its not RDBMS so its up to your code to have notion of a "foreign key". For example a Customer class can have an id of an account:
Customer cust = cbmCustomer.get("cust-1234");
String accId = cust.getAccountId();
//You can load account
Account acc = cbmAccount.get(accId);
So as you can see you are doing it all yourself. I wish it was JPA or JDO implementation/provider for Couchbase (like DataNucleus or Hibernate)
You should really start with your POJO/Document design to try to split your POJO entities into "chunks" of data to get a right balance between coarse vs fine grained POJOs.
Also see this discussion on key/document design considerations.

Persisting entity relationships from REST service for Android

I am trying to maintain a local store of a database, accessible via a REST API. I am attempting to use the fantastic RoboSpice and Spring libraries for the REST client, Jackson to parse/cache the JSON response and ORMLite to persist the resulting objects.
The problem is that I don't know how to store foreign object relationships for the JSON responses I get. Sometimes the JSON objects are nested, other times they are referenced by Id.
A typical systems response
{
id:567,
name:"The only system",
competitions:[{
id:123,
system_id:567
...
}];
}
A competitions response
items: {
123:{
id:123,
system_id:567 // System only referenced by id
...
}}
Another competitions response
items: {
123:{
id:123,
system_id:567, // System referenced by id and nested
system:{
id:567,
name:"The only system",
...
}
}
}
Nested objects work fine, but it's the cases where there is a reference by id that is killing it. I have two classes for my data model as follows.
Systems class
#DatabaseTable("systems")
public class System {
#JsonProperty("id")
#DatabaseField(id=true, columnName="id")
private long id;
#JsonProperty("name")
#DatabaseField(columnName="name")
private String name;
#JsonProperty("competitions")
#ForeignCollectionField
private ForeignCollection<Competition> competitions;
// getters & setters omitted
}
Competition class
#DatabaseTable("competitions")
public class Competition {
#JsonProperty("id")
#DatabaseField(id=true,columnName="id")
private long id;
#JsonProperty("system_id")
#DatabaseField(columnName="id")
private long systemId; // This is definitely at least part of the problem
#JsonProperty("system")
#DatabaseField(foreign=true, columnName="system_id")
private System system;
// getters & setters omitted
}
Having two properties references the system_id seems like a definitively bad idea, but I can't find an alternative for the behaviour I want. Even if the system object is not nested in the Competition object, the Competition should be able to map a relationship to the System object in the local database, because the id of the system is always provided.
The other problem I suspect is that I'm using two object persisters, the JacksonObjectPersister and the InDatabaseObjectPersisterFactory (provided by RoboSpice for use with ORMLite). The reason for this is because I don't want to persist the lists that the objects are nested in to the database. By my understanding, Jackson should cache the JSON response from the server, ORMLite should cache the data model.
This is the error I'm getting
02-03 15:15:57.640: D//DefaultRequestRunner.java:166(20944): 15:15:57.636 Thread-28
An exception occurred during service execution :org.codehaus.jackson.map.JsonMappingException:(was java.lang.NullPointerException)
(through reference chain: com.company.app.api.objects.List["items"]->
java.util.HashMap["51"]->
com.company.app.api.objects.Competition["system_id"])
Apologies for what seems like a number of questions in one, I am bashing my head against a wall. I will attempt to wrap this essay up with a summary...
Is there any way to piece together object relationships using Jackson and ORMLite for the JSON responses I have provided?

Categories

Resources