vendredi 13 mai 2011

Installer Oracle Weblogic Server 11gR1 sur Ubuntu 10.04 x86

Voici quelques détails sur l'installation du serveur d'application Oracle Weblogic 11gR1 (10.3.5). J'ai choisit d'installer ce serveur d'application ainsi que la machine virtuelle Java JRockit supportée par ce serveur.

Installation



  1. Télécharger la distribution de la JRockit (jrockit-jdk1.6.0_24-R28.1.3-4.0.1-linux-ia32.bin) à cette adresse,

  2. Ajouter les droits d'exécution au fichier (chmod) avant de l'exécuter et suivre l'assistant d'installation,

  3. J'ai choisit de déplacer le dossier contenant la JRockit dans le dossier /usr/lib/jvm/, à côté des autres machines virtuelles Java,

  4. Télécharger le ficher wls1035_dev.zip (~300 Mo) à cette adresse

  5. Dé-zipper le contenu de l'archive dans le répertoire de votre choix (j'ai choisit /opt/oracle/wls-10.3.5) que nous noterons <MW_HOME>

  6. Modifier le script configure.sh situé dans le dossier MW_HOME pour le faire utiliser /bin/bash en lieu et place de /bin/sh

  7. Lire attentivement et suivre les instructions situées dans le script README.txt fourni avec le serveur,

  8. J'ai choisit de créer le domaine /var/local/wlsdomains/localdomain en utilisant l'interface graphique via le script $MW_HOME/wlserver/common/bin/config.sh


Un peu de monitoring


Voilà, Weblogic 11gR1 est maintenant prêt à servir, JRockit est fournit avec JRockit Mission Control, une console d'administration de la machine virtuelle fortement utile pour inspecter en vol le fonctionnement des applications (Mémoire, CPU, Thread).
On pourra faire tourner le serveur avec un JVM classique et utiliser Visual VM présent depuis la version 1.6.0_07 dans $JAVA_HOME/bin/jvisualvm, ou alors utiliser JConsole présent depuis la JDK 1.5 dans $JAVA_HOME/bin/jconsole
Enjoy!

mardi 10 mai 2011

REST avec Jersey!

Les architectures REST sont une nouvelle forme d'architecture exprimant un certain retour aux sources. En effet, ce type d'architecture tire sa puissance des standards éprouvés du Web, en particulier du protocole HTTP.

Rappel HTTP


HTTP est un protocole orienté ressource, c'est-à-dire qu'il est dédié à la manipulation de ressources à travers un réseau et constitue un fondement de l'Internet et du World Wide Web. Il repose sur TCP et se traduit sous 2 formes :

La requête

Connexion effectuée depuis un client vers un serveur, elle identifie une ressource via son URL et donne un ordre à effectuer au serveur. Exemple :

GET http://www.google.com/

Les différents ordres sont :

  • (C) POST : pour créer une ressource,

  • (R) GET : pour lire une ressource,

  • (U) PUT : pour modifier une ressource,

  • (D) DELETE : pour supprimer une ressource,

  • ..., et bien d'autres encore, ...


Le format que nous utilisons tous (y compris en consultant ce billet) avec notre navigateur est codifié de la manière suivante : text/html. D'autre format sont également codifiés par la RFC 2046, on y retrouve notamment application/xml pour le format XML, application/json pour un flux JSON, ... Exemple :

Accept: application/xml, application/json, text/plain


La réponse

Connexion effectuée par le serveur vers le client ayant effectuée une requête afin de retourner le resultat de celle-ci. Elle est caractérisée par son code de retour, et eventuellement un contenu dont le format est précisé. Exemple :

HTTP/1.1 200 OK
<html>
...
</html>

Les codes de retour varient selon le résultat de l'exécution de la requête :

  • 200 : retour normal car tout va bien,

  • 201 : retour indiquant que la ressource a bien été créée,

  • 404 : la ressource n'a pu être trouvée

  • ..., et bien plus encore, ...



De la même manière qu'un client indique les représentations qu'il est en mesure de comprendre, le serveur indique dans l'entête de la réponse la représentation qu'il a choisit. Exemple :

Content-Type: text/html


Un premier pas en JEE


Maintenant que nous avons révisé les bases, allons plus loin avec un exemple d'implémentation en Java. Commençons par jetter un oeil sur la classe HttpServlet: avez vous remarqué ces méthodes, elles ne vous rappellent rien ?

Il s'agit des méthodes qu'il convient d'implémenter pour écrire une servlet orienté REST. Les codes de retour sont quant à eux disponibles sous forme de constantes dans la classe HttpServletResponse, c'est bien fait non ?

On passe la 6ième avec Jersey


