Qu'est ce qu'on se fait ch ... !

Aller au contenu | Aller au menu | Aller à la recherche

Test de la plateforme Google App Engine

Dans la série mieux vaut tard que jamais. Me voici décidé à tester la plateforme Google App Engine dans sa version JAVAEE. J'ai donc trouvé une idée d'application assez bidon qui pourrait être représentative du monde réel et sortir d'un simple Hello World. Vous allez voir que je pars de loin :) J'ai choisi d' aborder plein de technos que je ne connaissais pas ou de loin :

L'environnement de développement

Afin de ne pas trop me prendre la tête dans un premier temps avec l'intégration MAVEN et NETBEANS ( c'est mon éditeur de prédilection ) J'ai donc opté pour la solution standard Google : le plugin eclipse. Je ne détaillerai pas la procédure d'install car ce n'est pas le but de cet article. Tout se passe comme dans la doc. Je sais, ca peut faire un peu bizarre de prime abord, mais ca fonctionne :)

Après installation et au premier lancement d'une application démo, un plugin firefox (pour la version 3.5. La version 3.6 n'est encore disponible) et/ou un plugin IE. Ma première impression fut la qualité de l'intégration entre le browser et l'IDE. Les modifications sont prises en compte à chaud. J'ai pas ou très peu besoin de rafraîchir le navigateur. Bref, ce n'est que du bonheur .... Seule ombre au tableau: il manque par défaut un wizard WYSIWYG pour l'édition des écrans. Obligé par défaut de tout se coller à la mi-mine. Ce n'est pas très dur mais ca peut être un frein pour pas mal de gens.

GWT

