Rechercher sur arkzoyd.com

28 septembre 2006

Listeners et connexions à une base Oracle /*+B.A-BA*/

Vous êtes de plus en plus à lire mon blog... malheureusement, vous êtes également de plus en plus nombreux à ne pas y trouver ce que vous cherchez. C'est l'effet Google !

Pour répondre à beaucoup de questions, je vais toucher un mot du listener et des connexions à une base de données. Ce qui suit n'est qu'une rapide introduction et je vous renvoie au "Net Service Guide - Oracle 10.2", disponible dans la documentation Oracle à la page suivante : http://www.oracle.com/pls/db102/portal.portal_db?selected=4. Metalink est également une très bonne source d'information à ce sujet.

Adressage et connexions
Pour vous connecter à une base de données Oracle (Il s'agit d'un abus de langage), il vous faut d'abord une adresse... Ceci que vous y accédiez via un serveur d'applications, du Cobol, du .Net ou même SQL*Plus. Pour faire tout de suite compliqué, il faut dire qu'Oracle accepte de nombreuses formes d'adressage, par exemple :
  • "Rien" est une forme d'adressage ! Dans le cas où vous ne tapez rien comme adresse, la couche cliente va considérer que vous vous connectez à l'instance par défaut et va chercher un certain nombre de variables pour résoudre votre connexion. La plus généralement utilisée est ORACLE_SID. Si cette variable est positionnée, votre couche client va vous connecter à l'instance locale dont le nom est défini par la valeur de la variable. Cette méthode est peu souple puisque vous devez être sur le serveur de base de données. Elle ne nécessite pas que vous utilisiez un agent de connexion, comme un Listener et est donc souvent utilisée par les DBA. Par exemple, dans une Console Windows, vous taperez quelque chose comme :
    set ORACLE_SID=orcl
    sqlplus scott/tiger
    Sous réserve que votre instance Oracle s'appelle "orcl", qu'elle tourne sur la machine locale et que vous ayez un utilisateur "scott" activé dans la base de données dont le mot de passe est "tiger". Le script utlsampl.sql dans le répertoire ORACLE_HOME/rdbms/admin permet de créer l'utilisateur scott.
  • "Rien" peut être une autre forme d'adressage si les variables TWO_TASK (Unix & Linux) ou que la clé de registre LOCAL (Windows) sont positionnées. Cette méthode est moins utilisée. Toutefois elle permet de stocker une chaîne d'adressage réseau et que l'utilisateur n'ait rien à taper pour se connecter
  • Avec 10g, une connexion "EZConnect" peut être utilisée (prononcez "Easy Connect" ou si vous ne parlez pas anglais, ce dont je doute : "Izi connecte"). Cette chaîne d'adressage a la forme suivante : "//machine:port/service". Elle ne marche qu'avec les clients 10g et nécessite que le client connaisse l'alias de la machine et le port sur laquelle le listener (voir section suivante) est démarré ainsi que le nom de service utilisé pour la connexion. Elle est cependant très simple à utiliser et surtout ne nécessite aucune configuration sur le client. Cette méthode étant nouvelle n'est pas très répandue mais elle est très simple et évite donc plein d'erreurs. Par exemple, vous pouvez taper (en 10g) :
    sqlplus scott/tiger@//localhost:1521/XE
    Sous réserve que votre instance Oracle s'appelle "XE", qu'elle tourne sur la machine locale , qu'un Listener soit démarré sur la machine locale sur le port 1521 et que vous ayez un utilisateur "scott" activé dans la base de données dont le mot de passe est "tiger".
  • Le type d'adressage le plus répandu utilise un alias "TNS" stocké dans un fichier local. Ce fichier de configuration a forcément le nom "tnsnames.ora". Par défaut, il est stocké dans le répertoire ORACLE_HOME/network/admin mais peut être déplacé en positionnant une variable ou clé de registre TNS_ADMIN. Dans ce cas, vous tapez par exemple :
    sqlplus scott/tiger@gark
    Et le fichier tnsnames.ora contient une ligne comme celle-ci :
    gark=(description=(address=(protocol=tcp)(host=localhost)(port=1521))
    (connect_data=(service_name=orcl)))
    Sous réserve que votre instance Oracle s'appelle "orcl", qu'elle tourne sur la machine locale qu'un Listener soit démarré sur la machine locale sur le port 1521 et que vous ayez un utilisateur "scott" activé dans la base de données dont le mot de passe est "tiger".
    Cette méthode est sans doute la plus répandue de toutes : c'est la méthode historique ! Elle nécessite un paramétrage du client et en cas de modification de l'adressage, il faut modifier le fichier de tnsnames.ora. C'est la méthode la plus riche puisqu'elle permet d'exprimer toutes les options de paramétrages de la couche réseau.
  • Avec le client Oracle8i est apparut la possibilité de stocker l'alias TNS dans Oracle Internet Directory (i.e. un annuaire pour tous les clients). L'intérêt est d'offrir la richesse d'expression de l'adresse de connexion à une base de données dans un endroit central, compatible avec les régles de sécurité de l'entreprise et facile à sécuriser, via une réplication LDAP par exemple. Cette méthode est relativement répandue et surtout évite de repasser sur un client en cas de changement de paramétrage. L'utilisation d'OID à cet effet n'est pas soumis à license (cf "Oracle 10.2 - Licencing Guide"). A mon avis, si vous avez plus 30 ou 50 clients Oracle, c'est LA méthode à utiliser ! A moins que ça vous amuse de changer ou de faire changer vos adresses de connexions sur plusieurs 10x de machines.
  • Si vous utilisez un driver JDBC Thin (Type-4) , il existe des notations particulières pour se connecter à une base de données. Cela tient au fait que (1) le driver JDBC-Thin étant écrit complètement en Java, il n'a pas les mêmes fonctionnalités que les autres drivers et (2) Le drivers JDBC Thin pouvant être utilisés dans des applications légères comme des Applets, il faut pouvoir se connecter à distance sans fichiers de configuration.
    • La méthode la plus connue consiste à utiliser une syntaxe du type jdbc:oracle:thin:@machine:port:sid où vous remplacez les valeurs "machine" par le nom de machine sur laquelle le listener est démarré. "port" par le port d'écoute du Listener et "sid" par le nom de l'instance à laquelle vous voulez vous connecter. Cette méthode est très simple et assez pauvre. Elle est très répandue
    • En 10g, vous pouvez utiliser la syntaxe EZConnect décrite précédemment. Cela est aussi simple et offre de meilleures possibilités, comme la possibilité de se connecter à des instances sur des machines distinctes de la machine sur laquelle le listener est démarré ou celle d'utiliser une adresse IP virtuelle. Quand c'est possible, il faut donc préférer ce type de description de l'adressage. Dans ce cas, la chaîne de connexion ressemble à ceci : jdbc:oracle:thin:@//machine:port/service.
    • C'est moins connu mais assez utilisé, en particulier avec des configurations RAC, il est possible d'utiliser certaines syntaxes TNS avec un driver JDBC thin. Pour cela on utilise une chaîne de connexion qui ressemble à celle-ci : jdbc:oracle:thin:@(description=(address=(protocol=tcp)(host=localhost)
      (port=1521))(connect_data=(service_name=orcl)))
  • Il existe de nombreuses autres méthodes pour résoudre une adresse : DNS, Active Directory, CDS, NIS... Ces méthodes sont moins répandues mais peuvent être utiles si vous utilisez déjà des composants Réseau, Microsoft, Novell ou Unix et que vous voulez déléguer la gestion de l'adressage Oracle à ces services
  • La méthode ONS (Oracle Names Server) est une méthode qui permet comme pour OID de centraliser les alias TNS dans un serveur. Elle s'appuie sur le protocole SQL*Net au lieu de LDAP et ne permet pas de sécuriser simplement le référentiel. En 10g elle est totalement abandonnée au profit d'OID !
