samedi 27 avril 2013

Hibernate

Hibernate

La description d'un ORM peut sans doute paraître éloignée des statistiques et pourtant, cette technologie est au coeur d'un projet statistique que je suis en train de développer. Au vu de l'aspect critique de la persistance des données dans un projet de capture de donnée à des fins d'analyse statistique, je pense qu'il n'est pas inutile d'exposer dans ce blog le résultat d'essais, le résumé de lectures, ... concernant la technologie Hibernate. L'ouvrage de référence que j'utilise ici, outre les divers billet du blog de mkyong, est Java Persistence with Hibernate de Christian Bauer et Gavin King (maning's publication). La plupart des références au modèle ou encore les extraits de codes proviennent du projet SNT, qui un petit outil de capture de données spécifiques aux tablettes et smartphone, en vue d'analyse statistique avec R.

Object Relational Mapping (ORM)
Les points présentés ici sont un ensemble de problème pouvant apparaître lors du mapping objet/table et des points sur lesquels l'utilisation d'un ORM peut s'avérer très intéressante.

granularité

SQL permet de définir ses propres type de données suivant le RDMS choisi. Par exemple on peut utiliser un String pour stocker une adresse mais on pourrait définir une structure de données
1:  class address {  
2:    String street;  
3:    String zip;  
4:    Long number;  
5:  }  
Une façon brute de mapper cela dans une base de donnée consiste à créer une table pour adresse, ce qui est assez lourd...
Toutefois, ce type de structure (anciennement appelé Record en Pascal, ou struct en C) nécessiteront une définition SQL très différentes d'un SQL à l'autre. L'utilisation d'un ORM est très intéressante pour uniformiser ce genre de problème.

identité et égalité

L'identité de deux objets au sens de Java est qu'ils partagent la même addresse:
1:  String a = "my string";  
2:  String b = a;  
3:  if (a==b) System.out.println("identiques"); else System.out.println("pas identiques");  

a et b sont identiques car ils référencent tous deux un seul et même objet.

1:  String a= "my string";  
2:  String b= "my string";  
3:  if (a.equals(b)) System.out.println("égaux"); else System.out.println("pas égaux");  

Lorsque l'on utilise des equals, il est très important de définir correctement les fonctions hashCode et equals en cas de modification de classe, heureusement, l'environnement eclipse permet de les générer automatiquement. Notez que cette remarque est tout aussi valable lorsque l'on utilise des Set en java (liste ne contenant que des éléments différents, la non équivalence se calcule grâce à la fonction equals des objets contenus dans la liste).

Au niveau base de donnée l'identité se fait via la clé primaire (et pour éviter tout ennui on utilisera plutôt une surrogate key, plutôt qu'une natural key)

Ce qui signifie que lors de l'exécution d'un programme java, on peut avoir des tas de références non identiques sur des objets ayant une même clé primaire et donc identique en DB. Cette gestion peut parfois s'avérer problématique.

associations
Association en programmation orientée objet = référence.
La navigation d'une association en programmation orientée objet peut-être unidirectionnelle ou bidirectionnelle.
Unidirectionnelle : A partir d'un TreeNode on ne peut naviguer que dans ces childs
1:  class TreeNode {  
2:   protected List childList=null;  
3:  ...  
4:  }  
Bidirecionnelle:
1:  class TreeNode {  
2:    protected List childList =null;  
3:    protected TreeNode parent = null;  
4:  ...  
5:  }  
Dans ce cas de figure, on peut remonter.

En base de donnée = contrainte de type foreign key sur une colonne qui assure l'intégrité, cette colonne ne peut exister si la clé primaire associée n'existe pas.

La navigation uni ou bidirectionnelle n'a pas de sens dans les bases de données relationnelles, on peut parcourir le graphe des entités comme on veut.

Relations many-to-many:
Typiquement lorsqu'une entité A peut avoir n entités B associées et que chaque entité B peut avoir m entité A associées. En base de données relationnelle, on passe par une table de lien, dans un modèle objet on ne voit pas cette table.
1:  class A {  
2:   Set bList;  
3:  }  
4:  class B {  
5:   Set aList;  
6:  }  
héritage
une base de donnée ne connaît que l'association  "has a", l'association "is a", propre au concept de programmation orientée objet n'est pas reconnue par les bases de données relationnelles.
Cette problématique quant à elle à déjà été soulevée dans un précédent billet.

