Unable to perform JNDI lookup using IBM WebSphere Application Server Liberty - jndi

I am using IBM WebSphere Application Server Liberty to perform JNDI lookup.I am pretty sure about giving right about the location of resources in the project. However, when i run this I am getting a name not found error.
Here is the code performing the lookup:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
PrintWriter out = response.getWriter();
response.setContentType("text/html");
try {
FlightService flightService = (FlightService)new InitialContext().lookup("java:comp/Web1/FlightService!com.airline.FlightService");
}
catch(Exception ex){
ex.printStackTrace();
}
if(flightService !=null){
out.println(flightService.getAirplaneModel());
out.println(flightService.getFrom());
out.println(flightService.getTo());
}
}
Here is the server.xml:
<server description="new server">
<!-- Enable features -->
<featureManager>
<feature>webProfile-7.0</feature>
<feature>localConnector-1.0</feature>
</featureManager>
<!-- To access this server from a remote client add a host attribute to the following element, e.g. host="*" -->
<httpEndpoint httpPort="9090" httpsPort="9443" id="defaultHttpEndpoint"/>
<!-- Automatically expand WAR files and EAR files -->
<applicationManager autoExpand="true"/>
<applicationMonitor updateTrigger="mbean"/>
<webApplication id="Web1" location="Web1-0.0.1-SNAPSHOT.war" name="Web1"/>
</server>
I am not sure , If i have to set any configuration related properties. Any help would be appreciated.

Looking at the server xml. I don't see JNDI entry being defined.
Based on the code, it should be trying to access a JNDI entry from a servlet. In this case, where do you define you JNDI entry in the first place?
I think you need the following to define the JNDI entry in the server xml
https://www.ibm.com/support/knowledgecenter/en/SSEQTP_8.5.5/com.ibm.websphere.wlp.doc/ae/twlp_dep_jndi_refentry.html
Please give it a try

Related

IBM Content Navigator cannot connect to highly available Content Engine repository

