RichFaces

Je continue dans ma recherche de librairie de composants pour JSF. J'avais déjà testé ICEFaces, mais elle ne me satisfaisait pas. Trop de changement au niveau du cycle de vie de JSF à mon goût.

J'ai testé aujourd'hui une nouvelle librairie, qui à l'air de s'intégrer parfaitement à JSF. Très peu de changements dans le cycle de vie JSF, beaucoup de composants, dont la plupart en Ajax. Il s'agit de RichFaces.

L'installation, comparée à celle de ICEFaces, est très simple. Quelques librairies, quelques dépendances (BeanUtils, Collections, Digester, Commons Log). La seule configuration nécessaire est la déclaration d'un filtre dans le fichier web.xml :
Il ne reste plus qu'à tester la liste assez imposante de composants proposés :)

Permalink  |  Commentaires (0)

EJB 3.1, on y arrive !

Cela va mainteant faire 4 jours que GlassFish v3 prelude est sorti. Pour accompagner sa sortie, une vingtaine de présentations ont été faites sur GlassFish (via la chaine TheAquarium, sur Ustream.TV), mais aussi sur Java EE 6 et NetBeans 6.5.

Je viens d'en regarder quelques unes, et celle qui a le plus retenu mon attention est sans aucun doute la présentation des EJB 3.1, qui vient avec son lot d'améliorations et de nouvelles fonctionnalités qui méritent de s'y attarder :-)

On retrouve parmis ces fonctionnalités :
  • Les singletons
  • Une meilleure gestion des timers
  • Les noms JNDI globaux
  • Les Session Beans "sans interface"

Les singletons

Les singletons sont des beans qui ont la particularité de n'être instanciés qu'une seule et unique fois tout au long de la vie de notre application. Cette instance sera ensuite partagée entre les différents clients l'utilisant.

@Singleton
public class MySingleton {

    private int sharedValue;

    public int getSharedValue() {
        return (sharedValue);
    }

}

Dans cet exemple de code, notre bean MySingleton sera instancié une seule et unique fois, et chaque appel de méthode fera appel à la même instance, ce qui nous permettra, par exemple, de partager des données (comme la variable sharedValue de notre exemple).

Une meilleure gestion des timers

EJB 3.1 introduit également une nouvelle gestion des timers, qui se rapproche de la gestions des crons Unix : on peut spécifier des tâches à exécuter de manière très précise. Ces timers seront alors automatiquement créés et démarrés.

Voici un exemple, lançant une tâche tous les jours à 8 heures :
@Stateless
public class MyBean implements MyInterface {

    @Schedule(hour="8")
    void myTask() {
    }

}

Les noms JNDI globaux

Il s'agit sûrement d'une des plus grosses lacunes de la spécification EJB 3 qui se trouve ici comblée : l'absence de standardisation des noms JNDI associés aux Session Bean, ce qui entraînait des pertes de portabilité entre les différents serveurs d'application.

Par exemple, sous GlassFish, le nom par défaut d'un Session Bean est le nom complet de l'interface métier de notre bean (com.aperigeek.ejb.MyInterface). Sous JBoss, le nom est <nom du jar>/<nom du bean>/<visibilité>, ce qui donnerais par exemple aperigeek/MyBean/remote. Les noms sont donc très dépendants du serveur d'application.

La nouvelle spécification EJB 3.1 spécifie des noms standards à respecter lors du binding des beans : java:global[/<app-name>]/<module-name>/<ejb-name>, ce qui pourrait donner : java:global/aperigeek/aperigeek-ejb/MyBean. Cette fonctionnalité permet d'assurer la portabilité d'une application entre différents serveurs d'applications.

Les Session Beans "sans interface"

Dernière fonctionnalité dans la série des simplifications de la spécification : la possibilité de définir un Session Bean dans une seule classe, sans passer par une interface métier exposant les différentes méthodes.

@Stateless
public class MyBean {

    public void myMethod() {
    }

}

Dans ce cas de figure, toutes les méthodes publiques deviennent visibles.
@Stateless
public class MyOtherBean {

    @EJB
    private MyBean myBean;

    public void myOtherMethod() {
        myBean.myMethod();
    }

}



La nouvelle version des EJB, la version 3.1, apporte encore quelques améliorations à la version 3.0. L'optique de cette nouvelle version reste essentiellement la même : simplifier l'utilisation des EJBs. On retrouve quand même quelques nouvelles fonctionnalités intéressantes, comme les singletons ou les timers.

Toutes ces nouvelles fonctionnalités sont d'ores et déjà testables grâce à GlassFish v3 prelude, qui sert d'implémentation de référence à cette spécification.

