Local Navigation

PHP/JavaBridge and WebSphere 4: Using the Compiled JavaBridge Front End

JavaBridge is fairly well supported on a mailing list at  php-java-bridge-users@lists.sourceforge.net -- the archives are available here.  Jost Böekemeier, the creator and lead developer monitors the list and frequently answers questions; in response to some of my queries on architecture and performance he made a statement that seems obvious now, but really made the penny drop for me:

Re: Php-java-bridge-users Documenting WebSphere Integration; Uses of the C or PurePHP ComponentsFrom: <php-java-bridge-users@li...> - 2007-08-14 07:50
Hi,

> the php_java.dll (which I think is what Jost means by the C-based
> extension module ... is this correct?) or alternately the "pure PHP

The php_java.dll or java.so (Unix) is the Java.inc, compiled to native code, yes.


So ... the mystery is solved.  The dll for windows and .so library for linux are simply compiled front ends for specific platforms; the speed improvement is the usual improvement one sees for compiled code.

Recall that everything to this point in our series has explicitly invoked Java.inc from the JavaBridge to obtain a session object.  We now need to switch from the Pure PHP (Java.inc) model to a production-worthy model that uses compiled code.

 Switching to a Compiled Front End ... In Windows

The goal in operational terms can be demonstrated easily.  We have a little PHP program that we use directly from Apache, which accesses a Java session, with a critical section that looks like this:

<?php
ini_set('allow_url_fopen', 'on');
if(!extension_loaded('java')){
    require_once("http://localhost:9080/JavaBridge/java/Java.inc");

}
$session = java_session();
?>

The require_once is the line that effectively directs the script to use the slower Pure PHP (Java.inc) implementation running in our JEE servlet.

A simple test, proving we are running with the compiled C front end instead of the Java.inc Pure PHP front end would be to comment out the require_once, e.g.:

<?php
ini_set('allow_url_fopen', 'on');
if(!extension_loaded('java')){
#    require_once("http://localhost:9080/JavaBridge/java/Java.inc");
}
$session = java_session();
?>

 When we do this in our setup thus far we fail:

Fatal error: Call to undefined function java_session() in C:\Data\drupal\drupal_development\drupal_development\drupal-5.2\sessionPeek.php on line 6

which is quite true ... we've disabled Pure PHP by commenting out Java.inc but have not yet enabled the compiled front end.

Would that it were as simple as it seems.  Still, in all, it's not too bad. 

Enabling the Compiled Front End

 The gist of enabling the compiled front end is simple.  We need to:

  1. Install an appropriate shared library where PHP can get at it
  2. Tell PHP to use the library by modifying PHP.ini
  3. Give PHP some configuration instructions on using the library, again by modifying PHP.ini

How hard is that, right?  The problem is that, probably out of habit and laziness, I used Windows to compile this series.  And Windows is the very devil for configuration and compilation.  The entire process would have gone much better on Linux, where configuration locations are straightforward and compilation is an everyday event.

Nevertheless.

Version Issues for the Compiled Front End

The version of JavaBridge I've been working off of is 4.2.2, an unreleased beta build.  Usually using newer code has served me well; this time not so much.  4.2.2 turns out not to have any compiled libraries in it, just a Java.inc.

I attempted to use the compiled library in 3.2.2, and after some trial and error found that, as with most compiled programs, the version of the library must match the version of the program that calls the library.  Since the library is, in effect, a PHP extension this means that the library and PHP must match in version and a few compilation options.  Turns out that 3.2.2's library was compiled against PHP 5.1 and we've been running PHP 5.2.

The way to discover anomalies of this sort is to enable error reporting at startup in PHP.ini then run PHP direct from the command line.  Once I figured this out (remember, I'm totally new to PHP) the problem was plain:

 C:\PHP>php
PHP Warning:  PHP Startup: java: Unable to initialize module
Module compiled with module API=20050922, debug=0, thread-safety=1
PHP    compiled with module API=20060613, debug=0, thread-safety=1
These options need to match
 in Unknown on line 0




Warning: PHP Startup: java: Unable to initialize module
Module compiled with module API=20050922, debug=0, thread-safety=1
PHP    compiled with module API=20060613, debug=0, thread-safety=1
These options need to match
 in Unknown on line 0



Sad but true.

Now if we were in Linux we could probably build the library against the current PHP without too much trouble.  But we aren't, so effectively we need to drop back to version 3.2.2 from our 4.x version.

Resolving Version Issues in Windows

For reasons unknown to me as a PHP newbie I could find no archived version of PHP 5.1.  It was new or nothing, and new wouldn't run the libraries.  After some research I found that one of the Windows integrated application stack packages called WAMP had a decent archive on SourceForge.  The version we want is wamp5_1.6.5.  I'm sure there was an easier way, but I found this first.  After installing WAMP I found I had a working PHP installation of the correct version, now living at C:\wamp\php.

On running the PHP from WAMP I found some very strange behaviours -- modules I hadn't yet enabled (mysql and gd) but had enabled in the previous PHP install seemed to be configured but not found.  Tons of fooling with the PHP.ini were fruitless.

Turns out that, in accord with some rules I don't know yet, PHP under Windows sometimes insists on finding its PHP.ini file in the WINDOWS root directory!  I know this can be got around, because when you start the wamp PHP from the wamp Apache the local PHP.ini is read, as you'd expect.  But at this point it's just a distraction.

So ... how do you tell which PHP.ini is the one PHP under Windows is reading?  Easy.  Call phpinfo().

Determining PHP Configuration

phpinfo() is one useful little function.  At this point the PHP developers reading this are rolling on the floor laughing, but trust me, Java developers just don't know the PHP class libraries (as we call 'em) or API.  Make yourself a little program called phpinfo.php in your PHP directory, or point your Apache at your new backdated PHP using the PHP directive in httpd.conf and put the program in your Apache root.  In the program just call phpinfo()