We have an evirironment as follows:
CPE: 2 Servers
ICN: 2 servers
Application Server: WAS 8.5.5 Base
Both content Engine and Navigator are configured for high availability using Load Balancer. However, in case ICN 1 is connected to CPE1 and CPE1 is dwn, then Navigator is unable to connect to CPE2 even though load balancer of CPE is pointing to CPE2.
The logs are as follows:
javax.naming.NamingException: NMSV0610I: A NamingException is being thrown from a javax.naming.Context implementation. Details follow:
Context implementation: com.ibm.ws.naming.jndicos.CNContextImpl
Context method: lookupExt
Context name: HDOSYS0202Node01Cell/nodes/HDOSYS0202Node01/servers/server1
Target name: FileNet/Engine,10.39.128.66:2809/FileNet/Engine
Other data:
Exception stack trace: javax.naming.NamingException: Error during resolve [Root exception is org.omg.CORBA.TRANSIENT: initial and forwarded IOR inaccessible vmcid: IBM minor code: E07 completed: No]
at com.ibm.ws.naming.jndicos.CNContextImpl.doLookup(CNContextImpl.java:1867)
at com.ibm.ws.naming.jndicos.CNContextImpl.doLookup(CNContextImpl.java:1776)
at com.ibm.ws.naming.jndicos.CNContextImpl.lookupExt(CNContextImpl.java:1433)
at com.ibm.ws.naming.jndicos.CNContextImpl.lookup(CNContextImpl.java:615)
at com.ibm.ws.naming.util.WsnInitCtx.lookup(WsnInitCtx.java:165)
at com.ibm.ws.naming.util.WsnInitCtx.lookup(WsnInitCtx.java:179)
at org.apache.aries.jndi.DelegateContext.lookup(DelegateContext.java:161)
at javax.naming.InitialContext.lookup(InitialContext.java:436)
com.ibm.ws.ssl.channel.impl.SSLReadServiceContext$SSLReadCompletedCallback.complete(SSLReadServiceContext.java:1818)
at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:175)
at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)
at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)
at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:138)
at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:204)
at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:775)
at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:905)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1864)
Caused by: org.omg.CORBA.TRANSIENT: initial and forwarded IOR inaccessible vmcid: IBM minor code: E07 completed: No
Caused by: java.net.ConnectException: Connection refused: connect
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:412)
at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:271)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:258)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:376)
at java.net.Socket.connect(Socket.java:546)
at com.ibm.ws.orbimpl.transport.WSTCPTransportConnection.createSocket(WSTCPTransportConnection.java:370)
at com.ibm.CORBA.transport.TransportConnectionBase.connect(TransportConnectionBase.java:366)
at com.ibm.ws.orbimpl.transport.WSTransport.getConnection(WSTransport.java:437)
at com.ibm.CORBA.transport.TransportBase.getConnection(TransportBase.java:188)
at com.ibm.rmi.iiop.TransportManager.get(TransportManager.java:100)
at com.ibm.rmi.iiop.GIOPImpl.getConnection(GIOPImpl.java:134)
at com.ibm.rmi.iiop.GIOPImpl.createRequest(GIOPImpl.java:178)
at com.ibm.rmi.corba.ClientDelegate._createRequest(ClientDelegate.java:2010)
at com.ibm.rmi.corba.ClientDelegate.createRequest(ClientDelegate.java:1186)
at com.ibm.rmi.corba.ClientDelegate.createRequest(ClientDelegate.java:1272)
Content Platform Engine does not support session replication which would be required to failover. Once the connection is established, the client will bind to the specific endpoint so neither corbaloc nor a load balancing alias will help. If the nodes are not in a Cluster the peer will not be in the JNDI tree so do not know about each other. What you have is called a "stovepipe" configuration. You can load balance the front end, but each front end will talk to a specific backend, so not highly available. You could put the CE's behind a hardware load balancer (SNAT) but it would still lack fail over. CPE will run on JBOSS but ICN does not, so to be highly available you'll need to deploy to WebSphere ND or Weblogic.
Could you share the URI used to establish CPE connection?
When Content Platform Engine is made highly available through an application server cluster configuration the Content Platform Engine URI should have the following form (with no carriage returns):
corbaloc::node1_hostname:BOOTSTRAP_ADDRESS,:node2_hostname:BOOTSTRAP_ADDRESS/cell/clusters/your_websphere_cluster_name/FileNet/Engine
Example:
corbaloc::testnode1:9810,:testnode2:9810/cell/clusters/testwascluster/FileNet/Engine
This configuration requires the WebSphere cluster name in addition to the node names as part of the URI. The bootstrap port for a cluster configuration (by default, port 9810) is usually different from the bootstrap port on a non-cluster (standalone) configuration (by default, port 2809).
Only one URI is used regardless of SSL use. WebSphere EJB over SSL is automatically established if EJB security is enabled.
I found a link containing code to solve the issue in my case. The only problem is how to implement this code for Content Navigator
"This may help. I have recently written an EJB print app which is used by other apps at my company to generate printable documents. I am also using an access bean on the client to remotely call my EJB. The client is a 4 server cluster, and my EJB is a 2 server cluster. I have also experienced problems with the "connection refused" exception if I stop the application server(s) running my EJB when calling without restarting the client. Here is what I've done so far to resolve the issue.
Looking at the access bean, after you create an instance, when you call your remote method (whatever that may be and in my case is renderDocuments() which i will use in my example below) the access bean does the following:"
public DocumentRenderOutputContext renderDocuments
DocumentRequestList documentRequestList)
{
try
{
instantiateEJB();
return ejbRef().renderDocuments
documentRequestList);
}
catch (NamingException ne)
{
throw new DocumentRenderException(ne);
}
catch (CreateException ce)
{
throw new DocumentRenderException(ce);
}
catch (RemoteException re)
{
THE EXCEPTION THROWN WHEN THE APP SERVER IS
BROUGHT DOWN WITHOUT RESTARTING THE CLIENT
WILL BE CAUGHT HERE
}
}
If you bring down your EJB app server(s) without re-starting the client, the remote exception above will catch the "connect refused" exception.
So what i do inside the remote exception catch is the following:
try
{
//see below for methods
reset();
return retryRenderDocuments(documentRequestList);
}
catch (NamingException ne)
{
throw new DocumentRenderException(ne);
}
catch (CreateException ce)
{
throw new DocumentRenderException(ce);
}
catch (RemoteException remote)
{
throw new DocumentRenderException(re);
}
private void reset() throws NamingException
{
resetHomeCache();
resetEJBRef();
}
private DocumentRenderOutputContext retryRenderDocuments
DocumentRequestList documentRequestList)
throws
RemoteException,
NamingException,
CreateException,
DocumentRenderException
{
DocumentRenderOutputContext outputContext = null;
Properties properties = new Properties();
properties.put(
javax.naming.Context.PROVIDER_URL,
getInit_NameServiceURLName()); //im assuming youve
properties.put(
PROPS.JNDI_CACHE_OBJECT,
PROPS.JNDI_CACHE_OBJECT_CLEARED);
InitialContext initialContext = new InitialContext(properties);
Object object = initialContext.lookup(getInit_JNDIName());
ECommercePrintHome homeRef = (ECommercePrintHome) object;
ECommercePrint printEngine = homeRef.create();
outputContext = printEngine.renderDocuments(documentRequestList);
return outputContext;
}
Ref:- http://www.theserverside.com/discussions/thread.tss?thread_id=31495

