Home

Spring / Toplink / MySQL set up

28th August 2008

Spring / Toplink / MySQL set up

Spring is an amazing framework in Java. However, the set up pain was really huge for a Tomcat / Toplink / MySQL set up. Here's how I finally managed to do it.

According the Spring documentation, here's how you're supposed to do it.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd" >
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.TopLinkJpaVendorAdapter">
<property name="showSql" value="true"/>
<property name="generateDdl" value="false"/>
<property name="databasePlatform" value="oracle.toplink.essentials.platform.database.MySQL4Platform"/> </bean>
</property>
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.SimpleLoadTimeWeaver"/>
</property>
</bean>

<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mydatabase"/>
<property name="username" value="myuser"/>
<property name="password" value="mypass"/>
</bean>

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

</beans>

The advantage of using the Spring set up is that you can use Spring to inject an entityManager into your data access objects. Unfortunately, although I fiddled and tried many times, it just didn't work over Tomcat. I got it working fine for my unit tests so I ended up having a seperate Spring/Toplink config file.

First I established a javax.sql.DataSource datasource connection in Tomcat. I did this by sticking it in the /META-INF/context.xml file

<Resource
auth="Container"
name="jdbc/mycon"
type="javax.sql.DataSource"
password="mypass"
driverClassName="com.mysql.jdbc.Driver"
maxIdle="2"
maxWait="5000"
username="myuser"
url="jdbc:mysql://localhost:3306/mydatabase?characterEncoding=UTF-8"
maxActive="4"/>

The characterEncoding proved necessary as I've outlined here

Next, I set up a persistence file in /WEB-INF/classes/META-INF/persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0"> <persistence-unit name="mypersistence" transaction-type="RESOURCE_LOCAL"> <provider>oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider</provider>
<non-jta-data-source>java:comp/env/jdbc/mycon</non-jta-data-source> <class>com.yourclass</class>

<properties>
<property name="toplink.weaving" value="true"/>
<property name="toplink.cache.type.default" value="Full"/>
<property name="toplink.cache.size.default" value="1"/> <property name="toplink.logging.level" value="FINE"/>
<property name="toplink.session.customizer" value="classes.ToplinkSessionCustomiser"/>
</properties>

</persistence-unit>

</persistence>

To get Toplink to pick up the DataSource, I had to use the toplink.session.customizer property. Here's the class

import oracle.toplink.essentials.tools.sessionconfiguration.SessionCustomizer;
import oracle.toplink.essentials.sessions.Session;
import oracle.toplink.essentials.jndi.JNDIConnector;

/**
* This is what is needed to get a JNDI database connection
* http://forums.oracle.com/forums/thread.jspa?threadID=519351&tstart=105
*/
public class ToplinkSessionCustomiser implements SessionCustomizer {
public ToplinkSessionCustomiser() { }

public void customize(Session session) throws Exception {
JNDIConnector connector = (JNDIConnector) session.getLogin().getConnector();
connector.setLookupType(JNDIConnector.STRING_LOOKUP);

}
}

Next I put together an EntityManager

import javax.persistence.Persistence;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityManager;

public class PersistenceUtil {
private static EntityManagerFactory emf;
private static String entity_name = "mypersistence";
private PersistenceUtil() { }

public static EntityManagerFactory getEMF() {
return getEMF();
}

public static EntityManager getManager() {
return getEMF().createEntityManager();
}

public static EntityManagerFactory getEMF() {
if (emf == null) {
emf = Persistence.createEntityManagerFactory(entity_name);
}
return emf;
}

}

I had to put spring-tomcat-weaver.jar into my /tomcat/common/lib folder

Finally, I was able to write some code to stuff to and from the database

import javax.persistence.Query;

/**
* @author Kevin Saunders, saunderswebsolutions.com
*/

@NamedQuery(
name = "userById",
query = "SELECT t FROM MyUserClass t WHERE t.userid = :userid"
)
public class EmailService {
private EntityManager em;

public final EntityManager getEntityManager() {
if (em == null) {
return em = PersistenceUtil.getManager();
}
return em;
}

public MyUserClass getEmail(Integer userid) {
Query query = getEntityManager().createNamedQuery("userById");
query.setParameter("userid", userid);
return query.getSingleResult();
}
}

I hope this helps someone to cut down on the set up time needed to get Spring working with Tomcat.

If you are having problems getting MySQL to maintain a connection to Toplink, click here