Il y a 9 ans -

Temps de lecture 5 minutes

Revue de Presse Xebia

Revue de Presse Xebia
La revue de presse de l’actualité Java/J2EE hebdomadaire proposée par Xebia.

Actualité éditeurs / SSII

Le coin de la technique

Evènements de notre communauté en France et à l’étranger

Actualité éditeurs / SSII

Sortie de RabbitMQ 2.0

La sortie de la version 2.0 du serveur de messaging AMQP RabbitMQ vient d’être annoncée ici.
Cette release majeure vient avec une refonte importante et son lot de nouveautés :

  • Une refonte de la gestion de la persistence permettant une alternative au moteur de persistence embarqué. Il sera possible de développer un support pour une base de données relationelle ou NoSQL ou tout autre data store.
  • Le support de différents protocoles de messaging : AMQP (0-8 et 0-9-1), XMPP, STOMP, HTTP, SMTP… Il sera aussi possible d’ajouter de nouveaux protocoles à l’aide d’extensions.
  • La mise en place d’une infrastructure ayant pour but de simplifier le développement d’outils pour la gestion et le monitoring de RabbitMQ.
  • Une amélioration de la gestion des plugins (il n’est plus nécessaire de compiler les plugins, une version pré-compilée peut être directement chargée par RabbitMQ).

SpringSource qui a récemment racheté RabbitMQ (nous vous en avions parlé ici) propose de son côté un template reprenant les principes des templates jdbc, hibernate, jms ou encore LDAP encapsulant le client Java d’AMQP. Les utilisateurs habitués à JmsTemplate retrouveront donc leurs repères en utilisant l’AmqpTemplate du projet spring AMQP.

SpringSource/VMWare continue donc de faire évoluer son portefeuil de produits avec cette évolution majeure de RabbitMQ, qu’il considère comme une pièce essentielle à sa stratégie de développement du Cloud Computing (voir cet article de Rod Johnson).

Le coin de la technique

Gestion automatique des ressources dans Java7 (ARM)

Java7 suit son petit bonhomme de chemin sans qu’on ait encore une bonne visibilité sur la date de sortie officiel. Le build 105 de la version actuelle propose une nouvelle fonctionnalité très intéressante qui devrait facilité la vie de chaque développeur: l’Automatic Resource Management.

L’idée, proposée par Joshua Bloch depuis quelques années déjà, consiste à améliorer la fermeture des ressources sous la forme d’une clause try-with-resources. Actuellement lorsqu’on manipule une ressource, par exemple un InputStream, la façon la plus propre ressemble à ceci:

public void copyFile(File in, File out) {
    FileInputStream fis = null;
    FileOutputStream fos = null;
    try {
       fis = new FileInputStream(in);
       fos= new FileOutputStream(out);
       // Lire le fichier in et écrire dans le out
       ...
    }  catch (Exception e)  {
       ...    
    } finally {
      close(fis);
      close(fos);
    }
}

private void close(Closeable closeable){
    if(closeable != null) {
        try{
           closeable.close();
        } catch(IOException e){...}
    }
}

Ce code devient vite très verbeux et répetitif car beaucoup de vérifications doivent être faites pour s’assurer de la possibilité de fermer la ressource. La solution pour simplifier cela est de déléguer la fermeture du flux à l’aide du try:

public void copyFile(File file) {
    try(FileInputStream fis=new FileInputStream(in); 
        FileOutputStream fos=new FileOutputStream(out)) {
       // Lire le fichier in et écrire dans le out
       ...
    } 
}

Le code gagne énormément en visibilité, les tests pour savoir si la ressource est null ou si la fermeture s’est bien déroulée sont gérés en interne de la JVM. A noter que pour être fermées les ressources devront étendre une nouvelle interface AutoCloseable.

S’il existe un certain consensus autour de l’utilité de cette évolution, il demeure encore un petit débat sur la partie catch des exceptions. Sans rentrer dans les détails, les exceptions levées pendant la fermeture d’une ressource annihilent celles levées dans le bloc try, ce qui en général est préférable mais du coup peut aussi masquer des exceptions importantes pour l’analyse du problème.

Evènements de notre communauté en France et à l’étranger

Google et les brevets

