XLIX. Integración de Java y PHP

Introducción

Existen dos formas diferentes de integrar Java y PHP: en primer lugar, se puede integrar PHP dentro de un entorno de ejecución de servlets de Java, que en estos momentos es una solución mas estable y mas eficiente. La segunda opción es la de integrar Java dentro de PHP. La primera forma de integración se realiza a traves de un modulo SAPI que actua como interfaz del servidor de servlets. La segunda forma se realiza mediante esta extensión de Java.

Esta extensión de Java proporciona de forma sencilla los medios necesarios para crear e invocar métodos sobre objetos de Java desde PHP. La JVM se crea utilizando JNI y todo se ejecuta en un unico proceso.

Aviso

Esta extensión es EXPERIMENTAL. Esto significa que el comportamiento de esta extensión, los nombre de sus funciones y en definitiva TODO lo documentado sobre esta extensión, puede cambiar en una futura versión de PHP SIN AVISO. La advertencia queda hecha, y utilizar esta extensión queda bajo su propia responsabilidad.

Requirimientos

Para utilizar esta extensión es necesario disponer de una máquina virtual java (JVM) instalada en el sistema.

Instalación

Para incluir el soporte de Java en PHP, es necesario añadir el parámetro --with-java[=DIR] a las opciones de configuración de PHP. Ademas, es necesario indicarle a traves de la opción DIR, el lugar donde se encuentra el directorio base de la instalación del JDK. Esta extensión solamente puede ser construida como un modulo compartido. En el archivo php4/ext/java/README se incluye mas información sobre como construir esta extensión.

Nota para los usuarios de Windows: Para poder trabajar con este modulo en un entorno Windows con una versión de PHP <= 4.0.6, se debe copiar el archivo jvm.dll que se encuentra en el subdirectorio DLL del directorio PHP/Win32 de la distribución binaria de PHP, en el directorio SYSTEM32 de Windows (Normalmente es C:\WINNT\SYSTEM32 o C:\WINDOWS\SYSTEM32). Para versiones de PHP > 4.0.6 no es necesario realizar esta operación.

Configuración en tiempo de ejecución

El comportamiento de estas funciones está afectado por los valores definidos en php.ini.

Tabla 1. Opciones de configuraci??? de Java

NombreValor por defectoDonde se cambia
java.class.pathNULLPHP_INI_ALL
java.homeNULLPHP_INI_ALL
java.library.pathNULLPHP_INI_ALL
java.libraryJAVALIBPHP_INI_ALL
Para conocer todos los detalles y las definiciones de las constantes de PHP_INI_* se debe consultar la función ini_set().

Tipos de recursos

Esta extensión no tiene ningún tipo de recurso definido.

Constantes predefinidas

Esta extensión no tiene ninguna constante definida.

Ejemplos

Ejemplo 1. Ejemplo de Java

<?php
  
// se obtiene la instancia de la clase de Java java.lang.System desde PHP
  
$system = new Java('java.lang.System');

  
// se muestran las propiedades del acceso que se realiza a Java
  
print 'Version de Java='.$system->getProperty('java.version').' <br>';
  print
'Desarrollador de la JVM=' .$system->getProperty('java.vendor').' <br>';
  print
'Sistema Operativo='.$system->getProperty('os.name').' '.
              
$system->getProperty('os.version').' on '.
              
$system->getProperty('os.arch').' <br>';

  
// ejemplo de java.util.Date
  
$formatter = new Java('java.text.SimpleDateFormat',
                        
"EEEE, MMMM dd, yyyy 'at' h:mm:ss a zzzz");

  print
$formatter->format(new Java('java.util.Date'));
?>

Ejemplo 2. Ejemplo de AWT

<?php
  
// Este ejemplo solo puede ser ejecutado como CGI.

  
$frame  = new Java('java.awt.Frame', 'PHP');
  
$button = new Java('java.awt.Button', 'Hola Mundo de Java!');

  
$frame->add('North', $button);
  
$frame->validate();
  
$frame->pack();
  
