Spring Data JPA - Multiple Persistence Units working as JUnit, but not in Tomcat

I am nearly ready to fall back to my comfortable JDBC Template use for this one, but thought I'd see if the community has any insight. I added a 2nd set of JPA framework objects to my Spring-based application: new Entity Manager, Persistence Unit, etc. The exising Entity Manager uses ObjectDB for persistence and I want to use the slick Spring Data JPA API for a CRUD repository (Hibernate as an impl) but it's giving me trouble all along the way. I thought I had resolved everything locally b/c I had a JUnit that got past bean creation, but once I dropped those beans into an applicationContext I had a regression that I do not know how to fix

JUnit and Application context XML snippet with company name removed from the com.xxx

<context:annotation-config />
<context:component-scan base-package="com"/>
<jpa:repositories base-package="com.dms.server.mode" entity-manager-factory-ref="emf"/>
<!-- TxMgr #1 -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="emf" />
</bean>
<!-- EMF #1 -->
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" p:dataSource-ref="dataSource">
    <property name="persistenceUnitName" value="hibernate-pu" />
    <property name="persistenceXmlLocation" value="classpath:META-INF/persistence-hibernate.xml"/>
    <property name="persistenceProviderClass" value="org.hibernate.ejb.HibernatePersistence"/>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
    </property>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
        </props>
    </property>
</bean>


<bean id="sharedModeManager" class="com.dms.server.mode.DefaultSharedModeManager"/>
<bean id="changeRecordCommandFactory" class="com.dms.server.ChangeRecordCommandFactory"/>

<bean id="createModeCommand" class="com.dms.server.mode.CreateModeCommand">
    <property name="apsConnection" ref="ApsConnection" />
</bean>

<!-- TxMgr #2 -->
<bean id="EnvDMSTxManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="EnvDMSEntityManagerFactory"/>
</bean>
<!-- EMF #2 -->
<bean id="EnvDMSEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="envService"/>
    <property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml"/>
    <property name="persistenceProviderClass" value="com.objectdb.jpa.Provider"/>
</bean>

persistence-hibernate.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.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_2_0.xsd">
<persistence-unit name="hibernate-pu" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <mapping-file>META-INF/orm-none.xml</mapping-file>
    <class>com.api.dms.SharedMode</class>
    <class>com.api.dms.SharedModeAssignment</class>
    <exclude-unlisted-classes>true</exclude-unlisted-classes>
    <properties>
        <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
        <property name="hibernate.hbm2ddl.auto" value="validate" />
        <property name="hibernate.show_sql" value="true" />
    </properties>
</persistence-unit>

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.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_2_0.xsd">
<persistence-unit name="envService" transaction-type="RESOURCE_LOCAL">
    <provider>com.objectdb.jpa.Provider</provider>
    <mapping-file>META-INF/orm-objectdb.xml</mapping-file>
    <class>com.awareness.server.environment.SampleIndicationHistory</class>
    <exclude-unlisted-classes>true</exclude-unlisted-classes>
    <properties>
        <property name="javax.persistence.jdbc.url" value="$temp/awp/envService.odb" />
        <property name="javax.persistence.jdbc.user" value="admin" />
        <property name="javax.persistence.jdbc.password" value="admin" />
    </properties>
</persistence-unit>

orm-none.xml (everything is picked up via annotations, but if I don't specify this file, the other orm file is picked up)

<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd" version="1.0">
</entity-mappings>

orm-objectdb.xml

<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_2_0.xsd" version="2.0">
<entity class="com.awareness.server.environment.SampleIndicationHistory" access="FIELD">
    <table name="SAMPLE_IND_HISTORY"/>
    <attributes>
        <id name="deviceId"/>
        <basic name="tOldest"/>
        <basic name="tNewest"/>
        <element-collection name="timestamps"/>
        <element-collection name="indexes"/>
    </attributes>
</entity>

Again, this all works fine and dandy in a JUnit

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"/com/junit-context.xml"})
// Functioning JUnit

But fails in Tomcat with

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sharedModeManager': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sharedModeRepository': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalArgumentException: Not an managed type: class com.api.dms.SharedMode
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:306)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1116)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:323)
... 33 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sharedModeRepository': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalArgumentException: Not an managed type: class com.api.dms.SharedMode
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:149)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:102)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1454)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:249)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:198)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:442)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:416)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:550)
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:150)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:303)
... 41 more
Caused by: java.lang.IllegalArgumentException: Not an managed type: class com.api.dms.SharedMode
at org.hibernate.ejb.metamodel.MetamodelImpl.managedType(MetamodelImpl.java:171)
at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.<init>(JpaMetamodelEntityInformation.java:68)
at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getMetadata(JpaEntityInformationSupport.java:65)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:146)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:84)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:67)
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:150)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.getObject(RepositoryFactoryBeanSupport.java:162)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.getObject(RepositoryFactoryBeanSupport.java:44)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:142)
... 51 more

Java Classes

@Repository
@PersistenceContext(unitName="hibernate-pu")
public interface SharedModeRepository extends CrudRepository<SharedMode, SharedModeKey> {
Iterable<SharedMode> findByName(String name);
Iterable<SharedMode> findByCurrent(boolean current);
SharedMode findBySharedModeKeyIdAndCurrent(int id, boolean current);
}

@PersistenceContext(name="hibernate-pu")
@Entity(name="shared_mode")
@XmlRootElement(name="sharedMode")
public class SharedMode implements Comparable<SharedMode>, ModeLike, Serializable {
    private static final long serialVersionUID = -3202319961514321359L;
    @EmbeddedId
    @XmlElement
    private SharedModeKey sharedModeKey = new SharedModeKey();
    @Column
    private String name;
    @Column
    private boolean current;
    ...
}

It's hard to know what is done differently in the start-up to make things fail, I've been stepping through a lot of framework code trying to determine exactly what goes wrong.

Answers


The last exception you get means JPA provider can not identify your bean. As you are using Spring, you can set packagesToScan property on the entityManagerFactory to the package which contains your entities to enable JPA provider to find them. Alternatively you can use persistence.xml and list all entities there.


Need Your Help

Using JSON RPC in Struts2 along with Spring Security causes the request to be forbidden(403)

json spring struts2 spring-security json-rpc

I use the following JavaScript/jQuery function to make a remote procedure call through JSON.

Automatically identifying ultimate and penultimate columns as variable in python

python python-2.7 variables multiple-columns

I am trying to automize a part of the following code that I introduced HERE. As it is, the code works and achieves my desired final result. However, one of the variables is semi-automatic and I would