Semaine chargée pour Google:

  • InfoQ nous annonce que le MPEG LA a décidé de continuer à ne pas réclamer de royalties pour les videos encodées en H.264 et distribuées gratuitement aux utilisateurs. Seules les plateformes vendant des vidéos sont, elles, toujours soumises à taxation. C’est donc une réponse à Google qui avait il y a quelques temps annoncé WebM, un codec vidéo semblable au H.264 mais plus libre et débarrassé des problèmes de brevets et de royalties qui entravent ce dernier. Si InfoQ ne voit pas trop de problèmes à continuer d’utiliser H.264, ce n’est pas du tout l’avis de Mike Shaver ingénieur haut gradé chez Mozilla et qui rappelle que les logiciels permettant de produire ou de consommer ces vidéos devront eux toujours s’acquitter d’une licence. La bataille entre WebM et H.264 ne fait donc que commencer.
  • Ensuite, c’est Paul Allen, le co-fondateur de Microsoft, qui attaque Google et nombre de ses petits camarades (AOL, Yahoo, Facebook) pour avoir enfreint 4 brevets détenus par sa compagnie « Interval Licensing ». Le blog Digits du Wall Street Journal s’est penché sur 2 de ces brevets. Nous vous déconseillons fortement la lecture de son analyse si vous avez réalisé quoi que ce soit dans l’informatique ces 10 dernières années. En effet, vous risquez de ne plus trouver le sommeil en vous rendant compte que vous enfreignez sans doutes, vous aussi, nombre de brevets !
  • Et pour finir sur Google et les brevets, vous vous souvenez des récentes poursuites engagées par Oracle concernant Java et Android. Google vient de riposter, en annoncant qu’aucun de ses employés ne participera à JavaOne cette année. Pour ceux qui voulaient échanger avec les employés de Google, il semble que c’est plus tard dans l’année, à Devoxx, qu’il faille se rendre. Mais rassurez vous, il y aura quand même de l’ambiance à JavaOne: James Gosling, père de Java, demande sur son blog à toute personne y assistant de porter un TShirt arborant le slogan « Java just Free it ». Si cette idée ne risque pas trop de faire bouger Oracle, elle devrait quand même apporter sa dose de fun à l’évènement !

Commentaire

