Reputation: 872
I am using Spring 4 and Hibernate 4. I am using java jpa to use hibernate. I want to load few data lazily. And I have also configured Jackson mapper to convert my java object to json and vice versa. But it's throwing exception while converting the java to json. I have created custom object mapper but still it's not working.
Please see the following classes and see what I am missing here
I am using annotations. Hibernate configuration file: MvcConfiguration.java
package com.ampdev.platform.module.common.config;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import com.ampdev.platform.framework.dataaccess.config.HibernateAwareObjectMapper;
import com.ampdev.platform.framework.rest.security.AuthenticationService;
import com.ampdev.platform.framework.rest.security.AuthenticationServiceDefault;
import com.ampdev.platform.module.user.util.EncryptionUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
@Configuration
@ComponentScan(basePackages = "com.ampdev")
@EnableWebMvc
@EnableTransactionManagement
public class MvcConfiguration extends WebMvcConfigurerAdapter
{
@Bean
public ViewResolver getViewResolver()
{
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
@Autowired
@Bean(name = "authenticationService")
public AuthenticationService getAuthencticaionService()
{
return new AuthenticationServiceDefault();
}
@Autowired
@Bean(name = "passwordEncoder")
public PasswordEncoder getPasswordEncoder()
{
return new BCryptPasswordEncoder();
}
@Autowired
@Bean(name = "encrypyionUtil")
public EncryptionUtil getEncryptionUtil(PasswordEncoder passwordEncoder)
{
return new EncryptionUtil(passwordEncoder);
}
@Autowired
@Bean(name = "objectMapper")
public ObjectMapper getObjectMapper()
{
return new HibernateAwareObjectMapper();
}
@Autowired
@Bean(name = "jsonMessageConverter")
public MappingJackson2HttpMessageConverter getMessageConvertor()
{
return new MappingJackson2HttpMessageConverter();
}
@Autowired
private ObjectMapper objectMapper;
@Autowired
private MappingJackson2HttpMessageConverter jsonMessageConverter;
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters)
{
jsonMessageConverter.setObjectMapper(objectMapper);
converters.add(jsonMessageConverter);
}
}
I have created a custom object mapper to include Hibernate4Module HibernateAwareObjectMapper.java
package com.ampdev.platform.framework.dataaccess.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.hibernate4.Hibernate4Module;
public class HibernateAwareObjectMapper extends ObjectMapper
{
/**
*
*/
private static final long serialVersionUID = -4013528320937607847L;
public HibernateAwareObjectMapper()
{
Hibernate4Module hibernateModule = new Hibernate4Module();
registerModule(hibernateModule);
}
}
Here is my Data object in which I am using the lazy loading: UserMovieReviewData .java
package com.ampdev.platform.module.movie.review.user.dataobject;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import com.ampdev.platform.module.common.dataobject.PersistedDataObject;
import com.ampdev.platform.module.movie.dataobject.MovieData;
import com.ampdev.platform.module.movie.review.constants.ReviewConstants;
import com.ampdev.platform.module.user.dataobject.UserData;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
@Entity
@Table(name = "movie_review_user")
@JsonInclude(Include.NON_NULL)
public class UserMovieReviewData extends PersistedDataObject
{
/**
*
*/
private static final long serialVersionUID = -5644749600929596177L;
@Id
@GeneratedValue
@Column(name = "review_id")
private long id;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "movie_id")
private MovieData movieData;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private UserData userData;
@Column(name = "rating")
private int rating;
@Column(name = "title")
private String title;
@Column(name = "review")
private String review;
@Column(name = "create_date")
@Temporal(TemporalType.TIMESTAMP)
private Date createDate;
@Column(name = "update_date")
@Temporal(TemporalType.TIMESTAMP)
private Date updateDate;
@Override
public long getId()
{
return id;
}
public void setId(long id)
{
this.id = id;
}
public MovieData getMovieData()
{
return movieData;
}
public void setMovieData(MovieData movieData)
{
this.movieData = movieData;
}
public UserData getUserData()
{
return userData;
}
public void setUserData(UserData userData)
{
this.userData = userData;
}
public int getRating()
{
return rating;
}
public void setRating(int rating)
{
this.rating = rating;
}
public String getTitle()
{
return title;
}
public void setTitle(String title)
{
this.title = title;
}
public String getReview()
{
return review;
}
public void setReview(String review)
{
this.review = review;
}
public Date getCreateDate()
{
return createDate;
}
public void setCreateDate(Date createDate)
{
this.createDate = createDate;
}
public Date getUpdateDate()
{
return updateDate;
}
public void setUpdateDate(Date updateDate)
{
this.updateDate = updateDate;
}
}
Here is my web service resource which I am using as rest resource: ReviewResource.java
package com.ampdev.platform.module.movie.review.resource;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import com.ampdev.platform.framework.rest.BaseExecutor;
import com.ampdev.platform.framework.rest.RestBaseResource;
import com.ampdev.platform.module.common.constants.URIConstants;
import com.ampdev.platform.module.movie.review.constants.ReviewConstants;
import com.ampdev.platform.module.movie.review.user.dataobject.UserMovieReviewData;
@Controller
@RequestMapping(value = "/ws/movie/review")
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class ReviewResource extends RestBaseResource
{
@Autowired
private BaseExecutor<UserMovieReviewData, UserMovieReviewData> createMovieReviewExecutor;
@Autowired
private BaseExecutor<String, List<UserMovieReviewData>> getMovieReviewExecutor;
@RequestMapping(value = ReviewConstants.ADD, method = RequestMethod.POST)
public ResponseEntity<UserMovieReviewData> createMovieReview(
@RequestParam(value = ReviewConstants.TYPE, required = true) String type,
RequestEntity<UserMovieReviewData> requestEntity)
{
createMovieReviewExecutor.setAttribute(ReviewConstants.TYPE, type);
return performTask(requestEntity, createMovieReviewExecutor);
}
@RequestMapping(value = URIConstants.GET_IDS, method = RequestMethod.GET)
public ResponseEntity<List<UserMovieReviewData>> getReview(
@RequestParam(value = ReviewConstants.TYPE, required = true) String type, @PathVariable(value = "ids") String reviewIds)
{
getMovieReviewExecutor.setAttribute(ReviewConstants.TYPE, type);
getMovieReviewExecutor.setAttribute(ReviewConstants.REVIEW_IDS, reviewIds);
return performTask(null, getMovieReviewExecutor);
}
}
I am using spring 4 + hibernate 4.
I am getting the following error when I am trying to get data from Rest web service call:
I am getting the following error when I am trying to fetch the data from Rest web service:
org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:238)
org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:208)
org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:161)
org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:144)
org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:71)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:128)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:781)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:721)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:186)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)
root cause
com.fasterxml.jackson.databind.JsonMappingException: could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]->com.ampdev.platform.module.movie.review.user.dataobject.UserMovieReviewData["movieData"]->com.ampdev.platform.module.movie.dataobject.MovieData_$$_jvst49f_5["id"])
com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:232)
com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:197)
com.fasterxml.jackson.databind.ser.std.StdSerializer.wrapAndThrow(StdSerializer.java:187)
com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:652)
com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:152)
com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:541)
com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:644)
com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:152)
com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:100)
com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:21)
com.fasterxml.jackson.databind.ser.std.AsArraySerializerBase.serialize(AsArraySerializerBase.java:183)
com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:114)
com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:1837)
org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:231)
org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:208)
org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:161)
org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:144)
org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:71)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:128)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:781)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:721)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:186)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)
root cause
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:165)
org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:286)
org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185)
com.ampdev.platform.module.movie.dataobject.MovieData_$$_jvst49f_5.getId(MovieData_$$_jvst49f_5.java)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
com.fasterxml.jackson.databind.ser.BeanPropertyWriter.get(BeanPropertyWriter.java:726)
com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:506)
com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:644)
com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:152)
com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:541)
com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:644)
com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:152)
com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:100)
com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:21)
com.fasterxml.jackson.databind.ser.std.AsArraySerializerBase.serialize(AsArraySerializerBase.java:183)
com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:114)
com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:1837)
org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:231)
org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:208)
org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:161)
org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:144)
org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:71)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:128)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:781)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:721)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:186)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)
Upvotes: 0
Views: 5559
Reputation: 20270
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
You're trying to access a lazy collection outside of the hibernate session. There are a few ways to solve this, the most clear is to access the size()
of each collection you're going to be serializing in your service class, which causes the collection to be loaded and therefore available outside the session.
Another alternative is to annotate the collection with FetchType.EAGER
, but this will affect all uses of your model, which might not be what you want. Finally, you can use the OpenSessionInView
pattern, which maintains an open hibernate session for the duration of the request (and therefore allows you to load lazy collections outside where the session boundary would otherwise be). This last alternative is generally considered an anti-pattern.
Upvotes: 1