I have been asked to investigate some of our MDBs and where applicable move logic to an EJB. My question is does it matter if all the logic is in the OnMessage method or should this call an EJB method. The current logic does not need to be called directly so there is no need to make it accessible via an EJB. Would the MDB calling the EJB have any benefits?
The primary benefit of moving your logic to an EJB is that this will give you additional control over transaction boundaries.
As MDBs are inherently transactional, failures can result in a rollback followed by the message being re-delivered. Sometimes this is exactly the behaviour you want, but not often.
If you configure the service method on your EJB so that it starts a new transaction (REQUIRES_NEW) then any errors will result in a rollback of the EJB's transaction, but not that of the MDB.
The onMessage method can then take whatever action is required to recover (or not) within it's still intact transaction.
There is a difference between MDB and and EJB bean.
MDB is basically used for asynchronous processing where some system puts a message on the Queue and then Application server picks up an instance of MDB from the pool and process that message.
In case of EJB, its a synchronous call where client has to wait for the Application Server to respond.
So if you want to move your login into MDBs then check if the Asynhronous work which that MDB was doing is needed or not at all.
And instead of moving logic to EJB and calling that EJB , you can create an internal service class which will have the business logic and use this service from both the MDB and EJB implementation method.
So whichever way client wants it (asynchronous/synchronous), you can serve the same business logic.
An MDB can contain references to another EJB, JMS connection resources and any other datasource or database connection resources.
Other than that it should not hold any state (like a stateless bean not holding client state). MDBs are not accessed directly by clients, and no interface gets exposed, mdbs listen for messages asynchronously from clients.
So, check if the MDB instances retain any data or conversational state for a specific client.
Generally container should be able to assign a message to any one of the mdbs and also pool the instances, such that streams of messages from multiple clients can be processed concurrently. So separating concerns, as for any other class will have its benefit here as well, MDB should do what it is intended to do, move the business logic related to message handling to another EJB instance (if the contianer services are required).
The value of separation of concerns is simplifying development and
maintenance of computer programs. When concerns are well-separated,
individual sections can be reused, as well as developed and updated
independently. Of special value is the ability to later improve or
modify one section of code without having to know the details of other
sections, and without having to make corresponding changes to those
sections.
see wiki Separation of concerns. Separate class need be an ejb if u require the container services like transaction.
Related
Looking for an architectural pattern to solve the following problem.
In my architecture, I have a Stateless EventDispatcher EJB that implements:
public void dispatchEvent(MyEvent ev)
This method is called by a variety of other EJBs in their business methods. The purpose of my EventDispatcher is to hide the complexity of how events are dispatched (be it JMS or other mechanism).
For now let's assume my bean is using JMS. So it simply looks at the event passed it, and builds JMS messages and dispatches them to the right topic. It can produce several JMS messages and they are only sent if the surrounding transaction ends up being committed successfully (XA transaction).
Problem: I may be looking at transactions where I send thousands of individual messages. Some messages might become invalid because of other things that happened in a transaction (object Updated and then later Deleted). So I need a good deal of logic to "scrub" messages based on a context, and make a final decision on if it is one big JMS batch message or multiple small ones.
Solutions: What I would like to is use some sort of "TransactionalContext" object and use it in my Stateless EJB to "Buffer" all the events. Then I need a callback of some sort to tell me the transaction is about to commit. This is something similar to how we use EntityManager, i can make changes to entities, and it holds onto changes and is shared between stateless EJBs. At "flush" time (transaction complete) it does its logic to figure out what SQL to execute. I need a TransactionContext available to my stateless bean that has a unique session per transaction, and, has a callback as the transaction is about to complete.
What would you do?
Note that I am NOT in a valid CDI context, some of these transactions are starting because of #Schedule timers. Other transactions begin because of JMS MDBs.
I believe the thing I am looking for is the TransactionSynchronizationRegistry.
http://docs.oracle.com/javaee/5/api/javax/transaction/TransactionSynchronizationRegistry.html#putResource(java.lang.Object
In a code base that I've inherited, there's an MDB which is calling SingletonBeanFactoryLocator().getIntance().useBean() to get a factory reference in its ejbCreate(), and then getting a specific bean from this factory and storing it as an MDB instance variable. (The factory is of type 'ClassPathXmlApplicationContext').
The confusing part is: after that bean is obtained, it's calling 'release()' on this factory reference in that same ejbCreate().
Now, this MDB is pooled with poolsize 'x' and what I've observed is, beans defined in the context xml are getting created 'x' number of times. So my guess is, every time the 'ejbCreate()' executes, it's creating a context and its beans afresh.
I checked Spring doc for 'release() above which says:
In an EJB usage scenario this would normally be called from `ejbRemove()` and `ejbPassivate()`.
So here're my questions:
1) is it really creating a new context and new beans everytime ejbCreate() is called?
2) if yes, what happens to the context/beans created in the previous call (e.g. if the beans are singleton themselves, will they be destroyed)?
3) is this the right way to use SingletonBeanFactoryLocator (possibly for thread safety issues) in the context above?
4) if not, what is the right way to use it?
EDIT: one possibility I can think of is to make the concerned beans prototype to make each MDB instance thread-safe, so there's no need to release and recreate the context. Awaiting other comments/suggestions.
Yes
Nothing happens. The same objects will still be in the same MDBs. The MDB doesn't care and Spring is out of the picture at this point.
That really depends on the use circumstances. If you just use Spring to assemble objects and every MDBs should have it's own instances then the answer is yes.
Depending on the use case SpringBeanAutowiringInterceptor may or may not be a better alternative.
Prototype can be tricky. You have to understand your beans and the consequences well to make it do what you expect. That's why it's generally best to make spring beans stateless.
Update:
There is actually a race condition. If the container decides to run the ejbCreate() of two MDBs in parallel then they both will end up sharing the same application context.
Update 2:
I could not find a section that explicitly allows EJB creating through parallel threads but I could also not find a section that explicitly forbids it.
Given the following sections from the spec I assume it would be in the spirit of the spec to do it.
2.4.2 Message-Driven Objects
A typical EJB container provides a scalable runtime environment to execute a large number of mes- sage-driven objects concurrently.
5.2 Goals
A further goal of the message-driven bean model is to allow for the concurrent processing of a stream of messages by means of container-provided pooling of message-driven bean instances.
5.4 Protocol Between a Message-Driven Bean Instance and its Container
It is the container’s responsibility to ensure that the message-driven bean comes into existence when the container is started up and that instances of the bean are ready to receive an asynchronous message delivery before the delivery of messages is started.
5.4.11 Concurrency of Message Processing
A container allows many instances of a message-driven bean class to be executing concurrently, thus allowing for the concurrent processing of a stream of messages. No guarantees are made as to the exact order in which messages are delivered to the instances of the message-driven bean class, although the container should attempt to deliver messages in order when it does not impair the concurrency of mes- sage processing.
We have a JMS topic that is receiving several types of messages(number of types is determined at deploy time) with a requirement that the messages are processed in order by type. All of the types can be handled by the same MDB.
We have a solution where we deploy several versions of that MDB with selectors for each type. While that works, it means that we need to update deployment descriptors in our application every time we deploy a new version which seems to be an error prone process.
We've considered using deployment plans to handle that, but from what I understand it's only possible to change existing MDBs, not add new ones.
Is there anything we are missing?
We are using weblogic 10.3
Here is one way you could handle it. Since you are effectively single-threading the handling of messages of a given type, you could ditch your MDBs and instead manage a pool of threads, each handling a single type. you could implement a singleton service which exposes a JMX management interface (or a remote EJB interface) which allows you to dynamically add/remove types. when this service receives a call to add a new type, it starts a new thread which just loops doing a normal JMS receive call (with the appropriate selector). if your service maintains a map of type -> thread, you could also implement logic for removing a type (e.g. interrupting the thread or otherwise informing it that it is finished).
if you get to the point where a type per thread no longer scales, then you would need to implement a more complex queuing and pooling solution in your service.
Just an idea: Turn your topic into a queue. Create a "distributor" MDB of which you configure one (1) that listens on that queue.
That MDB accepts messages, maintains a (dynamic, static) map of type ("xyz") to queue ("queue15"), and re-sends the message to the appropriate "worker queue".
Create N (fixed, N > number of types) worker queues, with one of your MDBs listening on each queue. No special config required, since your MDB can handle any type.
This way, you do not need to know up-front just which message types there are.
Your worker MDBs will find that they receive only messages of one type, and in order.
Does that scale? Well, there is only one "distributor", but that just looks at the type, and re-sends. That should really be fast. The actual work is asynchronous on a second level.
I think it should even be possible to create "worker queues" dynamically, with the MDB to listen on them (probably via container-specific APIs?).
What is the reason why the Application Servers pool the Stateless EJBs?
I can understand that it is usefull to control the workload of the application for incomming invokations, but this only justifies the pooling of the EJBs that server as FAÇADE with the invoker client.
Does it have any benefit to pool the internal EJBs (those that are not exposed and only invoked internally to perform business logic)?? instead of use a shared single instance (like Spring does).
I can think about at least one downside: a highly used internal EJB could act as a bottleneck.
Stateless session bean EJBs are not necessarily thread-safe. They can be holding resources like JMS sessions which cannot be shared with more than one thread at a time so the server will pool them so that it can serve multiple requests for the same bean concurrently (JMS resources are also pooled, but I'm just using that for the sake of example).
I would also like to know why stateless EJBs are pooled. But i want to know why they're pooled rather than being created and destroyed on demand. The fact that instances can be reused for unrelated requests significantly complicates the implementation of stateless beans (it means you have to be incredibly careful about the use of instance fields), and i don't see any significant benefit to it.
Specifically, i don't see any performance benefit to it. I poked through the implementation of stateless beans in JBoss (6, IIRC), and its only the bean instance itself that's pooled; the plumbing to handle method invocation is recreated from scratch each time it's used. That means that the only performance saving is a single object creation, which should be a trivial amount of time. The only situation in which i can see it being non-trivial is if the bean acquires heavyweight resources, and holds on to them between invocations. However, in that case, the bean is really being used as a glorified, badly-managed, pool; the correct solution would be to pool the resource directly!
Now, EJB has been around a long time. Back when they first came out, object creation was expensive, so it made sense to pool them. But those days are long gone. Why was pooling not dropped in EJB3?
In a traditional n tier web app with servlets for web layer and ejbs(2.0) for biz layer, what is the rationale behind making the servlet model multi threaded and the ejb model single threaded?
i.e there is only 1 servlet instance for all requests, but for ejbs, for each request, there is a new bean instance assigned from the bean pool.
There is indeed only one instance for a specific Servlet since they are supposed to be stateless. In practice this isn't always the case, but so be it.
There are however multiple instances of Stateless session beans (SLSB), and those are pooled.
By their very definition, stateless session beans are stateless, so on the surface this seems like a paradox. The things is that while stateless session beans are stateless with respect to individual calls being made to them, they in fact very often have state.
This state is in the form of references to other resources. The JPA entity manager, which is not thread-safe, is a prime example here. During a single call to a stateless session bean, the caller must have exclusive access to this resource. When the call returns, the next caller can have exclusive access, etc.
If a single instance was used, then either all callers would have to wait on each other (which is of course killing for performance), or they would have the access this single instance concurrently. In the latter case, the bean implementor has to do manual locking of the non thread-safe resources like the entity manager which is often brittle, error-prone and in the end still causes callers to wait on each other.
So, in order to improve performance and still have the safety guarantee, multiple instances are being used.
Those instances are then being pooled and re-used instead of created fresh for each request, because finding, initializing and injecting all required dependencies of the bean can potentially be time consuming.
All of this thus automatically also means that if you inject an entity manager or other non thread-safe resource into a Servlet (which is allowed), you may run into problems. This is a small loop-hole in the Java EE architecture, which is of course easily worked around by simply making use of stateless session beans.
I think that typically servlets present thin facade to the heavy logic implemented in EJBs. Servlets should be stateless and therefore there is no reason to create more than one instance of the same servlet.
If you are using stateless beans only I think that there is no reason to have more than one instance too. But statefull EJBs have state and therefore you need instance per simultaneous request.
I hope I did not say bullshit.