EJB Pooling vs Thread-safe and @PreDestroy

I can't figure out how the EJB container controls thread safety for @Stateless beans with instance variables. Therefore, I will give a simple example before explaining my problems:

 @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 are my questions, assuming our container supports merging:

1. The path to the stream:

User 1 used an instance of BeanTest and modified var using the change method, then he finished and the container placed the instance of BeanTest in a managed pool. When user 2 tries to use the same bean for the request, he can get the same BeanTest instance modified by user 1 (I understand that he can get another instance as well). So, what state of the var instance variable will it find (the default is null or "TestName" )? if its new modified, does this mean that even @Stateless beans are not 100% thread safe? So finnaly does not add a container - a value for thread safety, since not using an instance variable makes the bean thread safe, even if it is not an @Stateless bean

2. Union vs @PreDestroy

If the bean returns to the managed pool and is not destroyed, does this mean that the @Predestroy method @Predestroy not be called, in which case the connection will remain open? So, if we have 30% of this bean in the pool, we can have 30 open connections that are not in use, isn't that a performance issue? or is it not how the @Predestroy pool related works? (using Connection is just an example, we may have another type of ressource that we need to close in @Predestroy )

NB: This is not a real life example, so I'm not looking for an alternative solution, my task is to understand the whole concept and how everything is managed on the application server, what happens under the hood

+5
source share
3 answers

I think the Thread-Safety you are talking about is an offer without reuse

Enterprise JavaBeans 3.2 Container Provider Responsibilities, Final Bean Release Contract April 10, 2013 14:59 Oracle

4.10.13 Non-returning instances A container must ensure that a single thread can execute an idle session or session with a Bean instance state at any time. Thus, statef ul and the idle beans session do not need to be encoded as reentrant. One consequence of this rule is that the application does not make loopback calls for stateless persons or a session with a state of Bean instance

You can in a session without a bean state, ignore the restrictions on EJB programming, create a bunch of threads and do something non-streaming safely. the container will not stop you. This can cause all kinds of errors due to flow control conflicts.

The container only promises that it will allow only one stream of access to an element without saving state at a time. (there are some rules regarding single numbers)

You are correct that if instances return to the pool, then the connections in your example can accumulate. because of course the instance still exists.

If you delve into the application server documents, that is, in the Glassfish EJB pool configuration chapter, you will find that by default you need to destroy the object instances and not return them to the pool. same with JDBC connections to be closed and cleared. Reuse is an option, in which case you can consume additional memory if you are trying to create state in SSB. I do not think that the performance effect is strongly affected if the instance sits idle in the pool.

the exact implementation of the federation depends on the application server provider if they comply with the specification. I think you will find that the default behavior is to destroy the instance after use. Which forces cleaned up managed resources.

But all this is kind of dumb, in your example you are trying to save the state, the connection field, in the class. There is no need to create a state in a component without a state for which this type of component is not intended. Other parts of the Java EE architecture handle state. (entities, statefulbeans, JCA)

+2
source

1) The container guarantees thread safety, which means that one thread can simultaneously access this SLSB. This has nothing to do with ensuring that the state will not be changed. BTW with mutable state inside SLSB makes no sense.

2) You do not want to maintain the connection during the entire life of the SLSB, because you effectively prevent it from returning to the pool, risking depletion.

+2
source
  • If the entered AnotherBean has no status, then it makes no sense to call AnotherBean.setName() . If it is statefull, then it makes no sense to introduce a stateful bean in a stateless one (check what the beans state is for). About streaming security: a container cannot make your classes thread safe, but ensures that one client thread will use a specific instance of EJB at a time (check the quote from Chris's answer). So, if you do not use EJB in different threads of your EJB client, then your code will be thread safe using thread restriction .
  • Do not use instance variables other than those that have been entered into a standless bean. Otherwise, you are not consistent with the @Stateful annotation. So, remove the connection state variable. In any case, you do not want to open a connection for your bean only for a long time: each time it is received from the data source. Also remember to close the connection after using it (in the try / finally clause). When merged, it acts as a JDBC connection pool: when the pool / EJB container decides that it no longer needs an instance (for example, when it wants to reduce the number of instances or when there is no application exception ), then the @PreDestroy method is @PreDestroy .
+1
source

All Articles