The Source for Java Technology Collaboration
User: Password:
Register | Login help    

Search

Online Books:
java.net on MarkMail:


Edgar Silva

Edgar Silva is a highly recognized consultant, technical leader, teacher and speaker in Brazil. As a Solutions Architect at JBoss, a division of Red Hat, he is responsible for JBoss products in Brazil helping customers and partners to design and develop very large JEE applications for several industries in the finance, telcos and B2C markets. He has been using Java since J2EE was just a dream. Furthermore, Edgar is a frequent Java speaker at events in Brazil, such as Comdex, Fisli, BorCon, JustJava, CafeBrasil, BrasilOne, Maratona4Java, as well as JavaOne in USA . He is NetBeans Dream Team founding member and also helps on Soujava(Java User Group Society) management .

 

Edgar Silva's blog

Creating a Process Server based on OpenSource Technologies using REST

Posted by edgars on August 4, 2008 at 6:01 PM PDT

This is a post where I will try share some thoughts about where REST could be useful inside a SOA architecture using Business Process Management, in that case we will be using jBPM and RESTEasy, which is the JBoss's implementation for JSR311 - Java Restful WebServices.

RESTEasy

RestEasy is a project that is getting a good relevance in terms of integration with some projects inside JBoss.ORG and even other projects. If you are trying use a simple REST implementation you should take a look on this projects, basically there are few steps you must to do to put RestEasy working for your Application, so see the following Steps:

  1. Download the RESTEasy from JBoss.ORG

  2. There is a worth documentation in RESTEasy Wiki, which I strongly recommend you read it first, in addition to this, in order to see some foundation for practical REST application, you can read this great blog entry written by Carol McDonald

  3. To make the things works, I recomend you read this link: http://wiki.jboss.org/wiki/RESTeasyInstall , RESTEasy is pretty easy to understand and apply in even legacy Java applications, where you can expose some methods simply putting some annotations into your pojos. Basically the steps are:

  • RESTeasy is deployed as a WAR archive and thus depends on a Servlet container. When you download RESTeasy and unzip it you will see that it contains an exploded WAR. Make a deep copy of the WAR archive for your particular application. Place your JAX-RS annotated class resources and providers within one or more jars within /WEB-INF/lib or your raw class files within /WEB-INF/classes. RESTeasy is configured by default to scan jars and classes within these directories for JAX-RS annotated classes and deploy and register them within the system:

Custom configuration

RESTeasy is implemented as a ServletContextListener? and a Servlet and deployed within a WAR file. If you open up the WEB-INF/web.xml in your RESTeasy download you will see this:

