I have an entity class whose full name is foo.bar.Book. I wrote a simple test class as below:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration({"/beans-test.xml", "/dataSource-test.xml"})
public class BookTest {
#PersistenceContext EntityManager entityManager;
#Transactional
#Test
public void test() {
Book book = new Book();
book.setTitle("Hello");
entityManager.persist(book);
}
}
In the dataSource-test.xml, I have
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath:META-INF/persistence-test.xml" />
<property name="persistenceUnitName" value="tempWarPU" />
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="foo.bar.*" />
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
</property>
</bean>
Note that there is a property packagesToScan above, which is supposed to enable Spring to find foo.bar.Book. However, that didn't happen. I got an error like this:
java.lang.IllegalArgumentException: Unknown entity: foo.bar.Book
Nevertheless, the test will pass if I add the line below to the persistence-test.xml that shows in the bean definition of entityManagerFactory:
<class>foo.bar.Book</class>
So, it seems to me the packagesToScan property is not really working. Is that true? If so, how can I make Spring to auto-scan for entity classes? I tried putting <exclude-unlisted-classes>false</exclude-unlisted-classes> in the persistence-test.xml, but that didn't help.
Thank you very much.
update
The version of Spring is 4.0.0.RELEASE.
I also tried non-wildcard way as below, but no luck.
<property name="packagesToScan" value="foo.bar" />
<property name="persistenceUnitName" value="test-pu" />
<property name="packagesToScan">
<list>
<value>abc.xyz.entity.**.*</value>
</list>
</property>
This two properties won't work together.
1. persistence.xml exist and LocalContainerEntityManagerFactoryBean specifies persistenceUnitName
2. LocalContainerEntityManagerFactoryBean defines persistence unit with scan.
If You want to check this behawior debug: org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager
methods: readPersistenceUnitInfos, buildDefaultPersistenceUnitInfo
Made my tests on spring 3.2.8
Try the following line in your configuration file
<property name="packagesToScan" value="foo.bar" />
Related
I asked a similar question, but based on the responses, I did a bad job describing what I am after. I have a spring 4 webapp that loads properties from a properties file. We consume those properties both via the "${proper.name"} expressions in spring, as well as by injecting a properties object into some of our classes.
We want to move most of the properties to a database table and make them reloadable. However, a few need to stay in local properties, potentially overriding the database setting. These should also be loaded dynamically after the app is running.
I know that once a particular bean is injected, it won't get reloaded, that doesn't concern me, it's up to that module to handle that. But I am having trouble getting the behavior I want. In particular, I have implemented an AbstractConfiguration from apache commons configuration to get the dual source and overriding I am after. But while it works for injecting the properties object, expressions loaded with "${prop.name}" don't work at all.
How can I get them to work? Did I override the wrong thing? Is it just some config detail?
<bean id="sysProperties" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="databaseConfigurator" />
<property name="targetMethod" value="getProperties"/>
</bean>
<bean id="databaseConfigurator" class="my.util.config.MyDatabaseConfigurator">
<property name="datasource" ref="dataSource" />
<property name="propertyFile" value="/WEB-INF/my.properties" />
<property name="applicationName" value="ThisApp" />
</bean>
<bean id="dbConfigFactory" class="org.apache.commons.configuration.ConfigurationConverter" factory-method="getProperties">
<constructor-arg ref="databaseConfigurator" />
</bean>
I haven't tested this, but I think it might work.
<bean id="sysProperties" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="databaseConfigurator" />
<property name="targetMethod" value="getProperties"/>
</bean>
<bean id="databaseConfigurator" class="my.util.config.MyDatabaseConfigurator">
<property name="datasource" ref="dataSource" />
<property name="propertyFile" value="/WEB-INF/my.properties" />
<property name="applicationName" value="ThisApp" />
</bean>
<bean name="PropertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties" ref="CommonsConfigurationFactoryBean"/>
</bean>
<bean name="CommonsConfigurationFactoryBean" class="org.springmodules.commons.configuration.CommonsConfigurationFactoryBean">
<constructor-arg ref="databaseConfigurator"/>
</bean>
The problem is that the EntityManager injected with #PersistenceContext in a Spring managed bean does not persist the entities to the database. I have tried using #Transactional on the AddDao bean, where entityManager.persist() is called (I have enabled annotation-driven transactions).
The transaction begins in another bean which is instantiated by Camel with .transacted() in the Camel Java DSL. That bean has an #Autowired property which is the DAO and has the EntityManager injected with #PersistenceContext.
As transaction manager Bitronix is used.
A portion of the Spring xml configuration file looks like this:
<bean id="localContainerEntityManagerFactoryBean" depends-on="btmConfig" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jtaDataSource" ref="dataSource"/>
<property name="persistenceUnitName" value="nameFromPersistenceXml"/>
<property name="persistenceProvider">
<bean class="org.hibernate.ejb.HibernatePersistence"/>
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
</property>
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
</property>
<property name="packagesToScan" value="package with #Entity POJOs"/>
</bean>
<bean id="btmConfig" factory-method="getConfiguration"
class="bitronix.tm.TransactionManagerServices">
<property name="serverId" value="spring-btm" />
</bean>
<!-- create BTM transaction manager -->
<bean id="BitronixTransactionManager" factory-method="getTransactionManager"
class="bitronix.tm.TransactionManagerServices" depends-on="btmConfig"
destroy-method="shutdown" />
<!-- Spring JtaTransactionManager -->
<bean id="springTransactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager" ref="BitronixTransactionManager" />
<property name="userTransaction" ref="BitronixTransactionManager" />
</bean>
<tx:annotation-driven transaction-manager="springTransactionManager" />
Edit: In a overly simplified version it looks like this:
In Camel Java DSL there is
from("wsLayer")
.transacted()
.otherProcessing()
.to("bean:addBean?method=addMyEntity")
And add beans look something like this:
#Component
public class AddBean {
#Autowired
private AddDao addDao;
public void addMyEntity(MyEntity myEntity) {
//other business logic
addDao.persistMyEntity(myEntity);
}
}
#Component
public class AddDao {
#PersistenceContext
private EntityManager entityManager;
//I have tried here
//#Transactional and
//#Transactional(propagation = PropagationType.REQUIRES_NEW)
public void persistMyEntity(MyEntity myEntity) {
entityManager.persist(myEntity);
}
}
The reading from the database works well.
See the data source:
<bean id="dataSource" class="bitronix.tm.resource.jdbc.PoolingDataSource"
init-method="init" destroy-method="close">
<property name="uniqueName" value="theName" />
<property name="maxPoolSize" ><value>${db.pool.maxSize}</value></property>
<property name="minPoolSize" ><value>${db.pool.minSize}</value></property>
<property name="allowLocalTransactions" ><value>true</value></property>
<property name="automaticEnlistingEnabled" ><value>true</value></property>
<property name="className" ><value>${db.pool.datasource}</value></property>
<property name="driverProperties" ref="databaseProperties" />
</bean>
where the properties are set in Maven's pom.xml like this:
db.pool.maxSize=15
db.pool.maxSize=5
db.pool.datasource=org.postgresql.xa.PGXADataSource
Did you tried to execute em.flush() after em.persist(entity)?
According with the docs of Java EE:
em.persist(entity): Make an instance managed and persistent.
BUT
em.flush(entity): Synchronize the persistence context to the underlying database.
So, you can do something like:
em.persist(myEntity);
em.flush();
And check if this change make a difference.
From the limited symptoms given, seems like the JTA transaction is not being started and propagated. Your EM would work fine up to a point - reading from DB, allowing data changes against it's Persistent Context cache, but never writing to the DB.
Think it's a config problem and your #Transaction annotations are being ignored.
I have enabled annotation-driven transactions.
Make sure it's configured as follows in your Spring configuration:
<tx:annotation-driven transaction-manager="springTransactionManager"/>
where:
xmlns:tx="http://www.springframework.org/schema/tx"
Try the #Transactional in this way
#Component
public class AddDao {
#PersistenceContext
private EntityManager entityManager;
#Transactional("BitronixTransactionManager")
public void persistMyEntity(MyEntity myEntity) {
entityManager.persist(myEntity);
}
}
I am configuring Spring to use JPA by using Hibernate implementation. However I don't understand the process completly. I have gotten it to work by following different blogs etc. I have used EJB 3.1 and there I had a persistence.xml. However in spring I declared a LocalContainer...Bean and provided some properties to it, and I have no persistence.xml. Could someone explain how it works in Spring and what the declared bean is?
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="packagesToScan" value="com.company.domain" />
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.PostgreSQL82Dialect
</prop>
</props>
</property>
</bean>
There are different flavors of Spring Configuration with JPA, one which requires persistence.xml and other which requires just bean declarations(no persistence.xml).
I am going to take up the Case-2 in your scenario:
The main reasons we want a persistence.xml is because of the following reasons:
Database connectivity details.
Java classes which are treated as Entities or packages in which to scan for Entities.
Other vendor specific settings like hibernate.show_sql or similar stuff.
Now if spring provides a way to mention all this together in bean configurations then there is no need to have the persistence.xml.
In case of your bean definitions, lets break it down.
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="packagesToScan" value="com.company.domain" />
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.PostgreSQL82Dialect
</prop>
</props>
</property>
</bean>
First property, dataSource already contains the database settings.
Second property, jpaVendorAdapter is a property specific to Spring
Third property, packagesToScan this is a property of Spring to scan for entities, this we either do in persistence.xml by using "class" tags by mentioning each class FQN.
Fourth property, jpaProperties as the name suggests can either be in Spring or in persistence.xml
e.g.
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL82Dialect" />
Since you have all the configurations already in Spring bean, there's no need to have a persistence.xml
Just to add a FootNote:
Spring 3.1 provides an alternative: LocalContainerEntityManagerFactoryBean that accepts a 'packagesToScan' property, specifying base packages to scan for #Entity classes.
Hope this answer your queries.
I have several Spring beans in which one of the property value for all of them are same String value. Is there a way where I can define this String in XML at one place and refer it in all beans at property value settings?
<bean id="somebean" class="test.SomeBean">
<property name="property1" ref="someValue"></property>
<property name="commonProperty" value="commonValue"></property>
<bean id="nextBean" class="test.NextBean">
<property name="property2" ref="someValue"></property>
<property name="commonProperty" value="commonValue"></property>
How to set commonValue in a seperate place and refer it in both places?
Try like this.
<bean id="commonConfig" abstract="true">
<property name="commonField" value="CommonValue"></property>
</bean>
<bean id="class1" class="com.dataclass.Class1" parent="commonConfig">
<property name="field1" value="value1"></property>
</bean>
<bean id="class2" class="com.dataclass.Class2" parent="commonConfig">
<property name="field2" value="value2"></property>
</bean>
Class1 & Class2 having one common field name "commonField", parent attribute is use for this common purpose only.
In Spring this is called bean definition inheritance(this is not java class inheritance, above example Class1 & n Class not inheriting in their respective java file.)
For more detail, look at Spring doc's link.
I've never tried it before, but this should work
<bean id="commonProp" class="java.lang.String">
<constructor-arg name="original" value="yourString"></constructor-arg>
</bean>
Then, in every bean you need to reference it:
<bean id="somebean" class="test.SomeBean">
<property name="property1" ref="someValue"></property>
<property name="commonProperty" ref="commonProp"></property>
</bean>
You can define your string properties in some "init_constants.properties" file. Then you should load properties file in spring xml:
<bean id="properties"
class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:db.properties</value>
<value>classpath:mail.properties</value>
<value>classpath:init_constants.properties</value>
</list>
</property>
</bean>
And after that you can inject this properties using xml:
<bean id="somebean" class="test.SomeBean">
<property name="property1" ref="{$prop1}"></property>
<property name="commonProperty" value="commonValue"></property>
</bean>
or in code using #Value annotation:
#Value(value="${prop1}")
private String property1;
Well If commonValue is string then you can put it in properties file and read it using #Value annotation.
My DAO's are going to extend the HibernateDaoSupport class that spring provides.
Now I need to:
setup my database connection in web.xml
Tell spring I am using annotations for hibernate mapping?
wire the session to the HibernateDaoSupport object.
The doc's show a sample xml:
<beans>
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="jdbc:hsqldb:hsql://localhost:9001"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<bean id="mySessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource"/>
<property name="mappingResources">
<list>
<value>product.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.HSQLDialect
</value>
</property>
</bean>
</beans>
So the 'mydatasource' configures the connection to the database, and the mySessionFactory sets up the session.
What I am confused with is, where in the code are these beans being used?
I want to create a GenericDaoImpl that extendsHibernateDaoSupport. I will then create EntityDaoImpl that extend GenericDaoImpl.
Just confused as to where 'mydatasource' and 'mysessionFactory' are used internally. Shouldn't they both be properties to HibernateDaoSupport?
Shouldn't they both be properties to
HibernateDaoSupport?
Well, SessionFactory should. The DAO won't need the DataSource, since that's used internally by the SessionFactory. Your own code should have no need for the raw DataSource, and so should not have to be injected with it.
Your DAOs (which extend HibernateDaoSupport) need to injected with the SessionFactory bean, e.g.
public class DaoA extends HibernateDaoSupport {
// business methods here, that use getHibernateTemplate()
}
public class DaoB extends HibernateDaoSupport {
// business methods here, that use getHibernateTemplate()
}
<bean id="daoA" class="DaoA">
<property name="sessionFactory" ref="mySessionFactory"/>
</bean>
<bean id="daoB" class="DaoB">
<property name="sessionFactory" ref="mySessionFactory"/>
</bean>