How to configure EclipseLink 2.0 and Spring 3.0.5 and Tomcat 6?

20,097

Thanks, James.

Following Springsource guidance at http://static.springsource.org/spring/docs/3.0.0.M4/reference/html/ch13s05.html, Tomcat 6 works on the weaving. The steps as mentioned in the guidance and copied here:

Step1.Copy spring-tomcat-weaver.jar into $CATALINA_HOME/lib, where $CATALINA_HOME represents the root of the Tomcat installation)

Step2. Tell Tomcat to use custom classloader by modifying context.xml:

<Context path="/myWebApp" docBase="/my/webApp/location">
    <Loader loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"
        useSystemClassLoaderAsParent="false"/>
</Context>

I didn't specify on path and docBase attribute as I put in $CATALINA_HOME/conf/context.xml

Step3. Turn on loadTimeWeaver property to LocalContainerEntityManagerFactoryBean

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
  <property name="loadTimeWeaver">
    <bean class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver"/>
  </property>
</bean> 

then, I started Tomcat 6 again and start-up process becomes clean. However, data still could not be persisted into database. The error is like below:

Not allowed to create transaction on shared EntityManager - use Spring transactions or EJB CMT instead

My co-worker saved me at this point by pointing out that Spring transaction handling with @Transactional and not use transactions on the entity manager to avoid the issue above. then I commented out em.getTransaction().begin() and em.getTransaction().commit(), leaving em.persist(todo) only. todo is the entity here. It works immediately. Here, developer should be aware that the difference between JPA transaction and Spring transaction. In fact, it's a confused part when EclipseLink/JPA working with Spring Transaction Management.

I also tried Tomcat 7 as I had thought it might be related to Tomcat. In fact, this issue is nothing to do with Tomcat version.

With LoadTimeWeaver enabled, It works on data persistence. Here is the working version on the transactionManager configuration part in applicationname-servlet.xml:

   <context:property-placeholder location="classpath:generalform.properties"/>
   <context:component-scan base-package="com.generalform" />

   <tx:annotation-driven transaction-manager="transactionManager"/> 
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="${mysql.database.driver}" />
    <property name="url" value="${mysql.database.url}" />
    <property name="username" value="${mysql.database.user}" />
    <property name="password" value="${mysql.database.password}" />
</bean>

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceXmlLocation" value="classpath:persistence.xml" />
        <property name="dataSource" ref="dataSource" />         
        <property name="persistenceUnitName" value="restfulPU" />
        <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
            <property name="showSql" value="true"/>
            <property name="generateDdl" value="true"/>
            <property name="databasePlatform" value="org.eclipse.persistence.platform.database.MySQLPlatform"/>
        </bean>
        </property>
        <property name="jpaDialect">
        <bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect" />
        </property>
        <property name="loadTimeWeaver">
        <bean class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver" />
        </property>         

</bean> 

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="emf" />
</bean> 

Below is my Dao class, in formal way, try/catch should be wrapped around the code inside the method:

@Repository("todoDao")
public class TodoDao {  

    @PersistenceContext
    private EntityManager em;


    public void saveTodo(Todo todo) {

        System.out.println("TodoDao:saveTodo into DB >>>");
        //em.getTransaction().begin();
        em.persist(todo);
        //em.getTransaction().commit();
        em.close();
        System.out.println("TodoDao: complete saveTodo into DB close()>>>");
    }   

}   

The TodoService class declares Spring Transaction with @Transactional annotation, @Autowired is also working after enabling LoadTimeWeaver:

@Service("todoService")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
public class TodoService {
    @Autowired
    private TodoDao todoDao;

    public TodoService() {
    }

    @Transactional(propagation = Propagation.REQUIRED, readOnly = false)
    public void saveTodo(Todo todo) {
        System.out.println("TodoService -> saveTodo is called!");
        todoDao.saveTodo(todo);
    }
}   
Share:
20,097
Admin
Author by

Admin

Updated on March 05, 2020

Comments

  • Admin
    Admin about 4 years

    My web application is using Tomcat 6.0.18 and Spring 3.0.5 and eclipselink 2.0.1 and javax.persistence 2.0.0, SQL Server Database. I could not figure out the configuration and also not able to find out a working example with such configurations. I tried to add property of loadTimeWeaver into entityManagerFacotory but it break AutoWired annotation in Spring 3, like below in applicationContext.xml:

    <context:load-time-weaver/>
    

    in appname-servlet.xml:

    But when I disable LoadTimeWeaver, my application can create database from JPA code but could not persist data into database.

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
            <property name="persistenceXmlLocation" value="classpath:persistence.xml" />
            <property name="dataSource" ref="dataSource" />         
            <property name="persistenceUnitName" value="restfulPU" />
            <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
                <property name="showSql" value="true"/>
                <property name="generateDdl" value="true"/>
                <property name="databasePlatform" value="org.eclipse.persistence.platform.database.SQLServerPlatform"/>
            </bean>
            </property>
            <property name="jpaDialect">
            <bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect" />
            </property>         
            <property name="jpaPropertyMap">
            <props>
                <prop key="eclipselink.weaving">false</prop>
            </props>
            </property>         
    </bean> 
    
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean> 
    <tx:annotation-driven transaction-manager="transactionManager"/>
      Persistence.xml
    <persistence-unit name="restfulPU" transaction-type="RESOURCE_LOCAL">
        <class>com.generalform.eclipselink.model.Todo</class>
        <properties>
            <!-- EclipseLink should create the database schema automatically -->
            <property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
            <property name="eclipselink.ddl-generation.output-mode"
               value="database" />
        </properties>
    

    I will be thankful if you can point me to a guide or tutorial about integration of EclipseLink into Spring 3 plus Tomcat.

  • Sarkhan
    Sarkhan about 7 years
    in declareing entityManagerFactory just setting setPersistenceXmlLocation and setLoadTimeWeaver is enough.Other properties can be define in persistence.xml to avoid recompile and alson in declareing transactionManager there is no need to define username password etc. because all of these are in persistence.xml