I have been struggling with this for a long time now. I have an IBM Websphere MQ, which uses EJB and MDB
The following is where the ejb mdb is configured.
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar-bnd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://websphere.ibm.com/xml/ns/javaee"
xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-ejb-jar-bnd_1_0.xsd" version="1.0">
<message-driven name="Queue1MDB">
<jca-adapter activation-spec-binding-name="jms/Queue1MQActivationSpec" destination-binding-name="jms/Queue1RequestQueue"/>
<resource-ref binding-name="jms/QueueConnectionFactory" name="jms/QueueConnectionFactory"/>
<message-destination-ref binding-name="jms/SuccessfulResponseQueue" name="jms/SuccessfulResponseQueue"/>
<message-destination-ref binding-name="jms/FailedResponseQueue" name="jms/FailedResponseQueue"/>
</message-driven>
<message-driven name="Queue2MDB">
<jca-adapter activation-spec-binding-name="jms/Queue2MQActivationSpec" destination-binding-name="jms/Queue2RequestQueue"/>
<resource-ref binding-name="jms/QueueConnectionFactory" name="jms/QueueConnectionFactory"/>
<message-destination-ref binding-name="jms/SuccessfulResponseQueue" name="jms/SuccessfulResponseQueue"/>
<message-destination-ref binding-name="jms/FailedResponseQueue" name="jms/FailedResponseQueue"/>
</message-driven>
<message-driven name="Queue3MDB">
<jca-adapter activation-spec-binding-name="jms/Queue3MQActivationSpec" destination-binding-name="jms/Queue3RequestQueue"/>
<resource-ref binding-name="jms/QueueConnectionFactory" name="jms/QueueConnectionFactory"/>
<message-destination-ref binding-name="jms/SuccessfulResponseQueue" name="jms/SuccessfulResponseQueue"/>
<message-destination-ref binding-name="jms/FailedResponseQueue" name="jms/FailedResponseQueue"/>
</message-driven>
<message-driven name="Queue4MDB">
<jca-adapter activation-spec-binding-name="jms/Queue4MQActivationSpec" destination-binding-name="jms/Queue4RequestQueue"/>
<resource-ref binding-name="jms/QueueConnectionFactory" name="jms/QueueConnectionFactory"/>
<message-destination-ref binding-name="jms/SuccessfulResponseQueue" name="jms/SuccessfulResponseQueue"/>
<message-destination-ref binding-name="jms/FailedResponseQueue" name="jms/FailedResponseQueue"/>
</message-driven>
</ejb-jar-bnd>
This is configured in ear, which is deployed in IBM WAS. The destination-binding-name will pick the corresponding queue details from the IBM WAS.
And later, my configuring the MDB in my java class like below, the listening is achieved on all the queues simultaneously and the messages are picked up:
#Resource(name = "jms/QueueContractConnectionFactory")
private ConnectionFactory connectionFactory;
#Resource(name = "jms/FailedResponseQueue")
private Queue errorQueue;
#Resource(name = "jms/SuccessfulResponseQueue")
private Queue responseQueue;
I now have to remove the ejb and modify the mdb configurations to make it deploy-able in tomcat.
The xml is something, which I literally have no idea on how to map it without the ejb parameters.
Can someone help or share a document on how to achieve this? I would like to have a example of IBM MQ to Spring JMS with Activation Spec.
Thanks in advance.
As has been commented, it's not simply a matter of replacing WAS with Tomcat, as they are not the same kind of container. So you can not directly deploy your WAS artifacts (the MDBs, notably) directly in to Tomcat. In order to get these in to Tomcat, they will have to be rewritten.
By being an MDB, the container manages for you: connecting to the JMS server, routing of messages from the queue/topic to your logic, multi-threaded message processing (handling more than one queued message at once) and, most notably, transaction management.
Now, message processing against JMS is pretty straightforward. You can make a connection to JMS readily. You can copy an example off the net and get that working. Running processing in the background is straightforward, there are examples of that as well. JMS 2.0 is easier to use than JMS 1.x. No reason not to port to that (unless MQ doesn't support JMS 2.0).
Running multiple instances of the logic, transactionally, is not so straightforward, but maybe that's not a keen aspect of your processing.
However, even if you were able to get all of that working, there's no guarantee at this juncture that your logic will work directly. We don't know if you logic calls other EJBs or leverages any of the other Java EE infrastructure. Were it to do so, them you have to port that aspect of your logic as well, not just the MDB connectivity.
So, this is a deeper problem. It's easy to say "just deploy it in Tomcat", but there could be details that derail that and need to be accounted for.
Another take is to convert the logic to Spring, as that can deploy in Tomcat readily. But that's not necessarily simpler than anything else -- all of the caveats remain.
Finally, "deploying in Tomcat" is almost a non-sequitur in this case because MDBs are not Web Apps, and Tomcat deploys Web Apps. You can create a shell of a Web App that does nothing but house your message driven logic. It's easy to do, I and many others have abused the Web App life cycles to our own nefarious ends for things like this.
So, in the end, I think you need more clarity as to what "deploy in Tomcat" really means, what the expectations are in the end, and whether your message logic relies on other Java EE infrastructure etc. Is the goal to run in Tomcat or to not run in WAS (in that case, as noted in the comments, there are other app servers you could possibly use that would be much easier to transition to).
Mike my other post that you linked to this question outlines the steps assuming you are good with setting up the springframework, MQ and server administration. But if you are struggling to get a start, here's some pointers.
Before you begin, you need to understand that this can be technically challenging. Sometimes, instead of changing what exists, breaking down what exists into multiple modules and implementing them from scratch makes more sense. Should you choose to change what exists, here's how to approach it:
Get the spring framework working in your application that you built in RAD. Did you do this successfully? Just inject any bean from the application context and see if you can get this to work on WAS. If you can do this successfully, it means you got a head start, the rest of it can be done. Let me know when you get to this - paste your application context or configuration here. I can tell you what to do next. Remember, you don't have to switch to tomcat right away - your aim should be to replace an MDB with a spring bean that can listen to messages - and this can run on WAS.
There is one thing you should be aware of with respect of Websphere MQ. The connection pooling with MQ classes for JMS is supported only through Websphere application server. When you migrate to Tomcat you may experience performance penalty and you may have to implement your self some amount of pooling. I think spring can help in this regards. I will quote it from IBM documentation
public void setUseConnectionPooling(boolean usePooling)
Deprecated. JMS does not use connection pooling anymore. Any
connection pooling should be done using the facilities provided by the
App Server. Set the use of ConnectionPooling in earlier versions of
the IBM MQ classes for JMS. This method is retained for compatibility
with older MQJMS applications, but, because this Connection Pooling
functionality has been removed from version 7, setting this property
will have no effect.
https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_9.0.0/com.ibm.mq.javadoc.doc/WMQJMSClasses/com/ibm/mq/jms/MQConnectionFactory.html#setUseConnectionPooling-boolean-
I think your best shot is to spring-ify(move to spring) your WAS application and then switch to Tomcat. Once you move to spring it should be a piece of cake to switch. It is supposed to be container independent. There are plenty of recipies online on how to migrate Java EE to spring applications. This excersise has been done for years(since spring exists:).
In the process you can also apply divide and conquere and end up with more then one app instead of monolith.
Related
I'm reading up on JMX for the first time, and trying to see if its a feasible solution to a problem we're having on production.
We have an architecture that is constantly hitting a remote web service (managed by a different team on their own servers) and requesting data from it (we also cache from this service, but its a sticky problem where caching isn't extremely effective).
We'd like the ability to dynamically turn logging on/off at one specific point in the code, right before we hit the web service, where we can see the exact URLs/queries we're sending to the service. If we just blindly set a logging level and logged all web service requests, we'd have astronomically-large log files.
JMX seems to be the solution, where we control the logging in this section with a managed bean, and then can set that bean's state (setLoggingEnabled(boolean), etc.) remotely via some manager (probably just basic HTML adaptor).
My questions are all deployment-related:
If I write the MBean interface and impl, as well as the agent (which register MBeans and the HTML adaptor with the platform MBean server), do I compile, package & deploy those inside my main web application (WAR), or do they have to compile to their own, say, JAR and sit on the JVM beside my application?
We have a Dev, QA, Demo and Prod envrionment; is it possible to have 1 single HTML adaptor pointing to an MBean server which has different MBeans registered to it, 1 for each environment? It would be nice to have one URL to go to where you can manage beans in different environments
If the answer to my first question above is that the MBean interface, impl and agent all deploy inside your application, then is it possible to have your JMX-enabled application deployed on one server (say, Demo), but to monitor it from another server?
Thanks in advance!
How you package the MBeans is in great part a matter of portability. Will these specific services have any realistic usefulness outside the scope of this webapp ? If not, I would simply declare your webapp "JMX Manageable" and build it in. Otherwise, componentize the MBeans, put them in a jar, put the jar in the WEB-INF/lib and initialize them using a startup servlet configured in your web.xml.
For the single HTML adaptor, yes it is possible. Think of it as having Dev, QA, Demo and Prod MBeanServers, and then one Master MBeanServer. Your HTML Adaptor should render the master. Then you can use the OpenDMK cascading service to register cascades of Dev, QA, Demo and Prod in the Master. Now you will see all 5 MBeanServer's beans in the HTML adaptor display.
Does that answer your third question ?
JMX is a technology used for remote management of your application and for a situation for example when you want to change a configuration without a restart is the most proper use.
But in your case, I don't see why you would need JMX. For example if you use Log4j for your logging you could configure a file watchdog and just change logging to the lowest possible level. I.e. to debug. This does not require a restart and IMHO that should have been your initial design in the first place i.e. work arround loggers and levels. Right now, it is not clear what you mean and what happens with setLoggingEnable.
In any case, the managed bean is supposed to be deployed with your application and if you are using Spring you are in luck since it offers a really nice integration with JMX and you could deploy your spring beans as managed beans.
Finally when you connect to your process you will see the managed beans running for that JVM. So I am not sure what exactly you mean with point 2.
Anyway I hope this helps a little
I'm currently developing a small EJB application running on IBM Websphere Application Server 7 (Java EE 5). The app mainly consists of one MDB listening for incoming MQ messages which are transformed and stored in a DB. Currently I'm using a lot of Singleton/Factories to share configurations, mappings, datasource lookups etc. But this actually leads to some very hard to test code. The solution might be using a (simple) DI framework like guice/spring to inject the different instances. The question is: Where to place the initialization/ setup code? Where is the main entry point of the application? How can I inject instances into the MDBs?
it might be worth looking at backing off from using Guice, and trying to work with the injection mechanisms already available with Java EE 5.
Regarding finding a suitable "startup point", unfortunately the EJB specification does not define a way where you can have a bean run at startup. However, the web profile of the EE spec does have one -- you can add a WAR to your application, and set a servlet listener component:
http://java.sun.com/javaee/5/docs/api/javax/servlet/ServletContextListener.html
You can set this to start whenever the application is loaded and started by the container (WebSphere). Watch out for classloader issues though.
Using Spring, you can do it via EJB3 interceptors, see http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/ejb.html#ejb-implementation-ejb3
Useful info on caveats are in the javadoc, make sure you read it: http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/ejb/interceptor/SpringBeanAutowiringInterceptor.html
I need some direction with JMX and Java EE.
I am aware (after few weeks of research) that the JMX specification is missing as far as deployment is concerned. There are few vendor specific implementations for what I am looking for but none are cross vendor. I would like to automate the deployment of MBeans and registration with the Server. I need the server to load and register my MBeand when the application is deployed and remove when the application is un-deployed.
I develop with:
NetBean 6.7.1, GlassFish 2.1, Java EE 5, EJB 3
More specific, I need a way to manage timer service runs. My application need to run different archiving agents and batch reporting. I was hoping the JMX will give me remote access to create and manage the timer services and enable the user to create his own schedule. If the JMX is auto registered on application deployment the user can immediately connect and manage the schedule.
On the other hand, how can an EJB connect/access an MBean?
Many thanks in advance.
Gadi.
I investigated JMX and EJB in Glassfish few years ago, so I don't remember all the details. But this might still help.
Glassfish-specific JMX. Glassfish has AMX and custom MBean can be deployed. AFAIK, such beans are meant to monitor the server itself, not to interact closely with a specific application. Such bean can be made persistent, and Glassfish will store their value somewhere across restart. Maybe have a look.
Registration and lookup. You can register MBean anytime from within an application using the MBeanPlatform, or MBeanServer. See this link, I don't remember exactly. You can also lookup other JMX bean and invoke operations on them. The names for the lookup are a bit crazy though. You can register the MBean when the app. starts from within a ServletContextListener.
Classloaders and deployment. The MBeans and the EJB instances are in distinct Classloader. I think you will need to place the .jar with the MBean implementation in the Glassfish deployment directory structure or add it the list of .jar in the classpath via the admin console. You can relatively easily manage to register a bean from within an EJB module, but a bean can not access a EJB easily, at least from my experience.
I managed to use plain JMX to expose statistics from my EJB application, and that worked relatively well. But I don't know if it's adequate to have something more interactive, as in your case where you want to have the EJB change their behavior depending the timer configured with JMX. I fear you will have troubles with this approach.
Hope it helps, despite the vagueness of what I remember.
It's simple: I have an MDB and an EJB that sends messages to a topic (or queue). JBoss complains that the topic is not bound to the JNDI context.
I want to have the topic/queue to be automatically created at best, or at least to have a standard way to define it, per application (say, in ejb-jar/META-INF)
this question and this blogpost show us how to do it in an application server specific way. This surely works, but:
I want to use the #MessageDriven annotation
I want the setting not to be global for the application server
I want the setting to be portable
It seems impossible to do this, with JavaEE 5 at least.
Right now I am using a web-server which does not contain EJB container. If my application needs EJB container, how could I add one?
Do you really mean into? If yes, then maybe have a look at OpenEJB (the EJB Container implementation for Apache Geronimo). But I can't say that it's widely used.
Actually, why not just replacing your servlet container with a full Java EE server if you need EJBs, I don't get it, something like JBoss AS or GlassFish.
OpenEJB and EasyBeans are open-source EJB containers that can be dropped into Tomcat or other servers / applications.
But, you should describing what you need this for... because if you need EJBs specifically, you're probably better off going with a full app server (JBoss, Glassfish, Weblogic, etc.). If you're just using it for persistence, you're probably better off using some other persistence technology (Hibernate, iBatis, etc.).
JBoss is an open source J2EE server. So if for some reason you can't just use it, you could take the EJB container and graft it into something else. Probably not a small job.
Too litte information on your architecture to give a decent answer.
Anyway chances are good you already apache as web server, you can simply connect using mod_jk to the embeddd tomcat in jboss.
This configuration will use the Apache JServ Protocol (AJP) for communication between Apache and Tomcat.
A description on which config files you have to fiddle about is here