n+1 selects problem
lorsque l'on accède des objets en java on le fait de cette façon:
objet1.objet2.objet3 ...
Le problème est que cela va générer un grand nombre de queries dans la base de données et massacrer les performances de l'application.
Là aussi les ORM peuvent apporter pas mal d'optimisations et améliorations de performances.

vendredi 29 mars 2013

MVC dans un form Master-Detail


Ce billet fait suite au billet posté sur MVC le 4 Janvier 2011

MVC est un design pattern relativement vieux, mais il faut reconnaître qu’il a été remis au goût du jour depuis quelques années déjà et ce en particulier grâce ou à cause de Java.
Dans ce billet je vais m’intéresser à : 
-A)          Pertinence de MVC
Un des problèmes majeurs du développement est que les possibilités de résoudre un problème sont généralement multiples.  Souvent a priori, il n’y a pas de bonne ou de mauvaise méthode, les dev se laissent aller à leur habitudes, leurs logiques propre (parfois très différentes d’un dev à l’autre, en fonction de leur expérience). Il est souvent difficile lorsque l’on s’attaque à un problème non connu de trouver la solution ou la stratégie qui sera la plus payante, sur le court ou sur le long terme. Souvent on se laisse aller à son bon sens, ce qui peut parfois être payant à court terme mais décevant sur le long terme ou pire, inutilisable lorsque le système grossit. Heureusement, nombre de développeurs et d’architectes ont formalisé leur expérience, leur stratégie applicable sur des problèmes concret de développement. Ce formalisme définit les design patterns.  L’un des avantages de MVC est qu’il est lui-même un design pattern s’appuyant sur le pattern Observer (View)-Subject (Model). Remarque que java.util définit aussi la notion d’observer : Observable (Model) – Observer(View) - Listener (Controller). 
Dans ce cas précis nous allons nous intéresser à la manière de modéliser les réponses d’un utilisateur à une interface graphique servant de vue et d’entrée sur les données contenues dans une base.

Un problème auquel tout développeur, qui se respecte,  a été confronté au moins une fois dans sa vie.
Dans le courant des années nonante et même plus tard, les IDE graphique permettait d’associer aux contrôles (widgets) d’une fenêtre, un code de réponse à un évènement. Ce formalisme, bien connu des utilisateurs VB, Delphi, .. est souvent connu sous le nom de programmation Event Driven.

Le  problème de cette approche est le couplage fort entre l’interface et le contrôle de flux. En effet, tant que le contrôle de flux ne dépend que d’une fenêtre cette approche fonctionne plus ou moins bien.
Toutefois, quand le contrôle de flux impacte plusieurs fenêtres, lorsque l’on veut, par exemple, répercuter les modifications provoquées par l'action sur une fenêtre dans les autres, on est souvent amené à faire des bidouilles de programmation pas très propres (euphémisme pour ne pas dire dégueulasses) qui au final transforme le code de contrôle des interfaces en magnifique spaghetti peu appétissant.

B)       L’approche MVC (pattern observer)
      Définition : Model View Controller.

Pour faire simple le controlleur répond aux évènements activés dans les vues, en réponse à cela il modifie le status du modèle, celui-ci répercute les changements sur les vues.

Avantage : Contrôle de flux est indépendant des vues,  ajouter de nouvelles vues n’impacte pas toujours  le contrôle de flux. Les vues ne se connaissent pas entre elles, ce qui évite des couplages entre vues et entre code de contrôle.  Le modèle n’update les vues que lorsqu’il a été modifié par le controlleur.

D'un point de vue design pattern, le model contient donc un pattern observer, au sens Java, il est un observable, tandisque la vue est un observer. On peut résumer cela par le formalisme UML.

Diagramme de Classe:
- La responsabilité de la vue est l'affichage du modèle et la capture des évènements liés à la vue (clic de souris, clavier, ...)
- La responsabilité du contrôleur est de répondre aux évènements engendrés dans la vue.
- La responsabilité du modèle est double d'une part récupérer et gérer les données en provenance d'une source de donnée (une DB par exemple) ET notifier les vues d'un changement d'état:

Diagramme de Sequence