$frame->visible = True;

  
$thread = new Java('java.lang.Thread');
  
$thread->sleep(10000);

  
$frame->dispose();
?>
Notas:

  • new Java() crea una nueva instancia de una clase solamente si existe un constructor adecuado. Si no se le pasan parámetros y existe un constructor por defecto adecuado (como por ejemplo en el caso de java.lang.System) se podrá acceder a la mayor parte de sus metodos, ya que son estáticos.

  • Al acceder a los miembros de una instancia, en primer lugar se buscarán las propiedades del bean y en segundo lugar los miembros publicos. En otras palabras, print $date.time se intentara resolver en primer lugar como $date.getTime() y posteriormente como $date.time.

  • Tanto los miembros estaticos como los miembros de una instancia de un objeto pueden ser accedidos utilizando la misma sintaxis. Ademas, si el objeto es de tipo java.lang.Class, entonces se puede acceder a los miembros estaticos de la clase (tanto los atributos como los metodos).

  • Las excepciones que se lanzan durante la ejecución se transforman en avisos de tipo "warning" de PHP y en resultados de tipo NULL. Los avisos de tipo "warning" se pueden eliminar añadiendo el prefijo "@" a la llamada del metodo. Las siguientes funciones de la API se pueden utilizar para obtener y borrar el ultimo error surgido

  • La resolución de la sobrecarga es uno de los problemas mas dificiles de resolver dadas las grandes diferencias entre PHP y Java en el tema del "tipado" de las variables. Esta extensión utiliza un metodo simple pero muy efectivo para determinar cual es la mejor decisión a tomar cuando se produce la sobrecarga.

    Ademas, los nombres de los metodos en PHP no distinguen entre mayusculas y minusculas, por lo que se aumenta la probabilidad de que se produzcan situaciones de sobrecarga.

    Una vez seleccionado el metodo, los parámetros se transforman si es necesario, incluso con la posibilidad de perder datos (por ejemplo, los numeros de tipo "double" se transforman en tipo boolean) (Nota del traductor: esta conversion parece totalmente absurda, asi que puede tratarse de un fallo de la documentacion de la version original).

  • Las variables de tipo "array" y "hashtable" pueden ser utilizadas de forma indistinta. En PHP, las hashtables solo pueden incluir en las claves variables de tipo integer o string. Ademas, en Java los arrays cuyas variables son de algun tipo primitivo, no pueden contener huecos. Por ultimo, se debe recordar que este tipo de variables se pasan por valor, por lo que pueden llegar a consumir una cantidad apreciable de memoria y de tiempo.

SAPI de los servlets Java

Basandose en el mismo mecanismo que la extension de Java de PHP, la SAPI de los servlets Java permite ejecutar PHP como un servlet de Java. La ventaja mas significativa de esta forma de actuar es que se aprovechan las caracteristicas de "pooling" y de reutilizacion implementadas por la mayoria de servidores que permiten ejecutar servlets. El archivo php4/sapi/README contiene las instrucciones necesarias para compilar el modulo SAPI para los servlets Java. Notas:

  • Aunque, en principio, este codigo podria ser ejecutado en cualquier servidor que permita la ejecucion de servlets, solo se ha probado en el servidor Jakarta/Tomcat desarrollado por la fundacion Apache. Por ese motivo, cualquier informacion sobre la forma de ejecutarlo en otros servidores, los errores encontrados, las soluciones planteadas, etc...sera una informacion muy apreciada y que animamos a que los desarrolladores envien a los responsables del desarrollo del proyecto PHP.

  • Se pueden producir conflictos entre PHP y SAPI con respecto al directorio de trabajo. Mientras PHP se esta ejecutando, el servidor de servlets no podra cargar ninguna clase que se encuentre en el CLASSPATH si su ruta se especifica de forma relativa y tampoco podra encontrar el directorio de trabajo utilizado para las tareas de administracion y compilacion de JSP.

Tabla de contenidos
java_last_exception_clear -- Borra la última excepción de Java
java_last_exception_get -- Obtiene la última excepción de Java