I have a very simple quartz job that is trying to fetch printer record from the DB,
I am getting this error:
org.springframework.dao.InvalidDataAccessApiUsageException: no transaction is in progress;
nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress
javax.persistence.TransactionRequiredException: no transaction is in progress
Here is the code of the application:
@SpringBootApplication
@ComponentScan(basePackages="com.xerox.printhub")
@EntityScan("com.xerox.printhub*")
@EnableTransactionManagement
@EnableJpaRepositories(basePackages ={"com.xerox.printhub.repository"})
@Import({ SchedulerConfig.class })
public class PrinterVerificationApp extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(PrinterVerificationApp.class, args);
}
}
Here is the code of the Quartz job:
package com.xerox.printhub.quartz.jobs;
import javax.transaction.Transactional;
import com.google.gson.Gson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
public class PrinterVerificationJob implements Job{
@Transactional
public void execute(JobExecutionContext jobExecutionContext) {
private static final Logger logger = LoggerFactory.getLogger(PrinterVerificationJob.class);
@Autowired
Gson g;
@Autowired
PrinterInfoRepository printerRepo;
logger.debug("Trying to fetch an available printer...");
PrinterInfo printerInfo=null;
try {
printerInfo = printerRepo.findOneAndLock(PrinterStatus.NEW.name());
} catch (Exception e1) {
logger.debug("Error!",e1);
}
}
Code of the Dao object (PrinterInfoRepository )
@Transactional
public interface PrinterInfoRepository extends CrudRepository<PrinterInfo ,String> {
@Lock(LockModeType.PESSIMISTIC_WRITE)//locking it to prevent other workers to access it.
@Query("SELECT p FROM PrinterInfo p where p.statusCd = :status")
List<PrinterInfo> findOneAndLock(@Param("status")String status);
}
In my application, this Rest controller is working just fine with PrinterInfoRepository
package com.xerox.printhub.controllers;
import java.text.ParseException;
import java.util.ArrayList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class PrinterAPIController {
@Autowired
PrinterInfoRepository printerRepo;
@PostMapping(value = "/SubmitPrinterData")
public PrinterInfo submitPrinterData(
@RequestBody PrinterInfoJason printerInfo) {
//THIS METHOD IS WORKING FINE.
}
I tried both annotations:
import javax.transaction.Transactional;
import org.springframework.transaction.annotation.Transactional;
And I tried annotating the PrinterVerificationJob with @service
I also added EnableTransactionManagement
But nothing helps.
Any idea what I'm doing wrong?
UPDATE
I found the culprit at PrinterInfoRepository-> findOneAndLock()
when I don't use LockModeType.PESSIMISTIC_WRITE, method works just find...
when I try to access using use LockModeType.PESSIMISTIC_WRITE, I get the InvalidDataAccessApiUsageException
What am I doing wrong? I need to lock the record from other workers.
@Lock(LockModeType.PESSIMISTIC_WRITE)//locking it to prevent other workers to access it.
@Query("SELECT p FROM PrinterInfo p where p.statusCd = :status")
PrinterInfo findOneAndLock(@Param("status")String status);
full stack trace:
org.springframework.dao.InvalidDataAccessApiUsageException: no transaction is in progress; nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:402)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:255)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:527)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:153)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:139)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy124.findOneAndLock(Unknown Source)
at com.xerox.printhub.quartz.jobs.PrinterVerificationJob.getPrinter(PrinterVerificationJob.java:158)
at com.xerox.printhub.quartz.jobs.PrinterVerificationJob.execute(PrinterVerificationJob.java:189)
at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
at org.quartz.simpl.SimpleThrexeroxool$WorkerThread.run(SimpleThrexeroxool.java:573)
Caused by: javax.persistence.TransactionRequiredException: no transaction is in progress
at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1556)
at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1529)
at org.hibernate.query.Query.getResultList(Query.java:168)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:402)
at com.sun.proxy.$Proxy141.getResultList(Unknown Source)
at org.springframework.data.jpa.repository.query.JpaQueryExecution$CollectionExecution.doExecute(JpaQueryExecution.java:129)
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:91)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:136)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:125)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:605)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.lambda$invoke$3(RepositoryFactorySupport.java:595)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:595)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:59)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
... 13 more
From you log it is obvious - Why ? Because if the Transaction was active you would have had a Proxy invocation in between like when you invoke a method on the repository. Visible from the same log.
at com.xerox.printhub.quartz.jobs.PrinterVerificationJob.getPrinter(PrinterVerificationJob.java:158) at com.xerox.printhub.quartz.jobs.PrinterVerificationJob.execute(PrinterVerificationJob.java:189) at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
That your PrinterVerificationJob is not instrumented. Which means that your @Transactional annotation is not working. You need your Bean to be managed by spring for the @Transactional annotation to take effect. What you can do si to isolate the contents of your execute method into a service and inject it into the JOB. Then you can annotate this Class or the method of this class with @Transctional. This bean will get instrumented and the @Transactional annotation will take effect.
@Service
PrinterVerificationService {
@Transactional
public void verifyPrinter(yuor parameters here)
}
public class PrinterVerificationJob implements Job{
@Autowire
PrinterVerificationService verificationService;
public void execute(JobExecutionContext jobExecutionContext) {
service.verifyPrinter(your prameters here)
}
If you would like to preserve your application logic as is. What you can do is to use the @PlatformTransactionManager that is already initialized in spring and @Autowire it to your job. With this transaction manager you can manualy start the transaction. With it you can initialize TransactionTemplate and do:
TransactionTemplate txTemplate = new TransactionTemplate(platformTransactionManagerHere);
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
txTemplate.execute(new TransactionCallback<Object>() {
public Object doInTransaction(TransactionStatus status) {
// do stuff
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With