jeudi 14 mars 2013

svnant, svnkit & subversion 1.7.x

Voici un topo rapide pour faire fonctionner svnant avec subversion 1.7.x

Le truc c'est d'utiliser svnant avec svnkit, mais la nouvelle version de svnkit, pas celle fournie avec svnant.

1°) Télécharger la dernière version de svnant :
http://subclipse.tigris.org/svnant.html
et la dézipper dans un répertoire, appelons-le SVNANT_HOME

2°) Il faut utiliser la dernière version de svnkit
http://svnkit.com/download.php
et la dézipper dans un répertoire, appelons-le SVNKIT_HOME


3°) Dans votre build.xml, définir le classpath et les tâches svn :


<path id="path.svnant">
 <fileset dir="${SVNANT_HOME}\lib" includes="**/*.jar" >
  <exclude name="svnkit.jar"/>
  <exclude name="ganymed.jar"/>
 </fileset>
 <fileset dir="${SVNKIT_HOME}\lib" includes="**/*.jar" />
</path>
<typedef resource="org/tigris/subversion/svnant/svnantlib.xml" classpathref="path.svnant" />


Remplacer ${SVNANT_HOME} et ${SVNKIT_HOME} par vos propres répertoires.
Remarquer la suppression de svnkit et ganymed.jar fourni avec svnant.

4°) On peut utiliser les tâches svn, par exemple récupérer le dernier numéro de révision du répertoire courant  :


<target name="revision">
<svnSetting
 svnkit="true"
 javahl="false"
 id="svn.settings"
/>
<svn refid="svn.settings" >
<wcVersion path="." />
</svn>
<echo message="Rev: ${revision.max}" />
</target>


5°) Soit le build.xml total :


<?xml version="1.0"?>
<project name="svnant-test" basedir="." default="revision">
<path id="path.svnant">
 <fileset dir="C:\Apps\svnant-1.3.1\lib" includes="**/*.jar" >
  <exclude name="svnkit.jar"/>
  <exclude name="ganymed.jar"/>
 </fileset>
 <fileset dir="C:\Apps\svnkit-1.7.8\lib" includes="**/*.jar" />
</path>
<typedef resource="org/tigris/subversion/svnant/svnantlib.xml" classpathref="path.svnant" />

<target name="revision">
<svnSetting
 svnkit="true"
 javahl="false"
 id="svn.settings"
/>
<svn refid="svn.settings" >
<wcVersion path="." />
</svn>
<echo message="Rev: ${revision.max}" />
</target>
</project>

mardi 26 février 2013

PayPal Instant Payment Notification (IPN) simulator

Je suis en train de mettre en oeuvre une solution de payement PayPal pour le site de calcul d'ensoleillement heliorama.com.
L'idée est de faire deux types de comptes utilisateurs : un gratuit et un payant.

Le payement se fait par des boutons PayPal et j'utilise l'Instant Payment Notification (IPN) pour activer le compte une fois le payement effectué.

IPN est un service asynchrone qui nous envoie des messages sur un listener pour notifier des évènements PayPal (payement en cours, payement effectué, remboursement etc.). Une bonne source d'information est l'IPN Guide de PayPal.

Donc, après avoir implémenté une servlet comme listener, j'utilise l'IPN Simulator de PayPal Sandbox pour vérifier son fonctionnement.

L'objectif est donc que le service PayPal accède en HTTP à mon poste de développement.
Il a fallu pour cela effectuer un translation de port NAT sur la box de mon FAI.
port externe 8080 --> @IPposteDev port interne 8080

Sauf que, malgré ce paramétrage, l'IPN Simulator donne l'erreur :

IPN delivery failed. Unable to connect to the specified URL. Please verify the URL and try again.

La solution, non documentée à ma connaissance, est que l'IPN Simulator ne fonctionne qu'avec le port HTTP par défaut : 80. La translation NAT est donc :
       port externe 80 --> @IPposteDev port interne 8080


lundi 25 février 2013

Génération Schéma Hibernate Annotation avec JNDI

Hiers, je suis tombé sur un os :
Pour le site de calcul d'ensoleillement sur www.heliorama.com, la gestion de la persistance objet est faite par Hibernate, avec une configuration par Annotation et la définition de la datasource en JNDI.