Auto-delete queue not recreated after broker outage

I have a question regarding the use of spring-amqp through XML wiring and through creation of the various objects in java code.
Doing this via XML and via Java code is pretty simple and has been working well for me in most cases. However, after an outage of the broker (simulated by shutting down and restarting my broker) I get two different results.
When using XML wiring to create the spring-amqp objects, everything works fine. The connection is re-established, the queue is recreated and reception of messages resumes.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:ctx="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit-1.4.xsd">
<rabbit:connection-factory id="connectionFactory"
addresses="192.168.1.10:5672"
username="guest"
password="guest"
/>
<rabbit:admin connection-factory="connectionFactory"/>
<rabbit:queue name="testQueue" id="testQueue" auto-declare="true" auto-delete="true" exclusive="false"/>
<rabbit:fanout-exchange name="testExchange" id="testExchange" >
<rabbit:bindings>
<rabbit:binding queue="testQueue" />
</rabbit:bindings>
</rabbit:fanout-exchange>
<bean class="TestConsumer" id="testConsumer" />
<rabbit:listener-container connection-factory="connectionFactory">
<rabbit:listener queues="testQueue" ref="testConsumer" method="inbound" />
</rabbit:listener-container>
</beans>
However, when using Java to create the spring-amqp objects, I run into issues. The connection is re-established, but then I immediately hit exceptions reporting that the queue is not found. The admin does not attempt to re-create the queue and after a few exceptions, the listener container is stopped.
public static void main(String[] args) {
CachingConnectionFactory cf = new CachingConnectionFactory("192.168.1.10", 5672);
RabbitAdmin admin = new RabbitAdmin(cf);
FanoutExchange testExchange = new FanoutExchange("testExchange", true, false);
admin.declareExchange(testExchange);
Queue testQueue = new Queue("testQueue", true, false, true);
admin.declareQueue(testQueue);
admin.declareBinding(BindingBuilder.bind(testQueue).to(testExchange));
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(cf);
container.setRabbitAdmin(admin);
container.setQueues(testQueue);
container.setMessageListener(new MessageListenerAdapter() {
public void handleMessage(String text) {
System.out.println("Received : " + text);
}
});
container.afterPropertiesSet();
container.start();
try {
Thread.sleep(600000L);
} catch(Exception e) {
e.printStackTrace();
}
container.stop();
container.destroy();
System.out.println("Exiting");
}
This is the exception that I see (three or four times) after the connection is re-established and before the listener container exits:
Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=404, reply-text=NOT_FOUND - no queue 'testQueue' in vhost '/', class-id=50, method-id=10)
at com.rabbitmq.client.impl.ChannelN.asyncShutdown(ChannelN.java:478)
at com.rabbitmq.client.impl.ChannelN.processAsync(ChannelN.java:315)
at com.rabbitmq.client.impl.AMQChannel.handleCompleteInboundCommand(AMQChannel.java:144)
at com.rabbitmq.client.impl.AMQChannel.handleFrame(AMQChannel.java:91)
at com.rabbitmq.client.impl.AMQConnection$MainLoop.run(AMQConnection.java:552)
I would assume that the XML wiring case and the pure Java case should work equivalently, but clearly this is not the case. I am not sure if
there is something that I am missing in my Java case, or whether this is just not supported.
I can of course detect the failure of the listener container and use the admin to re-declare the queues, but seeing as this is not necessary with the XML wired example, I am wondering what I might be missing.
Using org.springframework.amqp.spring-rabbit 1.4.5.RELEASE
The admin needs a Spring Application Context to automatically declare the elements (queues etc).
It registers a connection listener with the connection factory and, when a new connection is established, it looks for all the queues etc in the application context and registers them.
Since you are using "pure" java (no Spring Application Context), this mechanism can't work.
You can either use Spring Java Configuration to replace your XML (using #Bean definitions), or you will have to register your own class with the connection factory to perform the declarations.
See the admin source code for how he registers the listener and the initialize method for how he does the declarations.
You would simply need to do your
FanoutExchange testExchange = new FanoutExchange("testExchange", true, false);
admin.declareExchange(testExchange);
Queue testQueue = new Queue("testQueue", true, false, true);
admin.declareQueue(testQueue);
within the listener.
Spring AMQP only reconnects queues and exchanges registered using the #Bean annotation.
Queues and Exchanges registered directly by the RabbitAdmin will not be reconnected automatically. You need to set resetAllManualDeclarations() to true before declaring them.
Example:
RabbitAdmin admin = new RabbitAdmin(cf);
// enable auto reconnect when connection fails
admin.resetAllManualDeclarations(true);
FanoutExchange testExchange = new FanoutExchange("testExchange", true, false);
admin.declareExchange(testExchange);
Queue testQueue = new Queue("testQueue", true, false, true);
admin.declareQueue(testQueue);
Note: you need spring-rabbit 2.4+.

How to keep sitemap.xml out of webapp's deploy folder?

I'm using glassfish server 3.1.2 and jsf 2.1. Based on sitemaps.org standarts, sitemap file of entire web site should be in root folder. I will have multiple sitemaps and sitemap will change dynamically after i create new entries. I have read there, i want to use alternate docroot. But i can't create alternate docroot for root directory. I should find a solution as like as alternate docroot.
You could create a simple servlet to perform the job.
#WebServlet("/sitemap.xml")
public class SitemapServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/xml");
// You might want to add finer grained browser cache related headers.
InputStream input = new FileInputStream("/some/path/to/sitemap.xml");
OutputStream output = response.getOutputStream();
// Now just write input to output using your favorite way.
// ...
}
}