Ce diagramme donne les séquences de création par rapport à l'application. On crée le contrôleur, puis le modèle, puis les vues en leur passant une référence sur le contrôleur qui contient le code de gestion des événements, ensuite on appelle la fonction registerObserver du modèle pour assigner une nouvelle vue.

Lorsqu'un utilisateur effectue une action sur la vue, l'applic envoit un évènement, la réponse à cet évènement se fait dans le contrôleur qui va modifier l'état du modèle, la modification de l'état du modèle va obliger celui-ci à notifier les vues qui l'observent de son changement d'état. Ainsi quelques soit la modification effectuée dans une vue, cette modification, si elle a changé l'état du modèle se répercutera dans toutes les autres.

Traduisons cela en Java et pour se faire choisissons un exemple, tout d'abord une vue contenant une liste de studyInf contenue dans un JList.
La seconde vue contiendra la description des champs du studyInf ainsi qu'une liste de boutons permettant, la sauvegarrde, ou le passage à l'élément suivant ou précédent, il est à noter que les évènements du JList impacteront la vue contenant le descriptif et les boutons.

1. Crée les modèles:
dans ce cas nous avons besoin de deux modèles : StudyInf et StudyInfListModel

StudyInf : est le plus simple puisqu'il contiendra les données provenant de la DB. Remarquez que dans ce tutorial nous n'allons pas nous étendre trop loin sur la manière de récupérer les données DB.... Le mieux est de créer un service se chargeant de l'accès à la base de donnée et qui renverra un modèle ou une liste de modèles... Cela pourrait faire l'objet d'un autre billet... ou pas.


public class StudyInf {
protected String signalAction,
signalDescription,
assignment;
protected Long studyId;
protected int
protocolStatus,
signalStatus,
timeDimId;
protected float sizeN,
totalImbalance;
protected String protocolId,
protocolName;
...
// add getter/setter
}

Il s'agit d'une simple classe POJO. Intéressons nous maintenant à la classe StudyInfListModel qui sera utilisée par l'objet JList et par qui toutes les actions de rafraîchissements transiteront.


public class StudyInfListModel extends DefaultListModel {

/**

*
*/
private static final long serialVersionUID = -1561852405765263848L;
private static class MyObservable extends Observable {
@Override
public void setChanged() {
super.setChanged();
}

}

// embed the Observable (java does not support multiple inheritance)
public MyObservable observable;
public StudyInfListModel() {
super();
this.observable = new MyObservable();
}

public void addObserver(Observer observer) {

this.observable.addObserver(observer);
}

public void notifyObservers(Object object) {

this.observable.setChanged();
this.observable.notifyObservers(object);
}
}


Comme on le voit, la classe hérite de DefaultListModel, ce qui est obligatoire si on veut l'utiliser comme modèle pour un JList.. Comme Java ne supporte pas l'héritage multiple, on va simplement incorporer un Observable dans cette classe Model. Et on va ajouter les méthodes utiles à un Observable : 
- addObserver et notifyObserver(). Il faut noter qu'avant d'appeler notifyObserver il faut appeler la méthode setChanged(); Sinon l'appel ne se fait pas, si le modèle n'est pas passé à l'état changé.

Comme cette méthode est définie comme protected dans Observable, elle n'est donc pas directement accessible par notre classe wrapper. Pour pâlier à cela on va créer la classe interne : MyObserver qui va exposer publiquement la méthode setChanged(); Comme vous le savez une méthode protected peut être appelée par la classe fille, et celle-ci peut donc mettre le membre appelant public...

2.) Créer le contrôleur

Voici une partie du code de notre contrôleur:


public class StudyInfController implements ActionListener,
ListSelectionListener {
protected List studyInfList;
protected StudyInfListModel studyInfListModel;
public void initializeStudyInfModel() {
       //TODO add the code here
      //....
}

public StudyInfController(StudyInfDao studyInfDao,
StudyInfListModel studyInfListModel) {
this.studyInfListModel = studyInfListModel;

initializeStudyInfModel();

}


public void actionPerformed(ActionEvent e) {
StudyInf studyInf;
if (e.getSource() instanceof Component) {
Component source = (Component) e.getSource();
if (source.getName().equals("btCommit")) {
                             // TODO add the code here}
                            // ...
}

public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
try {
// Retrieve the selected item.
StudyInf studyInf = (StudyInf) this.getModel().getSelected();
this.getModel().notifyObservers(studyInf);
} catch (Exception ex) {
}
}
}
}


