mardi 24 mai 2016

Externaliser la configuration d'une webapp


Comment permettre à une application web Java de récupérer un paramètre de configuration sans avoir à repackager le ".war" ?



Si on s'interdit de modifier le fichier ".war" ça veut dire que l'on ne peut plus utiliser les possibilités de configuration à partir des fichiers qu'il contient ( web.xml, fichiers properties, etc ).
Les paramètres de configuration devront donc être portés par les environnements d'exécution de l'application (et non par l'application elle même), c'est à dire le server d'applications ( Tomcat, Jetty, etc ) ou le système d'exploitation.
Les trois possibilités les plus courantes sont décrites ci-après...

1) Utiliser une variable d'environnement

- Définir la variable d'environnement au niveau du système d'exploitation
Exemple sous Linux  :
   export MYFOLDER=/tmp/foo

- Récupérer la valeur de cette variable dans le code Java,
  par exemple dans une classe de type  "ServletContextListener" :
    String value = System.getenv("MYFOLDER")

Cette solution est simple et applicable indépendamment type de serveur d'applications.
Mais elle nécessite une intervention au niveau "système d'exploitation" (pas toujours possible) et on ne peut avoir qu'une seule valeur pour toutes les instances de serveurs d'application sur un même OS.


2) Configurer une propriété de type "Java System property"

Il s'agit de définir une propriété pour la JVM au lancement du serveur d'applications.

- Définir la propriété pour un serveur d'applications particulier :
Soit avec l'option "-D" de la ligne de commande
Soit en utilisant les fichiers de configuration propres à chaque serveur d'application
Exemple pour Tomcat :
        Dans le fichier "catalina.properties" de Tomcat :
    myfolder=/tmp/foo
       
        NB : pour un lancement dans Eclipse utiliser le fichier "catalina.properties"
                 situé dans le workspace (dans  "Servers" )

- Récupérer la valeur de cette propriété dans le code Java :
    String value = System.getProperty("myfolder");


3) Configurer une "valeur nommée" accessible via JNDI

Une "ressource nommée" peut être définie au niveau du serveur d'applications, elle sera ensuite récupérée via JNDI.

- Définir la "ressource nommée" pour le serveur d'applications concerné

Pour Tomcat :
        Dans le fichier "web.xml" de Tomcat (fichier global pour toutes les webapps) :
      <env-entry>
          <env-entry-name>myTextValue</env-entry-name>
          <env-entry-type>java.lang.String</env-entry-type>
          <env-entry-value>foo</env-entry-value>
      </env-entry>
      <env-entry>
          <env-entry-name>myMaxValue</env-entry-name>
          <env-entry-type>java.lang.Integer</env-entry-type>
          <env-entry-value>10</env-entry-value>
      </env-entry>
        NB :
        - respecter l'ordre des tags "name/type/value"
        - pour un lancement dans Eclipse utiliser le fichier "web.xml" situé
          dans le workspace (dans  "Servers" )
       
        cf https://tomcat.apache.org/tomcat-7.0-doc/config/globalresources.html#Environment_Entries 

Pour Jetty :
        Dans le fichier "jetty.xml" ajouter une ressource avec une entrée du type :
     <New class="org.eclipse.jetty.plus.jndi.EnvEntry">
       <Arg></Arg> <!-- scope : empty = JVM scope-->
       <Arg>myTextValue</Arg> <!-- name -->
       <Arg type="java.lang.String">foo</Arg> <!-- value-->
       <Arg type="boolean">true</Arg>  
     </New>

        cf http://www.eclipse.org/jetty/documentation/current/using-jetty-jndi.html

- Récupérer la valeur de cette variable dans le code Java
  Exemple pour une chaine de caractères :

   String name = "myTextValue" ;
   try {
      Object value = InitialContext.doLookup("java:comp/env/"+name);
      System.out.println("JNDI OBJECT '"+ name + "' = '" + value + "'");
   } catch (NamingException e) {
      System.out.println("JNDI OBJECT ERROR : " + e.getMessage());
      e.printStackTrace();
   }


mardi 22 mars 2016

Installation d'un serveur Git sur Ubuntu


1 - Sur le serveur Git


1.1 - Installation de "git"


Mise à jour du "apt-get repository" :
$ sudo apt-get update

Installation de Git
$ sudo apt-get install git

Test d'utilisation de Git
$ git --version
git version 2.5.0


1.2 - Création du user "git"


$ sudo adduser git
Saisie du password pour le user "git"

$ su git
$ cd
$ pwd
/home/git


1.3 - Création d'un "repository" vide

$ cd /opt/git
mkdir project1.git
$ cd project1.git
$ git init --bare
$ ls -lisa
Structure classique des fichiers et répertoire git :
   branches
   config
   description
   HEAD
   hooks
   info
   objects
   refs

