Thursday, October 27, 2016

Starting with EJB3(Eclipse and WildFly 10 embedded)


Here are to configure an eclipse project to run a small EJB3 example....

My current configuration is:
JDK 1.8.0_91
WildFly 10(WildFly embedded configuration for Eclipse, see here)
JBoss Tools 4.3.1.Final installed in Eclipse(see here)
Eclipse 4.5.1 Mars for JavaEE developer
all on Windows 10....

We configure two project. One for the server side application. The other one for the client; we create a Dynamic Web Project for this last one. With a jsp file, within a button that starts all the process flow.

Let's we start with the server side application.

1) Under Eclipse File --> New --> EJB Project
I choose the name StartingWithEJB3_ServerSideAppl




Choose "WildFly 10.0 Runtime"(or whatever WildFly version you have) under "Target runtime" combo menu.
Leaves default "3.2" under "EJB module version" combo menu.

Then you can click on Finish.

2) Now we have to created two classes.
All under "ejbModule" folder.
The first one will be our Stateless Session Bean.
The logic business class.
So, right click on the ejbModule folder --> New --> Other --> Session Bean (EJB 3.x)


Choose a new Java package, that will be created... I give com.test.server.business
Than choose the class name, I give StatelessServerBean
At State type choose Stateless,
and into "Create business interface" section select the "Remote" check field, and I put as name StatelessServerBeanInterface
This field will create the remote Interface for the stateless bean we have created.

This is the content of the com.test.server.business.StatelessServerBean class

package com.test.server.business;

import javax.ejb.Stateless;

/**
 * Session Bean implementation class StatelessServerBean
 * @author Maurizio Franco
 *         http://maurizio-franco.blogspot.it
 *         maurizio.franco@ymail.com
 */
@Stateless
public class StatelessServerBean implements StatelessServerBeanInterface {
    public StatelessServerBean() {
    }

    public String executeTestMethod() {
        return "executeTestMethod invoked!!!";
    }
}


This is the content of the com.test.server.business.StatelessServerBeanInterface interface

package com.test.server.business;

import javax.ejb.Remote;

/**
 * StatelessServerBean interface
 * @author Maurizio Franco
 *         http://maurizio-franco.blogspot.it
 *         maurizio.franco@ymail.com
 */
@Remote
public interface StatelessServerBeanInterface {
    public String executeTestMethod();
}



3) Now we provide to create the second application. The client side application. With a Dynamic Web Project.

Click on New --> Dynamic Web Project


I Choose StartingWithEJB3_ClientAppl as project name.
"JBoss 7.1 Runtime" as "Target runtime"
and "3.0" as Dynamic web module version.
In configuration I had leaved "Default Configuration for JBoss 7.1 Runtime".

Than click on Finish.

4) Under project root create a new folder, I call it resources.
Under it, create a new properties file, I named it jboss-ejb-client.properties
This is its content:

remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connections=default

remote.connection.default.host=localhost
remote.connection.default.port = 4447


remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false

After create it, we have to put it into the class path.
So right-click on the project, Properties --> Java Build Path --> Libraries
Click on the button, on the right, "Add Class Folder" and we have to flag the check button for resources folder under our project.



5) Under src folder now we have to create to packages.
com.ejb3.client.test and com.ejb3.client.test.servlet

6) Under com.ejb3.client.test we have to create to classes.
First one is ContextProvider.
It contains:

package com.ejb3.client.test;

import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class ContextProvider {

    private static Context initialContext;

    private static final String PKG_INTERFACES = "org.jboss.ejb.client.naming";

    public static Context getInitialContext() throws NamingException {
        if (initialContext == null) {
            Properties properties = new Properties();
            properties.put(Context.URL_PKG_PREFIXES, PKG_INTERFACES);

            initialContext = new InitialContext(properties);
        }
        return initialContext;
    }
}

7) The other one is EJBApplicationTestClient
It contains:

package com.ejb3.client.test;

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


import com.test.server.business.StatelessServerBean;
import com.test.server.business.StatelessServerBeanInterface;

public class EJBApplicationTestClient {
   
    public static void main(String[] args) {
        System.out.println(EJBApplicationTestClient.class.getName() + ".main - START");
        StatelessServerBeanInterface bean = doLookup();
        System.out.println(EJBApplicationTestClient.class.getName() + ".main - DEBUG - Call server business logic method: " + bean.executeTestMethod());
    }

    public static StatelessServerBeanInterface doLookup() {
        System.out.println(EJBApplicationTestClient.class.getName() + ".doLookup - START");
        Context context = null;
        StatelessServerBeanInterface bean = null;
        try {
            System.out.println(EJBApplicationTestClient.class.getName() + ".doLookup - DEBUG - Obtaining Context");
            context = ContextProvider.getInitialContext();
            System.out.println(EJBApplicationTestClient.class.getName() + ".doLookup - DEBUG - Generate JNDI Lookup name");
            String lookupName = getLookupName();
            System.out.println(EJBApplicationTestClient.class.getName() + ".doLookup - DEBUG - Lookup and cast");
            bean = (StatelessServerBeanInterface) context.lookup(lookupName);
            System.out.println(EJBApplicationTestClient.class.getName() + ".doLookup - DEBUG - remote server bean successfully looked up..");
        } catch (NamingException e) {
            e.printStackTrace();
        }
        return bean;
    }

