lundi 23 mars 2009

L'Enquête - The International

Synopsis

Sous des dehors respectables, l'International Bank of Business and Credit est une multinationale de la finance spécialisée dans le blanchiment d'argent et le financement d'opérations illégales.
Face à elle, Louis Salinger, agent d'Interpol, et Eleanor Whitman, district attorney adjoint de Manhattan, sont déterminés à mettre fin à ses activités illicites. Ils sont prêts à tout pour que la justice règle son compte à cette organisation tentaculaire et intouchable, mais pour y parvenir, ils vont eux aussi devoir agir au-delà des lois...
D'un bout du monde à l'autre, contre tous les dangers, Eleanor et Louis se lancent dans une partie à haut risque dont ils ne maîtrisent pas les règles. Une chose est certaine : ce jeu dans lequel leur redoutable ennemi contrôle tout et tout le monde ne s'arrêtera que lorsque l'un des adversaires sera à terre...

Avis

Un film peut un peu long par moment, mais qui décrit assez fidèlement le fonctionnement de certaines institutions financières. On se doute assez rapidement que le héros ne pourra rien faire contre l'IBBC, mais que l'histoire est plus un prétexte pour amener le spectateur a appréhender ce qu'il est possible de faire avec de pareilles outils financiers. Un film à voir plus pour son coté documentaire que pour l'enquête. Dommage, c'est le titre du film.

lundi 9 mars 2009

Implémentation orienté objet avec Oracle

Introduction

Le language PL/SQL met à la disposition du développeur des procédures et des fonctions ainsi que des packages pour les encapsuler. Les défauts de ce mode de programmation sont identiques à ceux rencontrés avec n'importe quel langage procédural:
  • code spaghetti
  • difficulté de maintenance
Pour palier ces différents problèmes, le paradigme objet a été introduit à travers les types.

Le projet: notifications par mail.

Pour introduire les différents concepts de la programmation orienté objet au langage PL/SQL, nous implémentons un modèle permettant l'envoi de mail avec un contenu de type texte et/ou d'un tableau (formatage automatique des colonnes).

  • CONTENT: Une interface représentant le contenu de la notification,
  • COMPOSITECONTENT: Un contenu composé d'autres contenus (texte, tableau ou composite),
  • TEXTCONTENT: Un contenu textuel pour le corps de l'e-mail,
  • TABCONTENT: Un contenu sous forme de tableau,
  • NOTIF: Une notification par e-mail.

Déclaration d'une classe

Une classe en PL/SQL est décrite comme étant un type. Sa structuration est semblable a celle d'un package PL/SQL, c'est-à-dire qu'il y a une partie concernant la déclaration des méthodes et une seconde partie, appelé le body, qui implémente les méthodes.
Un constructeur par défaut (sans paramètres) est ajouté par le compilateur si la classe n'en définit pas.
Le type NOTIF est définit comme étant un objet en le déclarant: AS OBJECT. Nous verrons par la suite comme définir un objet comme héritant d'un autre objet.

ATTENTION: Une contrainte sur la partie déclaration, celle-ci doit contenir au moins un attribut, que ce soit par héritage ou par déclaration propre.

CREATE TYPE NOTIF AS OBJECT
(
mailhost VARCHAR2(254),
to_address CHARLIST,
from_address VARCHAR2(254),
subject VARCHAR2(254),

MEMBER PROCEDURE send
);
/

CREATE TYPE BODY NOTIF AS

MEMBER PROCEDURE send IS
...
END send;

END;
/
En PL/SQL, il n'est pas possible de définir des méthodes ou des attributs privés ou protégés. Tout ce qui est définit dans un type est accessible dés qu'un objet est été créé.
Il également possible de définir des méthodes statiques, c'est-à-dire des méthodes définis pour le type et indépendante de l'instance d'objet. Pour déclarer une méthode statique, il suffit de remplacer le mot clé MEMBER par STATIC.

Instanciation et appels de méthode

L'instanciation dans un nouvel objet ne se fait pas, contrairement à la plupart des langages orientés objets, par l'appel au mot clé new. Celui-ci n'existe pas en PL/SQL. L'initialisation d'un nouvel objet se fait par l'appel au constructeur, comme s'il s'agissait d'une méthode définit dans un package standard. Dans notre cas, il s'agit du constructeur par défaut qui a été ajouté par le compilateur.

declare
n NOTIF;
begin
n := NOTIF();
....
end;

Pour les appels de méthode, le mécanisme implémenté est le même que dans la plupart des langages objet: la notation pointé.

declare
n NOTIF;
begin
n := NOTIF();
....
n.send;
end;

L'appel d'une méthode statique ne nécessite pas la création d'une instance. Elle peut être appelée de la même façon que pour une méthode contenue dans un package: nom_type.nom_methode(arguments...)

