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
Working with EJBs without any further configuration is thread-safe regardless whether you are invoking one method or multiple methods concurrently.
The pooling of Entity Beans is a functionality to pool the Entity Beans based on the access volume from the client. In the EJB container, you create a pool for each Entity Bean and manage these pools. By specifying the maximum and minimum values, the pooling operation can be customized.
Thread safety is one of the core features of EJBs. The point to be noted is that this thread safety is free of cost and does not need any concurrency related constructs to be coded in by the bean developer himself (there are a few exceptions).
Yes it's thread-safe.
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With