C'est le paramétrage des options par défaut, des variables d'environnements et du profil client (le fichier sqlnet.ora) qui permet au client Oracle de déterminer comment il doit résoudre une adresse. L'utilisation d'OID et/ou d'EZConnect sont les options par défaut des clients 10g. Cela permet si vous installez un client dit "Instant Client", c'est à dire sans "Installer" de ne faire aucun paramétrage sur le client. Dans ce cas, le client recherche une machine avec un alias oraldapx (x=1, 2...) dans votre réseau qui aurait OID installé sur le port par défaut (389) pour résoudre une adresse. Vous pouvez également et simplement modifier le fichier sqlnet.ora de la distribution avant de déployer vos clients.

Pour modifier les fichiers de profils (sqlnet.ora) et de paramétrage réseau (tnsnames.ora), vous pouvez éditer les fichiers manuellement. Pour avoir déjà laissé trainer un caractère dans ces fichiers et avoir mis des heures pour touver mon erreur... Pour ne pas connaître toutes les syntaxes par coeur et mettre des minutes pour déboguer, je vous conseille d'utiliser les outils suivants :
  • Oracle Configuration Assistant : netca, l'outil le plus simple et le moins riche
  • Oracle Network Manager : netmgr, mon outil préféré car le plus riche... Il permet par exemple de créer les alias dans OID
  • Oracle Enterprise Manager (Database Control ou Grid Control) : peut-être maintenant plus riche que netmgr... A condition de l'avoir installé
  • vi ou notepad : dans certains cas vous ne pouvez pas faire autrement... mais si c'est le cas, c'est que vous le méritez !
