Libellés

Affichage des articles dont le libellé est jvm. Afficher tous les articles
Affichage des articles dont le libellé est jvm. Afficher tous les articles

samedi 13 août 2011

Jaxrs client avec Jersey

Ce n'est souvent pas évident de trouver un client Jaxrs. Jersey vous en propose un, et voici comment l'utiliser.  Par défaut j'ai rajouté les logs des requêtes HTTP :


  @Grab('com.sun.jersey:jersey-client:1.8')
  @Grab('com.sun.jersey:jersey-core:1.8')
  @Grab('com.sun.jersey.contribs:jersey-apache-client4:1.8')

  import com.sun.jersey.api.client.*;
  import com.sun.jersey.api.client.filter.LoggingFilter;
  import javax.ws.rs.core.*;
  import com.sun.jersey.client.apache4.ApacheHttpClient4;

  Client client = ApacheHttpClient4.create();
  client.addFilter(new LoggingFilter());
  def resource = client.resource("http://geek-du-soir.blogspot.com").path("/feeds/posts/default")
  resource.accept("application/xml+atom").get(String.class);

jeudi 11 août 2011

Logguer les requettes HTTP de Jersey Client

Pour logguer les requêtes HTTP éffectuées par Jersey Client il suffit de rajouter :

client.addFilter(new LoggingFilter());


Voici un exemple complet :


@Grab('com.sun.jersey:jersey-client:1.8')
@Grab('com.sun.jersey:jersey-core:1.8')
@Grab('com.sun.jersey.contribs:jersey-apache-client4:1.8')

import com.sun.jersey.api.client.*;
import com.sun.jersey.api.client.filter.LoggingFilter;
import javax.ws.rs.core.*;


Client client = create();
client.addFilter(new LoggingFilter());
def resource = client.resource("http://geek-du-soir.blogspot.com").path("/feeds/posts/default")

resource.accept(MediaType.APPLICATION_XML).get(String.class);



import org.apache.http.client.HttpClient;
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
import org.apache.http.conn.ssl.SSLSocketFactory;
import com.sun.jersey.client.apache4.ApacheHttpClient4;
import com.sun.jersey.client.apache4.config.DefaultApacheHttpClient4Config;

ApacheHttpClient4 create() {
DefaultApacheHttpClient4Config config = new DefaultApacheHttpClient4Config();
ApacheHttpClient4 jerseyClient = ApacheHttpClient4.create(config);
HttpClient httpClient = jerseyClient.getClientHandler().getHttpClient();
SSLSocketFactory sf = (SSLSocketFactory) httpClient.getConnectionManager().getSchemeRegistry().getScheme("https").getSchemeSocketFactory();
sf.setHostnameVerifier(new AllowAllHostnameVerifier());
return jerseyClient;
}

mercredi 13 juillet 2011

Benchmark d'une classe, d'une méthode, ... en Groovy

Pour mesurer le temps d'exécution d'une méthode en Java, on utilise de l'AOP ou des println à la main.

EN Groovy, je viens de découvrir un projet qui s'appelle GBench qui permet de mesurer des temps d’exécutions.

On peut mesurer les temps d’exécutions de toutes les méthodes d'une classe :


@Grab(group='com.googlecode.gbench', module='gbench', version='11.07.05')
import gbench.*

@Benchmark()
class Klass {
def foo() {
Thread.sleep(10)
}
def bar() {
Thread.sleep(5)
}
}

def k = new Klass()

println "call foo"
k.foo()

println "call bar"
k.bar()

Klass void (): 14999053 ns
call foo
Klass java.lang.Object foo(): 14887245 ns
call bar
Klass java.lang.Object bar(): 5129355 ns



Seulement d'une méthode (et regarder comment spécifier le format d'affichage) :

@Grab(group='com.googlecode.gbench', module='gbench', version='11.07.05')
import gbench.*

class Klass {

@Benchmark({println("${method} of ${klass}: ${(time/1000000) as long} ms")})
def foo() {
Thread.sleep(10)
}
def bar() {
Thread.sleep(5)
}
}

def k = new Klass()

println "call foo"
k.foo()

println "call bar"
k.bar()


