Running Java Software on OpenVMS

Thursday, 08 April 2010 01:38

Things have been pretty quiet on my blog for the last few months.  Of course, this doesn't mean things have been quiet with me.  On the contrary, the blog has been neglected because I have been quite busy.  So, here is the first of many posts covering the things that have kept me away.

I don't know how many people reading this have ported Java applications to OpenVMS.  However, if you haven't, it's generally a lot easier than you might think.  Over time I have built up a bit of a "method" for getting Java software up and running quickly on OpenVMS.  My biggest quibble with Java applications is that they often need many of the JAVA$* or DECC$* logicals to be configured.  This often disrupts my environment, which I don't like.  The only "POSIX-like" option I have configured in my login is SET PROCESS/PARSE_STYLE=EXTENDED.  I find that this gives me a decent balance between the traditional DCL and just enough features so I can navigate through UNIX software archives without too much hassle.

When porting any software the first thing I do is check out what has been done for other platforms.  Normally if the package is available on both Windows and a UNIX derivative there is enough of a cross-section to see what sort of things might need changing.  Most Java packages are shipped with both a shell script and a batch procedure for running the software.  Initially I tried using a DCL procedure to do the same thing.  It seemed like the logical step to take.  Unfortunately this didn't work out.

While I don't specifically have a problem with DCL itself, it does have one rather large short-coming when attempting to write a procedure to start a Java application.  The arguments, P1-P8 are all uppercased! Even is you have altered the parse style of your session.  The only solution is to either quote everything, like back in the days before many of the current DECC$* feature logicals existed or try and put some smarts into the DCL procedure to guess the case of arguments.  All this is way to much work and potentially dangerous.  All I wanted to be able to type my commands just like they were described in the existing documentation.  So here is my solution...

I use the SPAWN and PIPE commands to configure a usable environment for Java software on OpenVMS.  The biggest reason for using a DCL procedure to start a Java package is that it is often necessary to do some configuration before running the software.  Java commands often end up being quite lengthy too.  So, to counter this I use the PIPE command and the sequential execution operator, or semi-colon (";").  By doing this I am able to run a number of DCL commands from the one PIPE command.  Into this I put the configuration of the environment, as well as the command to start the software.  Here is an example of the DCL symbol I was initially using to start my port of Maven:

$ mvn == "pipe def/u JAVA$DELETE_ALL_VERSIONS 1 ; " -
            + "def/u DECC$FILE_PERMISSION_UNIX 1 ; " -
            + "def/u JAVA$FORK_SUPPORT_CHDIR 1 ; " -
            + "def/u JAVA$FILENAME_CONTROLS 0 ; " -
            + "def/u DECC$ARGV_PARSE_STYLE ENABLE ; " -
            + "def/u DECC$EFS_CASE_PRESERVE ENABLE ; " -
            + "def/u DECC$EFS_CHARSET ENABLE ; " -
            + "java -classpath ""''classpath'"" ''f$trnlnm(""MAVEN_OPTS"")' "
            + "-Dclassworlds.conf=/m2_home/bin/m2.conf " -
            + "-Dmaven.home=/m2_home " -
            + """ org.codehaus.classworlds.Launcher"""

The example above is the method I used for some time to get Java software started on OpenVMS.  This method has two drawbacks.  The first is that it requires the executing process to have its /PARSE_STYLE set to EXTENDED.  This was not something I gave a lot of thought to as I enable the extended parse style at login.  The second I did not discover until I began porting Maven to OpenVMS.  Maven likes to SPAWN sub processes to do much of its work, just like MMK, MMS or GNU Make.  The sub processes could not get the advantages of the feature logicals as they were defined /USER which ensures that the logicals only exists in the context of the Java process and not in the parent or any spawned processes.  To counter this I started using the SPAWN command to kick off the PIPE command.  I could drop the /USER qualifier from the DEFINE commands and the logicals would now carry over to all child processes started by the Java software with the advantage of being kept from the parent also.  Here is the final symbol definition I now use to start Maven:

