views:

1487

answers:

3

What is the best way to create a java application that can be run using ‘service’ on Linux? I was going to use the JSW available here, but cannot use the licence on that (licence is either GPL or it costs money as far as I can tell). I’d need an apache style licence.

I’m using maven to build, so it would be great if it was possible to create the service using a maven plugin, but any other suggestions would be great.

I've seen Apache Commons Daemon, is there a maven plugin for this? Documentation seems sparse, so a working example of this would be good...

Thanks

A: 

You can look at the following projects.

Firstthumb
+5  A: 

Services on Linux are just shell scripts which start background processes. Have a look in /etc/init.d - you can open the files in a text editor. All you need is a bash script which responds to the parameters start and stop in an appropriate way (eg. start will start your service and record the process ID in a known location, stop will kill the process with the PID from the file you created), and then place it in /etc/init.d.

Have a look at Init Scripts and An introduction to services, runlevels, and rc.d scripts

robertc
+2  A: 

As far as I know there isn't a Maven plugin for either Apache Daemon or Akuma. Though you could attempt to invoke them from within a Maven build by using the maven-exec-plugin.


As far as your companies reservations about using GPL-licensed products, it's worth reading up on the implications of use. It is not as virulent as corporations fear. Here's an interpretation of the GPL. It of course doesn't carry any weight in law (and may not be correct or supported by precedent, I am not a lawyer), but might be sufficient to allow you to start a conversation with your legal people.

From the referenced page:

Simply combining a copyrighted work with another work does not create a derivative work. The original copyrighted work must be modified in some way. The resulting derivative work must itself "represent an original work of authorship." So if the licensee does not modify the original GPL-licensed program, but merely runs it, he is not creating a derivative work.


There is the Appassembler Maven plugin that I think does what you need (though it does create JSW wrappers). It creates a shell script (and a bat file), and collects all the application jars into a directory. It can optionally be configured to create JSW-based Daemon configurations.

Here is an example configuration that will generate the standalone application in the target/appassembler folder, and generate the JSW wrapper files in the target/appassembler/jsw/myApp directory. Note the assemble goal is bound to the integration-test phase to ensure the project's jar is created. To generate the output run mvn verify or to just generate the service wrappers run mvn package:

  <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>appassembler-maven-plugin</artifactId>
    <version>1.0</version>
    <executions>
      <execution>
        <id>assemble-standalone</id>
        <phase>integration-test</phase>
        <goals>
          <goal>assemble</goal>
        </goals>
        <configuration>
          <programs>
            <program>
              <mainClass>name.seller.rich.MyMainClass</mainClass>
              <name>myShellScript</name>
            </program>
          </programs>
          <platforms>
            <platform>windows</platform>
            <platform>unix</platform>
          </platforms>
          <!--collect all jars into the lib directory-->
          <repositoryLayout>flat</repositoryLayout>
          <repositoryName>lib</repositoryName>
        </configuration>
      </execution>
      <execution>
        <id>generate-jsw-scripts</id>
        <phase>package</phase>
        <goals>
          <goal>generate-daemons</goal>
        </goals>
        <configuration>
          <!--declare the JSW config -->
          <daemons>
            <daemon>
              <id>myApp</id>
              <mainClass>name.seller.rich.MyMainClass</mainClass>
              <commandLineArguments>
                <commandLineArgument>start</commandLineArgument>
              </commandLineArguments>
              <platforms>
                <platform>jsw</platform>
              </platforms>              
            </daemon>
          </daemons>
          <target>${project.build.directory}/appassembler</target>
        </configuration>
      </execution>
    </executions>
  </plugin>

For reference the generated files are as follows:

myApp\bin\myApp
myApp\bin\myApp.bat
myApp\bin\wrapper-linux-x86-32
myApp\bin\wrapper-macosx-universal-32
myApp\bin\wrapper-solaris-x86-32
myApp\bin\wrapper-windows-x86-32.exe
myApp\conf\wrapper.conf
myApp\lib\libwrapper-linux-x86-32.so
myApp\lib\libwrapper-macosx-universal-32.jnilib
myApp\lib\libwrapper-solaris-x86-32.so
myApp\lib\wrapper-windows-x86-32.dll
myApp\lib\wrapper.jar
Rich Seller
@Rich - thanks for the answer. I had originally done something like this, but the licence of JSW is too restrictive for me (well my employer!). By the way, is it possible to configure Appassembler from the main project POM on a project with multiple modules? The only way I could figure of doing it was to create a new module with the specific job of creating the service scripts (and RPM in my case) that ran after all of the other modules were packaged...
Lehane
If you run the assemble goal on the module that depends on all the others, those dependencies will be packaged in the appassembler directory. So it probably wouldn't be run on your aggregator pom, but on the module with the "main" class
Rich Seller
also the GPL license isn't as restrictive as corporations tend to believe. Have a read of this: http://www.sitepoint.com/article/public-license-explained/
Rich Seller