0. Introduction

Cet article explique :

  • Le couplage des langages Java EE et PHP
  • L'installation et configuration du serveur GlassFish responsable du couplage
  • Le développement d'une application Java EE 6 / PHP

Ce qu'il faut savoir :

  • Les bases du langage de programmation PHP
  • Les bases du langage de programmation Java
  • La maîtrise de projets Java EE
  • Des notions d'infrastructures Web pour la mise en place du serveur

La principale architecture Open Source actuelle pour le développement d'applications Internet de grande envergure est Java EE 6 avec ses API comme : Servlets, JavaServer Pages, JavaServer Faces, Enterprise JavaBean, Java Persitence API et son serveur standardisé : GlassFish. Le concurrent largement utilisé sur le Web est le langage PHP et le serveur Apache.

Les entreprises développent des projets de toutes tailles à l'aide de ces deux architectures et acquièrent de facto des connaissances approfondies dans l'une ou l'autre des technologies. Les développeurs travaillent avec des IDE évolués et utilisent en production le serveur Apache pour l'architecture LAMP et GlassFish pour l'architecture Java EE. Cependant, le serveur GlassFish permet, par l'intermédiaire d'une librairie, de coupler la puissance de Java EE et PHP pour le développement d'applications Internet.

I. GlassFish, le serveur Java EE de référence

