Hello friend i'm developing spring(4.0.3) and hibernate(4.3.6) based application.
I'm facing following error when I saved any object in session factory:
org.hibernate.HibernateException: save is not valid without active transaction
20:38:59,881 ERROR [STDERR] at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:348)
And following is the entry which I have used in my application-context.xml
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactoryAthena" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
On more thing I'd like to bring here if I used any value in transaction-manager attribute instead actual transactionManager for bean reference then its not throwing error.
So i think its not taking reference bean value.
Please help me!!
You should take a look in this link but follows an example using xml.
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactoryAthena" />
</bean>
<tx:annotation-driven transaction-manager="txManager"/>
<!-- the transactional advice (what happens; see the <aop:advisor/> bean below) -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<!-- the transactional semantics... -->
<tx:attributes>
<!-- all methods starting with get are read-only -->
<tx:method name="get*" read-only="true"/>
<!-- other methods use the default transaction settings (see below) -->
<tx:method name=""/>
</tx:attributes>
</tx:advice>
But nowadays I have been seeing the spring community using declarative transactions with annotations. Like the example below:
#Transactional(readOnly = true)
public class DefaultFooService implements FooService {
public Foo getFoo(String fooName) {
// do something
}
// these settings have precedence for this method
#Transactional(readOnly = false, propagation = Propagation.REQUIRED)
public void updateFoo(Foo foo) {
// do something
}
}
Use #EnableTransactionManagement at the top of your class:
#Component
#EnableTransactionManagement
public class Abc{
}
Related
I defined and successfully plugged in a Hibernate DB Interceptor which catches all Transactions.
public class HibernateTransactionInterceptor extends EmptyInterceptor {
#Override
public void afterTransactionBegin(Transaction tx) {
System.out.println("Intercepted");
// ...
super.afterTransactionBegin(tx);
}
}
applicationContext.xml:
<bean id="transactionInterceptor" class="myapp.interceptor.HibernateTransactionInterceptor" />
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<!-- Plug into SessionFactory the Interceptor bean define above -->
<property name="entityInterceptor" ref="transactionInterceptor" />
...
</bean>
Now, the Interceptor fires on all #Transaction service methods. But I need to only intercept #Transaction(readOnly=FALSE) methods (i.e., filter out all Read-Only methods). Is there a way to configure that?
I found the solution. There's an easy way to check for Read-Only/non-Read-Only Transactions with a Spring-level transaction listener. On the Spring level, rather than Hibernate, there's a method called TransactionSynchronizationManager.isCurrentTransactionReadOnly(). It can be called from the following implementation of TransactionSynchronization which uses a pointcut to intercept all #Before #Transactional Spring processing.
#Component
#Aspect
public class TransactionSynchronizationAspect implements TransactionSynchronization {
#Before("#annotation(org.springframework.transaction.annotation.Transactional)")
public void registerTransactionSynchronization() {
boolean isReadOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
if (!isReadOnly) {
// ... logic goes here...
}
// Continue
TransactionSynchronizationManager.registerSynchronization(this);
}
#Override
public void afterCompletion(int status) {
// No custom code here
}
}
As for the original Hibernate Transaction Listener in the Original Post, that strategy can still be used, but requires a tx:advice to restrict the Listener to specified (mapped) Service method names, like so:
<aop:config>
<aop:advisor id="managerTx" advice-ref="txAdvice"
pointcut="execution(* com.app.*.*.service.*.*(..))"/>
</aop:config>
<tx:advice id="txAdvice" transaction-manager="customTransactionManager">
<tx:attributes>
<tx:method name="delete*" propagation="REQUIRED" isolation="READ_COMMITTED"/>
<tx:method name="update*" propagation="REQUIRED" isolation="READ_COMMITTED"/>
<tx:method name="save*" propagation="REQUIRED" isolation="READ_COMMITTED"/>
</tx:attributes>
</tx:advice>
This XML file can be imported with #ImportResource. With this strategy, all Write operations would be intercepted with the Listener, while Reads would always go through automatically.
I have a JUnit test method which makes call to two different services and both services are running with different data sources and of course in two transaction managers.
So i have configured Flyway to use H2 data base and implemented JUnit test method as below.
#RunWith(SpringJUnit4ClassRunner.class)
#Transactional
public class DataControllerTest extends BaseIntegrationTest {
#Test
public void testDataSave() throws Exception {
// test code to call controller which internally calls two services.
assertEquals(1, JdbcTestUtils.countRowsInTable(this.jdbcTemplate, "Database1Table1"));
assertEquals(1, JdbcTestUtils.countRowsInTable(this.anotherjdbcTemplate, "Database2Table1"));
}
}
So my question is this test method is creating some records in H2 database and i want to clear that data after running this test.
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource1" />
</bean>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="*" />
</tx:attributes>
</tx:advice>
and other transaction manager to work on different data source are configured as below.
<bean id="txManager2"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="anotherDataSource" />
</bean>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="*" />
</tx:attributes>
</tx:advice>
Since i gave this test class as Transactional it would clean database after each test method run.
But currently it is clearning only one database. but i want to clean another database which is part of anotherDatasource.
How do i need to proceed to do that..?
If possible and How to mention these two transaction managers in #Transactional annotation.
I have a class that is responsible for execute stored procedure, it was working fine when I was using JTA... But cause I have some problems with redeploy, I removed JTA and I'm using local entity manager with spring:
<bean id="entityManagerFactoryErp" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="erpPU"/>
</bean>
<bean id="entityManagerErp" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
<property name="entityManagerFactory" ref="entityManagerFactoryErp"/>
</bean>
Now I get a NullPointerException when I try to get active session:
public class ExecutadorProcedimentoArmazenado extends BaseDao implements IExecutadorProcedimentoArmazenado {
public boolean executar(String nomeProcedimento) {
DataReadQuery query = configurarQuery(nomeProcedimento);
registro = executarProcedimento(query);
int resultado = Integer.parseInt(recuperarValorDeSaida("RESULTADO"));
mensagem = recuperarValorDeSaida("MSGERRO");
return resultado == 0;
}
.
.
private Session configurarSessao() {
JpaEntityManager jpaEntityManager = JpaHelper.getEntityManager(entityManager);
return jpaEntityManager.getActiveSession();
}
.
.
.
}
ADDED
Probably the problem is that entityManager doesn't have a transaction. I'm trying create the transaction with spring aop, it works for all other classes, but doesn't works for interface IExecutadorProcedimentoArmazenado:
<bean id="entityManagerFactoryErp" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="erpPU"/>
</bean>
<bean id="entityManagerErp" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
<property name="entityManagerFactory" ref="entityManagerFactoryErp"/>
</bean>
<bean id="transactionManagerErp"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactoryErp"/>
</bean>
<tx:advice id="txExecutadorProcedimento" transaction-manager="transactionManagerErp">
<tx:attributes>
<tx:method name="executar" rollback-for="Exception" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="operacoesExecutadorProcedimento" expression="execution(* com.hrgi.persistencia.IExecutadorProcedimentoArmazenado.executar(..))"/>
<aop:advisor advice-ref="txExecutadorProcedimento" pointcut-ref="operacoesExecutadorProcedimento"/>
</aop:config>
Could someone explain me why I can't get the Session for me invoke stored procedure??
The spring way of doing this is to simply inject the EntityManager with the #PersistenceContext annotation and return the delegate...
public class ExecutadorProcedimentoArmazenado extends BaseDao implements IExecutadorProcedimentoArmazenado {
#PersistenceContext
private EntityManager entitymanager
private Session configurarSessao() {
return ((JpaEntityManager) entityManager.getDelegate()).getActiveSession();
}
If the active session is null, it means there is no active session. I tested this and outside of a transaction, it gives an NPE. Inside a transaction, the code above works. Tested with Spring 3.1 / Eclipselink 2.0.
Your container in this case is Spring and is likely returning null from entityManager.getDelegate(), resulting in an NPE on jpaEntityManager.getActiveSession(). Try starting a transaction, or getting the EntityManager from an unwrapped EclipseLink EntityManagerFactory directly instead.
I am using Datanucleus, JDO and Spring's declarative #Transactional management woven with Aspect-J.
But when a 'normal' method gets a persistent object from a #Transactional method, the object's state will become transient (the persistence manager seems to be removed) and the object is no longer persistent.
Example:
public class Example {
public void test() throws Exception {
Login l = getLogin();
JDOHelper.getObjectState(l); // transient instead of persistent
l.getSomeOtherPersistentObj().doStuff(); // NullpointerException :(
}
#Transactional
private Login getLogin() {
// do transactional stuff here
// ..
return dao.find(Login.class, 1);
}
}
Why is this and how can I fix it without adding #Transactional in places where transactions are not needed? The following does (obviously) work so this indicates that a transactional as well as a non-transactional connection can be made:
A #Transactional method calls a #Transactional method
A #Transactional method calls a normal method
A normal method calls a normal method
If I call dao.refresh(l), I get: 'Object with id "" is managed by a different Object Manager', so maybe Spring is working on a different persistence manager than the DAO, is this the cause?
Here's my spring configuration (it might be relevant):
<bean id="pmf" class="org.datanucleus.api.jdo.JDOPersistenceManagerFactory" destroy-method="close">
<property name="connectionDriverName" value="com.mysql.jdbc.Driver"/>
...
<constructor-arg>
<map>
<entry key="datanucleus.autoCreateSchema" value="true" />
</map>
</constructor-arg>
</bean>
<bean id="myPmfProxy" class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy">
<property name="targetPersistenceManagerFactory" ref="pmf" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jdo.JdoTransactionManager">
<property name="persistenceManagerFactory" ref="myPmfProxy" />
</bean>
<bean id="JDODao" class="sw.JDODao">
<property name="persistenceManagerFactory" ref="myPmfProxy" />
</bean>
It turned out that my objects need to be detachable to do this.
Iv'e added (detachable="true") to my #PersistenceCapable annotations and set the following datanucleus options:
<entry key="datanucleus.DetachAllOnCommit" value="true" />
<entry key="datanucleus.detachedState" value="all" />
I'm having some trouble with Spring, JPA and Dynamic Proxy DAO classes which are initialized as Spring Beans. This particular project has been plaguing me on the persistence/transaction side for some time, and I'd like to get this nailed down once and for all.
First, here's a method from the DAO interface:
/**
* Perform a named query using numbered parameters and return the results as a list
* #param name
* #param params
* #return query results
*/
List getNQasList(String name, Object... params);
This bean is registered automatically with Spring using a postProcessBeanFactory method:
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
this.beanFactory = beanFactory;
for (Class entityClass : this.getPersistedClassList()) {
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
ConstructorArgumentValues constructorVals = new ConstructorArgumentValues();
constructorVals.addIndexedArgumentValue(0, entityClass);
beanDefinition.setConstructorArgumentValues(constructorVals);
beanDefinition.setBeanClass(GenericDAOImpl.class);
beanDefinition.setAutowireCandidate(true);
beanDefinition.setLazyInit(true);
beanDefinition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE);
String simpleName = entityClass.getSimpleName();
String convertedName = "" + simpleName.substring(0, 1).toLowerCase() + simpleName.substring(1) + "Dao";
registry.registerBeanDefinition(convertedName, beanDefinition);
}
}
The method getPersistedClassList() reads persistence.xml and finds all of the JPA classes. The above method registers each of these instances with Spring so they can be accessed easily by the variable "entityNameDao". Because this class is a transactional class, it gets initialized as a Dynamic Java Proxy, and that's where my problems begin. JSF doesn't perceive the object by its interfaces anymore, but looks directly at the proxy, which does in fact show the above method definition as:
List getNQasList(String name, Object[] params);
This makes it much more difficult to access from JSF than an Object... params signature method. Is there any way I can get JSF to recognize these objects by their interface, or convince Spring to somehow not make dynamic proxies of them? Alternatively, how does one go about doing the following in EL, it gives me errors about the curly braces if I try:
new Object[] {...}
My spring config relating to persistence, including the transaction advice is included below for good measure.
<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="${JDBC_CONNECTION_STRING}?autoReconnect=true&useUnicode=true&connectionCollation=utf8_general_ci&characterSetResults=utf8"/>
<property name="username" value="${PARAM1}"/>
<property name="password" value="${PARAM2}"/>
<property name="validationQuery" value="select 1"/>
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<context:annotation-config/>
<!-- Enable aspectj based transactions -->
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager" />
<!-- the transactional advice (i.e. what 'happens'; see the <aop:advisor/> bean below) -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- the transactional semantics... -->
<tx:attributes>
<!-- all methods starting with 'get' are read-only -->
<tx:method name="get*" read-only="true"/>
<!-- other methods use the default transaction settings (see below) -->
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<!-- ensure that the above transactional advice runs for any execution
of an operation defined by the GenericDAOImpl class -->
<aop:config>
<aop:pointcut id="DaoOps" expression="execution(* daos.GenericDAOImpl.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="DaoOps"/>
</aop:config>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" >
<property name="showSql" value="true"/>
</bean>
</property>
</bean>