Newsletters Subscriptions Media Kit About Us Contact Search Home

Stuff
OS/400 Edition
Volume 2, Number 8 -- April 10, 2003

Calling Java from RPG: Beyond the Basics


by Kevin Vandever

[The code for this article is available for download.]

In "Prototyping and Calling Java Methods from RPG," I discussed the new features available in V5R1 to allow you to call Java methods from RPG using the Java Native Interface (JNI). I have heard from many of you out there who have either tried the technique in that article or wanted to try it, but, in either case, still had some questions. For those of you, as well as anyone just now interested in calling Java from RPG, I thought I'd answer some questions and share some more code with you.

CLASSPATH

First, I want to say a little something about the CLASSPATH. For those of you who read the first article and gave the technique a whirl, you may have noticed that you didn't have to do anything with the CLASSPATH. To some of you this may not be a big deal, as you may be new to Java and don't yet understand the importance of the CLASSPATH environment variable. If that is the case, then you may want to check out "How Do I Set My CLASSPATH? Let Me Count the Ways." If you are new to the Java language and want a general overview of some Java concepts, check out "Java Concepts for iSeries Programmers." For those of you already familiar with Java in general and the CLASSPATH environment variable specifically, you may be wondering what sort of black magic I employed to call Java from RPG without concerning myself with the CLASSPATH. Well, even though I spend a considerable amount of time in New Orleans, not very much of what I learn down there helps me out with calling Java from RPG, so instead I simply let OS/400 handle things for me. When you run an RPG program that calls a Java method, the Java Virtual Machine (JVM) is started using the default CLASSPATH. The default CLASSPATH allows you to access the core Java classes that come already installed on your iSeries. If you have written, or plan to write, your own Java classes and methods, and would like to call them from RPG, you will have to modify the CLASSPATH to include the location of your homegrown Java classes. Check out the link to the CLASSPATH article mentioned earlier in this paragraph for more information about setting your CLASSPATH.

Creating the JVM

