1

I have been using Spring data and Hibernate to make query to mySql database. I Have an error

[http-nio-8086-exec-3] ERROR com.controller.ErrorController - org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: could not initialize proxy - no Session (through reference chain: com.model.Response["body"]->java.util.ArrayList[0]->com.domain.Car["carType"]->com.domain.CarType_$$_jvste93_e["note"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: could not initialize proxy - no Session (through reference chain: com.model.Response["body"]->java.util.ArrayList[0]->com.domain.Car["carType"]->com.domain.CarType_$$_jvste93_e["note"]) at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:271) at org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:100) at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:167) at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:100) at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:166) at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:80) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:127) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:806) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:729) at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) at javax.servlet.http.HttpServlet.service(HttpServlet.java:622) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:673) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1526) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1482) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:745)

and I would like to undestand why, if the problem is into my entity or in my code. I made entity through Hibernate tools Plugin, and this is part of car entity:

@Entity
@Table(name = "car", catalog = "ATS")
public class Car implements java.io.Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private Integer idCar;
    private CarType carType;
    private Fleet fleet;
    private String id;
    private int initialKm;
    private String carChassis;
    private String note;
    private Set<Acquisition> acquisitions = new HashSet<Acquisition>(0);

carType:

    @Entity
@Table(name = "carType", catalog = "ATS")
public class CarType implements java.io.Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private String idCarType;
    private String note;
    //private Set<Car> cars = new HashSet<Car>(0);

    public CarType() {
    }

    public CarType(String idCarType) {
        this.idCarType = idCarType;
    }

    public CarType(String idCarType, String note, Set<Car> cars) {
        this.idCarType = idCarType;
        this.note = note;
//      this.cars = cars;
    }

    @Id

    @Column(name = "id_carType", unique = true, nullable = false, length = 5)
    public String getIdCarType() {
        return this.idCarType;
    }

    public void setIdCarType(String idCarType) {
        this.idCarType = idCarType;
    }

    @Column(name = "note", length = 100)
    public String getNote() {
        return this.note;
    }

    public void setNote(String note) {
        this.note = note;
    }

//  @OneToMany(fetch = FetchType.LAZY, mappedBy = "carType")
//  public Set<Car> getCars() {
//      return this.cars;
//  }
//
//  public void setCars(Set<Car> cars) {
//      this.cars = cars;
//  }

}

and this is part of my database ER shema: enter image description here

In my Spring controller:

@Override
@RequestMapping(value = { "/cars/{idFleet}"}, method = RequestMethod.GET)
public @ResponseBody Response<List<Car>> getCars(@PathVariable int idFleet) throws QueryException{
    Response<List<Car>> cars=fleetAndCarService.findCarsByIdFleet(idFleet);
    return cars;

}

The query is so defined:

public interface CarRepository extends JpaRepository<Car, Integer> {

    //Query method of spring 
    List<Car> findByFleetIdFleet(int idFleet);
}

Service method:

@Override
    public Response<List<Car>> findCarsByIdFleet(int idFleet) throws QueryException {
        try{
            List<Car> cars=databaseFleetsAndCarsServices.findCarsByIdFleet(idFleet);
            System.out.println("Number of acquisition: "+cars.get(0).getAcquisitions().size());
            return new Response<List<Car>>(HttpStatus.OK.value(),databaseFleetsAndCarsServices.findCarsByIdFleet(idFleet));
        } catch (Exception e) {
            throw new QueryException(e);
        }
    }

return:

Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.domain.Car.acquisitions, could not initialize proxy - no Session

What do you think?Thanks,regards

UPDATE with my configuration class

@EnableWebMvc
@Configuration
@PropertySource(value = { "classpath:application.properties" })
@ComponentScan({ "com.*" })
@EnableTransactionManagement
@Import({ SpringMvcInitializer.class })
@EnableJpaRepositories("com.repository")
public class AppConfig extends WebMvcConfigurerAdapter{
    @Autowired
    private Environment env;

