Thursday 12 September 2013

EJB Patterns: Service Facade example

This article shows the common Service Facade pattern in the EJB context. Several aspects takes into account this pattern.

 

1) The Service Facade insolates the service definition from its implementation.

2) It is the way of decoupling the Web tier from the Business tier.

3) From a transactional point of view, the business service may implement his transaction scope or be part of the current transaction.

4) The contract of the Service Facade interface is oriented to be invoked by Web tier or client software, but methods of the contract should not be invoked within the business implementation.

The following is an example of this pattern.

Firstly, an interface with the contract definition is defined:

@Local

public interface FarewellBusiness {

      public void sendMessage(String message);

      public void sendMessageDetail(String message,String detail);

     

}

 Secondly, a class that implements this interface is created. This class is the Stateless bean that will be managed by the JEE-container.

@Stateless (name="farewellBusiness")

@Clustered

@TransactionAttribute (TransactionAttributeType.REQUIRES_NEW)

public class FarewellBusinessBean implements FarewellBusiness {

 

      @Inject FarewellBusinessLogic business;

      public void sendMessage(String message) {

           

           

            business.sendMessage(message);

     

      }

      public void sendMessageDetail(String message,String detail)

      {

            business.sendDetailForMessage(message, detail);

      }

 

}

As the class reflects :

@Stateless: It is a stateless java bean.

@Clustered: It is executed within a JBoss cluster (for instance)

@TransactionAttribute (REQUIRED_NEW). Invocations of methods of this class require a transaction scope. If there is already a transaction scope running, the instance is executed under the transaction scope, if not; a new transactional process is created.

The invocation of the EJB is by way of the Service Interface, as the example below shows:

@ManagedBean (name="manager")

@SessionScoped

public class ManagerBean implements Serializable{

            @ManagedProperty(value="#{farewell1}")

            FarewellBean bean;

           

            @EJB

            FarewellBusiness farewellBusiness;

           

            public String send(){

                                    // send the message invoking business ejb

                 

                  farewellBusiness.sendMessage(bean.getFarewell1());

                  return "success";

            }

            public void setBean(FarewellBean bean) {

                  this.bean = bean;

            }

            public String sendDetail(){

                  farewellBusiness.sendMessageDetail(bean.getFarewell1(), bean.getDetail());

                  return "success";

            }

           

}

 

Friday 6 September 2013

JBoss 7.1.1.Final clustering with mod_proxy and Apache 2.2

This article shows how to configure a cluster made up of two JBoss AS 7.1.1.Final instances and how to config Apache Web Server to implement the so-called load balanced mechanism.
The version of Apache used to implement this example is Apache 2.2
Firstly, I would like to show how to create two clustered nodes with JBoss standalone version.
Finally, I will outline the steps needed to configure the Apache server to behave just like a load balancer element.
JBoss Cluster configuration
It is extremely easy to create a JBoss cluster based on the Standalone modality.
Imagine that the Jboss server is installed in the following filesystem location.
\JBOSS_HOME\
For dealing with a simple and non-infrastructure complex example, this example deploy two clustered nodes in the same machine but listening different ports.
Thus, we are going to create two nodes called: node1 and node 2
For creating each node, the following steps must be followed:
1) Copy the folder \JBOSS_HOME\standalone to \JBOSS_HOME\ with the name, for instance, “standalone_node1”
2) Copy the folder \JBOSS_HOME\standalone again to \JBOSS_HOME\ with the name, form instance, “standalone_node2”
3) In the \JBOSS_HOME\bin create a “bat” file called, for instance, “cluster_node1.bat” and include the following sentence that run and deploy the instance of the node1.
./standalone.bat -c standalone-ha.xml -b 127.0.0.1 -u 230.0.0.4 -Djboss.server.base.dir=../standalone_node1 -Djboss.node.name=node1 -Djboss.socket.binding.port-offset=100
 4) In the \JBOSS_HOME\bin create a “bat” file called, for instance, “cluster_node2.bat” and include the following sentence that run and deploy the instance of the node1.
