Feb 28 2010

Self-Improvement : [Java] – ClassLoading in depth

As i'm reading a really great book form the series "the pragmatic Bookshelf" called The Passionate Programmer, remiding me of my (not so) early ages or some of my friends like catwell, baal and Tit'Aude.

I figure i would myself have liked a post from one of my favorite blog allowing me to self-improve my pratical knowledge of the world i'm working on, so here we go on the road to a (not so) uncommon Java advanced topic - the ClassLoader. As your humble servant i must, however, apologies because being an expert in many areas (but not this one), i'll join myself to your reading for this great in depth post about class loading in the Java language, brought to you by O'Reilly On Java.

Hope you'll enjoy reading it and (re-)discovering this area.

P.S. i'll soon be going back to Paris, i hope we'll take the time to see each other guys ++


Nov 26 2009

Hibernate 3.5.0 will soon come out

As everybody know the main issue about Java technologies creating web applicates used to be too much XML verbosity. You had to write so much "descriptor files" that any technology (except maybe C++) was way more efficient into creating common websites.

Now i say used to be because of many improvements, considering the well designed way of handling annotation based configuration since Java 1.5 and the many frameworks taking advantages from these features (Struts, Spring etc...). All that was left was a good way of handling Java Persistence without having to write any mapping file or DAO configuration.

Well it may be on the way to be achieved with this new coming version of Hibernate. Hibernate is one of the key-technology for java persistence, but now as of Hibernate 3.5.0 the annotation based branch - Hibernate Annotations - will be integrated by default.

It will drastically improve the beggining of new projects and allow for Java to keep up the pace, and keep up its ability to handle large datasets and distributed environments.


Nov 14 2009

Useful Tips : StringBuilder and Java String Concatenation

As you certainly now, string concatenation in Java can be achieved using the "+" operator like that :

  1.  
  2. String parText = "This " + "is " + "a full text";
  3. parText = parText + " in a new String object";
  4.  

But each time you try to concat the string in a new line a new String object is created, therefor the String concatenation may end up as being a performance issue.

To fix this we use two types of objects : StringBuilder and StringBuffer. Then you can translate your String (e.g. a SQL Query) into :

  1.  
  2. StringBuilder stb = new StringBuilder();
  3. stb.append("This ");
  4. stb.append("is ");
  5. stb.append("a full text");
  6. stb.append(" in a new String object");
  7.  

The main differences between StringBuilder and StringBuffer is that the last one is synchronized and may be used in a multi-threaded context while the other one won't have any type of synchronization. Luckily when you try to concatenate multiple string items, Eclipse IDE, (if you ask it by typing Ctrl + 1), will ask you if you need to translate it to a StringBuilder object :

StringBuilder

But nowadays, if you're careful and know what you're doing, you can avoid typing this kind of "ultra verbose" way of dealing with strings. Actually since Java 1.5 String concatenations when they're done on a whole line, are directly translated by Java Compiler, but if you jump onto another line and keep on concatenating the same String, optimization will be lost. E.g. :

  1.  
  2. // this way
  3. StringBuilder stb = new StringBuilder();
  4. stb.append("This ");
  5. stb.append("is ");
  6. stb.append("a full text");
  7. stb.append(" in a new String object");
  8. // and this one are equivalent
  9. String parText = "This " + "is " + "a full text" + " in a new String object";
  10.  
  11. // but this one isn't :
  12. String parText2 = "This " + "is " + "a full text";
  13. parText2 = parText2 + " in a new String object";
  14.  


Oct 30 2009

Design Pattern : Proxy

Continuons un peu notre tour d'horizon avec le design pattern Proxy. Un proxy est, de par la nature du mot, souvent une interface entre plusieurs composants, servant de pont entre ceux-ci.

Avec un Proxy, on peut contrôler des objets, tout en manipulant des "remplaçants". Un exemple souvent pris dans la littérature est celui d'une image à charger. Si l'on cherche à peindre l'image directement (surtout si c'est une grosse image), on risque de faire ramer notre application en monopolisant son processus principal, il est donc préférable de mettre un petit "Loading image ..." et faire tourner le chargement en tâche de fond.

Un exemple plus explicite consiste en Java-RMI (Remote Method Invocation) à utiliser un "représentant" local pour manipuler un objet distant, la technologie se chargeant alors de la communication et de la transmission des exceptions.

