Pages

Thursday, December 13, 2012

JSF - EJB 3.0 on Glassfish V2

This is a very basic tutorial on how to create and deploy a very basic JSF - EJB application on Glassfish application server. The whole process is very simple and straight forward. I will be using Glassfish V2 as the Application Server and Eclipse IDE to develop the application.

Before we begin, we need to setup the environment. For this very basic tutorial, all we need is a Glassfish AS installed and an Eclipse IDE downloaded. Please go to the Glassfish Installation page for details of how to install and configure Glassfish V2.

After the Glassfish is installed and Eclipse downloaded, go to the Eclipse and switch to the Java EE perspective. After closing all the unnecessary views, your environment would look something like this:


Now go to the Package Explorer and right click on the pan (If project Explorer is not there then you can add it by going to Window --> Show View --> Other and select project explorer from this menu) From the Right click menu select New --> Project. This will open a New Project Wizard. Select Enterprise Application Project on this screen and click next.


This will open New project creation screen.


Give a name to your project and select a Target Runtime, In our case we don't have one so click on New to create one.


Select the Glassfish V2 Java EE 5 from this list and click next. If you don't see this Runtime then click on the Download additional server adapters link and add Glassfish V2 on your list.


On this screen you need to provide the installation directory to the Glassfish server already installed on your machine. In my case the installation directory is C:\Software\Glassfish so I browsed to that directory. Now click the Finish button to return to your Project Configuration screen. You can now see you have Glassfish V2 Java EE 5 as your Target Runtime in the configurations.


No further configurations required at this point. Click Finish to return to your IDE.

Now you need to add the EJB project to this Enterprise Project. For that again right click on the package explorer pan and open the New Project Wizard as before.


This time select the EJB Project and click Next.


On this screen, give it a project name and Add the project to the Enterprise Project created earlier. Click Next for further configurations.


Remove the tick from Create EJB Client JAR option and make sure the Generate deployment descriptor is not ticked. We will do that later. Now click finish to create the project and go back to the IDE.

Now we need to create the web project for our interface. For that again right click on the Package Explorer view and open the new project wizard as before.


This time we need to select the Dynamic Web Project as our project type. Click on next on this screen after selecting the project type.


As before, give your project a meaningful name, add it to the EAR, and click next for further configurations.


Again, we don't need IDE to generate deployment descriptors so remove this option. Click on finish to go back to the IDE.

Last configuration that we need is to add JSF facets to our web project. For that right click on the Web Project and select properties. From the project properties screen select the Project Facets option.


On the Facets screen tick the Java Server Faces, and update the version to 1.2. As soon as you make these changes you will see another link appearing at the bottom of the screen asking you for Further Configurations. Click on this link to add JSF libraries.



You actually don't need to make any changes here, I changed the URL mapping from /faces/* to *.jsf just because it looks a little better to me. But that is my personal preference and it has nothing to do with the requirements. Click on OK to go back to the IDE.

Now you need to add the JSF libraries on the build path of your web project. Right click on the project and from the right click menu select Build Path --> Configure Build Path option. This will open the Java Build Path configuration wizard.


On this screen click on the Add External JARs... button and browse to your Glassfish lib directory and select the jsf-impl.jar from from there. This jar should already be there in the Glassfish lib directory, if not then download the file from Glassfish website. Click OK to finish the configurations.

All the configurations are now done. Let's start with creating the EJB project. Create a new package under the default ejbModule package in the EJB project. I created the package as com.test.session for the session EJBs.

Right click on the package and select New --> Other or select the package and hit Ctrl+N. This will open the Create New wizard.


Go down to the EJB folder and select Session Bean from the list and click Next.


Give your first EJB Class a meaningful name and click Finish. On the same screen you can tick the Remote check-box to create the remote interface for this session bean. Also you may want to create your Local and Remote interfaces in separate folders, I prefer this way as it is easier to manage when we have a large project. However, for this exercise, let's keep things as simple as possible.

When you click finish, it will create a Local interface and an session bean in the com.test.session package. Open the HelloEJBLocal interface and add a very simple business method.
package com.test.session;

import javax.ejb.Local;