./standalone.bat -c standalone-ha.xml -b 127.0.0.1 -u 230.0.0.4 -Djboss.server.base.dir=../standalone_node2 -Djboss.node.name=node2 -Djboss.socket.binding.port-offset=200
5) Finally, execute in different cmd console each of the “bat” files in order to lauch and make available the JBoss cluster.
APACHE LOAD BALANCER CONFIGURATION
For activate the load balancer feature of the Apache, I assume in this example to do so by using the mod_proxy module that is included in this version of Apache Web Server. It is not the best option to configure a load balancer node, because the best protocol called ajp is not used. Instead, all the communication is based on the common http protocol.
In the file \APACHE_HOME\conf\httpd.conf several modifications must be done:
1) Activate the following modules by adding these sentences
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_scgi_module modules/mod_proxy_scgi.so

Be aware that all this *.so files are included in the distributable 2.2.* version of Apache
2) Create a virtual host as follow:
<VirtualHost localhost:90>
    ServerName localhost:90
    DocumentRoot "d:/Program Files/Apache Software Foundation/Apache2.2/htdocs"
    # Enable forward proxy
    ProxyRequests On
    ProxyVia On
    <Proxy *>
        Order deny,allow
        Allow from all
    </Proxy>
    # Enable reverse proxy
    ProxyPass / balancer://mycluster/ stickysession=JSESSIONID
    ProxyPassReverse / http://localhost:8180/
    ProxyPassReverse / http://localhost:8280/
    <Proxy balancer://mycluster>
        BalancerMember http://localhost:8180/ route=node1
        BalancerMember http://localhost:8280/ route=node2
        # Set counting algorithm to more evenly distribute work:
        ProxySet lbmethod=byrequests
    </Proxy>
    # Enable load balancer management
    <Location /balancer-manager>
        SetHandler balancer-manager
    </Location>
    <Directory "htdocs">
        AllowOverride AuthConfig
    </Directory>
</VirtualHost>

As you can see, this load balancer configuration points to the two JBoss instances deployed by way of the http ports (8180 for node 1 and 8280 for node2).
 The Jboss node1 listen the request in the port 8180 because when the instance is launched , the port offset is indicated properly in the command showed previously (8080 + 100 offset=8180). The same for the node 2 (8080 + 200=8280).
./standalone.bat -c standalone-ha.xml -b 127.0.0.1 -u 230.0.0.4 -Djboss.server.base.dir=../standalone_node1 -Djboss.node.name=node1 -Djboss.socket.binding.port-offset=100
./standalone.bat -c standalone-ha.xml -b 127.0.0.1 -u 230.0.0.4 -Djboss.server.base.dir=../standalone_node2 -Djboss.node.name=node2 -Djboss.socket.binding.port-offset=200

With these steps, you have in your own machine a Jboss cluster comprised of two nodes and in front of them an Apache Web service balancing the petitions.





Thursday 5 September 2013

Web Service implementation with JAX-WS 2.1 and jBPM workflow engine

This entry shows how to construct a Web Service by using the JAX-WS specification. The web service proposed is a standalone SOAP- based service that implements a workflow deployed in the platform JBpm. This example uses an embedded workflow engine and this is the piece that will be invoked by a client application to decide if a message is persisted in the database via EJB or is sent to a JMS queue. These steps will be explained in following entries. In this article, only the Web service creation and the jbpm implementation are contemplated.

Firstly I would like to show how to define a workflow in jBpm.

In this occasion, the version chosen is the jBpm 4.1. The persistence of the processes definitions and instances are persisted in memory using HSQL database. I considered deploying it as a workflow application in JBoss 7.1.1.Final but several problems arose regarding Hibernate version. jBPm uses the Hibernate 3 version and JBoss the Hibernate 4.  I could work it out but I’d rather use the workflow engine just like an application-embedded component.

Here we go.

FUNCIONALITY: There is a Web Services deployed out of the JBOss AS which execute a workflow. This workflow is embedded in the WS itself and his main goal is deciding whether a message is persisted in a database by way of EJB or , on the other hand, the message is sent to a JMS-based queue. This queue is deployed and managed by the jBoss AS server.

This example only shows how the Web Service is developed and deployed and how the jBpm process is developed and deployed. It is important to highlight the fact that the IoC pattern is implemented by using Spring Framework 2.5. The web service has a little authentication provider.

Here I resume the technologies used:

JAX-WS for implementing the Web Service.

Spring Framework for IoC pattern implementation

jBpm for implementing the process deciding the channel to be used to send the message.

This Web Service will be invoked by a JSF application that will be described in a future article.

Maven is used for developing this example.

 

Web Service Creation

This is the code of the Web Service based on JAX-WS