L'écriture d'un servlet faisant du REST est une belle aventure à vivre mais on se heurte à une difficulté majeure : celle de savoir facilement interpréter une URL. C'est-à-dire comment savoir que

http://people.host.ext/user/guillaume.wallet/messages/20110101

est une URL listant les messages datés du premier janvier de l'année deux mille onze de l'utilisateur enregistré sous le nom 'guillaume.wallet', galère non?
JAX-RS est une spéficiation Java EE, incluse depuis la verion 6, ayant pour objet la standardisation de cette démarche REST au sein d'une application Java. L'implémentation de référence est fournit par le projet Jersey. Un tutorial complet est disponible sur le site.

Pom Pom Pom pommmm


Voici le pom qui m'a servi pour cette démarche:

<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>org.sample.jersy</groupId>
<artifactId>jersey-sample</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<inceptionYear>2011</inceptionYear>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.8</version>
<configuration>
<classpathContainers>
<classpathContainer>org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6</classpathContainer>
</classpathContainers>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
<wtpversion>2.0</wtpversion>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-servlet-api</artifactId>
<version>${tomcat.version}</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
</dependencies>
<properties>
<tomcat.version>7.0.12</tomcat.version>
</properties>
<repositories>
<repository>
<id>maven2-repository.java.net</id>
<name>Java.net Repository for Maven</name>
<url>http://download.java.net/maven/2/</url>
<layout>default</layout>
</repository>
</repositories>
</project>

Bonjour toi!


Notre première resource:

package org.sample.jersey.rest;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;

/**
* Une ressource polie.
*/
@Path( "/hello/{world}" )
public class HelloWorldResource
{
@GET
@Produces("text/plain")
public String greet(@PathParam("world") String world)
{
return "Hello " + world;
}
}

Et un peu de magie : pour tester notre application, il faut ... une application. Nous allons créer la classe suivante qui suffira à lancer notre premier test:

package org.sample.jersey.rest;

import javax.ws.rs.ApplicationPath;

import com.sun.jersey.api.core.PackagesResourceConfig;

/**
* La racine de l'application REST.
*/
@ApplicationPath( "/resources" )
public class SampleRESTApplication
extends PackagesResourceConfig
{
/**
* On explique à JERSEY que les Resources sont dans le paquet org.sample.jersey.rest.
*/
public SampleRESTApplication()
{
super( "org.sample.jersey.rest" );
}
}

Pour tester, une fois déployée dans le serveur de votre choix (tant qu'il s'agit de Tomcat dans sa version 7), rendez à l'URL suivante :

http://localhost:8080/<nom>/resources/hello/World

où <nom> remplace le nom de votre WebApp. Maintenant, remplacer "World" par ce qui vous chante et constater la magie: si peu de ligne pour un si bel effet.

«Comment tu le veux ta ressource ?»


L'exemple ci-dessous illustre la négociation de contenu.

package org.sample.jersey.rest;

import java.util.HashMap;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;

import org.json.simple.JSONObject;

/**
* Gestion des gens.
*/
@Path( "/users/{username}" )
public class PeopleResource
{
@GET
@Produces( "application/json" )
public String showUserAsJSON( @PathParam( "username" ) String username )
{
User user = findUserByUsername( username );
return user.toJSON();
}

@GET
@Produces( "text/plain" )
public String showUserAsTextPlain( @PathParam("username") String username )
{
User user = findUserByUsername( username );
return user.toString();
}

public PeopleResource()
{
users.put( "guillaume.wallet", new User( "guillaume.wallet", "Guillaume", "Wallet" ) );
users.put( "linus.torvalds", new User( "linus.torvalds", "Linus", "Torvalds" ) );
}

private User findUserByUsername( String username )
{
User user = users.get( username );
return user;
}

/* Une vraie BDD. */
private HashMap users = new HashMap();

/**
* Euh, ... un utilisateur quoi!
*/
private static class User
{
private String username;

private String firstname;

private String lastname;

public User( String username, String firstname, String lastname )
{
super();
this.username = username;
this.firstname = firstname;
this.lastname = lastname;
}

@SuppressWarnings( "unchecked" )
public String toJSON()
{
JSONObject me = new JSONObject();
me.put( "username", username );
me.put( "firstname", firstname );
me.put( "lastname", lastname );
return me.toJSONString();
}

@Override
public String toString()
{
return String.format( "%1s %2s", firstname, lastname );
}
}
}

Selon que vous fassiez :

$> wget --header "Accept: application/json" http://localhost:8080/<nom>/resources/users/guillaume.wallet

ou

$> wget --header "Accept: text/plain" http://localhost:8080/<nom>/resources/users/guillaume.wallet

Le rendu de la ressource change.

Conclusion


Cet article ne constitue qu'un petit pas, c'est maintenant à vous de faire le REST.