persistence@glassfish.java.net

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

From: Sanjeeb Kumar Sahoo <Sanjeeb.Sahoo_at_Sun.COM>
Date: Tue, 16 May 2006 22:19:00 +0530

Hi John,

John Fagan wrote:
> 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,
No, server does not create the business interface.
> or perhaps this is only for the remote interface and not the local
> interface?
In the initial versions of the spec, something like this was proposed,
but it was discarded because it was not useful.
>
> 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?
Yes.
> Maybe this is just bad documentation?
No, I don't see any issues here. It clearly says, that resource can be
inject into JSF managed beans.
> I expected that my annotations for PersistenceContext would work based
> on this statement.
Yes, provided your JSF managed bean is packaged *inside* war file and
web.xml file uses *schema version > 2.4*. Remove @Stateful from your
UserManagerBean.class and package the class along with entity classes,
persistence.xml into war file and you can see EntityManager being non-null.
>
> For me, a bug is that the EntityManger will not inject with JSF
> managed beans (either a verifier bug, server bug or documentation bug).
EntityManager can be injected into JSF managed bean and I know that
works. In your case, is it possible that you are treating the same class
as both a JSF bean and a Stateful EJB which uses the injected EntityManager?
> Maybe, the verifier not catching the missing local interface is a bug,
> too. I'll file a bug report, as you suggested.
Yes, please file a verifier bug for not detecting missing local
interface in the EJB.

On a separate note, have you tried using NetBeans 5.5? It has very good
support Java EE 5 development. We have also added some checks in
NetBeans which would have detected this error while you were editing the
source code in the IDE.

Thanks,
Sahoo
>
> Take care,
> John
>
> John Fagan, CCP, SCJP, ACP
> John.Fagan_at_clarisource.com <mailto:John.Fagan_at_clarisource.com>
> http://www.clarisource.com
>
> ----- Original Message -----
> *From:* Sanjeeb Kumar Sahoo <mailto:Sanjeeb.Sahoo_at_Sun.COM>
> *To:* persistence_at_glassfish.dev.java.net
> <mailto: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 <mailto: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>
>