Connexion via l'OS et SYSDBA
Avant de parler du Listener plus en détail, il faut faire une remarque sur le rôle SYSDBA et sur l'utilisation d'un fichier de mot de passe. Pour certaines opérations, se connecter avec un utilisateur "classique", même DBA, de base de données ne suffit pas ! Par exemple, si vous voulez démarrer l'instance qui permet d'accéder à la base de données, il parait assez évident que vous ne pouvez pas utiliser un utilisateur de base de données puisque celle-ci est inaccessible.

En général, on s'appuie sur la sécurité locale du système d'exploitation. Sous Unix ou Linux, par exemple, un utilisateur de l'OS qui appartient au groupe "dba" ou son équivalent si vous avez choisi de l'appeler autrement lors de l'installation peut se connecter et ainsi démarrer l'instance. Pour se connecter, il faut être sur la machine et taper :
  • sqlplus "/ as sysdba" (en 9i et 10g)
  • ou plus simplement sqlplus / as sysdba (en 10g)
Dans ce cas, vous aurez une équivalence entre l'utilisateur "dba" au sens OS et l'utilisateur SYS au sens de la base de données. D'ailleurs, si un jour vous perdez les mots de passe de votre base de données... Connectez-vous depuis l'OS et changez le mot de passe avec la commande "alter user" !

De manière générale seuls les utilisateurs SYSDBA ont certains droits comme celui de se connecter quand la base de données est en mode restreint. Il est possible que vous ayez envie de vous connecter SYSDBA sans vous connecter à l'OS et ainsi, par exemple, démarrer ou arrêter une base de données à distance, sans passer par un agent qui s'exécute sur la machine locale. Ces utilisateurs particuliers doivent alors pouvoir être identifiés, même si la base est arrêtée. Leur identité est gérée dans la base de données ET dans un fichier de mot de passe (le password file). Pour créer ou recréer un password file, il faut utiliser l'interface en ligne de commande "orapwd". Le fichier a un nom et un emplacement bien particulier qui dépend du système d'exploitation. Par exemple sous Unix et Linux, il s'agit de ORACLE_HOME/dbs et le nom est orapwSID où SID est le nom de l'instance. Pour dire qu'on utilise ce fichier, il faut mettre le paramètre d'initialisation "remote_login_passwordfile" à la valeur "exclusive" (ou "shared", si vous voulez utiliser le même fichier pour plusieurs instances) dans le fichier de paramètre de l'instance, pfile ou spfile selon votre choix.

Le listener
Pour se connecter à distance à une base de données, il faut établir une connexion avec un process qui gère la relation entre votre client et l'instance : dans le cas le plus général, cette connexion est établie avec un process serveur dédié. Ce process est un processus sous Unix et un thread sous Windows. Il est possible d'utiliser un process partagé pour gérer le dialogue avec l'instance, mais cela sort du scope de cette explication.

Pour arriver à établir la connexion, il faut le demander à quelqu'un. Le listener peut être ce vecteur: il sert d'agent de connexion. Tout serait trop simple, s'il n'existait pas d'autres agents de connection comme Oracle Connection Manager (CMAN) dans certaines configurations plus évoluées. L'un des rôles du listener est donc de créer **sous Unix et Linux, on dit spawner**, le process serveur qui va dialoguer avec votre client et de vous mettre en relation avec ce process. Pour cela, il se met à l'écoute sur une adresse réseau sur un port particulier et répond à toutes les demandes de connexions. Le nom du processus listener est tnslsnr ou tnslsnr.exe.

Pour configurer le listener, il faut créer un fichier listener.ora dans le répertoire pointé par les variables ORACLE_HOME/network/admin ou TNS_ADMIN si cette variable existe. Il est à noter que si ce fichier n'existe pas, vous pouvez démarrer malgré tout un listener en 10g. Dans ce cas, il se mettra en écoute sur le port 1521 sur le réseau de votre machine. Pour créer un fichier listener.ora, le moyen le plus simple est d'utiliser un des outils de configuration du réseau : network configuration assistant (netca), network manager (netmgr) ou Enterprise Manager 10g.
  • Pour démarrer le listener, tapez : lsnrctl start listener où listener est le nom de votre listener.
  • Pour vérifier l'état de votre listener (les adresses et les ports sur lesquelles il écoute), tapez : lsnrctl status listener
