EJB-Stateless implementation using Remote JNDI Lookup


This tutorial is another part of JavaEE project tutorial series, in this part we demonstrate how to perform JNDI lookup on the Remote Interface Implementation on EJB. In this step by step tutorial we demonstrate the JNDI properties method with Context naming

Tools Used: Eclipse JavaEE - Juno, Wildfly 8.1.0

This tutorial is next part of the JavaEE project tutorial series, in this part we are going to describe the use of EJB and we will implement it with Remote Interface method. We will do it using JNDI properties and lookup. Following is a complete Series Index.

Series Index:

In this tutorial we will use the Remote Interface we created in last tutorial, it is simple the structure of the remote Interface and class that implements it is as follows.


package com.em.ejb.beans.interfaces;

import java.util.List;
import javax.ejb.Remote;
import com.em.jpa.entity.Student;

@Remote
public interface StudentDAORemote {
	public Student create(Student student);
	public Student update(Student student);
	public void remove(int id);
	public Student getStudent(int id);
	public List<Student> getAllStudents();
}


package com.em.ejb.beans;

import java.util.List;
import com.em.ejb.beans.interfaces.StudentDAOLocal;
import com.em.ejb.beans.interfaces.StudentDAORemote;
import com.em.jpa.entity.Student;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

/**
 * Session Bean implementation class StudentDAO
 */
@Stateless
public class StudentDAO implements StudentDAORemote, StudentDAOLocal {

	@PersistenceContext
	private EntityManager em;
	
    /**
     * Default constructor. 
     */
    public StudentDAO() {
    }

	@Override
	public Student create(Student student) {
		em.persist(student);
		return student;
	}

	@Override
	public Student update(Student student) {
		em.merge(student);
		return student;
	}

	@Override
	public void remove(int id) {
		em.remove(getStudent(id));
		
	}

	@Override
	public Student getStudent(int id) {
		return em.find(Student.class, id);
	}

	@Override
	public List<Student> getAllStudents() {
		return em.createNamedQuery("Student.getAll", Student.class).getResultList();
	}
}

When you will deploy this application you will notice that this class and Interface are exposed with the JNDI, here is a sample of this exposure of JNDI.

	java:global/DemoProject/DemoEJB/StudentDAO!com.em.ejb.beans.interfaces.StudentDAORemote
	java:app/DemoEJB/StudentDAO!com.em.ejb.beans.interfaces.StudentDAORemote
	java:module/StudentDAO!com.em.ejb.beans.interfaces.StudentDAORemote
	java:jboss/exported/DemoProject/DemoEJB/StudentDAO!com.em.ejb.beans.interfaces.StudentDAORemote

Please note that, when you declare an interface as remote and implement it in a class, that should be listed in the JNDI java:exported section of the wildfly.

Exported JNDI

As demonstrated in the article EJB with Local Interface Implementation, the Injection does not work on the RemoteInterface implementation, Also Remote EJB may be hosted on a different JVM than the JVM with the web client. So there is requirement of the Context lookup. There is proper tutorial for this lookup on the documentation of JBoss.

 

This tutorial is also based on the documentation tutorial on the Official JBoss Remote EJB lookup. The process is in two steps.

  • Create a Lookup method to perform EJB lookup using NamingContext.
  • Set up a jboss-ejb-client properties. which holds the context properties.

After these two steps we can obtain a reference to the Remote EJB through which we can invoke the methods defined in the EJB. First of all we are going to create a method in a separate class we name it as Utils. So we are defining a method in this class named, doLookup(). Please look at the code first we will tell it later.

 


package com.em.utils;

import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import com.em.ejb.beans.StudentDAO;
import com.em.ejb.beans.interfaces.StudentDAORemote;

public class Utils {
	public static StudentDAORemote doLookup() throws NamingException{
		 final Hashtable jndiProperties = new Hashtable();
	        jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
	        final Context context = new InitialContext(jndiProperties);
	        final String appName = "DemoProject";
	        final String moduleName = "DemoEJB";
	        final String distinctName = "";
	        final String beanName = StudentDAO.class.getSimpleName();
	        final String viewClassName = StudentDAORemote.class.getName();
	        return (StudentDAORemote) context.lookup("ejb:" + appName + "/" + moduleName + "/" + distinctName + "/" + beanName + "!" + viewClassName);
	}
}

So with this code we have completed first step. This is notable step. Please note the first line of the doLookup() after declaration of a hashtable. The first property put in the hashtable is URL_PKG_PREFIXES and as a parameter the client naming is passed. This is to tell the lookup to use the naming proxy for the EJB lookup and to use the naming context properties in order to perform the lookup.

appName is the name of the ear file without .ear extension. This is the deployed name of the application. The moduleName is the name of the EJB module which contains the EJB classes and interfaces. The distinctName is the mapped name of the interface but if not specified in the code it may be left blank. Finally the Class name and the Interface name is in the last two values, it is to be noted that the fully classified class name is used for the Remote interface.

Property file

property file 2

Next we need to create the properties file and add it to the application client classpath. In eclipse it can be created by right clicking the Web application and selecting Other then searching for the properties. Here you need to specify the location for the property file, it is to be noted that the property is to be added to the classpath of the client class(ManagedBean). The name of the file should be jboss-ejb-client.properties The structure of the file is as follows:

remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
 
remote.connections=default
 
remote.connection.default.host=localhost
remote.connection.default.port = 8080
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
 
remote.connection.default.username=administrator
remote.connection.default.password=secure

In the properties and values the first entry tells if secure port is to be used. Second connection tells the number of remote connections. then the host and port where the EJB is hosted and then if the security policy is enforced or not, followed by the username and password for the remote access authentication.

Finally everything is set now we are creating a ManagedBean(Actually we are changing the managed bean class created in previous article of series).


package com.em.managedbeans;

import java.util.List;
import com.em.utils.Utils;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import com.em.ejb.beans.interfaces.StudentDAORemote;
import com.em.jpa.entity.Student;

@ViewScoped
@ManagedBean
public class StudentMB {

	public StudentMB() {
	}
	
	public void createStudent(){
		StudentDAORemote studentDAORemote = Utils.doLookup();
		Student student = new Student();
		student.setFirstName("ExamsMyantraRemote");
		student.setLastName("TutorialsRemote");
		student.setStanderd("X");
		studentDAORemote.create(student);
	}
}

In this we have used the static method from Utils class to obtain the lookup and on the basis of that we are invoking the create(Student student) method from StudentDAO class. To demonstrate the working of the Bean we are invoking the method from the index.xhtml.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets"> 

<h:head></h:head> 
<h:body> 
Hello World!
#{studentMB.createStudent()}
</h:body> 
</html>

This is how we can use the Remote EJB lookup to work with the EJBs. In the next tutorial we are going to create a working view for CRUD of the Student entities. We will use Entity, EJB, ManagedBean and JSF view to achieve the result.