An interface is defined:

 

package com.farewell.ws;

import javax.jws.WebMethod;

import javax.jws.WebService;

import javax.jws.soap.SOAPBinding;

import javax.jws.soap.SOAPBinding.Style;

 

@WebService

@SOAPBinding(style = Style.DOCUMENT)

public interface FarewellManager {

      @WebMethod int giveComm(String pattern);

}

 

The class implemeting the inteface

 

import javax.jws.WebService;

import javax.jws.WebMethod;

import javax.inject.*;

import javax.annotation.*;

import com.farewell.workflow.*;

import com.farewell.ws.monitoring.FarewellMonitorContainer;

import com.farewell.ws.publisher.FarewellManagerPublisher;

import javax.xml.ws.WebServiceContext;

import javax.xml.ws.handler.MessageContext;

 

import org.apache.log4j.*;

//Service Implementation

@WebService(endpointInterface = "com.farewell.ws.FarewellManager")

public class FarewellManagerImpl extends FarewellBaseManager implements FarewellManager {

      private final int JMS=1;

      private final int EJB=2;

      private final int ERROR=-1;

      static Logger logger = Logger.getLogger(FarewellManagerImpl.class.getName());

     

      @Resource WebServiceContext wcontext;

     

      private WorkflowManager manager;

     

     

      public FarewellManagerImpl ()

      {

            FarewellMonitorContainer.setCondition(FarewellMonitorContainer.PERMIT_BOTH);

      }

      @WebMethod ( exclude=true)

      public void setWorkflowManager(WorkflowManager workflow)

      {

            logger.info("Web Service is instantiating the worflow engine");

           

            this.manager=workflow;

     

      }

      public int giveComm(String pattern) {

            if (this.isUserActive()){

                 

                  if (this.authenticate(user, password)==null)

                  {

                        return -1;

                  }else{

                  String result=manager.executeWorkflow(user);

                                          return checkRestriction(result);  

                  }

                 

            } else{

                  return this.ERROR;

            }

           

      }

      private int checkRestriction(String text){

            logger.info("Checking constrsit");

            if (FarewellMonitorContainer

                        .getCondition()

                        .compareTo(FarewellMonitorContainer.PERMIT_BOTH)==0){

                  if (text.compareTo("ejb")==0){

                        return this.EJB;

                  }

                  if (text.compareTo("jms")==0){

                        return this.JMS;

                  }

                 

            }

            if (FarewellMonitorContainer

                        .getCondition()

                        .compareTo(FarewellMonitorContainer.PERMIT_EJB_ONLY)==0){

                  return this.EJB;

            }

            if (FarewellMonitorContainer

                        .getCondition()

                        .compareTo(FarewellMonitorContainer.PERMIT_JMS_ONLY)==0){

                  return this.JMS;

            }

            return this.ERROR;

      }

}

There is a method which is excluded from the WSDL definition. The reason is that it is needed to inject the Workflow class implementing the workflow functionality via Spring.

To generate the rest of classes needed to deploy the Web Service, the following command is required.

wsimport -keep http://localhost:9980/service/FarewellWS?wsdl

 

This command generates extra classes that must be included in the project.

To launch as an standalone the Web Service, in the context of Spring, these two beans must be included:

<bean class="org.springframework.remoting.jaxws.SimpleJaxWsServiceExporter">

      <property name="baseAddress" value="http://localhost:9980/service/FarewellWS"/>

      </bean>

     

<bean id="farewellManagerImpl" class="com.farewell.ws.FarewellManagerImpl">

      <property name="workflowManager"><ref bean="farewellWorkflowManager"/></property>

      </bean>

 

This chuck of application context creates the Service deploying the EndPoint in a standalone way. You can see that the “workflow manager” is injected.

To start the application context, there is a class that does this action:

package com.farewell.ws.publisher;

import com.farewell.ws.*;

 

import javax.xml.ws.Endpoint;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class FarewellManagerPublisher {

 

      public static void main(String[] args) {

           

            //Endpoint.publish("http://localhost:9980/service/FarewellWS", new FarewellManagerImpl());

            ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

 

     

      }

 

}

 

The invocation of the service from a “console” client application is as follow:

package com.client;

import java.net.URL;

import javax.xml.namespace.QName;

import javax.xml.ws.Service;

import com.farewell.ws.*;

import java.util.Collections;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

 import javax.xml.ws.BindingProvider;

