Remote XA JMS Connection - java

Is it possible to provide and lookup connection factories that are transactional on a JBoss AS 7? The standard "RemoteConnectionFactory" doesn't seem to be transactional (XA) and I don't know how to make it XA or how to define some sort of XARemoteConnectionFactory that I can use from a remote client.
I tried adding the <xa>true</xa> element (which works in a hornetq configuration but is illegal in a jboss config file) and tried to create a <pooled-connection-factory> like the "java:/jmsXA" (but I wasn't able to look it up in the context even with a correct name for exporting).

Related

websphere wasjdbcDataSource to XADataSource

i already setup oracle xadatasource in websphere, and i want get datasource by using spring context lookup jndi , exception happen when i start my app : WasjdbcDataSource incompatible with javax.sql.XADataSource.
how can i solve this?
In a Java EE application server, such as WebSphere Application Server, even though you configure the XA-capable javax.sql.XADataSource, the application (and Spring) should always expect to use it as javax.sql.DataSource. Look in the Spring configuration if there is a way to indicate the expected type of javax.sql.DataSource rather than javax.sql.XADataSource. The XADataSource API is intended only for the application server's own internal use in order to accomplish two-phase commit. The user always interacts with it as javax.sql.DataSource, and gains the ability to enlist multiple resources in a single global transaction.

Websphere MQ JMS - Configuration Options

I am currently successfully using an MQConnectionFactory to connect and post to a Websphere MQ queue using JMS.
However I'm getting a requirement from a client that I must use mqclient.ini instead.
So my question is, for a 'standard' JMS setup, should I be using:
Straight up MQConnectionFactory instance
A JMS configuration file
An mqclient.ini file
? What would one use one over the other? Does one take precedence over another?
The mqclient.ini and JMSconfig files are used setting attributes like what client side exits to use, TCP level overrides etc. They are basically used for configuring the client libraries/jars. They are not meant for application configuration for example what queue manager or queue to use. This sort of info, connection factory or destination info, is typically pulled from a JNDI so that the configuration can be modified without affecting application.

WebSphere MQ connection pooling with Tomcat

Tomcat has a built-in JDBC connection pooling, but unfortunately no built-in JMS connection pooling.
We are migrating a legacy Tomcat web application from WebSphere MQ version 6 to 7.
Unfortunately, connection pooling has been removed in WebSphere MQ 7 as described here: http://www-01.ibm.com/support/docview.wss?uid=swg21665128
Now we are afraid that we will run into troubles if we just use the following code for configuring MQ in Tomcat:
<Resource name="jms/XXXQCF" auth="Container"
type="com.ibm.mq.jms.MQQueueConnectionFactory" factory="com.ibm.mq.jms.MQQueueConnectionFactoryFactory"
description="JMS Queue Connection Factory"
HOST="xxx.com" PORT="1429" CHAN="XXX" TRAN="1"
QMGR="XXX" />
The reason for our concerns is that this will not use a pooled JMS provider when using MQ 7. For details, see also http://activemq.apache.org/jmstemplate-gotchas.html
Alternative solutions we see are:
1) Use of Atomikos
Atomikos has a com.atomikos.jms.AtomikosConnectionFactoryBean that can be used instead of MQQueueConnectionFactory
But using an XA transaction manager is a huge overhead when we don't need XA
2) Use Spring's CachingConnectionFactory
looks like a good solution, but unfortunately our legacy application does not use Spring.
So we assume that using CachingConnectionFactory would mean quite some effort.
3) Use Apache Commons Pool
looks promising too, but implementing it correctly for JMS will require some good JMS knowledge
Our questions:
is there a JMS provider that can be used to wrap MQQueueConnectionFactory and that will pool connections, sessions, producers and consumers?
did anyone succeed in implementing one of the alternative solutions we outlined above?
As proposed by Umapathy in option 3, we now opted for the approach using Spring's CachingConnectionFactory, and it works well even for a non-Spring application. All you need to do is add the Spring Jars to the classpath, and wrap the MQQueueConnectionFactory with a CachingConnectionFactory.
We chose to create our own Tomcat QueueConnectionFactoryFactory that enables us to leave the original application code completely untouched, you just need to replace the original MQ connection factory from the Tomcat configuration file (shown above in the question) with the following XML definition:
<Resource name="jms/XXXQCF" auth="Container"
type="org.springframework.jms.connection.CachingConnectionFactory"
factory="at.rsf4j.core.utilities.RSFCachingMQQueueConnectionFactoryFactory"
description="JMS Queue Connection Factory"
HOST="xxx.com" PORT="1429" CHAN="XXX" TRAN="1"
QMGR="XXX" />
Here is the (simplified) code (without error checking) for the RSFCachingMQQueueConnectionFactoryFactory:
public class RSFCachingMQQueueConnectionFactoryFactory implements ObjectFactory{
public Object getObjectInstance (Object obj, Name name, Context nameCtx, Hashtable<?,?> environment)
throws NamingException {
Reference ref = (Reference) obj;
String beanClassName = ref.getClassName();
Class<?> beanClass = Class.forName(beanClassName);
if (CachingConnectionFactory.class.isAssignableFrom(beanClass)){
MQQueueConnectionFactoryFactory cff = new MQQueueConnectionFactoryFactory();
Reference mqReference = new Reference(
MQQueueConnectionFactory.class.getName());
Enumeration<RefAddr> allAddrs = ref.getAll();
while (allAddrs.hasMoreElements()){
mqReference.add(allAddrs.nextElement());
}
MQQueueConnectionFactory cf = (MQQueueConnectionFactory)cff.getObjectInstance(mqReference, name, nameCtx, environment);
CachingConnectionFactory ccf = (CachingConnectionFactory)beanClass.newInstance();
ccf.setTargetConnectionFactory(cf);
return ccf;
}
}
I think you already know the answer.
option 1: Go with a Java EE application server. This has inbuilt JMS pools.
option 2: If this is a simple application that does a single job (like putting on a queue with fire and forget type), you can connect to the JMS provider (qmgr) and create the producer or consumer in the servlet_init method. This means the legacy code needs an update. You also need to take care of the reconnect when something breaks as JMS reconnect properties doesn't kick off a reconnection (as far as my experience goes).
option 3: I have gone with Spring's CachingConnectionFactory when the application happens to be more than a little complex than one in option 2. I have applications that use JMSTemplate and some doesn't.

Custom resource in JNDI on different application servers

Preface:
Most of J2EE applications are using container managed datasources through JNDI. This is fine as it gives one place for configuring these connections.
The problem arises when we want to use ORM framework (like hibernate) or something that have to know the default schema (mostly for Oracle, may be others too), which can be different from the username that is used to connect to the DB.
I want to put the default schema name somewhere close to the datasource definition. One of the options would be to put it in JNDI. I will then manually read of from there before construction the EntityManager (well actually using Spring).
As I found out there is a simple way to specify custom resource (in this situation it will be String with default schema name) in Apache Tomcat like this (correct me if I'm wrong):
<Environment name="schemaNames/EmployeeDB"
type="java.lang.String"
value="empl"
description="Schema name of Employees Database for HR Applications"/>
Anyway, considering this can be done in Apache Tomcat, how should I configure the same custom JNDI resource (of String type) within other application servers:
JBoss 4/5
WebSphere 6/7
WebLogic 9/10
If you know about other servers that would be great too.
Also, as an alternative I don't want to put the schema name in system properties or environment variables.
Thank you very much !
Update:
Found some way of achieving it on JBoss. I didn't test it tho.
http://forums.java.net/jive/thread.jspa?messageID=316228
Found information for WebLogic, but they talk about doing it programmaticly and not with configuration:
http://weblogic-wonders.com/weblogic/2010/06/12/binding-objects-in-weblogic-servers-jndi-tree/
http://forums.oracle.com/forums/thread.jspa?messageID=4397353
For WebSphere you can actually set the default schema in your defined DataSource. It is a custom property called currentSchema. (ie, in V7 it is Resources > JDBC > Data sources > your data source name > Custom properties > currentSchema.
Otherwise you can use a Name Space Binding and define it there: (ie, in V7 it is Environment > Naming > Name Space Bindings. You can use JNDI to look this up if you don't want to programmatically set it in WebSphere.
Can't speak to JBoss and WebLogic as I haven't worked with them.
If you are using Hibernate, this is the property to add in persistence unit :
<property name="hibernate.default_schema" value="myschema" />
That is the prefix that JPA will insert for table names.
If you need something 'closer' to the AS Datasources definitions, you may inject some DB-specific SQL at DB connection time; for instance Oracle,
ALTER SESSION SET CURRENT_SCHEMA =
On JBoss, you may add this in the datasource definition :
<new-connection-sql>
ALTER SESSION SET CURRENT_SCHEMA=myschema
</new-connection-sql>
Also editable in JBoss 7 Admin.
On Weblogic, you may inject this in the Connection Pools.
On Websphere, this should be similar.
On JBoss, you can use a special MBean(org.jboss.naming.JNDIBindingServiceMgr) and a service.xml to configure JNDI-entries, and then map these entries into your webapps. There is a lengthy explication for this rather non-trivial process here:
http://usna86-techbits.blogspot.com/2011/01/jboss-jndi-and-javacompenv.html
I'm still looking for a a way to place an entire properties-file/resourcebundle into jndi, as this manual mapping gets very tedious when you have a lot of properties that you want to put into jndi and make available for your webapps.
This same problem has been bothering be for quite a while for WebLogic, in particular 10.3.5 (11g).
I spent most of a day looking around and all I found was this: http://code.google.com/p/weblogic-jndi-startup/. It works just fine. It is a little restrictive: it requires the object you want to add to JNDI to have a constructor with a single String parameter.
For what I needed, weblogic-jndi-startup didn't work, so I built on Roger's code and came up with this: https://bitbucket.org/phillip_green_idmworks/weblogic-jndi-custom-resource-configuration/. I have a write up for it at http://coder-in-training.blogspot.com/2012/03/weblogic-jndi-custom-resource.html

Programaticly create datasource for JBoss 4.2.x

Would it be possible to programmaticly create a data source in jboss and still have a valid jndi entry for the entity manager to use?
Creating the data source is where I am lost, I hope I can use a MBean that runs on stat-up to handle this.
This would not be my preferred method, but the application I am working on has a global configuration file hosted on another server I am suppose to use for configuration.
update: In this instance I need to create a data source programticly or change the jdbc url of an exsiting datasource. I don't know the DB server url until runtime.
Rather than poking around in the guts of JBoss in order to do this, I suggest using a 3rd-party connection pool utility, such as Apache Commons DBCP. There are instructions on how to programmatically register a DBCP datasource on JNDI here.
The first two lines of the sample code should be unnecessary, just create the default InitialContext and then rebind the datasource reference into it as described.
Here's a post that describes how to create a jboss service archive (SAR) that you can put in your EAR that will deploy a data source when the EAR is deployed, and remove it when the EAR in undeployed.

Categories