persistence@glassfish.java.net

Re: EJB and JSF: Entity Manager not injecting on Sun AS9PE

From: John Fagan <John.Fagan_at_clarisource.com>
Date: Tue, 16 May 2006 11:32:50 -0400

Hi Sahoo,

Thanks very much for the reply. I'll try what you suggest.

I originally had an interface and after hundreds of permutations, I took it out. I understood that the interface was created for you by the server, or perhaps this is only for the remote interface and not the local interface?

According to the Java EE 5 Tutorial:

"Unfortunately for the web application developer, resource injection using annotations can only be used with classes that are managed by a Java EE compliant container. Because the web container does not manage JavaBeans components, you cannot inject resources into them. One exception is a JavaServer Faces managed bean. These beans are managed by the container and therefore support resource injection. This is only helpful if your application is a JavaServer Faces application."

So, according to this, if I am reading it right, JSF applications can use container managed beans? Maybe this is just bad documentation? I expected that my annotations for PersistenceContext would work based on this statement.

For me, a bug is that the EntityManger will not inject with JSF managed beans (either a verifier bug, server bug or documentation bug). Maybe, the verifier not catching the missing local interface is a bug, too. I'll file a bug report, as you suggested.

Take care,
John

John Fagan, CCP, SCJP, ACP
John.Fagan_at_clarisource.com
http://www.clarisource.com
  ----- Original Message -----
  From: Sanjeeb Kumar Sahoo
  To: persistence_at_glassfish.dev.java.net
  Sent: Tuesday, May 16, 2006 12:43 AM
  Subject: Re: EJB and JSF: Entity Manager not injecting on Sun AS9PE


  Hi,

  I think there two problems. One with the ejb and another with the faces-config.xml.

  1. The problem is that your EJB does not have any interface. You just annotated it as @Local, but since UserSessionBean does not implement any interface, there is no way to know what is the local business interface. It should have been caught during verification, but that looks like a bug. Please file an issue for that.

  One way to fix your EJB is to:
  @Stateful
  @Local
  public class UserSessionBean implements UserSessionBeanInterface{
     // everything remains same here
  }

  public interface UserSessionBeanInterface {
     // all the methods that you want to expose as business methods go here: e.g.
     String getName();
     void setName(String name);
     String newStudent();
  }

  Package this interface into ejb-jar along with other classes.

  2. I don't know much about JSF, but I think <managed-bean> element can't be used to directly refer to this bean class. I think, you should write another JavaBean like this:

  // a JavaBean where the session bean is injected.
  public class MyBean {
      @javax.ejb.EJB UserSessionBeanInterface sb;
      // in this bean, you can use the session bean to create student.
  }
  and use it in your faces-config.xml as shown below:
  <managed-bean>
  <managed-bean-name>foo</managed-bean-name>
  <managed-bean-class>MyBean</managed-bean-class>
  <managed-bean-scope>session</managed-bean-scope>
  </managed-bean>

  Package this into your war file.

  Hope this helps. Refer to http://weblogs.java.net/blog/ss141213/archive/2005/12/using_java_pers.html for a discussion on a portable way to package your war and ejb classes in an ear.

  Thanks,
  Sahoo

  John Fagan wrote:
    Please help!

    I'm trying to write an application using JSF and EJB3. After several days and many variations I have had no success injecting the EntityManager in my session bean. It's always null!

    Using the following:
    Win XP
    Sun AS 9 PE
    JDK 1.5.0_06
    Eclipse 3.1 (tried the Glassfish plugin, but it wasn't working so created ant build script to package).

    The code is very simple test code. Nothing fancy.

    Application EAR file verifies with no problems. Server identifies EJB3 and Web module fine. Web is packaged in WAR file and EJB3 classes with persistence.xml are packaged in a JAR. Both are packaged in the EAR.

    Server is setup with a connection pool to a Postgres data source (pings fine), jdbc resource is setup, as well. Toplink creates the table in the database fine, so connection and persistence.xml is not a likely problem.

    The page displays fine and the JSF servlet gets the return value of either "success" or "em-null" (always returns em-null in the server log). No errors or warnings in the server log except for create table warning (since it is already created).

    Does anyone have an idea on how to fix this problem?
    Does anyone have any simple examples of EJB3 session bean being accessed by JSF that will deploy and work on AS 9?
    Am I missing a deployment descriptor for the EJB (I understood that it was not needed for EJB3)?

    Take care,
    John

    John Fagan, CCP, SCJP, ACP
    John.Fagan_at_clarisource.com
    http://www.clarisource.com

    UserSessionBean.java
    ---------------------------------------
    package edu.sunysb.pep.ejb3;

    import javax.ejb.Local;
    import javax.ejb.Stateful;
    import javax.persistence.EntityManager;
    import javax.persistence.PersistenceContext;

    @Stateful
    @Local
    public class UserSessionBean {

    @PersistenceContext
    EntityManager em;

    public UserSessionBean()
    {
    }

    private String name = "anon";

    public String getName() {
    return name;
    }

    public void setName(String name) {
    this.name = name;
    }

    public String newStudent()
    {
    Student student = new Student();
    student.setName("name");

    if(em == null)
    {
    return "em-null";
    }
    else
    {
    em.persist(student);
    return "success";
    }
    }
    }

    Home.jsp
    ---------------------------------------
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
    <%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
    <%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>
    <f:view>
    <h:form id="LoginForm">
    <h:message for="LoginForm" styleClass="error" />
    <h:outputLabel value="User Name:" />
    <h:inputText id="username1" value="#{UserSessionBean.name}" />
    <br />
    <h:message for="username1" styleClass="error" />
    <h:commandButton action="#{UserSessionBean.newStudent}" value="Login" />
    </h:form>
    </f:view>

    faces-config.xml
    ---------------------------------------
    <?xml version='1.0' encoding='UTF-8'?>
    <faces-config xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"
    version="1.2">

    <navigation-rule>
    <from-view-id>/faces/Home.jsp</from-view-id>
    <navigation-case>
    <from-outcome>em-null</from-outcome>
    <to-view-id>/faces/Null.jsp</to-view-id>
    </navigation-case>
    </navigation-rule>

    <managed-bean>
    <managed-bean-name>UserSessionBean</managed-bean-name>
    <managed-bean-class>edu.sunysb.pep.ejb3.UserSessionBean</managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>
    </managed-bean>

    </faces-config>

    web.xml
    ---------------------------------------
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <display-name>Test</display-name>
    <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

    <context-param>
    <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
    <param-value>client</param-value>
    </context-param>

    <context-param>
    <param-name>javax.faces.application.CONFIG_FILES</param-name>
    <param-value>/WEB-INF/faces-config.xml</param-value>
    </context-param>

    <context-param>
    <param-name>com.sun.faces.validateXml</param-name>
    <param-value>true</param-value>
    <!--

    Set this flag to true if you want the JSF Reference
    Implementation to validate the XML in your faces-config.xml
    resources against the DTD. Default value is false.

    -->
    </context-param>

    <context-param>
    <param-name>com.sun.faces.verifyObjects</param-name>
    <param-value>true</param-value>
    <!--
    Set this flag to true if you want the JSF Reference
    Implementation to verify that all of the application objects
    you have configured (components, converters, renderers, and
    validators) can be successfully created. Default value is
    false.

    -->
    </context-param>

    <!-- Faces Servlet -->
    <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    </servlet>

    <!-- Faces Servlet Mapping -->
    <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>/jsf/*</url-pattern>
    </servlet-mapping>

    </web-app>

    persistence.xml
    ---------------------------------------
    <persistence xmlns="http://java.sun.com/xml/ns/persistence"
    version="1.0">
    <persistence-unit name="PEP">
    <jta-data-source>jdbc/PEP</jta-data-source>
    </persistence-unit>
    </persistence>

    build.xml
    ---------------------------------------
    <?xml version="1.0" encoding="UTF-8"?>
    <project name="Site.pipeline" default="deploy">

    <property name="web.application.name" value="Test" />
    <property name="web.deploy.dir" value="C:\Sun\AppServer\domains\domain1\autodeploy" />
    <property name="web.source" value="./WebContent/" />

    <property name="web.jar.name" value="./${web.application.name}.war"/>
    <property name="ejb.jar.name" value="./${web.application.name}_ejb3.jar"/>
    <property name="application.jar.name" value="./${web.application.name}.ear"/>

    <target name="init">

    <delete file="${web.jar.name}"/>
    <delete file="${ejb.jar.name}"/>
    <delete file="${application.jar.name}"/>

    </target>

    <target name="build" depends="init">

    </target>

    <target name="undeploy">

    <delete file="${web.deploy.dir}/${application.jar.name}" />
    <sleep seconds="4" />

    </target>

    <target name="deploy" depends="package-ear,undeploy">

    <copy file="${application.jar.name}" todir="${web.deploy.dir}" />

    </target>

    <target name="redeploy" depends="undeploy">

    <copy file="${application.jar.name}" todir="${web.deploy.dir}" />

    </target>

    <!-- Create the EJB 3 deployment file. -->
    <target name="package-ejb" depends="build">

    <jar destfile="${ejb.jar.name}">
    <fileset dir="./build/classes">
    <include name="**/*.class" />
    </fileset>
    <metainf dir=".">
    <include name="persistence.xml" />
    </metainf>
    </jar>

    </target>

    <!-- Create the Web deployment package. -->
    <target name="package-web" depends="build">

    <jar jarfile="${web.jar.name}">

    <fileset dir="${web.source}" />

    </jar>

    </target>

    <!-- Creates an ear file containing all the modules. -->
    <target name="package-ear" depends="package-ejb,package-web">

    <jar jarfile="${application.jar.name}">

    <fileset dir="." includes="*.jar,*.war" />

    <!--
    <metainf dir=".">
    <include name="application.xml" />
    </metainf>
    -->
    </jar>

    </target>

    <target name="verify" depends="package-ear">

    <!-- "verifier" conflicts with some driver test software on my computer, so the
    full path was specified to the Java EE 5 verifier. -->
    <exec dir="." executable="\Sun\AppServer\bin\verifier.bat" failonerror="true">
    <arg line="-d VerifierResults"/>
    <arg line="${application.jar.name}"/>
    </exec>

    </target>

    </project>