import javax.xml.ws.handler.MessageContext;

 

public class Cliente1{

 

      public static void main(String[] args) throws Exception {

 

      URL url = new URL("http://localhost:9980/service/FarewellWS?wsdl");

        QName qname = new QName("http://ws.farewell.com/", "FarewellManagerImplService");

 

        Service service = Service.create(url, qname);

 

        FarewellManager manager = service.getPort(FarewellManager.class);

       

        Map<String, Object> req_ctx = ((BindingProvider)manager).getRequestContext();

        req_ctx.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://localhost:9980/service/FarewellWS?wsdl");

 

        Map<String, List<String>> headers = new HashMap<String, List<String>>();

        headers.put("Username", Collections.singletonList("user4"));

        headers.put("Password", Collections.singletonList("puser1"));

        req_ctx.put(MessageContext.HTTP_REQUEST_HEADERS, headers);

 

 

    }

 

}

As you can see, the user and password are conveyed to authenticate the operation. The authentication is quite basic but it is a good approach to show how it works. All about login is delegated to the parent class

package com.farewell.ws;

 

import javax.annotation.Resource;

import javax.xml.ws.WebServiceContext;

import javax.xml.ws.handler.*;

 

import org.apache.log4j.Logger;

 

import com.farewell.ws.provider.FarewellAuthorization;

import com.farewell.ws.provider.FarewellAuthorizationProvider;

import com.farewell.ws.provider.FarewellUserInfo;

 

import java.util.*;

 

public class FarewellBaseManager {

      static Logger logger = Logger.getLogger(FarewellBaseManager.class.getName());

      @Resource

      protected  WebServiceContext wcontext;

      protected String user;

      protected String password;

      protected  boolean isUserActive(){

            logger.info("Service is checking if user is provided");

            MessageContext mctx = wcontext.getMessageContext();

             

            //get detail from request headers

              Map http_headers = (Map) mctx.get(MessageContext.HTTP_REQUEST_HEADERS);

              List users = (List) http_headers.get("Username");

              List passwords = (List) http_headers.get("Password");

              if (users==null || passwords==null) return false;

             

              user= users.get(0).toString();

              password=passwords.get(0).toString();

              System.out.println("Usuario" + user + " password " + password);

       

            return true;

      }

      protected FarewellUserInfo authenticate (String user, String password)

      {

            logger.info("User is being authenticated");

            FarewellAuthorization provider=new FarewellAuthorizationProvider();

            return provider.authenticate(user, password);

           

           

      }

     

     

}

The rest of the classes involved in the authentication process are the following

package com.farewell.ws.provider;

 

public interface FarewellAuthorization {

      public FarewellUserInfo authenticate(String user, String password);

}

 

package com.farewell.ws.provider;

 

public class FarewellAuthorizationProvider implements FarewellAuthorization{

 

      public FarewellUserInfo authenticate(String user, String password) {

           

            if (((user.compareTo("user1")==0) && (password.compareTo("puser1")==0))

            || ((user.compareTo("user2")==0) && (password.compareTo("puser2")==0))){

                  return new FarewellUserInfo(user, password);

            }

           

            return null;

      }

     

}

package com.farewell.ws.provider;

 

public class FarewellUserInfo {

     

      private String user;

      private String password;

      public FarewellUserInfo(String user, String password){

            this.user=user;

            this.password=password;

      }

      public String getUser() {

            return user;

      }

      public String getPassword() {

            return password;

      }

     

}

 

This Web Service provides a JMX MBean for tunning it properly. We can see it in other article.

WORKFLOW Creation

Creating a process and executing it is quite easy with jBPM once the development environment is well conformed. I assume this task is already done properly.

The first thing to do is to write the jdpl file that defines the process to be executed.

<?xml version="1.0" encoding="UTF-8"?>

 

<process name="process1" xmlns="http://jbpm.org/4.0/jpdl">

   <start g="256,25,48,48" name="start1">

      <transition g="-68,-18" name="ichannel" to="exclusive1"/>

   </start>

   <decision g="257,95,48,48" name="exclusive1">

    

      <transition g="-49,-18" name="to ejb" to="ejb">

            <condition expr="#{channel==&quot;user1&quot;}" />

      </transition>

      <transition g="-49,-18" name="to jms" to="jms">

            <condition expr="#{channel==&quot;user2&quot;}" />

      </transition>

     

   </decision>

   <state g="162,173,92,52" name="ejb">

      <transition g="-42,-18" name="to end1" to="end1"/>

   </state>

   <state g="326,169,92,52" name="jms">

      <transition g="-42,-18" name="to end1" to="end1"/>

   </state>

   <end g="270,256,48,48" name="end1"/>