$ mvn == "spawn/nolog pipe set process/parse=extended ; " -
            + "@sys$manager:java$150_setup ; " -
            + "def JAVA$DELETE_ALL_VERSIONS 1 ; " -
            + "def DECC$FILE_PERMISSION_UNIX 1 ; " -
            + "def JAVA$FORK_SUPPORT_CHDIR 1 ; " -
            + "def JAVA$FILENAME_CONTROLS 0 ; " -
            + "def DECC$ARGV_PARSE_STYLE ENABLE ; " -
            + "def DECC$EFS_CASE_PRESERVE ENABLE ; " -
            + "def DECC$EFS_CHARSET ENABLE ; " -
            + "java -classpath ""''classpath'"" ''f$trnlnm(""MAVEN_OPTS"")' " -
            + "-Dclassworlds.conf=/m2_home/bin/m2.conf " -
            + "-Dmaven.home=/m2_home " -
            + """org.codehaus.classworlds.Launcher"""

An advantage of using the SPAWN command is that it is now no longer necessary for the parent process (the one executing the mvn command) to have extended parse style enabled, or even a Java environment confgured.  So, the basic template is:

$ cmd = "SPAWN/NOLOG PIPE SET PROCESS/PARSE_STYLE=EXTENDED ; " - [1]
            + "@<java-setup-procedure> ; " -                     [2]
            + "DEFINE <JAVA$-or-DECC$-logical> <value> ; " -     [3]
            + "java <java-options-and-program>"                  [4]
  1. Defining the foreign command.  This part should be copied verbatim (well almost).  If the command starts to get big it can often be neccessary to shorten the DCL commands to their absolute minimum.
  2. Insert your preferred Java startup procedure here.  You may want to use some clever DCL in the procedure that defines your command to determine the most recent Java version installed on the system.  I have some code that does this, but I will save that for another post.
  3. Here is where you put your JAVA$*, DECC$* and other environment configuration steps.
  4. Lastly, this is the actual Java command.  Please replace <java-options-and-program> with those most relevant to your application.

It is important to remember that the above symbol works because of Extended DCL which is available on OpenVMS Alpha V7.3-2 and higher and all versions of OpenVMS I64.  Prior to this DCL had the command line limit of 256 characters which would not allow this use of the PIPE command to work.  Thankfully it is not really an issue as most Java software requires a recent version of OpenVMS and there is no Java for OpenVMS VAX.  There are also no issues passing command line arguments as they tack right on to the end of the foreign command.  Do also remember not to enclose the PIPE arguments in parentheses as any extra arguments will not be passed to the Java VM.  The parentheses in a PIPE command server to delimit the commands that will execute in a single process.

Something else you might notice in the example is the definition of JAVA$FILENAME_CONTROLS.  I don't like many of the JAVA$* logicals, but this must be my least favourite.  From what I can tell, this logical hails from a time when Java under OpenVMS ran on ODS-2 disks and UNX-style file names often needed a bit of extra munging.  Fortunately, those days are over.  I find it best to set this logical to 0 and use the DECC$* logicals to define how file names are handled.  Otherwise a lot of unexpected transformations can occur to the file name before it is actually used.

Maven on OpenVMS

At this time I am still working on the port.  It is coming along exceptionally well.  The following are a some of the more important tasks that have been acheived:

  • Successfully ran mvn compile against Scala and Java code modules.
  • Successfully ran mvn clean.
  • Completed extensive work to allow Apache Commons Exec to work correctly on OpenVMS.  These changes have not yet made it back to the source pool though.  This will happen in the very near future.
  • Successfully set up the Scala+Lift basic example app. and executed mvn jetty:run.

There is still much to be done, but a release of a largely working build system is imminent.  To keep up to date with progress you can follow this blog (as you may already do) by signing up to the [RSS feed] as well as follow @tesneddon on Twitter for shorter, more frequent updates.

[PRINT]  [PRINT]