Pour répondre à votre demande de connexion et créer le process qui vous authentifiera, il faut que le listener connaisse l'instance ou le service auquel vous voulez vous adresser. Vous pouvez utiliser un enregistrement dynamique ou un enregistrement statique des instances et des services dans le listener :
  • L'enregistrement dynamique est désormais la méthode conseillée. Dans ce cas, l'instance se déclare, elle et les services qu'elle sert, auprès du listener. Par défaut, l'instance se déclare auprès d'un listener qui écoute sur le port 1521 sur la machine local (elle utilise la fonction "hostname"). Si vous désirez changer cet enregistrement vers un autre listener, il faut créer un alias TNS dans le fichier tnsnames.ora qui pointe vers le listener. Par exemple :
    mon_listener= (description=(address=(protocol=tcp)(host=localhost)(port=1526))
    et positionner le paramètre d'initialisation local_listener avec le nom de l'alias. Pour cela, vous pouvez taper les commandes :
    SQL> alter system set local_listener='mon_listener' scope=both;
    SQL> alter system register; <<-- Cette ligne force l'instance à s'enregistrer à nouveau La base de données enregistre alors son nom ainsi que l'ensemble des noms de services qu'elle sert dans le listener. Pour ajouter ou supprimer des services à la base de données, il suffit de modifier le paramètre d'initialisation service_names ou, en 10g, d'utiliser le package DBMS_SERVICES. Par exemple : SQL> alter system set service_names='service1, service2, service3' scope=both;
    SQL> alter system register;
  • L'enregistrement statique est l'ancienne méthode... Du temps en 8.0 où la base de données ne s'enregistrait pas dans le listener. Dans ce cas, il faut enregistrer le nom de l'instance dans le fichier de paramétrage du listener (le fichier listener.ora dans le répertoire TNS_ADMIN ou ORACLE_HOME/network/admin). Pour cela la méthode la plus simple est sans doute d'utiliser Oracle Network Manager (netmgr). En général on n'utilise plus cette méthode sauf si vous voulez vous connecter à distance sous le compte SYSDBA alors que l'instance n'est pas ouverte. En effet comme dans ce cas, la base de données ne s'est pas encore enregistrer dans le listener (puisqu'elle est arrêtée), le seul moyen de permettre un accès distant est d'enregistrer l'instance de manière statique dans la configuration du listener.
Vous pouvez vérifier les services et les instances disponibles dans un listener en tapant : lsnrctl services listener, où listener est le nom du listener que vous voulez vérifier.

Listener distant ou "remote"
Le listener auquel vous vous adressez pour établir une connexion n'est pas forcément sur la machine qui exécute l'instance. L'intérêt d'utiliser un listener "distant" est multiple :
  • Si vous déplacez une instance, vous n'avez pas à changer la configuration du client... puisque le listener lui ne bouge pas
  • Si vous voulez répartir les connexions sur plusieurs serveurs (avec RAC, par exemple), le fait d'utiliser un listener distant permet de faire du loadbalancing
Mais comment le listener peut-il établir une connexion s'il est sur une machine distante puisque dans le cas de l'utilisation d'un process serveur dédié, il doit créer un process sur la machine de l'instance de base de données ? La réponse réside dans le fait que les listeners distants connaissent le listener local de chaque instance. L'instance de base de données doit donc indiquer où est le listener local lorsqu'elle s'enregistre dans le listener distant. Il faut donc bien distinguer le listener local des listeners distants. Pour déclarer un ensemble de listener distant, on procède d'une manière assez similaire à la déclaration des listeners locaux :
  1. On crée un alias TNS dans le fichier tnsnames.ora de la base de données. Cet alias contient la liste des adresses des listeners distants avec une syntaxe comme celle-ci :
    alias=(description=(address_list=
    (address=(protocol=tcp)(host=machine1)(port=1521))
    (address=(protocol=tcp)(host=machine2)(port=1521))
    (address=(protocol=tcp)(host=machine3)(port=1521))
    ))
  2. Il faut ensuite déclarer cet alias dans le paramètre d'initialisation de l'instance remote_listener avec une commande comme celle-ci :
    SQL> alter system set remote_listener='alias' scope=both;
    SQL> alter system register;
Vous pouvez ensuite vérifier que l'instance s'est enregistrée dans les listeners distants et que le listener local est associé aux services enregistrés comme des services distants. Utilisez "lsnrctl services" pour vérifier que le paramétrage est efficace.

Autres considérations :
Il y a de nombreuses choses à dire sur la manière de paramétrer et sécuriser le réseau Oracle. Si vous avez des questions, n'hésitez pas à les poster dans les commentaires de ce thread. Je vais déjà répondre à une question : "Pourquoi il faut sécuriser votre listener avec un mot de passe ?".