Pour ceux qui aimerait plus d'information et une implémentation explicite de ce pattern, voilà un petit lien avec l'exemple des images (ImageProxy) implémenté : http://perfectjpattern.sourceforge.net/ et un mini-framework pour mettre en application ce design.


Oct 27 2009

Advanced use of Eclipse for Java

Eclipse is a wonderful tool when you're developing big projects using the Java programming language, but it's easy to just see the monster as one big, buggy, slow, heck of a program and just enjoy a simple text editor with a few tweakings for syntax highlighting.

But as you come to use it on a regular basis a few tricks comes, almost naturally, to help you get more efficient. I'm just going to present a few that i use regularly, and that makes me keep using Eclipse :

  • Auto-completion tool (+ with javadoc) : Ctrl + space

I won't go presenting this one, everyone knows, but you just have to test it to be able to savour it the way it should.

  • Open type (class, Interface etc...) search engine : Ctrl + shift + T (Cmd + shift + T under MacOsX)

openType

  • Quick refactor : Alt + shift + R

refactor

  • Delete a line : ctrl + D
  • Delete a line, word by word (with camelCase handling)

Allows you to delete Words step by step : e.g. parRotSubscription will become  parRot

  • Change method Signature  : Alt + shift + C

signature

  • Usage search of a method/attribute : Ctrl + Shift + G

You just have to select the attribute or method, and it will search for you where this object is used.

  • Show the type hierarchy : F4

Shows the full hierarchy of the class/interface, showing ancestors and descendents.

call

  • Organize Imports : Ctrl + Shift + O

This is, in my view, the most useful function : it allows you to remove un-used imports (e.g. import java.io.IOException;) and add the one you need "precisely" so that you don't go adding import java.*

  • Comment selected lines : Ctrl + shift + C

The last one to comment full paragraphs and lines of code, and un-comment them when you need to.

I know that many of so-called geeks are able to make vim or emacs do it all, but the refactor functions of the jdt Core of Eclipse makes it so easy, it's just a burden sometimes to have to use other IDE.


Oct 2 2009

Better web applications

Petit article sur un débat d'idées assez intéressant autour des Applications web et du meilleur framework/langage a utilisé. Je suis en simple spectateur compte tenu de mon poste actuel (très peu orienté Web) mais la conclusion sur Zope/Plone est assez intéressante et je ne manquerai pas de tester les deux lors de mes prochains projets Web.

J'apprécie surtout la conclusion sur Django et les URL en Regex que j'avais trouvé très puissante à l'époque, mais qui sont un calvaire à prendre en main et à débugger (comme toute les Regex...).

Je laisse le troll là où il a commencé pour moi sur le site :

http://linuxfr.org/~ploum/23607.html où déjà un certain nombre de participants se sont bien tapés dessus.

Et enfin le screen cast originel venant du JPL : Jet Propulsion Laboratory de la Nasa et plus précisemment de Sean Kelly dont je trouve les videos assez facile d'accès et stimulantes  !

Enjoy.

++


Sep 5 2009

Expression régulières Vs State Machines

Les expressions régulières sont un outil très pratique, voire même la martingale dans beaucoup de situations. Seulement dans le cas (improbable) où vous deviez reprendre un code un peu comme celui là :

  1. public static boolean isPrime(String number) {
  2. // compiling the regexp
  3. Pattern p = Pattern.compile("/^1?$|^(11+?)\1+$/");
  4.  
  5. // creating the matcher
  6. Matcher m = p.matcher(number);
  7.  
  8. boolean isPrime = m.find();
  9.  
  10. return isPrime;
  11. }

