Register JmsListener after EntityManager

Hello,

I’m setting up an ActiveMQ Listener in a CUBA application. The listener retrieves messages from a queue, applies bussiness logic and then persists in the database the result.

When the application is started and a message is queued, it is processed properly and the database is updated accordingly.

When the application is starting and there are messages queued, however, the listener fails because it fails to EntityManager is null. Here is a stacktrace of the error:

StackTrace
org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is javax.persistence.PersistenceException: java.lang.NullPointerException
    at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:431) ~[spring-orm-4.3.18.RELEASE.jar:4.3.18.RELEASE]
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:378) ~[spring-tx-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:474) ~[spring-tx-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:289) ~[spring-tx-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) ~[spring-tx-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) [spring-aop-5.1.1.RELEASE.jar:5.1.1.RELEASE]
    at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88) [spring-aop-5.1.1.RELEASE.jar:5.1.1.RELEASE]
    at com.haulmont.cuba.core.sys.ServiceInterceptor.aroundInvoke(ServiceInterceptor.java:117) ~[cuba-core-6.10.7.jar:6.10.7]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_144]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_144]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_144]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_144]
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644) [spring-aop-5.1.1.RELEASE.jar:5.1.1.RELEASE]
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633) [spring-aop-5.1.1.RELEASE.jar:5.1.1.RELEASE]
    at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70) [spring-aop-5.1.1.RELEASE.jar:5.1.1.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175) [spring-aop-5.1.1.RELEASE.jar:5.1.1.RELEASE]
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93) [spring-aop-5.1.1.RELEASE.jar:5.1.1.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) [spring-aop-5.1.1.RELEASE.jar:5.1.1.RELEASE]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) [spring-aop-5.1.1.RELEASE.jar:5.1.1.RELEASE]
    at com.sun.proxy.$Proxy361.registrarMensajePasarelaVirtual(Unknown Source) [na:na]
    at com.projectname.activemq.listener.ActiveMqListener.procesaMensajePasarelaVirtual(ActiveMqListener.java:83) [app-core-0.1-SNAPSHOT.jar:na]
    at com.projectname.activemq.listener.ActiveMqListener.listenPasarelaVirtualNodo1(ActiveMqListener.java:53) [app-core-0.1-SNAPSHOT.jar:na]
    at com.projectname.activemq.listener.ActiveMqListener$$FastClassBySpringCGLIB$$68bd4cf9.invoke(<generated>) [app-core-0.1-SNAPSHOT.jar:na]
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) [spring-core-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746) [spring-aop-5.1.1.RELEASE.jar:5.1.1.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) [spring-aop-5.1.1.RELEASE.jar:5.1.1.RELEASE]
    at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88) [spring-aop-5.1.1.RELEASE.jar:5.1.1.RELEASE]
    at com.haulmont.cuba.security.sys.AuthenticationInterceptor.aroundInvoke(AuthenticationInterceptor.java:41) [cuba-core-6.10.7.jar:6.10.7]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_144]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_144]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_144]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_144]
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644) [spring-aop-5.1.1.RELEASE.jar:5.1.1.RELEASE]
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633) [spring-aop-5.1.1.RELEASE.jar:5.1.1.RELEASE]
    at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70) [spring-aop-5.1.1.RELEASE.jar:5.1.1.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) [spring-aop-5.1.1.RELEASE.jar:5.1.1.RELEASE]
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93) [spring-aop-5.1.1.RELEASE.jar:5.1.1.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) [spring-aop-5.1.1.RELEASE.jar:5.1.1.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) [spring-aop-5.1.1.RELEASE.jar:5.1.1.RELEASE]
    at com.projectname.activemq.listener.ActiveMqListener$$EnhancerBySpringCGLIB$$a58367ea.listenPasarelaVirtualNodo1(<generated>) [app-core-0.1-SNAPSHOT.jar:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_144]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_144]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_144]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_144]
    at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:170) [spring-messaging-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:120) [spring-messaging-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:114) [spring-jms-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:77) [spring-jms-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:736) [spring-jms-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:696) [spring-jms-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:674) [spring-jms-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.jms.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:645) [spring-jms-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.jms.listener.SimpleMessageListenerContainer.processMessage(SimpleMessageListenerContainer.java:322) [spring-jms-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.jms.listener.SimpleMessageListenerContainer.lambda$createListenerConsumer$2(SimpleMessageListenerContainer.java:299) [spring-jms-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.apache.activemq.ActiveMQMessageConsumer.dispatch(ActiveMQMessageConsumer.java:1404) ~[activemq-client-5.15.9.jar:5.15.9]
    at org.apache.activemq.ActiveMQSessionExecutor.dispatch(ActiveMQSessionExecutor.java:131) ~[activemq-client-5.15.9.jar:5.15.9]
    at org.apache.activemq.ActiveMQSessionExecutor.iterate(ActiveMQSessionExecutor.java:202) ~[activemq-client-5.15.9.jar:5.15.9]
    at org.apache.activemq.thread.PooledTaskRunner.runTask(PooledTaskRunner.java:133) ~[activemq-client-5.15.9.jar:5.15.9]
    at org.apache.activemq.thread.PooledTaskRunner$1.run(PooledTaskRunner.java:48) ~[activemq-client-5.15.9.jar:5.15.9]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_144]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_144]
    at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_144]