Définition d'un constructeur

Nous allons maintenant définir un constructeur pour le type NOTIF. Celui-ci devra prendre en paramètre un objet de type CONTENT.

CREATE TYPE NOTIF AS OBJECT
(

CONSTRUCTOR FUNCTION NOTIF(c CONTENT) RETURN SELF AS RESULT

);
/

CREATE TYPE BODY NOTIF AS

CONSTRUCTOR FUNCTION NOTIF(c CONTENT) RETURN SELF AS RESULT AS
BEGIN
SELF.notif_content := c;
RETURN;
END NOTIF;

END;
/


Le constructeur définit ci-dessus se présente sous la forme d'une fonction retournant SELF comme résultat. SELF est le mot clé définissant une référence à l'objet courant. La fonction doit également être déclarée comme étant un constructeur par l'utilisation du mot clé CONSTRUCTOR. La fin de la méthode doit être indiqué par le mot clé RETURN. Mais aucun objet ne doit être renvoyé.

REMARQUE: SELF étant une référence à l'objet courant, il peut être utilisé pour lever une ambiguïté. Par exemple, lorsqu'une variable locale a le même nom qu'une variable d'instance.

Définition d'une interface

Autant le dire, les interfaces n'existent pas en PL/SQL, mais il est possible de faire quelque chose qui s'en rapproche.
Dans notre exemple, le type CONTENT représente une interface, c'est-à-dire qu'il doit seulement contenir le prototype des méthodes, ne pas être instanciable et pouvoir être hérité. Puisque nous n'avons pas besoin de définir le corps des fonctions, nous n'avons pas besoin de définir le corps du type (partie BODY).

CREATE TYPE CONTENT AS OBJECT
(
text VARCHAR2(4000),

MEMBER FUNCTION format RETURN LONG
) NOT FINAL NOT INSTANTIABLE;
/

La variable d'instance text a été définit pour respecter la syntaxe du langage: tout type doit avoir au moins un attribut, que ce soit par héritage ou qu'il le définisse lui même.
Par défaut, le PL/SQL n'autorise pas l'héritage d'un type. Pour l'autoriser, il faut rajouter à la fin de la déclaration du type: NOT FINAL.
Par défaut, il est autorisé d'instancier n'importe quel type. Pour empécher l'initialisation d'objets de type CONTENT, il faut ajouter à la fin de la déclaration du type: NOT INSTANCIABLE.

L'héritage et polymorphisme

Nous allons maintenant implémenter le type TEXTCONTENT chargée d'implémenter un texte simple. Ce type hérite de CONTENT:

CREATE TYPE TEXTCONTENT UNDER CONTENT
(
MEMBER PROCEDURE set_content(t VARCHAR2),

OVERRIDING MEMBER FUNCTION format RETURN LONG
);
/

CREATE TYPE BODY TEXTCONTENT AS

MEMBER PROCEDURE set_content(t VARCHAR2) IS
BEGIN
SELF.text := t;
END;

OVERRIDING MEMBER FUNCTION format RETURN LONG IS
BEGIN
RETURN SELF.text || chr(13) || chr(10);
END format;

END;
/
L'héritage est déclaré par le mot clé: UNDER. Pour hériter d'un type, le type courant doit être déclaré:
CREATE TYPE TEXTCONTENT UNDER CONTENT
au lieu de:
AS OBJECT.
Le PL/SQL ne supporte que l'héritage simple.

Pour redéfinir une méthode, celle-ci doit être déclarée avec le mot clé: OVERRIDING.
Il est possible de définir un méthode de façon à ce qu'elle ne puisse être redéfini en ajout le mot clé FINAL devant la définition d'une méthode.

Le partage d'objet

Le PL/SQL implémente le passage de paramètre par copie, c'est-à-dire, qu'à chaque fois qu'une variable est affectée à un objet, celui-ci est copié dans une nouvelle instance. Toutefois, un mécanisme nous permet d'utiliser un passage de paramètre par référence. En utilisant le mot clé REF devant le type de la variable, celle-ci peut alors partager un objet avec une autre variable.
Dans notre exemple, il faut donc ajouter "REF" devant les attributs ayant pour type, ceux du projet de notification.

Conclusion

La programmation objet permet d'organiser son code de manière à ce que celui-ci puisse être plus facilement réutilisable. Alors pourquoi ne pas s'en servir en PL/SQL.
Le modèle objet proposé par le PL/SQL est relativement simple (pas d'héritage multiple, ni d'interface), mais il permet tout de même de résoudre des problèmes complexes avec élégance.

Références

Code Source
Documentation Oracle

samedi 7 mars 2009

Everybody is kung fu fighting