Imaginons que vous ayez un listener sans mot de passe positionné sur un serveur. Si, sur un client qui accéde à ce serveur par le réseau TCP/IP, vous créez un alias TNS, par exemple :
alias=(description=(address=(protocol=tcp)(host=machine)(port=1521)))
Alors, vous pouvez effectuer plusieurs opérations à distance comme arrêter le listener avec une commande du type:
lsnrctl stop alias
Les clients ne peuvent plus alors se connecter. Vous pouvez également effectuer d'autres opération comme activer des traces qui pourraient saturer l'espace de certains systèmes de fichiers de votre serveur. Ce type d'attaque sont dites "Denial of Service", et même si elles sont limitées au réseau des bases de données... Mieux éviter de tenter le diable. Mettre un mot de passe sur les listeners est facile et une bonne pratique.

Déboguer votre configuration réseau
Le message d'erreur d'une connexion est généralement explicite et on peut en déduire la raison d'un échec de connexion. Si jamais vous aviez du mal, vous trouverez ci-dessous un ensemble d'étapes qui vous permettent de valider votre connexion à une base de données. Si les symptômes persistent, ouvrez une SR sur Metalink :
  1. Valider que vous arrivez à vous connecter à l'instance sans passer par le réseau
    set ORACLE_SID=orcl
    sqlplus "/ as sysdba"
  2. Vérifiez que votre instance est ouverte :
    set ORACLE_SID=orcl
    sqlplus "/ as sysdba"

    SQL> select status from v$instance;
  3. Vérifiez que votre nom d'utilisateur et mot de passe sont corrects
    set ORACLE_SID=orcl
    sqlplus scott/tiger
  4. Vérifiez que votre listener est bien démarré
    lsnrctl status listener
    (où listener est le nom de votre listener)
    et qu'il est bien à l'écoute sur la bonne adresse IP et le bon port :
    netstat -a
    (y compris sous Windows)
  5. Vérifiez que la base de données s'est bien enregistrée dans le listener
    lsnrctl services listener
    (où listener est le nom de votre listener)
    Si ce n'est pas le cas, forcer l'enregistrement avec la commande :
    set ORACLE_SID=orcl
    sqlplus "/ as sysdba"

    SQL> alter system register;
    Si l'instance ne s'enregistre pas dans le listener, vous pouvez effectuer les tests 6-7-8 et 9 en considérant que le client est la base de données et donc également le serveur. L'alias que vous testerez est la chaîne de caractère contenue dans le paramètre d'initialisation local_listener. Si ce paramètre est vide, cela signifie que la base de données tente de s'enregistrer dans un listener en écoute sur le port 1521 et sur l'adresse servie par la fonction hostname.
  6. Vérifiez que vous arrivez à accéder à la machine sur laquelle le listener est démarré :
    ping machine_serveur
    (depuis le client)
  7. Vérifiez que vous pouvez atteindre la machine cliente depuis votre serveur
    ping ip_client
    (depuis le serveur)
  8. Lancez l'assistant de création/modification des fichiers de configuration (netmgr) sur le client pour vérifier qu'il n'y a pas de problème de formattage dans le fichier tnsnames.ora. Retrouvez et visualisez dans cet assistant votre alias de connexion.
  9. Tentez d'atteindre le listener distant via l'alias TNS grâce à la commande "tnsping" qui permet de tester la présence du listener sans résoudre le service ou l'instance. Utilisez la commande :
    tnsping alias
    (ou alias est le nom de l'alias TNS que vous testez)
  10. Tentez de vous connecter avec sqlplus :
    sqlplus scott/tiger@alias (ou alias est le nom de l'alias TNS que vous testez)
Encore une erreur courante
Encore une chose, parce qu'on tombe tous un jour ou l'autre dans ce piège : Si vous utilisez le paramètre NAMES.DEFAULT_DOMAIN dans le fichier de profil SQL (sqlnet.ora), alors un suffixe est ajouté de manière transparente à chaque fois que vous tapez un alias.

Par exemple :
  • Si vous avez la valeur NAMES.DEFAULT_DOMAIN=world dans le fichier sqlnet.ora
  • Si vous avez un alias "gark=(description=..." dans le fichier tnsnames.ora
  • Si vous tentez de vous connecter avec sqlplus user/password@gark
Vous aurez un message d'erreur qui indique que l'alias n'est pas trouvé. C'est parce que l'alias qui est réellement cherché dans le fichier tnsnames.ora n'est pas gark mais gark.world ! Et puis un jour, vous aurez 2 alias gark et gark.world dans le fichier tnsnames.ora...

GarK!

09 septembre 2006

Plus de JPA : generer les PKs, etc...

Java Persistence API permet d'utiliser plusieurs mecanismes pour generer des cles primaires des tables et ceci au moyen d'une simple declaration (Annotations ou fichier XML). La cle primaire peut ainsi etre :
  • Une sequence generee par la base de donnees si celle-ci le permet (Oracle, par exemple)
  • Une colonne identite si la base de donnees le permet (SQL Server, par exemple)
  • Une valeur stockee dans une ligne d'une table
  • Une methode automatique geree par l'API. Dans ce dernier cas, il faut utiliser la generation automatique du schema pour que les structures correspondantes puissent etre creees.
Pour en savoir plus sur ces methodes, il existe un document "howto" sur le site dedie a Toplink Essentials, ici ainsi qu'un second document qui illustre comment effectuer des insert-update-delete avec JPA ici.

La troisieme methode, qui s'appuie sur une table, est generalement possible avec toutes les bases de donnees; Je vais continuer le thread precedent et la mettre en oeuvre avec Derby. Pour cela, il faut utiliser 2 annotations :
  • javax.persistence.GeneratedValue se situe generalement apres l'annotation javax.persistence.Id. Elle indique que la valeur de la cle doit etre generee ainsi que la methode associee. Pour une table, la maniere la plus simple est de donner un nom a la methode de generation. Par exemple :
    @GeneratedValue(generator="monGen4EmpPk")
  • javax.persistence.TableGenerator se situe generalement en dessous de l'annotation precedente et contient les attributs suivants : (1) name est le nom du generateur, (2) table est le nom de la table dans laquelle la valeur de cle est stockee, (3) pkColumnName est le nom de la colonne qui contient le nom du compteur, (4) valueColumnName est le nom de la colonne qui contient le compteur de la cle et (5) pkColumnValue est la valeur pour la colonne definie precedemment et correspond a la ligne du compteur. Par exemple, on trouvera l'annotation suivante :
    @TableGenerator(name="monGen4EmpPk",
    table="TABSEQ",
    pkColumnName="ID_TABSEQ",
    valueColumnName="VAL_TABSEQ",
    pkColumnValue="SEQEMP")
Dans le cas illustre precedemment, pour initialiser la base de donnees, on pourra creer une table TABSEQ(ID_TABSEQ VARCHAR(10), VAL_TABSEQ INT) puis inserer une ligne avec les valeurs SEQEMP et 1. Avec une base Derby, cela signifie, qu'il faut executer le code suivant sur Derby :
TABSEQ values ('SEQEMP', 5);

Si on reprend maintenant notre classe persistente Emp et qu'on la manipule sans positionner d'identifiant, on constate que c'est l'API de persistence Java qui positionne les valeurs en s'appuyant sur la table parametree ci-dessus. Vous pouvez recuperer le projet JDeveloper qui reprend l'exemple complet sur mon repertoire internet en cliquant sur le lien suivant.

Pour terminer cet exemple, vous trouverez plus d'informations dans de nombreux documents, et en particulier :
Reste a continuer... Encore !

GarK!

Apache Derby (1er Pas) /*+Way Out?*/

Ce n'est pas que je veuille vraiment renoncer a Oracle... Cela dit quitte a voir autrechose, autant que ce soit une base Java. Java DB (i.e. Apache Derby) est inclus dans le JDK (Mustang) de Sun pour Java SE 6.0. Pour la petite histoire, il s'agit de la version open source de la base de donnees Cloudscape d'IBM. Pour ne pas mourrir idiot, j'ai fait quelques tests ! Ce que je voulais particulierement regarder c'est si c'est possible de manipuler Derby depuis un IDE comme JDeveloper et avec une "Java Persistence API" comme Toplink Essentials.

Pour installer Derby, c'est tres simple :
  • S'assurer que l'on a installe et configure un JRE 1.3 minimum (J'ai fait mes tests avec le JDK 1.5 Update 8 de Sun pour Windows)
  • Recuperer Derby sur le site d'Apache (http://db.apache.org/derby/derby_downloads.html) et decompresser la distribution.
  • Positionner la variable systeme DERBY_INSTALL sur le repertoire dans lequel Derby est decompresse
  • Ajouter les fichiers JAR derby.jar et derbytools.jar (repertoire lib de DERBY_INSTALL) dans la variable CLASSPATH
  • Lancer la classe org.apache.derby.tools.sysinfo pour verifier que le parametrage de Derby est correct avec la commande "java org.apache.derby.tools.sysinfo". Le retour de cette commande indique les versions de Derby et JDK utilisees
Pour utiliser Derby, on peut, dans un premier temps, utiliser l'outil en ligne de commande "ij" :
  • Tapez : "java org.apache.derby.tools.ij"; le prompt ij> doit apparaitre.
  • Pour se connecter a une base de donnees nommee "test", il suffit de taper
    ij> connect 'jdbc:derby:test';
    Si la base de donnees n'existe pas encore, vous pouvez la creer en meme temps que vous vous connectez avec la commande :
    ij> connect 'jdbc:derby:test;create=true';
    La base de donnees est creee dans le repertoire de lancement de la JVM; Vous voyez un fichier derby.log et un repertoire correspondant a la base de donnees. Si vous voulez creer une base de donnees qui n'est pas dans ce repertoire, vous pouvez preceder le nom de la base de donnees par son chemin absolu
  • Vous pouvez ensuite utiliser le langage SQL pour manipuler des objets dans votre base de donnees.
    ij> create table emp(id int, lastname varchar(40), firstname varchar(40));
    ij> insert into emp values (1, 'Arkzoyd', 'Gregory');
    ij> insert into emp values (2, 'Smith', 'John');
    ij> update emp set firstname='Jack' where id=2;
    ij> select * from emp;
  • Pour executer un script demo.sql, tapez
    ij> run 'demo.sql';
    ou java org.apache.derby.tools.ij demo.sql
  • Tapez 'disconnect' ou 'exit' pour vous deconnecter de la base de donnees
Pour vous connecter a Derby depuis une autre JVM, cette approche est plus lourde et proche du fonctionnement d'une base de donnees comme Oracle. Elle permet d'acceder a la meme base de donnees depuis plusieurs JVM distinctes. Ces JVM peuvent etre sur la meme machine ou sur d'autres machines :
  • S'assurer que l'on a installe et configure un JRE 1.3 minimum
  • Recuperer Derby sur le site d'Apache (http://db.apache.org/derby/derby_downloads.html) et decompresser la distribution.
  • Positionnez la variable systeme DERBY_INSTALL sur le repertoire dans lequel vous avez decompresse Derby
  • Ajouter les fichiers JAR derby.jar, derbytools.jar et derbynet.jar (inclus dans le repertoire lib de DERBY_INSTALL) dans la variable CLASSPATH
  • Lancer la classe org.apache.derby.drda.NetworkServerControl avec les parametres (1) start (2) -h %derbyHost% (pour le nom de la machine sur laquelle Derby va binder une socket en LISTEN, par defaut hostname) et (3) -p %derbyPort% (pour le port de la machine sur laquelle Derby va binder une socket en LISTEN, par defaut 1527). Pour cela, il faut taper, par exemple :
    java
    org.apache.derby.drda.NetworkServerControl start -h localhost -p 1527
  • Pour se connecter, il suffit de lancer ij et de taper comme url de connexion "jdbc:derby://host:port/dbname". Les fichiers jar necessaires sont derbyclient.jar et derbytools.jar. Une fois les variables positionnees, il faut taper :
    java org.apache.derby.tools.ij
    ij> connect 'jdbc:derby://localhost:1527/test';
    ij> select * from emp;
Acceder a Derby depuis Oracle Jdeveloper...


Comme presente dans la copie d'ecran ci-dessus, il est possible d'utiliser JDeveloper pour acceder a Derby comme a une base Oracle, pour cela :
  • Creer une nouvelle connexion et selectionner un driver tiers
  • Ajouter derbyclient.jar dans la bibliotheque d acces
  • Mettre org.apache.derby.jdbc.ClientDriver comme driver
  • Ne pas mettre de connexion utilisateur
  • Mettre une URL correspondant a une connexion distante (e.g. jdbc:derby://localhost:1527/test) et assurez vous que Derby est demarree en mode reseau
Il est egalement possible d'inclure Derby dans JDeveloper mais ca pose des problemes si on veux lancer un programme (pour des tests) qui accede a la meme base de donnees depuis une autre JVM

Developper une entity avec l'API de Persistence Java (JPA)

Depuis JDeveloper, On peur developper une entity qui accede a Derby et faire le mapping objet/relationnel. Pour cela,
  • On ajoute les librairies Derby au projet et on s'assure que la base Derby est lancee en reseau.
  • On cree une classe Emp qui est une entity qui mappe la table EMP de la base Derby.
  • On cree (ou modifie) ensuite un fichier persistence.xml dans le repertoire META-INF :
  • Pour finir on cree une classe JavaServiceFacade avec une methode main() qui manipule notre entity
Un projet exemple est disponible sur mon repertoire internet, ici. Regardez bien le fichier persistence.xml dans le repertoire META-INF; c'est lui qui contient le parametrage de la couche de persistence Toplink Essentials pour acceder a Apache Derby. Si vous voulez en savoir plus sur la maniere de developper des entities, reportez-vous a l'un de mes threads precedents sur EJB 3.0 et JPA ou, mieux, a toute la litterature sur ce theme... Interessant non ? pour developper une application en utilisant une infrastructure de base de donnees embarquee dans le serveur d'applications.

GarK!

04 septembre 2006

JSF et modification des données /*+Tutorial*/

La Section 6 - Création d'une page JavaServer Faces pour modifier les contacts du Tutorial est désormais disponible ! Elle illustre, en plus de la navigation entre les pages, la manipulation du "Managed Backing Bean" et des objets sous-jacents. Vous verrez comment utiliser des fonctions de mise à jour des objets dans Toplink à travers un EJB qui sert de Session Facade !

Le principe reste le même... Il s'agit d'un enregistrement commenté de l'ensemble de la manipulation ! Pour comprendre le projet, assurez vous d'avoir bien suivi les Sections 1 à 4 et, éventuellement si JPA vous intéresse, la Section 5.

Je commence mon nouveau travail demain... Il faudra sans doute attendre encore quelques jours pour la Section 7. Vos commentaires sont les bienvenus !

GarK!

03 septembre 2006

EJB 3.0 et Java Persistence API (JPA) /*+Tutorial*/

La cinquième section du tutorial relatif aux technologies Java EE est disponible. Avant de vous précipiter pour la télécharger assurez-vous d'avoir d'abord suivi les 4 sections précédentes.

Cette section 5 illustre comment utiliser "Java Persistence API" dans un modèle métier. Très proche de Toplink, certaines différences sont notables et en particulier, (1) le fait que Toplink génère plus de fichiers et de descriptions, (2) le fait que les informations de mapping puissent être des annotations avec JPA et (3) le Mapping Workbench de Toplink qui facilite indéniablement le développement en représentant graphiquement les mappings. Cela étant, vous ne serez pas perdu.

Cet exemple est simple et pourtant assez illustratif de ce qui vous attend si vous décidez d'utiliser cette API. A bientôt pour une section... plutôt "interface web" !

GarK!

PS : Pour télécharger la section 5 du tutorial vous cliquez sur le lien ici!

02 septembre 2006

Tutorial EJB3, JSF, TopLink... /*+FastTrack*/

Un des accents de Java EE 5.0 est la simplicité de développement. Qu'est-ce que ça veux dire ?

A travers les différentes sections enregistrées et commentées de ce tutorial, vous allez découvrir ce que cela signifie et comment développer une application de gestion des contacts. Nous explorerons EJB 3.0, JSF mais également TopLink et beaucoup d'autres aspects du développement d'applications.

Les quatre premières sections sont disponibles. Cet ensemble forme une base pour explorer des sujets plus avancés dans les sections à venir. Vous les récupèrerez aux URLs qui suivent :
Ces sections sont suffisamment simples pour être refaîtes rapidement. Vous aurez alors développé une application web en Java EE. Et en plus, (1) vous n'avez pas développé de SQL, (2) vous n'avez pas fait de HTML, Javascript ou de CSS et (3) vous avez développé une application capable de tirer avantage des capacités d'ouverture, de montée en charge, de déploiement distribué, de sécurité et d'évolutivité de la plateforme Java EE.

Pour vous aider (L'objectif, c'est que vous soyez capable de tout faire vous même), je vous conseille de vous procurer pour Windows ou Linux l'ensemble des outils qui suivent :
Si vous voulez déjà anticiper la suite des Tutorials, OTN est une mine d'informations :
Voilà, c'est un début ! Il reste maintenant plein de choses à illustrer. La prochaine section remplacera le mapping Objet/Relationnel de Toplink par l'API de persistence Java disponible avec les EJB 3.0 (JPA : Java Persistence API). Cela enlèvera le seul composant non-Standard de notre application... Même si Toplink reste un outils inégalé qui fonctionne sur tous les serveurs d'applications (ou dans une simple JVM) et avec toutes les bases de données ! Nous pourrons également explorer la création de pages pour mettre à jour les données et l'utilisation de composants JSF évolués avec Apache MyFaces ou Trinidad (aka ADF Faces). Nous pourrons utiliser des sources qui ne sont pas des bases de données (XML, Java Connector Architecture...), publier des services web ou créer des interfaces pour différents types de terminaux (PDA, Telnet pour les environnements industriels...).

Toutes vos idées sont bonnes à prendre, n'hésitez pas à ajouter vos commentaires à ce thread qui évoluera bientôt. Si je peux perfectionner ces démonstrations, ce sera bénéfique pour tous !

Mais tout ça, c'est une autre histoire...

GarK!

Remarques
1- Il s'agit de démonstrations Flash enregistrées. Téléchargez les fichiers Zip et décompressez les. Ouvrez le fichier HTML avec un navigateur pour lancer la video
2- Mes commentaires sont toujours médiocres... mais en mettant le son à fond, vous devriez pouvoir suivre le cheminement de la démonstration
3- Je réalise ces présentations avec un logiciel opensource très intéressant : CamStudio.