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.
Related
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.
I'm trying to get a Marklogic ContentSource object loaded from Tomcat's context.xml using JNDI and Spring.
I'm using Tomcat 8.5, and Spring 2.5 (unfortunately)
I have added the following to context.xml in Tomcat
<Resource name="MLContentSource" auth="Container" type="com.marklogic.xcc.ContentSource"
factory="com.marklogic.xcc.jndi.ContentSourceBeanFactory"
url="xcc://username:password#mymarklogic-server/DatabaseName"/>
And the following in my applicationContext.xml
<bean id="contentSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/MLContentSource"/>
</bean>
I have another bean declared in my applicationContext.xml that relies on the ContentSource bean. Its expecting a property to be set that is of type com.marklogic.xcc.ContentSource
<bean id="marklogicRepository" class="org.example.repository.ingestion.MarkLogicRepositoryImpl">
<property name="contentSource" ref="contentSource" />
</bean>
The issue is that the contentSource bean is of type JndiObjectFactoryBean and not com.marklogic.xcc.ContentSource. Is there something I'm missing to get a proper ContentSource from the JndiObjectFactoryBean?
It turns out the above code actually worked, my IDE was complaining about types but Spring will automatically cast the object stored inside JndiObjectFactoryBean to the target type at runtime.
Maybe try XQJ?
https://github.com/cfoster/xqj-pool-example/blob/master/src/main/java/simple/WithJNDI.java
http://xqj.net/
The XQuery API for Java
A standard Java interface to XML DataSources which support XQuery 1.0.
The XQJ API is to XML Databases as the JDBC API is to Relational Databases.
Is a light-weight design and is very easy to pick up.
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" />
Is there any way to enable or disable a java bean definition in application context?
<bean id="enBean" classs="com.en.bean.BeanName">
<property name="prop1"/>
</bean>
Or, is there any way to load the bean conditionally defined in application context?
There is a new feature #Profile in spring 3.1 that would do the job
From here
Spring 3.1 introduces the concept of environment profiles. A common
use case is the setting up of beans that are different between
development, QA and production environments. A typical example is
going against a standalone DataSource in development versus looking up
the DataSource from JNDI in production. Another example is a beans
profile for profiling that can easily be turned on or off. You can add
a profile attribute on a beans element in XML or add #Profile
annotation in code. Note that a Spring bean can be assigned to
multiple profiles.
<beans profile="dev">
...
</beans>
#Profile("dev")
public class Bean {
...
}
These profiles can be activated through the spring.profiles.active
property which may be specified through an environment variable, a JVM
system property, a Servlet in web.xml or JNDI. These
profiles can also be activated through code using
Environment.setActiveProfiles(String ...). To make bean profiles work,
nested beans elements are now allowed in the Spring XML, although
constrained only at the end of the file. Note that it's recommended to
keep your bean topology as close as possible between environments, so
your application gets properly tested across environments. You also
use the Environment.containsProperty() method to search for properties
across the different property sources. This property resolution also
works for ${placeholder} variables in XML bean definitions.
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.