@Local
public interface HelloEJBLocal {
 
 // Simple business method
 public String sayHello(String name);

}

Now implement the method in your Session EJB.

package com.test.session;

import javax.ejb.Stateless;

/**
 * Session Bean implementation class HelloEJB
 */
@Stateless
public class HelloEJB implements HelloEJBLocal {

    /**
     * Default constructor. 
     */
    public HelloEJB() {
        // TODO Auto-generated constructor stub
    }

 @Override
 public String sayHello(String name) {
  
  String msg = "EJB Says Hello ";
  return msg + name;
  
 }

}

A Very simple method. All we are doing here is taking the name of the caller in the parameter and saying Hello to the caller with her name.

Now let's start working on the Web Tier. I started by creating a Utility Class to communicate with all of my local EJB interfaces. For any Utility classes it's better to create a separate package for them. I created the package com.test.util under the src folder of my Web project.

Now create a utility class in the util package of your web project called BeanManagerFaces.java as follows

package com.test.util;

import javax.ejb.EJB;
import javax.el.ELContext;
import javax.faces.context.FacesContext;
import javax.servlet.ServletContext;

import com.test.session.HelloEJBLocal;

public class BeanManagerFaces {

 
 public static String REAL_PATH;
 public static String CONTEXT_PATH;
 
 static{
  ServletContext context = (ServletContext)FacesContext.getCurrentInstance().getExternalContext().getContext();
  REAL_PATH = context.getRealPath("");
  CONTEXT_PATH = context.getContextPath();
 }
 
 public String getContextPath() {
  return CONTEXT_PATH;
 }

 public String getRealPath() {
  return REAL_PATH;
 }
 
 
 public Object getBean(String beanName){
  
  Object ejb;
  ELContext elContext = FacesContext.getCurrentInstance().getELContext();
  ejb = FacesContext.getCurrentInstance().getApplication().getELResolver().getValue(elContext, null, beanName); 
  return ejb;
 }
 
 @EJB
 private HelloEJBLocal helloEJBLocal;
 public HelloEJBLocal getTestEJB() {
  return ((BeanManagerFaces)getBean("beanManager")).helloEJBLocal;
 }

}

The most important line here is the line 42
  return ((BeanManagerFaces)getBean("beanManager")).helloEJBLocal;

Note the "beanManager" name, this is the name of this class when we add it to our list of Backing Beans in the Faces Config configurations. To do that go to the WebContact -->  WEB-INF folder of your web project and open the faces-config.xml file. Ideally Eclipse will open the file in the GUI Editor for faces-config file for you


On that configuration screen, go to the ManagedBeans tab and click the Add button.


Type in the fully qualified name of your utility class or click Browse button to locate your file. Now clock next to go to the next screen.


On this screen select the "session" option and give it the name "beanManager". Note here this is the same name that you specified on the Line 42 of BeanManagerFaces.java otherwise JSF will not be able to locate this bean.

If for whatever reason Eclipse fails to open the faces-config.xml in a UI editor then you can manually edit the faces-config.xml source to add these two Managed Beans as follows.
<?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">
 <managed-bean>
  <managed-bean-name>beanManager</managed-bean-name>
  <managed-bean-class>com.test.util.BeanManagerFaces</managed-bean-class>
  <managed-bean-scope>session</managed-bean-scope>
 </managed-bean>
 <managed-bean>
  <managed-bean-name>helloBean</managed-bean-name>
  <managed-bean-class>com.test.bean.HelloBean</managed-bean-class>
  <managed-bean-scope>session</managed-bean-scope>
 </managed-bean>

</faces-config>

Now create a Backing Bean for JSF with just two simple variables and one method as follows. It is a good idea to place all of the backing beans in a separate package for ease of management if you have a large project. I created the com.test.bean package to place all the backing beans.
package com.test.bean;

import com.test.service.HelloService;

public class HelloBean {
 
 private String name;
 private String mesg;
 
 public String sayHello(){
  return new HelloService().sayHello(this);
 }

 public String getName() {
  return name;
 }

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

 public String getMesg() {
  return mesg;
 }

 public void setMesg(String mesg) {
  this.mesg = mesg;
 }

}