Il n'y a que deux solutions vraisemblablement utilisée, la première consistant à forwarder le boulot à quelqu'un de clairement "plus compétent" que vous (genre un stagiaire...), soit à tout ré-ecrire de manière plus "compréhensible" (où en gros vous allez refaire le travail, seulement comme c'est vous qui allez le faire la regexp sera "nécessairement plus claire" que celle de votre prédécesseur...).

Alors je dis NON, ce n'est pas une fatalité... lol

Le problème est simple, les regexp sont souvent difficilement maintenables. Et la solution est encore plus simple, arréter d'en faire pour n'importe quoi, surtout quand elles ne sont pas nécessaires, et où elles compliquent la tâches plus qu'autre chose... Personnellement j'ai fini par être convaincu qu'il est souvent plus simple de faire une simple machine à états, mais ne vous inquiétez pas je vais m'expliquer par un petit exemple...

Certains *******, de la race de ceux qui adorent dire "mais pourtant ça marche dans mon Excel", adorent donner comme source de donnée pour des transferts des fichiers CSV (Comma Separated Values) suivant un format très drole. Le plus ironique j'ai trouvé avait pour habitude de donner des lignes comme ça :

"Ccy Name, For the current date", 28-Sep-2009, 456.75, (248.56), "134,546,678.15"

Avec la virgule comme séparateur de colonne, des parenthèses pour représenter des nombres négatifs, et des virgules (toujours !!) comme séparateur des milliers, et un point pour les nombres à virgules... Mais bien sûr comme ça pose parfois des problèmes d'avoir pleins de virgules comme ça, Excel a décidé de mettre des guillemets autour des chiffres à problèmes (donc pas tout le temps).

Alors comment vous parseriez cette ligne avec une Expression régulière ?

Je ne vous dirait pas la regexp que j'ai obtenu pour des trucs pareils.... mais j'attends avec impatience vos commentaires, si le coeur vous en dit ;-)

Donc finalement lors du développement du parseur, j'ai finalement conçu une méthode public String trashAnyUnWantedComma(String line) pour gérer ces cas pourris :

  1. public String trashAnyUnWantedComma(String line) {
  2.                 StringBuilder result = new StringBuilder();
  3.                 boolean commaSeparatedFieldReached = false;
  4.  
  5.                 for (char c : line.toCharArray()) {
  6.                         if (c == '"') {
  7.                                 commaSeparatedFieldReached =
  8.                                         (commaSeparatedFieldReached)? false : true;
  9.  
  10.                         } else if (commaSeparatedFieldReached) {
  11.                                 if (c == ',') {
  12.                                         continue;
  13.                                 }
  14.                         }
  15.                         result.append(c);
  16.                 }
  17.                 return result.toString();
  18. }

ce qui avec la bonne dose de commentaire, permet d'avoir une fonction simple qui fait le travail et qui reste compréhensible.

Voilà, KIS : Keep It Simple


Jul 18 2009

Modélisation de la C.A.F par des Threads asynchrones

Sur une idée originale de Divarvel, qui a un jour twitté que le meilleur exemple pour décrire les Threads asynchrones était la C.A.F... et surtout grâce aux C.A.F de Loire-Atlantique et de Moselle qui pour une fois m'ont donnée un bon exemple que je vais retranscrire de la manière la plus fidèle possible.

!!!! CET ARTICLE N'EST SURTOUT PAS UN PAMPHLET CONTRE LES C.A.F. QUI FONT UN TRES BON TRAVAIL, C'EST JUSTE POUR L'EXEMPLE PEDAGOGIQUE ET TOUTES RESSEMBLANCES AVEC DES SITUATIONS EXISTANTE SONT BIEN SÛR TOTALEMENT INVOLONTAIRE !!!!