La méthode classique pour générer un schéma DDL à partir de la config annotation est d'utiliser la tâche ant hibernatetool, de cette façon (QUI NE FONCTIONNE PAS SI LA DATASOURCE EST EN JNDI):


<hibernatetool destdir="./generated">
 <classpath>
  <path location="." />
  <path location="../build/classes" />
 </classpath>
 <annotationconfiguration configurationfile="../WebContent/WEB-INF/hibernate.cfg.xml"/>
 <hbm2ddl export="false" outputfilename="sql.ddl"/>
</hibernatetool>

A ce propos, il assez sioux de faire fonctionner cette tâche, étant donné qu'il faut récupérer tout les jar nécessaires. Pour ma part, j'ai décidé d'allez assez vite en ajoutant tout les jar du plug-in hibenate-tool eclipse (plugins/org.jboss.tools.hibernate4_0_3.5.1.v20130102-1835-H100-Final) et tous les jar de ma webapp.

On défini un classpath de cette façon :


<path id="toolslib">
<fileset dir="lib" includes="**/*.jar"/> <!-- copie du plug-in hibernate-tool dans un répertoire lib au même niveau que le build.xml -->
<fileset dir="../WebContent/WEB-INF/lib" includes="**/*.jar"/> <!-- webapp -->
</path>

Puis on l'utilise dans une taskdef :

<taskdef name="hibernatetool"
         classname="org.hibernate.tool.ant.HibernateToolTask"
         classpathref="toolslib" />

Ce qui donne le fichier de build ant :

<project name="MyProject" basedir="." default="default">
<path id="toolslib">
<fileset dir="lib" includes="**/*.jar"/>
<fileset dir="../WebContent/WEB-INF/lib" includes="**/*.jar"/>
</path>

<taskdef name="hibernatetool"
         classname="org.hibernate.tool.ant.HibernateToolTask"
         classpathref="toolslib" />

<target name="default">
<hibernatetool destdir="./generated">
 <classpath>
  <path location="." />
  <path location="../build/classes" />
 </classpath>
 <annotationconfiguration configurationfile="../WebContent/WEB-INF/hibernate.cfg.xml"/>
 <hbm2ddl export="false" outputfilename="sql.ddl"/>
</hibernatetool>
</target>
</project>

JNDI 

Lorsque la configuration de la connexion à la base de donnée est définie par JNDI, il est évident que cela ne peut pas fonctionner. Pourquoi ? Car un build ant n'a pas de context JNDI défini et encore moins celui de tomcat (ou autre) où est définie notre datasource.

La solution est de faire la génération de manière programatique :


// Get de MySQL Dialect
Properties props = new Properties();
props.put(Environment.DIALECT , "org.hibernate.dialect.MySQLDialect");
props.put(Environment.DEFAULT_SCHEMA, "heliorama");
Dialect dialect = Dialect.getDialect(props);

// Configure Hibernate
File configFile = new File("WebContent/WEB-INF/hibernate.cfg.xml");
Configuration configure = new Configuration().configure(configFile).setProperties(props);

// Generate Drop
String[] sqls  = configure.generateDropSchemaScript(dialect);
for(String s : sqls){
System.out.println(s + ";");
}

// Generate schema
sqls  = configure.generateSchemaCreationScript(dialect);
for(String s : sqls){
System.out.println(s + ";");
}












lundi 18 février 2013

Changer de version Java sous Windows 7

En tant que développeur Java, il est souvent nécessaire de changer de version Java pour différents projets : Certaines applications ne supportant que Java  7, d'autre étant encore strictement Java 6 ou 5.

La méthode classique est d'avoir plusieurs répertoires d'installation de Java pour chaque version et de changer soit :

  • les paramètres d'appel de l'application. Par exemple préciser dans eclipse.ini le chemin du jdk à utiliser,
  • la variable d'environnement %Path% pour pointer vers la bonne version.
Cependant, j'ai eu quelques difficultés avec mon nouveau PC sous Windows 7 : En effet, après avoir installé Java 7, même en changeant la variable %Path%, java -version continuait à me fournir Java 7.