How to get error details on Azure Web site

I'm new to Azure. Does anybody know how get detailed error message on website deployed to Azure web?
I added SimpleMembership to website and now Registration and Login (Post) are showing
Sorry, an error occurred while processing your request.
I'm connecting to DB on my home computer (no problem with connection).
LogFiles folder on azure ftp server has some files but I don't see how to use this information. I wish I can get YellowScreen on azure...
You have two options:
First, you can turn off custom errors in your web config. This is the quick-and-dirty approach but it will at least get you the information you are looking for. Just be sure to turn custom errors back on when you are done. NOTE: This method will display your stacktrace to the entire world.
<configuration>
<system.web>
<customErrors mode="Off" />
</system.web>
</configuration>
Second, you can remote desktop into your deployed machine, go to IIS Manager, and Browse to your site. Once you are there, reproduce the error and you will get the yellow screen of death you are looking for. For this to work, you will have to Enable Detailed Errors
Create a table in db where you will store you error logs, I'm using EF and table called Logs.
Create a class:
public class MyAppExceptionFilter : IExceptionFilter
{
private MyApp.Models.ApplicationDbContext db = new Models.ApplicationDbContext();
public void OnException(ExceptionContext context)
{
Exception ex = context.Exception;
Log log = new Log();
log.DateTime = DateTime.Now;
log.LogText = "Exception happened, text:" + ex.Message;
try
{
log.LogText +="User details:"+context.HttpContext.User.Identity.Name;
}
catch
{
log.LogText += "User details:none";
}
db.Logs.Add(log);
db.SaveChanges();
}
}
In FilterConfig.cs in App_Start folder add:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
*filters.Add(new MyAppExceptionFilter());*
}
You can also get the same diagnostic by piping console logs to the cloud shell.
Login to azure. Bring up the console...azure CLI.
az webapp log config --name <app-name> --resource-group
myResourceGroup --application-logging filesystem --level information
To start streaming...
az webapp log tail --name <app-name> --resource-group myResourceGroup
Now just refresh the browser for the error.
Ctrl-C back at the CLI will stop streaming.
I picked this up here:Tutorial: Build an ASP.NET Core and Azure SQL Database app in Azure App Service