Alors tout d'abord on va définir ce qu'est une C.A.F. (ou Caisse d'Allocation Familiale). Au fond c'est une organisme conçu pour aider, en versant de l'argent, les personnes qui en ont besoin, mais ce n'est pas cette définition qui nous intéresse, plutôt une définition en terme d'objet :

  1. import java.math.BigDecimal;
  2.  
  3. public interface CAF {
  4.  
  5.         /**
  6.          * Pour accéder au dossier sur internet
  7.          *
  8.          * @param numeroAllocataire
  9.          * @param mdp
  10.          */
  11.         public void accesDossierAllocataire(Integer numeroAllocataire, String mdp);
  12.  
  13.         /**
  14.          * Pour parler à un conseiller de la C.A.F. de son dossier par téléphone
  15.          *
  16.          * @param numeroAllocataire
  17.          * @param mdp
  18.          */
  19.         public void accesConseillerCAF(Integer numeroAllocataire, String mdp);
  20.  
  21.         public BigDecimal getAllocations(...); // BigDecimal ... un peu exagéré
  22.  
  23.         public void recevoirDossierTransféré(Dossier dossierAllocataire);
  24.  
  25.         public Dossier envoyerDossierToCAF(String autreCAF);
  26. }

Ainsi voilà l'interface qui caractériserait une C.A.F, (en un peu simplifiée... mais le coeur y est),  bien sûr l'implémentation des méthodes est propre à chaque C.A.F., c'est d'ailleurs pour ça qu'elles ont toutes des sites internet différents...  Alors prenons 3 entités différentes, un étudiant qui déménage de Nantes vers Metz, la caf de loire-atlantique, la caf de la moselle et voyons comment ils vont interagir ensemble :

L'étudiant, tout d'abord, il est bête et feignant, il ne sait que déménager et emménager, mais il pense quand même à faire ses déclarations de C.A.F :

  1. public class Etudiant{
  2.  
  3.         public void demenage(){
  4.                 // casse des meubles
  5.                 ...
  6.                 // oublie des affaires
  7.                 ...
  8.                 // fait chier ses parents...
  9.                 ...
  10.                 // ah oui !! et appelle sa CAF pour dire qu'il déménage
  11.                 appellerCAFpourDemenagement();
  12.         }
  13.  
  14.         public void emmenage(){
  15.                 // recolle les meubles
  16.                 ...
  17.                 // oublie des affaires
  18.                 ...
  19.                 // fait chier ses parents...
  20.                 ...
  21.                 // et fait chier son proprio à lui faire remplir le dossier de CAF
  22.                 // envoie enfin son dossier :
  23.                 envoyerDossierCourierANouvelleCAF();
  24.                 // oufff... re-glandouille
  25.                 this.wait();
  26.         }
  27. }

Bon mais le problème c'est plus l'implémentation du coté des C.A.F qu'on assimilera à des Singletons tout simplement parce qu'elles sont uniques et indivisibles par région (enfin tout comme un singleton quoi !) :

Donc bien sûr on a le début suivant :

  1. import java.math.BigDecimal;
  2.  
  3. public class CafMoselle implements CAF {
  4.  
  5.         private static CafMoselle instance = null;
  6.         /**
  7.           * Petit point de technique, les map sont donc des tables de hashages
  8.           * mais la LinkedHashMap est une structure qui contient a la fois une HashMap et une LinkedList
  9.           * ainsi on peut récupérer (si on fait une boucle sur les clés par exemple)
  10.           * les éléments dans l'ordre dans lesquels on les as insérés (ce qui n'est pas le cas avec une HashMap classique)
  11.           *
  12.           */
  13.         private Map<String, String> allocataires = new LinkedHashMap<String, String>();
  14.  
  15.         private CafMoselle(){
  16.         }
  17.  
  18.         public static CafMoselle getInstance(){
  19.                 if(instance == null)
  20.                         instance = new CafMoselle();
  21.                 return instance;
  22.         }

avec plusieurs moyens de discuter avec sa CAF, le téléphone et internet, mais tout d'abord la CAF reçoit le dossier :

  1.        private void recevoirDemandeCourrier(Dossier courrier) throws InterruptedException{
  2.                 // exemples de premières synchronizations, pour faire des interruptions volontaires (en ms)
  3.                 synchronized(this){
  4.                         this.wait(10000); // petite pause de reflexion ...
  5.                 }
  6.  
  7.                 System.err.println("humm faudrait faire quelque chose...");
  8.  
  9.                 synchronized(this){
  10.                         this.wait(100000); // un peu plus grosse pause de reflexion
  11.                 }
  12.                 // et si l'étudiant était déjà allocataire ??
  13.                 if(!allocataires.containsKey(courrier.getNumeroSecuriteSociale()));
  14.                         traiterLeDossier(courrier);
  15.         }

Le synchronized permet ici de mettre un bout de code en tant que section critique, dans le cadre d'une exclusion mutuelle. Ainsi avec le synchronized ici, l'objet courant this, n'est pas accessible par quelqu'un d'autre pendant toute la durée de l'exécution du code entre accolades.

Mais attention !!!! Le synchronized n'est pas applicables à des types natifs (int, double, etc...) il n'est applicable qu'a des objets car les objets possèdent des méthodes wait notify/notifyAll, utilisée pour gérer les accès. !!!!

Mais c'est déjà suffisamment d'émotions, pour cet article, donc la suite au prochain épisode, vous saurez comment le dossier sera traité, et les deadlocks/livelock qui peuvent arriver.

++