La raison est la suivante : L'installateur Java 7 créé une copie de java.exe et javaw.exe sous C:\Windows\System32, or ce répertoire est avant celui de Java 6 dans mon Path.

C'est, à mon avis, une très mauvaise pratique de la part d'Orcale de fournir un installateur de JDK, dédié au développement, qui se comporte de cette façon !

Les solutions sont donc :
  • Supprimer ou renommer java.exe et javaw.exe de System32 (ce que j'ai fait)
  • Mettre le répertoire de Java avant System32 dans le Path
Noter qu'il existe aussi dans le "Panneau de configuration" Windows un "Java Control Panel" qui donne accès à des clé dans la base de registre, notamment pour les applets et pour Java Web Start. Je n'ai pas réussi à la faire fonctionner correctement... Encore une pollution Oracle lors de l'installation ! Grrrrrr...

EDIT :
Le problème de Java Control Panel qui ne sauve pas la configuration semble être un problème de droit : Il doit est exécuté avec le droit Admin, voir : Can't seem to disable Java Automatic Update
L’astuce est d'exécuter javacpl.exe en administrateur (chercher javacpl.exe dans /jre/bin de l'installation du jdk/jre, clic-droit exécuter en tant qu'administrateur).


mardi 5 février 2013

Ignorer les erreurs javascript pour les fichier javascript minifier dans Eclipse (Ignore Minify js Validation in Eclipse)

Eclipse ne gère pas correctement les fichiers minifier en javascript (minified javascript). La validation échoue est on est pollué avec des erreurs dans la vue "Problems" qui n'en sont pas.


Pour résoudre ce problème, il suffit de contrôler la validation javascript dans Eclipse :
Window > Preferences > Validation

Cliquer sur "settings" de "Client-side Javascript Validator".

Nous allons ajouter une règle pour exclure les fichiers javascript terminant par .min.js :

  1. "Add Exclude Group", 
  2. Sélectionner le nouveau "Exclude Group" 
  3. Puis cliquer "Add Rule".
  4. Choisir "File extension"
  5. Saisir "min.js" dans File extension.
  6. Finish


J'effectue l'opération en même temps que j'écris se message et après validation et rebuild, j'ai toujours les messages d'erreurs....

En fait, il y a deux types dans la vue Problems : "Javascript Problem" et "Client-side Javascript Problem".
En activant "Client-side Javascript Problem" j'ai eu un nouveau "problem".

Je pense qu'il y a deux validations différente entre "Javascript Problem" et "Client-side Javascript Problem".
Je vais creuser cela un peu plus tard.

Un peu plus tard :
Ok, si vous supprimez les markers problem suivi d'un clean, ça devrait marcher !

Autre solution : Commentaire 15 de https://bugs.eclipse.org/bugs/show_bug.cgi?id=349020#c11.

Pour aller plus loin :

Différence entre "Javascript Problem" et "Client-side Javascript Problem" :
The Client-side JavaScript Validator only validates JavaScript in web pages, as its name implies.









dimanche 6 janvier 2013

La qualité d'un langage de programation

Qu'est ce qu'un bon langage de programmation ?

Encore récemment il m'est arrivé de débattre sur les qualités de PHP, de Java, de C++, C# et j'en passe. Ce genre de discussion ne termine jamais, ou alors termine mal ! Trop souvent cela ce limite à un combat entre communauté : libre v.s. non-libre; Microsoft v.s. anti-Microsoft; et les arguments portent moins sur le langage que sur les idéologies sous-jacente des communautés. Certains défendent becs et ongles un langage qui n'a comme seul qualité être celui que l'on maîtrise !

Pourtant, débattre sur les qualités des langages est très instructif. D'une part parce qu'il est relativement rare d'être expert dans plusieurs langages et cela permet de mettre en perspective l'outil que l'on maîtrise par rapport à d'autres. D'autre part car cela donne l'occasion de poser les qualités d'un langage de programmation : c'est sur ce dernier point que je vais exposer mon point de vu.

Premièrement, il paraît important de préciser le périmètre du terme "langage de programmation" : Pour moi, il s'agira :

  • du langage à proprement parlé
  • de l'ensemble des bibliothèques disponibles
  • des outils de développement disponibles
Deuxièmement, il faut comparer ce qui est comparable, c'est  dire des langages ayant la même cible fonctionnelle : Rien de sert de comparer Java, langage généraliste à Node.js, environnement event-driven.

Finalement, le fond du problème :
Pour moi un bon langage de programmation généraliste sera défini comme le langage qui a le meilleur ratio entre expressivité et facilité à produire des bugs.


         expressivité
Score = -------------------------------
         facilité à produire de bugs

Précisions sur les termes utilisés : 
  • expressivité : on parle aussi de la "puissance" du langage, c'est à dire la capacité à résoudre des problème ou faire des calculs en peu de code. Par exemple, l’assembleur est peu puissant, Python grâce à la fonctionnalité de "List comprehension" est très expressif. Les langages dynamiques sont en général puissant, la fonction même de typage dynamique leur permet de faire facilement des choses complexes (introspections, l'intercession, etc.)
  • facilité à produire des bugs : c'est un point souvent oublié sur la qualité des langages et qui me tient particulièrement à coeur. L'idée ici est d'évaluer la facilité avec laquelle un programme peut être buggé sans que cela soit vu par un lecteur expérimenté. C et C++ par exemple, avec leur gestion manuelle de la mémoire sont défavorisés sur ce point par rapport à Java et son garbage collector. Le typage dynamique est aussi très défavorable à ce sujet : la possibilité de mélanger et inter-changer des type différents dans une même variable permet d'écrire des horreurs absolument illisible. Attention ! Je ne dis pas qu'il n'est pas possible d'écrire du code propre en Javascript, mais qu'il est possible, et c'est malheureusement souvent le cas, d'écrire du code illisible.