Comme déjà expliqué le rôle de contrôleur est de répondre aux évènements générés par les vues et d'adapter le modèle en conséquence. C'est pourquoi la classe implémente deux interfaces : SelectionListener pour la JList et ActionListener pour les boutons.
Tout d'abord le constructeur va charger les données utiles à l'initialization du modèle. C'est durant la construction du controlleur que le modèle studyInfListModel sera chargé avec les données provenant de la DB.
Comme vous l'aurez remarqué les fonctions actionPerformed() et selectionChanged() ne font jamais directement un appel explicite à la vue étant donné que si les vues connaisssent le contrôleur celui-ci ne les connais pas. La plupart des actions se feront au travers du modèle qui lui impactera ses vue (notifyObservers()). Dans actionPerformed() les tests sur les contrôles cliqués se feront au moyen du nom de ceux-ci.

if (source.getName().equals("btCommit")) {...
}

Remarquez aussi que le modèle est passé en paramètre au contrôleur.

3.) Les vues:
D'une manière générale, nos vues ne sont rien d'autre que des JPanel.

3.1) La listview:
La première vue définie ici s'occuppe d'afficher la liste des studyInf et de permettre à l'utilisateur de les sélectionner.

public class StudyInfListView extends JScrollPane implements Observer {
private static final long serialVersionUID = 1L;
JList list;
public StudyInfListView(StudyInfController controller) {
super();

this.list =new JList(controller.getModel());
this.setViewportView(this.list);
controller.getModel().setListContainer(this.list);
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.addListSelectionListener(controller);
list.setFont(new Font("Courier",Font.BOLD, 12));

}
public void update(Observable observable, Object arg1) {

this.list.revalidate();
}
}

Comme déjà expliqué, la vue va implémenter une interface Observer qui va nous fournir la fonction update, qui sera automatiquement appelée par le modèle.
La vue est constituée d'un ScrollPane qui va nous servir de pattern decorator sur la JList afin de lui ajouter des scrollbars.

On va ensuite créer la JList en utilisant le modèle contenu dans le contrôleur, en effet la vue peut contenir une référence sur le contrôleur (notamment dans le but de l'assigner comme classe de réponse aux évènements reçu par ses composants). Comme par exemple pour la vue représentant le modèle:


btCommit.addActionListener(controller);
btClose.addActionListener(controller);
btNext.addActionListener(controller);
btPrev.addActionListener(controller);

Remarquez l'utilisation de "revalidate()" pour réafficher la fenêtre updatée.


4) L'application:
C'est là que l'on va gérer la création des entités MVC et lier le tout ensemble:

   StudyInfListModel listInfModel = new StudyInfListModel();

    this.studyInfController=new StudyInfController(listInfModel);

    JPanel panelEdt = new JPanel();
        panelEdt.setLayout(new BorderLayout());

     StudyInfListView panelEdtTop = new StudyInfListView(  studyInfController);

    panelEdtTop.setPreferredSize(new Dimension(640,240));
      listInfModel.addObserver(panelEdtTop);


On crée le modèle
On crée le contrôleur auquel on passe le modèle.
On crée le panel principal en border Layout (Center contiendra la liste et South les composants text edit, label, combo ainsi que les boutons).
On crée la première vue "StudyInfListView" et on lui passe le contrôleur en paramètre. 
On informe le modèle qu'une vue est prête à l'observer : addObserver()

On fait de même avec la seconde vue et puis on active le tout:

  listInfModel.notifyObservers(null);

      panelEdt.add(panelEdtTop, BorderLayout.CENTER);
      panelEdt.add(panelEdtBottom, BorderLayout.SOUTH);

      this.getContentPane().add(panelEdt);

    this.pack();

D'abord on demande au modèle de rafrâichir ses vues fraîchement crées, puis on place les deux vues dans le panneau principal que l'on attache au JFrame de l'application (getContentPane) et puis on fait un pack.


 Une fois ceci fait l'application devrait créer les vues sur les modèles et permettre à l'utilisateur d'influer sur l'état des modèles aux moyens des contrôles placés sur les vues...

