7 Replies Latest reply on May 28, 2009 8:09 PM by cdunphy

    Error injecting EntityManager in Seam session component on Glassfish

      Hello,


      First, some information about my environment:





      • Seam 2.1.2.CR2





      • Glassfish 2.1





      • Windows XP SP3 32-bit





      I am working on a Seam session component that I can use to authenticate users to our AD controllers... here is the component I am trying to define:


      @Stateless
      @Name("authenticator")
      public class AuthenticatorBean implements Authenticator {
      
           @Logger
           private Log log;
           @In
           private EntityManager entityManager;
      
           @In
           private Identity identity;
           @In
           private Credentials credentials;
      
           @In(create = true)
           private ActiveDirectoryController domain1ADPrimary;
           @In(create = true)
           private ActiveDirectoryController domain2ADBackup;
      
           @In(create = true)
           private ActiveDirectoryController domain2ADPrimary;
           @In(create = true)
           private ActiveDirectoryController domain2ADBackup;
      
           @Out(scope = ScopeType.SESSION)
           private User currentUser;
      
           // Here we inject the domain we want to use
           @RequestParameter
           private String domain;
      
           @Override
           public boolean authenticate() {
      
                currentUser = (User) entityManager.createQuery("select u from User u where u.username = :username")
                                           .setParameter(0, credentials.getUsername())
                                           .getSingleResult();
      
                if (currentUser == null) {
                     log.error("User " + credentials.getUsername() 
                                 + " exists in AD but is not authorized to use this application.");
                     return false;
                }
      
                Map<String, Object> userMap = null;
                if (domain.equals(domain1ADPrimary.getDomain())) {
                        // Login using domain1 AD Controllers
                } else if (domain.equals(domain2ADPrimary.getDomain())) {
                     // Login using domain2 AD Controllers
                } else {
                     log.error("ERROR: You must specify an NT domain.");
                     return false;
                }
      
                identity.addRole(currentUser.getTeam().getLabel());
                log.error("Authentication succeeded for user "
                          + credentials.getUsername());
                return true;
           }
      }



      The applications starts and I can navigate through the CRUD pages that were made by seam-gen.  The problem is that I am getting an Exception when I try to call this authenticate method on the authenticator component:


      Caused by: javax.ejb.TransactionRolledbackLocalException: Exception thrown from bean; nested exception is: java.lang.IllegalArgumentException: EntityManagerFactory not found in JNDI : java:comp/env/mnt/pu


      This is strange for a few reasons.  First of all, the CRUD pages that I generated from my Entity classes using the Seam Application Framework are all working just fine.


      Here is the relevant persistence section of my components.xml file:



      <persistence:managed-persistence-context
                name="entityManager" persistence-unit-jndi-name="@puJndiName@"
                auto-create="true" />



      And the security portion:



      <security:identity authenticate-method="#{authenticator.authenticate}"
                remember-me="true" />




      Here is the persistence unit:


      <persistence-unit name="mnt">
           <provider>org.hibernate.ejb.HibernatePersistence</provider>
           <jta-data-source>mntDatasource</jta-data-source>
           <jar-file>../../mnt.jar</jar-file>
           <properties>
                <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
                <property name="hibernate.hbm2ddl.auto" value="update" />
                <property name="hibernate.show_sql" value="true" />
                <property name="hibernate.format_sql" value="true" />
                <property name="hibernate.default_catalog" value="mnt" />
           </properties>
      </persistence-unit>



      When I check the exploded EAR file, it looks like it is setting the property correctly in C:\Projects\mnt\exploded-archives\mnt.ear\mnt_war\WEB-INF\classes\components.properties):




      # These properties are used to replace Ant-style tokens in the component descriptor (components.xml) at runtime.
      jndiPattern=java:comp/env/mnt/#{ejbName}/local
      debug=true
      seamBootstrapsPu=false
      seamEmfRef=#{null}
      puJndiName=java:comp/env/mnt/pu




      Does the fact that the CRUD classes are working, despite the fact the Home classes are JavaBean components, mean anything?  Or could my persistence configuration for glassfish be working for JavaBean components but not EJB components?  Or could there be something else going on that could be breaking the injection of the entityManager for this component?


      Thanks!


      // Chris

        • 1. Re: Error injecting EntityManager in Seam session component on Glassfish
          arshadm
          Hi,

          Did you include a reference to your persistence unit in web.xml. This is required because Glassfish is JEE5 compliant and that is the (stupid) way you have to do things.

          You need something like this in your web.xml

              <!--  persistence unit -->
              <persistence-unit-ref>
                 <persistence-unit-ref-name>myEntityManagerFactory</persistence-unit-ref-name>
                 <persistence-unit-name>myPersistenceUnit</persistence-unit-name>
              </persistence-unit-ref>

          Your app can then get at the entity manager factory under java:comp/env/myEntityManagerFactory. Also don't forget that you have to reference all your EJB's in the web.xml as well.

          MY own experience with EJB on Glassfish has not been good. To do things in a JEE5 compliant way you have to write a hell of a lot of XML to hook all the EJB's and the entityManager together. That's why I dropped EJB and went back to basic Seam components (I don't need the clustering et al at the moment).

          JEE6 should fix most of these problem (due out around October, I think). At which point I'll convert everything back to EJB.

          Regards.
          • 2. Re: Error injecting EntityManager in Seam session component on Glassfish

            Hello there,


            I did include that reference:



            <persistence-unit-ref>
                      <persistence-unit-ref-name>mnt/pu</persistence-unit-ref-name>
                      <persistence-unit-name>mnt</persistence-unit-name>
            </persistence-unit-ref>



            When I try to use container managed persistence, I get another error:




            @PersistenceContext(unitName = "mnt")
                 private EntityManager entityManager;




            Error:



            CLI171 Command deploy failed : Deploying application in domain failed; Could not resolve a persistence unit corresponding to the persistence-context-ref-name [ca.shaw.ops.entmgt.mnt.action.AuthenticatorBean/entityManager] in the scope of the module called []. Please verify your application.



            I'm missing something...


            // Chris

            • 3. Re: Error injecting EntityManager in Seam session component on Glassfish
              arshadm

              Hi,


              Where did you put the jar that contains META-INF/persistence.xml. If you are building an EAR project then it MUST be in the lib folder of the EAR.


              Regards.

              • 4. Re: Error injecting EntityManager in Seam session component on Glassfish

                I think I might have found a problem with the Glassfish ant (glassfish-build.xml) script that is used by seam-gen Seam 2.1.2.CR2:




                <target name="gf-cleanup-ear" if="project.ear">
                        <move todir="${war.dir}/WEB-INF/classes">
                            <fileset dir="${jar.dir}">
                                <include name="META-INF/orm.xml" if="project.ear"/>
                                <include name="META-INF/persistence.xml" if="project.ear"/>
                            </fileset>
                        </move>
                </target>




                It is moving META-INF/orm.xml and META-INF/persistence.xml to /WEB-INF/classes/META-INF directory in the WAR.  Shouldn't these files be in the EJB-JAR file instead for an EAR project?

                • 5. Re: Error injecting EntityManager in Seam session component on Glassfish
                  arshadm

                  Hi,


                  Yes, the persistence.xml for an EAR project should be in either an EJB-JAR or more flexilby in a JAR file in the lib folder.


                  Regards.

                  • 6. Re: Error injecting EntityManager in Seam session component on Glassfish

                    Hmmm,


                    if I leave the persistence.xml file in EJB-JAR/META-INF deployment fails:




                    [exec] CLI171 Command deploy failed : Deploying application in domain failed; Could not resolve a persistence unit corresponding to the persistence-unit-ref-name [mnt/pu] in scope of the module called []. Please verify your application





                    If I change it back so that the persistence.xml file goes into WAR/WEB-INF/classes/META-INF it deploys, but I am back to getting:




                    Caused by: javax.ejb.TransactionRolledbackLocalException: Exception thrown from
                    bean; nested exception is: java.lang.IllegalArgumentException: EntityManagerFact
                    ory not found in JNDI : java:comp/env/mnt/pu




                    I'm pretty much at trial and error at this point... I did fix a stupid unrelated bug in the AuthenticatorBean class where I was using a numbered parameter instead of a named parameter when I execute the query against the EntityManager, but that wasn't it either.

                    • 7. Re: Error injecting EntityManager in Seam session component on Glassfish

                      Hello all,


                      So I am still struggling with this issue.  A couple of things about seam-gen (Seam 2.1.2.CR2) for Glassfish that I don't understand.





                      • Why does the persistence.xml file get moved into project_war/WEB-INF/classes/META-INF for an EAR based project under Glassfish??  Why not keep it in project_ejb_jar/META-INF?  Is this why the persistence unit is not working inside session beans?  How can I work around this problem?






                      • No matter what i try, I can't seem to access the EntityManager from an EJB based session bean Seam component.  This is despite the fact that the seam-gen created CRUD pages for my entities are working.  It is when I try to call the method on the session bean for authentication that it complains about not being able to find the EntityManager in JNDI.





                      Has anyone out there gotten this to work on Glassfish using seam-gen based projects for Seam 2.1.2.CR2) ??  I'd love to hear what I am doing wrong.


                      If I can get past this hurdle I'll be off to the races on this application...


                      Thanks,
                      // Chris