The JNDI lookup for the JTA UserTransaction is not available to MBean threads in Websphere Application Server 7

I'm trying to invoke business logic via JMX (using 'standard' MBeans) in a web application in Websphere Application Server 7 with JTA switched on and would like to know why this business logic can't see the JTA UserTransaction when invoked from an MBean (because it can when invoked via the web app's UI).
When hibernate attempts to look up the UserTransaction via 'java:comp/UserTransaction', the following exception is thrown:
org.hibernate.TransactionException: Could not find UserTransaction in JNDI [java:comp/UserTransaction]
at org.hibernate.transaction.JTATransactionFactory.getUserTransaction(JTATransactionFactory.java:173)
at org.hibernate.transaction.JTATransactionFactory.createTransaction(JTATransactionFactory.java:149)
...
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:48)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at java.lang.reflect.Method.invoke(Method.java:600)
at com.sun.jmx.mbeanserver.StandardMBeanIntrospector.invokeM2(StandardMBeanIntrospector.java:105)
at com.sun.jmx.mbeanserver.StandardMBeanIntrospector.invokeM2(StandardMBeanIntrospector.java:39)
at com.sun.jmx.mbeanserver.MBeanIntrospector.invokeM(MBeanIntrospector.java:220)
at com.sun.jmx.mbeanserver.PerInterface.getAttribute(PerInterface.java:77)
at com.sun.jmx.mbeanserver.MBeanSupport.getAttribute(MBeanSupport.java:228)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getAttribute(DefaultMBeanServerInterceptor.java:678)
at com.sun.jmx.mbeanserver.JmxMBeanServer.getAttribute(JmxMBeanServer.java:650)
at com.ibm.ws.management.AdminServiceImpl.getAttribute(AdminServiceImpl.java:853)
at com.ibm.ws.management.remote.AdminServiceForwarder.getAttribute(AdminServiceForwarder.java:270)
at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1415)
at javax.management.remote.rmi.RMIConnectionImpl.access$200(RMIConnectionImpl.java:84)
at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1276)
at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1371)
at javax.management.remote.rmi.RMIConnectionImpl.getAttribute(RMIConnectionImpl.java:612)
at javax.management.remote.rmi._RMIConnectionImpl_Tie.getAttribute(_RMIConnectionImpl_Tie.java:578)
at javax.management.remote.rmi._RMIConnectionImpl_Tie._invoke(_RMIConnectionImpl_Tie.java:98)
at com.ibm.CORBA.iiop.ServerDelegate.dispatchInvokeHandler(ServerDelegate.java:622)
at com.ibm.CORBA.iiop.ServerDelegate.dispatch(ServerDelegate.java:475)
at com.ibm.rmi.iiop.ORB.process(ORB.java:513)
at com.ibm.CORBA.iiop.ORB.process(ORB.java:1574)
at com.ibm.rmi.iiop.Connection.respondTo(Connection.java:2841)
at com.ibm.rmi.iiop.Connection.doWork(Connection.java:2714)
at com.ibm.rmi.iiop.WorkUnitImpl.doWork(WorkUnitImpl.java:63)
at com.ibm.ejs.oa.pool.PooledThread.run(ThreadPool.java:118)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1563)
Caused by: 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/UserTransaction" not found in context "java:".]
at com.ibm.ws.naming.java.javaURLContextImpl.throwConfigurationExceptionWithDefaultJavaNS(javaURLContextImpl.java:428)
at com.ibm.ws.naming.java.javaURLContextImpl.lookup(javaURLContextImpl.java:399)
at com.ibm.ws.naming.java.javaURLContextRoot.lookup(javaURLContextRoot.java:214)
at com.ibm.ws.naming.java.javaURLContextRoot.lookup(javaURLContextRoot.java:154)
at javax.naming.InitialContext.lookup(InitialContext.java:455)
at org.hibernate.transaction.JTATransactionFactory.getUserTransaction(JTATransactionFactory.java:163)
... 53 more
Caused by: javax.naming.NameNotFoundException: Name "comp/UserTransaction" not found in context "java:".
at com.ibm.ws.naming.ipbase.NameSpace.lookupInternal(NameSpace.java:1178)
at com.ibm.ws.naming.ipbase.NameSpace.lookup(NameSpace.java:1095)
at com.ibm.ws.naming.urlbase.UrlContextImpl.lookup(UrlContextImpl.java:1233)
at com.ibm.ws.naming.java.javaURLContextImpl.lookup(javaURLContextImpl.java:395)
... 57 more
This problem looks like it's more than just a hibernate configuration problem - hibernate is looking for the UserTransaction at what IBM say is the correct UserTransaction JNDI location ('java:comp/UserTransaction') - see this infocenter document.
Furthermore, I can reproduce the problem in a simple web app that has an MBean that does the lookup:
public class JTALookup extends NotificationBroadcasterSupport implements JTALookupMBean {
Log log = LogFactory.getLog(JTALookup.class);
/**
* {#inheritDoc}
* #see JTALookupMBean#lookupUserTransaction()
*/
#Override
public void lookupUserTransaction() {
try {
log.info("Attempting 'java:comp/UserTransaction' lookup");
Object usrTxn = new InitialContext().lookup("java:comp/UserTransaction");
log.info("Successfully looked up 'java:comp/UserTransaction' [" + usrTxn + "]." );
} catch (NamingException e) {
log.info("'java:comp/UserTransaction' lookup failed");
throw new RuntimeException("Failed to lookup JTA user transaction", e);
}
}
and a context listener that invokes the lookup during start up and then registers the MBean:
public void contextInitialized(ServletContextEvent sce) {
log.info("Initialising context");
JTALookup jtaLookup = new JTALookup();
jtaLookup.lookupUserTransaction(); // This succeeds
log.info("Looked up JTA transaction");
MBeanServer mbServer = AdminServiceFactory.getMBeanFactory().getMBeanServer();
log.info("Got MBeanServer");
try {
mbServer.registerMBean(jtaLookup, new ObjectName("webJTALookupStub:type=JTALookup"));
log.info("Registered dummy MBean");
} catch (Exception e) {
log.info("Failed to register dummy MBean");
throw new RuntimeException("Failed to register dummy MBean", e);
}
}
The lookup on 'java:comp/UserTransaction' succeeds during context initialisation, but fails (with a similar stack trace to that above) when invoked via jmx, like so:
public static void main(String[] args) {
JMXServiceURL url = new JMXServiceURL(
"service:jmx:rmi://" + "your.server.name.co.uk" + ":" + "2809" + "/jndi/JMXConnector"
);
Hashtable<String, Object> env = new Hashtable<String, Object>();
env.put(Context.PROVIDER_URL, "corbaloc:iiop:gbbldd66.sys.chp.co.uk:2809/WsnAdminNameService");
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.ibm.websphere.naming.WsnInitialContextFactory");
// Establish the JMX connection.
JMXConnector jmxc = JMXConnectorFactory.connect(url, env);
// Get the MBean server connection instance.
MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
ObjectName mbeanName = new ObjectName("webJTALookupStub:type=JTALookup");
JTALookupMBean mBean = JMX.newMBeanProxy(mbsc, mbeanName, JTALookupMBean.class, true);
mBean.lookupUserTransaction(); // This fails
The 'Extending the WebSphere Application Server administrative system with custom MBeans' document in IBM's infocenter suggests that standard MBeans that have been tested in applications outside WAS should just work.
IBM do state that the UserTransaction lookup is not available to:
CMT Enterprise beans `http://publib.boulder.ibm.com/infocenter/wasinfo/v7r0/index.jsp?topic=/com.ibm.websphere.base.doc/info/aes/ae/cjta_glotran.html
Async Beans created by EJBs `http://publib.boulder.ibm.com/infocenter/wasinfo/v7r0/topic/com.ibm.websphere.javadoc.doc/web/apidocs/com/ibm/websphere/asynchbeans/package-summary.html?resultof=%22%61%73%79%6e%63%68%62%65%61%6e%22%20%22%75%73%65%72%74%72%61%6e%73%61%63%74%69%6f%6e%22%20%22%75%73%65%72%74%72%61%6e%73%61%63%74%22%20
Apologies for the non-functional links - I'm a new user and so can only post two working links.
Do plain old MBeans fall into either of these categories from IBM's point of view?
Interestingly, the UserTransaction appears to be available on JNDI lookup 'jta/UserTransaction' and using that as a fallback option seems to work - but:
WAS 7 is Java EE 5 compliant and as of J2EE 1.3 'java:comp/UserTransaction' is the specified JNDI location for the UserTransaction - see the J2EE 1.3 spec `http://java.sun.com/j2ee/j2ee-1_3-fr-spec.pdf
Using a lookup from an earlier version of the EE specification seems like a potential source of other bugs, and might only be addressing part of my problem - the fact that WAS thinks my MBean's thread is not associated with an application could cause other issues.
One further point to note is that the UserTransaction is also hidden to threads for work submitted from the MBean to the application's work manager (an IBM work manager) - which could be because it's treating that work like it's an async bean submitted by an EJB?
Possible explanations that have occurred to me are:
There might issues with how IBM set up MBean threads in WAS 7 and associate then with the applications that register the MBeans.
There might be some additional configuration options for the MBean registration that would let WAS know that it should associate the MBean with the application that registered it. I have tried several alternative approaches but saw the same exception each time:
Registering the MBeans with UserCollaborators and xml descriptors
Registering them with ModelMBeanInfo
Registering them with the AdminService rather than the MBeanServer
Enhancing the ObjectName for the MBean with additional properties (Application, J2EEApplication) at registration
There might be some additional configuration options for the jmx client request that would let WAS know that it should associate the MBean invokation with the appropriate application. This forum post suggests it's possible to configure a client application to have access to the initial context: `http://www.ibm.com/developerworks/forums/thread.jspa?messageID=14021995
I might just not be supposed to try to use MBeans this way - despite IBM's statements that I should be able to. It's been suggested that EJBs are the appropriate solution for this kind of requirement.
Any light that can be shed on this problem would be greatly appreciated.
MBeans run on a separate thread than your application, so they don't have access to the application naming context in JNDI, and therefore they don't have access to your UserTransaction.
I think your final potential explanation is likely most accurate:
I might just not be supposed to try to use MBeans this way - despite IBM's statements that I should be able to. It's been suggested that EJBs are the appropriate solution for this kind of requirement.
MBeans may not be appropriate for this type of work. Rather, using EJBs or a web service might be more appropriate.
You have to set TransactionManagementType.BEAN on transactionManagement like so:
#TransactionManagement(TransactionManagementType.BEAN)

Resources