</process>

 

As you can see, the process takes a decision depending on the channel variable value (user 1 or user2). If the user that request the action to the Web Service is “user1”, the process indicates that the message must be persisted via EJB. If the user is “user2”, the communication will be via JMS. Graphically,  the process is the following

There are a class that manages  the process and launches the process instances. This class is injected (IoC) to the Web Service via Spring context.

package com.farewell.workflow;

import org.jbpm.api.ProcessInstance;

import java.util.HashMap;

import java.util.Map;

import org.jbpm.api.Configuration;

import org.jbpm.api.ExecutionService;

import org.jbpm.api.HistoryService;

import org.jbpm.api.ManagementService;

import org.jbpm.api.ProcessEngine;

import org.jbpm.api.RepositoryService;

import org.jbpm.api.TaskService;

import org.jbpm.api.Execution;

public class WorkFlowManagerImpl implements WorkflowManager {

      private String deploymentId;

      private ProcessEngine processEngine;

      private RepositoryService repositoryService;

      private ExecutionService executionService;

      public WorkFlowManagerImpl(){

           

            processEngine = new Configuration()

            .buildProcessEngine();

            repositoryService = processEngine.getRepositoryService();

           executionService = processEngine.getExecutionService();

         

          // Deploying a process

           deploymentId = repositoryService.createDeployment()

              .addResourceFromClasspath("process1.jpdl.xml")

              .deploy();

 

           

           

           

           

      }

      public String executeWorkflow(String text) {

           

            String result;

            Map<String, Object> variables = new HashMap<String, Object>();

         

            variables.put("channel", text);

          ProcessInstance processInstance = executionService.startProcessInstanceByKey("process1", variables);

          if (processInstance.isActive("ejb")){

            result="ejb";

            executionService.endProcessInstance(processInstance.getId(), "ejb");

          } else

          {

            result="jms";

             executionService.endProcessInstance(processInstance.getId(), "jms");

          }

            return result;

      }

 

}

 

The maven files for the Web Service project is the following

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>

  <groupId>com.farewell.webservice</groupId>

  <artifactId>FarewellWebService</artifactId>

  <version>0.0.1-SNAPSHOT</version>

 

      <dependencies>

            <dependency>

      <groupId>org.springframework</groupId>

      <artifactId>spring</artifactId>

      <version>2.5.6</version>

</dependency>

           

            <dependency>

                  <groupId>javax.inject</groupId>

                  <artifactId>javax.inject</artifactId>

                  <version>1</version>

            </dependency>

            <dependency>

                  <groupId>com.farewell.workflow</groupId>

                  <artifactId>FareWellWorkflowManager</artifactId>

                  <version>0.0.1-SNAPSHOT</version>

            </dependency>

 

      </dependencies>

      <build>

            <plugins>

                  <plugin>

                          <groupId>org.apache.maven.plugins</groupId>

                          <artifactId>maven-jar-plugin</artifactId>

                          <version>2.4</version>

                          <configuration>

                             <archive>

                                   <manifest>

                                         <mainClass>com.farewell.ws.publisher.FarewellManagerPublisher</mainClass>

                                   </manifest>

                             </archive>

                          </configuration>

                  </plugin>

     

           

            </plugins>

     

     

      </build>

</project>

 

The maven file for the WorkflowManager project is the following:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>

  <groupId>com.farewell.workflow</groupId>

  <artifactId>FareWellWorkflowManager</artifactId>

  <version>0.0.1-SNAPSHOT</version>

 

 

<dependencies>

     

      <dependency>

      <groupId>javax.inject</groupId>

      <artifactId>javax.inject</artifactId>

      <version>1</version>

</dependency>

      <dependency>

            <groupId>org.jbpm.jbpm4</groupId>

            <artifactId>jbpm-jpdl</artifactId>

            <version>4.1</version>

      </dependency>

    <dependency>

      <groupId>hsqldb</groupId>

      <artifactId>hsqldb</artifactId>

      <version>1.8.0.7</version>

    </dependency>

  </dependencies>

  </project>