    private static final String PROPERTY_NAME_DATABASE_DRIVER = "db.driver";
    private static final String PROPERTY_NAME_DATABASE_PASSWORD = "db.password";
    private static final String PROPERTY_NAME_DATABASE_URL = "db.url";
    private static final String PROPERTY_NAME_DATABASE_USERNAME = "db.username";

    private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect";
    private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "hibernate.show_sql";
    private static final String PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN = "entitymanager.packages.to.scan";
    private static final String PROPERTY_NAME_HIBERNATE_FORMAT_SQL = "hibernate.format_sql";

    private Properties getHibernateProperties() {
        Properties properties = new Properties();
        properties.put(PROPERTY_NAME_HIBERNATE_DIALECT, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_DIALECT));
        properties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL));
        properties.put(PROPERTY_NAME_HIBERNATE_FORMAT_SQL, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_FORMAT_SQL));
        return properties;
    }

    @Bean(name = "dataSource")
    public BasicDataSource dataSource() {
        BasicDataSource ds = new BasicDataSource();
        ds.setDriverClassName(env.getRequiredProperty(PROPERTY_NAME_DATABASE_DRIVER));
        ds.setUrl(env.getRequiredProperty(PROPERTY_NAME_DATABASE_URL));
        ds.setUsername(env.getRequiredProperty(PROPERTY_NAME_DATABASE_USERNAME));
        ds.setPassword(env.getRequiredProperty(PROPERTY_NAME_DATABASE_PASSWORD));
        return ds;
    }

    @Bean
    public ServletContextTemplateResolver TemplateResolver(){
        ServletContextTemplateResolver resolver = new ServletContextTemplateResolver();
        resolver.setPrefix("/WEB-INF/templates/pages/");
        resolver.setSuffix(".html");
        resolver.setTemplateMode("LEGACYHTML5");
        resolver.setCacheable(false);
        return resolver;
        /*ServletContextTemplateResolver resolver = new ServletContextTemplateResolver();
        resolver.setPrefix("/WEB-INF/pages/");
        resolver.setSuffix(".html");
        resolver.setTemplateMode("HTML5");
        return resolver;*/
    }

    @Bean
    public SpringTemplateEngine templateEngine(){
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(TemplateResolver());
        return templateEngine;
    }


    @Bean
    public ThymeleafViewResolver viewResolver() {
        ThymeleafViewResolver resolver = new ThymeleafViewResolver();
        resolver.setTemplateEngine(templateEngine());
        resolver.setOrder(1);
        resolver.setViewNames(new String[]{"*", "js/*", "template/*"});
        return resolver;
    }

    /**
     * Register multipartResolver for file upload
     * @return
     */
    @Bean
    public CommonsMultipartResolver multipartResolver() {
        CommonsMultipartResolver resolver=new CommonsMultipartResolver();
        resolver.setDefaultEncoding("utf-8");
        return resolver;    
    }

    /**
     * Allow use of bootstrap
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/static/**")
                    .addResourceLocations("/static/");
    }

    /**
     * Allow use of JPA
     */
    @Bean
    public JpaTransactionManager transactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
        return transactionManager;
    }
    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactoryBean.setDataSource(dataSource());
        entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
        entityManagerFactoryBean.setPackagesToScan(env.
        getRequiredProperty(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN));
        entityManagerFactoryBean.setJpaProperties(getHibernateProperties());
        return entityManagerFactoryBean;

    }
