Transaction readonly=true not throwing exception when commiting transaction - spring

We have Spring MVC based web-app having service method attributed with #Transactional(readonly=true).
I was expecting spring to throw exception because we have method which is committing data in mysql db.
Can anyone help me out why transaction attribute (Readonly) related exception is not thrown ?
below mentioned is code...
#Service
#Transactional
public class AppService {
... #Autowired Dao
public int createApplication(AppVO vo){
....
}
}

Taken straight from the Javadoc of readOnly of #Transactional is the following:
This just serves as a hint for the actual transaction subsystem; it
will not necessarily cause failure of write access attempts. A
transaction manager which cannot interpret the read-only hint will not
throw an exception when asked for a read-only transaction.
So it is not unexecpected that an exception is not thrown.

Related

SpringBatch #Async method not working in persistent layer (JPAItemWriter)

SpringBoot Application with SpringBatch and JPA, without #Async all working fine but with #Async added in the REST API the job is completed but JPAItemWriter is not persisting the objects in the DB. looks like Transactional problem as am getting this exception.
Transaction Manager [org.sringframework.batch.support.transaction.ResourcelessTransactionManager] does not support transaction suspension.
I tried with different approaches like changing Propagation.Requires_New (Required, Supports) but nothing works, tried searching all the forums but no luck.
#Service
public class SampleWriter extends JpaItemWriter<TestEntity> {
#Autowired
EntityManager entityManager;
#Transactional(readOnly=false, propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
#Override
public void write(List<TestEntity> entities) {
this.doWrite(entityManager, entities);
}
}
It seems that you are configuring and using Spring Batch in a wrong way.
Firstly, it is using the default BatchConfigurer which the TransactionManager is ResourcelessTransactionManager that is mainly use for testing or acts as a "no-op" TransactionManager for the batch job that does not require any transaction which is definitely not your case now.
Secondly, Spring Batch will internally take care of managing the transaction boundary for processing each chunk , you do not need to extend JpaItemWriter and control the transaction behaviour using #Transactional by yourself.
So , read this section for how to configure Spring Batch , especially the part related to BatchConfigurer
On the other hand if you are using Spring-boot , it should already configure a JpaBatchConfigurer for you.

ServiceLocatorFactoryBean #transactional

can someone please explain it to me, is it possible to forward existing opened transaction to a service that has been created with ServiceLocatorFactoryBean in Spring, and how does the factory manages transactions.
I have issues with a transaction rollback in the service that was created by the factory, in a way that if I throw checked exception in it, the transaction will be committed regardless the fact that the exception occurred.
My service is annotated with #Transactional(propagation = Propagation.REQUIRED, rollbackFor = MyException.class), so it should use the existing transaction and it should rollback in case of the checked exception.
I assume that somehow, a new transaction is opened during creation of a new service, so although one transaction gets rollbacked, the other one gets committed independently.

Spring #Transactional timeout not timing out

I have set transaction timeout in my application as #Transactional(propagation=Propagation.REQUIRED,timeout=30)
ActiveMQXAConnectionFactory and Oracle XA Datasource are two resources of my Distributed transaction. after reading a message from queue my transaction begins and while processing the application is taking more than 30 seconds and still transaction is not timed out. Only when committing the transaction its throwing timeout exception. I wanted immediately after 30 seconds the transaction should time out and throw the exception and make that thread available to consume another message from queue. Is this possible?
Without seeing your configuration it will be hard to say. If you are just adding an #Transactional, it is not going to do anything. You going to need both an EntityManager and a TransactionManager, then you need to turn on annotation based transaction management, and Spring needs to be controlling your datasource if I recall correctly.
Another, probably unnecessary side note, #Transactional will only work on public methods. Spring will proxy your method in order to manage the transaction and Spring can only proxy public methods. Also, it will only be able to work on calls from another class to that method, if you are calling that method from another method inside the same class, Spring cannot proxy either, thus no transaction management. Spring is sneakily deceptive here.
#Service
public class A{
#Autowired
Datasource datasource;
#Transactional
public void save(){
datasource.doStuff();
}
public void callSave(){
save();
}
}
#Service
public class B{
#Autowired
A a;
public void callSave(){
a.save();
}
}
Here, if a.save() is called from a.callSave(), no proxy will occur, thus you will have no transaction management. But in the exact same application, if you call b.callSave(), you will have transaction management, since Spring can then proxy the method call to a.save().
Are you using Spring Boot or vanilla Spring? We can probably give you more of a direction if you divulge that.
Hopefully that helped a bit!

Using PersistenceContext in a Quartz Job

We're using Spring 3.1, JPA (via Hibernate) and Quartz. Typically we interact with the DB via #PersistenceContext annotation on Service beans, and either SpringMVC controllers, or GraniteDS-managed service invocation.
I'm working on writing a Quartz job that needs to interact with the database. I've tried everything I can find to get this working. I tried passing in a Spring-managed component (annotated with #PersistenceContext and #Transactional) via the jobMap, the call to entityManager.persist(o) executes, but nothing happens in the database. I also tried similar to this answer, creating a factory class to call autowireBean() on the job object. I set up the job class like so:
public class CreateAlertJob implements Job {
#PersistenceContext
EntityManager entityManager;
#Override
#Transactional
public void execute(JobExecutionContext context) throws JobExecutionException {
SomeEntity entity = new SomeEntity();
entityManager.persist(entity);
}
}
Same result, the method executes but the database is unaltered. I found this blog post which references a GitHub project. There he is using JpaInterceptor to establish a Hibernate session, but this uses the DAO pattern and I'd like to stick with using #PersistenceContext.
Clearly there is something about the Quartz thread that is preventing this from working properly? I'm about out of ideas and considering making a web service call to a SpringMVC controller just to get this working.
Since your CreateAlertJob is not created by Spring, #Transactional in it doesn't take effect.
You have the following options:
Delegate actual work to Spring bean and put #Transactional there
Use programmatic transaction management
Use AspectJ-based AOP implementation instead of Spring default implementation (but it would be overkill for such a simple problem)

spring Transaction exception handling

Basically with spring Transaction management .We can annotate the service layer class with #Transactional.
Also i have annotated my DAO layer class with #repository to make checked exception to unchecked exception.
Now when a runtimeexception is encoutered by the service layer class it will rollback.
My question how do we go about the exception handling. I will have to put some error message to UI .So i need to capture the exception .
How do i go about it.

Resources