5 Replies Latest reply on Aug 21, 2008 5:56 PM by Dick Starr

    npe when injecting entityManager using PersistenceContext

    Dick Starr Newbie

      When I try to inject entityManager in this stateful session bean the entityManager is null. The only thing different about my component is that it is not linked to any el (unlike the examples).


      The intention of my component is to read some small control tables, hopefully more efficiently than the Seam CRUD Application Framework does. I want this component to return a control table as a List to the calling class. Once I get this version running I will modify it using Generics to read all control files.


      I am running jboss-4.2.2.GA and jboss-seam-2.0.2.SP1. The application was initially generated with Seam Gen.


      Thanks in advance,


      Dick Starr


      Here is my stateful session bean :



      package com.starrcs.action.utilities;
      
      import com.starrcs.action.common.*;
      import com.starrcs.model.system.*;
      import java.util.*;
      import javax.ejb.*;
      import javax.persistence.*;
      import org.jboss.seam.annotations.*;
      
      @Stateful
      @Name("ctrlTable")
      public class CtrlTableAction extends BaseAction implements CtrlTable {
        
        private List<SyCtrlMain> ctrlList;
        @PersistenceContext private EntityManager entityManager;
        
        @Remove
        public void destroy() {
        }
        
        public List<SyCtrlMain> retrieveAllCtrlList() {
          // Why is entityManager null here?
          ctrlList = entityManager.createQuery("select ctrl from SyCtrlMain ctrl").getResultList();
          return ctrlList;
        }
        
      }
      



      Here is the interface:



      package com.starrcs.action.utilities;
      
      import com.starrcs.action.common.*;
      import com.starrcs.model.system.*;
      import java.util.*;
      import javax.ejb.*;
      
      @Local
      public interface CtrlTable extends BaseSessionBean {
        
        // Methods, in alphabetic order
        
        //public void destroy();
        
        public List<SyCtrlMain> retrieveAllCtrlList();
        
      }




      Here is my persistence.xml:


      <?xml version="1.0" encoding="UTF-8"?>
      <!-- Persistence deployment descriptor for dev profile -->
      <persistence xmlns="http://java.sun.com/xml/ns/persistence" 
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" 
                   version="1.0">
                   
         <persistence-unit name="starraSeam">
            <provider>org.hibernate.ejb.HibernatePersistence</provider>
            <jta-data-source>java:/starraSeamDatasource</jta-data-source>
            <properties>
               <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
               <property name="hibernate.hbm2ddl.auto" value="validate"/>
               <property name="hibernate.show_sql" value="true"/>
               <property name="hibernate.format_sql" value="true"/>
               <property name="jboss.entity.manager.factory.jndi.name" value="java:/starraSeamEntityManagerFactory"/>
            </properties>
         </persistence-unit>
          
      </persistence>
      


      Here is my components.xml



      <?xml version="1.0" encoding="UTF-8"?>
      <!-- components.xml
        2008-06-26 RJS. New.
      -->
      <components xmlns="http://jboss.com/products/seam/components"
        xmlns:core="http://jboss.com/products/seam/core"
        xmlns:persistence="http://jboss.com/products/seam/persistence"
        xmlns:drools="http://jboss.com/products/seam/drools"
        xmlns:bpm="http://jboss.com/products/seam/bpm"
        xmlns:security="http://jboss.com/products/seam/security"
        xmlns:mail="http://jboss.com/products/seam/mail"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation=
         "http://jboss.com/products/seam/core http://jboss.com/products/seam/core-2.0.xsd 
         http://jboss.com/products/seam/persistence http://jboss.com/products/seam/persistence-2.0.xsd 
         http://jboss.com/products/seam/drools http://jboss.com/products/seam/drools-2.0.xsd
         http://jboss.com/products/seam/bpm http://jboss.com/products/seam/bpm-2.0.xsd
         http://jboss.com/products/seam/security http://jboss.com/products/seam/security-2.0.xsd
         http://jboss.com/products/seam/mail http://jboss.com/products/seam/mail-2.0.xsd
         http://jboss.com/products/seam/components http://jboss.com/products/seam/components-2.0.xsd">
      
         <core:init debug="@debug@" jndi-pattern="@jndiPattern@"/>
           
         <core:manager concurrent-request-timeout="1000" 
                       conversation-timeout="120000" 
                       conversation-id-parameter="cid"/>
          
         <persistence:managed-persistence-context name="entityManager"
                                           auto-create="true"
                            persistence-unit-jndi-name="java:/starraSeamEntityManagerFactory"/>                          
      
         <drools:rule-base name="securityRules">
             <drools:rule-files>
                 <value>/security.drl</value>
             </drools:rule-files>
         </drools:rule-base>
      
         <security:identity security-rules="#{securityRules}" authenticate-method="#{authenticator.authenticate}" remember-me="true"/>
         
         <event type="org.jboss.seam.security.notLoggedIn">
             <action execute="#{redirect.captureCurrentView}"/>
         </event>
         <event type="org.jboss.seam.security.loginSuccessful">
             <action execute="#{redirect.returnToCapturedView}"/>
         </event>
         
         <mail:mail-session host="localhost" port="2525" username="test" password="test" />
              
         <!-- For use with jBPM pageflow or process management -->
         <!--  
         <bpm:jbpm>
            <bpm:process-definitions></bpm:process-definitions>
            <bpm:pageflow-definitions></bpm:pageflow-definitions>
         </bpm:jbpm>
         -->
         
         <core:resource-loader>
           <core:bundle-names>
             <value>messages</value>
             <value>msgsApp</value>
             <value>msgsMenu</value>
           </core:bundle-names>
         </core:resource-loader>
         
      </components>
      





        • 1. Re: npe when injecting entityManager using PersistenceContext
          Guillaume Jeudy Master

          How do you invoke your component ? From a facelets ? Please provide code sample.

          • 2. Re: npe when injecting entityManager using PersistenceContext
            Dick Starr Newbie

            I am using Facelets and doing a list of a table (I started with the Seam Gen code). It all worked fine until I added code to getMaxResults from a control file. If I comment out the two lines in Utilities referencing ctrlTableAction the list is displayed correctly.


            Here is the list code. Note that getMaxResults() calls utilities.getListRowsPerPage() who in turn calls CtrlTableAction().


            Here is SyOperatorList


            package com.starrcs.action.system.tables;
            
            import com.starrcs.action.utilities.*;
            import com.starrcs.model.system.*;
            import org.jboss.seam.annotations.*;
            import org.jboss.seam.framework.*;
            import java.util.*;
            
            /**
             * SyOperatorList.
             * 
             * @author Dick Starr
             * @version 1.0
             */
            @Name("syOperatorList")
            public class SyOperatorList extends EntityQuery {
              
              private static final String[] RESTRICTIONS = {
               "lower(syOperator.name) like concat(lower(#{syOperatorList.syOperator.name}),'%')",
               "lower(syOperator.logonName) like concat(lower(#{syOperatorList.syOperator.logonName}),'%')",};
              private SyOperator syOperator = new SyOperator();
              private Utilities utilities = new Utilities();
              
              @Override
              public String getEjbql() {
                return "select syOperator from SyOperator syOperator";
              }
              
              @Override
              public Integer getMaxResults() {
                return utilities.getListRowsPerPage();
              }
              
              @Override
              public List<String> getRestrictions() {
                return Arrays.asList(RESTRICTIONS);
              }
              
              public SyOperator getSyOperator() {
                return syOperator;
              }
            
            }
            



            Here is some of Utilities:


            package com.starrcs.action.utilities;
            
            ...
            
            @Name("utilities")
            public class Utilities extends BaseAction {
              
              /**
               * Get list rows per page;
               * for all table lists.
               * 
               * @return listRowsPerPage as int
               */
              public int getListRowsPerPage() {
                // TODO: for each possible Get code: if (x) listRowsPerPage=y return listRowsPerPage
                int listRowsPerPage = Constants.DEFAULT_LIST_ROWS_PER_PAGE;
                // Get from session.
                // Get from SyOperator table.
                // Get from SyCtrlMain table.
                ...
                CtrlTableAction ctrlTableAction = new CtrlTableAction();
                List<SyCtrlMain> blap = ctrlTableAction.retrieveAllCtrlList();
                ...
              }
              
              ...
              }
              


            Class CtrlTableAction is listed above.


            Here is some of SyOperatorList.xhtml:



            <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
              "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
            
            <!-- SyOperatorList.xhtml
              2008-06-23 RJS. New.
            -->
            
            <ui:composition
              xmlns="http://www.w3.org/1999/xhtml"
              xmlns:s="http://jboss.com/products/seam/taglib"
              xmlns:ui="http://java.sun.com/jsf/facelets"
              xmlns:f="http://java.sun.com/jsf/core"
              xmlns:h="http://java.sun.com/jsf/html"
              xmlns:rich="http://richfaces.org/rich"
              template="/layout/template.xhtml">
                                   
            <ui:define name="body">
              
              <h:messages globalOnly="true" styleClass="message" id="globalMessages"/>
                
              <h:form id="syOperatorSearch" styleClass="edit">
                
                <rich:simpleTogglePanel
                  label="#{messages['table.SyOperator']} #{messages['app.search.parameters']}"
                  switchType="ajax">
                  
                  <s:decorate template="/layout/display.xhtml">
                    <ui:define name="label">#{messages['app.Name']}</ui:define>
                    <h:inputText id="name" value="#{syOperatorList.syOperator.name}"/>
                  </s:decorate>
            
                  <s:decorate template="/layout/display.xhtml">
                    <ui:define name="label">#{messages['app.Logon.name']}</ui:define>
                    <h:inputText id="logonName" value="#{syOperatorList.syOperator.logonName}"/>
                  </s:decorate>
                  
                </rich:simpleTogglePanel>
                    
                <div class="actionButtons">
                  <h:commandButton id="search"
                    action="/system/tables/SyOperatorList.xhtml"
                    value="#{messages['button.Search']}"/>
                </div>
                    
              </h:form>
                
              <rich:panel>
                <f:facet name="header">
                  <h:outputFormat value="#{messages['app.search.results']}"
                    rendered="#{!empty syOperatorList.resultList}">
                    <f:param value="#{messages['table.SyOperator']}"/>            
                  </h:outputFormat>
                </f:facet>
                <div class="results" id="syOperatorList">
            
                <h:outputFormat value="#{messages['app.search.no.results']}"
                  rendered="#{empty syOperatorList.resultList}">
                  <f:param value="#{messages['table.SyOperator']}"/>            
                </h:outputFormat>
                           
                <rich:dataTable id="syOperatorList"
                  var="syOperator"
                  value="#{syOperatorList.resultList}" 
                  rendered="#{not empty syOperatorList.resultList}">
                  <h:column>
                    <f:facet name="header">
                      <s:link styleClass="columnHeader"
                        value="syOperatorId #{syOperatorList.order=='syOperatorId asc'
                         ? messages.down : ( syOperatorList.order=='syOperatorId desc'
                         ? messages.up : '' )}">
                        <f:param name="order" value="#{syOperatorList.order=='syOperatorId asc'
                         ? 'syOperatorId desc' : 'syOperatorId asc'}"/>
                      </s:link>
                    </f:facet>
                    #{syOperator.syOperatorId}
                  </h:column>
                  
                  <h:column>
                    <f:facet name="header">
                      <s:link styleClass="columnHeader"
                        value="name #{syOperatorList.order=='name asc'
                         ? messages.down : ( syOperatorList.order=='name desc'
                         ? messages.up : '' )}">
                        <f:param name="order" value="#{syOperatorList.order=='name asc'
                         ? 'name desc' : 'name asc'}"/>
                      </s:link>
                    </f:facet>
                    #{syOperator.name}
                  </h:column>
                  
                  ...
                  
                  <h:column>
                    <f:facet name="header">action</f:facet>
                      <s:link view="/system/tables/#{empty from
                       ? 'SyOperator' : from}.xhtml" 
                        value="Select" 
                        id="syOperator">
                        <f:param name="syOperatorSyOperatorId" 
                          value="#{syOperator.syOperatorId}"/>
                      </s:link>
                  </h:column>
                </rich:dataTable>
            
                </div>
              </rich:panel>
              
              <div class="tableControl">
                
                <s:link view="/system/tables/SyOperatorList.xhtml"
                  rendered="#{syOperatorList.previousExists}" 
                  value="#{messages.left}#{messages.left} #{messages['link.First.Page']}"
                  id="firstPage">
                  <f:param name="firstResult" value="0"/>
                </s:link>
                    
                ...
                    
              </div>
                
              <s:div styleClass="actionButtons" rendered="#{empty from}">
                <s:button view="/system/tables/SyOperatorEdit.xhtml"
                  id="create" 
                  value="#{messages['button.Create']} #{messages['table.SyOperator']}">
                  <f:param name="syOperatorSyOperatorId"/>
                </s:button>
              </s:div>
                
            </ui:define>
            
            </ui:composition>
            
            





            • 3. Re: npe when injecting entityManager using PersistenceContext
              Guillaume Jeudy Master
              @PersistenceContext

              annotation is only useful when retrieving your bean as a managed entity (either by seam or EJB). In this case it's the EJB container (jboss) that will inject the entityManager for you. If you start instantiating the beans yourself none of the dependency injection goodness will happen as this is handled by your container (seam or ejb).


              I suggest you read more Seam reference doc. Trying replacing:


              private Utilities utilities = new Utilities();



              with


              @In(create=true)
              private Utilities utilities;



              do the same in Utility class with:


              @In(create=true)
              CtrlTableAction ctrlTableAction;



              You can use

              @AutoCreate

              at the class level instead of adding
              create=true

              in the In annotation. By doing it this way you let Seam manage the lifecycle of these components. In the case of CtrlTableAction it is an EJB so Seam retrieves the EJB from the EJB container which has injected the entityManager bound to the PersistenceContext annotation.

              • 5. Re: npe when injecting entityManager using PersistenceContext
                Dick Starr Newbie

                Sorry for the delay in my reply, as I got sidetracked for a few days.


                Guillaume, thank you for getting me started down the right track. I did read more and soon realized that I was bypassing dependency injection by instantiating the beans myself.


                The working code follows:



                package com.starrcs.action.common;
                
                public interface BaseSessionBean {
                
                  public void destroy();  
                }
                




                package com.starrcs.action.common;
                
                import javax.ejb.*;
                
                public class BaseSessionBeanImpl {  
                
                  public BaseSessionBeanImpl() {
                  }
                 
                  @Remove
                  public void destroy() {
                  }  
                }
                




                package com.starrcs.action.utilities;
                
                import com.starrcs.action.common.*;
                import com.starrcs.model.system.*;
                import java.util.*;
                import javax.ejb.*;
                
                @Local
                public interface CtrlTable extends BaseSessionBean {
                   
                  public List<SyCtrlMain> retrieveAllCtrlList();  
                }
                




                package com.starrcs.action.utilities;
                
                import com.starrcs.action.common.*;
                import com.starrcs.model.system.*;
                import java.util.*;
                import javax.ejb.*;
                import javax.persistence.*;
                import org.jboss.seam.annotations.*;
                
                @Stateless
                @Name("ctrlTable")
                public class CtrlTableImpl extends BaseSessionBeanImpl implements CtrlTable {
                  
                  private List<SyCtrlMain> ctrlList;
                  @PersistenceContext private EntityManager entityManager;
                  
                  public CtrlTableImpl() {
                  }
                  
                  public List<SyCtrlMain> retrieveAllCtrlList() {
                    ctrlList = entityManager.createQuery("select ctrl from SyCtrlMain ctrl").getResultList();
                    return ctrlList;
                  }  
                }
                




                package com.starrcs.action.utilities;
                
                import com.starrcs.action.common.*;
                import com.starrcs.model.system.*;
                import java.util.*;
                import javax.ejb.*;
                
                @Local
                public interface Utilities extends BaseSessionBean {
                 
                  public int getListRowsPerPage();
                ...  
                }



                In an earlier version of Utilities I had a bug in the line private CtrlTable ctrlTable in that I used the instance Class name instead of the interface class name CtrlTable. It gave an error that made no sense to me, but i found a solution from Gavin King here. Also in this link Gavin recommends the implementation/interface naming standards that I used.


                package com.starrcs.action.utilities;
                
                import com.starrcs.action.common.*;
                import com.starrcs.model.system.*;
                import java.text.*;
                import java.util.*;
                import java.util.logging.Level;
                import javax.ejb.*;
                import org.jboss.seam.ScopeType;
                import org.jboss.seam.annotations.*;
                
                @Stateless
                @Name("utilities")
                public class UtilitiesImpl extends BaseSessionBeanImpl implements Utilities {
                  
                  @In(create=true)
                  private CtrlTable ctrlTable;
                 
                  public UtilitiesImpl() {
                  }
                
                  /**
                   * Get list rows per page;
                   * for all table lists.
                   * 
                   * @return listRowsPerPage as int
                   */
                  public int getListRowsPerPage() {
                    // TODO: for each possible Get code: if (x) listRowsPerPage=y return listRowsPerPage
                    int listRowsPerPage = Constants.DEFAULT_LIST_ROWS_PER_PAGE;
                    // Get from session.
                    // Get from SyOperator table.
                    // Get from SyCtrlMain table.
                    List<SyCtrlMain> ctrlList = ctrlTable.retrieveAllCtrlList();
                    if (ctrlList.size() == 1) {
                      SyCtrlMain syCtrlMain = ctrlList.get(0);
                      listRowsPerPage = syCtrlMain.getListRowsPerPage();
                      return getListRowsPerPageEdit(listRowsPerPage);
                    }   
                    return getListRowsPerPageEdit(listRowsPerPage);
                  }
                  
                  private int getListRowsPerPageEdit(int listRowsPerPage) {    
                    if (listRowsPerPage < 1) {
                      listRowsPerPage = Constants.DEFAULT_LIST_ROWS_PER_PAGE;
                    }
                    return listRowsPerPage;
                  }
                  ...  
                }
                




                package com.starrcs.action.system.tables;
                
                import com.starrcs.action.utilities.*;
                import com.starrcs.model.system.*;
                import org.jboss.seam.annotations.*;
                import org.jboss.seam.framework.*;
                import java.util.*;
                
                @Name("syOperatorList")
                public class SyOperatorList extends EntityQuery {
                  
                  private static final String[] RESTRICTIONS = {
                   "lower(syOperator.name) like concat(lower(#{syOperatorList.syOperator.name}),'%')",
                   "lower(syOperator.logonName) like concat(lower(#{syOperatorList.syOperator.logonName}),'%')",};
                  private SyOperator syOperator = new SyOperator();
                  
                  @In(create=true)
                  private Utilities utilities;
                
                  public SyOperatorList() {
                  }
                  
                  @Override
                  public String getEjbql() {
                    return "select syOperator from SyOperator syOperator";
                  }
                  
                  @Override
                  public Integer getMaxResults() {
                    return utilities.getListRowsPerPage();
                  }
                  
                  @Override
                  public List<String> getRestrictions() {
                    return Arrays.asList(RESTRICTIONS);
                  }
                  
                  public SyOperator getSyOperator() {
                    return syOperator;
                  }
                }