luca
  • 3,248
  • 10
  • 66
  • 145
  • Don't you need Transactional annotation? – Rufi Oct 21 '15 at 07:55
  • this is my first spring query method, until now I used query of repository(with override and Transactional annotations), I update my code with query – luca Oct 21 '15 at 07:59
  • 3
    The transaction/session is closed once your service method completes. JSON serializer then tries to access a lazily loaded collection (Acquisitions) in your controller layer but as there is no session an exception is thrown. Quick fix to test this, Call car.getAquisitoions().size() in your service layer which will trigger loading of the lazy collection at that point. – Alan Hay Oct 21 '15 at 08:07
  • I retrieve the same error in service class of spring and in carServices that call carRepository method – luca Oct 21 '15 at 08:26
  • Your service isn't transactional unless you add `@Transactional`. – M. Deinum Oct 21 '15 at 08:27
  • I add @Transactional to my CarServices but if a call acquisition.size it works until service layer of spring, in controller it throws exception – luca Oct 21 '15 at 09:04

1 Answers1

2

Add this property to your EntityManager configuration

<prop key="hibernate.enable_lazy_load_no_trans">true</prop>

Example:

<bean id="entityManagerFactory"
  class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="myDataSource"/>
<property name="packagesToScan" value="com.mycompany.somepackage"/>
<property name="jpaVendorAdapter" ref="hibernateVendorAdapter"/>
<property name="jpaDialect" ref="jpaDialect"/>
<property name="jpaProperties">
    <props>
        <prop key="hibernate.enable_lazy_load_no_trans">true</prop>
    </props>
</property>

Java Config:

@Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(){
        LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean();
        //..
        entityManager.setJpaProperties(additionalProperties());
        //..
        return entityManager;
    }


  public Properties additionalProperties(){
        Properties properties = new Properties();

        // Etc
        properties.setProperty("hibernate.enable_lazy_load_no_trans",true));
     // Etc
    return properties;
  }
Rafik BELDI
  • 4,140
  • 4
  • 24
  • 38
  • I'm using annotation, futhermore this decreases the program performance, or I wrong? – luca Oct 21 '15 at 09:16
  • @luca here is a detailed explanation http://stackoverflow.com/questions/25362831/solve-hibernate-lazy-init-issue-with-hibernate-enable-lazy-load-no-trans – Rafik BELDI Oct 21 '15 at 09:21
  • so it is better to use custom query inside the repository rather than query methods, I understood the problem, but does it appear only with query method of spring? – luca Oct 21 '15 at 09:28
  • @luca no it's hibernate specific problem, it has nothing to do with spring – Rafik BELDI Oct 21 '15 at 09:39
  • so it isn't my error, so exists annotation to enable lazy load? – luca Oct 21 '15 at 09:41
  • @luca no it is a jpa propetry that you need to set up ? are you using spring boot ? – Rafik BELDI Oct 21 '15 at 09:45
  • @luca I added java config , all you have to do is to edit `getHibernateProperties` and add the lazy load property – Rafik BELDI Oct 21 '15 at 10:03
  • I have added this row, but now I have .12:34:11.830 [http-nio-8086-exec-4] WARN o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Handler execution resulted in exception: Could not write content: Infinite recursion (StackOverflowError) (through reference chain: com.domain.Car["carType"]->com.domain.CarType_$$_jvst4f2_e["cars"]->org.hibernate.collection.internal.PersistentSet[0]->com.domain.Car["carType"]- etc... – luca Oct 21 '15 at 10:36
  • 1
    @luca that's because you are doing a `bidirectionnel mapping` on CarType , comment cars on CarType it should fix that – Rafik BELDI Oct 21 '15 at 10:40
  • well, so I have to check all the entity created by Hibernate tools because probably all of them have this bidirectionnel mapping. Furthermore I receive Could not write content: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer – luca Oct 21 '15 at 12:34
  • @luca no you don't have to do that , you got stackoverflow,only when you are loading data from both directions, try to avoid that , it has nothing to do with the previous configuration – Rafik BELDI Oct 21 '15 at 12:48
  • I have update main post with carType changed, this problem could happen also for the other classes, independently to the previous configuration – luca Oct 21 '15 at 12:57
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/92965/discussion-between-rafik-beldi-and-luca). – Rafik BELDI Oct 21 '15 at 13:13