    private static String getLookupName() {
        System.out.println(EJBApplicationTestClient.class.getName() + ".getLookupName - START");
        //The app name is the EAR name of the deployed EJB without .ear suffix.
        //Since we haven't deployed the application as a .ear, the app name for us will be an empty string
      
        String appName = "";

        //The module name is the JAR name of the deployed EJB without the .jar suffix - in this case is the name of the Project..
       
        String moduleName = "StartingWithEJB3_ServerSideAppl";

        //AS7 allows each deployment to have an (optional) distinct name.
        //This can be an empty string if distinct name is not specified.
        String distinctName = "";

        System.out.println(EJBApplicationTestClient.class.getName() + ".getLookupName - DEBUG - Get EJB bean implementation class name");
        String beanName = StatelessServerBean.class.getSimpleName();
        System.out.println(EJBApplicationTestClient.class.getName() + ".getLookupName - DEBUG - beanName: " + beanName);
       
        System.out.println(EJBApplicationTestClient.class.getName() + ".getLookupName - DEBUG - Get fully qualified remote interface name");
        final String interfaceName = StatelessServerBeanInterface.class.getName();
        System.out.println(EJBApplicationTestClient.class.getName() + ".getLookupName - DEBUG - interfaceName: " + interfaceName);
       
        System.out.println(EJBApplicationTestClient.class.getName() + ".getLookupName - DEBUG - Create a look up string name");
        String name = "ejb:" + appName + "/" + moduleName + "/" + distinctName    + "/" + beanName + "!" + interfaceName;
        System.out.println(EJBApplicationTestClient.class.getName() + ".getLookupName - DEBUG - lookup up name: " + name);
       
        return name;
    }
}

WARNING!!!! I pick the background to red to pay attention to the moduleName, it must be the server module name(normally the name of the server application gived to the eclipse project)

8) Next, under com.ejb3.client.test.servlet we create a Servlet class.
Its name is TestServlet and it contains:

package com.ejb3.client.test.servlets;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.ejb3.client.test.EJBApplicationTestClient;
import com.test.server.business.StatelessServerBeanInterface;

/**
 * Servlet implementation class TestServlet
 */
@WebServlet("/TestServlet")
public class TestServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
      
    /**
     * @see HttpServlet#HttpServlet()
     */
    public TestServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {       
        System.out.println(TestServlet.class.getName() + ".main - START");
        StatelessServerBeanInterface bean = EJBApplicationTestClient.doLookup();
        //Call server business logic method
        System.out.println(TestServlet.class.getName() + ".main - DEBUG - " + bean.executeTestMethod());        
    }


}




9) Now we have surely some errors on the Servlet and on the EJBApplicationTestClient class. Some classes used are not resolved.
So we have to import the jar file of the Server application.
So we do it right clicking on the Server Side Application, in my case on the 
StartingWithEJB3_ServerSideAppl project, (remember the Java EE perspective) go under "Export" --> EJB JAR file  

Our server application project selected in the EJB Project text field.
Than in the Destination text filed we have(with "Browse.." button) to point to:
%ECLIPSE_WORKSPACE_FOLDER/StartingWithEJB3_ClientAppl/WebContent/WEB-INF/lib






After give an F5 on the client project. Only with this forced refresh the project will see the server application jar.


10) We have at the last point. Create a simple jsp file to invoke all the process. A simple page that through the button pression will call the
TestServlet thats using the EJBApplicationTestClient class will invoke the remote(on the server) instance of StatelessServerBean to call the executeTestMethod()
The index.jsp contains:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!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=UTF-8">
<title>Jsp test page for invoke ejb3 test client class...</title>
</head>
<body>
    <form action="${pageContext.request.contextPath}/TestServlet">
        <h1>After clicking see the server console output....</h1>
        <input type="submit" value="invoke ejb3 client application"/>
    </form>
</body>
</html> 



That's all. 
You can find all this small example in a branch of sourceforge.net ready for download.
The urls for Anonymous download(no password required) are:

svn://svn.code.sf.net/p/mauriziofranco/code/StartingWithEJB3/trunk/StartingWithEJB3_Server 

svn://svn.code.sf.net/p/mauriziofranco/code/StartingWithEJB3/trunk/StartingWithEJB3_Client

Or for checkout directly from command line give these:

svn checkout svn://svn.code.sf.net/p/mauriziofranco/code/StartingWithEJB3/trunk/StartingWithEJB3_Server  mauriziofranco-code

svn checkout svn://svn.code.sf.net/p/mauriziofranco/code/StartingWithEJB3/trunk/StartingWithEJB3_Client  mauriziofranco-code

Bye...