2 - Sur le "client" Git

Sur le poste qui va se connecter au serveur...


2.1 - Mise en place de la connexion "ssh" avec clé publique

- Test de la connexion ssh avec mot de passe :
$ ssh git@<hostname> 
En l'absence de clé publique le mot de passe est demandé

- Génération des clés ( clé publique et clé privée ) si elles n'existent pas déjà
$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which you want to save the key (xxx/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in xxx/.ssh/id_rsa.
Your public key has been saved in xxx/.ssh/id_rsa.pub.
The key fingerprint is :
... 
The key’s ramdonart image is:
... 
2 fichiers sont générés dans le répertoire $HOME/.ssh de l’utilisateur :
  - id_rsa  ( la clé privée )
  - id_rsa.pub  ( la clé publique )

- Copie de la clé publique sur le serveur git pour le user "git"
$ ssh-copy-id -i ~/.ssh/id_rsa.pub git@<hostname>
git@<hostname>’s password:
Number of key(s) added: 1
Now try to logging into the machine, 
with "ssh 'git@<hostname>‘”

- Test de la connexion ssh sans mot de passe :
$ ssh git@<hostname> 
Le mot de passe n'est plus demandé

L'accès en "ssh" sans mot de passe est maintenant OK.
Git va donc pouvoir utiliser le serveur remote avec le protocole "ssh"

2.2 - Utilisation de Git en SSH à partir du poste client

Initialisation du repository local
$ git init

Création d'un fichier (par exemple un simple fichier ".txt" )

Staging et commit du nouveau fichier
$ git add .
$ git commit -m "Initial commit"

Définition du serveur "remote" (SSH est le protocole par défaut)
$ git remote add origin git@<hostname>:/opt/git/project1.git
git remote -v
origin  git@<hostname>:/opt/git/project1.git (fetcth)
origin  git@<hostname>:/opt/git/project1.git (push)
ou avec le préfixe "ssh://" pour être plus explicite
git remote add origin ssh://git@<hostname>:/opt/git/project1.git


Push sur le serveur "remote"
$ git push origin master

Fetch à partir du serveur "remote"
git fetch


3 - Au-delà du protocole SSH 

Le serveur Git peut être adressé avec différents protocoles
  • file://
  • ssh://
  • git://
  • http://
  • https://

Le protocole git:// nécessite de lancer le "git daemon" sur le serveur,
il permet un accès non authentifié mais n'est pas "internet friendly" (il écoute sur un port spécifique, le 9418 par défaut)

Le protocole http:// ou https:// suppose la mise en place d'un serveur http,
généralement "Apache" avec utilisation de WebDAV ou du script CGI "git-http-backend"

Pour plus d'information sur les différents modes d'accès à un serveur Git voir l'article de Patrick Debois http://www.jedi.be/blog/2009/05/06/8-ways-to-share-your-git-repository/ 


jeudi 28 janvier 2016

Installation d'Apache 2 sur Ubuntu


Avant toute installation, mettre à jour le "apt-get repository" :

sudo apt-get update


Installation du paquet "Apache 2"

$ sudo apt-get install apache2 


Le service apache est démarré immédiatement après l'installation et écoute sur le port 80.

Liste des processus 

$ ps -edf | grep apache
 root      4927     1  0 17:04 ?        00:00:00 /usr/sbin/apache2 -k start
 www-data  4930  4927  0 17:04 ?        00:00:00 /usr/sbin/apache2 -k start
 www-data  4931  4927  0 17:04 ?        00:00:00 /usr/sbin/apache2 -k start


Test avec un navigateur :  

http://adresse-ip-du-host/

Affiche "Apache2 Ubuntu Default Page"
avec les principales informations sur les fichiers de configuration :

The configuration layout for an Apache2 web server installation on Ubuntu systems is as follows:
/etc/apache2/
|-- apache2.conf
|       `--  ports.conf
|-- mods-enabled
|       |-- *.load
|       `-- *.conf
|-- conf-enabled
|       `-- *.conf
|-- sites-enabled
|       `-- *.conf

The default Ubuntu document root is /var/www/html.


Installation du mod "PHP"

$ sudo apt-get install php5 libapache2-mod-php5


Tester avec un primier fichier ".php" dans "/var/www/html" :

$ cd /var/www
$ chmod 777 html
$ cd html
$ vi phpinfo.php
<?php
  phpinfo();
?>

Test avec un navigateur :  
http://adresse-ip-du-host/phpinfo.php

Affiche la page standard d'information sur la version de PHP utilisée
"PHP Version 5.6.4-4ubuntu6.4"
etc...

Pour utiliser MySQL avec PHP  :  

sudo apt-get install php5-mysql 

Pour utiliser PostgreSQL avec PHP  :  

sudo apt-get install php5-pgsql 

Redémarrer Apache 2 (après installation des paquets complémentaires de PHP5 )  :  
sudo service apache2 restart

Nouveau test avec le navigateur :
http://adresse-ip-du-host/phpinfo.php

La page doit contenir les infos relatives aux paquets complémentaires,
par exemple pour "PostgreSQL" :
    "pdo_pgsql"
    "pgsql"


lundi 25 janvier 2016

Installation de PostgreSQL 9.4 sur Ubuntu



Avant toute installation, mettre à jour le "apt-get repository" :

sudo apt-get update

Installation de PostgreSQL 9.4 sur Ubuntu

$ sudo apt-get install postgresql postgresql-contrib

Voir les processus actifs de PostgreSQL :
$ ps -f -u postgres
6 processus actifs ( "postgres" est le user Linux )

Autoriser les connexions en "remote"

Dans le répertoire "/etc/postgresql/9.4/main

1) Modifier le fichier "postgresql.conf"
$ sudo vi postgresql.conf

listen_addresses = '*'

( le port par défaut est 5432 )

2) Modifier le fichier "pg_hba.conf"
$ sudo vi pg_hba.conf

# IPv4 local connections
host  all  all  (remote_ip)/32   md5
(autorise la connexion pour tous les utilisateurs pour toutes les bases à partir
du poste ayant l'adresse ip indiquée )

An IP address range is specified using standard numeric notation for the range's starting address, 
then a slash (/) and a CIDR mask length. The mask length indicates the number of high-order bits of the client IP address that must match. Bits to the right of this should be zero in the given IP address. There must not be any white space between the IP address, the /, and the CIDR mask length.

Typical examples of an IPv4 address range specified this way are :
 172.20.143.89/32   for a single host
 172.20.143.0/24    for a small network
 10.6.0.0/16      for a larger one

Restart Linux.

Création d'un utilisateur

Lancement de l'interpéteur SQL ( "psql" ) :
$ sudo -u postgres psql
Exemple : création d'un utilisateur "foo" avec mot de passe "foo" :
postgres=# create user foo createdb createuser password 'foo' ;
CREATE ROLE 
postgres=# 

Liste des utilisateurs existants :
postgres=# select * from pg_catalog.pg_user ;

postgres=# \q    (quit)

Création d'une base de données pour un utilisateur

sudo -u postgres psql
postgres=# create database foodb with encoding='UTF8' owner=foo connection limit=-1;
CREATE DATABASE
postgres=# 

Liste des bases de données existantss :
postgres=# \list
ou 
postgres=# select * from pg_database ;

Connexion JDBC à distance

Driver class : "org.postgresql.Driver"

URL : jdbc:postgresql://host:port/database
Exemple : 
   - URL : "jdbc:postgresql://10.226.159.81:5432/foodb"
   - User : "foo"
   - Password : "foo"

Installation de Telnet server sur Ubuntu



Deux paquets à installer : "telnetd" et "xinetd"

$ sudo apt-get install telnetd

$ sudo apt-get install xinetd 

Restart


Fichiers de configuration :

/etc/xinetd.conf

/etc/services  ( ports )
Exemple :
$ cat /etc/services | grep telnet
telnet          23/tcp
rtelnet         107/tcp                         # Remote Telnet
rtelnet         107/udp
telnets         992/tcp                         # Telnet over SSL
telnets         992/udp
tfido           60177/tcp                       # fidonet EMSI over telnet

Process : "telnetd"

$ ps -edf | grep telnet
telnetd   3494  3061  0 16:42 ?        00:00:00 in.telnetd: xxxxx


Test avec un client "Putty" sous Windows :

Conserver le port telnet par défaut : "23

Sélectionner "(o) Telnet "

mercredi 28 octobre 2015

JUnit Vade-mecum

Un petit mémo JUnit ...



Cycle de vie des instances et ordre d'exécution :


Remarques : l'API JUnit ne définit aucun ordre d'exécution des tests, ils doivent donc être exécutable dans n'importe quel ordre. Chaque test doit être indépendant des autres.
Cependant JUnit ver 4.11 permet de fixer l'ordre d'exécution avec l'annotation "@FixMethodOrder" qui peut être utilisée au niveau de la classe.
Exemple :
   @FixMethodOrder(MethodSorters.NAME_ASCENDING)
   public class MyTestCase {
      ...
   }

Sous Eclipse, pour faciliter l'utilisation des "assert" avec import statique :
Window / Preferences : Java / Editor / Content Assist / Favorites
ajouter org.junit.Assert.*