Un langage très sécurisé mais trop peu expressif sera lourd et volumineux.
Un langage très expressif mais non sécurisé permettra de produire du code très rapidement, au détriment de la pérennité du code.  
 

lundi 31 décembre 2012

Réparation Bâton de Ski de Fond Carbone

En fin d'hivers dernier, une malheureuse rencontre entre mon ski et mon bâton à provoqué la mort de celui-ci.

J'ai, en effet, des bâton de ski de fond en carbone Rossignol qui sont très léger, mais fragile comme tout fabrication carbone.

Les éléments en fibre de carbone stratifiés ont les caractéristiques suivante :

  • très légers,
  • très rigides, ce qui est très important en ski de fond,
  • très sensibles aux chocs.
Dans des techniques de stratifications on peut comparer le carbone avec d'autres matériaux :

  • fibre de verre
  • fibre d'aramide (nom générique du Kevlar, qui est une marque de Du Pont de Nemours)
La fibre de verre est moins chère, moins légère, moins rigide et moins sensible aux chocs.
La fibre d'aramide est aussi chère, plus lourde, beaucoup plus résistante.

J'ai donc cherché à réparer mon bâton. Plusieurs solutions s'offrent à moi:

  • Changer le tube par un même tube de bâton de ski, garder la poignée et le panier.
  • Changer le tube par un tube industriel de section homogène.
  • Réparer le tube par une stratification epoxy
1°) Changer le tube par un même tube de bâton de ski, garder la poignée et le panier :
Impossible de trouver un tube en pièce détachée, d'autant que le tarif serait probablement élevé

2°) Changer le tube par un tube industriel de section homogène :
On trouve toute sorte de tube carbone sur le marché, mais c'est chère (au moins 50€ le mètre) et la réparation serait complexe en raison de la grande différence de diamètre entre la poignée (~16mm) et le panier (>10mm)

3°) Réparer le tube par une stratification epoxy : C'est donc cette solution que j'ai choisi.
Quelques liens intéressant :
Comme le tube est déstratifié mais par rompu totalement, je n'ai pas procédé comme le premier lien.
Ma méthode sera la suivante :

  • Enduire de résine epoxy la partie du tube cassé
  • Enroulé, comme une ligature, un ruban de carbone sur le tube