call foo
java.lang.Object foo() of Klass: 14 ms
call bar



Ou faire des comparaisons sur 1000 exécutions.
Dans cet exemple je compare le Parseur JSON de Groovy 1.8 avec celui de Jackson :


@Grab(group='com.googlecode.gbench', module='gbench', version='11.07.05')
@Grab(group='org.codehaus.jackson', module='jackson-mapper-asl', version='1.8.3')

import gbench.*
import groovy.json.JsonSlurper
import org.codehaus.jackson.map.ObjectMapper;

def slurper = new JsonSlurper()
def mapper = new ObjectMapper();

def jsonString = '{"name": "Romain", "age": 25}'
class Personn{ String name; int age }

def bench = new BenchmarkBuilder()
bench.run(times: 1000){
with 'Groovy JSON', {
Personn p = slurper.parseText(jsonString)
assert p.name == "Romain"
assert p.age == 25
}
with 'Jackson', {
Personn p = mapper.readValue(jsonString, Personn.class)
assert p.name == "Romain"
assert p.age == 25
}
}

println bench


time
Groovy JSON 179218175
Jackson 66699800

Singleton en Groovy

Rien de plus simple que de faire un Singleton en Groovy. Cela se résume à annoter une classe par ​@Singleton, puis à utiliser l'instance via le getter getInstance()

Je vous donne un exemple, testable ici:


​@Singleton
class Personn {
String name
int age
}

​def ​p = Personn.instance;
​p.name = "Romain"
p.age = 25

assert p == Personn.instance;
​


Si jamais vous tentez d'utiliser le constructeur par défaut, une exception sera lancée.


java.lang.RuntimeException: Can't instantiate singleton Personn. Use Personn.instance
at Personn.(Script1.groovy)
at Script1.run(Script1.groovy:9)




Par contre si vous créez un constructeur (même privé), ça ne marche plus.


@Singleton class Personn {

private Personn(){
println "toto"
}

String name

int age
}

def p1 = new Personn();
def p2 = new Personn();

assert p1 == p2

Assertion failed:

assert p1 == p2
| | |
| | Personn@1ee0563
| false
Personn@1a3e311

jeudi 7 juillet 2011

UglifyJs en Java

UglifyJS est une librairie javascript qui permet de minifier des fichiers javascripts.

Normalement UglifyJs est utilisé avec Node.js, mais si vous voulez appeler UglifyJs depuis un environnement Java vous pouvez le faire à l'aide du projet Wro4J

Vous allez surement me demander pourquoi utiliser UglifyJS en Java alors que Google Closure répond exactement à ce problème ? Vous auriez raison, mais c'est tellement plus drôle d'essayer de faire tourner du Javascript dans une JVM !!!

Aller je vous un bout de code codé en Groovy qui utilise UglifyJS :


@Grab(group = 'ro.isdc.wro4j', module = 'wro4j-extensions', version = '1.3.8')

import ro.isdc.wro.extensions.processor.algorithm.uglify.*

def uglify = UglifyJs.uglifyJs()
uglify.process(new File("/home/romain/plugin/web/web-app/lib/route.js").text);


Wro4J utilise Rhino pour exécuter le Javascript.
Les sources sont ici :
https://github.com/alexo/wro4j/blob/master/wro4j-extensions/src/main/java/ro/isdc/wro/extensions/processor/algorithm/uglify/UglifyJs.java

mardi 5 juillet 2011

Maven : créer un projet multi-module

Maven, le très célèbre outil de build et gestionnaire de dépendances nous offre quelques possibilités bien sympatique.

Vous connaissez sûrement les projets multi-modules, qui permettent de découper un projet pour plus de modularité.

Par exemple vous construisez un projet P. Ce projet est constitué de plusieurs sous-projet A, B, C ayant comme dépendances respectives :

P :
  - A (A1, O)
  - B (O)
  - C (C1, A)

Comme vous le voyez, C dépend de A, mais pas de B. De plus la dépendance O est partagée entre plusieurs sous-projet.

Maven va bous permettre de gérer ses trois sous projet en réduisant le nombre de lignes de code copiées collées.



Voici le pom de P, le projet coordinateur :