Je viens d'obtenir ma ceinture orange sur le site JavaBlackBelt.
C'est un site, basé sur le principe de communauté, qui propose des tests sur différentes technologies Java et même sur d'autres langages. Le principe est simple:
il y a certains tests a passer pour pouvoir obtenir les ceintures, les couleurs correspondent au nombre de points de connaissances, c'est à dire aux points accumulés en passant les tests avec succès. Pour prétendre à passer un test, il est nécessaire d'avoir un certain nombre de points de participation. Ces points peuvent être obtenus en ajoutant des questions à des tests, ou en modifiant des questions.
Pour faciliter l'intégration des nouveaux venus, il existe un chemin à parcourir, c'est à dire un ensemble de tests prédéfinis, où il n'est pas nécessaire d'avoir des points de participations. Biensûr, il n'y a qu'une dizaine d'examens de disponibles sur ce chemin, mais cela permet d'aller jusqu'à la ceinture verte.

samedi 21 février 2009

De l'utilité des certifications

Personnellement, j'ai trois certifications Java:
  • Java programmer sur JDK 1.4,
  • Web component pour J2EE 1.4,
  • Business component pour J2EE 1.4.
Je me pose la question de l'utilité de les mettre à jour.
Drôle de question lorsque l'on se fi à ce que le site veut nous faire croire: passer une certification vous donnera une justification de votre niveau dans une technologie et ne peut être que bénéfique pour valoriser votre CV.

Mes certifications n'ont jamais eu la moindre influence sur mon parcours, pour preuve, juste après les avoir passées, mon patron m'a assigné à des projets Perl et C++. Et aucune chance de basculer vers des projets Java, j'ai essayé...

Et ce n'est pas plus valorisant pour postuler dans une nouvelle société. A chaque entretien, je soulignais soigneusement mes certifications pour montrer à quel point mon niveau était élevé... Mais les employeurs potentiels ne s'intéressaient qu'aux différents projets sur lesquels j'avai travaillé.

Ma démarche concernant les certification était la suivante: une certification pour appréhender une technologie. Je pense que je m'y suis pris à l'envers.La certification devrait permettre d'entériner une expérience professionnelle: un projet J2EE 5 pendant un an, puis la certification.

Sans savoir faire, la connaissance théorique apportée par la préparation d'une certification n'apporte malheureusement pas grand chose. Je me souviens d'un projet servlet/JSP sur lequel j'ai travaillé après avoir passé la certification web component. Heureusement que j'avais le livre qui m'a servit à la préparer, sinon, le projet aurait difficilement aboutit.

Une autre question: l'expérience ne serait elle pas en faire valoir suffisant? Est il réellement besoin de passer un examen pour valider des connaissances aquises pendant la réalisation de projets?

jeudi 19 février 2009

Adobe Flex 3: Training from the Source de Jeff Trapper, Michael Labriola, Matthew Boles, James Talbot

Ce livre est prétexte à la mise en place d'une application d'e-commerce, ce qui permet de faire le tour des différents aspets de Flex.
J'avais une peur concernant ce livre, c'est qu'il soit centré uniquement sur Flex Builder, l'environement de dévelopement d'Adobe. Dans les premières leçons, l'environement est utilisé de manière intensive, mais on arrive rapidement à mettre les mains dans le MXML et l'ActionScript.
Chaque chapitre est centré sur un théme, qui est expliqué en dehors du contexte de l'application d'e-commerce, avec plusieurs exemples simples. Puis, la leçon est appliquée à l'application, pas à pas. Le code disponible sur le CD permet de reprendre une leçon au début ou, suivant sa longueur, au milieu de celle-ci.
Une bonne surprise est que des rudiments de la plateforme AIR font l'objet d'un chapitre.
Seul regret, concernant la partie communication avec le serveur, aprés l'annonce tonitruante en 2007 à Javapolis, de la disponibilité de Flex 3 et de ses formidables possibilités d'intégrations avec Java, que le backend fournit soit basé sur ColdFusion. J'aurais également voulu abordé la communication avec le serveur un peu plus tôt.
Globalement un bon livre, à ranger dans les livres de référence sur le sujet.

mercredi 28 janvier 2009

Java EE 5 2e édition par Antonio Goncalves

Un bon livre d'initiation aux spécifications J2EE. Il couvre les principaux sujets auxquels on pouvait s'attendre. Le bémol vient des trois premiers chapitres qui portent sur la description de l'application sur laquelle est basé l'ouvrage et sur l'environnement de développement.
L'application est le traditionnel magasin d'animaux en ligne. L'auteur précise qu'il utilise cette application parce qu'elle fait parti d'un blue print de Sun et non par commodité. On lui pardonnera donc d'utiliser cet exemple "bateau".
Ce que j'ai également beaucoup apprécié est la description de JAXB comme étant une des pièces maitresse des web service.
Je recommande ce livre à tous ceux qui veulent avoir une overview de la spécification J2EE. Sans permettre de construire une application compléte, cet ouvrage forunit un quick start sur un grand nombre des technologies Java.