Caused by: javax.persistence.PersistenceException: java.lang.NullPointerException
    at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:815) ~[eclipselink-2.6.2.cuba24.jar:2.6.2.cuba24]
    at org.eclipse.persistence.internal.jpa.EntityManagerFactoryDelegate.getAbstractSession(EntityManagerFactoryDelegate.java:205) ~[eclipselink-2.6.2.cuba24.jar:2.6.2.cuba24]
    at org.eclipse.persistence.internal.jpa.EntityManagerFactoryDelegate.createEntityManagerImpl(EntityManagerFactoryDelegate.java:305) ~[eclipselink-2.6.2.cuba24.jar:2.6.2.cuba24]
    at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFactoryImpl.java:337) ~[eclipselink-2.6.2.cuba24.jar:2.6.2.cuba24]
    at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:303) ~[eclipselink-2.6.2.cuba24.jar:2.6.2.cuba24]
    at org.springframework.orm.jpa.JpaTransactionManager.createEntityManagerForTransaction(JpaTransactionManager.java:449) ~[spring-orm-4.3.18.RELEASE.jar:4.3.18.RELEASE]
    at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:369) ~[spring-orm-4.3.18.RELEASE.jar:4.3.18.RELEASE]
    ... 61 common frames omitted
Caused by: java.lang.NullPointerException: null
    at com.haulmont.cuba.core.sys.persistence.EclipseLinkSessionEventListener.preLogin(EclipseLinkSessionEventListener.java:66) ~[cuba-core-6.10.7.jar:6.10.7]
    at org.eclipse.persistence.sessions.SessionEventManager.preLogin(SessionEventManager.java:620) ~[eclipselink-2.6.2.cuba24.jar:2.6.2.cuba24]
    at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.preConnectDatasource(DatabaseSessionImpl.java:797) ~[eclipselink-2.6.2.cuba24.jar:2.6.2.cuba24]
    at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.login(DatabaseSessionImpl.java:773) ~[eclipselink-2.6.2.cuba24.jar:2.6.2.cuba24]
    at org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider.login(EntityManagerFactoryProvider.java:267) ~[eclipselink-2.6.2.cuba24.jar:2.6.2.cuba24]
    at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:731) ~[eclipselink-2.6.2.cuba24.jar:2.6.2.cuba24]
    ... 67 common frames omitted

So far I’ve tried to use the @DependsOn annotation to make the ActiveMQ component which registers listeners dependent on cuba_Persistence with no success. I suspect that listeners, which are registered with the annotation @JmsListener(destination = ${activemq.queuename}", containerFactory = "myFactory"), are outside the bean creation lifecycle.

What approach would you use to make sure persistence has finished starting before the listener is registered?

Thanks for your time.

Hi,

CUBA app has a specific lifecycle, so I would suggest registering the listener programmatically in AppContextStartedEvent. Probably you can do it using Spring’s JmsListenerEndpointRegistrar.

1 Like

Thanks for your reply, Konstantin.

EntityManager was available after AppContextStartedEvent. The only thing left was to programmatically start the JmsListeners after setting auto-start to false with factory.setAutoStartup(false).

@Configuration
@EnableJms
public class ActiveMqConfig implements ApplicationListener<AppContextStartedEvent> {
// ...

    @Override
    public void onApplicationEvent(AppContextStartedEvent event) {
        logger.info("## onApplicationEvent - INICIO");

        jmsListenerEndpointRegistry.getListenerContainer(ActiveMqListener.ID_LISTENER_NODO_1).start();
        jmsListenerEndpointRegistry.getListenerContainer(ActiveMqListener.ID_LISTENER_NODO_2).start();

        logger.info("## onApplicationEvent - FIN");
    }

// ...

Regards,
Bernat.

1 Like