Développeurs Swing, vous pouvez dorénavant faire des interfaces WEB :D ! Ayant fait un peu de swing il y a quelques années de ça (putain, je commence à me faire vieux...), je retrouve pas mal d'automatismes sur l'assemblage des composants dans des panels avec la gestion des layouts. C'est stable. Franchement, je préfère cette manière de développer des GUI. Je trouve que JSF a manqué l'occasion de faire un vrai développement à base de composants ( même si ca s'est amélioré en version 2.0). Il y a un vrai binding composant/modèle.

Mais j'ai encore quelques reproches à faire (juste pour faire mon chieur):

A l'instar de JSF, la bibliothèque de composants est assez pauvre en standard. Certes, largement plus fournie que l'implémentation de base fournie par SUN mais je m'attendais à créer des applications GMAIL like avec l'implémentation fournie par Google. Bon il existe quand même des librairies de composants qui étendent GWT. Mais bon attention, toutes ne gèrent pas convenablement le JAVASCRIPT.

L'accessibilité n'est pas encore totalement gagné. Certes il existe l'infrastructure technique. Depuis la version 1.5, c'est totalement intégré à GWT, cependant, il n'y a aucune garantie pour les bibliothèques tierces.

Guice

L'introspection de ce framework faisait parti de ma TODO LIST depuis pas mal de temps.

L'intégration dans un environnement WEB est très simple. Après avoir crée un listener

public class MyGuiceServletContextListener extends
		GuiceServletContextListener {
	@Override
	protected Injector getInjector() {
		Injector injector = Guice.createInjector(new MyModule(),
				new EMModule());
		return injector;
	}
}

et correctement initialisé le fichier web.xml

<filter>
		<filter-name>guiceFilter</filter-name>
		<filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
	</filter>
 
	<filter-mapping>
		<filter-name>guiceFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	<listener>
		<listener-class>info.touret.my.MyGuiceServletContextListener</listener-class>
	</listener>

Là, j'ai peut être loupé quelque chose, mais le binding se fait par le code

Il ne me restait plus qu'à utiliser les fameuses annotations Guice @Provides et @Inject Bref, GUICE?C'est simple. Ça fait peut de choses , mais ca le fait bien...

Google App Engine

L'un des gros manques de JAVA était la présence d'hébergeurs fournissant une stack JAVAEE. Maintenant c'est chose faite, grâce à Google. L'ensemble est clair et cohérent. GAE n'oblige pas à utiliser GWT. Je crois que l'on peut également utiliser JSF avec facelets. Seul bémol à mon sens, c'est le stockage des données. On ne peut pas - si je me trompe, n'hésitez pas à le mettre en commentaire- visualiser les données aisément. Le chargement est possible grâce à un script python. Quid de la pérennité des données stockées sur le serveur de google, pour faire des retours arrières simplement, etc etc. Bref des questions que l'on se pose dès que l'on travaille de manière un peu plus professionnelle et que l'on veut vendre un service à des clients.

Personnellement, je vois très bien ce genre de plateforme utilisée pour les PME qui font appel à des indépendants pour réaliser des WEBAPPS et les héberger à moindre cout. ( cloud quand tu nous tiens...)

Utilisation de la JSR 88

Bon une fois n'est pas coutume, me voila en train de pester sur JAVA EE. Dans la catégorie spec inutilisable en tant que tel, je vous présente la spécification JSR 88. Derrière ce nom barbare, se cache une API permettant de déployer des applications ou d'autres "objets" JAVA ( files JMS par exemple)

Pourquoi je gueule ? Ben d'abord, pour faire passer le temps :-D? Ensuite, pour donner un retour d'expérience sur cette fonctionnalité que je trouve pas assez exploitée

La documentation

ben d'abord, cette api n'est pas assez documentée. On peut trouver sur le net quelques exemples mais pas assez fournis. Pour développer un plugin MAVEN pour gérer le déploiement sur Oracle AS 10.1.3, j'ai personnellement du me pencher sur la documentation officielle de l'éditeur ( qui ne détaillait que l'implémentation de l'éditeur) et décompiler les classes qu'il utilisait dans ses scripts ANT

L'API

Cette API n'exempte pas l'utilisation des implémentations des serveurs. D'abord, elle est complètement obscure. Les classes ne sont pas du tout intuitives et imposent pas mal de debugging pour savoir comment obtenir des BONNES instances de Target et DeployableObject. Pour obtenir ces objets, on est presque obligé d'utiliser des objets provenant des implémentations des serveurs JAVAEE.

Par exemple sur Oracle AS :

public class DeployGoal extends BaseOC4JGoal {
  /**
   * Comment for <code>artifact</code>
   * 
   * @parameter expression="${artifact}"
   *            default-value="${project.build.directory}/${project.artifactId}-${project.version}.ear"
   */
  private File artifact = null;

  /**
   * @return the artifact
   */
  public File getArtifact() {
    return this.artifact;
  }

  /**
   * @param _artifactPath
   *          the artifact to set
   */
  public void setArtifact(File _artifactPath) {
    this.artifact = _artifactPath;
  }

  /**
   * @return the deploymentParameters
   */
  protected HashMap<String, String> getDeploymentParameters() {
    if (deploymentParameters == null) {
      HashMap<String, String> parameters = new HashMap<String, String>();
      //parameters.put("bindAllWebApps", getWebSite());
      parameters.put("bindWebApp", getWebSite());
      setDeploymentParameters(parameters);
    }
    return this.deploymentParameters;
  }

  /**
   * @param _deploymentParameters
   *          the deploymentParameters to set
   */
  protected void setDeploymentParameters(HashMap<String, String> _deploymentParameters) {
    this.deploymentParameters = _deploymentParameters;
  }

  HashMap<String, String> deploymentParameters = null;

  public void execute() throws MojoExecutionException, MojoFailureException {
    if (getArtifact() == null && !getArtifact().exists())
      throw new MojoFailureException("Artifact [" + getArtifact().getAbsolutePath()
          + "] doesnt exist!");
    else
      try {
        doDeploymentGoal();
      } catch (J2EEDeploymentException e) {
        throw new MojoExecutionException(e.getMessage(), e);
      }
  }

  /**
   * @throws J2EEDeploymentException
   */
  protected void doDeploymentGoal() throws J2EEDeploymentException {
    getJ2eeDeploymentManager().deploy(getArtifact().getAbsolutePath(), getApplicationName(),
        getDeploymentParameters(), true);
    
  }


 protected DeploymentManager getDeploymentManager() {
    try {
      if (deploymentManager == null) {
        Oc4jDeploymentFactory oc4jDeploymentFactory = new Oc4jDeploymentFactory();
        oc4jDeploymentFactory.handlesURI(getUrl());
        DeploymentFactoryManager factory = DeploymentFactoryManager.getInstance();
        factory.registerDeploymentFactory(oc4jDeploymentFactory);
        setDeploymentManager(factory.getDeploymentManager(getUrl(), getUsername(),
            getUserpassword()));
      }
      return this.deploymentManager;
    } catch (DeploymentManagerCreationException e) {
      getLog().error("The deploymentmanager is not available", e);
      throw new RuntimeException(e);
    }
  }




}

Enfin, comble du paroxysme, on ne peut pas déployer une application avec cette API. La classe DeploymentManager permet de supprimer, mettre à jour mais pas de déployer. !!!!!!