Voilà, l'exemple donné ici, n'est pas fonctionnel tel quel mais le but est de donner une idée, un cannevas permettant d'implémenter du MVC dans Swing.



mardi 26 mars 2013

Les stratégies de mapping d’héritage en hibernate

Tableau récapitulatif:

Il n’y a pas une stratégie meilleure qu’une autre, il y a des stratégies meilleures en fonction des situations.
Dans un cas GCP compliance, on peut se permettre de sacrifier quelque peu les performances en faveur de l’intégrité des données. J’opterai donc plus pour une stratégie : JOINED.
Hibernate n’est pas ce qu’il y a d’idéal pour du reporting ou encore de l’ETL, là il est toujours possible d’utiliser une solution annexe comme des vues, directement attaquées par du SQL natif. Evidemment, ça ne permet plus à l’application d’être DBAgnostique mais cela permet de régler des problèmes de performances.
La dernière approche serait évidemment la création d’une base de données OLAP dans laquelle on chargerait les données en vue du reporting.

Référence :


mercredi 20 mars 2013

EDC Challenges



Se dire que l'on peut transformer en cinq minutes une applic EDC standard (laptop) en une applic EDC mobile est à mon sens aller un peu vite en besogne.

D'une part les framework mobile et web classic sont généralement assez différents (jQuery vs jQuery mobile, ExtJS vs Sencha Touch).
D'une part, vu les limitations physiques des BYOD, il est généralement intéressant de proposer une solution spécifique pour mobile.
D'autre part, même si les concepts de base restent les même, les API changent tout de même sensiblement ce qui a des impacts sur le développement , la validation et la maintenance.
Une idée intéressante est la conception d'une application web utilisable par les BYOD mais là il faut se méfier de la stabilité des liaisons 3G et des pertes de connexions éventuelles.

Les BYOD deviennent communément répandus, toutefois un certain nombre de problème persiste quant à la stabilité des connexion. Une perte de connexion peut facilement signifier perte de donnée. Dans certains hopitaux les accès wifi sont coupés (BYOD sont inactifs), vu les trous de sécurité présent dans les BYOD, je ne serais pas étonné que certaines organization banissent purement et simplement, pour l'instant, ce genre d'équippement de leurs réseaux.
Il serait intéressant de pouvoir travailler sur une solution hybride (mixant du online et du offline).

L'un des challenge (outre la réplication correcte des données) pour un système offline est la validation des données. (Gardons en tête que la plupart des EDC travaille par query, chaque query à un coût parfois 100$). La validation des données permet de limiter le nombre de query.

Développer un tel système poserait toutefois des question par rapprt à DataSci patent mais cela implique des contraintes techniques non négligeables (gestion des transactions longues, réplications, ...). Ceci, doit être pris en compte dès le début et peut sensiblement allonger les temps de développement.

D'un autre côté voyons aussi ce que l'avenir réserve :
  • l'amélioration au niveau sécurité
  • la généralisation de la 4G qui rendra l'utilisation de BYOD aussi fiable qu'une connexion WiFi classique.
Perdre du temps à développer un système offline/online qui sera absolète dans deux ans n'est pas très intéressant non plus.

ICH E6 GCP

Les GCP (Good Clinical Practices) couvertes par l'ICH (International Conference on Harmonization) prennent une place prépondérantes dans la conduite d'essais cliniques mais aussi dans la manière dont on doit concevoir des applications liées au domaine clinique.

Bon nombre de ces GCP sont reprises dans les guidelines ICH E6 (E pour efficacy). En ce qui nous concerne il faudra retenir qu'une application clinique doit obéir à 6 règles fondamentales:

- Validation : Le système doit être validé suivant un processus qualité bien règlementé.
- SOPs : Les standard operation procedures sont les procédures permettant d'assurer la validation de l'application.
- Maintenir un Audit trail sur les données sensibles (cfr CDISC)
- Securité (HTTPS, authentication et autorisation)
- Backup régulier (un private cloud peut-etre une solution intéressante)
- Maintient du blinding : selon les règles GCP on ne peut jamais savoir ce qu'un patient a reçu comme traitement (control / actif). Cela signifie aussi que l'on ne peut pas prédire ce qu'un nouveau sujet entrant dans l'étude va recevoir.

vendredi 24 août 2012

Clarification sur le Datawarehousing


