Pages

Wednesday, April 28, 2010

EJB injection in a JSF Managed Bean

EJB injection in a managed bean of a JSF application deployed on a Weblogic Server can be tricky, Lucas already made a good  blogpost about this subject and provided a workaround. In this blogpost I will show how you can inject a local and remote EJB Session Bean which are deployed with the Web Archive (WAR) in one Enterprise Archive ( EAR) and I injected a remote EJB deployed with a different EAR.
The First and most important step is It only works when you define the Managed Bean in the faces-config.xml and not as an ADF Managed Bean ( like in an unbounded or bounded Task Flow xml )
Here an example of a managed bean configuration
<?xml version="1.0" encoding="windows-1252"?>
<faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee">
  <application>
    <default-render-kit-id>oracle.adf.rich</default-render-kit-id>
  </application>
  <managed-bean id="__2">
    <managed-bean-name id="__1">Injection</managed-bean-name>
    <managed-bean-class id="__4">nl.whitehorses.ejb.beans.InjectionBean</managed-bean-class>
    <managed-bean-scope id="__3">request</managed-bean-scope>
  </managed-bean>

</faces-config>
Here an example of the Local and Remote bean which I used in the managed bean
EJB with Remote interface
@Stateless(name = "HrSessionEJB1", mappedName = "EjbInjection-Model-HrSessionEJB1")
@Remote
public class HrSessionEJB1Bean implements HrSessionEJB1 {
    @PersistenceContext(unitName="Model")
    private EntityManager em;
EJB with Local interface
@Stateless(name = "HrSessionEJB2", mappedName = "EjbInjection-Model-HrSessionEJB2")
@Local
public class HrSessionEJB2Bean implements HrSessionEJB2Local {
    @PersistenceContext(unitName="Model")
    private EntityManager em;
Before you deploy the JSF web application on a Weblogic Server you need to make an EJB deployment profile of your EJB model project and add this to the EAR assembly in the application menu of your Workspace. This is not necessary when you run it in the integrated Weblogic Server of JDeveloper.

Here is my example of a managed bean.
package nl.whitehorses.ejb.beans;


import javax.ejb.EJB;
import javax.faces.event.ActionEvent;
import nl.whitehorses.ejb.injection.model.HrSessionEJB1;
import nl.whitehorses.ejb.injection.model.HrSessionEJB2Local;

import nl.whitehorses.model.HRSessionEJB;

public class InjectionBean {
    public InjectionBean() {
    }

    @EJB
    private HrSessionEJB1 hrRemote;

    @EJB (name = "HrSessionEJB1", mappedName = "EjbInjection-Model-HrSessionEJB1")
    private HrSessionEJB1 hrRemote2;

    @EJB( beanName="../hrejb.jar#HrSessionEJB2") 
    private HrSessionEJB2Local hrLocal;

    private HRSessionEJB hrSessionEJB;


    public void inject(ActionEvent actionEvent) {
      // Add event code here...
      if ( hrSessionEJB != null)  {
        System.out.println("found remote bean outside ear");
      }
      if ( hrRemote != null)  {
        System.out.println("found remote bean");
      }
      if ( hrRemote != null)  {
        System.out.println("found remote bean2");
      }
      if ( hrLocal != null)  {
        System.out.println("found local bean");
      }        
    }
}
When you deploy the EJB deployment profile in the same EAR as the WAR then you can use the @EJB annotation on your local or remote interface variable. As extra you can add the name and mappedName attribute, these values are the same as the attributes of the Stateless annotation of your Session Bean.

An other not recomended way is to provide the beanName attribute and provide the EJB deployment jar location on the WLS server together with a hash and the name of the Bean. Don't know if this works on your integrated Weblogic server of JDeveloper.

And the last way to inject a Remote EJB is to define an ejb-ref element in the web.xml with the injection managed bean class and the variable inside this class and weblogic.xml for the JNDI name of the Remote EJB. This works perfectly when the Remote EJB is not deployed in the same EAR as the Web Application.
<ejb-ref>
        <ejb-ref-name>ejb/HRSessionEJB</ejb-ref-name>
        <ejb-ref-type>Session</ejb-ref-type>
        <remote>nl.whitehorses.model.HRSessionEJB</remote>
        <injection-target>
           <injection-target-class>nl.whitehorses.ejb.beans.InjectionBean</injection-target-class>
           <injection-target-name>hrSessionEJB</injection-target-name>
        </injection-target>
    </ejb-ref>  
</web-app>

And the weblogix.xml with the JNDI name
<?xml version = '1.0' encoding = 'windows-1252'?>
<weblogic-web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xsi:schemaLocation="http://www.bea.com/ns/weblogic/weblogic-web-app http://www.bea.com/ns/weblogic/weblogic-web-app/1.0/weblogic-web-app.xsd"
                  xmlns="http://www.bea.com/ns/weblogic/weblogic-web-app">
  <ejb-reference-description>
    <ejb-ref-name>ejb/HRSessionEJB</ejb-ref-name>
    <jndi-name>ADF_EJB-SessionEJB#nl.whitehorses.model.HRSessionEJB</jndi-name>
  </ejb-reference-description>
</weblogic-web-app>
Hope this also works in an ADF Managed Bean soon, it should, but I tested it with JDeveloper 11g PS2 without any success.

No comments:

Post a Comment