Reputation: 31
I am developing a typical Java EE 7 application on Glassfish 4.0, using Netbeans 7.4. I have a set of JPA entities with all kinds of relationships. As it is probably a well-known issue, I face a problem (most likely caused by a serialization loop) when I try to expose an entity with a bidirectional relationship with another one using a JAX-RS service.
I have searched a lot for the solution. Apparently, the most clean way of solving this is to use Jackson providers instead of Jersey built-in ones. However, it has not been a success for me. I may be doing something wrong in the middle, and any hint would be much appreciated.
First Entity:
@Entity
public class User implements Serializable {
@Id
private long id;
...
@OneToMany(
mappedBy = "owner",
cascade = CascadeType.ALL
)
private List<Playlist> playlists;
...
}
Second Entity:
@Entity
public class Playlist {
@Id
@GeneratedValue
private long id;
...
@NotNull
@ManyToOne
private User owner;
...
}
JAX-RS Service:
@Path("/user")
@Stateless
public class UserResource {
@Inject
private UserService userService;
@GET
@Path("/{username}")
@Produces(MediaType.APPLICATION_JSON)
public Response getUser(@PathParam("username") String username) {
return Response.ok(userService.getUser(username)).build();
}
}
I have downloaded and included latest Jackson binary (jackson-core-2.3.1.jar) in my classpath and I can actually see something related to jackson in Glassfish server log when I deploy my application. If the returned user entity does not have any associated playlists, everything is fine. However, with one or more playlists for the specified user, a HTTP 500 error is returned and nothing shows up in Glassfish server log.
Thanks in advance for any help.
UPDATE
After lots of back and forth. I am still unable to make jackson work. I moved to Wildfly (Jboss 8), and I cannot make it use the provided version of jackson instead of the built-in one. No matter which version of jackson is added in the classpath (with or without Maven), the error always indicates org.codehaus.jackson.*.
Upvotes: 3
Views: 3809
Reputation: 6054
Find the @MGorgon answer useful.
In my case I want to use hibernate along with jersey but retrieve only id of relation (and not loading the entire object) in a RestFull json web service.
I end up creating a field for the id:
@JsonIgnoreProperties({"parent"}) // this ignores the object for json serialization
public class Object{
private int id;
private AnotherObj parent;
@Transient // this ignores the properties for hibernate mapping, cause we want to use the parent.getId() instead. You may have to put it in your get too
private ind parent_id;
}
Then in your ObjectDao query you can define the parent id as parent_id if you need to get it from a relation :
something like "from files WHERE user_id = parent_id").
You will have to do this for all your queries:
Object.setParent_id(Object.getParent().getId());
Because parent_id
is transient, invisible to hibernate and it wont be listed otherwise.
And of course you should use LAZY relations (otherwise it would load the obj anyway). It works because the parent_id is a column of the object table, it wont need to make a call to parent.
This is useful when you have a lot of relations but you just need to query the id.
Upvotes: 1
Reputation: 2607
Modify your Playlist
entity class:
@Entity
@JsonIgnoreProperties({"owner"})
public class Playlist {
Your Jackson is running to recurency when he tries to serialize User which have Playlist which have User and so on...
Upvotes: 1