Page 1 of 2 12 LastLast
Results 1 to 10 of 18

Thread: Toplink ignores JPA annotations / porting Petclinic

  1. #1
    Join Date
    Dec 2006
    Posts
    4

    Default Toplink ignores JPA annotations / porting Petclinic

    As the Petclinic example (JPA version) uses xml-based mapping files (orm.xml), I tried to create a Petclinic version that uses JPA annotations.

    I succeeded with Hibernate as JPA persistence provider, my petclinic version with JPA annotations runs fine.

    But when using Toplink as JPA provider, I managed to run the Petclinic only successfully when I continue to use the xml-based mapping (orm.xml).

    It appears that Toplink completely ignores the JPA annotations , so when I eliminate orm.xml, no mappings are defined. Consequently, when running the Petclinic and trying to display all veterinarians, Toplink throws the following exception, which isn't surprising: oracle.toplink.essentials.exceptions.EJBQLExceptio n Exception Description: Unknown abstract schema type [Vet]

    When NOT eliminating orm.xml, however, my Petclinic JPA version runs fine with Toplink.

    There are some pitfalls I am aware of:

    First of all, my persistence.xml file to define the persistence unit has the <exclude-unlisted-classes> element either uncommented or set to "false", so scanning of unlisted-classes should actually not be prevented. Also, there is no <xml-mapping-metadata-complete/> element in my persistence.xml.

    Secondly, when persistence.xml is placed in WEB-INF/classes/META-INF of my Petclinic WAR-file, my compiled Java classes are in WEB-INF/classes (and not in a separate JAR file placed in WEB-INF/lib).

    My questions:

    How can I configure Toplink Essentials (using Tomcat 6.0.2) and Spring 2.0 so that it doesn't ignore the JPA annotations placed on Entity classes?

    Does anyone perhaps have a small example to demonstrate that Toplink, set up by Spring, can read JPA annotations (rather than just xml-based mapping files)?


    Any hints would be highly appreciated.



    applicationContext-jpa.xml (placed in WEB-INF):
    Code:
    <?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:aop="http://www.springframework.org/schema/aop"
    	     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.0.xsd
               http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
               http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
    
    
    	<!-- Configurer that replaces ${...} placeholders with values from a properties file -->
    	<!-- (in this case, JDBC-related settings for the dataSource definition below) -->
    	<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    		<property name="location" value="/WEB-INF/jdbc.properties"/>
    	</bean>
    
    
    	<!-- Local DataSource that works in any environment -->
    	<!-- Note that DriverManagerDataSource does not pool; it is not intended for production -->
    	<!-- See JPetStore for an example of using Commons DBCP BasicDataSource as alternative -->
    	<!-- See Image Database for an example of using C3P0 ComboPooledDataSource as alternative -->
    	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    		<property name="driverClassName" value="${jdbc.driverClassName}"/>
    		<property name="url" value="${jdbc.url}"/>
    		<property name="username" value="${jdbc.username}"/>
    		<property name="password" value="${jdbc.password}"/>
    	</bean>
    
    	<!-- JPA EntityManagerFactory -->
    	<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    		<property name="dataSource" ref="dataSource"/>
    		<!-- loadTimeWeaver not needed for Hibernate --> 
    		<property name="loadTimeWeaver">
    			<bean class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver"/>
    		</property> 
    		
    		<property name="jpaVendorAdapter">
    			<bean class="org.springframework.orm.jpa.vendor.TopLinkJpaVendorAdapter">
    				<!-- <property name="databasePlatform"
    						value="org.springframework.samples.petclinic.toplink.EssentialsHSQLPlatformWithNativeSequence"/> -->
    			        <property name="databasePlatform" value="oracle.toplink.essentials.platform.database.MySQL4Platform"/>
    		        	<property name="generateDdl" value="false"/> 
    				<property name="showSql" value="true" />
    			</bean>
    		</property> 
    	</bean>
    
    	<!-- Transaction manager for a single JPA EntityManagerFactory (alternative to JTA) -->
    	<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    		<property name="entityManagerFactory" ref="entityManagerFactory"/>
    	</bean>
    
    
    	<!--
    		Instruct Spring to retrieve and apply @AspectJ aspects which are defined
    		as beans in this context (such as the UsageLogAspect below).
    	-->
    	<aop:aspectj-autoproxy/>
    
    	<!--
    		Simply defining this bean will cause requests to owner names to be saved.
    		Spring automatically deploys the @Aspect when AspectJ autoproxying is enabled.
    		Note that we can dependency inject this bean like any other bean.
    	-->
    	<bean class="org.springframework.samples.petclinic.aspects.UsageLogAspect">
    		<property name="historySize" value="300"/>
    	</bean>
    
    
    	<!--
    		Instruct Spring to perform declarative transaction management automatically
    		on annotated classes.
    	-->
    	<tx:annotation-driven/>
    
    	<!--
    		PostProcessors to perform resource injection according to the JPA specification
    	  (@PersistenceContext, @PersistenceUnit).
    	-->
    	<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
    
    	<!--
    		PostProcessors to perform exception translation on @Repository classes (from native
    		exceptions such as JPA PersistenceExceptions to Spring's DataAccessException hierarchy).
    	-->
    	<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
    
    
    	<!--
    		Will automatically be transactional due to @Transactional.
    		EntityManager will be auto-injected due to @PersistenceContext.
    		PersistenceExceptions will be auto-translated due to @Repository.
    	-->
    	<bean id="clinic" class="org.springframework.samples.petclinic.jpa.EntityManagerClinic"/>
    
    
    </beans>
    persistence.xml (placed in WEB-INF/classes/META-INF):
    Code:
    <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="PetClinic" transaction-type="RESOURCE_LOCAL">
    
    
    		<!--
    			Prevent annotation scanning. In this app we are purely driven by orm.xml.
    		-->
    		 <exclude-unlisted-classes>false</exclude-unlisted-classes> 
    
    		<!--
    			Using Spring we don't need the basic required vendor-specific properties like 
    			the following, which in this sample app are all conveyed in Spring configuration...
    		-->
    		<properties>
                   </properties>
    	</persistence-unit>
    
    </persistence>

    Spring version used: 2.0

    Toplink essentials version:
    taken from Spring 2.0 distribution, but version from glassfish-persistence-installer-v2-b25.jar doesn't work either.

    spring-tomcat-weaver.jar placed in ${TOMCAT_HOME}/lib

    Tomcat version used: 6.0.2

  2. #2
    Join Date
    Dec 2006
    Location
    Normal, Illinois
    Posts
    277

    Default

    Have you tried listing your entities in the persistence.xml file using the <class> node?
    Caleb Washburn

  3. #3
    Join Date
    Dec 2006
    Posts
    4

    Default

    Quote Originally Posted by cwash5 View Post
    Have you tried listing your entities in the persistence.xml file using the <class> node?
    Yes, I already tried that before posting here.

    An hour ago I tried the following:

    I deployed a Petclinic version with JPA-Annotations and Hibernate as persistence provider. Via context.xml put in /META-INF of the WAR-File, I also activated the org.springframework.instrument.classloading.tomcat .TomcatInstrumentableClassLoader,
    even though this classloader is NOT needed by Hibernate, but only by Toplink.

    My intention was to first deploy a Hibernate-JPA-Annotations-based Petclinic and afterwards, when it runs without problems, simply choose Toplink as persistence provider by stopping Tomcat, changing the persistence provider defined via the Spring application context (and not via persistence.xml) and then restarting Tomcat.

    But it does not have any effect on Toplink, as far as processing of the Annotations is concerned.

    Of course, if I add orm.xml, the deployed Petclinic also works with Toplink as persistence provider.


    My context.xml is as follows: (placed in /META-INF of the WAR file)
    Code:
    <?xml version="1.0" encoding="UTF-8" ?>
    
    <Context path="/petclinicJPA_Annotations" 
                   docBase="petclinicJPA_Annotations"
            debug="5" reloadable="true" crossContext="true">
        <Loader loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"/>
    </Context>
    persistence.xml (with explicitly listed classes):
    Code:
    <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="PetClinic" transaction-type="RESOURCE_LOCAL">
                  <class>org.springframework.samples.petclinic.Person</class>
                  <class>org.springframework.samples.petclinic.BaseEntity</class>
                  <class>org.springframework.samples.petclinic.Owner</class>
                  <class>org.springframework.samples.petclinic.Visit</class>
                  <class>org.springframework.samples.petclinic.Vet</class>
                  <class>org.springframework.samples.petclinic.Pet</class>
                  <class>org.springframework.samples.petclinic.PetType</class>
                  <class>org.springframework.samples.petclinic.Specialty</class>
                  <class>org.springframework.samples.petclinic.NamedEntity</class>
    	</persistence-unit>
    
    </persistence>


    Has anyone ever got Toplink with JPA annotations (not just XML mapping files) to work under Spring + Tomcat 6?
    Last edited by IngoM; Dec 17th, 2006 at 01:55 PM.

  4. #4
    Join Date
    Jul 2006
    Posts
    22

    Default

    I've got JPA Toplink working well. But to wrok, I had to use the JpaDaoSupport.getJpaTemplate().

    I'm a beginner, so take the following code has a working example, not a good example ;-)

    Here are my files (sorry but XML file attachment is not allowed).

    persistence.xml:
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <persistence version="1.0" 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">
      <persistence-unit name="Tap03PU" transaction-type="RESOURCE_LOCAL">
    <provider>oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider</provider>
        <class>tap03.domain.model.Document</class>
        <class>tap03.domain.model.Configuration</class>
        <properties>
          <property name="toplink.jdbc.url" value="jdbc:mysql://localhost:3306/tap03"/>
          <property name="toplink.jdbc.driver" value="com.mysql.jdbc.Driver"/>
          <property name="toplink.jdbc.user" value="root"/>
          <property name="toplink.jdbc.password" value=""/>
          
          <property name="toplink.cache.type.default" value="NONE" />
          <property name="toplink.logging.level" value="FINEST" />
          <property name="toplink.logging.thread" value="true" />
          <property name="toplink.logging.session" value="true" />
          <property name="toplink.logging.exceptions" value="true" />
          
        </properties>
      </persistence-unit>
    </persistence>
    applicationContext.xml:
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" 
    "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
    <beans>
        <bean id="documentsManager" class="tap03.service.impl.DocumentsManagerImpl">
            <property name="documentDao">
                <ref bean="documentDAO" />
            </property>
            <property name="configurationManager">
                <ref bean="configurationManager" />
            </property>
        </bean>
        <bean id="configurationManager" class="tap03.service.impl.ConfigurationManagerImpl">
            <property name="configurationDao">
                <ref bean="configurationDAO" />
            </property>
        </bean>
    </beans>
    applicationContewxt-JPA.xml:
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" 
    "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
    <beans>
        <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
            <property name="persistenceUnitName" value="Tap03PU" />
            <property name="jpaVendorAdapter">
                <bean class="org.springframework.orm.jpa.vendor.TopLinkJpaVendorAdapter">
                    <property name="showSql" value="true" />
                    <property name="generateDdl" value="true" />
                    <property name="databasePlatform" value="oracle.toplink.essentials.platform.database.MySQL4Platform" />
                </bean>
            </property>
        </bean>
        
        <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
            <property name="entityManagerFactory" ref="entityManagerFactory" />
            <property name="dataSource" ref="dataSource" />
        </bean>
        <bean id="documentDAOTarget" class="tap03.domain.dao.jpa.GenericDaoJpa" >
            <constructor-arg>
                <value>tap03.domain.model.Document</value>
            </constructor-arg>
            <property name="entityManagerFactory" ref="entityManagerFactory" />
        </bean>
        <bean id="documentDAO" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" >
            <property name="transactionManager" ref="transactionManager" />
            <property name="target" ref="documentDAOTarget" />
            <property name="transactionAttributes">
                <props>
                    <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
                    <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
                    <prop key="save*">PROPAGATION_REQUIRED</prop>
                    <prop key="delete*">PROPAGATION_REQUIRED</prop>
                </props>
            </property>
        </bean>
        <bean id="configurationDAO" class="tap03.domain.dao.jpa.GenericDaoJpa" >
            <constructor-arg>
                <value>tap03.domain.model.Configuration</value>
            </constructor-arg>
            <property name="entityManagerFactory" ref="entityManagerFactory" />
        </bean>
    
    </beans>
    and finally the GenericDaoJpa.java:
    Code:
    package tap03.domain.dao.jpa;
    import java.io.Serializable;
    import java.util.Collection;
    import java.util.Map;
    import org.springframework.dao.DataAccessException;
    import org.springframework.orm.ObjectRetrievalFailureException;
    import org.springframework.orm.jpa.support.JpaDaoSupport;
    import tap03.domain.dao.GenericDao;
    public class GenericDaoJpa<T, ID extends Serializable>
        extends JpaDaoSupport
        implements GenericDao<T, ID>
    {
        private Class<T> entityClass;
        public GenericDaoJpa()
        {
        }
        public GenericDaoJpa(Class<T> type)
        {
            this.entityClass = type;
        }
        public Class<T> getPersistentClass()
        {
            return entityClass;
        }
        public T findById(ID id) throws ObjectRetrievalFailureException
        {
            return (T) getJpaTemplate().find(getPersistentClass(), id);
        }
        @SuppressWarnings("unchecked")
        public Collection<T> findAll()
        {
            String q = "SELECT z FROM "+ this.entityClass.getSimpleName() +" z" ;
            System.out.println( "GenericDaoJpa.findAll() q=\""+q+"\"" );
            return (Collection<T>) this.getJpaTemplate().find(q);
        }
        @SuppressWarnings("unchecked")
        public Collection<T> findByNamedQueryAndNamedParam(Class<T> entityClass,
            String queryName, Map<String,Object> params ) throws DataAccessException
        {
            return (Collection<T>) this.getJpaTemplate().findByNamedQueryAndNamedParams( queryName, params);
        }
        public T saveOrUpdate(T entity)
        {
            return getJpaTemplate().merge(entity);
        }
        public void delete(ID id)
        {
            /*
             * Entity must be managed to call remove: tap03.domain.model.Document[docId=11],
             * try merging the detached and try the remove again.
             */
            this.delete( this.findById(id) );
        }
        public void delete(T entity)
        {
            getJpaTemplate().remove(entity);
        }  
    }

  5. #5
    Join Date
    Dec 2006
    Posts
    4

    Default

    Quote Originally Posted by cyrille37 View Post
    I've got JPA Toplink working well. But to wrok, I had to use the JpaDaoSupport.getJpaTemplate().
    Hello,

    thanks for posting. In what environment do you use Spring with Toplink? Standalone, or have you deployed your application to Tomcat?


    The Petclinic example also contains a JpaTemplateClinic as alternative to EntityManagerClinic. But unfortunately, it does not solve my problem.

    In my case it appears that Toplink simply doesn't get initialized correctly to process the JPA annotations on Entity classes.

    I'm a beginner too who wants to evaluate to what extent Spring could be an alternative to EJB 3.0.

    As mentioned, my Hibernate configuration works fine with JPA annotations. As far as Toplink is concerned, I was just curious to know whether I could easily use Toplink as alternative JPA provider...


    But I will give up on this issue (Toplink) now... I do not have the knowledge of the Spring internals yet to find out why Toplink doesn't get intialized correctly, and I do not have a working example for comparison:

    Spring+ Toplink-JPA (with JPA annotations, not xml-mapping), deployable to Tomcat 6
    Last edited by IngoM; Dec 18th, 2006 at 08:15 AM.

  6. #6
    Join Date
    Jan 2005
    Location
    Bucharest, Romania
    Posts
    5,403

    Default

    Ingo, can you please raise an issue on JIRA and assign it to me. It's probably a good idea to add an annotation-petclinic example to prevent users from having problems as you did.
    I haven't tried Tomcat 6.x which is still in beta and I would advice you to try the latest stable release which is 5.2-something.
    Thanks.
    Costin Leau
    SpringSource - http://www.SpringSource.com- Spring Training, Consulting, and Support - "From the Source"
    http://twitter.com/costinl
    Please use [ c o d e ] [ / c o d e ] tags

  7. #7
    Join Date
    Jan 2005
    Location
    Bucharest, Romania
    Posts
    5,403

    Default

    Btw, can you give OpenJPA a try also? It would be helpful to pin point the problem - is it your configuration or something specific to oracle and tomcat?
    Costin Leau
    SpringSource - http://www.SpringSource.com- Spring Training, Consulting, and Support - "From the Source"
    http://twitter.com/costinl
    Please use [ c o d e ] [ / c o d e ] tags

  8. #8
    Join Date
    Dec 2006
    Posts
    4

    Default

    Quote Originally Posted by Costin Leau View Post
    Ingo, can you please raise an issue on JIRA and assign it to me. It's probably a good idea to add an annotation-petclinic example to prevent users from having problems as you did.
    I haven't tried Tomcat 6.x which is still in beta and I would advice you to try the latest stable release which is 5.2-something.
    Thanks.
    I'll make a deployment test to Tomcat 5.5 later today.

    As for the Petclinic example, if there is interest, I could send you my Hibernate JPA-annotations based version.

  9. #9
    Join Date
    Jan 2005
    Location
    Bucharest, Romania
    Posts
    5,403

    Default

    When creating the JIRA issue, please add the classes as an attachment.
    The only thing I am worried about is packing all this samples - one reason why annotations where not provided was to be able to reuse the current example for non-java5 users.
    I'll see what can be done. Thanks for the feedback!
    Costin Leau
    SpringSource - http://www.SpringSource.com- Spring Training, Consulting, and Support - "From the Source"
    http://twitter.com/costinl
    Please use [ c o d e ] [ / c o d e ] tags

  10. #10
    Join Date
    Jul 2006
    Posts
    22

    Default

    Quote Originally Posted by IngoM View Post
    Hello,
    thanks for posting. In what environment do you use Spring with Toplink? Standalone, or have you deployed your application to Tomcat?
    JDK 1.5, Tomcat 5.5.17, Spring 2, Toplink 9.1 build: b28

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •