I have an application which uses dynamic consumers. I'm using Spring Framework with RabbitMQ.
I have parameters like concurrentConsumers and maxConcurrentConsumers.
This is a example:
#Bean
public SimpleMessageListenerContainer container(ConnectionFactory connection) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setMaxConcurrentConsumers(8);
container.setConcurrentConsumers(1);
return container;
}
Can I change the values when the application is running? For example, if I want 5 maxConcurrentConsumers instead of 8, can I change the value on a terminal or something like this while the application is running?
Your bean is a singleton and should be stateless (at least, immutable or effectively stateless) to ensure thread-safety and correctness.
As a rule, you should use the prototype scope for all stateful beans and the singleton scope for stateless beans.
Spring documentation
Sometimes, the creation of a bean is quite expensive, so it's more reasonable to construct an instance once and then guarantee that all possible changes made on this object will be permeated in a safe and correct fashion over all its consumers.
I advise building a simple event-driven mechanism.
There are
a MessageListenerContainerEvent extends ApplicationEvent which represents the changes made to the MessageListenerContainer bean;
a MessageListenerContainerChanger implements ApplicationListener<MessageListenerContainerEvent> who is the one listener who modifies the state of the bean, and guarantees that everything works properly;
other listeners who are class that use the bean and are interested in keeping it up-to-date. It's not necessary to send the changes to bean consumers, you could just notify them with no message. For them, it means that some properties of the bean they use locally might be out-of-date.
a publisher which could be an HTTP endpoint, or a #ShellMethod.
It might look too complex, you always can simplify it to
// somewhere in your code
synchronized(bean) {
bean.setConcurrentConsumers(10);
}
but bear in mind the correctness this snippet propagates.
Related
EDITED SHORT VERSION OF THE POST:
Haven't had enough views, so I'm summarizing the question:
My architecture is completely stateless and async, the front-end makes a petition to a REST API and then long-polls for the response. This Rest API queues petitions into a messaging queue, and each petition is dequeued and processed by the Back-end.
I want this Back-end to follow the "traditional" Spring #Service interface and ServiceImpl approach, however is kind of hard because of how I'm doing it.
One Thread dequeues the petition (Producer), spawns a new Thread (Consumer), and then it processes all the petition within that thread, which later sends back to a "responses pool" where it gets polled. That petition might need to use several #Service's and merge the responses from each, maybe even the same #Service twice.
How would you do it? For more information, check the description below!
ORIGINAL LONG POST:
I have a large application with 3 layers like this:
Front-end (Spring-MVC): Views and Controllers, "Model" are async requests to REST API in Middleware to queue the petition first and then long-polling for an answer
Middleware (Spring-MVC): The rest API. Two main functions: receives a petition from front-end and queues it, receives an answer from Backend and stores it on responses cache until retrieved by front-end
Back-End (Spring Standalone App): Producer/Consumer pattern, ONE Producer dequeues petition and creates a Prototype Consumer for each petition. The consumer implements InitializingBean, so it goes something like this: It is initialized, many Autowired fields are initialized and then afterPropertiesSet is executed and many fields which depends on the petition are set.
I also have a Repository Layer of HibernateDaos, which does all the querying to the database.
I'm missing a properly built Service Layer and that's what this question is all about.
Let me put a little bit more of context. What I have right now is like one only HUGE service with 221 functions (The Consumer's file is very long), and one petition may need to invoke several of this functions, and the result of each is merged into a List of DTOs, which is later received by the front-end.
I want to split this one and only service into several, in a logical match to "it's" corresponding Repository, however I've faced the following problems:
Keep this in mind:
One petition has many Actions, one action is a call to a function of a Service.
Each Consumer is a single and unique Thread.
Every time a Consumer Thread starts, a transaction is started and right before returning it is commited, unless rollbacked.
I need all the services of that petition to be executed in the same thread and transaction.
When the consumer runs afterPropertiesSet, several fields specific to that request are initialized by some parameters which are always sent.
With a good Service Layer I want to acomplish:
I don't want to have to initialize all these parameters always for each service of the petition, I want them to be global to the petition/Thread, however, I don't want to have to pass then as parameters to all the 221 functions.
I want to lazily initialize the new services, only if needed, and when it is initialized, I want to set all the parameters I mentioned above. Each service needs to be a Prototype to the petition, however I feel like is dumb initializing it twice if needed within the same petition (2 actions for the same service on one petition), i.e. I want it to behave like a "Request" scope, however, it is not a request since it is not Web Based, it is a new Thread initialized by the Producer when de-queuing a petition.
I was thinking of having a prototype ServicesFactory per Consumer which is initialized with all the parameters afterPropetiesSet in the Consumer, inside this ServicesFactory all possible Services are declared as Class fields, and when a specific service is requested, if it's field is null it is initialized and all fields are set, if not null, the same instance is returned. The problem with this approach, I that I'm losing Dependency Injection on all the Services. I've been reading about ServiceFactoryBean thinking maybe this is the way to go, however I really can't get a hold to it. The fact that it needs all the parameters of the Consumer, and that it needs to be an unique ServiceFactoryBean per Consumer is really confusing.
Any thoughts?
Thanks
Based on the description I don't think this is a good case for using the protoype scope, in this case the ideal scope seems to be thread scope.
As a solution, the simplest would be to make all services singleton. Then the consumer reads the petition from the inbound queue and starts processing.
One of the services that is also singleton and gets injected in all services needed, let's call it PetitionScopedService.
This service internally uses a ThreadLocal, which is a thread scoped holder for a variable of type PetitionContext. PetitionContext on it's turn contain all information that is global to that petition.
All the consumer needs to do is to set the initial values of the petition context, and any caller of PetitionScopedService on the same thread will be able to read those values in a transparent way. Here is some sample code:
public class PetitionContext {
... just a POJO, getters and setters etc.
}
#Service
public class PetitionScopedService {
private ThreadLocal<PetitionContext> = new ThreadLocal<PetitionContext>();
public doSomethingPetitionSpecific() {
... uses the petition context ...
}
}
#Service
public class SomeOtherService {
#Autowired
private PetitionScopedService petitionService;
... use petition service that is a singleton with thread scoped internal state, effectivelly thread scoped ...
}
Points 2 and 3 need more reorganizing, prefer to check "Spring Integration" for both "Middleware" and "(Spring Standalone App): Producer/Consumer pattern" actually spring integration made to solve these 2 points, and using publish/subscribe if you are doing 2 or more actions at same time, the other point why you are using REST in "Middleware" are these "Middleware" services exposed by another app rather than your front end, in this case you can integrate this part in your Spring-MVC front end app using "content negotiation", otherwise if you are going to use "Spring Integration" you will find multiple ways for communication.
if I understand EJB correctly, #Singleton is actually the same as Singleton in plain Java and also singleton in spring -> one instance, every call goes through the same instance concurrently.
#Stateless declares a bean, that could (but must not) have multiple instance, with the limitation that only one call can be in an instance at the same time. Right sofar?
This remains me on the servlet programming model: in theory servlet containers are allowed to make multiple copies of the servlet, in practice I haven't seen any servlet container to do so.
So assuming I do not have REALLY LIMITED resources like doors, windows or printers in my code (and if I did I could still solve it with queues and stuff), what is the REAL example, where usage of #Stateless is advantageous over usage of #Singleton.
regards
Leon
You can have multiple instances of a stateless bean to increase throughput.
On the other hand there is only one instance of a singleton. The reason for this is normally to share state in application scope, serializes access to resources etc., and this implies locking or synchronization.
So if you are not really having a singleton, then use a stateless bean.
If you have a "stateless singleton", there is no difference. But if you read "singleton", it has a special meaning by convention (= there must be a reason for using the singleton pattern).
Stateless implies that the bean is thread safe. This is because there is no code in the bean that relies on state. This means that running any of its methods will not affect future running of said methods.
An example of a stateless class would a class that does addition and subtraction. All the necessary parameters are passed into the method. Doing an addition or subtraction does not alter the way these methods work at a later call. This implies that you do not need to worry about concurrency with the class.
A singleton is usually used for a class that is very expensive to create such as a Database connection. You do not want every class creating a new Database connection every time they need to use the database so you have it instantiated once at program start up. Being a singleton does not necessarily mean that the class is thread safe (although it absolutely should be).
So Stateless means the class is threadsafe.
Singleton refers to the fact that the class is only created once. While this heavily implies that the class is (AND IT SHOULD BE) thread safe, it does not directly imply it like stateless does.
we have a situation where we want to perform some tasks at the end of a request or transaction. More specifically, we need to collect some data during that request and at the end we use that data to do some automatic database updates.
This process should be as transparent as possible, i.e. users of the EJBs that require this should not have to worry about that.
In addition we can't control the exact call stack since there are multiple entry points to the process.
To achieve our goal, we're currently considering the following concept:
certain low level operations (that are always called) fire a CDI event
a stateless EJB listens for those events and upon receiving one it collects the data and stores it into a scoped CDI bean (either request scope or conversation scope would be fine)
at the end of the request another event is fired which causes the data in the scoped CDI bean to be processed
So far, we managed to get steps 1 and 2 up and running.
However, the problem is step 3:
As I already said, there are multiple entry points to the process (originating from web requests, scheduled jobs or remote calls) and thus we thought of the following approach:
3a. A CDI extension scans all beans and adds an annotation to every EJB.
3b. An interceptor is registered for the added annotation and thus on every call to an EJB method the interceptor is invoked.
3c. The first invocation of that interceptor will fire an event after the invoked method has returned.
And here's the problem (again in the 3rd step :) ):
How would the interceptor know whether it was the first invocation or not?
We thought of the following, but neither worked so far:
get a request/conversation scoped bean
fails because no context is active
get the request/conversation context and activate it (which then should mark the first invocation since in subsequent ones the context should be active)
the system created another request context and thus WELD ends up with at least two active request contexts and complained about this
the conversion context stayed active or was deactivated prematurely (we couldn't yet figure out why)
start a long running conversation and end it after the invocation
failed because there was no active request context :(
Another option we didn't try yet but which seems to be discouraged:
use a ThreadLocal to either store some context data or at least to use invocation context propagatation as described here: http://blog.dblevins.com/2009/08/pattern-invocationcontext-propagation.html
However, AFAIK there's no guarantee that the request will be handled entirely by the same thread and thus wouldn't even invocation context propagation break when the container decides to switch to another thread?
So, thanks to all who endured with me and read through all that lengthy description.
Any ideas of how to solve this are welcome.
Btw, here are some of the software components/standards we're using (and which we can't switch):
JBoss 7.1.0.Final (along with WELD and thus CDI 1.0)
EJB 3.1
Hibernate 3.6.9 (can't switch to 4.0.0 yet)
UPDATE:
With the suggestions you gave so far, we came up with the following solution:
use a request scoped object to store the data in
the first time an object is stored in that object an event is fired
a listener is invoked before the end of the transaction (using #Observes(during=BEFORE_COMPLETION) - thanks, #bkail)
This works so far but there's still one problem:
We also have MBeans that are managed by CDI and automatically registered to the MBean server. Thus those MBeans can get EJB references injected.
However, when we try and call an MBean method which in turn calls an EJB and thus causes the above process to start we get a ContextNotActiveException. This indicates that within JBoss the request context is not started when executing an MBean method.
This also doesn't work when using JNDI lookups to get the service instead of DI.
Any ideas on this as well?
Update 2:
Well, seems like we got it running now.
Basically we did what I described in the previous update and solved the problem with the context not being active by creating our own scope and context (which activated the first time an EJB method is called and deactivated when the corresponding interceptor finishes).
Normally we should have been able to do the same with request scope (at least if we didn't miss anything in the spec) but since there is a bug in JBoss 7.1 there is not always an active request context when calling EJBs from MBeans or scheduled jobs (which do a JNDI lookup).
In the interceptor we could try to get an active context and on failure activate one of those present in the bean manager (most likely EjbRequestContext in that case) but despite our tests we'd rather not count on that working in every case.
A custom scope, however, should be independent from any JBoss scope and thus should not interfere here.
Thanks to all who answered/commented.
So there's a last problem though: whose answer should I accept as you all helped us get into the right direction? - I'll try to solve that myself and attribute those points to jan - he's got the fewest :)
Do the job in a method which is annotated with #PreDestroy.
#Named
#RequestScoped
public class Foo {
#PreDestroy
public void requestDestroyed() {
// Here.
}
}
It's invoked right before the bean instance is destroyed by the container.
What you're looking for is SessionSynchronization. This lets an EJB tie in to the transaction lifecycle and be notified when transactions are being completed.
Note, I am being specific about Transactions, you mention "requests and transactions" and I don't know if you specifically mean EJB Transactions or something tied to your application.
But I'm talking about EJB Transactions.
The downside is that it is only invoked when the specific EJB is invoked, not to "all" transactions in general. But that may well be appropriate anyway.
Finally, be careful in these interim call back areas -- I've had weird things happen with transactional at these lifecycle methods. In the end, ended up putting stuff in to a local, memory based queue that another thread reaped for committing to JMS or whatever. Downside is that they were tied to the transaction at hand, upside was that they actually worked.
Phew, that's a complex scenario :)
From how I understand what you've tried so far you are pretty advanced with the CDI techniques - there is nothing big you are missing.
I would say that you should be able to activate a conversation context at the entry point (you've probably seen the relevant documentaton?) and work with it for the whole processing. It might actually be worthwhile considering implementing an own scope. I did that once in a distantly related scenario where we could not tell whether we've been invoked by HTTP-request or EJB-remoting.
But to be honest, all this feels far too complex. It's a rather fragile construct of interceptors notifying each other with events which all in all seems just too easy to break.
Can it be that there is another approach which better fits your needs? E.g. you might try to hook on the transaction management itself and execute your data accumulation from there?
Is there a request-scoped context for EJB3 session-beans? My environment is Java-EE-5.
This example
#Remote(SessionFacade.class) #Stateless
public class SessionFacadeBean implements SessionFacade {
#EJB
private Other bean;
public void myBusinessMethod() {
// TODO: get or create *myRequestScope*
*myRequestScope*.put("demo", Integer.valueOf( 1 ));
bean.otherBusinessMethod();
sysout(*myRequestScope*.get("demo"));
}
}
#Local(Other.class) #Stateless
public class OtherBean implements Other {
public void otherBusinessMethod() {
// TODO: get or create *myRequestScope*
*myRequestScope*.put("demo", Integer.valueOf( 2 ));
}
}
should always printout "2" when invoking SessionFacadeBean#myBusinessMethod() - irrespective of parallel invocations.
I do not have the luxury of using CDI. And, it should also work independently of transaction propagation (so JCA is also not an option).
Stateless EJBs, are their name suggests do not store state, so there is no concept of request-scope. There is a session scope that is limited to the current runtime session context, where you cannot store state as well, so that rules out any option of storing state within the bean or within the container.
You might find some luck by using ThreadLocal variables, but this as the name suggests, is scoped to the current thread of execution. Going by your posted code, this appears to be what you would want. The problem with this approach is that,
Thread objects are simply not destroyed once the EJB method has completed execution; they are returned to the container's thread pool. Therefore, if you read the ThreadLocal value in a different context of execution, you will find the value of the previous execution context that used the same thread. In other words, ensure that your application always puts values in the ThreadLocal object before reading them.
Additionally, free any ThreadLocal objects once you do not require them, otherwise you would have a memory leak on your hands.
Is there a request-scoped context for stateless session-beans?
Short answer is No.
The long answer is: You need some context to share data between invocations of your business methods. This could be a design issue. Requestscope is a concept of web-tier.
In the Web-tier the request,page,session and application scope is implemented as a Hashmap. So you could pass a reference to a Hashmap as context to share all data.
Another approach could be to use a singleton (which needs to be shared between nodes e.g. using ehcache).
Migrate to EJB 3.1 and use #Singleton
Consider to use stateful Beans and put your request-scope into the beans session scope which could be removed after you leave the request scope.
Stateless beans in Java do not keep their state between two calls from the client. So in a nutshell we might consider them as objects with business methods. Each method takes parameters and return results. When the method is invoked some local variables are being created in execution stack. When the method returns the locals are removed from the stack and if some temporary objects were allocated they are garbage collected anyway.
From my perspective that doesn’t differ from calling method of the same single instance by separate threads. So why cannot a container use one instance of a bean instead of pooling a number of them?
Pooling does several things.
One, by having one bean per instance, you're guaranteed to be threads safe (Servlets, for example, are not thread safe).
Two, you reduce any potential startup time that a bean might have. While Session Beans are "stateless", they only need to be stateless with regards to the client. For example, in EJB, you can inject several server resources in to a Session Bean. That state is private to the bean, but there's no reason you can't keep it from invocation to invocation. So, by pooling beans you reduce these lookups to only happening when the bean is created.
Three, you can use bean pool as a means to throttle traffic. If you only have 10 Beans in a pool, you're only going to get at most 10 requests working simultaneously, the rest will be queued up.
Pooling enhances performance.
A single instance handling all requests/threads would lead to a lot of contention and blocking.
Since you don't know which instance will be used (and several threads could use a single instance concurrently), the beans must be threadsafe.
The container can manage pool size based on actual activity.
The transactionality of the Java EE model uses the thread context to manage the transaction lifecycle.
This simplification exists so that it is not necessary to implement any specific interface to interact with the UserTransaction object directly; when the transaction is retrieved from the InitialContext (or injected into the session bean) it is bound to a thread-local variable for reuse (for example if a method in your stateless session bean calls another stateless session bean that also uses an injected transaction.)
Life cycle of the Statelesss session beans are Doesnot exist, Passive and MethodReady(Passive or Inactive) state.To optimize on perormance, instead of traversing the bean all through from create to method ready state, container manages the bean between active and passive states through the container callbacks - ejbActivate() and ejbPassivate() there by managing the bean pool.
sreenut
Methods by nature ARE THREAD SAFE (including static). Why? Simple, because every variable inside the method is created in the stack memory, i.e. every variable used inside the method is created per call (it's not shared). However, parameters aren't part of the stack.
However, a method is unsafe if it uses an unsafe variable:
a) calling a static field or variable. However, it happens in every single case.
b) calling a resource that it's shared. Such as the EntityManager.
c) passing a parameter that is not safe.