5 Replies Latest reply on Nov 28, 2012 10:45 AM by pczekaj

    javax.ejb.NoSuchEJBException: JBAS016055: EJB has been removed

    pczekaj

      I'm getting exception "javax.ejb.NoSuchEJBException: JBAS016055: EJB has been removed" when using JBoss 7.1.3 with Weld 1.1.9 or Weld 1.1.10 in web app. It happens after there is some runtime exception in one of my stateful ejb beans. Until user will create new session (for example by closing web browser and opening it once again) he cannot use application at all because each request ends with "javax.ejb.NoSuchEJBException: JBAS016055: EJB has been removed". What's strange is that exceptions seems to be caused by logging code in Weld. Below is how to replicate my problem and exception that I'm constantly getting. Is it know problem? Is there a workaround other than "don't throw exceptions in stateful beans"?

       

      facelets page:

      <h:form>
      <h:commandButton value="doIllegalStateException" action="#{exceptionGenerator.doIllegalStateException()}" />
      </h:form>
      
      
      

       

      bean:

      package org.jboss.tools.examples.controller;
        
      import java.io.Serializable;
      import javax.ejb.Stateful;
      import javax.enterprise.context.SessionScoped;
      import javax.inject.Named;
        
      @Stateful
      @Named
      @SessionScoped
      public class ExceptionGenerator implements Serializable { 
        
                public void doIllegalStateException() {
                          throw new IllegalStateException("Test Exception");
                }
      }
      
      exception stack trace:
      
      15:04:20,035 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host]] (http-localhost/127.0.0.1:8080-4) Exception sending request initialized lifecycle event to listener instance of class org.jboss.weld.servlet.WeldListener: javax.ejb.NoSuchEJBException: JBAS016055: EJB has been removed
                at org.jboss.as.weld.ejb.StatefulSessionObjectReferenceImpl.getBusinessObject(StatefulSessionObjectReferenceImpl.java:124) [jboss-as-weld-7.1.3.Final.jar:7.1.3.Final]
                at org.jboss.weld.bean.proxy.EnterpriseBeanProxyMethodHandler.invoke(EnterpriseBeanProxyMethodHandler.java:108) [weld-core-1.1.9.Final.jar:2012-08-06 19:12]
                at org.jboss.weld.bean.proxy.EnterpriseTargetBeanInstance.invoke(EnterpriseTargetBeanInstance.java:56) [weld-core-1.1.9.Final.jar:2012-08-06 19:12]
                at org.jboss.weld.bean.proxy.ProxyMethodHandler.invoke(ProxyMethodHandler.java:105) [weld-core-1.1.9.Final.jar:2012-08-06 19:12]
                at org.jboss.tools.examples.controller.ExceptionGenerator$Proxy$_$$_Weld$Proxy$.toString(ExceptionGenerator$Proxy$_$$_Weld$Proxy$.java) [classes:]
                at java.lang.String.valueOf(String.java:2826) [rt.jar:1.6.0_35]
                at java.lang.StringBuilder.append(StringBuilder.java:115) [rt.jar:1.6.0_35]
                at org.jboss.weld.context.SerializableContextualInstanceImpl.toString(SerializableContextualInstanceImpl.java:60) [weld-core-1.1.9.Final.jar:2012-08-06 19:12]
                at java.lang.String.valueOf(String.java:2826) [rt.jar:1.6.0_35]
                at java.lang.StringBuilder.append(StringBuilder.java:115) [rt.jar:1.6.0_35]
                at org.jboss.weld.context.beanstore.AttributeBeanStore.attach(AttributeBeanStore.java:109) [weld-core-1.1.9.Final.jar:2012-08-06 19:12]
                at org.jboss.weld.context.AbstractBoundContext.activate(AbstractBoundContext.java:66) [weld-core-1.1.9.Final.jar:2012-08-06 19:12]
                at org.jboss.weld.servlet.WeldListener.requestInitialized(WeldListener.java:141) [weld-core-1.1.9.Final.jar:2012-08-06 19:12]
                at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) [jbossweb-7.0.17.Final.jar:]
                at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.17.Final.jar:]
                at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.17.Final.jar:]
                at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:372) [jbossweb-7.0.17.Final.jar:]
                at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [jbossweb-7.0.17.Final.jar:]
                at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:679) [jbossweb-7.0.17.Final.jar:]
                at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:931) [jbossweb-7.0.17.Final.jar:]
                at java.lang.Thread.run(Thread.java:662) [rt.jar:1.6.0_35]
      
      
      

       

      exception occurs within AttributeBeanStore.java at line on log.trace:

       

                  /*
                  * Additionally copy anything not in the bean store but in the session
                  * into the bean store
                  */
                  for (String prefixedId : getPrefixedAttributeNames()) {
                      String id = getNamingScheme().deprefix(prefixedId);
                      if (!beanStore.contains(id)) {
                          ContextualInstance<?> instance = (ContextualInstance<?>) getAttribute(prefixedId);
                          beanStore.put(id, instance);
                          log.trace("Adding detached contextual " + instance + " under ID " + id);
                      }
                  }
      
      

       

      btw. I think it would be better if logging statements in Weld wouldn't use string concatenation because currently no matter what logging level is selected message is always constructed which might be bad for performance reasons

        • 1. Re: javax.ejb.NoSuchEJBException: JBAS016055: EJB has been removed
          luksa

          Piotr, thanks for pointing out the trace string concatenation thing. I've wrapped them with isTraceEnabled(). You can try my branch at https://github.com/luksa/weld-core/tree/trace_opti

           

          When a stateful bean throws a system exception, the bean is always removed. So all subsequent calls to the bean's methods will then throw a NoSuchEJBException. This is perfectly ok if it happens when client code is invoking the methods. Of course it's not ok that weld is the one invoking these methods for every request and not handling the exception appropriately. We'll need to see what we can do about this.

           

          Can you try my branch? I'm interested in seeing if there are any other places where Weld invokes methods of the EJB.

          • 2. Re: javax.ejb.NoSuchEJBException: JBAS016055: EJB has been removed
            pczekaj

            Marko, thank you very much for investigating this issue. I wasn't able to directly use your branch because it's based on Weld 1.1.5 or 1.1.6 which isn't compatibile with jboss as <-> Weld integration present in JBoss 7.1.3. Anyway, I took sources of Weld 1.1.10 and applied there your changes and exception is gone for ExceptionGenerator class that I put in my first post. Still, it will fail if ExceptionGenerator class has some extra field which is then used on facelets page. To make things easier I've put my exception tester app on https://github.com/pczekaj/exception-tester

             

             

            package org.jboss.tools.examples.controller;
            
            
            import java.io.Serializable;
            import java.util.Date;
            
            
            import javax.annotation.PostConstruct;
            import javax.ejb.Stateful;
            import javax.enterprise.context.SessionScoped;
            import javax.inject.Named;
            
            
            @Stateful
            @Named
            @SessionScoped
            public class ExceptionGenerator implements Serializable { 
            
                      private Date constructedAt;
            
                      @PostConstruct
                      public void init() {
                                constructedAt = new Date();
                                System.err.println("ExceptionGenerator @PostConstruct");
                      }
            
                      public void doIllegalStateException() {
                                throw new IllegalStateException("Test Exception");
                      }
            
                      public Date getConstructedAt() {
                                return constructedAt;
                      }
            }
            

             

            package org.jboss.tools.examples.controller;
            
            
            import java.util.Date;
            
            
            import javax.ejb.Stateless;
            import javax.inject.Named;
            
            
            @Stateless
            @Named
            public class CurrentDateProducer {
                      public Date getCurrentDate() {
                                return new Date();
                      }
            }
            

             

            page:

             

            <?xml version="1.0" encoding="UTF-8"?>
            <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
                "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
            <html xmlns="http://www.w3.org/1999/xhtml"
               xmlns:h="http://java.sun.com/jsf/html"
               xmlns:ui="http://java.sun.com/jsf/facelets">
            <h:head>
               <title>Exception tester</title>
               <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
            </h:head>
            <h:body>
                         <h:form>
                                <h:outputText value="exceptionGenerator created at: #{exceptionGenerator.constructedAt}" />
                                <h:commandButton value="doIllegalStateException" action="#{exceptionGenerator.doIllegalStateException()}" />
                      </h:form>
            
                      <h:outputText value="Current time: #{currentDateProducer.currentDate}" /> 
            </h:body>
            </html>
            

             

            I checked my sample app on JBoss 7.1.1 and it works better, there is no 'javax.ejb.NoSuchEJBException: JBAS016055: EJB has been removed'. But I'm not sure if it works correctly. When I load a page for the first time (or after session has expired) I can see sth similiar to:

             

            exceptionGenerator created at: Fri Oct 26 11:05:43 CEST 2012

            Current time: Fri Oct 26 11:05:43 CEST 2012

             

            After causing exception in ExceptionGenerator class and opening page once again I can see:

             

            exceptionGenerator created at:

            Current time: Fri Oct 26 11:06:59 CEST 2012

             

            so it looks like that new instance ExceptionGenerator class wasn't created and Weld is trying to access one which has been removed, in JBoss 7.1.1 it doesn't throw exception here. I don't know how CDI standard defines how should it behave in such situation but for me it should create new instance of ExceptionGenerator.

             

            In JBoss 7.1.3 and Weld 1.1.10 patched the same way as Marko's version (log.isTraceEnabled()) it behaves differently, after causing exception in ExceptionGenerator each new request to open page when that bean is used causes:

             

            11:18:59,568 SEVERE [javax.enterprise.resource.webcontainer.jsf.application] (http-localhost/127.0.0.1:8080-2) Error Rendering View[/index.xhtml]: javax.el.ELException: /index.xhtml @13,94 value="exceptionGenerator created at: #{exceptionGenerator.constructedAt}": javax.ejb.NoSuchEJBException: JBAS016055: EJB has been removed
                      at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:114) [jsf-impl-2.1.11-jbossorg-3.jar:]
                      at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:194) [jboss-jsf-api_2.1_spec-2.0.4.Final.jar:2.0.4.Final]
                      at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:182) [jboss-jsf-api_2.1_spec-2.0.4.Final.jar:2.0.4.Final]
                      at javax.faces.component.UIOutput.getValue(UIOutput.java:169) [jboss-jsf-api_2.1_spec-2.0.4.Final.jar:2.0.4.Final]
                      at com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer.getValue(HtmlBasicInputRenderer.java:205) [jsf-impl-2.1.11-jbossorg-3.jar:]
                      at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.getCurrentValue(HtmlBasicRenderer.java:355) [jsf-impl-2.1.11-jbossorg-3.jar:]
                      at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeEnd(HtmlBasicRenderer.java:164) [jsf-impl-2.1.11-jbossorg-3.jar:]
                      at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:875) [jboss-jsf-api_2.1_spec-2.0.4.Final.jar:2.0.4.Final]
                      at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1786) [jboss-jsf-api_2.1_spec-2.0.4.Final.jar:2.0.4.Final]
                      at javax.faces.render.Renderer.encodeChildren(Renderer.java:168) [jboss-jsf-api_2.1_spec-2.0.4.Final.jar:2.0.4.Final]
                      at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:845) [jboss-jsf-api_2.1_spec-2.0.4.Final.jar:2.0.4.Final]
                      at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1779) [jboss-jsf-api_2.1_spec-2.0.4.Final.jar:2.0.4.Final]
                      at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1782) [jboss-jsf-api_2.1_spec-2.0.4.Final.jar:2.0.4.Final]
                      at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1782) [jboss-jsf-api_2.1_spec-2.0.4.Final.jar:2.0.4.Final]
                      at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:424) [jsf-impl-2.1.11-jbossorg-3.jar:]
                      at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:125) [jsf-impl-2.1.11-jbossorg-3.jar:]
                      at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:288) [jboss-jsf-api_2.1_spec-2.0.4.Final.jar:2.0.4.Final]
                      at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:121) [jsf-impl-2.1.11-jbossorg-3.jar:]
                      at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) [jsf-impl-2.1.11-jbossorg-3.jar:]
                      at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139) [jsf-impl-2.1.11-jbossorg-3.jar:]
                      at javax.faces.webapp.FacesServlet.service(FacesServlet.java:594) [jboss-jsf-api_2.1_spec-2.0.4.Final.jar:2.0.4.Final]
                      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329) [jbossweb-7.0.17.Final.jar:]
                      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.17.Final.jar:]
                      at org.jboss.weld.servlet.ConversationPropagationFilter.doFilter(ConversationPropagationFilter.java:62) [weld-core-1.1.10.Final.jar:2012-10-26 09:53]
                      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280) [jbossweb-7.0.17.Final.jar:]
                      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.17.Final.jar:]
                      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) [jbossweb-7.0.17.Final.jar:]
                      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161) [jbossweb-7.0.17.Final.jar:]
                      at org.jboss.as.jpa.interceptor.WebNonTxEmCloserValve.invoke(WebNonTxEmCloserValve.java:50) [jboss-as-jpa-7.1.3.Final.jar:7.1.3.Final]
                      at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:165) [jboss-as-web-7.1.3.Final.jar:7.1.3.Final]
                      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155) [jbossweb-7.0.17.Final.jar:]
                      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.17.Final.jar:]
                      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.17.Final.jar:]
                      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:372) [jbossweb-7.0.17.Final.jar:]
                      at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [jbossweb-7.0.17.Final.jar:]
                      at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:679) [jbossweb-7.0.17.Final.jar:]
                      at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:931) [jbossweb-7.0.17.Final.jar:]
                      at java.lang.Thread.run(Thread.java:662) [rt.jar:1.6.0_35]
            Caused by: javax.ejb.NoSuchEJBException: JBAS016055: EJB has been removed
                      at org.jboss.as.weld.ejb.StatefulSessionObjectReferenceImpl.getBusinessObject(StatefulSessionObjectReferenceImpl.java:124) [jboss-as-weld-7.1.3.Final.jar:7.1.3.Final]
                      at org.jboss.weld.bean.proxy.EnterpriseBeanProxyMethodHandler.invoke(EnterpriseBeanProxyMethodHandler.java:109) [weld-core-1.1.10.Final.jar:2012-10-26 09:53]
                      at org.jboss.weld.bean.proxy.EnterpriseTargetBeanInstance.invoke(EnterpriseTargetBeanInstance.java:56) [weld-core-1.1.10.Final.jar:2012-10-26 09:53]
                      at org.jboss.weld.bean.proxy.ProxyMethodHandler.invoke(ProxyMethodHandler.java:105) [weld-core-1.1.10.Final.jar:2012-10-26 09:53]
                      at org.jboss.tools.examples.controller.ExceptionGenerator$Proxy$_$$_Weld$Proxy$.getConstructedAt(ExceptionGenerator$Proxy$_$$_Weld$Proxy$.java) [classes:]
                      at org.jboss.tools.examples.controller.ExceptionGenerator$Proxy$_$$_WeldClientProxy.getConstructedAt(ExceptionGenerator$Proxy$_$$_WeldClientProxy.java) [classes:]
                      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.6.0_35]
                      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [rt.jar:1.6.0_35]
                      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [rt.jar:1.6.0_35]
                      at java.lang.reflect.Method.invoke(Method.java:597) [rt.jar:1.6.0_35]
                      at javax.el.BeanELResolver.getValue(BeanELResolver.java:302) [jboss-el-api_2.2_spec-1.0.2.Final.jar:1.0.2.Final]
                      at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:176) [jsf-impl-2.1.11-jbossorg-3.jar:]
                      at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:203) [jsf-impl-2.1.11-jbossorg-3.jar:]
                      at org.apache.el.parser.AstValue.getValue(AstValue.java:169) [jbossweb-7.0.17.Final.jar:]
                      at org.apache.el.parser.AstDeferredExpression.getValue(AstDeferredExpression.java:44) [jbossweb-7.0.17.Final.jar:]
                      at org.apache.el.parser.AstCompositeExpression.getValue(AstCompositeExpression.java:50) [jbossweb-7.0.17.Final.jar:]
                      at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:189) [jbossweb-7.0.17.Final.jar:]
                      at org.jboss.weld.el.WeldValueExpression.getValue(WeldValueExpression.java:50) [weld-core-1.1.10.Final.jar:2012-10-26 09:53]
                      at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109) [jsf-impl-2.1.11-jbossorg-3.jar:]
                      ... 37 more
            

             

            Maybe it would be worthwhile to look at org.jboss.as.weld.ejb.StatefulSessionObjectReferenceImpl, one of recent commits (29/04/2012) to it states:

             

            SHA-1: d4315547ccca3a95e49eac4dcdab959b4cf68623
             * Add proper SFSB removal checking for Weld
            
            • 3. Re: javax.ejb.NoSuchEJBException: JBAS016055: EJB has been removed
              maschmid

              I don't know how CDI standard defines how should it behave in such situation but for me it should create new instance of ExceptionGenerator.

               

              I couldn't find any statement in the CDI spec supporting that it should do that. IMHO it would not be a good idea, as it could put the application into an unexpected state, as some SFSB would silently reset into their initial state in the middle of some kind of a workflow. (It would make sense only if it invalidated the whole session)

              • 4. Re: javax.ejb.NoSuchEJBException: JBAS016055: EJB has been removed
                jharting

                I don't think either that CDI should go and get a new SFSB instance in that case. This needs clarification, though. In CDI 1.1 we introduced the contept of AlterableContext where you can relese resources by destroying an existing normal-scoped instance. A new one will be recreated on demand again.

                 

                That means that after getting the exception your code would be responsible for calling SessionContext.destroy(instance). Afterwards, it would get a new instance of the SFSB. This is explicit and does not lead to surprises where your code suddently works with a different instance.

                • 5. Re: javax.ejb.NoSuchEJBException: JBAS016055: EJB has been removed
                  pczekaj

                  I can confirm that snapshot of weld 1.11 running on JBoss 7.1.3 doesn't have a problem described in my first post in this thread. Thank you very much for fixing it.

                   

                  Invalidating whole session would be nice feature, probably better than creating new instance of removed bean because of runtime excepion and that's what I usually do when programming in dot net. I've wrote about creating new instance in such situation because if I'm correct currently it also puts application is strange state: maybe facelet page will render but some parts might be missing, for example normally page contains:

                   

                  exceptionGenerator created at: Fri Oct 26 11:05:43 CEST 2012
                  Current time: Fri Oct 26 11:05:43 CEST 2012
                  

                   

                  Same page after exception:

                   

                  exceptionGenerator created at:
                  Current time: Fri Oct 26 11:06:59 CEST 2012
                  

                   

                  That facelets page wouldn't even render if it would try to access something that cannot be null (like int). What's more if I would inject somewhere class that has been removed because of exception then that new bean would stop working because of NullPointerException. Had one bean not working, now have 2 of them and it can continue that way...

                   

                  What's the best practice in CDI to handle such unexpected runtime exceptions?