No JTA UserTransaction available - java

Background I'm using spring, jboss, java. Below is my configuration for spring JtaTransactionManager.
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="defaultTimeout" value="150" />
</bean>
ISSUE:
I'm facing below issue not while running application server (JBOSS), because I believe Jboss is binding to default transaction manager. However while I'm running integration test cases loading of springapplicationcontext fails with below error.
BeanInstantiationException: Failed to instantiate [org.springframework.context.support.ClassPathXmlApplicationContext]: Constructor threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transac
tionManager' defined in class path resource [spring-container.xml]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: No JTA UserTransaction available - specify either 'userTransaction' or 'userTransactionName' or 'tra
nsactionManager' or 'transactionManagerName'
Is there a way we can ask spring to use default transaction, if application server is not provided?
By not making any changes in this file, since my usage is only for test cases not recommended to change in actual code.

Related

Unable to register MBean for ws-outbound-gateway

The integration flow uses the following:
<int:chain input-channel="input" id="inChain">
<!-- some header-enrichers -->
<int-ws:outbound-gateway id="outGateway"/> <!-- other properties are omitted -->
</int:chain>
In the process of deploying to Tomcat, i get an error:
Caused by: org.springframework.jmx.export.UnableToRegisterMBeanException:
Unable to register MBean [inChain$child.outGateway.handler] with key 'inChain$child.outGateway.handler';
nested exception is org.springframework.jmx.export.MBeanExportException:
Could not create ModelMBean for managed resource [inChain$child.outGateway.handler] with key 'inChain$child.outGateway.handler';
nested exception is java.lang.IllegalArgumentException:
MetadataMBeanInfoAssembler does not support JDK dynamic proxies - export the target beans directly or use CGLIB proxies instead.
Is there a simple solution in spring integration or is it necessary to follow the advice from the error text (make a custom MBeanExporter and so on)?
May be better to think not making that gateway as a proxy at all? How that happen though? Nothing confirms in your question that there is a story about proxying... on the other hand you can exclude that bean from JMX exporting. Or you can provide an other way to gather MBean info for that bean. See how you can customize MBeanExporter.
Or you just can add an IntegrationMBeanExporter: https://docs.spring.io/spring-integration/docs/current/reference/html/jmx.html#jmx-mbean-exporter
Thanks to Artem Bilan for search direction: found AOP advice in code:
<bean id="interceptor" class="..."/>
<aop:config>
<aop:pointcut id="all" expression="execution(*org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleRequestMessage(..))"/>
<aop:advisor pointcut-ref="all" advice-ref="interceptor" order="1"/>
</aop:config>
The best solution for now is to disable JMX.

Spring JMS Message Listener fails to find JNDI lookup

The application uses Spring JMS Listener to connect to JMS Queues and it is deployed in WAS 8.5.x.
Using spring application context xml, org.springframework.jms.listener.DefaultMessageListenerContainer bean is initialized with ConnectionFactory, Destination as JndiObjectFactoryBean.
Inside MessageListener class onMessage() method, the code is trying to look JNDI reference using InitialContext, code snippet is below,
InitialContext ic = new InitialContext();
String name = (String) ic.lookup("jndiName");
Application throws below exception while processing a message.
Exception : javax.naming.ConfigurationException: A JNDI operation on
a "java:" name cannot be completed because the server runtime is not
able to associate the operation's thread with any J2EE application
component. This condition can occur when the JNDI client using the
"java:" name is not executed on the thread of a server application
request. Make sure that a J2EE application does not execute JNDI
operations on "java:" names within static code blocks or in threads
created by that J2EE application. Such code does not necessarily run
on the thread of a server application request and therefore is not
supported by JNDI operations on "java:" names. [Root exception is
javax.naming.NameNotFoundException: Name comp/env/cache not found in
context "java:".]
My understanding is, the Message Listener threads are created by the application during initialization under J2EE Web Container. The code is trying to access JNDI resource defined in WebSphere server, but not able to get the handle to Initial Context.
Note: resource-ref tag with this JNDI entry is included in web.xml.
<resource-ref id="configCache">
<description>Resource reference to Configuration Cache</description>
<res-ref-name>cache/config</res-ref-name>
<res-type>com.ibm.websphere.cache.DistributedMap</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
Any help would be appreciated.
I was able to fix this problem.
Here is the solution,
In web.xml I defined the Resource reference of type com.ibm.websphere.cache.DistributedMap. I created the JNDI (of type Object Cache) in WebSphere Admin console and map it to this resource during deployment.
<resource-ref id="sampleCacheName">
<description>Resource reference to Cache</description>
<res-ref-name>cache/sampleCache</res-ref-name>
<res-type>com.ibm.websphere.cache.DistributedMap</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
In my spring context xml, I defined the JMS Listener bean which takes Task Executor object from default WebSphere work manager,
<bean id="jmsContainerSampleEvent"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="myConnectionFactory" />
<property name="destination" ref="myQueue" />
<property name="messageListener" ref="myEventListener" />
<property name ="concurrentConsumers" value ="5"/>
<property name ="maxConcurrentConsumers" value ="20"/>
<property name="taskExecutor" ref="workManagerTaskExecutor" />
</bean>
<bean id="workManagerTaskExecutor"
class="org.springframework.scheduling.commonj.WorkManagerTaskExecutor"
p:workManagerName="wm/default" />