Matériel :
  • Résine expoy à stratifier chez Conrad
  • Ruban carbone chez Conrad
  • Vielle brosse à dent ou pinceau
  • Pot de yaourt ou autre pour faire le mélange
  • Un contenant pour faire les dosages (par exemple un doseur d'Extril)
  • DuckTape pour maintenir chaque bout du ruban.

Matériels

Ruban carbone



Procédure :

  1. Faire le mélange epoxy, attention au dosage très précis.
  2. Encoller le tube sur la partie cassé en débordant de 3cm
  3. Stocher un bout du ruban à 1cm de la partie encollé
  4. Enrouler en serrant fort le ruban sur le tube. L'epoxy doit imprégner totalement le ruban
  5. Arrivé à la fin de la partie encollée après la cassure, stocher le rubant
  6. Brosser légèrement dans le sens de la longueur pour homogénéiser la surface et avoir des fibres longitudinale (pour renforcement - non vérifié)
  7. Laisser sècher au moins une semaine pour être sûr. 




mercredi 19 décembre 2012

Réparation d'un motoculteur

En attendant le printemps, prenons soin de nos outils de jardin !

Mon motoculteur, une motobineuse de 30 ans, a des sérieux problèmes de démarrage : En effet, le lanceur de fait plus prise avec le moteur et tourne dans le vide lorsque on tire la corde.

Ci-dessous un photo avec le carter et le ressort de rappel du lanceur démonté :

Gros plant sur l'axe du lanceur :

Cet axe devrait être une "roue libre" comme sur un vélo : tourner dans un sens, celui dans lequel on tire, être libre dans l'autre, lorsque le moteur prend le relais et tourne plus vite que le lanceur.

Dans mon cas, cet axe tourne librement dans les deux sens...
Pour analyser et corriger le problème, démontons cette roue libre. Avec un tourne-vis plat, faites sauter le capot :

Attention aux billes !!! Elles vont filer sous l'établi, hors de portée !!!

Voici comment être faite la roue libre : une partie mâle et un partie femelle avec des billes :

Dans un sens, les billes sont poussée dans leur logement par la partie en pente de la partie mâle, dans l'autre sens, les billes sont bloquées par la partie en cuvette.

Mon problème vient de la saleté qui "colle" les billes dans leur logement, en les empêchant de redescendre.

Après un bon dégraissage à l’essence de toutes les pièces, la roue libre fonctionne de nouveau correctement. 


mercredi 12 décembre 2012

Arrêtez de vous battre avec log4j

Log4j, puissance librairie de log est un incontournable des projet Java.

Mais qui n'a jamais bataillé avec sa configuration délicate ? Une méthode simple est très efficace pour diagnostiquer des problèmes de configuration est d'activer le debug pour log4j.

Rajouter log4j.debug comme variable JVM au lancement du programme.

Rappel : pour ajouter une variable JVM c'est -Dmavariable=mavaleur.

Soit : -Dlog4j.debug

Deuxième rappel : Pour rajouter une variable JVM pour tomcat sous eclipse c'est :

1°) Double-clic sur le serveur dans l'onglet "Servers"
2°) Clic sur "Open lauch configuration"
3°) Onglet "Arguments"
4°) Rajouter la variable dans "VM arguments"

dimanche 21 octobre 2012

Lampe de spéléologie "VocLed I"



La lampe VocLed I est mon premier prototype 'fait main' de lampe pour la spéléologie.















Fonctionnalités en bref

2 Modes


Forte Puissance (5h autonomie - 440lm)


Faible Puissance (au minimum 12h - 110lm)

Eclairage


Wide (aucune optique), Blanc chaud (proche acétylène)
Montage et batterie


Batterie Li-ion (pile rechargeables dans boîtier)  sur casque
Poids


460g

Construction

 

 

Led
2 * Led Cree XM-L T2 High Power LED, Warm White 650 lm 1cm Square PCB

LedRise.com
14.24€        
Boîtier avant




DissipateurTO220

RS
3.36€HT


Plaque de polystyrène transparent
GSB
~5€

Cartouche Silicone
GSB
~3€
Driver




Montage 'maison' : Transistor bipolaire NPN, Mosfet Canal N, Interrupteurs et résistances 3W
RS
~5€
Boîtier batterie




Boîtier PVC industriel IP67
RS
10.30€HT

Presse étoupe et accessoires
RS
~3€

2*Keygos 26650 4800Ah 3.7V + chargeur
Keygos.com
20€
Total


~65€