12 réponses pour " Revue de Presse Xebia "

  1. Publié par , Il y a 9 ans

    Salut,

    Je ne suis pas vraiment d’accord avec votre code pour la fermeture des ressources. Il y a une duplication de la gestion des exceptions, et surtout une obligation de les traiter (si on laisse remonter les exceptions cela peut poser des problmes sur les fermetures : essayez tout simplement de code la mme mthode en laissant remonter les exceptions en cas d’erreur).

    Je lui prfre de loin l’utilisation d’un try/finally par ressources, avec un try/catch indpendant (et optionnel), mme si cela s’avre un peu plus verbeux :

    public void readFile(File in, File out) {
    	try {
    		FileInputStream fis = new FileInputStream(in);
    		try {
    			FileOutputStream fos = new FileOutputStream(out);
    			try {
    				// Lire le fichier in et crire dans le out
    			} finally {
    				fos.close();
    			}
    		} finally {
    			fis.close();
    		}
    	} catch (IOException e) {
    		...
    	}
    }
    

    D’ailleurs c’est en partie la solution utilise par le try-with-resources…

    Il est vrai qu’avec ce code, si une exception surgit dans le bloc finally on peut « perdre » la trace d’une autre exception remonte dans le bloc try correspondant, et donc perdre une information qui pourrait tre importante… mais ce cas se rvle quand mme assez rare.

    Toutefois, contrairement ce qui est dit, ce problme n’existe plus avec le try-with-resources, car il s’occupe de rcuprer les exceptions « perdus » et les rajoutent au stacktrace via une nouvelle mthode de Throwable : addSuppressedException().

    a++

  2. Publié par , Il y a 9 ans

    @adiGuba

    Merci pour ce commentaire et pour les billets que vous avez publis sur ce sujet sur votre blog.

    A mon sens les, les dfaut que vous annoncez me semblent pour la plupart des cas excusables (visibilit des variables, masquage de l’exception d’origine (en fonction de votre code)…). Dans l mesure ou la gestion de ce genre de ressources fait l’objet d’une mthode spcifique, je ne suis pas prt sacrifier la lisibilit du code de la sorte. Tout a pour dire, que j’utilise rgulirement la solution propose par Guillaume dans cet article. Au final, les deux solutions ne sont pas si loignes.

    Quoi qu’il en soit, s’il on revient au coeur du sujet, il est clair que la solution jdk7 est nettement plus simple d’utilisation. Pourtant, il faut bien admettre qu’il ne s’agit d’un suc syntaxique … le glas de la fin des problmes de ressources n’a pas encore sonn :)

    Au plaisir de lire vos prochains articles.

    Erwan (Xebia)

  3. Publié par , Il y a 9 ans

    @adiGuba

    Merci pour cette prcision sur le addSuppressedException(), en effet a devrait permettre d’avoir une bonne lisibilit sur les causes d’une exception.

    Pour le code Java actuel, je suis partag, je pense que a va dpendre des use cases.
    Quoiqu’il en soit cet exemple tait surtout pour illustrer le ct verbeux et certainement pas la seule et unique faon de faire.

    (dsol Erwan nos rponses se sont croiss :) )

    (Guillaume de Xebia)

  4. Publié par , Il y a 9 ans

    @Erwan : Les dfauts que j’indique sont excusables dans l’tat actuelle, mais le try-with-resources a l’avantage de les corriger ;)

    @Guillaume : En fait ce qui me gne avec cette solution c’est qu’on est forc de traiter les exceptions. On ne peut pas les ignorer et les laisser remonter sans modifier grandement le code, moins d’ignorer les exceptions lors de la fermeture :(

    a++

  5. Publié par , Il y a 9 ans

    Le point cl c’est le « Throwable.addSuppressedException() » (1).

    A partir du moment o il n’y a plus d’exception masque, chaque dveloppeur peut choisir la forme qui lui convient.
    Celle du try-with-ressource ou celle des try finally imbriqus.
    Cest une superbe progression de Java.

    Deux remarques :
    1)Les interfaces et classes jdbc du java.sql nimplmentent pas AutoCloseable.
    2)Je prfre la solution try finally qui prsente pour moi lavantage de remonter des exceptions types. Disons quavec quen traitant avec un FileOuputStream je suis certain de nattraper que de(s) IOException. Alors quavec le try-with-ressource jai limpression de pouvoir attraper aussi une Exception car cest ce que lance AutoCloseable. Ai-je bien compris ?

    En reformulant la question, une mthode copyFile utilisant try-with-resource se dclare-t-elle

    public void copyFile(File file) throws IOException

    ou bien

    public void copyFile(File file) throws IOException, Exception

    ?

    (1) : http://download.java.net/jdk7/docs/api/java/lang/Throwable.html#getSuppressedExceptions

  6. Publié par , Il y a 9 ans

    @Stephane : Les suppressed-exceptions ne seront gres que par le try-with-resource. Ce dernier gnre en fait un try-finally, donc il n’y a plus de raison de l’utiliser…

    Concernant tes deux remarques :

    1) Les interfaces de JDBC devrait implmenter AutoCloseable dans JDBC 4.1 (mais on ne sait toujours pas si ce dernier sera prsent dans Java 7 :( )

    Au pire on pourra passer par une mthode utilitaire qui renverrait une instance d’AutoCloseable :

    Connection con = …
    try (Utils.autoCloseable(con)) {
    // …
    }

    2) Chaque classe qui implmente AutoCloseable peut modifier le type de l’exception remonte par la mthode close(), ou mme la supprimer. Le try-with-resource s’adapte donc bien l’exception prcise (donc on n’est pas polluer par des throws Exception inutile)

    a++

  7. Publié par , Il y a 9 ans

    @Stphane : si ca peut te rassurer, la mthode copyFile() ressemblerait ceci (test l’instant sur le dernier build du jdk7) :

    	public void copyFile(File in, File out) throws IOException {
    		try (FileInputStream fis = new FileInputStream(in);
    		     FileOutputStream fos = new FileOutputStream(out) ) {
            	        // Lire le fichier in et crire dans le out
    		}
    	}
    

    a++

  8. Publié par , Il y a 9 ans

    @adiGuba

    « Les suppressed-exceptions ne seront gres que par le try-with-resource. Ce dernier gnre en fait un try-finally, donc il n’y a plus de raison de l’utiliser… »

    Jai limpression que le problme a t pris lenvers.
    Le vritable problme ce sont justement ces exceptions masques, ce sont elles qui obligent dinterminables try/catch/finally, contenants de nombreux ifelse, tout cela pour ne pas perdre la premire exception, celle qui est lorigine de toutes les autres et qui contient le message derreur qui compte.

    Sils avaient fait que la JVM gre elle-mme getSuppressedExceptions, ou plutt getMasked() le problme serait dfinitivement rsolut.

    AutoCloseable naurait t quune facilit de plus, alors que l cest la finalit.

    De plus, nous obtenons des exceptions qui deviennent Mutable, lexception de setStackTrace() qui est limit, elles ne ltaient pas.

  9. Publié par , Il y a 9 ans

    @adiGuba

    De tout ce que j’ai vu dans le framework Spring, c’est que les exceptions lors de fermeture de ressource sont systmatiquement ignores et logges en DEBUG (voir TRACE).

    De mon point de vue je ne vois pas de raison de faire remonter une exception d’un close(). Et en JDK 6 si on perd l’exception d’origine, c’est contre productif.

    Dans le cas de fichier, il suffit de « commiter » l’criture par un flush() dans le try{} pour ne plus avoir se soucier du close().

  10. Publié par , Il y a 9 ans

    Pour ceux qui ne veulent pas attendre Java 7, il y a Lombok (un « annotation processor compiler plugin » pour javac) et son annotation @Cleanup. Petite demo:

    Pur Java:

    import java.io.*;
    
    public class CleanupExample {
      public static void main(String[] args) throws IOException {
        InputStream in = new FileInputStream(args[0]);
        try {
          OutputStream out = new FileOutputStream(args[1]);
          try {
            byte[] b = new byte[10000];
            while (true) {
              int r = in.read(b);
              if (r == -1) break;
              out.write(b, 0, r);
            }
          } finally {
            out.close();
          }
        } finally {
          in.close();
        }
      }
    }
    

    Avec Lombok:

    import lombok.Cleanup;
    import java.io.*;
    
    public class CleanupExample {
      public static void main(String[] args) throws IOException {
        @Cleanup InputStream in = new FileInputStream(args[0]);
        @Cleanup OutputStream out = new FileOutputStream(args[1]);
        byte[] b = new byte[10000];
        while (true) {
          int r = in.read(b);
          if (r == -1) break;
          out.write(b, 0, r);
        }
      }
    }
    

    Et voil, sans les mains. Et il y a d’autres petites ppites dans Lombok.

  11. Publié par , Il y a 9 ans

    @Stephane : Il y a une discussion sur l’intgration de cela automatiquement dans le try/finally, mais cela pose un problme de compatibilit.

    Regarde ce code :

    try {
    	throw new A();
    } finally {
    	throw new B();
    }
    

    Quel est l’exception qui doit tre remonte ? Et quel est celle qui doit tre ajout dans les « suppressed-exceptions » ?

    La logique voudrait qu’on remonte A en cachant B, car A est l’exception d’origine, mais on obtient alors un comportement totalement diffrent de ce qui est fait actuellement (seul B est remonte)
    Il faudrait faire l’inverse pour rester compatible, mais on obtient alors l’inverse de ce qui est souhait…

    Mais en fait, ce problme se pose principalement sur la gestion des ressources. Je ne vois pas beaucoup de cas o l’on a besoin de traiter des exceptions dans un finally.

    Enfin, les exceptions ne sont pas mutable. La mthode initCause() permet dj de modifier le stacktrace…

    @Sebastien : La plupart du temps le close() ne gnrera pas d’exception (et du coup les deux solutions ne posent aucun problme).

    Mais lorsqu’on utilise des flux buffris ou un peu plus volu, il est possible que le close() crivent des donnes sur le disque. Dans ce cas l ignorer l’exception pourrait poser quelque problme car on ne pourra pas dtecter les erreurs d’criture.

    Imagine un code comme celui-ci qui dplace un fichier (copie puis suppression du fichier d’origine) :

    copyFile(a, b);
    a.delete();
    

    En cas d’erreur lors du close() pour X raison, le fichier peut tre corrompu.
    En ignorant l’exception on continuera normalement en supprimant notre fichier source…

    Avec le code de l’article on ne peut pas dtecter cela programmatiquement.
    Avec le pattern d’un try/finally par ressource on recevra bien l’exception.

    a++

  12. Publié par , Il y a 9 ans

    @adiGuba

    Je suis bien d’accord que si le close() modifie l’tat de la ressource (flush du buffer) alors une exception dans le close() doit tre remonte et le traitement interrompu. D’o ma prcision sur l’appel de flush().

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Nous recrutons

Être un Sapient, c'est faire partie d'un groupe de passionnés ; C'est l'opportunité de travailler et de partager avec des pairs parmi les plus talentueux.