EJB Bean passivation - java

I have read that when ejbPassivate() is called Stateful Session Beans are usually evicted but Entity Beans and Stateless Beans are pooled which means they are not appilicable for passivation.
In another article I have read that activation and passivation is applicable only for Stateful Session Beans and Entity Beans which is a contrast to the claim that Entity Beans and Stateless Beans are pooled.
For what beans does the passivation apply and what does really happen when they do?

Passivation and Activation only apply to EJBs that have state, namely stateful session beans and entity beans.
Passivation is the process by which any state a given bean has is moved into storage.
Activation is the process by which any state that a given bean previously had is loaded from storage.
This mechanism is needed because the EJB contain creates a pool of each bean type but gives the illusion that there are an infinate number of each bean, loading and storing them using the ejbActive and ejbPassivate methods respectively as needed.
The full life-cycle of each bean type is described here:
Stateless Session Bean
Stateful Session Bean
Entity Bean

Related

CDI / JTA - Error during session replication: UnproxyableResolutionException

I am testing server failover in a Wildfly 26 cluster (using standalone-ha.xml config)
The application is a stateful JSF / Jakarta EE8 / CDI war deployment
We are using Deltaspike Data and JPA modules in DAO pattern (with #RequestScoped entity managers)
I have two nodes runnings 1 and 2 and perform the following steps:
Login to a user account on Node 1 to create some session data.
Perform a graceful shutdown of Node 1, logs show Node 1 has left the cluster and is reported in logs at Node 2
Refresh browser
Node 2 loads the replication session data then throws the exception pasted below to say that com.arjuna.ats.jta.cdi.DelegatingTransactionManager is not proxyable. The page doesn't render any content and I have to start a new HTTP session to be able to continue on Node 2
[0m [31m11:31:47,479 ERROR [io.undertow.servlet.request] (default
task-2) UT015005: Error invoking method requestInitialized on listener
class org.jboss.weld.module.web.servlet.WeldInitialListener:
org.jboss.weld.exceptions.UnproxyableResolutionException: WELD-001435:
Normal scoped bean class
com.arjuna.ats.jta.cdi.DelegatingTransactionManager is not proxyable
because it has no no-args constructor - Managed Bean [class
com.arjuna.ats.jta.cdi.NarayanaTransactionManager] with qualifiers
[#Any #Default].
Further down it references one of our CDI #ViewScoped beans (ManageCheers):
Caused by: an exception which occurred: in object of type
org.jboss.weld.bean.proxy.util.SerializableClientProxy in field
com.arjuna.ats.jta.cdi.transactional.TransactionalInterceptorBase.transactionManager
in object
com.arjuna.ats.jta.cdi.transactional.TransactionalInterceptorRequired#2cbfe004
in object of type
com.arjuna.ats.jta.cdi.transactional.TransactionalInterceptorRequired
in field
org.jboss.weld.interceptor.proxy.InterceptionContext.interceptorInstances
in object
org.jboss.weld.interceptor.proxy.InterceptionContext#7ce2923f in
object of type org.jboss.weld.interceptor.proxy.InterceptionContext
in field
org.jboss.weld.interceptor.proxy.InterceptorMethodHandler.ctx in
object
org.jboss.weld.interceptor.proxy.InterceptorMethodHandler#651c0cb2 in
object of type
org.jboss.weld.interceptor.proxy.InterceptorMethodHandler in field
org.jboss.weld.bean.proxy.CombinedInterceptorAndDecoratorStackMethodHandler.interceptorMethodHandler
in object
org.jboss.weld.bean.proxy.CombinedInterceptorAndDecoratorStackMethodHandler#36f06fd5
in object of type
org.jboss.weld.bean.proxy.CombinedInterceptorAndDecoratorStackMethodHandler
in field
com.myapp.actions.notifications.ManageCheers$Proxy$_$$WeldSubclass.methodHandler
in object
com.myapp.actions.notifications.ManageCheers$Proxy$$$WeldSubclass#4e106109
in object of type
com.myapp.actions.notifications.ManageCheers$Proxy$$$_WeldSubclass
in object of type javax.faces.component.UIViewRoot$ViewMap in object
of type com.sun.faces.util.LRUMap
-----UPDATE
The problem seems to be linked to the
#Transactional(Transactional.TxType.REQUIRED)
annotation, if I remove this annotation from our CDI bean it does not occur, but then we have no transactions.
I notice that NarayanaTransactionManager is #ApplicationScoped so maybe the server shutdown is causing it to be re-created?
Looks like com.arjuna.ats.jta.cdi.NarayanaTransactionManager is being put into your session state but is not compatible with the state replication.
Are you actually expecting this to be part of your state? Feels like it's not intentional
You could maybe enable sticky session to avoid session replication (from one node to another) ?
https://docs.wildfly.org/26/wildscribe/subsystem/undertow/configuration/filter/mod-cluster/balancer/index.html
This seems to be a bug in Narayana, I forked the library and added a no-args constructor to the DelegatingTransactionManager and the exception no longer occurs.
Bug reported here:
https://issues.redhat.com/projects/JBTM/issues/JBTM-3703?filter=allopenissues

EJB with CMT when migrate from JBoss 7 to WildFly 9

I'm migrating my application from JBoss 7 to WildFly (v9.0.1) and it is not deployed because of bean transaction management error.
Caused by: javax.naming.NamingException: WFLYNAM0062: Failed to lookup env/com.component.eventmgt.EventServiceImpl/transaction [Root exception is java.lang.RuntimeException: WFLYNAM0059: Resource lookup for injection failed: java:jboss/UserTransaction]
at org.jboss.as.naming.ServiceBasedNamingStore.lookup(ServiceBasedNamingStore.java:157)
at org.jboss.as.naming.ServiceBasedNamingStore.lookup(ServiceBasedNamingStore.java:83)
at org.jboss.as.naming.NamingContext.lookup(NamingContext.java:207)
at org.jboss.as.naming.NamingContext.lookup(NamingContext.java:193)
at org.jboss.as.naming.NamingContext.lookup(NamingContext.java:189)
at org.jboss.as.naming.deployment.ContextNames$BindInfo$1$1.getReference(ContextNames.java:316)
... 90 more
Caused by: java.lang.RuntimeException: WFLYNAM0059: Resource lookup for injection failed: java:jboss/UserTransaction
at org.jboss.as.naming.deployment.ContextNames$BindInfo$1$1.getReference(ContextNames.java:319)
at org.jboss.as.naming.ServiceBasedNamingStore.lookup(ServiceBasedNamingStore.java:143)
... 95 more
Caused by: javax.naming.NameNotFoundException: UserTransaction [Root exception is java.lang.IllegalStateException: WFLYEJB0137: Only session and message-driven beans with bean-managed transaction demarcation are allowed to access UserTransaction]
at org.jboss.as.naming.ServiceBasedNamingStore.lookup(ServiceBasedNamingStore.java:153)
at org.jboss.as.naming.ServiceBasedNamingStore.lookup(ServiceBasedNamingStore.java:83)
at org.jboss.as.naming.NamingContext.lookup(NamingContext.java:207)
at org.jboss.as.naming.NamingContext.lookup(NamingContext.java:193)
at org.jboss.as.naming.NamingContext.lookup(NamingContext.java:189)
at org.jboss.as.naming.deployment.ContextNames$BindInfo$1$1.getReference(ContextNames.java:316)
... 96 more
Here is the EventServiceImpl class.
#Stateless
#Remote(EventService.class)
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public class EventServiceImpl implements EventService {
/**
* Logger
*/
private static Logger log = LoggerFactory.getLogger(EventService.class);
private EventTableDAO eventDao;
#PersistenceContext(unitName = "SOMF-GT")
private EntityManager entityManager;
#Resource
private UserTransaction transaction;
public List<Map> loadEvents() throws EventsException {
Configuration configurationEntry = new Configuration();
try {
Map configuration = configurationService.getConfiguration();
if (configuration != null) {
eventDao = new EventTableDAO(Event.class, entityManager, transaction);
List<Map> eventsMapList = new ArrayList();
}
}
I know that if i changed the transaction management to BMT with #TransactionManagement(TransactionManagementType.BEAN) but then the following error emerge
WFLYJPA0060: Transaction is required to perform this operation (either use a transaction or extended persistence context)
I want to know why we have to change this in the first place ?
Any information, please !
These changes rolled out in Wildfly 8 and were (as noted below) based on standardization of the global JNDI namespace in EJB 3.1.
From the Wildfly 8 Developer Guide:
EJB 3.1 introduced a standardized global JNDI namespace and a series of related namespaces that map to the various scopes of a Java EE application. The three JNDI namespaces used for portable JNDI lookups are java:global, java:module, and java:app. If you use JNDI lookups in your application, you will need to change them to follow the new standardized JNDI namespace convention.
To conform to the new portable JNDI namespace rules, you will need to review the JNDI namespace rules and modify the application code to follow these rules.
The guide further notes:
WildFly 8 has tightened up on JNDI namespace names to provide predictable and consistent rules for every name bound in the application server and to prevent future compatibility issues. This means you might run into issues with the current namespaces in your application if they don't follow the new rules.
Here's a snippet from the table showing Examples of JNDI mappings in previous releases and how they might look now specific to the UserTransaction:
Previous Namespace New Namespaces
------------------ --------------
java:comp/UserTransaction java:comp/UserTransaction (This will not be accessible for non EE threads, e.g. Threads your application directly creates)
java:comp/UserTransaction java:jboss/UserTransaction (Globally accessible, use this if java:comp/UserTransaction is not available)
Edit re: WFLYEJB0137:
This is theory-craft and may be worthless - let me know and I'll delete it. Java EE 6 Tutorial - Container-Managed Transactions says:
Enterprise beans that use container-managed transaction demarcation also must not use the javax.transaction.UserTransaction interface.
Further:
(Transaction) Required Attribute
If the client is running within a transaction and invokes the enterprise bean’s method, the method executes within the client’s transaction. If the client is not associated with a transaction, the container starts a new transaction before running the method.
The Required attribute is the implicit transaction attribute for all enterprise bean methods running with container-managed transaction demarcation. You typically do not set the Required attribute unless you need to override another transaction attribute. Because transaction attributes are declarative, you can easily change them later.
The exception message pretty much says it all:
WFLYEJB0137: Only session and message-driven beans with bean-managed transaction demarcation are allowed to access UserTransaction
Your EJB is using container managed transaction (CMT) demarcation which does not inter-operate with bean managed transaction (BMT) demarcation wherein UserTransaction lies.
Regarding a switch to BMT and
WFLYJPA0060: Transaction is required to perform this operation (either use a transaction or extended persistence context)
I found Transaction is required to perform this operation (either use a transaction or extended persistence context) which seems to indicate that the transaction is to be managed by you, as you noted in your comments #Marco. It appears that you have made the appropriate modification.

WELD-001303 No active contexts for scope type javax.enterprise.context.SessionScoped

I have searched every where, but seem I cannot find out the best answer for me to resolved this error, there is my stack trace, can somebody tell me what happening with me, I have spent twos date to finding this error....:(
16:55:02,405 SEVERE [org.activiti.engine.impl.jobexecutor.TimerCatchIntermediateEventJobHandler] (Thread-16 (HornetQ-client-global-threads-982087879)) exception during timer execution: org.activiti.engine.ActivitiException: Exception while invoking TaskListener: WELD-001303 No active contexts for scope type javax.enterprise.context.SessionScoped
at org.activiti.engine.impl.persistence.entity.TaskEntity.fireEvent(TaskEntity.java:529) [activiti-engine-5.11.jar:5.11]
at ....
Caused by: org.jboss.weld.context.ContextNotActiveException: WELD-001303 No active contexts for scope type javax.enterprise.context.SessionScoped
at org.jboss.weld.manager.BeanManagerImpl.getContext(BeanManagerImpl.java:598) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.bean.proxy.ContextBeanInstance.getInstance(ContextBeanInstance.java:71) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.jboss.weld.bean.proxy.ProxyMethodHandler.invoke(ProxyMethodHandler.java:79) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at com.metro.wfm.shared.cdi.OverrideUserBean$Proxy$_$$_WeldClientProxy.hasBean(OverrideUserBean$Proxy$_$$_WeldClientProxy.java) [wfm-shared-0.0.2.jar:]
... 168 more
Session scoped contexts are only active during servlet calls with the service() method, or when executing a servlet filter. Not sure how you have your Activiti job setup, but it would appear not to be within the active period of a session context. As such, if you inject any beans that require #SessionScoped then the injection will fail.
The solution would be to remove the bean injections that require #SessionScoped, or to modify the beans.
I was facing the same problem, and based on the answer that #Perception posted, it seems that if you are using #Singleton (javax.ejb.Singleton) along with #Startup (javax.ejb.Startup) annotations on some initialization class, and also injecting other bean which is #SessionScoped or depends on other bean that is #SessionScoped, it will cause this WELD-001303 error.
You should separate frontend session logic. Imagine you have #SessionScoped bean for every logged user, it contains Account object.
After login, the same time save Account object into session bean and save Account object in the #ApplicationScoped bean, but in the HashMap(id, account), in the backend logic, every Singleton bean can access and get data from #Application Scoped bean. Even #Schedule method.

Spring Injection & Globally initialized objects

I have a spring injected service
class A{
List l = new ArrayList();
public m1(){
//do some additions in list
}
public m2(){
//do some new additions in list
}
}
Now because creating of objects of A, is in the hands of spring the behavior of program is not what is expected. (I expect list to be available empty always but not initialized by methods for some wired reason)
Will Spring always create only one instance of A, so that list l will keep on growing, I have configured bean as singleton in application context.
If yes, naturally I must initialize the list inside the functions m1 & m2 or callee must past the reference, and in my case callee being struts2 actions they are not singleton so this issue can be solved?
Or
Does spring provide any support in configuration to initialize member variables at every call or something else?
More generally what are best practices to have in writing services injected by spring about using member variables/ local variables for performance & efficiency.
Trying to answer following :
Does spring provide any support in configuration to initialize member variables at every call or something else?
By default Spring beans are singleton. Initialized only once and use the same object again and again.
However, if requirement changes as you asked. You need to understand scope attribute provided by the Spring.
<bean id="id" class="com.test.TP" scope="prototype">
</bean>
Refer following for detail understanding.
Scope Description
singleton
Scopes a single bean definition to a single object instance per
Spring IoC container.
prototype
Scopes a single bean definition to any number of object instances.
request
Scopes a single bean definition to the lifecycle of a single HTTP
request; that is each and every HTTP request will have its own
instance of a bean created off the back of a single bean definition.
Only valid in the context of a web-aware Spring ApplicationContext.
session
Scopes a single bean definition to the lifecycle of a HTTP Session.
Only valid in the context of a web-aware Spring ApplicationContext.
global session
Scopes a single bean definition to the lifecycle of a global HTTP
Session. Typically only valid when used in a portlet context. Only
valid in the context of a web-aware Spring ApplicationContext.
http://static.springsource.org/spring/docs/3.0.0.M3/spring-framework-reference/html/ch04s04.html
It is also possible to have user defined scope such as thread scope.
You can configure your bean as follows:-
<bean id = "serviceBeanA" class = "somepkg.A" scope="prototype">
<property name = "l">
<value>
<list>
<value>ABC</value>
.....
</list>
</value>
</property>
</bean>
I'm not sure if I understand the question but your sample class should work fine with spring. Spring will call the default constructor unless you pass in constructor args in the configuration file. As long as you have an id="..." in the bean then it will create a singleton of that class. Then, the first class that calls a.m1() will see l as being an empty list.
What may be happening is that you have multiple instances of A being created. See here about Spring singletons versus non. To quote:
Beans are defined to be deployed in one of two modes: singleton or non-singleton. (The latter is also called a prototype, although the term is used loosely as it doesn't quite fit). When a bean is a singleton, only one shared instance of the bean will be managed and all requests for beans with an id or ids matching that bean definition will result in that one specific bean instance being returned.
So if you don't have an id or name specified in your Spring configuration then you might get multiple instances of A created.
The non-singleton, prototype mode of a bean deployment results in the creation of a new bean instance every time a request for that specific bean is done. This is ideal for situations where for example each user needs an independent user object or something similar.

Stateful EJB not being passivated when the client VM is abruptly terminated

I have an stateful session bean deployed on Jboss 4.3 with the following config on jboss.xml:
<cache-config>
<idle-timeout-seconds>7200</idle-timeout-seconds>
<remove-timeout-seconds>8000</remove-timeout-seconds>
</cache-config>
IE:
The bean should be passivated after 2 hours of IDLE and removed after 2 hours and 15 minutes.
The problem is: when the client VM is abruptly terminated the bean is neither passivated nor removed.
Is there a way to avoid this?
A container may only passivate a stateful session bean instance when
the instance is not in a transaction.
A container must not passivate a stateful session bean with an
extended persistence context unless the following conditions are met:
All the entities in the persistence context are serializable.
The EntityManager is serializable.
Any interceptor classes associated with the stateful session bean must be Serializable.
The references can possibly restrict the bean from getting passivated.

Categories