MetadataMBeanInfoAssembler does not support JDK dynamic proxies

Recently I added JMX support to my Spring web application.
This works fine for beans with #Component, however, for some services there seems to be a problem when adding #ManagedResource
I have a spring service annotated with #Service method.
I'm trying to add JMX to that service using #ManagedResource but it seems like spring is having troubles registering the beans:
org.springframework.beans.factory.BeanCreationException:
Caused by: org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'mbeanExporter': Invocation of init method
failed; nested exception is
org.springframework.jmx.export.UnableToRegisterMBeanException: Unable
to register MBean [...] with key 'appAnalysisServiceImpl'; nested
exception is org.springframework.jmx.export.MBeanExportException:
Could not create ModelMBean for managed resource [
l#6142152] with key 'myservice'; nested exception is java.lang.IllegalArgumentException: MetadataMBeanInfoAssembler does
not support JDK dynamic proxies - export the target beans directly or
use CGLIB proxies instead
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1486)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:524)
From the exception message it seems like spring requires a special exporter for this kind of class.
How do i export the bean directly without writing my own exporter ?
If your service uses #Transactional then Spring won't be able to create a ModelBean since the service is proxied.

JNDI initial context for JtaTransactionManager using Spring and Glassfish

I want to use JTA Transaction Manager for my application. I'm using Spring and Glassfish. I want to use JNDI lookup to get the JtaTransactionManager instance. My Spring bean configuration for JtaTransactionManager is set up as follows:
<tx:annotation-driven transaction-manager="jtaTransactionManager"/>
<bean id="jtaTransactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManagerName" value="java:comp/TransactionManager"/>
<property name="userTransactionName" value="java:comp/UserTransaction"/>
</bean>
But when I run the program, it reported errors:
Caused by: org.springframework.transaction.TransactionSystemException: JTA UserTransaction is not available at JNDI location [java:comp/UserTransaction]; nested exception is javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial
which is associated with Non-initialized JNDI context. So I added a resource file jndi.properties which adds the missing initial context reported above:
java.naming.factory.initial=???
But the question is: What should I put in the above JNDI initial context field to be able get Glassfish transaction manager via JNDI lookup? I searched a number of sources but didn't find this piece of information. The official document only says:
To access a UserTransaction instance, you can either look it up using
the java:comp/UserTransaction JNDI name or inject it using the
#Resource annotation.
So how should I set up the JNDI initial factory for JTA Transaction Manager in jndi.properties file so that both TransactionManager and UserTransaction can be injected into my jtaTransactionManager bean by JNDI lookup? Thanks.

Spring session scoped bean in EJB 2 Stateless Session Bean

I'm adding some features to an old EJB 2 application using Spring. The Spring application context used by the EJBs is a parent context of the web application as described here.
I'm trying to use a session scoped bean from within the EJBs. The bean in question is initialized from the EJB application context.
However, I get this error when trying to access the bean:
Caused by: java.lang.IllegalStateException: No Scope registered for scope 'session'
From what I've read, this is because the parentContextKey is not an instance of WebApplicationContext. Does anyone have an ideas of how I could get this working?
You may try to register the scope manually:
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="session">
<bean class="org.springframework.web.context.request.SessionScope"/>
</entry>
</map>
</property>
</bean>
I guess it should work, because SessionScope itself depends only on the thread-bound request context exposed by the RequestContextListener and doesn't depend on the application context.
You can only use session-scoped Spring beans from within a Spring WebApplicationContext. There's no getting around this - no WebApplicationContext, no session-scoping.
Perhaps if you explained what you're trying to achieve, we could help further. Are you perhaps conflating stateful session EJBs with servlet sessions? They're not the same thing.

Categories