Depuis quelques temps déjà on nous parle de plus en plus de datawarehouse (c'est un assez vieux concept qui semble revenir à la mode) et d’un terme que je trouve un peu pompeux le BI. Etant obligé par mon travail à replonger dans cet univers (mauvais jeu de mot ?), voici un petit billet concernant quelques cogitations à ce sujet…

OLTP et OLAP

OLTP : online transaction process : il s’agit là des base de données bien connu et bien classique (RDMS, entendez relational database management system). Le but de ces bases de données est de stocker des données utilisateurs via des applications clientes. Les paramètres importants sont :
1        1)Transactionnel (toujours se retrouver dans un état cohérent, même si le système crash)
2          2)Intégrité de donnée (clé primaire, foreign key, contrainte)
3          3)Index
4          4)Gestion d’accès concurrent (cfr transaction : Atomicity, Consistency, Isolation, Durability)
L’accent est mis sur la rapidité d’accès aux données et l’intégrité de celle-ci. Idéalement, de mon point de vue, une base de donnée OLTP ne devrait même pas être utilisée pour du reporting (sauf reporting bête et méchant).  Un chirurgien doit attendre d’opérer un patient, car il ne peut accéder aux informations du patient parce que le système est bloqué par quelqu’un générant un rapport trop lourd. Ces types de situations sont évidemment inacceptables.
Pour optimiser et réduire la redondance des informations, on utilise abusivement des formes normales.
Dans certains cas on utilise des ORM (iBATIS, Hibernate…) pour construire la structure du RDMS et assurer un mapping cohérent entre l’architecture objet et sa persistance transactionnelle.

OLAP : online analytical process
Ces bases de données sont dédiées au reporting, voir au reporting sur plusieurs dimensions. Dans cec cas de figure aucun souci par rapport au performance, puisque les deux bases de données sont séparées physiquement.
La structure des tables n’a plus rien à voir avec une base de donnée classique puisque la plupart des tables sont dé-normalisées. L’accès en écriture se fait en général via un processus d’ETL (Export, Transform, Load).
Pratiquement on utilise une table de fait représentant des comptes  en fonction de différentes dimensions. (Axe d’analyse), il s’agit de la table centrale. Les  dimensions sont des variables catégorielles independantes. L’ensemble des dimension forment un espace appelé Univers. La table centrale contient une foreign key pour chaque dimension (on appelle cette modélisation, modélisation en étoile, c’est une des plus simples). On peut aussi décomposer les dimensions suivant leur hiérarchies et définir des sous tables par dimension et niveau hiérarchique (architecture en flocon de neige). On peut aussi faire un mix des deux…
D’un point de vue pratique, même si des clés primaires peuvent être définies conceptuellement, aucune contrainte n’est mise sur la DB et l’autocommit est aussi désactivé puisque la DB fonctionne en read only.
Une fois les dimensions clairement établies, celles-ci peuvent être lues via certains outils de BI (Pentaho, offre quelque bon exemple open source, ceci dit il est aussi possible de faire du BI avec Excel).
Avant de se lancer dans la conception du système, il est important de se figurer les rapports dont on a besoin et les axes suivant lesquels on voudrait naviguer dans les données. Il faut veiller que ses axes soient indépendants (ou alors les regrouper sous forme hiérarchique). On définit ensuite la hiérarchie, puis on modélise.
La partie tricky à mon sens est la partie ETL car si quelque chose foire là-dedans, cela peut très vite devenir problématique. D’une part, les données peuvent venir d’une foulée de systèmes différents, donc on a besoin de réconciliation et de consolidation (remettre les bons ID), d’autre part si la réconciliation se passe mal, ce sont tous les résultats qui peuvent être impacté. C’est pourquoi il est important d’une part de travailler dans une sandbox, et d’autre part de bien dater les modifications.
Une fois les données prêtes (dans mon cas via des scripts PERL), il faut ensuite faire un bulk-copy dans la base de donnée OLAP. Comme cette DB est read-only, la seule phase d’écriture se fait au moment du chargement (LOAD), en général on utilise un bulk-copy (bcp) ou COPY en Postgres.
Les bases de données OLAP sont souvent qualifiées de Datawarehouse, en général le domaine qui nous occupe s’appelle un datamart (partie d’un datawarehouse), si le domaine concerné impacte le business par rapport à ses ventes on parle alors de BI (Business intelligence). Dans ce cas les dimensions sont souvents:la géographie (Région/Pays/Ville), le temps(Year/Quarter/Month), les types de produits. La table de fait est en général le total des ventes en fonctions des dimensions précitées.
Plusieurs systèmes peuvent être utilisés pour créer une base de donnée OLAP : SAS, SQL-Server, ORACLE ou dans les gratuits : R et PostgreSQL. Il en existe bien sûr d’autres mais ce sont ceuxt là que je connais le mieux…

