Build windows service from java application with procrun
Recently, I needed to adjust a Java application to be able to run as a Windows service which is the Windows equivalent to a Unix daemon. There are several libraries available for this kind of task and after some reading, I chose Apache procrun which turned out to be a good choice. The configuration was less painful than expected and the tool seems quite powerful, due to a large set of configuration options. Also, building a Windows service or a Unix daemon should not make much of a difference.
Everything you need to know about procrun really is on the page that is linked above. There even is a basic tutorial. However, the documentation is not overly verbose and it took me some time to get everything up and running, so I think a more verbose basic tutorial will not hurt.
To begin with, you need a Java application. You can built a service from more or less any application and here is a simple class, SomeService with some artifical behaviour:
package com.wordpress.joerglenhard.procrun.demo;
public class SomeService {
private static boolean stop = false;
public static void start(String[] args) {
System.out.println("start");
while (!stop) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.println("running");
}
}
public static void stop(String[] args) {
System.out.println("stop");
stop = true;
}
public static void main(String[] args) {
if ("start".equals(args[0])) {
start(args);
} else if ("stop".equals(args[0])) {
stop(args);
}
}
}
The application acknowledges the call of the start method and then keeps on printing the String “running” every second until it is stopped through the stop method.
Actually, the normal main method and the other two static methods are alternatives for starting and stopping the service. I found both ways useful and will get to that later.
Next, you need to build an executable from this class. For Windows that would be the usual .exe, but an executable jar file is just as fine. I used a jar file and though the contents are very basic, for completeness, here is the MANIFEST.MF:
Manifest-Version: 1.0 Class-Path: . Main-Class: com.wordpress.joerglenhard.procrun.demo.SomeService
Now, you need procrun to turn that into a Windows service. Download it from the procrun download page and unpack whatever you chose to download. In my case, this was version 1.0.10 of the Windows binaries and the essential part in the archive is prunsrv.exe, the procrun service application which is responsible for installing and removing the service. prunmgr.exe is also an extremly useful application that provides a GUI to set everything you can configure via batch scripts.
The difficult part now is to install the service. This can be done by a call of prunsrv.exe with appropriate options. There are quite some options you can / have to use, so this is best packaged as a batch script which I called installService.bat:
set SERVICE_NAME=TestService set PR_INSTALL=C:\workspaces\blog\procrun-demo\prunsrv.exe REM Service log configuration set PR_LOGPREFIX=%SERVICE_NAME% set PR_LOGPATH=c:\logs set PR_STDOUTPUT=c:\logs\stdout.txt set PR_STDERROR=c:\logs\stderr.txt set PR_LOGLEVEL=Error REM Path to java installation set PR_JVM=C:\Program Files (x86)\Java\jre7\bin\client\jvm.dll set PR_CLASSPATH=someservice.jar REM Startup configuration set PR_STARTUP=auto set PR_STARTMODE=jvm set PR_STARTCLASS=com.wordpress.joerglenhard.procrun.demo.SomeService set PR_STARTMETHOD=start REM Shutdown configuration set PR_STOPMODE=jvm set PR_STOPCLASS=com.wordpress.joerglenhard.procrun.demo.SomeService set PR_STOPMETHOD=stop REM JVM configuration set PR_JVMMS=256 set PR_JVMMX=1024 set PR_JVMSS=4000 set PR_JVMOPTIONS=-Duser.language=DE;-Duser.region=de REM Install service prunsrv.exe //IS//%SERVICE_NAME%
Open the command prompt and move to the directory where the script is located. The script modifies the registry, so it needs to have administrator privileges to execute successfully. The first line sets the service name which determines its registry key. Next, you need to set the path to prunsrv.exe. On that note, here is a lesson that took me some time to learn: If you use (correct) relative paths to files in the installation script, the service will install correctly and it will run fine in debugging mode. It will however fail when run normally with any administrative tooling you have. Be it the usual Windows management console (Computer -> Manage -> Services and Applications -> TestService) or prunmgr.exe. Generally, you should use absolute paths with procrun. Interestingly, there is one exception to this rule: the jar file you use as classpath. Here, the relative path worked out fine for me. Another lesson, I found on stackoverflow, is that you must not use white spaces in the service name.
But back to the script: Lines 5 – 9 set the logging behaviour This needs to be adjusted to proper paths of the system. The same applies to line 12 which needs to point to a jvm, on my system this is a client jvm. This is required, because the service here is set to run in jvm mode (line 17). In java mode, the JAVA_HOME environment variable is used to resolve the jvm location. The difference between the modes essentially is that the jvm mode starts the service in-process while the other modes (java or exe) use a separate one.
Lines 16 – 19 and 22 – 24 reference the class that allows to start and stop the service which is of course the only class we have here. Furthermore, the methods to be invoked on startup and shutdown are set. You can set the method arguments as well using PR_STARTPARAM or PR_STOPPARAM, but this is required for the methods used here. Had I used the normal main method, the setting of the program arguments would have been required. Lines 27 – 30 set the memory settings of the jvm and last but not least, Line 33 installs the service.
Now, you can use prunsrv.exe to run the service in debugging mode (you can do that without administrator privileges) which uses the current command prompt as output:
> start prunsrv.exe //TS//TestService
This fires up a new window and if you hit CTRL+C to stop the service, you should see something like the following before the window closes:
You might wonder why the service outputs one more “running” after the stop method was invoked. Start and stop are called from different threads, so there can be race conditions. I wanted to keep the service code simple and did not use any synchronization. That’s fine for a trivial example, but not for production code, of course.
Finally, in case you don’t want to keep that service on your system, uninstallation is pretty easy. Simply call (with administrator privileges):
> prunsrv.exe //DS//TestService
So actually procrun is a fine tool that is not difficult to use. You just have to invest some time to dig into it. I hope some people will have that easier with this tutorial.
Basic tutorial for the bpel-g engine
The most well-known open source BPEL engine is Apache ODE. Nevertheless, there are several other engines available that also deserve some attention. One of them I recently started using is bpel-g. This engine is based on the final release of the former ActiveBPEL engine by Active Endpoints. This engine was quite well-known at its time (and used in quite some scientific papers), but the direct support by Active Endpoints for the open source version seems to have discontinued (although I could not find an announcement confirming this). I assume the engine has made it into their BPM suite, but again, this is just guesswork. Today, the engine is still under active development, but with a new name, bpel-g. One of its recent new features is integration with Apache Camel. Bpel-g still falls somewhat short on tutorials which is why I am writing this post.
The engine is quite light-weight and you can run it on tomcat. Here, I provide a simple example for installing the engine and deploying a simple BPEL process, an echo process that replies an int value. I assume that you are familiar with the basics of BPEL and WSDL.
INSTALLATION
To install the engine on tomcat, you need to get three things:
- The engine itself, available here
- Tomcat, for example available here
- A special version of the H2 database, available here
First, you need to put the h2-1.2.122.jar in tomcats lib directory, to be found at $TOMCAT_HOME/lib. The bpel-g.war goes in tomcats webapps directory, located at $TOMCAT_HOME/webapps and that’s it. You can start tomcat (the startup script is located in $TOMCAT_HOME/bin) and the engine gets installed and is ready for use. It creates a directory named bpr in $TOMCAT_HOME where the deployment artifacts ought to go, but first you need to build such an artifact.
BUILDING DEPLOYMENT ARCHIVE AND DEPLOYING A PROCESS
Basically, you need a BPEL process, a WSDL definition serving as interface for the process, and a deployment descriptor. Here is the interface for the echo process defined in the WSDL file (named EchoInterface.wsdl):
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:plink="http://docs.oasis-open.org/wsbpel/2.0/plnktype"
xmlns:vprop="http://docs.oasis-open.org/wsbpel/2.0/varprop"
xmlns:tns="http://dsg.wiai.uniba.de/wsdl/echointerface"
name="EchoInterface"
targetNamespace="http://dsg.wiai.uniba.de/wsdl/echointerface">
<plink:partnerLinkType name="EchoInterfacePartnerLinkType">
<plink:role name="echoInterfaceRole" portType="tns:EchoInterfacePortType"/>
</plink:partnerLinkType>
<types>
<xsd:schema targetNamespace="http://dsg.wiai.uniba.de/wsdl/echointerface">
<xsd:element name="echoRequest" type="xsd:int"/>
<xsd:element name="echoResponse" type="xsd:int"/>
</xsd:schema>
</types>
<message name="echoRequestMessage">
<part name="inputPart" element="tns:echoRequest"/>
</message>
<message name="echoResponseMessage">
<part name="outputPart" element="tns:echoResponse"/>
</message>
<portType name="EchoInterfacePortType">
<operation name="echo">
<input name="echoInput" message="tns:echoRequestMessage"/>
<output name="echoOutput" message="tns:echoResponseMessage"/>
</operation>
</portType>
<binding name="EchoInterfacePortTypeBinding" type="tns:EchoInterfacePortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="echo">
<soap:operation/>
<input name="echoInput">
<soap:body use="literal"/>
</input>
<output name="echoOutput">
<soap:body use="literal"/>
</output>
</operation>
</binding>
</definitions>
Its structure is pretty simple: A partnerLinkType which we need for the BPEL process. Further, type and message definitions for two messages that consist of a single message part, being an int value. A portType definition with a single synchronous operation and a simple document/literal style binding for this operation. You might notice that there is no service and endpoint address definition in this WSDL. From what I have experienced so far, bpel-g is a little bit special here. You can put service definitions in the WSDL and the package will deploy, but the definitions are ignored. For bpel-g, endpoint information needs to go into the deployment descriptor and more on that later.
Now, here comes a BPEL process that provides an implementation for this interface (named Echo.bpel):
<?xml version="1.0" encoding="UTF-8"?>
<process
name="Echo"
targetNamespace="http://dsg.wiai.uniba.de/bpel/echo"
xmlns="http://docs.oasis-open.org/wsbpel/2.0/process/executable"
xmlns:ec="http://dsg.wiai.uniba.de/wsdl/echointerface">
<import namespace="http://dsg.wiai.uniba.de/wsdl/echointerface" location="EchoInterface.wsdl" importType="http://schemas.xmlsoap.org/wsdl/"/>
<partnerLinks>
<partnerLink name="MyRoleLink" partnerLinkType="ec:EchoInterfacePartnerLinkType" myRole="echoInterfaceRole"/>
</partnerLinks>
<variables>
<variable name="ReplyData" messageType="ec:echoResponseMessage"/>
<variable name="InitData" messageType="ec:echoRequestMessage"/>
</variables>
<sequence>
<receive name="InitialReceive" createInstance="yes" partnerLink="MyRoleLink" operation="echo" portType="ec:EchoInterfacePortType" variable="InitData"/>
<assign name="AssignReplyData">
<copy>
<from variable="InitData" part="inputPart"/>
<to variable="ReplyData" part="outputPart"/>
</copy>
</assign>
<reply name="ReplyToInitialReceive" partnerLink="MyRoleLink" operation="echo" portType="ec:EchoInterfacePortType" variable="ReplyData"/>
</sequence>
</process>
The process imports the WSDL file and defines a
partnerLink set to myRole referencing the partnerLinkType from the WSDL file. Furthermore, it defines two variables of the messageTypes from in the WSDL and starts the process with a receive activity that references the appropriate variable and the operation defined in the WSDL porttype. An assign activity copies the input value to the second variable and this variable is used in the final reply activity that replies to the synchronous invocation and ends the process.
There is only one more file required, the deployment descriptor (named deploy.xml):
<?xml version="1.0" encoding="UTF-8"?>
<deploy xmlns="http://www.apache.org/ode/schemas/dd/2007/03"
xmlns:bpel="http://docs.oasis-open.org/wsbpel/2.0/process/executable">
<process xmlns:tns="http://dsg.wiai.uniba.de/bpel/echo"
name="tns:Echo">
<provide xmlns:tns="http://dsg.wiai.uniba.de/wsdl/echointerface"
partnerLink="MyRoleLink">
<service name="tns:EchoInterfaceService" port="EchoInterfacePort"/>
</provide>
</process>
</deploy>
The structure of this descriptor is actually identical to the structure of the deployment descriptors used by Apache ODE. From version 5.2 on, bpel-g supports the ODE structure. Basically, for every process to be deployed, the services provided and invoked need to be listed here. As said before: If you want to set endpoint addresses, this information needs to go here, in the form of a WS-Addressing
EndpointReference. If you do not set it explicitly, a default address is set for your service, in my case this is http://localhost:9080/bpel-g/services/EchoInterfaceService. As a side note: The BPEL process at hand does not invoke a service, but if so, an EndpointReference for that service needs to be put into the deployment descriptor as well.
Now, all you need to do is to build a zip archive of these files (named echo.zip) and put it into bpel-g’s working directory, located at $TOMCAT_HOME/bpr for hot deployment. Eventually (pretty quickly, from what I have seen), the bpel-g deployment scanner will find the new archive, unpack it into $TOMCAT_HOME/bpr/work and thus deploy the process. You can fire up your browser at localhost:8080/bpel-g/ for the bpel-g management pages, where you can see the process deployed and ready for invocation.
INVOKING THE DEPLOYED PROCESS
You can now send SOAP messages to the address http://localhost:8080/bpel-g/services/EchoInterfaceService using the tool of your choice. Mine is soapUI. A sample SOAP request looks like this:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ech="http://dsg.wiai.uniba.de/wsdl/echointerface">
<soapenv:Header/>
<soapenv:Body>
<ech:echoRequest>1</ech:echoRequest>
</soapenv:Body>
</soapenv:Envelope>
And the response I got is this:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<ns1:echoResponse xmlns:aetgt="http://dsg.wiai.uniba.de/wsdl/echointerface" xmlns:ns1="http://dsg.wiai.uniba.de/wsdl/echointerface">1</ns1:echoResponse>
</soapenv:Body>
</soapenv:Envelope>
SUMMARY
The engine is pretty simple to install and use, especially if you compare it to certain commercial products. I suggest you give it a try!
Eclipse “An error has occurred. See the log file .metadata/.log.”
I am currently using Eclipse Indigo Service Release 1 and out of a sudden received a strange error message when trying to open my workspace, or in fact any workspace:
“An error has occurred. See the log file [WORKSPACE-DIR]/.metadata/.log.“
Inspecting the log file, it seems that this behaviour was caused by an OutOfMemoryError error in a subpackage of org.eclipse.core which is somewhat strange, as I have plenty of memory available for the VM. A Google search for the error, suggested to invoke Eclipse via the command line with the -clean option:
eclipse/dir> eclipse -clean
Eclipse successfully started again and subsequently also without the -clean option. However, an interesting message was writen into the log file:
!MESSAGE The -clean (osgi.clean) option was not successful. Unable to clean the storage area: C:\eclipse-dir\eclipse\configuration\org.eclipse.osgi.
Nevertheless, Eclipse is working fine again and I am not experiencing any problems while programming, so I guess that inspite of the log message, the -clean option works.
Paper accepted at Zeus 2012
Tomorrow (Feb. 23, 2012), the fourth central european workshop on services and their composition (ZEUS 2012) will start in Bamberg. A total of 18 papers have been accepted for the on-site proceedings and there will be participants from four countries. For the details, have a look at the program. Apart from helping to prepare coffee and cookies and move around tables, I will also hold a presentation.
My paper with the title Building Orchestrations in B2Bi – The Case of BPEL 2.0 and BPMN 2.0 has been accepted for the on-site proceedings. I will have a glance at the application of different orchestration languages in current top-down choreography-to-orchestration approaches in the domain of business-to-business integration. Using a requirements framework, I will look at two standards that are natural candidates for this task, BPEL and BPMN 2.0 process diagrams.
Nitpicker
The (anonymous) reviewer of a paper I am working on at the moment pointed me to this tool called Nitpicker, written by Niels Lohmann. Its subtitle describes it as “an overly picky language style checker” and after using it this morning to check the style of the aforementioned paper I would add “that is absolutely simple to use, even in the face of poorly formatted text, and provides very helpful style recommendations“. I guess that subtitle would be too long, though…
The tool basically consists of a textbox to which you can copy your text, hit analyze and in milliseconds it highlights problematic words or phrasings and provides an explanation why this is the case as well as advice on how to improve it. I used my LaTeX sources directly, so there were a lot of special characters and macros in the text, but this didn’t bother Nitpicker at all. I would suggest you give Nitpicker a try, I certainly will use it again.
Wat
If you have not already seen it, you should have a look at this excellent screencast by Gary Bernhardt. It is only 4 minutes and don’t forget to turn on your speakers. At CodeMash 2012, Gary talked about some nice little features of ruby and javascript. If you have already seen it, you might want to watch it once more!
Zeus 2012 submission deadline extension
Today, the submission deadline of the 4th central european workshop on services and their composition(Zeus) has been extended for one week. The new submission deadline is January 27, 2012.
Zeus 2012, which will take place in Bamberg, is a high-quality workshop in the area of services science. Here is an excerpt form the Zeus 2012 homepage:
“ZEUS is a classical scientific workshop. We are seeking creative ideas and ongoing scientific work with some preliminary results. ZEUS offers you an open-minded community of services researchers who are willing to discuss your ideas and help you improve your contents for highly ranked conferences. Your submission will be peer-reviewed by at least three independent reviewers and may be rejected, accepted as position statement or as full workshop paper. Innovation and creativity are the most important factors for ZEUS. Of course, the rules of technical correctness and scientific method must be adhered to as well.“
This years workshop focuses on the following topics:
- Integration of choreography and orchestration models
- Conformance notions
- Analysis, simulation and verification
- Modelling and specification
- Execution and monitoring
- Testing, deployment and practical issues
- Adoption models for choreography and orchestration technology
- Value and maturity assessment
- Multi-view and multi-perspective engineering
- Advanced communication qualities in choreography and orchestration scenarios
- Patterns
- Choreographies and orchestrations in Cloud environments
- Interoperability of language formats as well as models
