Question

I am using Hibernate 4.1 and Spring 3.1.

Consider the following User class having references to other object including self. All the hibernate mappings I have defined are LAZY so will load the reference objects only when I use them in the jsp or code else where.

class User {
  private User createdBy;
  private Department department;
  private Project project;
  .....
  .....
}

The problem is when I want to return a JSON representation where it uses reflection to do it and there by does a deep serialization. Below is my controller code.

@ResponseBody
public User getUser(int id) {
  User user = [fetch user from service];
  return user;
}

Since I have self reference also it goes into infinite loop.

What is the solution to get away with this problem? I know that I need to use DTO pattern where I return a UserDTO instead but how many such methods I create. For example, at one place I need just the basic User attributes, at other place I need User and its Department, at other place I need User with Department and Project.

How many such methods I would need to expose. Is there any other way to resolve this?

Was it helpful?

Solution

The problem is that you have a circular reference and your JSON encoder is not handling it. So, you need to handle it manually.

Creating a DTO as you commented would help. You can implement a Helper with one method for each level of decoding you need.

You could use BeanUtils to copy each property from one bean to the other.

Another solution (a bit more conceptual) would be:

Implement a kind of decorator for each boundary method and apply dozer over the result. An example you could take here

The Decoration occurs more or less like this:

public interface Controller {
   User getUser(int id);
}

public class RealController {
   public User getUser(int id) {
      return dao.getUser(id);
   }
}

public class DecoratedController {

   private Controller realController;

   public User getUser(int id) {
      // here you will apply dozer or do it manually creating an object with so deep as you wish
      return flatUserStructure(realController.getUser(id));
   }
}

OTHER TIPS

I think the problem is composed of two parts:

JSON custom serialization: You can use this approach to avoid defining several UserDTOs for User. However, it still remains that you should probably define the JSON serializer as a bean or a configurable service object such that you can command it what to serialize in different controller method mappings. A good example can be found here.

Spring configuration: The next step is configure spring to use your customer JSON serializer. So, when using @ResponseBody, Spring will use your custom JSON serializer. Nice examples can be found here and there.

To be able to tune Hibernate association loading you can use fetch join, please read 14.3. Associations and joins

To avoid issues with deep serialization you can create appropriate DTOs and tune them with some thing like the @JsonIgnore annotation of the Jackson Java JSON-processor project.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top