Permalink  |  Commentaires (0)

Java/C : Sockets


J'ai refait un peu de C hier, "pour le plaisir"... Je pense que les deux bouts de code au dessus parlent pour moi :-)

Juste, en passant, le plugin C/C++ de NetBeans est tout simplement... bien. Toutes les fonctionnalités que l'on attend d'un IDE sont là (autocomplétion, affichage des paramètres des fonctions, ...). Moi qui n'aimais pas les IDE pour le C, j'ai été plutôt surpris. Dans le bon sens :-)

Permalink  |  Commentaires (1)

Java/.NET : Opérateurs

Dans ce billet, nous allons parler des opérateurs. Les opérateurs existants en Java existent également en C#, et les différences entre les deux sont quasi-inexistantes.

Nous allons donc parler de deux fonctionnalités, présentes en C#, qui n'existent pas en Java :
  • La surcharge des opérateurs
  • Les indexeurs

Surcharge des opérateurs

Le langage C#, contrairement au langage Java, implémente la surcharge des opérateurs. Les principes sont inspirés du C++.

Voici un exemple de surcharge des opérateurs en C# :
class Program
{
    static void Main(string[] args)
    {
        MyString s1 = new MyString("Hello ");
        MyString s2 = new MyString("World!");
        MyString s = s1 + s2;
    }
}

class MyString
{
    private string _value;
    public MyString(string _value)
    {
        this._value = _value;
    }
    public static MyString operator + (MyString a, MyString b)
    {
        return (new MyString(a._value + b._value));
    }
}

Il n'existe aucun équivalent à la surcharge des opérateurs en Java.

Indexeurs

Le langage C# introduit un nouveau concept, les indexeurs. Un indexeur est semblable à un opérateur, et il permet d'accéder à un index donné d'un objet, comme par exemple un tableau. Cet index peut être de type int, mais aussi de n'importe quel autre type, valeur ou référence.

Voici un exemple de code mettant en oeuvre un indexeur :
class Program
{
    static void Main(string[] args)
    {
        MyIndex i = new MyIndex();
        Console.WriteLine(i[12]);
    }
}

class MyIndex
{
    public string this [int index]
    {
        get
        {
            return ("Index " + index);
        }
    }
}

Il n'existe aucun équivalent aux indexeurs en Java.


En ce qui concerne les opérateurs en C#, nous avons vu deux fonctionnalités intéressantes qui n'existent malheureusement pas en Java.

Beaucoup de personnes ont espéré voir la surcharge des opérateurs arriver dans Java 7. Cependant, cette fonctionnalités est assez controversée, et il y a peu de chances de la voir arriver dans le langage (de même que les indexeurs).

Permalink  |  Commentaires (0)

Java/.NET : Types de données

Dans ce second billet de la série "Java/.NET", nous allons parler de toutes les différences touchant aux types de données.

Fichiers sources

En Java, le compilateur n’autorise qu’une seule et unique classe publique par fichier source. De plus, la classe publique d’un fichier source doit posséder exactement le même nom que le fichier dans lequel elle se trouve.

En C#, les restrictions comme celles-ci n’existent pas. Il est possible de déclarer plusieurs classes publiques au sein du même fichier, et aucune vérification n’est faite quand au nom du fichier contenant les classes.

Types primitifs - types valeurs

En Java comme en C#, il existe un type de données particulier : leur valeur est directement stocké dans une zone mémoire appelée la pile. De plus, ces différents types de données sont directement passés par valeur.

Ils peuvent représenter une valeur "basique", à savoir :
  • Un nombre (entier ou à virgule flottante)
  • Un caractère
  • Un booléen

En Java, ces types de données qui sont appelés des types primitifs. Il s’agit des seuls types de données qui ne sont pas des objets, c'est-à-dire qu’ils ne possèdent aucune méthode. Pour palier à cet inconvénient, il existe des types dits wrappers, qui sont des équivalents objets de ces types primitifs.

En C#, ces types sont appelés les types valeurs. Ils résident également sur la pile, mais ce sont cependant des objets. Chaque type valeur possède un alias, qui permet de faciliter l’appel de ces types dans le code. Par exemple, le type valeur Int32 possède un alias int. Ces alias seront convertis au moment de la compilation.

A noter également qu’en C#, les chaînes de caractères et les énumérations ont la particularité d’être des types valeur. Au contraire, les chaînes de caractères et les énumérations en Java sont des objets, et résident sur le tas.

Types références

Chacun des deux langages définit un autre type de variables : les types références.

