Alright, first off I know the topic has been discussed before. I've been googling and browsing the forums for three days and haven't found a suitable solution yet. I am trying to build a web app that delivers nested entities to a web frontend via AJAX with lazy-loading enabled. I am using Spring WebMVC, Hibernate and Jackson. Turning off lazy load is not a solution.
The problem is that during conversion of my entity beans to JSON, the jackson converter is not able to get a hibernate session in order to materialize the embedded (lazy-load) objects.
I tried to turn on the OpenSessionInView filter, but that didn't help a thing.
That's how it looks. Sorry for having german entity names upfront, but you might be able to read it anyways, the logic is: A "Person" ownes a "Niederlassung" (location), which further contains an "Adresse" (adress object).
The entity is defined as follows (shortened):Code:DEBUG LogicalConnectionImpl - Obtained JDBC connection DEBUG JdbcTransaction - initial autocommit status: true DEBUG JdbcTransaction - disabling autocommit DEBUG HibernateTransactionManager - Exposing Hibernate transaction as JDBC transaction ... DEBUG TwoPhaseLoad - Resolving associations for [galileo.model.Niederlassung#1] DEBUG TwoPhaseLoad - Done materializing entity [galileo.model.Niederlassung#1] DEBUG TwoPhaseLoad - Resolving associations for [galileo.model.Person#4] DEBUG TwoPhaseLoad - Done materializing entity [galileo.model.Person#4] DEBUG StatefulPersistenceContext - Initializing non-lazy collections DEBUG HibernateTransactionManager - Initiating transaction commit DEBUG HibernateTransactionManager - Committing Hibernate transaction on Session [SessionImpl(PersistenceContext[entityKeys=[EntityKey[galileo.model.Niederlassung#1], EntityKey[galileo.model.Person#4]],collectionKeys=[CollectionKey[galileo.model.Niederlassung.adressen#1]]];ActionQueue[insertions=[] updates=[] deletions=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[]])] DEBUG AbstractTransactionImpl - committing DEBUG AbstractFlushingEventListener - Processing flush-time cascades DEBUG AbstractFlushingEventListener - Dirty checking collections DEBUG Collections - Collection found: [galileo.model.Niederlassung.adressen#1], was: [galileo.model.Niederlassung.adressen#1] (uninitialized) DEBUG AbstractFlushingEventListener - Flushed: 0 insertions, 0 updates, 0 deletions to 2 objects DEBUG AbstractFlushingEventListener - Flushed: 0 (re)creations, 0 updates, 0 removals to 1 collections DEBUG EntityPrinter - Listing entities: DEBUG EntityPrinter - galileo.model.Niederlassung{id=1, adressen=<uninitialized>, reihenfolge=1, niederlassung=HQ, version=1} DEBUG EntityPrinter - galileo.model.Person... DEBUG JdbcTransaction - committed JDBC Connection DEBUG JdbcTransaction - re-enabling autocommit DEBUG HibernateTransactionManager - Closing Hibernate Session [SessionImpl(PersistenceContext[entityKeys=[EntityKey[galileo.model.Niederlassung#1], EntityKey[galileo.model.Person#4]],collectionKeys=[CollectionKey[galileo.model.Niederlassung.adressen#1]]];ActionQueue[insertions=[] updates=[] deletions=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[]])] after transaction DEBUG LogicalConnectionImpl - Releasing JDBC connection DEBUG LogicalConnectionImpl - Released JDBC connection ... DEBUG eptionHandlerExceptionResolver - Resolving exception from handler [public org.springframework.http.HttpEntity<java.util.List<galileo.model.Person>> galileo.controller.PersonAjaxController.get(javax.servlet.http.HttpServletRequest)]: org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: failed to lazily initialize a collection of role: galileo.model.Niederlassung.adressen, no session or session was closed (through reference chain: java.util.ArrayList[0]->galileo.model.Person["niederlassung"]->galileo.model.Niederlassung["adressen"]); nested exception is org.codehaus.jackson.map.JsonMappingException: failed to lazily initialize a collection of role: galileo.model.Niederlassung.adressen, no session or session was closed (through reference chain: java.util.ArrayList[0]->galileo.model.Person["niederlassung"]->galileo.model.Niederlassung["adressen"]) ... DEBUG DispatcherServlet - Null ModelAndView returned to DispatcherServlet with name 'spring': assuming HandlerAdapter completed request handling DEBUG DispatcherServlet - Successfully completed request DEBUG OpenSessionInViewFilter - Closing Hibernate Session in OpenSessionInViewFilter
Code:@Entity @Table(name = "person", catalog = "mdcrm") public class Person implements Serializable { private Niederlassung niederlassung; @ManyToOne @JoinTable(name="niederlassungPerson", joinColumns = @JoinColumn(name="person_id"), inverseJoinColumns = @JoinColumn(name="niederlassung_id")) public Niederlassung getNiederlassung() { return niederlassung; } public void setNiederlassung(final Niederlassung niederlassung) { this.niederlassung = niederlassung; } }
The controller that delivers the entites via AJAX:
The OpenSessionInView Filter in web.xml config looks like this: (shortened):Code:@RequestMapping(method = RequestMethod.POST, headers = { ACCEPT_JSON }, value="/get") public @ResponseBody HttpEntity<List<Person>> get(HttpServletRequest request) { logger.info("getPerson"); HttpHeaders headers = new HttpHeaders(); boolean intern = Boolean.parseBoolean(request.getParameter("intern")); String position = request.getParameter("position"); List<Person> persons = new ArrayList<Person>(); persons = bestandService.findAllPersonIntern(); return new HttpEntity<List<Person>>(persons, headers); }
The spring config looks like this (shortened):Code:<filter> <filter-name>sessionFilter</filter-name> <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class> <init-param> <param-name>sessionFactory</param-name> <param-value>sessionFactory</param-value> </init-param> </filter> <filter-mapping> <filter-name>sessionFilter</filter-name> <url-pattern>/app/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>ERROR</dispatcher> </filter-mapping>
Please advice. Thanks you :-)Code:<!-- HIBERNATE --> <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost/mdcrm" /> <property name="username" value="root" /> <property name="password" value="" /> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="packagesToScan" value="galileo.model" /> </bean> <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <tx:annotation-driven transaction-manager="transactionManager" /> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="*" propagation="REQUIRED" /> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="serviceMethods" expression="execution(* galileo.service.*Service*.*(..))" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods" /> </aop:config>


Reply With Quote