As I said in the last paragraph, when you call a Java method from an RPG program, the JVM is started for you. So why would you want to start it yourself, manually? There are many reasons, and we will discuss some of those reasons in a future article (that's called a tease in the business), but for now I am going to give you one good reason, and not just because I say it, but because the point has been brought up by others who've dug into stuff a little bit. One minor sticking point with calling Java that I found, and that some of you found and let me know, is that the first call to a Java method is extremely slow. If you plan to make multiple calls to Java methods within the same job, the first time delay may not be a big deal; however, if it is a big deal, or if you plan to call a method once, or very few times in the same job, the fact that the first call is slow may really matter. Well, you don't have to wait until the first time you call a Java method to start the JVM. You can start the JVM first; thus removing the performance hit from an important interactive job or, worse, an impatient but well-within-his-right-to-complain user. I've included the source code, JVMModule, which is a module that can be used to start or stop the JVM for a specific job. Let's first talk about starting the JVM.

At first glance at the source code, you're probably thinking, "how can that Kevin be so gosh darn smart?" Well, I have to admit, I didn't invent the code. I found the snippets while digging around in IBM's RPG manuals and put them together in my own module. The JNI source member that I copied in is already on your iSeries in library QSYSINC, source file QRPGLESRC, so I didn't include it with this article. The JNI source member is the key to all this and is really where all the good stuff is contained. It houses all the necessary pointers to environment variables, procedures, and data structures, as well as all the required definitions for Java data types, Java classes, and constants. It also contains all the necessary prototypes for calls to JNI functions. I will talk in detail about the guts of the JNI source member, and some of the things it allows you to do, in a future article. For now, you just to need to be able to copy it into your module so that you can manually start and stop the JVM.

The second /Copy statement copies in the JVMModuleP source member. This source member contains the prototypes necessary for the two subprocedures created in this module. Let's skip the destroyJVM subprocedure for now and jump down to the getJniEnv subprocedure. This subprocedure allows you to start the JVM up manually. It also allows you to retrieve a pointer to the JVM environment, which allows you to access additional information about the JVM. When you call this subprocedure from your RPG to start the JVM, you will receive a *NULL value if the request was unsuccessful, or a pointer to the JVM environment if your request to start the JVM was successful. Later in our JNI development (I mean growth, not program development) we will do more with that environment pointer, but for now, check for NOT *NULL to ensure that your JVM was started.

The getJniEnv subprocedure first checks to see if the JVM is started and how many are started. Yes, you can start more than one JVM. Again, I'll talk more about that in a future article. If the JVM is started, the subprocedure retrieves the pointer to the JVM environment. If the JVM is not started, the subprocedure retrieves the default JVM settings, including the CLASSPATH, and starts the JVM. It then returns a *NULL for an unsuccessful start, or, if the start of the JVM was successful, the pointer to the environment variables is returned to the calling program.

As you can see, the code is pretty simple; however, if you're not used to free-formed RPG, the code may be confusing to you. You may even think it's Java, but it's not. It's good old RPG. Really all that's happening are the setting of some variables and the calling of JNI subprocedures, all of which are defined in the JNI copy member. Once you compile this module and bind it to your calling program, however you do so in your shop, you can now call the getJniEnv to start the JVM manually, instead of waiting until the first call of a Java method.

A note on compiling. I realize I left the compiling instructions kind of vague. That is because each shop is a little different in the way it implements ILE. Some may create service programs and bind them to the calling programs. Others might place the service programs in a binding directory and bind the binding directory to the calling programs. Still others might not use service programs at all and bind directly to the module or place the module in a binding directory and bind to that binding directory. The choice is yours, and it all depends on your ILE experience and what your shop is doing at the moment.

Now back to our regularly scheduled article.

Destroying the JVM

If you look again at our JVMModule source member, you will find the subprocedure used to destroy the JVM, destroyJVM. It might not be as important to manually destroy the JVM, but if you know that a given job is done calling Java methods, you could certainly clean up after yourself and destroy the JVM right then and there. Otherwise the JVM will get destroyed when the job ends.

IBM does warn that if you destroy the JVM in your job, you might not be able to create another JVM within that job. This is an interesting warning, and one that I have tested but have yet to find true. Now, I do not doubt IBM, because my test could be too simple, but I have manually created the JVM, destroyed it, and then created it again with no problems. Still the warning is out there, and as I mess with this stuff further, I will be sure to report to you anything that I uncover. In fact, I have included the simple program I used to test the creating and destroying of the JVM. JVMTest is a program that attempts to start the JVM and display the results of the start, to destroy the JVM and display the results of the destroy, and, finally, to start the JVM again. This last start is more to test IBM's warning. What I haven't done yet, and I invite you to try, as I will in the near future, is to call a Java method after manually creating and destroying the JVM. I have yet to combine the work from my first article with the stuff in this article. I am in the process of doing just that in order to build a more robust test, as well as to mess around with more advanced techniques and features.

Baby Steps

I have given you a little taste of how you can take more control over the JVM. But this is only the beginning. There is a lot going on under the covers as it relates to communication and data conversion between the typical OS/400 operating system and the JVM. In the next few articles, I am going to take you on a journey deep into the Java Native Interface (JNI) as it relates to RPG. I am only starting this journey myself, so look at it as though we are traveling together and I am going into the scary places first. I will further test the manual creation and destroying of the JVM to see how it affects calling other Java methods. I will also delve into exception handling and debugging calls to Java, as well as unearth more of the nuggets in the JVM environment to see how we might use them. Not many have gone before us, so it might be a bit rough and dangerous, but well worth the effort. Who's with me?


Sponsored By
PROFOUND LOGIC SOFTWARE

Announcing RPGsp!

RPG Smart Pages (RPGsp) is an Integrated Development Environment for creating dynamic web applications.

If you are a shop with strong RPG skills, you can start developing e-Business / e-Commerce or Intranet Applications IMMEDIATELY! It's easier than traditional RPG/DDS development!

RPG Smart Pages (RPGsp) integrates an RPG aware WYSIWYG HTML Designer with RPG-Alive enabled Code Editing Capabilities, allowing you to create and compile dynamic Web applications as well as traditional RPGLE programs from one sophisticated GUI development environment!

For a Free Trial or more information, contact Profound Logic Software at www.ProfoundLogic.com


THIS ISSUE
SPONSORED BY:

Profound Logic Software
ASNA
DRV Technologies
WorksRight Software


BACK ISSUES

TABLE OF
CONTENTS
Calling Java from RPG: Beyond the Basics

Just Push a Button to Get AS/400 Query Results in Excel

Distributing iSeries Java Applications with Web Start

An Alternative Method of Serving Web Pages from AS/400


Editors
Shannon O'Donnell
Kevin Vandever

Managing Editor
Shannon Pastore

Contributing Editors:
Howard Arner
Raymond Everhart
Joe Hertvik
Ted Holt
David Morris

Publisher and
Advertising Director:

Jenny Thomas

Advertising Sales Representative
Kim Reed

Contact the Editors
Do you have a gripe, inside dope or an opinion?
Email the editors:
editors@itjungle.com


Copyright © 1996-2008 Guild Companies, Inc. All Rights Reserved.