mardi 26 juin 2012

Exercice 1.C


référence :
http://static.springsource.org/spring-ws/sites/1.5/reference/html/tutorial.html

Web Service :
Contract Last : on écrit d'abord le code Java et sur base de cela on génère le contrat après (WSDL)
Contract First : On écrit d'abord le contrat (WSDL) et on génère du Java à partir de là.

Rappel sur les dates :
ISO 8601 format : yyyy-mm-dd

D'une manière générale le XSD deviendra le Data Contract (qui définira le payload) :
Voir le rappel sur les XSD et le XSD final généré :

Une fois le data contract terminé on passe au Service Contract : Le WSDL
En général Spring WS sait générer le WSDL pour nous automatiquement

WSDL abstract parts : (doc xml utilisé pour localiser et décrire des webservices)
  1. definitions :<definitions>
    - namespaces
    - types <wsdl:types><xsd:schema xmlns>
    data type definition : décrits les types des paramètres impliqués dans le message
    </xsd:schema></wsdl:types>
  2. on définit le message : <wdsl:message>
    xsd décrivant la forme du message (data contract). Un peu comme les paramètres d'une fonction
    </wsdl:message>
  3. On décrit un porttype :
    <portType>
    décrit les opérations et les message impliqués
    </portType>
  4. Binding : on associe le message à un port type comme opération (le porttype sera utilisé dans le binding)
    <binding>
    protocoles et format de données
    </binding>
    </definitions>

Exemple : portType
<message name= »getTermRequest »>
<part name= »term » type= »xs:string » />
</message>
<portType name= »gloassaryTerms » />
<operation name= »getTerm »>
<input message= »getTermRequest » />
<output message= »getTermResponse » />
</operation>
</portType>
Dans ce cas de figure glossaryTerms peut être comparé à une librairie de fonction (ou classe?)
En gros le portType se comporte comme une classe accessible via le web.
Request-response est le mode de fonctionnement le plus commun.
Les autres types sont:
  • One-way : pas de réponse attendue (uniquement input est défini
  • Request-response : web request classique (stateless) : input / output
  • Solicit-response : l'appli va attendre la réponse (statefull?)
  • Notification : le serveur envoie un message mais n'attend pas de réponse

Le binding :
deux attributs :
  • name : nom du binding
  • type : pointe sur le port (une instance de porttype)

Le binding contient l'élément : soap:binding (style et transport)
  • style : rpc/document
  • transport : HTTP (mais pourrait-être autre chose : JMS)
Rmk on ne définit pas transport comme étant HTTP mais :

Le soapbinding contient l'élément opération :
définir l'opération que le portType expose
c'est là que l'on définit les requêtes http qui permettrond l'appel ex :
Il faut aussi spécifier les types d'entrées sortie : ex:literal


WSDL concrete part
on effectue un
  • binding qui indique au client comment invoker l'opération
  • service qui dit au client où la trouver (le binding sera utilise dans le port du service)

Voir le tutoriel pour explications complémentaires :

On crée le projet via Maven2
mvn archetype:create -DarchetypeGroupId=org.springframework.ws -DarchetypeArtifactID=spring-ws-archetype -DarchetypeVersion=1.5.9 -DgroupId=be.sdlg.ws -DartifactId=anovaWS

On obtien un répertoire src/main/webapp
Le servlet spring-ws est automatiquement crée et les requêtes redirigés vers lui.

3.6 Implementing the endpoint
Remarque sur les documents XML

Mieux vaut utiliser un name space lorsque l'on déclare un élément :
<ELEMENT xmlns= « http://www.sdlg.be/web/myapp/schemas »>
</ELEMENT>

Utliser plutôt
AnovaRequest (éviter les – car conversion vers Java class)