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:
- MySql Datasource creation in Wildfly 8
- Project structure Eclipse+Wildfly+MySql+JPA+EJB+JSF+RS
- Creating Entity using JPA+Hibernate
- Creating EJB to do CRUD on Entity
- Creating View in JSF+Managed Bean
- Applying Bootstrap to JSF based Web Application
- Template based View in JSF Web Application
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.
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.
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.
Hi Thank you Mayank for this wonderful example it helped me a lot. Now I have a requirement how can get the reference of data source in remote client application and run a select query on that reference.
I am waiting for you reply, I have already wasted my 5 days in searching this please help me if you need more information then let me know.
I am sorry to say I didn’t really understand your question, This tutorial already shows how you can do remote lookup to obtain data source. as far as I can recall everything should work exactly the same but the calling client will be different and url will be different in configuration and doLookup method. Sorry to say this is as far as I can remember this was done about 2 years ago and I am currently not into this. My apologies for being unhelpful at the moment.