Question

I have a SFSB defined bellow:

@Named("loginManager")
@Stateful
@SessionScoped
public class LoginManager {
    @PersistenceContext(type = PersistenceContextType.EXTENDED)
    private EntityManager em;

And I have a @Remove annotated method:

@Remove
public void remove() {
    log.info("loginManager removed");
}

But when I call this method in h:commandButton, an Exception is thrown:

16:19:32,640 FATAL [javax.enterprise.resource.webcontainer.jsf.context] (default task-64) #{loginManager.logout()}: org.jboss.weld.exceptions.UnsupportedOperationException: WELD-000037: Cannot call EJB remove method directly on non-dependent scoped bean public java.lang.String cn.fh.codeschool.action.LoginManager.logout(): javax.faces.FacesException: #{loginManager.logout()}: org.jboss.weld.exceptions.UnsupportedOperationException: WELD-000037: Cannot call EJB remove method directly on non-dependent scoped bean public java.lang.String cn.fh.codeschool.action.LoginManager.logout()
    at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:89) [jsf-impl-2.2.6-jbossorg-3.jar:]
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) [jsf-impl-2.2.6-jbossorg-3.jar:]
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198) [jsf-impl-2.2.6-jbossorg-3.jar:]
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:646) [jboss-jsf-api_2.2_spec-2.2.6.jar:2.2.6]
    at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85) [undertow-servlet-1.0.5.Final.jar:1.0.5.Final]
    at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:61) [undertow-servlet-1.0.5.Final.jar:1.0.5.Final]
    at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) [undertow-servlet-1.0.5.Final.jar:1.0.5.Final]
    at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.5.Final.jar:1.0.5.Final]
    at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:113) [undertow-servlet-1.0.5.Final.jar:1.0.5.Final]
    at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:56) [undertow-servlet-1.0.5.Final.jar:1.0.5.Final]
    at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:45) [undertow-core-1.0.5.Final.jar:1.0.5.Final]
    at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:61) [undertow-servlet-1.0.5.Final.jar:1.0.5.Final]
    at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:58) [undertow-core-1.0.5.Final.jar:1.0.5.Final]
    at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:70) [undertow-servlet-1.0.5.Final.jar:1.0.5.Final]
    at io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76) [undertow-core-1.0.5.Final.jar:1.0.5.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.5.Final.jar:1.0.5.Final]
    at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.5.Final.jar:1.0.5.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.5.Final.jar:1.0.5.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:240) [undertow-servlet-1.0.5.Final.jar:1.0.5.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:227) [undertow-servlet-1.0.5.Final.jar:1.0.5.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:73) [undertow-servlet-1.0.5.Final.jar:1.0.5.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:146) [undertow-servlet-1.0.5.Final.jar:1.0.5.Final]
    at io.undertow.server.Connectors.executeRootHandler(Connectors.java:168) [undertow-core-1.0.5.Final.jar:1.0.5.Final]
    at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:727) [undertow-core-1.0.5.Final.jar:1.0.5.Final]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [rt.jar:1.7.0_21]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [rt.jar:1.7.0_21]
    at java.lang.Thread.run(Thread.java:722) [rt.jar:1.7.0_21]

enter image description here

How can I destroy SFSB by myself instead of by container? I find that when I request a SFSB, there will be many beans constructed instead of one. I really concern about the memory usage.

Thanks!

Was it helpful?

Solution 2

I've figured it out.

SFSB should not be used in this way. Normally I need to inject it to a managed bean then invoke SFSB's business logic inside that managed bean.

If we want to destroy SFSB by calling @Remove method, we shoud Remove the @Named and the @SessionScoped annotation on that SFSB.

OTHER TIPS

From documentation :

  • retainIfException: If true, the stateful session bean will not be removed if an exception is thrown from the designated method.

  • At the end of the lifecycle, the client invokes a method annotated @Remove, and the EJB container calls the method annotated @PreDestroy, if any. The bean’s instance is then ready for garbage collection.

Therefore, in case of exception, the bean isn't removed by the container. You can call this method to make it eligible for garbage collection.

@Remove(retainIfException=false)
public void remove() {
    log.info("loginManager removed");
}

Edit: If the application calls the remove() on the instance of a session bean with scope other than @Dependent it would result in UnsupportedOperationException.

Stateful session beans may define a remove method, annotated @Remove, that is used by the application to indicate that an instance should be destroyed. However, for a contextual instance of the bean—an instance under the control of CDI—this method may only be called by the application if the bean has scope @Dependent. For beans with other scopes, the application must let the container destroy the bean.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top