<project ....>

    <groupId>org.groupId</groupId>
    <artifactId>P</artifactId>
    <packaging>pom</packaging>
    <version>1.0.0</version>
    <modelVersion>4.0.0</modelVersion>
    
    <modules>
        <module>A</module>
        <module>B</module>
        <module>C</module>
    </modules>
</project>


Il faut remarquer deux choses :
 
  - le packaging == pom, qui nous dit que ce projet n'aura pas de code source
  - la section modules qui représente notre structure.


Ensuite à la racine de ce projet, nous allons créer les 3 sous projets : A, B, C

/my-project
|--pom.xml
|--A
|  `--pom.xml
|--B
|  `--pom.xml
`--C
   `--pom.xml     



Voici le pom du sous-projet A  :

<project ...>
    <parent>
        <artifactId>P</artifactId>
        <groupId>org.groupId</groupId>
        <version>1.0.0</version>
    </parent>
    
    <modelVersion>4.0.0</modelVersion>
    <artifactId>A</artifactId>
    
....


Dans la balise parent, on défini la dépendance vers notre projet parent P.

Nous remarquons que pour A, il n'y a pas de balise groupId ni de balise version à définir A.
En effet, ces valeurs sont héritées du pom parent, pratique !!!!



Maintenant prenons le cas où certains sous-projets aient des dépendances en commun. A et B dépendent de O.

On pourrait tout a fait déclarer dans A et dans B les dépendances complètes (avec la version) :
<dependencies>
    <dependency>
        <groupId>com.aProject</groupId>
        <artifactId>O</artifactId>
        <version>5.6.7</version>
    </dependency>
</dependencies>


Mais le jours, on l'on changera la version de O ( 5.6.7 ---> 5.6.8 ) dans A, on oubliera sûrement de changer la version de O dans B, et l'on se retrouvera avec un pom dégelasse avec plein de dépendances différentes.

La solution consiste donc à ne pas déclarer les versions dans les poms des sous-projets, mais dans le pom parent.


Je vous donne un exemple :

<project ....>

    <groupId>org.groupId</groupId>
    <artifactId>P</artifactId>
    <packaging>pom</packaging>
    <version>1.0.0</version>
    <modelVersion>4.0.0</modelVersion>
    
    <modules>
        <module>A</module>
        <module>B</module>
        <module>C</module>
    </modules>
    
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>commons-io</groupId>
                <artifactId>commons-io</artifactId>
                <version>2.0.1</version>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.8.2</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>




Dans le pom d'un sous-projet, la section de dépendance ressemblera à :
<dependencies>
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

Cool, on a supprimé la version !!!!



Maintenant voyons le cas où C dépend de A, c'est à dire étudions les dépendances entre sous-projets.

Voici la section de dépendance de C :
<dependencies>
    ....
    <dependency>
        <groupId>${parent.groupId}</groupId>
        <artifactId>A</artifactId>
        <version>${parent.version}</version>
    </dependency>
    ....
</dependencies>


On est obligé de spécifier la version, mais regardez bien, nous faisons référence à une variable interne : ${parent.version}, de même pour la balise groupId. Zéro problème pour maintenir ce pom !!!


Et maintenant nous pourrions avoir envie de créer nos propres variables dans le pom parent et d'utiliser n'importe où.
Aussitôt dit, aussitôt fait. Editez votre pom parent et ajoutez la section :
<properties>
    <foo.bar>FooBarValue</foo.bar>
</properties>

Maintenant on peut utiliser cette valeur de partout ce cette façon : ${foo.bar}

Il y a bien sur une limite, la section parent ne peut être défini à partir de variable défini dans le pom parent. Sinon ce n'est pas évident pour deviner qui est le parent quand on lit le pom d'un sous-projet.

mardi 28 juin 2011

Compiler des fichers less -> css en Groovy

Less-css est un CSS amélioré.

Pour citer quelques exemples on peut :
- créer des variables et les réutiliser partout
- imbriquer des blocs css, dans d'autre bloc css.
- ...

Par exemple :

@import "global.less";

@size: 14px;

#col{

.odd{
color: red;
font-size: @size;
}

.even{
color: blue;
font-size: @size;
}

}


