How to start a transaction in a spring-installed bean?

I have a Spring 3.2.8 application in which I have a specific case where I want to start a transaction inside a context listener.

I know and understand that the listener is not a Spring bean, so I'm not quite sure how to mark my method as @Transactional. I tried labeling the bean as @Configurable, but that doesn't seem like a trick; I assume the b / c application server creates this bean before the Spring context is loaded.

I checked the status of the transaction with TransactionAspectSupport.currentTransactionStatus(), but I get a throw NoTransactionExceptionthat occurs when there is no managed open transaction.

Is there anything inside Spring that will allow me to mark this method as part of a transaction?

@Configurable
public class PatchEngineContextListener implements ServletContextListener{

    // SLF4J logger
    private static final Logger logger = LoggerFactory.getLogger(PatchEngineContextListener.class);


    // HELPERS
    private ApplicationContext appContext;
    @Autowired private PatchService patchService;
    @Autowired private PatchEngine patchEngine;

    @Override
    @Transactional
    public void contextInitialized(ServletContextEvent sce) {

        // get the app context
        appContext = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
        appContext.getAutowireCapableBeanFactory().autowireBean(this);

        logger.info( TransactionAspectSupport.currentTransactionStatus().toString() );

        try {
            setPatchEngineUser();
            patchEngine.execute();
            clearPatchEngineUser();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

Stacktrace error:

org.springframework.transaction.NoTransactionException: No transaction aspect-managed TransactionStatus in scope
    at org.springframework.transaction.interceptor.TransactionAspectSupport.currentTransactionStatus(TransactionAspectSupport.java:110)
    at com.ia.system.patch.engine.PatchEngineContextListener.contextInitialized(PatchEngineContextListener.java:92)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4939)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5434)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
    at java.util.concurrent.FutureTask.run(FutureTask.java:262)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:724)

web.xml:

<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- Patch Engine launched after spring finishes setting up its context -->
<listener>
    <listener-class>com.ia.system.patch.engine.PatchEngineContextListener</listener-class>
</listener> 

applicationContext.xml:

<context:spring-configured/>
+4

Source: https://habr.com/ru/post/1532187/


All Articles