Hi Doychi,
Did a small implementation of the "Open EntityManager In View" pattern using Spring 2.5.6 and
Hibernate 3.3.2 which is used as the JPA provider.
Here are the details:
- WEB-INF/web.xml:
<filter>
<filter-name>jpaFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>jpaFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>ClickServlet</servlet-name>
<servlet-class>org.apache.click.extras.spring.SpringClickServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
- src/conf/persistence.xml (mostly empty as setup is done by spring)
<persistence-unit name="persistence"
transaction-type="RESOURCE_LOCAL">
</persistence-unit>
- WEB-INF/applicationContext.xml (meat is defined in spring config)
<context:component-scan base-package="com.mycorp"
scope-resolver="org.apache.click.extras.spring.PageScopeResolver"/>
<bean id="myDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="jdbc:hsqldb:mem:demoDB"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="myDataSource"/>
<property name="jpaVendorAdapter">
<bean
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform"
value="org.hibernate.dialect.HSQLDialect"/>
<property name="showSql" value="true" />
<property name="generateDdl" value="true" />
</bean>
</property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
<property name="dataSource" ref="myDataSource"/>
</bean>
- MyContactService class:
@Component
@Transactional
public class MyContactService implements ContactService {
@PersistenceContext
private EntityManager entityManager;
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
public List<Contact> getAll() {
return entityManager.createQuery("from Contact").getResultList();
}
}
- And finally the ContactPage:
@Component
public class ContactEditPage extends Page {
@Resource(name="myContactService")
private ContactService contactService;
...
}
Here is a snippet from the log file (add log4j.xml to the classpath to view
detailed logs):
DEBUG OpenEntityManagerInViewFilter - Using EntityManagerFactory 'entityManagerFactory' for
OpenEntityManagerInViewFilter
DEBUG DefaultListableBeanFactory - Returning cached instance of singleton bean
'entityManagerFactory'
DEBUG OpenEntityManagerInViewFilter - Opening JPA EntityManager in
OpenEntityManagerInViewFilter
[Click] [debug] GET http://localhost:9999/click-jpa-example/contact-edit.htm
DEBUG DefaultListableBeanFactory - Creating instance of bean 'contactEditPage'
DEBUG InjectionMetadata - Processing injected field of bean 'contactEditPage': ResourceElement for
private com.mycorp.service.ContactService com.mycorp.ContactEditPage.contactService
DEBUG DefaultListableBeanFactory - Returning cached instance of singleton bean
'myContactService'
DEBUG DefaultListableBeanFactory - Finished creating instance of bean
'contactEditPage'
....
DEBUG AnnotationTransactionAttributeSource - Adding transactional method [save] with attribute
[PROPAGATION_REQUIRED,ISOLATION_DEFAULT]
** Note this entry **
DEBUG JpaTransactionManager - Found thread-bound EntityManager
[org.hibernate.ejb.entitymanageri...@13e6f83] for JPA transaction
DEBUG JpaTransactionManager - Creating new transaction with name
[com.mycorp.service.ContactService.save]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
DEBUG DriverManagerDataSource - Creating new JDBC DriverManager Connection to
[jdbc:hsqldb:mem:demoDB]
DEBUG JpaTransactionManager - Exposing JPA transaction as JDBC transaction [SimpleConnectionHandle:
org.hsqldb.jdbc.jdbcconnect...@b0c5a]
Hibernate: insert into Contact (id, firstname, lastname, email) values (null,
?, ?, ?)
Hibernate: call identity()
DEBUG JpaTransactionManager - Initiating transaction commit
DEBUG JpaTransactionManager - Committing JPA transaction on EntityManager
[org.hibernate.ejb.entitymanageri...@13e6f83]
** NOTE this entry **
DEBUG JpaTransactionManager - Not closing pre-bound JPA EntityManager after
transaction
...
DEBUG OpenEntityManagerInViewFilter - Closing JPA EntityManager in
OpenEntityManagerInViewFilter
DEBUG EntityManagerFactoryUtils - Closing JPA EntityManager
Bob Schellink wrote:
> Hi Doychi,
>
> Your transaction setting looks right. Have a look at your logs at
> startup for anything odd. Check that only one EntityManagerFactory or
> SessionFactory is created. Other than that I'm out of ideas at this
> point. Play around with the @Transactional annotation (remove it and see
> what happens). It seems to me like a Spring config issue so you might
> want to post on their forum for some help on this.
>
> Let us know how it goes.
>
> kind regards
>
> bob
>
>
> Doychi wrote:
>> Hi Bob,
>>
>> I'm using org.springframework.orm.jpa.JpaTransactionManager with
>> <tx:annotation-driven /> for transactions.
>>
>>
>> Bob Schellink-2 wrote:
>>> Been doing some investigation myself and seems that @Transactional
>>> might in fact work with the OpenEntityManagerInView filter.
>>>
>>> @Doychi: Which transaction manager have you defined in your spring.xml?
>>>
>>>
>>
>> --
>> Doychi
>
>