Announcement Announcement Module
Collapse
No announcement yet.
Spring data cross-store support not work if entities are builded from another project Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring data cross-store support not work if entities are builded from another project

    Hi all,

    I'm integrating mongoDb in my project that still use JPA persistence. The entities are in another project that my business layer project import as a maven dependency. The "data project" contains entities with JPA annotation and only one @Document annotated bean and exist only ome relation between a jpa entity and this object through @RelatedDocument.
    The "data project" is successfully builded with maven 3 and aspect-j compile time weaving is ok.

    Code:
    <!-- aspect J -->
          <plugin>
    				<groupId>org.codehaus.mojo</groupId>
    				<artifactId>aspectj-maven-plugin</artifactId>
    				<version>1.3.1</version>
    				<configuration>
    					<complianceLevel>1.5</complianceLevel>
    					<verbose>true</verbose>
    					<showWeaveInfo>true</showWeaveInfo>
    					<outxml>true</outxml>
    					<aspectLibraries>
    						<aspectLibrary>
    							<groupId>org.springframework</groupId>
    							<artifactId>spring-aspects</artifactId>
    						</aspectLibrary>
    						<aspectLibrary>
    							<groupId>org.springframework.data</groupId>
    							<artifactId>spring-data-neo4j</artifactId>
    						</aspectLibrary>
    						<aspectLibrary>
                  				<groupId>org.springframework.data</groupId>
                  				<artifactId>spring-data-mongodb-cross-store</artifactId>
                			</aspectLibrary>
    					</aspectLibraries>
    				</configuration>
    				<executions>
    					<execution>
    						<goals>
    							<goal>compile</goal>
    							<goal>test-compile</goal>
    						</goals>
    					</execution>
    				</executions>
    				<dependencies>
    					<dependency>
    						<groupId>org.aspectj</groupId>
    						<artifactId>aspectjrt</artifactId>
    						<version>${aspectj.version}</version>
    					</dependency>
    					<dependency>
    						<groupId>org.aspectj</groupId>
    						<artifactId>aspectjtools</artifactId>
    						<version>${aspectj.version}</version>
    					</dependency>
    				</dependencies>
    			</plugin>
    In my business layer I've integrated the entityManagerFactory bean with mongo following Spring data cross-store guide:

    Code:
    	<!--  Mongo config -->
    	<mongo:mongo host="localhost" port="27017" />
    
    	<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
    		<constructor-arg name="mongo" ref="mongo" />
    		<constructor-arg name="databaseName" value="${documentStore.name}" />
    	</bean>
    
    	<bean class="org.springframework.data.mongodb.core.MongoExceptionTranslator" />
    
    	<!--  Mongo cross-store aspect config -->
    	<bean class="org.springframework.data.persistence.document.mongodb.MongoDocumentBacking" 
                    lazy-init="true" depends-on="mongoChangeSetPersister"
    		factory-method="aspectOf">
    		<property name="changeSetPersister" ref="mongoChangeSetPersister" />
    	</bean>
    	<bean id="mongoChangeSetPersister" lazy-init="true" depends-on="entityManagerFactory"
    		class="org.springframework.data.persistence.document.mongodb.MongoChangeSetPersister">
    		<property name="mongoTemplate" ref="mongoTemplate" />
    		<property name="entityManagerFactory" ref="entityManagerFactory" />
    	</bean>
    
            <!-- JPA Entity Manager Factory -->
        <bean id="entityManagerFactory" 
              class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
              lazy-init="true"
              depends-on="dataSource"
              p:dataSource-ref="dataSource"
              p:persistenceXmlLocation="classpath:META-INF/persistence.xml" 
        	  p:persistenceUnitName="${persistence.unit.name}" />
    
        <!--  ==================== -->  
        <!--   TRANSACTION Config  -->
        <!--  ==================== -->
        
    	<!-- Construct Atomikos UserTransactionManager, needed to configure Spring -->
    	<bean id="AtomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
    		init-method="init" destroy-method="close"
    		p:forceShutdown="false" />
    
    	<!-- Also use Atomikos UserTransactionImp, needed to configure Spring -->
    	<bean id="AtomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp" 
    		p:transactionTimeout="300" />
    
    	<!-- Configure the Spring framework to use JTA transactions from Atomikos -->
    	<bean id="transactionManager"
    		class="org.springframework.transaction.jta.JtaTransactionManager" 
    		p:transactionManager-ref="AtomikosTransactionManager" 
    		p:userTransaction-ref="AtomikosUserTransaction">
    	</bean>
    	
    	<!-- use declarative transaction management  -->
        <tx:annotation-driven transaction-manager="transactionManager" mode="aspectj"/>
    As you see from the spring xml context, the EntityManagerFactory is created and configured from persistence.xml located in the jar of my "data layer" project. I'm NOT USING Spring data JPA or repositories, etc, etc.

    During startup the creation of EntityManagerFactory fails after hibernate validation phase:

    Code:
    javax.persistence.PersistenceException: [PersistenceUnit: moveoPersistenceUnit] Unable to build EntityManagerFactory:
    org.hibernate.MappingException: property mapping has wrong number of columns: org.novaworks.data.Calendar._persistent_id type: object
    	at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:465)
    	at org.hibernate.mapping.RootClass.validate(RootClass.java:236)
    	at org.hibernate.cfg.Configuration.validate(Configuration.java:1193)
    	at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1378)
    	at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:954)
    	at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:891)
    	at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:74)
    	at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:225)
    	at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:308)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1477)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1417)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
    	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
    	at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findDefaultEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:529)
    	at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:495)
    	at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.resolveEntityManager(PersistenceAnnotationBeanPostProcessor.java:656)
    	at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.getResourceToInject(PersistenceAnnotationBeanPostProcessor.java:629)
    	at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:147)
    	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:84)
    	at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:338)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1074)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:374)
    	at org.springframework.beans.factory.wiring.BeanConfigurerSupport.configureBean(BeanConfigurerSupport.java:140)
    	at org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect.configureBean(AnnotationBeanConfigurerAspect.aj:59)
    	at org.springframework.beans.factory.aspectj.AbstractDependencyInjectionAspect.ajc$afterReturning$org_springframework_beans_factory_aspectj_AbstractDependencyInjectionAspect$2$1ea6722c(AbstractDependencyInjectionAspect.aj:89)

    The buiness layer itself is builded by maven using aspect-j plugin for compile-time weaving, same configuration used in the "data layer" project.
    I'm guess that the error came from this "two step" build process (the complete project is composed by 6 modules!) and all are builded with maven (jenkins continuous integration): some aspect are not weaved in my entities (or maybe too many! :-) ) so Hibernate it's trying to map mongo related properties to relational DB?

    It's strange that the entity tha raise the error first, has no @RelatedDocument fields!

    Another hint: I've already tested a similar integration with Spring data graph cross-store, and I've found a similar problem (EntityManager tried to map a neo4j weaved property)! So it seems a problem related to Spring DATA's cross-storing architecture in general? or maybe of my domain model? (ALL my entities inherits from a common AbstractPersistenceEntity class, so the @Document aspect can work badly with such objects- actually no example provided by Spring data store guides show use of inheritance in beans or entities).

    Hoping that Spring Data community can help me, kind regards
    Stefano

  • #2
    Solution (very simple ... ):
    JPA entity mapping annotations were on getter methods while Spring data mongo were on fields. Moving jpa's on fields too solved my problem.

    Comment

    Working...
    X