Les fichiers less sont transformés en CSS par un script js. Ce qui permet de tester en live sur son site web, mais la conversion less/css est plutôt lente.

Il est donc préférable de compiler les fichiers less avant la prod.

Je vous livre donc un code groovy qui permet très facilement de convertir un fichier less en CSS. A vous de le transformer en JAVA et de l'intégrer dans votre environnement de développement.

Pour info, il existe lessc, le compilateur less officiel qui repose sur nodeJS. Si vous ne voulez pas installer node.js, cette version Java vous plaira (elle utilise Rhino).


@Grab(group='com.asual.lesscss', module='lesscss-engine', version='1.0.43')
@GrabResolver(name='asual', root='http://www.asual.com/maven/content/repositories/releases')

import com.asual.lesscss.*

new LessEngine().compile(new File("/home/romain/Bureau/less/root.less"),new File("/home/romain/Bureau/less/root.css"));

lundi 27 juin 2011

Groovy et l'immutabilité

Depuis la version 1.8, Groovy permet de rendre des classes entièrement immutables, c'est à dire des classes qui ne peuvent pas changer d'état.

Ceci peut être pratique pour écrire du code thread safe.

Voici un exemple de classe immutable en Groovy.
PS : ne surtout pas oublier le import groovy.transform.Immutable, sinon c'est l'ancien groovy.lang.Immutable qui est utilisé (Cf : http://comments.gmane.org/gmane.comp.lang.groovy.user/55021)


import groovy.transform.Immutable

@Immutable
final class Punter {
String first
String last
Map params
}

@Immutable
final class PunterWrapper {
String name
Punter punter
}


def wrapper = new PunterWrapper(
name: 'hi',
punter: new Punter(
first: 'Foo',
last: 'Bar',
params: [k: 'value']
)
)


println wrapper

try{
wrapper.punter.params.toto = 3
}catch(Exception e){
println('Exception catched ')
}

try{
wrapper.punter.last = 'Tutu'
}catch(Exception e){
println('Exception catched ')
}

try{
wrapper.name = 'Toto'
}catch(Exception e){
println('Exception catched ')
}

PunterWrapper(name:hi, punter:Punter(first:Foo, last:Bar, params:[k:value]))
Exception catched
Exception catched
Exception catched




Mais écrire des classes immutables en Groovy peux s'avérer complexe à gérer.

Pour éviter récrire le constructeur complet de l'objet à chaque fois que l'on souhaite modifier une valeur, voici une solution que j'ai trouvé :


println new PunterWrapper(wrapper.properties + [
name: 'Titi',
punter: new Punter(wrapper.punter.properties + [
first: 'Mickael'
])
])​

PunterWrapper(name:Titi, punter:Punter(first:Mickael, last:Bar, params:[k:value]))



Un nouvel objet est créé à partir des attributs modifiés de l'ancien objet.



On peut également travailler avec les Collections de la même façon :

def list = [a: 1,b: 2,c: 3].asImmutable()
println list

try{
list​.d=4
}catch(Exception e){
println 'Exception catched'
}


def list2 = (list + [d:4]).asImmutable()
​println list2


def listMutable = list2 + [e:5]
listMutable.f = 6
println listMutable


[a:1, b:2, c:3]
Exception catched
[a:1, b:2, c:3, d:4]
[a:1, b:2, c:3, d:4, e:5, f:6]



Mais il ne faut pas oublier le asImmutable() à chaque modification de la collection.


Groovy nous donne donc quelques possibilités pour travailler dans un environnement immutable, mais ce n'est pas encore très pratique.

Scala est mieux sur ce point là.

lundi 20 juin 2011

JAVA et Groovy

Groovy est un langage de programmation, basé sur Java et s'intégrant très bien avec tout son écosystème.

Pour vanter quelques mérites de Groovy voici des exemple Groovy VS Java :



JAVA
--------
String name = "World"
System.out.println("Hello " + name);

GROOVY
-----------
def name = "World"
println "Hello $name"


JAVA
--------
Map<String, String> params = new HashMap<String, String>();
params.put("key", "value")
System.out.println(params.get("key"))

GROOVY
-----------
def params = [key: "value"]
println params.key



JAVA
--------
public class Customer {

    private String name;

    private int age;

    Customer() {
    }

    Customer(String name, int age) {
        this.age = age;
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }


    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Customer customer = (Customer) o;

        if (age != customer.age) return false;
        if (name != null ? !name.equals(customer.name) : customer.name != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }

    @Override
    public String toString() {
        return "Customer{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public static void main(String[] args) {
        Customer toto = new Customer("Toto", 7);

        Customer toto2 = new Customer();
        toto2.setName("Toto");
        toto2.setAge(7);

        System.out.println(toto.equals(toto2));
    }
}


GROOVY
-----------
import groovy.transform.* 

def toto = new Customer(name: 'Toto', age: 7)

def toto2 = new Customer()
toto2.name = 'Toto'
toto2.age = 7

assert toto == toto2

@ToString 
@EqualsAndHashCode 
class Customer{

  String name

  int 
age


}​






Comme vous le voyez, Groovy permet d'avoir une syntaxe bien plus concise que l'équivalent en Java.

Moins de code à écrire == plus facile à développer == plus facile à lire (une fois que l'on a l'habitude) == plus facile à maintenir...


Et la liste est longue des Groovyness utilisables : 
  - la gestion des collections : filtrage, trie, modification, .... (simplifié grâce à la programmation fonctionnelle) : http://groovy.codehaus.org/Collections
  - la gestion des dates : http://groovy.codehaus.org/JN0545-Dates
  - la création de script dépendant de librairies présent sur Maven : http://groovy.codehaus.org/Grape
  - éviter les null pointer exceptions avec les opérateurs ?. et ?: : http://docs.codehaus.org/display/GROOVY/Operators#Operators-ElvisOperator%28%3F%3A%29
  - la gestion des fichiers : http://groovy.codehaus.org/JN2015-Files
  - toute les exceptions sont gérées comme des RuntimeException
  - ...

Groovy est un langage qui évolue vite, actuellement nous sommes à la version 1.8. Cette version ci rajoute un certain nombre de fonctionnalités intéressantes comme le support natif du JSON, l’annotation @Log qui permet d'injecter un logger (slf4j, log4j, ...), @ToString et @EqualsAndHashCode que je viens de vous montrer et encore pleins d'autres choses merveilleuses à découvrir ici : http://docs.codehaus.org/display/GROOVY/Groovy+1.8+release+notes






Depuis plus d'un an que j'utilise groovy tous les jours, je n'ai toujours pas rencontré de bug. Nous l'avons utilisé pour des scripts, des tests et des applications en production (http://www.grails.org/). C'est un langage que je recommande vraiment. Pour un développeur Java, c'est vraiment une bouffé d'air frais.

Il n'y a pas que des avantages, Groovy est lent, mais je trouve que le temps gagné lors de la phase de développement en vaut la chandelle.

Groovy est dynamique et n'est pas fortement typé, ce qui nécessite d'écrire plus de test unitaire. C'est peut être là sont plus gros défaut. 

Néanmoins, ces problèmes disparaîtront peut être un jours car les performance de Groovy ne font que s'améliorer avec le temps. De plus groovy++ est un projet prometteur car il ajoute un typage statique et des performances équivalentes à celles de Java. Mais je ne l'ai encore jamais testé.

L'intégration avec les IDE n'est pas forcement parfaite : 
  Netbeans -> moyen, 
  IntelliJ -> excellent, équivalent à Java

Mais l'integration avec Maven ne pose aucun problème : http://docs.codehaus.org/display/GMAVEN/Building+Groovy+Projects

Concernant les tests je conseille le framework Spock, sinon un simple JUnit fait très bien l'affaire. Pour du BDD, on peut utiliser EasyB, mais je préfère quand même Spock.

Come Java, Groovy ne favorise pas l'immutabilité (contrairement à scala) est c'est bien dommage pour les applications multi-threadées.

GPars a été intégré avec Groovy depuis la version 1.8 pour simplifier la programmation multi-threadée, mais j'ai encore un peu de mal à l'utiliser. Je ne trouve pas l'API intuitive. Mais bon je vais surement m'y habitué.

Pour avoir également testé Scala quelques jours, Groovy est peut être moins puissant mais est plus facile à prendre en main lorsque l'on est habitué à Java. Mais Scala semble quand même plus robuste et plus simple pour tout ce qui concerne le développement d'applications multi-threadées, tolérantes aux pannes et scalable  : http://akka.io/

lundi 9 mai 2011

Dig en Java

DNSJava est une API JAVA permettant de faire des résolutions de domaines.

DNSJava offre également une implémentation équivalente à dig (voir les sources)

Si vous souhaitez parser le contenu d'un DIG en Java pour récupérer les IPs des serveurs, je vous conseil plutôt d'utiliser l'API de DNSJava.
Vous aurez une représentation objet du DIG qui vous permettra de ne récupérer que ce qui vous intéresse vraiment.

Voici un exemple écrit en groovy qui fait l'équivalent d'un 'dig google.com'


import org.xbill.DNS.*;

@Grab(group='dnsjava', module='dnsjava', version='2.1.1')

SimpleResolver res = new SimpleResolver();
Record rec = Record.newRecord(Name.fromString("google.com", Name.root), Type.A, DClass.IN);
Message query = Message.newQuery(rec);
Message response = res.send(query);
println("----------------------------------------------------------");
for (Record record : response.getSectionArray(1)) { // ANSWER SECTION
println(record.rdataToString());
}
println("----------------------------------------------------------");
println(response.toString()); //THE WHOLE DIG


Et voici le résultat affiché :

--------------------------------------------------------
209.85.227.106
209.85.227.103
209.85.227.105
209.85.227.104
209.85.227.99
209.85.227.147
--------------------------------------------------------
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 53158
;; flags: qr rd ra ; qd: 1 an: 6 au: 0 ad: 0
;; QUESTIONS:
;; google.com., type = A, class = IN

;; ANSWERS:
google.com. 300 IN A 209.85.227.106
google.com. 300 IN A 209.85.227.103
google.com. 300 IN A 209.85.227.105
google.com. 300 IN A 209.85.227.104
google.com. 300 IN A 209.85.227.99
google.com. 300 IN A 209.85.227.147

;; AUTHORITY RECORDS:

;; ADDITIONAL RECORDS:

;; Message size: 124 bytes

vendredi 15 avril 2011

Grails thumbnail : Reduire une image dans grails en gardant une bonne qualité

En java ce n'est pas forcement facile de trouver une librairie pour réduire des images en gardant une bonne qualité.

Heureusement il existe le projet Java Image Scaling qui a sa librairie sur maven.
http://code.google.com/p/java-image-scaling/


Maintenant voici comment intégrer Java Image Scaling dans grails : un jeu d'enfant :)

Ajouter la dépendance suivante dans grails-app/conf/BuildConfig.groovy


runtime 'com.mortennobel:java-image-scaling:0.8.5'


Dans votre controller ajoutez le bout de code suivant :


/**
* Return the content of screen shot
*/
def viewScreen = {
File img = new File("myImage.png")
response.contentType = 'image/png'
if(params.thumbnail){
BufferedImage inputImage = ImageIO.read(img);
BufferedImage rescaledImage = new MultiStepRescaleOp(DimensionConstrain.createMaxDimension(355,500)).filter(inputImage, null);
def outputStream = new ByteArrayOutputStream()
ImageIO.write(rescaledImage, "png", outputStream);
response.outputStream << outputStream.toByteArray()
}else{
response.outputStream << img.bytes
}
}

jeudi 24 mars 2011

Script SQL en Groovy

Voici un exemple de script Groovy se connectant sur une base de donnée MySQL avec Groovy Grape :


import org.springframework.jdbc.datasource.SimpleDriverDataSource;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;

@GrabConfig(systemClassLoader=true)
@Grab(group='mysql', module='mysql-connector-java', version='5.1.6')
@Grab(group='org.springframework', module='spring-jdbc', version='3.0.5.RELEASE')


DataSource dataSource = new SimpleDriverDataSource(
Class.forName("com.mysql.jdbc.Driver").newInstance(),
"jdbc:mysql://localhost:3306/myDatabase",
"login",
"password");

JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
println jdbcTemplate.queryForList( """SELECT 1;""" )


C'est très pratique pour debugguer les erreurs du type :

Caught: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

Last packet sent to the server was 0 ms ago.
at test.run(test.groovy:19)

lundi 7 mars 2011

Selenium Perl et Debian (ou Ubuntu)

Selenium IDE : http://seleniumhq.org/projects/ide/ permet de créer des scripts selenium et de les exporter sous différents langage : Java, C#, Groovy, Python, Ruby et Perl pour les sysadmins


Ce qui nous intéresse ici c'est d'utiliser perl!


Tout d'abord il faut installer les paquets suivant :

apt-get install perl libtest-exception-perl libtest-www-selenium-perl


Ensuite il faut créer un script selenium sous Selenium IDE et l'exporter au format Perl.

Voici un script selenium bidon exporté en Perl :

use strict;
use warnings;
use Time::HiRes qw(sleep);
use Test::WWW::Selenium;
use Test::More "no_plan";
use Test::Exception;

my $sel = Test::WWW::Selenium->new( host => "localhost",
port => 4444,
browser => "*chrome",
browser_url => "http://fr.yahoo.com/" );

$sel->open_ok("/");
$sel->click_ok("link=Jacques Chirac aux portes du tribunal pour un procès?");
$sel->wait_for_page_to_load_ok("30000");
$sel->click_ok("link=Villepin souhaite que Chirac soit jugé, s'oppose à un report");
$sel->wait_for_page_to_load_ok("30000");


Maintenant si on lance le script perl on obtient l'erreur suivante :

Error requesting http://localhost:4444/selenium-server/driver/?cmd=getNewBrowserSession&1=*chrome&2=http%3A%2F%2Ffr.yahoo.com%2F:
500 Can't connect to localhost:4444 (connect: Connexion refusée)
# Looks like your test died before it could output anything.
zsh: exit 255 perl perl.pl

Ce qui signifie qu'il n'y a pas de serveur selenium de lancé.


Pour lancer un serveur selenium, il y a plusieurs méthodes :

1 - On télécharge le jar de selenium-server et on le lancer en java

firefox http://seleniumhq.org/download/
java -jar selenium-server.jar


2 - Sinon, on exécute le script groovy suivant (Il s'occupe de télécharger et lancer Selenium Server)

import com.thoughtworks.selenium.*
import org.openqa.selenium.server.*

@Grab(group='org.seleniumhq.selenium.server', module='selenium-server', version='1.0.1')

def server = new SeleniumServer()
server.main(new String[0])
println("Started")

lundi 14 février 2011

Rechercher dans Maven Central

Nous avons souvent besoin de rechercher des dépendances pour les inclure dans nos projets maven.

Le problème c'est que maven central est un peu gros. Sonaytype nous dis en 2010 :
"the Central Maven repository contains almost 90000 software artifacts occupying around 70 GB of disk"

Pour trouver nos petits, soit on navigue à la main dans l'arborescence de maven central :
http://repo1.maven.org/maven2/
http://repo2.maven.org/maven2/

Soit on utilise des outils de recherche. J'en connais deux :
  - http://mavencentral.sonatype.com/ : Qui utilise l'indexer maven, open sourcé par sonatype (Cf : http://www.sonatype.com/people/2011/02/maven-indexer-sonatypes-donation-to-repository-search/)

  - http://mvnrepository.com


Je trouve http://mavencentral.sonatype.com/ intéressant car il nous montre si les sources et la javadoc sont téléchargeable via maven.

Quand à http://mvnrepository.com, c'est celui que j'utilise depuis toujours :). Il est bien, mais il génère beaucoup plus de résultats parasites. Par contre il permet une navigation via les dépendances et via les usages.

dimanche 6 février 2011

Serveur REST avec JAXRS + Basic Auth + SSL avec Restlet

J'avais un peu galéré pour mettre en place un serveur webservice REST avec authentification basic et chiffrement  SSL en java.

L'authentification basic transmettant le login et le mot de passe en clair, il est indispensable de l'utiliser via une connexion chiffré (HTTPS).

JAX-RS est l'un des standard pour faire des web-services JAVA :

  • JAX-RS = JSR311 pour les webservices REST
  • JAX-WS = JSR 224 pour les webservices SOAP

En dehors des standards il existe un certain nombre de frameworks pour faire des web-services REST en JAVA :



A l'époque j'était parti sur une base CXF, mais la documentation n'étais pas très abondante.

Ensuite j'ai migré sur Restlet. La solution n'a pas été très évidente à trouver, mais ça marche.

Voici la solution (pour les plus pressés):
https://github.com/Filirom1/JAX-RS-Server/blob/master/src/main/java/org/filirom1/jaxrs/JAXRSServer.java


Maintenant, si vous ne voulez pas vous prendre la tête, voici une API plus simple d'utilisation :
JAXRSServer server = new JAXRSServer(MyResource.class, 8443);
server.enableBasicAuthentication("Realm", "login", "password");
server.enableSSL("www.hostname.fr", new File("path-to-your-keystore.jks"), "keyStorePassword", "keyPassword");
try {
    server.start();

    /* do what you have to do */

    server.stop();
} catch (Exception ex) {
    Assert.fail("Unable to start", ex);
}

Et voici un exemple de Resource JAX-RS qui affiche un hello world :
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

@Path("/")
class MyRessource{

    @GET
    @Produces("text/plain")
    public String getPlain() {
        return "Hello world)";
   

Et pour les utilisateurs de maven, voila comment inclure cet API dans votre pom.xml :
<dependencies>
...
    <dependency>
        <groupId>org.filirom1</groupId>
        <artifactId>JAX-RS-Server</artifactId>
        <version>1.0.0</version>
        <type>jar</type>
    </dependency>
...
</dependencies>
<repositories>
    <repository>
        <id>filirom1-repo</id>
        <url>https://Filirom1@github.com/Filirom1/filirom1-mvn-repo/raw/master/releases</url>
    </repository>
    <repository>
        <id>maven-restlet</id>
        <url>http://maven.restlet.org</url>
    </repository>
</repositories>
https://github.com/Filirom1/JAX-RS-Server

Juste pour le fun, j'utilise Resty comme client Webservice REST.
Il est simple d'utilisation et léger (0 dépendance externe).

Voici un exemple pour faire un GET avec authentification basic :
Resty r = new Resty();
r.authenticate("https://localhost:8443", "login", "password".toCharArray());
String resp = r.text("https://localhost:8443").toString();


Si vous avez des problèmes avec votre client REST avec les certificats auto-signés, je vous conseil le code de Francis Labrie :
  • SSLUtilities.trustAllHostnames() pour désactiver la vérification du hostname pour les connexion HTTPS
  • SSLUtilities.trustAllHttpsCertificates() pour désactiver la vérification du certificat pour les connexions HTTPS


Et si vous ne savez encore comment générer un certificat auto-signé :
# Generate a Self-Signed Certificate #
keytool -genkey -v -alias localhost -dname "CN=localhost, OU=IT, O=MyCompany, L=Lyon, ST=France, C=FR" -keypass password -keystore localhost.jks -storepass password -keysize 1024;

# Export your certificate in order to import it in your trustore
keytool -storepass password -alias localhost -export -file localhost.cer -keystore localhost.jks

# Import your certificate into the default JAVA truststore.
sudo keytool -keystore /etc/java-6-sun/security/cacerts -storepass changeit -import -trustcacerts -v -alias localhost -file localhost.cer



Ou sinon, on peut également générer des certificats auto-signés avec maven (très pratique pour les tests) :
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>keytool-maven-plugin</artifactId> <executions> <execution> <phase>generate-resources</phase> <id>clean</id> <goals> <goal>clean</goal> </goals> </execution> <execution> <phase>generate-resources</phase> <id>genkey</id> <goals> <goal>genkey</goal> </goals> </execution> </executions> <configuration> <keystore>${project.build.directory}/localhost.jks</keystore> <dname>CN=localhost, OU=IT, O=MyCompany, L=Lyon, ST=France, C=FR</dname> <keypass>password</keypass> <storepass>password</storepass> <alias>localhost</alias> <keyalg>RSA</keyalg> </configuration> </plugin>