Now we need to add this bean to our list of Managed Beans in the faces-config file. I gave it the name helloBean when adding it as a session bean in the faces-config.xml configuration. The process will be exactly the same as described above for BeanManagerFaces.java

Notice here that in the HelloBean we are delegating the actual processing to a separate service class to handle the business methods. Let's create this class now to handle the method details. I created a package com.test.service for all of my service classes. Now lets create the service class as follows:
package com.test.service;

import com.test.bean.HelloBean;
import com.test.session.HelloEJBLocal;
import com.test.util.BeanManagerFaces;

public class HelloService {
 
 public String sayHello(HelloBean bean){
  
  String name = bean.getName();
  String msg = null;
  
  // Get the local interface from bean manager faces
  HelloEJBLocal ejb = new BeanManagerFaces().getTestEJB();
  
  // Call the EJB method
  msg = ejb.sayHello(name);

  bean.setMesg(msg);
  
  return null;
 }
}


Now let's create a JSF page to test the EJB method. Right click on the WebContent directory and go to New --> Other and browse down to Web folder. Open the Web folder and select the JSP from there and click next. This is the same menu that you used previously to add Session EJB. Click next and select the WebContent directory and give a file name. I entered hello.jsp as my file name. Click next and it will show you options to select a template for your JSP.


Select the "New JavaServer Faces (JSF) Page (html)" from the options and click finish.This will create a JSF Template JSP file in the WebContent folder for you. Open the hello.jsp and add these lines:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="f"  uri="http://java.sun.com/jsf/core"%>
<%@ taglib prefix="h"  uri="http://java.sun.com/jsf/html"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<f:view>

 <h:form id="testForm">
  <table border="1">
   <tr>
    <td> <h:outputText value="Name:" /> </td>
    <td> <h:inputText value="#{helloBean.name}" /> </td>
    <td> <h:commandButton value="Say Hello" action="#{helloBean.sayHello}" /> </td>
   </tr>
   <tr>
    <td colspan="3"> <h:outputText value="#{helloBean.mesg}" /> </td>
   </tr> 
  </table>
 </h:form>
 
</f:view>
</body>
</html>

All Done, now let's export the project as EAR and deploy that to the Glassfish. For that right click on the Enterprise Project and click on Export from the menu. This will open the Export project Wizard. On this screen go to the Java EE folder and select the EAR File.


Click on Next, this will ask you for a location to save the file. Browse to whatever folder you want and save the file as TestProject.ear in your prefered location.

Now start the Glassfish server. Once you verify the Glassfish server is running then go to the Glassfish home directory --> domains --> test --> autodeploy

Test is the name of the domain I created for this exercise. Every domain has an autodeploy directory and all you need to do is to copy the TestProject.ear file to the autodeploy folder. Give it a few seconds to process the Enterprise Archive and once it is done then you will see TestProject.ear_deployed file appearing in this folder. This is the sign that Glassfish has deployed your EAR successfully. In case of any failures you will see the file deploy_failed appearing on this directory.

If you go to the server.log log file now, you will see the last line on the logs something like this:

/TestProjectWeb;|Initializing Mojarra (1.2_13-b01-FCS) for context '/TestProjectWeb'
[AutoDeploy] Successfully autodeployed : C:\software\glassfish\domains\test\autodeploy\TestProject.ear

This means your web application is successfully deployed and is initialized and waiting for requests at /TestProjectWeb

This is the root directory of your web project, i.e., WebContent. Since we placed our jsp file in the root directory, our fill URL including the domain name will look something like this:
http://localhost:8080/TestProjectWeb/hello.jsf

Notice the .jsf here. We are calling the hello.jsp as hello.jsf because in our previous steps we configured the jsf URLs to be *.jsf when we configured the Project Facets.

Let's go to this URL and see what happens.


Type in your name and click the Say Hello button to see if it is working ......


As you can see here. The EJB take the name entered in the box and returned with the response message.

1 comment:

  1. Hi,
    The document above mentions creating EJB client jar project. Do you have that article published separately? Can youpost a link to it?

    Thanks,

    ReplyDelete