Contrairement aux types primitifs (ou types valeurs), ils sont passés par référence lors des différents appels de méthodes. Ils représentent en général des types complexes, que nous allons définir nous même. De plus, la valeur de ces types de données est stockée sur le tas, et la pile ne contient qu’une référence vers ces objets.

En Java, chaque type primitif possède un équivalent en type référence. Ce sont les types wrappers. Ces objets sont des objets comme tous les autres objets Java. Leur valeur réside sur le tas et ils sont passés par référence lors des différents appels de méthodes. Depuis Java 1.5, la conversion entre les types primitifs et types wrapper est automatique.

En C# comme en Java, les classes sont des types références.

Structures

Le langage C# introduit un type de données qui n’existe pas en Java : le type structure. Les structures sont un type de données semblable aux classes, sauf qu’elles sont de types valeur, et non de type référence.

Cette différence implique que les structures sont stockées sur la pile (et non sur le tas, contrairement aux objets), et qu’elles sont passées par valeur en paramètre aux méthodes.

De par leur statut particulier, les structures ont cependant quelques fonctionnalités en moins par rapport aux classes. Il est impossible par exemple d’hériter d’une structure en C#.

Enumérations

En Java, les énumérations sont des objets. Comme pour les objets, il est possible de leur définir des attributs, des méthodes, et même des constructeurs.

Contrairement à cela, en C#, les énumérations sont de type valeur. Les énumérations correspondent à des entiers codés sur 8, 16, 32 ou 64 bits. Il est également possible d’assigner n’importe quelle valeur numérique à une énumération (y compris des valeurs non définies dans l’énumération), ainsi que de combiner plusieurs valeurs pour une même énumération grâce à l’opérateur | (bitwise or).

Espaces de nommages

Lors du développement d’applications, il arrive que plusieurs structures de données (classes, interfaces, énumérations...) possèdent le même nom. Afin d’éviter les collisions de noms ainsi générées, chaque langage à mis en place sa propre solution : les espaces de nommages.

En Java, un espace de nommage s’appelle un package. Un package doit être déclaré en début de tout fichier source grâce au mot clé package suivi du nom du package, et s’applique à tout le fichier. Il est possible d’accéder à des classes appartenant à d’autres packages grâce au mot clé import, suivi du nom de la classe à importer. Il est également possible d’importer toutes les classes d’un package en utilisant l’étoile (*).

En C#, un espace de nommage s’appelle un namespace. Un namespace est un bloc de code, noté grâce au mot clé namespace, suivi du nom du namespace. Il est possible d’utiliser des classes appartenant à d’autres espaces de noms grâce au mot clé using, suivi du nom de l’espace de nom à utiliser.

Voici par exemple la déclaration de deux classes dans un espace de nommage, en Java (à gauche) et en C# (à droite) :
package ns;

class Toto {
}

class Tata {
}

namespace Ns
{
    class Toto
    {
    }
    class Tata
    {
    }
}

Types génériques

Java et C# implémentent tous les deux les types génériques. Si l’utilisation est similaire dans les deux langages, leurs implémentations sont cependant très différentes.

Premier point, les types génériques en Java n’acceptent pas les types primitifs, alors que l’implémentation en C# accepte les types valeurs.

Second point, les génériques en Java sont implémentés selon une technique dite du type erasure. Derrière ce nom effrayant se cache un concept simple : les génériques en Java sont évalués à la compilation, toute trace de type générique n’existe plus à l’exécution. C’est le compilateur qui va se charger de transformer les types génériques en leurs opérations équivalentes (principalement du transtypage et des vérifications de types), et supprimer toute trace de leur passage.

Contrairement à cela, les génériques en C# persistent à l’exécution, et sont interprétés par l’environnement d’exécution. Il est donc possible de connaître le type générique d’une classe ou d’une méthode lors de l’exécution.

Les conséquences sont alors multiples. Par exemple, en C#, il est possible de créer une instance d’un type générique, et des tableaux de types génériques, choses qui sont impossibles à faire en Java, principalement à cause du type erasure.

Autre différence importante, il est possible d’effectuer des vérifications plus poussées sur les types utilisés en tant que types génériques dans le langage C#. Par exemple, en C#, il est possible de définir une contrainte « Cette classe utilise un type T, qui doit posséder un constructeur par défaut », contrainte qui est impossible en Java.


Voilà donc la fin de cette liste de différences entre Java et C# en ce qui concerne les types de données.

Le prochain billet portera sur les opérateurs, et devrait parler de deux fonctionnalités présentes en C# et inexistantes en Java : la surcharge des opérateurs et les indexeurs.

PS : Ceci était de 42ème billet de ce blog ;-)

Permalink  |  Commentaires (1)