phpinfo.php: 

<?php
   phpinfo();
?>

When you run the program PHP will joyfully dump out a great deal of what it knows about itself.  One of the first things it tells you is which PHP.ini it's reading for it's configuration:

So now we know.

Copy your PHP.ini file from your initial PHP install to wherever phpinfo() says it is reading from, and repeat all your work to reconfigure the backdated PHP.  It usually amounts to little or nothing; making sure that the mysql_ and gd_ extensions are properly located in the old distribution. 

Enabling the Compiled Front End

At this point you should be able to:

  1.  Run the backdated PHP without errors from the command line
  2. Invoke the backdated PHP from Apache and view phpinfo.php

Note that as you scroll down in the phpinfo display you see no mention of Java.  The Java extension from 3.2.1 JavaBridge is located inside the WAR file.  Download the distribution from SourceForge, then expand the JavaBridge.war, using either the Java jar command or WinZip, which happily deals with the WAR and EAR formats.  In the WEB-INF/cgi directory you'll find a series of compiled artifacts like this:

 

For our purposes, take the windows file, called php-5.0-java-x86-windows.dll and copy it to your PHP extensions directory.  If you've been following along with this section, that'll be c:\wamp\php\ext, but in any event it will be clearly defined in the active PHP.ini.

Now rename that file:

from:   php-5.0-java-x86-windows.dll

to:       php_java.dll 

 Edit your operative PHP.ini file and instruct PHP to load php_java.dll at startup with the directive:

extension=php_java.dll

 Finally, create a Java section in PHP.ini that tells the DLL where to look for your servlet:

[java]
java.hosts     = 127.0.0.1:9080
java.servlet   = On
java.log_level = 3

 This instructs the DLL to look on the local host at port 9080 where the JavaBridge servlet is running

Downgrade the JavaBridge Servlet to Match the Library

 Unfortunately the 3.2.1 version of JavaBridge seems to use a slightly different protocol than the 4.2.1 version we originally installed, so we need to reinstall the JavaBridge WAR in our WebSphere or other JEE server as well.  Follow the instructions from the first section, preserving your deployment descriptor and making one important change:

Change the php_exec parameter to point to the backgraded PHP instance in your new downgraded deployment descriptor , e.g.

<init-param>
           <param-name>php_exec</param-name>
           <param-value>C:/wamp/php/php-cgi.exe</param-value>
         </init-param>

You may need to regenerate and propagate your plug-in. In the course of this series I've found that RAD does some very unpredictable things in terms of plugin generation, typically overwriting a good plugin with one missing the RAD-deployed elements like JavaBridge

I now strongly recommend that you move your plugin-cfg.xml file to somewhere WebSphere and RAD cannot get at it, and maintain it by hand, even in development, such as the Apache conf directory. Change the plugin location directive in Apache's httpd.conf to match the new location

Testing the Compiled Front End

 OK, let's repeat our tests.  I'm assuming that at this point:

  1. Your Apache is integrated with WebSphere via the plugin
  2. Your JavaBridge Servlet (in the JavaBridge WAR) has been downgraded to 3.2.1, properly mapped to the same URI as the 4.2.1 version (e.g. /JavaBridge), properly configured to point to a downgraded PHP and a new plugin generated and placed in the correct location
  3. Your PHP has, as mentioned in (2), been downgraded to the level to match the 3.2.1 JavaBridge
  4. Optional ... your PHP document root points to Drupal

First let's test our Apache Root:

http://localhost&nbsp;&nbsp;* or   http://drupal.development*

You should see the Apache welcome page or the Drupal front page depending on whether you chose to point your doc root to Drupal

From here on I'll just use the drupal.development hostname.  Use that or localhost depending on your configuration


Your PHP info page should point to the PHP.ini you configured.  In addition, look down your phpinfo display for a Java section.  It should look like the display below. 

If you do not find a Java section in phpinfo's display you are not using the compiled front end!

Most of the time I've found that the absence of a Java section in phpinfo display or the presence of unexpected DLL version or not found errors at PHP startup comes from PHP under Windows finding an unexpected PHP.ini file.  For example, if your original 5.2 PHP install is still present at c:\PHP you may find to your surprise that the downgraded PHP still wants to look there, even when you remove PHP from the windows PATH environment.  In such a case you may want to remove or rename your original installation directory, as maintaining a dual use PHP.ini in that location will probably introduce a great deal of confusion down the road.
 

Verify that your WebSphere plugin is working by accessing

http://localhost/snoop

You should see the snoop servlet display 

Verify that your WebSphere downgraded 3.2.1 JavaBridge is working by accessing

http://localhost/JavaBridge

and trying the SessionSharing demo.

If you see odd protocol errors you should be sure you are running 3.2.1; running the 4.x version with a 3.2.1 front end seems to produce these problems, probably because the XML protocol has changed.

Finally, verify that you can peek into a session directly from Apache/PHP using the compiled front end.  Note the session counter from your previous test by running

http://localhost/sessionPeek.php

If your previous display of the session counter was "1" you should see: