Publié le 19 Août 2013

MySQL ne fournit pas de syntax pour le FULL OUTER JOIN mais par contre on peut facilement obtenir le même résultat à l'aide d'un UNION.

SELECT a.*, b.* FROM a LEFT JOIN b USING (id)
UNION
SELECT a.*, b.* FROM b LEFT JOIN a USING (id);

Il est important de garder le même ordre des champs entre les 2 SELECT pour que MySQL supprime automatiquement les doublons lors du l'UNION.

Voir les commentaires

Rédigé par Bliz

Publié dans #MySQL

Repost 0

Publié le 17 Août 2013

Selon votre IDE préféré vous avez différents fichiers qui apparaissent à la racine de votre projet:

  • .classpath et cie pour Eclipse
  • *.iml pour IntelliJ
  • ...

Sur notre poject il a été décidé de ne pas ajouter ces fichiers aux .gitignore des projets, cependant il faut quand même éviter de commiter ces fichiers (même par accident).

Et bien chaque développeur peut facilement mettre en place un .gitignore global sur ça machine.

Cela s'effectue en 2 étapes:

  1. Création du fichier .gitignore_global:

    Utiliser votre éditeur préférer pour créer un fichier ~/.gitignore_global
    Dans le fichier ajouter les fichiers à ignorer. Par exemple:

    .classpath
    .project 
     
  2. Configuration de git pour prendre en compte le .gitignore global 

    #  git config --global core.excludesfile ~/.gitignore_global

Voir les commentaires

Rédigé par Bliz

Publié dans #Version control

Repost 0

Publié le 16 Août 2013

Apache fournit une lib HttpClient très simple et qui semble assez fréquemment utilisée. C'est d'ailleurs le cas sur mon projet où elle est utilisée pour interagir avec d'autres services webs.

Pour interroger ces services webs nous utilisons simplement l'authentification HTTP basique soit un login/mot de passe.

Le problème est que par défaut HttpClient n'envoie pas l'authentification dans la requête (pour des raisons de sécurité) ce qui donne le callflow suivant:

Client                                         Server
   | ----- HTTP req sans authentification   ----> |
   | <---- HTTP 401 Authentication required ----- |
   | ----- HTTP req avec authentication     ----> |
   | <---- HTTP 200 OK                      ----- |

Evidemment ça n'est pas optimum et on peut facilement envoyer directement l'authentication dans la première requête comme expiqué par Apache (Preemptive authentication): http://hc.apache.org/httpcomponents-client-ga/tutorial/html/authentication.html

Maintenant voyons comment tester tout ça. Première chose il nous faut un serveur HTTP, ça tombe bien il y en a un dans le JDK (package com.sun.net.httpserver):

HttpServer server = HttpServer.create(new InetSocketAddress(8765), 0);
HttpHandler handler = new HttpHandler() {
   @Override
   public void handle(HttpExchange httpExchange) throws IOException {
      String response = "This is OK";
      httpExchange.sendResponseHeaders(200, response.length());
      OutputStream os = httpExchange.getResponseBody();
      os.write(response.getBytes());
      os.close();
   }   
};
HttpContext context = server.createContext("/test", handler);
context.setAuthenticator(new BasicHttpAuthenticator("realm-test") {
   @Override
   public boolean checkCredentials(String authUser, String authPwd) {
      return "bliz".equals(authUser) && "1234".equals(authPwd);
   }
});
server.setExecutor(null);
server.start(); 

Voilà le serveur est prêt pour notre test. Nous avons:

  • un server HTTP
  • un handler qui sert le chemin "/test"
  • un authenticator qui vérifie les login / mot de passe

C'est pas trop mal mais il va falloir compter les requêtes envoyer au serveur pour vérifier qu'on est bien en mode preemptive et qu'on ne reçoit pas un 401 à chaque fois.

On peut donc imaginer introduire un compteur de requête au niveau du HttpHandler et de l'incrémenter dans la méthode handle().

Oui mais voilà comme il y a un Autenticator associé au context la réponse 401 est renvoyé automatiquement par le serveur sans qu'on s'en aperçoive au niveau du handler.

Il nous faut donc gérer l'authentification directement dans le handler sans l'associer au context. Ce qui donne au niveau du handler:

   @Override
   public void handle(HttpExchange httpExchange) throws IOException {
      requests++;
      String response = "";
      if (checkAuth(httpExchange)) {
         response = "This is OK";
         httpExchange.sendResponseHeaders(200, response.length());
      } else {
         response = "Missing or wrong authentication";
         httpExchange.getResponseHeaders().set("WWW-Authenticate", "Basic realm=realm-test");
         httpExchange.sendResponseHeaders(401, response.length());
      }
      OutputStream os = httpExchange.getResponseBody();
      os.write(response.getBytes());
      os.close();
   }

   boolean checkAuth(HttpExchange httpExchange) {
      Authenticator.Result res = auth.authenticate(httpExchange);
      return res instanceof Authenticator.Success;
   }

Ne pas oublier d'enlever la ligne pour ne pas associer d'authenticator au context:

context.setAuthenticator(...)

et de créer l'authenticator au sein du HttpHandler.

Maintenant on voit passer les 2 requêtes dans notre handler et on peut vérifier facilement les requêtes envoyées.

Voir les commentaires

Rédigé par Bliz

Publié dans #Java

Repost 0

Publié le 13 Août 2013

Lors des tests unitaires j'aime bien afficher les logs d'exécution surtout quand ils deviennent complexe et se rapproche (un peu) des tests fonctionels. Et comme sur mon projet nous utilisons Log4J il suffit d'initialiser Log4J pour activer les logs.

Cela se fait simplement en ajoutant une méthode de 2 lignes annotée avec @BeforeClass dans la classe de test:

   @BeforeClass
   public static void initLog() {
       BasicConfigurator.configure();
       Logger.getRootLogger().setLevel(Level.TRACE);
   } 

Voir les commentaires

Rédigé par Bliz

Publié dans #Java

Repost 0

Publié le 12 Août 2013

J'utilise quotidiennement maven et le plus souvent en ligne de commande et s'il y a un reproche qu'on peut faire sur la forme (je ne parle pas du fond et ni de la philosophie maven mais uniquement de la forme), c'est bien que tout cela est terne.

Heureusement il est facile d'ajouter un peu de couleur dans un terminal en fonction les niveaux de logs de la sortie maven. Après quelques recherches je suis tombé sur la définition d'un alias 'mvn' qui ajoute la couleur en utilisant sed avec les codes d'échapement de couleur.

Donc si vous êtes pressés vous pouver l'installer facilement avec la commande suivante:

# curl https://raw.github.com/builddoctor/maven-antsy-color/master/mvn >> ~/.bash_aliases
# . ~/.bashrc

Et voilà c'est tout de suite beaucoup plus gai!

Comme l'idée n'est pas de moi voici où trouver toutes les infos : https://github.com/builddoctor/maven-antsy-color

Sinon j'ai trouvé la sortie un peu trop verte (toutes les lignes INFO sont en vert) et apporté une petite correction sur les lignes en WARNING.

Donc voici ma version qui reste très proche de l'original:

# thanks to:  http://blog.blindgaenger.net/colorize_maven_output.html
# and: http://johannes.jakeapp.com/blog/category/fun-with-linux/200901/maven-colorized
# Colorize Maven Output

alias maven="command mvn"

color_maven() {

maven $* | sed -e 's/Tests run: \([^,]*\), Failures: \([^,]*\), Errors: \([^,]*\), Skipped: \([^,]*\)/Tests run: ^[[1;32m\1^[[0m, Failures: ^[[1;31m\2^[[0m, Errors: ^[[1;33m\3^[[0m, Skipped: ^[[1;34m\4^[[0m/g' \
   -e 's/\(\[WARN\].*\)/^[[1;33m\1^[[0m/g' \
   -e 's/\(\[WARNING\].*\)/^[[1;33m\1^[[0m/g' \
   -e 's/\(\[INFO\].*\)/^[[1;37m\1^[[0m/g' \
   -e 's/\(\[ERROR\].*\)/^[[1;31m\1^[[0m/g' \
   -e 's/\(BUILD FAILURE.*\)/^[[1;31m\1^[[0m/g' \
   -e 's/\(FAILURE!.*\)/^[[1;31m\1^[[0m/g' \
   -e 's/\(BUILD SUCCESS.*\)/^[[1;32m\1^[[0m/g' \
   -e 's/\(SUCCESS.*\)/^[[1;32m\1^[[0m/g' 

}

alias mvn=color_maven

Voir les commentaires

Rédigé par Bliz

Publié dans #Maven

Repost 0

Publié le 8 Août 2013

J'ai souvent besoin d'ouvrir un fichier de log dans less pour comprendre un problème par exemple et puis parfois j'aimerai bien pouvoir suivre l'évolution des logs en temps réel (comme un tail -f). Et bien c'est possible sans quitter less avec la commande <shift>+F:

# less monfichier.log
<shitf>+G // pour aller à la fin du fichier
<shift>+F // pour suivre l'évolution (à la mode tail)
<ctrl>+C // pour arrêter
q // pour quitter 

Voir les commentaires

Rédigé par Bliz

Publié dans #Linux

Repost 0

Publié le 7 Août 2013

Sur mon project nous avons 2 branches: master et dev.

Lors d'un push de master vers origin/master on utilise la commande:

# git push orign master

similairement pour la branch dev.

Comme nous n'avons qu'en seul remote: origin et grâce à la commande

# git config --global push.default current

on peut réduite le push à la commande:

# git push

qui aura pour effet de pousser la branche courante sur le serveur: origin.

C'est pas grand chose mais ça simplifie la vie.

Voir les commentaires

Rédigé par Bliz

Publié dans #Version control

Repost 0