I can't understand how the EJB container manage thread-safety for #Stateless beans with instance variables. So I will give a simple example before explaining my concerns:
#Stateless
public class BeanTest{
#Inject
private String var;
private Connection connection;
#Resource(name = "jdbc/TestDB")
private DataSource dataSource;
public void modify() {
var = "TestName";
}
#PostConstruct
public void initialize() {
try {
connection = dataSource.getConnection();
} catch (SQLException sqle) {
sqle.printStackTrace();
}
}
#PreDestroy
public void cleanup() {
try {
connection.close();
connection = null;
} catch (SQLException sqle) {
sqle.printStackTrace();
}
}
}
Here is my questions, assuming that our container supports pooling:
1. Pooling vs Thread-safe:
User 1 used an instance of BeanTest and modified the var using the modify method, then he finished and the container put the instance of BeanTest in the managed pool. When User 2 tries to use the same bean for a request, he might get the same instance of BeanTest intially modified by User 1 (I understand that might get another instance too). So which state of the instance variable var he will find (default value which is null or "TestName")? if its the new modified one, do that mean that even #Stateless beans are not 100% thread-safe? So finnaly there is no container added -value regarding thread safety, as not using instance variable makes a bean thread safe even if it's not a #Stateless bean
2. Pooling vs #PreDestroy
If the bean is returned to the managed pool and not destroyed, do that mean that the #Predestroy method will not be called and in that case the connection will stay opened ? So, if we have 30 inctance of that bean in the pool, we may have 30 open connection that is not used, isn't that a performance issue? or this not how #Predestroy is working conbined with pooling? (using Connection is just an example, we may have other kind of ressource that we need to close in #Predestroy)
NB: This is not a real life example, so I'am not looking for an alternative solution, my concern is to understand the whole concept and how things are managed in the Application Server, what is happening under the hood
I think the Thread-Safety you are referring to is the non-reenterant clause
The Responsibilities of the Container Provider
Enterprise JavaBeans 3.2, Final Release Session Bean Component Contract
April 10, 2013 2:59 pm Oracle
4.10.13 Non-reentrant Instances The container must ensure that on ly one thread can be executing a st ateless or stateful session bean
instance at any time. Therefore, statef ul and stateless session beans
do not have to be coded as reentrant. One implication of this rule
is that an application ca nnot make loopback calls to a stateless or
stateful session bean instance
You could in a stateless session bean, ignore the EJB programming restrictions, create a bunch of threads and do something non-Thread safe. the container won't stop you. This may cause all sorts of errors due to thread management conflicts.
The container only promises that it will only allow 1 thread access to the stateless ejb at a time. (there are some different rules around singletons)
you are right, that if the instances are returned to a pool that the connections in your example could build up. because of course the been instance still exists.
If you dig in to app server docs, ie Glassfish EJB pool tuning chapter, you will find that the default is to destroy the object instances rather than return them to the pool. same with the JDBC connections, which would get closed and cleaned up. Re-use is an option, in which case you could consume some extra memory if you attempt to create state in SSBs. I don't think there is much performance impact if the instance is sitting idle in a pool.
the exact pooling implementation is up to the application server vendor, so long as they obey the spec. I think you will find the default behavior is to destroy the instance after use. Which causes managed resources to get cleaned up.
But all this is kind of mute, in your example you are trying to store a state, the connection field, in the class. There is no need to create state in a stateless component, that is not what this type of component is for. Other parts of the Java EE architecture handle state. (entities, statefulbeans, JCA)
1) The container guarantees Thread safety which means that a single thread can access a given SLSB at a time. It has nothing to do with guaranteeing that the state won't be changed. BTW having mutable state inside SLSB makes no sense at all.
2) You don't want to keep a connection during the lifetime of a SLSB because you're effectively preventing it from returning to the pool risking an exhaustion.
If the injected AnotherBean is stateless, then it makes no sense to call AnotherBean.setName(). If it is statefull, then it does not make sense to inject a stateful bean in a stateless one (check what stateful beans are made for). About thread-safety: the container cannot make your classes thread safe themself, but it guarantees that a single client thread will use a certain EJB instance at a time (check the quotation from Chris' answer). So, if you do not use an EJB in different threads in your EJB client, then your code is thread-safe by using thread confinment.
Do not use instance variables other then injected ones in a stateless bean. Otherwise you are not consistent with your #Stateful annotation. So, remove the connection state variable. Anyway, you do not want to keep an open connection for long only for your bean: get it every time from the datasource. Also do not forget to close the connection after you used it (in a try/finally clause). With pooling, it works like a JDBC connection pool: when the pool/EJB container decides it does not need the instance anymore (e.g when it wants to reduce the number of instances or when a non application exception is thrown), then the #PreDestroy method wil be called.
Related
I have the following code:
#ConcurrencyManagement(BEAN)
#Startup
#Singleton
public class MySingletonBean {
private Object threadSafeObject;
#PostConstruct
private void init() {
threadSafeObject = nonTrivialInitialization();
}
private void nonTrivialInitialization() {
// something with other beans or container resources
}
public void accessObject() {
threadSafeObject.performSomeThreadSafeOperation();
}
}
The circumstances are as follows:
threadSafeObject is accessed concurrently (obviously)
threadSafeObject takes care internally of its own synchronization
threadSafeObject initialization is not trivial, i.e. it accesses other beans or resources, so it needs to be performed inside container managed code aka #PostConstruct method, not as field initialization at object instantiation
bean managed concurrency is required because actual business code behind the singleton bean can be executed from both a JEE environment and a non-managed environment. Because of this, uniform handling of synchronization is preferred, thus, bean managed concurrency
Direct question: do I need to synchronize the initialization of threadSafeObject and therefore all other accesses to it to prevent possible visibility issues, e.g. thread A processes the initialization of the bean, but, afterwards, thread B doesn't see a correct view of threadSafeObject?
More elaborate question: When putting a singleton session bean into service, in case of bean managed concurrency, does the container offer any guarantees with regards to the safe publishing of the state of the singleton session bean? The EJB spec [part that I read] didn't quite give any hints towards this.
More rants from my part: For container managed concurrency, the container synchronizes all access to the singleton session bean, therefore we have the guarantee that all threads see the most recent consistent state of the bean. For bean managed concurrency, I keep reading that all synchronization is left to the implementor of the bean and the story ends there. Nothing more. So, even though, the container doesn't perform synchronization per se, bean initialization and feeding requests to the bean is still container managed, I'd still expect that the container somehow performs a write barrier when putting the bean into service. The JVM offers this guarantee for instance initialization for example and the metaphor goes that a JEE container is a JVM on steroids with ripped abs, right? :D
Great question! I think this is the relevant part of the spec (taken from here):
Independent of the bean’s concurrency management type, the container
must ensure that no concurrent access to the Singleton bean instance
occurs until after the instance has successfully completed its
initialization sequence, including any #PostConstruct lifecycle
callback method(s). The container must temporarily block any Singleton
access attempts that arrive while the Singleton is still initializing.
(section 4.8.5, p109)
My understanding of "no concurrent access" would be that some container synchronization is required after #PostConstruct completes. Hope that helps?
I have been studying ejb recently and I am also reading about the timer service as well, but even though I have read about Stateless, Stateful and Singleton types of Session Beans, I still have some trouble to figure out what makes the Timer Service have a multiple instance attribute.
I have seen some examples around, and even the simplest ones use the Singleton Session Bean, so, If I were to write a simple program to test it, would it be ok to use a Stateless Bean or is it recommended to use a Singleton anyway? Also, if possible, can I have a case where a Stateless would not be optimal?
Use a singleton if you want to ensure that all timeout callbacks are invoked on the same underlying bean instance. This is important if you want to maintain state in the bean instance itself, and you want to ensure that only one timeout callback can be invoked at a time (by default, the timeout callback will use the singleton's concurrency management settings, which by default is container-managed with a write lock, so only one method on the singleton can be invoked at a time).
Use a stateless if you want to allow multiple timeout callbacks to be invoked at once. The EJB container will create new bean instances if there are multiple timeout callbacks happening concurrently.
If you want to configure a non-persistent timer to begin running when the application begins running, then you can either use the #Schedule annotation on either a stateless or singleton bean, or you can use an #Singleton #Startup bean with an #PostConstruct (and if you want the stateless behavior, you can inject the stateless bean into the stateless bean and invoke a createTimer on the stateless session bean during startup).
The reasons it uses singletons are at least 2 fold:
1.
only singletons have the capabilities of start up initialization. That means, you are able to register your timer services when your application starts.
2.
if it were to use stateless beans, then a new timer service will be registered with every stateless bean setup to serve a request. A singleton guarantees that only one of a kind of your timer is registered. Imagine a contention or integrity issues, or money losses, were you to inadvertently use a timer in a stateless bean and then more than 1 is created at more or less the same time to serve requests.
I have created a stateless session bean(SLSB) and doing a local call from the same JVM. I have a BO local variable in the SLSB when initializing i am setting this value and in the next call i am performing some business function but in the next call i am unable to get the value which i have set in prev. call.
which seems to be according to the SLSB functionality but there is a similar fucntionality which is working in another part of our application. I have confirmed both are SLSB and no connection pooling is done in the ejb-jar.xml and weblogic-ejb-jar.xml(also both are same) also i have debugged both the class but no clue how it is working in the other class.
I am wondering is there any other way in which we can do the state full behaviour of stateless session bean apart from connection pooling.
The important (if slightly obvious) lesson here is: Don't store state in stateless session beans. If you want to store conversational state, use a stateful bean, if you want shared state use a singleton bean. You could also use an entity bean to persist the state.
The reason this is working elsewhere is most likely to do with bean pooling. EJB containers mostly use bean pools to store their stateless beans, as this gives the best performance and scalability. When a request comes in, the container chooses a bean from the pool to service it, takes it out of the pool, the bean handles the request, then is placed back in the pool. Which bean gets chosen is up to the container, since in theory they are all interchangeable.
If you're setting a member variable in your bean then finding (some of the time) later calls find the variable set to your value, this shows that the container has given you the same bean instance back. This is non-deteministic - it depends on server load, pool size and the container's strategy.
With EJB (3.x) you have a choice of Session Beans: #Stateful and #Stateless. If I understand the basics behind these two options:
#Stateful - Each user/client gets their own and is thus typically not pooled; maintains state across multiple requests
#Stateless - Does not maintain state between requests and thus is usually pooled so each new client request gets a fresh bean
My core question here is quite simply, however there are several mini-questions that I have that are tangential to it: how does my POJO design differ between #Stateful beans vs. #Stateless? In other words, if I have a HelloWorld bean that implements the Hello interface, how does that POJO's design change depending on whether I want it to be stateful or not?
Tangential to this:
What different restrictions does the app container (in my case GlassFish) impose upon the EJB depending on whether it is stateful or not?
In the case of #Stateful, how does a client-side request from the same user/client get mapped to the correct bean (the one maintaining the client's state from a previous request)?
When do session beans die? I assume its immediately after the request is done for #Stateless, but no clue for #Stateful.
Thanks in advance for any clarity here.
Regarding the core question "how does my POJO design differ between #Stateful beans vs. #Stateless":
Your hello world example is an excellent example of a #Stateless session bean: the implementation has no state (no class instance variables). It makes no assumptions about state. If you do need "more information" in a #Stateless bean look it up, (re)compute it, etc. If you break this rule and define instance variables on the bean, you have no assurance that the information will be what you expect it to be on each invocation of the bean: don't do it.
Your design of a #Stateful bean would keep internal state (class instance variables) that the container will preserve for the life of the bean; the bean must be Serializable. There are very real run-times costs (memory, and managing the issues around your second tangential question, particularly in a clustered environment) associated with keeping the bean around for the life of the session - so use this only as appropriate (which justifies the existence of #Stateless beans).
For example, consider a simple sign-up page: enter user name, email address, etc, followed by "are you sure"? A #Stateful bean can preserve this temp information until you're ready to submit it to a back end.
Google for examples; here's one: http://docs.redhat.com/docs/en-US/JBoss_Enterprise_Application_Platform/6/html/Beta_Documentation/Stateful_Session_Bean_Example.html
HOW the client-side gets mapped to the correct #Stateful bean is truly implementation dependent (not spec'd), however you can expect that it's managed analogous to how your Servlet Session information is maintained. That said, don't confuse the Servlet Session with a #Stateful session - they're not the same thing at all.
For Java EE 5/6 in your #Stateful bean annotate one method with #Remove, and when your client calls that method it'll be released back to the ether. Outside of that, as long as you hold a reference to the #Stateful bean (i.e. in your Servlet Session) you can expect that #Stateful bean to be around when you need it.
See also: http://docs.oracle.com/javaee/5/tutorial/doc/bnbmt.html
1) Your EJB/Pojo really doesn't know the difference. You as a developer do, but at the code level, a Stateless bean looks pretty much like a Stateful bean. The life cycles and callbacks are effectively the same, the distinction is that the client has more control over that lifecycle, whereas with a Stateless bean the container has control over that lifecycle.
2) Your client simply maintains a copy of the Session Bean instance. So, for example, in a web container you can simply stuff the instance in to the session. What you don't want to do is simply continually inject a Stateful Session bean (using #EJB) for every request as this will create a new one each time. It's better to check your session, if it does not exists, then look it up normally.
3) Stateful beans can have a method annotated with #Remove. When you call this method, the bean is destroyed. If you do not call this method, the container has a timeout facility that will reap the session beans automatically after some configured duration. There is no expectation of a Stateful bean surviving a server restart (though that contract may well be different in a clustered environment).
There's also a bunch of legacy EJB 2 behavior that mostly works, you just have to jump through hoops to get to it, the modern stuff is easier.
If you have instance variables in a Stateless Session Bean, their values will be meaningless (practically speaking). This is because you never know which instance of a Stateless Session Bean will be retrieved from the instance pool to service a request.
Stateless Session Beans only die when the container decides to kill them. They are instantiated as needed, and will only be destroyed if the container decides to destroy them (for example if it decides to make the instance pool smaller). You say that you assume they are destroyed after the request, but this is incorrect. After the request they are returned to the instance pool and remain ready to service the next request.
Because questions are wide, I will try to answer shortly and provide links to additional information.
What different restrictions does the app container (in my case GlassFish) impose upon the EJB depending on whether it is stateful or not?
Main difference in your case is told with following quotation from specification:
Stateless session beans are session beans whose instances have no
conversational state. This means that all bean instances are
equivalent when they are not involved in servicing a client-invoked
method. The term “stateless” signifies that an instance has no state
for a specific client. However, the instance variables of the instance
can contain the state across client-invoked method calls. Examples of
such state include an open database connection and an object reference
to an enterprise bean object.
In the case of #Stateful, how does a client-side request from the same user/client get mapped to the correct bean (the one maintaining the client's state from a previous request)?
In client side you have to store reference to business interface of stateful session bean. This object you got from the EJB container. It is container created object that contains details about how to locate server side object. Some information about these proxies in GlassFish can be found from:
When do session beans die? I assume its immediately after the request is done for #Stateless, but no clue for #Stateful.
No, stateless session bean (SLSB) do not die after request. Life of stateless session bean is:
It is created when container decides so. This happens naturally in
some point before it is used, but otherwise it is in the hands of
container. After SLSB is created, it is placed to pool.
When some client needs to call method in SLSB, one instance is taken away from pool for duration of method call. After method call is finished, instance
is returned to pool. Then this instance (amoung others) is ready to serve next client.
Life of SLSB ends when container decides to adjust size of the pool
Life of stateful session bean (SFSB) is roughly follows:
New instance is created by container when JNDI lookup or injection happens.
During its life time SFSB can server multiple method calls. It can also be passivated (basically stored to disc to save resources) and activated again.
Life of SFSB ends when remove method is called or timeout (SFSB was not in use for some duration of time) happens. Containers usually have implementation specific default timeout and timeout can be also adjusted. In Java EE 6 (EJB 3.1) this timeout can be adjusted per bean basis via StatefulTimeout.
Additionally instance of session bean is discarded when system exception occurs. System exception is RuntimeException (that is not marked as application exception) or java.rmi.RemoteException. Fact that instance of SLSB is discarded is transparent to client. Next call will be for sure served by other instance
of SLSB. In the case of SFSB all possible future business method calls will fail, because server side instance of SFSB does not exist anymore. Details can be found from EJB 3.1 specification chapter 14.
Definitive and detailed description of life cycle can be found from EJB 3.1 specification (4.6, 4.7). Description more detailed than above and with graphs is available in Java EE 6 Tutorial.
And what is the main effect to the design of Hello service:
#Stateless
public class HelloStateless implements HelloRemote {
#Override
public String getGreeting(String name) {
return "Hi " + name;
}
}
/**
* This design is not possible for Stateless, because
* subsequent calls to setName and getGreeting can be
* handled by two different instances. For stateful it
* is fine, because we use one exclusively one instance.
*/
#Stateful
public class HelloStateful {
private String name;
public void setName(String name) {
this.name = name;
}
public String getGreeting() {
return "Hi " + name;
}
}
I was thinking how could i save time on looking up remote ejb reference through jndi. I had an application that needed to work very fast, but it also had to call remote ejb which slowed it down.
So my solution was something like this:
I took apache commons-pool library and used its StackObjectPool implementation for my remote ejb references cache.
private static final ObjectPool pool = new StackObjectPool(new RemoteEjbFactory());
Factory looks something like this:
public static class RemoteEjbFactory extends BasePoolableObjectFactory {
#Override
public Object makeObject() {
try {
return ServiceLocator.lookup(jndi);
} catch (NamingException e) {
throw new ConfigurationException("Could not find remote ejb by given name", e);
}
}
}
Then i take object by borrowing it from pool (if no free object in pool it uses factory to create one):
SomeEjbRemote someEjb = null;
try {
someEjb = (SomeEjbRemoteImpl) pool.borrowObject();
someEjb.invokeRemoteMethod();
} catch (Throwable t) {
if (someEjb != null) {
pool.invalidateObject(someEjb);
}
pool.clear(); // Maybe its not neccessary
someEjb = (SomeEjbRemoteImpl) pool.borrowObject();
someEjb.invokeRemoteMethod(); // this time it should work
}
And of course returning ejb back to pool after successful invokacion
finally {
try {
pool.returnObject(someEjb);
} catch (Exception e) {
logger.error("Could not return object to pool.", e);
}
}
As i understand there is no guarantee that remote reference will stay connected so if we catch exception using cached remote ejb, we just invalidate that object and retry.
What do you think about such approach? Is it correct? Maybe some other solutions, advices?
From the spec
3.4.9 Concurrent Access to Session Bean References
It is permissable to
acquire a session bean reference and
attempt to invoke the same reference
object concurrently from multiple
threads. However, the resulting client
behavior on each thread depends on
the concurrency semantics of the
target bean. See Section 4.3.14 and Section 4.8.5 for details of
the concurrency behavior for session beans.
Summary of § 4.3.14:
If the bean is SLSB, each call will be served by one EJB in the app. server pool. The app. server synchronizes the calls the EJB instances, so each EJB instance are never accessed concurrently.
For SFSB, each call is dispatch to one specific EJB instance, and the app. server does not synchronises the call. So two concurrent calls to the remote reference might lead to a concurrent access to the EJB instance which raises then a javax.ejb.ConcurrentAccessException. The client is responsible of the correct synchronization of the access to the remote reference.
And § 4.8.5 is about EJB singleton, probably not what you are using.
I assume you use SLSB, so you don't need to have a pool on the client-side: look up the remote bean once, and use the same reference from multiple threads.
You could however do a benchmark to see if using multiple reference improves performance, but the gain -- if any -- is probably neglectable compare to the cost of the remote invocation itself.
If then you still decide to have more than one remote reference, I would suggest an other design. Based on your question I assume you have a multi-threaded app. You probable already use a pool for the threads, so a pool for the reference is maybe redundant. If each thread gets a remote reference when it is created, and threads are pooled, there won't be that many remote lookup and the design is simplified.
My 2 cents
I'm answering for JBoss AS since I have limited experience with other AS:s.
Remote JNDI-references are just (load-balancing) connection-less proxies (see JBoss clustering proxy architecture). Serializing them is fine, which means that you can keep them as members in other EJBs, and cache them as you do (I don't know if your pool serializes your objects, some caches do).
Regarding invalidation of proxies:
The proxies will open a connection only for the duration of the method call, and therefore does not have a 'connected' state per se. The proxies can additionally have multiple IP-addresses and load-balance. In JBoss the node list is dynamically updated at every method call, so the risk of a reference to go stale is small. Still there is a chance for this to happen if all nodes go down or the proxy remains inactive while all node IP addresses go stale. Depending on the pool reuse policy (LRU or other?) the the probability that the rest of the cached proxies are invalid once one is will vary. A fair policy will minimize the risk of having very old entries in the pool, which you would like to avoid in this scenario.
With a fair policy in place, the probability that all go stale for the same reason increases, and your 'clear pool once one is stale' policy would make sense. Additionally, you need to take the case of the other node being down into account. As it is now, your algorithm would go into a busy-loop looking up references while the other node is down. I would implement an exponential back-off for the retries, or just consider it a fatal failure and make the exception a runtime exception, depending on whether you can live with the remote EJB being gone for a while or not. And make the exception you catch specific (like RemoteCommunicationFailedException), avoid catching generic exceptions or errors like Exception, Error or Throwable.
Another question you must ask yourself is the amount of concurrency that you want. Normally proxies are thread-safe for SLSBs and single thread only for SFSBs. SFSBs themselves are not thread safe, and SLSBs serialize access per default. This means that unless you enable concurrent access to your EJB 3.1 beans (see tss link) you will need one remote reference per thread. That is: pooling N SLSB remote references will give you N threads concurrent access. If you enable concurrent access and write your SLSB as a thread-safe bean with the annotation #ConcurrencyAttribute(NO_LOCK) you can get unlimited concurrency with just one proxy, and drop your whole pool. Your pick.
EDIT:
ewernli was right, the thread-safe SLSB proxy creates one new instance on the server per call. This is specified in 4.3.14:
There is no need for any restrictions
against concurrent client access to
stateless session beans because the
container routes each request to a
different instance of the stateless
session bean class.
This means that you don't need any pool at all. Just use one remote ref.