Reputation: 5175
Good day all, I have spent considerable time Googlin' and upgrading from JSON 1 to JSON 2 but when I try and return a list of entities, I get the exception:
"Received Exception Could not write JSON: could not initialize proxy - no Session (through reference chain:"
I know this is related to Hibernate lazy init but I haven't figured out how to fix it. I thought the jackson-module-hibernate project was the solution. However I haven't been able to make it work.
Here is my tech:
I am using Java Config: ...
@Bean
public com.mycompany.config.MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
mappingJackson2HttpMessageConverter.setObjectMapper(new HibernateAwareObjectMapper());
return mappingJackson2HttpMessageConverter;
}
@Bean
public OpenEntityManagerInViewFilter springOpenEntityManagerInViewFilter() {
return new org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter();
}
@Bean
public ContentNegotiatingViewResolver contentNegotiatingViewResolver() {
final ContentNegotiatingViewResolver contentNegotiatingViewResolver = new ContentNegotiatingViewResolver();
contentNegotiatingViewResolver.setDefaultContentType(MediaType.APPLICATION_JSON);
final ArrayList defaultViews = new ArrayList();
defaultViews.add(converter());
contentNegotiatingViewResolver.setDefaultViews(defaultViews);
return contentNegotiatingViewResolver;
}
I also have:
public class HibernateAwareObjectMapper extends ObjectMapper {
public HibernateAwareObjectMapper() {
Hibernate4Module hm = new Hibernate4Module();
registerModule(hm);
}
}
The flow starts from the controller, which calls several services that each return an entity or List. I then put the returned objects into a object and return it, thinking the @ResponseBody will work. However, I must not have things wired right since I still get the exceptions.
Can anyone see any errors here?
Gratefully...
Upvotes: 4
Views: 6671
Reputation: 41
This is resolved in 2.5.0 version of jackson-datatype-hibernate. Just pass Hibernate SessionFactory in Hibernate(3,4)Module as follows:
public class HibernateAwareObjectMapper extends ObjectMapper {
private static final long serialVersionUID = 1L;
@Autowired
private EntityManagerFactory emf;
@PostConstruct
public void init() {
Hibernate4Module module = new Hibernate4Module(emf.unwrap(SessionFactory.class));
module.enable(Hibernate4Module.Feature.FORCE_LAZY_LOADING);
module.disable(Hibernate4Module.Feature.USE_TRANSIENT_ANNOTATION);
}}
Above snippet is fine if JPA is in use, so EntityManagerFactory bean is available. Otherwise, just inject Hibernate SessionFactory and pass to constructor.
No need to use OpenSessionInView pattern.
Upvotes: 3
Reputation: 388316
It is because the object you are trying to serialize has lazy loaded component, you can add OpenSessionInViewFilter to your web configuration to fix this problem.
The hibernate session used to load the object gets closed when the execution exists the transaction, so when the view layer(jackson) tries to serialize the object and tries to load the lazy loaded objects it fails with this error.
Add this in your web.xml
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>/app/*</url-pattern>
</filter-mapping>
Upvotes: 0