mardi 25 novembre 2008

Injection d'une DataSource dans un contexte Spring

Cet article a pour but de décrire comment injecter une datasource dans un contexte Spring existant et surtout de décrire les solutions que j'ai envisagé.

La problématique

Dans le cadre du développement d'une API devant interroger une base puis traiter ces données, les contraintes techniques suivantes sont apparues :
  • une seule classe doit servir de façade pour utiliser l'API,
  • celle-ci doit prendre une DataSource définit par le client,
  • la partie cliente ne doit pas avoir connaissance du contexte Spring de l'API.
Sachant que la partie cliente est dépendante du framework Spring, son utilisation dans ce cas de figure semblait naturel. Ainsi, la partie ORM du framework permet de coder plus rapidement les accès à la base et le fichier de contexte permet de résoudre les problèmes d'injection de dépendance, de transaction et permet d'éviter l'écriture de fabriques.
Les beans d'accès aux données ainsi que les beans gérant les transactions ont besoin d'une DataSource pour pouvoir fonctionner.
Comment faire pour créer le bean d'entrée de la librairie, donc charger le contexte, sans qu'une exception soit lancé par Spring? Comment faire pour que Spring s'occupe de l'injection de la DataSource alors que celle-ci n'est connu qu'au moment d'utiliser la librairie?

Quelques solutions

Injecter manuellement la DataSource

L'idée ici est de créer le bean façade de l'API, d'y injecter les dépendances et d'injecter manuellement la DataSource.
Cette solution oblige le développeur à connaitre le nom des beans dépendants de la DataSource. Toute modification du contexte implique alors d'intervenir dans le code.

Injection de la DataSource par Spring

Cette fois ci, il s'agit de laisser Spring injecter la DataSource dans les beans.

La méthode d'initialisation du bean:

public void init(DriverManagerDataSource driverDataSource) throws EngineException {
// premièrement, création d'un contexte parent
ConfigurableApplicationContext genericContext = new GenericApplicationContext();
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) genericContext.getBeanFactory();

// création du bean datasource et injection de ses propriétés
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(DriverManagerDataSource.class); beanDefinitionBuilder.addPropertyValue("url", driverDataSource.getUrl());
beanDefinitionBuilder.addPropertyValue("password", driverDataSource.getPassword());
beanDefinitionBuilder.addPropertyValue("username", driverDataSource.getUsername());
beanDefinitionBuilder.addPropertyValue("driverClassName", "oracle.jdbc.OracleDriver");

// enregistrement du bean dans le contexte parent
beanFactory.registerBeanDefinition("parentDataSource", beanDefinitionBuilder.getBeanDefinition());
genericContext.refresh();

// création du contexte de l'API comme contexte enfant
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "engine-context.xml", "service-context.xml", "dao-context.xml" }, true, genericContext);

// déclare le bean courant comme autowired
context.getAutowireCapableBeanFactory().autowireBeanProperties(this,AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false);

// initialise le bean courant en y injectant les beans
context.getAutowireCapableBeanFactory().initializeBean(this,"modeDataEngine");
}

Contexte Spring

La ligne suivante définit une dataSource dans le contexte de l'API.

<bean id="datasource" parent="parentDataSource">


Quelques remarques

La datasource utilisée est une DriverManagerDataSource fournie par le framework Spring. Pourquoi est-ce la seule utilisable?
Pour définir une datasource dans un contexte, nous avons besoin de lui fournir plusieurs données pour s'initialiser:
  • l'URL de connexion,
  • la classe du driver JDBC,
  • le nom d'utilisateur,
  • Le mot de passe.
Le DrvierManagerDataSource est une classe qui permet d'obtenir ces informations en utilisant de simples setter, ce qu'un grand nombre d'implémentation de l'interface DataSource ne font pas.
L'objectif est de proposer une API, ce qui implique qu'elle ne doit prendre en entrée, pour rester flexible, que des interfaces ou des classes définies par l'API elle-même.

Utilisation d'une factory

Une autre solution consiste à créer une factory de DataSource.
L'idée est de fournir une dataSource, n'importe quelle implémentation, à la méthode d'initialisation de l'API, qui ensuite, chargera le contexte Spring. Dans ce contexte, une factory doit être définit. Elle doit définir une méthode d'initialisation, qui ira chercher la dataSource dans l'instance de l'API, puis la fournira aux autres beans.

Contexte Spring

<bean id="dataSourceFactory" class="DataSourceFactory" method="init">

<bean id="dataSource" bean="dataSourceFactory" method="getDataSource">