<web-app>
   <display-name>Archetype Created Web Application</display-name>
   <context-param>
      <param-name>resteasy.scan</param-name>
      <param-value>true</param-value>
   </context-param>

   <listener>
      <listener-class>org.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
   </listener>

   <servlet>
      <servlet-name>Resteasy</servlet-name>
      <servlet-class>org.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
   </servlet>

   <servlet-mapping>
      <servlet-name>Resteasy</servlet-name>
      <url-pattern>/*</url-pattern>
   </servlet-mapping>

</web-app>

The ResteasyBootstrap listener is responsible for initializing some basic components of RESTeasy as well as scanning for annotation classes you have in your WAR file. It receives configuration options from <context-param> elements. Here's a list of what options are available

  • And that's all! Everything you need is ready to run your REST Services in any JEE App Server.

Proof of Concept of a “Process Server”

We have several open source BPM Engines , I am using JBoss jBPM because I wanna show you a Web-Console where the process are running on, in addition a graphical tool to design my processes.

First of all I have a really simple “Controller” based on REST principles, nothing too complex or beautiful so far, but is useful, so I created a simple class called RestService.java where you can find many useful methods to operate business process using jBPM. Based on my own experience could be considered a “best practice” you design your URLs first, who knows some day we could create a tool (ant or maven), that could based on a text file containing one URL per line, where after reading it could create an abstract class with the methods. (Maybe a good way to forget any XML). Based on this practice I wanna give the ability for PHP, .net or even HTML interact with my “Process Server”, to do that I can have the following URLs:

  1. /start/process/{some process}/{some user to be associated to my Swilanes}, it I can pass via a GET method and I can keep the process id as my return

  2. /signal/process/{the process id I must have stored somewhere}/{user} , via a GET I can navigate into my process

  3. /process/{process id}/add/var , via a GET I can get a way to add some variables for my process execution

    Based on these 4 actions I defined above, I can show you now how implement them:

1- Start a new Process Instance

  • For jBPM you must have access to Context, which is the key object to operate processes using jBPM.

  • The following code shows this method in action:

@GET

@Path("/start/process/{processdefinition}/{user}")

@ProduceMime("text/plain")

public String startProcesInstance(

@PathParam("processdefinition")String processDefintion,

@PathParam("user")String user) {

JbpmContext ctx = JbpmConfiguration.getInstance().createJbpmContext();

try {

ProcessInstance instance = ctx.newProcessInstance(processDefintion);

instance.getContextInstance().setVariable("user", user);

Token t = instance.getRootToken();

t.signal();

ctx.save(instance);


return new Long(instance.getId()).toString();

}

catch (Exception e) {

e.printStackTrace();

}

finally {

ctx.close();

}

return "ERROR";


      }

2 - Signaling your Process

Once you have your Process Id, you can operate it and do whatever you want, this is one of the “Key-benefits” in jBPM, the ability to keep everything related to the process stored in the database, and not in the memory, it allow you have several application interacting with your Process Engine, for my testing, I have jBPM Server (jBPM+JBoss [could be any other AppServer]) in one IP address, and a TomCat with my simple REST application based in RESTEasy. Keep in mind, that having your process stored in regular tables in many Databases supported by Java, you shall create many kinds of applications, you may use Hibernate for persistence, query and cache as well as JDBC or even Spring helpers. See the following source code to allow this action:

@GET

@Path("/signal/process/{id}/{user}")

@ProduceMime("text/plain")

public String signalProcess(

@PathParam("id")String id,

@PathParam("user")String user) {

JbpmContext ctx = JbpmConfiguration.getInstance().createJbpmContext();

try{

GraphSession graphSession = ctx.getGraphSession();

ProcessInstance processInstance = graphSession.loadProcessInstance((new Long(id)).longValue());

processInstance.signal();

ctx.save(processInstance);

return processInstance.getRootToken().getNode().getName();

} catch (Exception e ) {

e.printStackTrace();

return "ERROR";

}

finally {

ctx.close();

}

}



3 – Adding variables to your processes via a simple URL

  • For many reasons, you might need some variables for your processes, maybe for a decision taken or for anything else, so the following source shows how you can get the HttpServletRequest using the injection executed by the REST implementation. This method shows you how you can use contextual http objects, besides your variables from URL.

  • This could be really useful to capture other information, or even process some files not using GET method, but the POST method for instance, see the following implementation:

@GET

@Path("/process/{id}/add/var")

@ProduceMime("text/plain")

public String addVariables(

@PathParam("id")String id,

@Context HttpServletRequest request) {

JbpmContext ctx = JbpmConfiguration.getInstance().createJbpmContext();

try{

GraphSession graphSession = ctx.getGraphSession();

ProcessInstance processInstance = graphSession.loadProcessInstance((new Long(id)).longValue());

Enumeration params = request.getParameterNames();

String param;

StringBuilder b = new StringBuilder();

while (params.hasMoreElements()) {

param = (String) params.nextElement();

processInstance.getContextInstance().setVariable(param, request.getParameter(param));

b.append(String.format("Param:%s=%s is Stored in BPM Context\n",param,request.getParameter(param)));

}

ctx.save(processInstance);

return b.toString();

} catch (Exception e ) {

e.printStackTrace();

return "ERROR";

}

finally {

ctx.close();

}

}

Time for Testing

As far you can see, everything on our example just returns basic “plain texts” as results, so we can use those everywhere, in The Developers Conference (A Brazilian Java Conference) I did an examples really “old school”, I used a Borland Delphi 5 client, in terms of integration, I can get an existing Delphi or Visual Basic Application and integrate them with my “Process Server”, than for our Proof of Concept. My process for testing is really easy, as far you can see in the following image:




This is a simple “Buying Process”, where could be used for many different scenarios, on our case, we try simulate a simple Delphi client interacting with this process. On Delphi's side, I need just a component to interact with HTTP requests and nothing else, so in my case I used TidHTTP object for it.

My Process Server in Action

When we execute the following URL: http://192.168.161.1:8080/flowlet/start/process/buyticket/edgar , we are informing the process name: buyticket and the user ir edgar , and the result we can expect is a text with process id as the text returned via Http, see the following image:




After execute our method, the process instance id is 124, this id might be used for this process interaction, at this moment, my application is used a process which was deployed in my Process Server, and then we can create a new instance from the process called buyticket , so everything is stored in the database, and we can create any kind of information based on database tables about our process instances, such as: “Execution time”, “Troubleshooting” and so on.

Now, it's time to see our JBoss jBPM Console in action, take a look on my process listing and you can see the process instance id: 124




And you can see where in the process, you process instance actually is stopped:




Now, it's time to navigate through the process instance, so I will execute the following rest URL: http://192.168.161.1:8080/flowlet/signal/process/124/edgar , the result are the following screen shots:




This method, basically execute the signal into the process instance, and move the process to the next node, as far you can in the result and in the following image in the jBPM Console:




Adding the variables based on HttpServletRequest shall be executed using the following URL: http://192.168.161.1:8080/flowlet/process/124/add/var?payment=Yes&blog=Edgar , so based on the Java Web technologies, you can assume that you have 2 variables: payment and blog, so what we wanna do now is to transfer these variables from http context, which are durable just while the server is running or some clustering replication in really durable information stored in the database as process variables. In addition to this capacity, imagine that we need some variable to define some execution path in the process instance handling, like a decision handler based on some expression(EL) based on some variable, for instance: expression='#{payment=="No"}'; this expression can decide in the decision-node “Is Payment Approved?” which path(direction) the process will go as the next execution node and transitions. See the results in the following images:




Now, we can signal the process again, and the results in our jBPM Server could be as the following :




Conclusion

Basically, as far you can see Process Server is something beyond a product, can be a concept that you can apply in many different ways, and one of that, for sure could be using Open-Source technologies, such as we had shown here on this entry.









Related Topics >> Java Web Services and XML      
Comments
Comments are listed in date ascending order (oldest first)
Syndicate content