GlassFish (http://glassfish.org) est le nom du nouveau serveur v3 d'applications Open Source Java EE 6 développé par la société Sun MicroSystems. Le serveur GlassFish est gratuit, libre et distribué sous licence CDDL et GNU GPL. Le mot d'ordre de ce serveur est rapidité et performance. La version 3.0 date de décembre 2009 et propose la gestion de Web Services, des EJB3.1, l'implémentation en standard du moteur de persistance Java Persistence API et plusieurs autres outils. Actuellement, GlassFish est le seul serveur totalement compatible Java EE 6, il est d'ailleurs utilisé comme serveur de référence par plusieurs sociétés comme la SNCF et RTL.

Depuis quelques années, les serveurs d'applications sont devenus de plus en plus complexes et offrent un nombre croissant de services. Les fonctionnalités et services proposés ont augmenté en même temps que le coût des serveurs. Le serveur Sun GlassFish propose un logiciel serveur pour les applications Web et un développement rapide pour un coût moindre. La dernière version de GlassFish v3 implémente en standard la dernière plate-forme Java EE 6, mais en plus, le serveur GlassFish fournit une plate-forme complète de type LAMP/SAMP (Sun Apache MySQL PHP) avec le support multi-langages (PHP, Java ou Ruby). Le serveur GlassFish est également compatible et permet un fonctionnement avec le serveur Apache en frontal (mod_jk).

L'administration de GlassFish est basée sur le concept de domaines gérés par un Domain Administration Server (DAS) et des noeuds agents (node agent) exécutés sur une machine. Le DAS permet de gérer le système central contenant les applications déployées. Les communications entre le DAS, les noeuds agents et les instances sont sécurisées et l'API Java Management Extensions (JMX) est disponible pour gérer le serveur et changer sa configuration. À la suite de l'installation du serveur, nous utiliserons le domaine installé par défaut (domain1).

Le serveur est livré en standard avec deux outils de gestion et d'administration. L'interface graphique disponible par défaut sur le port 4848 (http://localhost:4848) permet de gérer, à partir d'un navigateur Web, le serveur et ses applications. L'interface en ligne de commande nommée asadmin permet de réaliser les mêmes opérations.

II. Installation du serveur GlassFish

Le couplage Java EE 6 / PHP utilise le serveur GlassFish v3 (sges-v3.zip) qui peut être installé à partir d'une archive ZIP, d'un script pour les systèmes Linux, MacOs X et Solaris ou d'un exécutable Windows.

Le serveur est téléchargé sur le site officiel du projet GlassFish : https://glassfish.dev.java.net/public/downloadsindex.html.

Remarque : Le serveur GlassFish Java EE est développé en Java et nécessite l'installation d'un kit de développement Java JDK 1.6 ou supérieur.

L'installation du serveur est simple et peut être réalisée à partir de l'archive multi plateformes au format ZIP.

  • Copier l'archive du serveur GlassFish précédemment téléchargée dans le répertoire des sources.

    #cp sges-v3.zip /usr/local/src

  • Se déplacer dans le répertoire des sources.

    #cd /usr/local/src

  • Décompresser l'archive du serveur GlassFish.

    #unzip sges-v3.zip

  • Déplacer l'archive décompressée du serveur GlassFish dans le répertoire des logiciels.

    #mv glassfishv3 /usr/local

Sous Windows l'installation peut être réalisée également à l'aide de l'archive au format ZIP ou directement avec l'exécutable.

Le serveur GlassFish est maintenant correctement installé. Nous devons terminer la configuration en ajoutant la variable d'environnement GLASSFISH_HOME dans le fichier caché /root/.bashrc sous Linux en précisant le chemin absolu vers le répertoire d'installation du serveur.

 
Sélectionnez

export GLASSFISH _ HOME=/usr/local/glassfi shv3 
export PATH=$JAVA _ HOME/bin:$GLASSFISH _HOME/bin:$PATH

Sous Windows le principe reste le même et il est conseillé d'ajouter la variable d'environnement GLASSFISH_HOME avec le panneau de configuration. Cette variable d'environnement permet de référencer directement les exécutables utilisés par le serveur.

Remarque : Avec l'installation par défaut du serveur GlassFish, nous utilisons le port 8080 pour le serveur Java EE, le port 4848 pour l'accès à l'interface d'administration, admin comme identifiant et adminadmin comme mot de passe.

L'arborescence de GlassFish est présentée dans la Figure 1 et montre les différents dossiers nécessaires pour l'exécution du serveur, la configuration ou la gestion des domaines.

Image non disponible
Figure 1. Arborescence du serveur GlassFish

L'installation du serveur étant terminée, nous pouvons tester son fonctionnement en lançant directement GlassFish à l'aide de la commande suivante dans un terminal ou une console Ms-DOS :

 
Sélectionnez

#asadmin start-domain

Le serveur est alors accessible à l'adresse suivante http://localhost:8080/ et l'interface d'administration à l'adresse http://localhost:4848 (Figure 2).

Image non disponible
Figure 2. Interface d'administration GlassFish

III. GlassFish et PHP avec Quercus

Il existe plusieurs approches pour exécuter du code PHP sur le serveur Java EE GlassFish.

La première consiste à installer un exécutable comme Quercus, capable d'interpréter du PHP avec la machine virtuelle Java.

La seconde consiste à installer un pont entre l'implémentation Java EE et PHP comme JavaBridge. Enfin, la dernière solution consiste à utiliser le serveur Web Apache en frontal et à exécuter les pages PHP avec le module d'Apache. Cette technique est utilisée pour le load balancing mais ne permet pas de coupler/mélanger le code Java avec PHP.

La première solution concerne l'utilisation d'un interpréteur comme Quercus permettant d'utiliser un seul serveur, et surtout de bénéficier du mélange Java / PHP dans les applications comme nous allons le voir ci-après.

Quercus est une technologie Caucho sous licence GPL utilisant Resin et développée en Java pour l'interprétation du langage PHP.

Quercus permet l'intégration de Java dans des services PHP ou scripts mais également une interaction entre le code Java et PHP.

Avec Quercus, les applications PHP peuvent ainsi manipuler les technologies Java comme les Enterprise JavaBeans, les frameworks, Java Message-Service et les JavaBeans. Ce concept est rendu possible grâce aux techniques suivantes (Figure 3) :

Image non disponible
Figure 3. Dialogue Java / PHP avec Quercus
  • Le code PHP est interprété et compilé dans le code Java.
  • Quercus est entièrement écrit en Java et donc interprétable par un serveur Java.
  • Quercus propose une API de communication Java vers PHP.

Quercus (version 4.0.3 pour cet ouvrage) est livré sous forme de fichier .war (Web Archive ou archive de type .tar) contenant l'interpréteur Quercus et les librairies PHP. Ce fichier .war peut être déployé sur n'importe quel serveur compatible Java comme GlassFish, Tomcat ou encore Jboss. La mise en place de Quercus commence par le téléchargement de la dernière version du fichier .war (http://quercus.caucho.com).

La suite consiste à installer la librairie Quercus. L'installation d'une librairie sous GlassFish peut être réalisée de deux façons :

  • Pour l'ensemble des applications du domaine en copiant les fichiers .jar dans le répertoire /glassfishv3/glassfish/lib/.
  • Pour un domaine particulier en copiant les archives .jar dans le répertoire /glassfishv3/glassfish/domains/domain1/lib/ext.

Nous utilisons la première solution et nous copions les archives téléchargées resin.jar et inject-16.jar dans le répertoire /glassfishv3/glassfish/lib.

Remarque : L'installation d'une nouvelle librairie nécessite un redémarrage du serveur GlassFish.

IV. Mise en place d'un premier projet Java EE / PHP

Nous allons créer un nouveau projet Java EE de type Dynamic Web Project nommé projetjavaeephp avec l'IDE Eclipse ou NetBeans. Nous allons ensuite créer un simple fichier PHP (Listing 1) dans le répertoire Web de notre projet avec le contenu suivant permettant de tester le fonctionnement de l'interpréteur.

Listing 1. Test du fonctionnement de Quercus - Fichier : /WebContent/php.php
Sélectionnez

<html>
<head>
<title>Premier projet Java EE
avec PHP</title>
<?php
	function quercus_test()
	{
		return function_exists("quercus_version");
	}
?>
</head>
<body>
<p>
Test de Quercus
</p>
<?php
	if (quercus_test())
	{
		echo "Quercus fonctionne parfaitement";
	}
?>
</body>
</html>

L'installation est presque terminée, il reste à préciser dans le fichier de déploiement (Listing 2) de l'application Java EE /WEB-INF/web.xml, l'exécution des fichiers portant l'extension .php par Quercus.

Listing 2. Paramétrage du fichier de configuration de l'application Java EE - Fichier : /WEB-INF/web.xml
Sélectionnez

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
		xmlns="http://java.sun.com/xml/ns/javaee" 
		xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
		xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
		id="WebApp _ ID" version="2.5">
	<display-name>projetjavaeephp</display-name>
	<servlet>
		<servlet-name>Quercus Servlet</servlet-name>
		<servlet-class>com.caucho.quercus.servlet.QuercusServlet</servletclass>
		<init-param>
			<param-name>script-encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
		<init-param>
			<param-name>license-directory</param-name>
			<param-value>WEB-INF/licenses</param-value>
		</init-param>
	</servlet>
	<servlet-mapping>
		<servlet-name>Quercus Servlet</servlet-name>
		<url-pattern>*.php</url-pattern>
	</servlet-mapping>
	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
</web-app>

Nous pouvons tester notre application déployée avec GlassFish et déclencher le fichier PHP à l'URL suivante : http://localhost:8080/projetjavaeephp/php.php (Figure 4).

Image non disponible
Figure 4. Exécution de code PHP dans un projet Java EE

L'arborescence du projet à cette étape est présentée dans la Figure 5.

Image non disponible
Figure 5. Arborescence du projet

V. Utilisation de classes Java en PHP

Afin de présenter la puissance du couplage Java EE / PHP, nous allons créer une première classe simple JavaBean POJO nommée Personne avec des attributs et méthodes.

L'importation de classes Java dans un fichier PHP est réalisée avec l'opérateur import. L'appel de méthode Java en PHP respecte la notation pointée. Nous allons utiliser notre classe Java Personne (Listing 3) dans un fichier PHP personne.php (Listing 4).

Listing 3. Classe JavaBean Personne - Fichier : com.gdawj.Personne
Sélectionnez

package com.gdawj;
public class Personne {
	private int id;
	private String nom;

	public Personne()
	{
		System.out.println("Appel du constructeur");
	}
	public String afficherPersonne()
	{
		return "Bonjour "+this.id+" "+this.nom;	
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getNom() {
		return nom;
	}
	public void setNom(String nom) {
		this.nom = nom;
	}
}
Listing 4. Utilisation d'une classe Java en PHP - Fichier : /WebContent/personne.php
Sélectionnez

<?php
	//importation du paquetage Java
	import com.gdawj.Personne;
	//instanciation de la classe
	$pojo=new Personne();
	//declenchement de methodes
	$pojo->setId(1);
	$pojo->setNom("Lafosse");
	echo $pojo->afficherPersonne();
	//importation
	import java.util.Calendar;
	//singleton
	$calendar=Calendar::getInstance();
	//afficher la valeur
	echo("<br/>".$calendar);
?>

L'appel de membres statiques et de Singleton est également possible avec PHP.

Le résultat de l'exécution est présenté avec la Figure 6.

Image non disponible
Figure 6. Utilisation d'une classe Java en PHP

GlassFish et Quercus permettent une intégration simple et performante de PHP avec Java. Les possibilités de PHP et Java sont multiples et permettent également d'utiliser les pools de connexions JNDI avec PHP pour les connexions aux bases de données, de réaliser des conversions de type PHP vers Java, de gérer les sessions ou autres.

VI. Ajouter de nouvelles fonctionnalités à PHP

Quercus permet également de déclencher des méthodes Java de classes statiques sans instancier d'objet. La classe Java statique BoiteOutils.java présentée dans le Listing 5, permet d'afficher la date courante du système.

Listing 5. Classe statique boite r outils - Fichier : com.gdawj.BoiteOutils.java
Sélectionnez

package com.gdawj;
import java.util.Calendar;
public class BoiteOutils {
	public static String afficherDate(){
		Calendar calendar=Calendar.getInstance();
		return calendar.getTime().toString();
	}
}

Cette classe est déclenchée en PHP avec la méthode java_class() permettant de charger des informations statiques.

 
Sélectionnez

<?php
	$class=java_class("com.gdawj.BoiteOutils");
	echo $class->afficherDate();
?>

Cette technique est très largement utilisée pour proposer de nouvelles fonctionnalités à PHP en profitant de la puissance du langage Java. Par exemple, la manipulation de flux d'octets est largement détaillée et documentée en Java. Elle pourra ainsi être utilisée à l'aide de PHP.

Remarque : Pour les exemples qui suivent nous utilisons les librairies Quercus installées dans le répertoire /WEBINF/lib de notre projet Java EE afin de pouvoir y faire référence et importer les classes.

VII. Utiliser des composants Java EE avec PHP

Les Enterprises JavaBeans (EJB) sont largement utilisés pour la gestion de la couche métier en Java EE et permettent de séparer la partie modèle du design pattern MVC de façon optimisée. Ce type de technologie n'existe pas en PHP mais il est tout à fait possible de profiter de la puissance des EJB Java en PHP. Les développeurs peuvent ainsi coder en Java EE et les intégrateurs en PHP.

Pour cet exemple, nous utilisons une classe EJB Java EE nommée ClientEJBBean (Listing 6) fournissant deux services simples.

Listing 6. EJB fournissant deux services - Fichier : com.gdawj.ejb.ClientEJBBean.java
Sélectionnez

package com.gdawj.ejb;
import java.util.Calendar;
import javax.ejb.Stateless;

@Stateless
public class ClientEJBBean implements ClientEJB{
	Calendar calendar=Calendar.getInstance();
	public String infoClient(String param){
		return "Service réalisé par Client EJB : "+param.toUpperCase()+" !";
	}
	public String infoDateClient(){
		return "Date depuis l'EJB : "+calendar.getInstance().getTime().toString();
	}
}

Dans un cas professionnel, ces services pourraient accéder à un SGBD ou un ERP. Ce code représente la couche Modèle du design pattern MVC.

Nous allons maintenant dans le Listing 7, présenter la couche Contrôleur avec une Servlet nommée ServletClientEJB. Cette Servlet invoque l'EJB à partir du paramètre entré dans la vue PHP.

Listing 7. Servlet contrôleur de gestion du client - Fichier : com.gdawj.servlets.ServletClientEJB.java
Sélectionnez

package com.gdawj.servlets;
import java.io.IOException;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.gdawj.ejb.ClientEJB;
public class ServletClientEJB extends HttpServlet
{
	private static final long serialVersionUID = 1L;
	// utiliser l'EJB
	@EJB
	private ClientEJB clientEJB;

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	{
		// chargement de l'EJB Java et envoi à la vue PHP
		if(request.getParameter("saisie")!=null && !request.getParameter("saisie").equals(""))
		{
			String infoEJB=clientEJB.infoClient(request.getParameter("saisie").toString());
			request.setAttribute("infoEJB", infoEJB);
			response.sendRedirect("vuephp.php?infoEJB="+infoEJB);
			return;
		}
		// redirection vers la vue PHP
		getServletContext().getRequestDispatcher("/vuephp.php").forward(request, response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	{
		doGet(request, response);
	}
}

Enfin, la dernière partie (Listing 8) est codée en PHP et représente la couche vue du modèle MVC.

Listing 8. Vue PHP utilisant les services d'un EJB Java - Fichier : /vuephp.php
Sélectionnez

<html>
<head>
<title>Premier projet Java EE avec PHP</title>
</head>

<body>
<p>Utilisation de Java et des EJB en MVC avec PHP</p>

<?php
	// afficher les informations de l'EJB Java EE dans du PHP
	$resultatClientEJB=$_REQUEST["infoEJB"];
	if(!empty($resultatClientEJB))
	{
		echo $resultatClientEJB."<br/>";
	}
	// utiliser le client EJB directement
	$clientEJB=jndi_lookup("java:global/projetjavaeephpEAR/projetjavaeephpEJB/ClientEJBBean");
	echo $clientEJB->infoDateClient()."<br/>";
?>

<form name="formulaire" action="servlet" method="POST">
	Saisir les informations &agrave; envoyer &agrave; l'EJB<br/>
	<input type="text" name="saisie" id="saisie"/>
	<input type="submit" value="Envoyer"/>
</form>

</body>
</html>

Cette page déclenche la Servlet et affiche le résultat de l'exécution de l'EJB Java en PHP. Nous utilisons également JNDI pour appeler directement l'EJB depuis le code PHP.
Le résultat est présenté dans les Figures 7 et 8.

Image non disponible
Figure 7. Utilisation des EJB Java avec PHP
Image non disponible
Figure 8. Résultation de l'exécution de l'EJB

Remarque : L'API Java Naming and Directory Interface (JNDI) fournit un mécanisme de nommage de type annuaire pour l'accès aux ressources. Ces ressources peuvent être de différents types mais le but étant d'associer les objets à un nom (bind) et de retrouver ces objets (lookup) dans un annuaire de nommage semblable à LDAP, DNS ou NIS.

VIII. Profiter de la souplesse de PHP en Java

Le paragraphe précédent montre le principe d'utilisation de Java avec PHP mais il est également possible d'utiliser des techniques PHP avec Java. Par exemple, la librairie de graphisme GD est très simple à utiliser en PHP et peut être ajoutée à Java.

Nous allons dans cet exemple utiliser PHP et la librairie GD à l'aide d'une classe Java afin de générer une image à la volée.

Pour cela, nous allons créer une nouvelle classe Pojo Java nommée ImageMiniature.java (Listing 9) composée de ses attributs et accesseurs.

Listing 9. Classe JavaBean ImageMignature - Fichier : com.gdawj.ImageMignature.java
Sélectionnez

package com.gdawj;
public class ImageMiniature {
	
	private String chemin;
	private int largeur;
	private int hauteur;

	public ImageMiniature()
	{
		System.out.println("Appel du constructeur ImageMiniature");	
	}

	public String getChemin() {
		return chemin;
	}

	public void setChemin(String chemin) {
		this.chemin = chemin;
	}

	public int getLargeur() {
		return largeur;
	}
	
	public void setLargeur(int largeur) {
		this.largeur = largeur;
	}

	public int getHauteur() {
		return hauteur;
	}

	public void setHauteur(int hauteur) {
		this.hauteur = hauteur;
	}
}

La page PHP nommée image.php utilise le POJO Java pour les informations et génère une miniature de l'image source à l'aide de PHP / GD.

Listing 10. Page PHP responsable de la génération de l'image - Fichier : /image.php
Sélectionnez

<?php
	// importation du paquetage Java
	import com.gdawj.ImageMiniature;
	// instanciation de la classe Java
	$pojo=new ImageMiniature();
	// declenchement de methodes
	$pojo->setChemin("images/image.jpg");
	// afficher l'image d'origine
	echo "Image d'origine<br/><img src=\"".$pojo->getChemin()."\"/>";
	// retailler l'image avec PHP GD
	$pojo->setHauteur(150);
	$pojo->setLargeur(150);
	// recuperer la source avec Java
	$source=imagecreatefromjpeg($pojo->getChemin());
	// creer la vignette avec les infos du pojo
	$destination=imagecreatetruecolor($pojo->getHauteur(), $pojo->getLargeur());
	// les fonctions imagesx et imagesy renvoient la largeur et la hauteur d'une image
	$largeur_source=imagesx($source);
	$hauteur_source=imagesy($source);
	$largeur_destination=imagesx($destination);
	$hauteur_destination=imagesy($destination);
	// on cree la miniature
	imagecopyresampled($destination, $source, 0, 0, 0, 0, $largeur_destination, 
		$hauteur_destination, $largeur_source, $hauteur_source);
	// on enregistre la miniature sous le nom "miniature.jpg"
	imagejpeg($destination, "miniature.jpg");
	// afficher l'image miniature
	echo "<br/>Image miniature<br/><img src=\"miniature.jpg\"/>";
?>
Image non disponible
Figure 9. Génération d'images avec Java, PHP et GD

IX. Conclusion

La plate-forme Java EE 6 et le langage PHP ont actuellement le monopole pour les développements Internet Open Source, et il est courant de trouver des codeurs pro Java EE ou PHP.
Java EE est utilisé pour les grosses infrastructures et permet de gérer des pools de connexion, Enterprise JavaBean, Java Persistence API ou encore des WebServices évolués quand PHP permet un développement rapide de vues ou l'utilisation simplifiée de librairies pour la manipulation d'images par exemple.

Le serveur GlassFish Open-Source totalement compatible Java EE 6, permet de coupler la puissance de ces deux langages.

Un projet existant pourra par exemple migrer de PHP vers Java EE, ou conserver les meilleurs services de chaque langage afin d'optimiser le produit. Ainsi dans le cas d'une migration totale de PHP vers Java EE, le passage pourra être progressif et réalisé service par service. Enfin, dans le meilleur des cas, les services optimisés pour Java seront développés avec Java EE et les autres resteront en PHP. Plus rien ne nous empêche désormais de développer des projets en MVC I ou II avec Java EE pour les parties Contrôleur et Modèle et de conserver la couche Vue en PHP/XHTML.

Merci à Lyche pour sa relecture orthographique.