Blogounage

Aller au contenu | Aller au menu | Aller à la recherche

lundi 30 juin 2008

Comment réinitialiser manuellement les pages chargées par firefox au démarrage

Si, comme moi depuis 10 minutes, vous êtes dans l'impossibilité de relancer Firefox parce que la page sur laquelle vous étiez provoquait un plantage de FF, ce qui suit est pour vous.

Dans les options de Firefox, vous pouvez demander à ce que celui-ci réouvre les onglets ouverts avant la dernière fermeture (Onglet Général, le premier combobox). Une fois cette option sélectionnée, mon firefox qui gelait avait pour bonne idée de redémarrer sur la page en question et de regeler...

Et là, bizarrement, la proposition de "restaurer les onglets" ou de "démarrer une nouvelle session" n'était même pas offerte. Donc, bien bien bloqué.

La solution que j'ai trouvée est la suivante :

  • Tuez firefox
  • dans votre répertoire profile (dans quelque chose comme $HOME/.firefox/1d5s1.default sous Linux ou C:\Documents and Settings\votreuser\Application Data\Mozilla\Firefox\Profiles\1d5s1.default sous windows), supprimez simplement le fichier sessionstore.js.
  • Relancez firefox...

Voilà, en espérant que ça serve...

mardi 24 juin 2008

Quelques déclarations XSD ou DTD de formats XML connus

C'est le genre de chose qu'il est sympathique d'avoir écrit en tête de ce type de fichier pour disposer de l'auto-complétion XML dans son IDE favori. Lorsque j'utilise un nouveau format XML, la première chose que je cherche est en effet à ajouter cet entête pour me faciliter la vie (et aux autres une fois commité :)).

Note : dans la liste ci-dessous, je ne mets pas le prologue XML pour gagner en concision. Toutefois, ça ne fait jamais pas de mal de le mettre, personnellement j'essaie de le mettre systématiquement.

Hibernate : mappings hbm.xml

Même s'il vaut mieux à mon avis passer aux annotations lorsqu'on en a la possibilité, voici une déclaration de DTD qui fonctionne chez moi pour ceux qui ont encore des mappings hibernate à la sauce XML :

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="net.batmat.domaine">
...
</hibernate-mapping>

Java Persistence : persistence.xml

Pour ceux qui utilisent Java Persistence, cette "sous-spécification" des EJB3 devenue une spécification autonome dans sa version 2 :

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="
                http://java.sun.com/xml/ns/persistence
                http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"

        version="1.0">

...
</persistence>

Spring : fichier de contexte XML

Depuis la version 2, ils ont subdivisé leur format XML en différents namespaces. Voici un exemple fonctionnel qui met en œuvre un certain nombre de ces espaces de nommages XML. Je laisse en exercice le passage à Spring 2.5 (que nous utilisons, d'ailleurs, mais on n'a pas mis à jour le XML) ou l'ajout d'un autre namespace dont vous auriez besoin :-).

<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:util="http://www.springframework.org/schema/util"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="
                http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
                http://www.springframework.org/schema/util
                http://www.springframework.org/schema/util/spring-util-2.0.xsd
                http://www.springframework.org/schema/tx
                http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
                http://www.springframework.org/schema/aop
                http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"
>

...
</beans>

Maven : pom.xml

Celui-là, il est sacrément pratique vu la taille du truc :

<project xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                      http://maven.apache.org/maven-v4_0_0.xsd"
>

...
</project>

Voilà déjà pour cette fois. Une fois cet entête ajouté, dans Eclipse par exemple, tapez juste "<" quelque part et vous verrez la liste des balises apparaître et leur documentation si les auteurs l'ont indiquée (après qu'Eclipse ait pu récupérer le XSD sur Internet, bien sûr) : Auto-complétion du XML avec Eclipse

Si vous en avez d'autres, n'hésitez pas à les poster (ou à les demander, si je suis dans un bon jour) dans les commentaires.

mercredi 4 juin 2008

FIA : les œillères de la connerie

Sans déconner, c'est pas un ramassis de neuneus à la FIA ?

Lorsque Sébastien Loeb, le multiple champion du monde de rally, monte une fois de plus sur un podium sans prendre soin de passer devant les maquilleuses auparavant, il est des gens assez chiants pour trouver à redire ! Surinder Thatti, via Libé :

Je me dois d’exprimer mon opinion à propos du piètre passage de Sébastien Loeb à la TV lors de l’arrivée du rallye du Mexique. Il n’était pas rasé, dépenaillé avec une chevelure négligée.

Jusque là, rien d'anormal. Il y a plein de gens aux mœurs différentes sur la planète. Ça peut éventuellement se comprendre.

Là où j'hallucine, c'est lorsqu'un débile de la direction de la Fédération Internationale de l'Automobile, j'ai nommé Morrie Chandler, se dit que vraiment oui, c'est pas normal, c'est une honte aux vrais mâles et tout et tout :

Malheureusement, ce n’est pas un problème propre à notre sport, vu que la même chose arrive dans le football et d’autres sports de "mâles". Bien sûr, ces personnes sont une insulte aux vrais mâles Ma seule solution c’est que nous suggérions à ISC (NDLR: International Sportsworld Communicators, la société détentrice des droits commerciaux et de retransmission) qu’ils aient la couverture à laquelle ils ont droit en tant que vainqueurs, mais sans gros plans et sur un laps de temps réduit.

Comme le dit Libé, après les récentes révélations au sujet de Max Mosley et ses frasques sado-masochistes nazi, il y a de quoi se demander dans quelle réalité des types comme Chandler vivent ! Qu'un champion soit pas très frais et un peu ébouriffé après une course de plusieurs heures et le port d'un casque, ça c'est inadmissible.

Par contre, que le président de toute la fédé s'amuse en privé à papoter en allemand avec des prostitués qui le traitent comme un prisonnier, là c'est le black out. (Précisons que Max Mosley n'est pas allemand et que son père avait créé l'Union Fasciste Britannique, le deuxième point peut donner une idée de l'origine de ce genre de fantasme...)

Et nouvelle fraîche : Max Mosley a donc bien été réélu hier à la tête de la FIA.

Plutôt douteuse cette histoire, vous avouerez...

mercredi 28 mai 2008

40 000 ans de prison

En triant mes vieux mails, je viens de me marrer un bon coup. Merci à Yoyo sur ce coup-là :

mardi 5 février 2008

Danseuse : quel côté de votre cerveau utilisez-vous le plus ?

Je viens de recevoir cette image par mail, je vous mets le texte explicatif, sans préjuger de la véracité des propos. Ce qui est sûr, c'est que le résultat parmi les collègues que j'ai autour de moi est déroutant. Certains voient tourner cette danseuse dans un sens, d'autres dans l'autre sens, d'autres la voient changer régulièrement...

Nous utilisons les hémisphères gauche et droit de notre cerveau pour des tâches bien différentes. Pas étonnant dès lors, que notre caractère détermine l'hémisphère que l'on sollicite le plus souvent. Ca vous laisse dubitatif ? Faites le test ! Le test est simple. Regardez cette danseuse et dites-nous dans quel sens elle tourne.

Pour une grande majorité, la danseuse tourne dans le sens contraire des aiguilles d'une montre; ceux-là utilisent surtout l'hémisphère gauche. Pour les autres en revanche, elle tourne dans le sens des aiguilles d'une montre ; ces derniers utilisent plus souvent l'hémisphère droit.

Mais qu'est-ce que cela signifie ?

* L'hémisphère gauche du cerveau est le côté de la logique, des sciences et des faits purs et durs. Vous faites attention aux détails, aux mots que vous utilisez et reconnaissez des patrons. Vous êtes ancré dans la réalité, et vous basez sur ce que vous savez et comprenez. Vous vous préoccupez du présent, et du passé et avez tendance à ne prendre aucun risque. Vous êtes concret et élaborez des stratégies.

* L'hémisphère droit du cerveau est caractérisé par les sentiments, l'imagination, la philosophie et la religion. Vous vous préoccupez des images, des symboles et des concepts. Vous n'avez pas besoin de tout savoir ; parfois, il vous suffit de croire. Vous êtes compréhensif, impulsif et prenez des risques. Vous êtes plus préoccupé par l'avenir que par le passé.

Personnellement, jusqu'à présent, ça ne tourne QUE dans le sens des aiguilles d'une montre.

samedi 2 février 2008

Optimisation GWT 1.4

Wouah, je viens de regarder l'interview de Bruce Johnson par InfoQ à propos de GWT.

Bruce explique les nombreuses optimisations qu'ils effectuent au niveau du compilateur GWT. Il explique notamment qu'ils (les développeurs GWT) cherchent sans cesse à optimiser le compilateur, pour cela il comparent par exemple les requêtes qu'une webapp classique effectue vers le serveur et les requêtes que GWT fait.

Et en exemple, autour de la dixième minute, il explique l'optimisation concernant les images : l'ImageBundle. Dans une application classique, il y a des dizaines d'images, souvent toutes petites (icônes, fonds...). Le problème, c'est que le navigateur, même pour se voir répondre que l'image est à jour ouvre très souvent des connexions, d'autant plus qu'il y a d'image ! Ça peut créer (dixit Bruce) une contention en raison du grand nombre de sockets ouvertes côté serveur.

Et bien si vous utilisez cet objet ImageBundle, GWT construit côté serveur une image composite. Comme ça, le navigateur n'a qu'une seule image à télécharger puis vérifier, et les morceaux sont déconstruits côté client en récupérant les bouts de la grosse image et en les plaçant au bon endroit (cf. 10m40s). C'est quand même génial comme idée.

Bon après, il faut que la machine sur laquelle le navigateur tourne dépote d'autant plus, mais on n'a rien sans rien.

PS : Ce que je viens de dire n'est que le reflet de ce que j'ai compris de l'interview. Je n'ai pas testé cette fonctionnalité.

Ça y est, @Override fonctionne enfin comme je l'ai toujours voulu :-)

Depuis Java 5, les annotations ont été ajoutées. L'une des premières a été @Override, une annotation destinée à informer le compilateur que la méthode ainsi annotée redéfinit une méthode parente.

Le problème, c'est qu'en Java 5, cette annotation ne pouvait être utilisée que sur des méthodes en provenance d'une classe parente, pas d'une interface.

Je l'ignorais jusqu'à hier soir, mais en posant la question de la justification de ce choix d'implémentation sur ma liste de diffusion favorite, c'est mon ancien prof de Java et de Génie Logiciel qui m'a répondu que c'était possible depuis Java 6. Cf. le blog de Peter Ahé.

En clair :

public interface MonInterface
{
        void methode();
}

class MonImpl implements MonInterface
{
        // L'annotation suivante est valide depuis Java6, mais produit à la compilation le
        // message suivant en Java5 :
        // "The method methode() of type MonImpl must override a superclass method"
        @Override
        public void methode()
        {
        }
}

Ça fait un outil de plus pour augmenter la qualité du code, en l'occurrence en diminuant le risque de se retrouver avec du code mort.

dimanche 13 janvier 2008

How to load a XML Spring context lazily by default

Say you want to change the default-lazy-init attribute programmatically. The most common use case for this seems to appear with unit-testing. In fact, you probably want to load everything when starting a production server, even if it costs you more time. But when testing, and particularly on your machine, you might want to inverse this behaviour. In fact, you might be interested in not loading every 1000 beans of your context when you just need less than 10 for example...

A (beginning of) solution

If you crawl Google, you might find this entry that links to this other one that explains how to programatically modify the lazy-init attribute of each bean of your context. In fact, before the loading occurs, you can iterate through the bean list and call setLazyInit using the method AbstractBeanDefinition.setLazyInit(true). This will be roughly equivalent to manually put lazy-init="true" on every single bean of your context files.

The problem

The problem with this is that you override everything that was declared in the XML context file. You might want a particular bean be instantiated lazily or eagerly for some reason. But iterating through the whole list like this won't let you keep what was explicitly defined and only redefine the default value. Another problem is that you may have to exclude some bean from this loop, ending up with a condition that really looks like an ugly hack :

for (String beanDefinitionName : context.getBeanDefinitionNames()) {
    AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition)context
            .getBeanDefinition(beanDefinitionName);
    System.err.println(beanDefinitionName);
    // FIXME : ugly hack
    if (!"org.springframework.aop.config.internalAutoProxyCreator".equals(beanDefinitionName)) {
        beanDefinition.setLazyInit(true);
    }
}

Having to exclude the one bean that's (according to its name) responsible for proxying beans that have to be lazy-loaded seems quite reasonable. But the thing is you obviously don't have to do it when you put the default-lazy-init manually...

So I looked for a way to simply replace the default value of this attribute instead. After some time digging into Spring code, I finally found it.

When parsing context definition written in XML (since writing it in XML is no requirement), Spring will use an instance of BeanDefinitionReader that will then call DefaultBeanDefinitionDocumentReader to parse the Document instance. Searching a bit more lets us find where the default values are initialized : BeanDefinitionParserDelegate.initDefaults().

LazyInitByDefaultBeanDefinitionDocumentReader

public class LazyInitByDefaultBeanDefinitionDocumentReader extends DefaultBeanDefinitionDocumentReader
{
        @Override
        protected BeanDefinitionParserDelegate createHelper(XmlReaderContext readerContext, Element root)
        {
                root.setAttribute(BeanDefinitionParserDelegate.DEFAULT_LAZY_INIT_ATTRIBUTE, "true");
                return super.createHelper(readerContext, root);
        }
}

I would have preferred to use the seemingly more dedicated method preprocessXml(Node root)], but this method is called after createHelper(), so the default values are already initialized when calling preprocessXml()... So overriding preprocessXml() is "too late".

I think I'm going to submit a patch into the Spring bug tracker about this problem.

Unit-testing

When you do unit-testing with Spring, you generally inherit the AbstractDependencyInjectionSpringContextTests class. Add this method redefinition to enable the "lazy by default" behaviour :

@Override
protected BeanDefinitionReader createBeanDefinitionReader(GenericApplicationContext context)
{
        XmlBeanDefinitionReader r = new XmlBeanDefinitionReader(context);
        r.setDocumentReaderClass(LazyInitByDefaultBeanDefinitionDocumentReader.class);
        return r;
}

Plain old Java (Spring) code

When you want to create an XML context, you generally use a ClassPathXmlApplicationContext instance. If you want to modify the default behaviour like here, you have to use a GenericApplicationContext. Note that this is what is adviced in the javadoc of ClassPathXmlApplicationContext :

This is a simple, one-stop shop convenience ApplicationContext. Consider using the GenericApplicationContext class in combination with an org.springframework.beans.factory.xml.XmlBeanDefinitionReader for more flexible context setup.

Here is the code using this GenericApplicationContext that enables the lazy-loading :

GenericApplicationContext context = new GenericApplicationContext();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(context);
reader.setDocumentReaderClass(LazyInitByDefaultBeanDefinitionDocumentReader.class);
reader.loadBeanDefinitions("/yourApplicationContext.xml");
context.refresh();

When is it needed ?

At the moment, I see two reasons for enabling the lazy-loading by default :

  1. When unit-testing, this lets you test a part of the code a bit more quickly, since not every single beans needs to be instantiated.
  2. When using code-coverage tools to evaluate a part of the code, this prevents totally unrelated code to appear with non-null percentage.

Hope this small article will help some other people :-).

vendredi 4 janvier 2008

The Mythical 5%

Via InfoQ, voici un article de Bruce Eckel sur l'informatique aujourd'hui.

Il commence par parler du "fascinant" 5% des programmeurs sont 20 fois plus productifs que les autres 95%., et élargit ensuite au monde de l'informatique : jeune, immature, ...

Note : Le titre de l'article de Bruce fait très certainement référence au célèbre livre "The Mythical Man-Month" de Frederick P. Brooks. C'est de ce livre qu'est issu la plus célèbre encore "loi de Brooks" :

Ajouter des ressources à un projet en retard le rend encore plus en retard

Je vous conseille aussi la lecture de cet ouvrage, ça se lit très bien et c'est très instructif.

vendredi 21 décembre 2007

Quelles méthodes je peux mettre dans mes « objets du domaine » ?

Gavin King, le créateur du projet Hibernate, dont le hobby est maintenant devenu Seam, a récemment publié un billet intéressant sur ce sujet.

Souvent, la question se pose : quelles méthodes doit-on modéliser dans un objet métier ? Concrètement, où dois-je mettre mon code métier ? Par exemple, est-ce que la méthode de sauvegarde d'une facture doit se trouver dans l'objet Facture lui-même ? Si je veux récupérer le nombre de clients d'une facture, dois-je mettre la méthode dans la Facture, etc. ?

Gavin a formulé d'une façon très concise une règle à laquelle je souscris totalement :

the domain model (entity classes) are the most reusable classes in my codebase

[...]

In particular, I would never write code that calls out to external services, or accesses the database, or calls an EJB/Seam/Spring component in my entity class. I want my domain model to be completely self-contained!

So anytime you find yourself wishing that entities supported injection, or find yourself writing a JNDI lookup in a method of an entity, please consider that your domain model is no longer self-contained, and will be less reusable in different execution environments.

Rien de plus à ajouter.

jeudi 20 décembre 2007

Paranoïa

Extraits de Wikipedia :

Dès lors, la paranoïa est définie comme un délire chronique, organisé, structuré, logique dans son développement, comportant le plus souvent un sentiment de persécution, entraînant une forte adhésion du patient, mais n'entravant pas les autres fonctions psychiques. Ce type de délire, dit délire paranoïaque apparaît préférentiellement chez des sujets marqués par un trouble de la personnalité paranoïaque pré-existant.

Et aussi

Ce trouble affecte 0,3 à 2,5 % de la population générale. D'un point de vue sémiologique les personnalités paranoïaques se caractérisent par quatre traits fondamentaux qui entraînent à terme une inadaptabilité sociale :

1. la surestimation pathologique de soi-même ;
2. la méfiance extrême à l'égard des autres ;
3. la susceptibilité démesurée ;
4. la fausseté du jugement.

Et pour finir :

La dangerosité psychiatrique des patients affectés par des psychoses paranoïaques n'est pas à négliger. Elle est d'autant plus à craindre :

* qu'il existe un persécuteur désigné, c'est-à-dire un individu précis, jugé comme étant responsable des persécutions que le sujet pense endurer
* que le délire évolue de longue date et s'est enrichi au cours du temps
* qu'il existe un trouble de l'humeur concomittant
* qu'il existe un alcoolisme et/ou une consommation excessive de cannabis

dimanche 16 décembre 2007

Do Interfaces have semantics ?

When I saw the title of this entry in my feed reader, my first thought was who the f*** could be wondering if interfaces have semantics ?. Happily, that's not Gavin who thinks this.

The assertion is the following :

Interfaces in Java don't have any semantics attached. Only a concrete class can define the semantics of a method.

In my opinion, that's even what interfaces are designed for, defining semantics...

I totally agree with Gavin when he says semantics is defined in the Javadoc and the "name of the things". I always find myself taking a long time to carefully choose the naming of my objects, since I want those names to be the most meaningful possible (same for method parameters, method names, and so on. Naming meaninfully local variable is also important, but it goes beyond the scope of the current subject).

Using polymorphism let you see different implementations as the same thing, thanks to the defined contract. Maybe I'm only viewing interfaces throught the Liskov principle. But for me contract is a synonymous for semantics when it comes to programming, although I'd be glad to hear explanations of where it differs in your opinion.

Even more, I think that today, as everybody gets more and more used to using the dependency injection pattern, some concrete classes are not even known to the code they're used by. It's becoming common to use classes only through their interfaces only (services, for example). In those case, semantics resides in the interface only, and implementations obviously have to respect it very carefully.

mardi 11 décembre 2007

J'ai un différentiel de 500 ou 300mA et je vais mourir si je touche le jus

Attention, ce qui suit est issu de ma compréhension du domaine de l'électricité et plus particulièrement de la sécurité électrique. Ne prenez donc pas mes dires pour argent comptant. Si j'ai dit une bêtise, n'hésitez pas à me corriger dans les commentaires. Tout le monde en profitera :-).

J'ai trouvé ce petit sondage via google sur le forum Santé de hardware.fr. passons sur la question : mais que vient f***re un forum santé sur Hardware.fr. Faut que j'arrête d'être mauvaise langue, cette page contient quelques informations intéressantes.

En plus, en recoupant avec les informations de connaissances plus au jus (haha) que moi et ma récente formation de Sauveteur Secouriste du Travail, on comprend mieux cette phrase. En effet, sachez qu'en gros, la mort se trouvera presque toujours si vous prenez 50mA en touchant un fil dans lequel circule le courant. Et même à partir de 25mA, vous serez pas en grande forme.

La question qui se pose donc est la suivante : est-ce que je peux faire quelque chose au niveau de mon installation pour que si je touche d'une façon ou d'une autre quelque chose qui serait en contact avec le courant électrique de ma maison ? (l'un des deux fils, la phase, plus précisément).

Allez voir à l'entrée de votre maison. Vous devez avoir un truc qui permet de faire une coupure générale de l'électricité de votre maison. C'est ça qu'on appelle le disjoncteur. Regardez ce qu'il y a écrit dessus. S'il ressemble à ça : Disjoncteur différentiel antédiluvien Si vous touchez le courant, vous êtes mort...

Que faire ?

Derrière le disjoncteur, que vous ne pouvez pas changer sans faire appel à EDF, vous pouvez installer un dispositif différentiel plus sensible que les 500mA comme celui que j'ai, par exemple. La norme est aujourd'hui à 30mA. Mais il est quand même flippant de voir des statistiques annoncées qu'au vu du parc électrique français, 50% des foyers sont encore équipés de différentiels comme le mien, inutiles pour protéger les humains...

Par contre, je n'ai pas encore bien compris s'il fallait mettre un interrupteur ou un disjoncteur différentiel. D'après cette réponse sur leurs différences sur Yahoo Questions/Réponses, je comprends que le disjoncteur est juste un peu mieux parce qu'il va aussi protéger les installations des surintensités, alors qu'un interrupteur grillera tout simplement.

Ce que j'en comprends aussi, c'est que disjoncteur ou interrupteur, l'important est qu'il soit différentiel pour protéger les humains. Au choix du propriétaire de choisir ou non de mieux protéger aussi son installation.

mercredi 5 décembre 2007

En vrac

Quelques trucs marrants reçus ou trouvés ces temps-ci :

Le karaté à la Star Ac' :

Via Géraud, le Rap de l'Aveyron :

Via BienBienBien, le nouveau teckto-tube pour les moins de 15 ans, flippant :

Et pour finir, cours de strip-tease :

vendredi 30 novembre 2007

Continuum : envoyer le mail après le build dans tous les cas

Nous avons récemment installé et configuré Continuum. Comme nous démarrons avec, nous avons configuré nos projets pour recevoir systématiquement un mail lorsque le build est terminé, qu'il ait réussi ou non. Nous voulons en effet nous assurer que le build est bien effectué par ce biais. Une fois que nous aurons rôdé le processus, dans quelques mois par exemple, je pense que nous modifierons effectivement la configuration pour rendre le serveur d'intégration moins bavard...

Voici le bloc qui permet de dire au serveur d'intégration d'envoyer les mails dans tous les cas. À mettre dans le pom.xml de votre projet :

<ciManagement>
        <system>continuum</system>
        <url>http://mvnrepo.mipih.fr:8080/continuum</url>
        <notifiers>
                <notifier>
                        <type>mail</type>
                        <sendOnError>true</sendOnError>
                        <sendOnFailure>true</sendOnFailure>
                        <sendOnSuccess>true</sendOnSuccess>
                        <sendOnWarning>true</sendOnWarning>
                        <configuration>
                                <address>notre-adresse@mipih.fr</address>
                        </configuration>
                </notifier>
        </notifiers>
</ciManagement>

Dans tous les cas, j'ai dit !

Mais en fait, même comme ça, continuum ne vous enverra pas toujours la notification. En fait, il ne l'enverra que si l'état de la construction de votre projet a changé depuis la dernière fois. De base, donc, continuum n'enverra pas de mail si dexu builds successifs ont réussi.

J'ai donc cherché à savoir comment configurer continuum pour envoyer le mail inconditionnellement à la fin de chaque build. Comme je n'ai pas trouvé cette information dans la documentation de continuum, j'ai posé la question sur la liste de diffusion. J'ai eu la réponse d'Emmanuel Venisse, le projet lead de continuum :

You can configure "alwaysSend to true in WEB-INF/classes/META-INF/plexus/application.xml in the mail notifier component descriptor.

By default, we don't send notifications if the state doesn't change to not spam users.

Emmanuel

Dans continuum 1.0.3, c'est là : $CONTINUUM_HOME/apps/continuum/conf/application.xml. Et effectivement, après modification du bloc <alwaysSend/> à true du composant mail notifier comme suit, ça marche !

<!--
        The mail notifier
-->

<component>
        <role>org.codehaus.plexus.notification.notifier.Notifier</role>
        <role-hint>mail</role-hint>
        <implementation>
                org.apache.maven.continuum.notification.mail.MailContinuumNotifier
        </implementation>
        <requirements>
                <requirement>
                        <role>org.codehaus.plexus.velocity.VelocityComponent</role>
                </requirement>
                <requirement>
                        <role>org.apache.maven.continuum.store.ContinuumStore</role>
                </requirement>
                <requirement>
                        <role>org.codehaus.plexus.mailsender.MailSender</role>
                </requirement>
                <requirement>
                        <role>org.apache.maven.continuum.configuration.ConfigurationService</role>
                </requirement>
        </requirements>
        <configuration>
                <from-mailbox></from-mailbox>
                <from-name></from-name>
                <timestamp-format>EEE, d MMM yyyy HH:mm:ss Z</timestamp-format>
                <includeBuildResult>true</includeBuildResult>
                <alwaysSend>true</alwaysSend>
        </configuration>
</component>

En espérant que ça en aide certains...

samedi 24 novembre 2007

Problème Gmail avec Adblock plus

Depuis quelques jours, j'avais des problèmes à l'utilisation de gmail. Je n'ai pas fait le rapprochement tout de suite. La page principale de la boite de réception s'affichait, mais cliquer sur un message n'affichait jamais ce dernier. Certaines fois, même, Firefox m'affichait le message indiquant qu'un "script (javascript) ne répond pas"...

Après réflexion, je me suis demandé si adblock plus, l'extension anti-pub pour firefox que j'ai installée ne pouvait pas être en cause ? Bingo avec Google. Je n'ai par contre pas compris pourquoi les billets comme celui-ci dataient déjà de 2005, alors que je suis persuadé que ça fait une ou deux semaines au moins que j'utilisais déjà conjointement adblock plus et gmail sans soucis. Peut-être une mise à jour d'adblock plus récente que j'aurais faite sans y faire attention ?

Bref, la solution est simple. Il suffit d'ajouter mail.google.com à la liste blanche. Pour faire ceci, on peut se référer au billet en lien ci-dessus ou à la documentation d'adblock plus. En fait, pour ajouter un filtre à la liste blanche, il faut simplement préfixer le filtre par @@ (enfin, simplement, faut le savoir, quand même...).

Une fois ceci fait, tout roule normalement à nouveau.

jeudi 22 novembre 2007

44 balises en 5 minutes...

Via Prendre un café, un petit test rigolo sur vos connaissances HTML4 :

44

Pas trop mal. J'ai honte d'avoir oublié de citer acronym, abbr que j'ai déjà pas mal utilisé, et toutes les balises des formulaires ;-).

jeudi 15 novembre 2007

Grève à Toulouse : toujours aucun problème

N'hésitez pas à prendre le métro, il fonctionne parfaitement. Les bus étaient, paraît-il, moins nombreux le premier jour, mais pratiquement à 100% aujourd'hui...

Allez, encore un peu de patience, la réforme va finir par passer :-).

vendredi 26 octobre 2007

Limitation Oracle antédiluvienne

Je découvre avec une relative stupeur que la taille maximale des noms de tables, de colonnes, de contraintes est limitée sur Oracle à 30 caractères seulement !

Imaginez que vous ayez une contrainte d'intégrité référentielle entre deux tables :

  • PRODUIT
  • CATEGORIE_PRODUIT

Par convention, on préfixe souvent ces contraintes de clés étrangères par FK (voire C_FK par exemple, pour Constraint et Foreign Key). Ça me donne quelque chose comme ça :

  • FK_PRODUIT_CATEGORIE_PRODUIT

Là, j'ai 28 caractères, je passe limite. Si je rajoute "C_", je suis à fond...

Imaginons maintenant que votre fonctionnel vous indique qu'il y a une relation de réflexivité sur CategorieProduit. Les catégories de produit forment en effet un arbre avec des catégories, des sous-catégories, etc. Ben là, vous oubliez le nommage ci-dessus :

  • FK_CATEGORIE_PRODUIT_PRODUIT_CATEGORIE_PRODUIT, ça passe pas...

Autre cas, si vous avez deux relations entre deux mêmes tables. Par exemple, Adresse et Client : un client peut avoir une adresse de facturation et une adresse de livraison. En base, on doit donc retrouver deux contraintes d'intégrité. La première idée qui vient est de concaténer par exemple le rôle au nommage ci-dessus. Euuu, ça commence à exclure pas mal de cas.

Franchement, à l'occasion du passage de la mise à jour de Oracle v10, Oracle aurait pu supprimer ou au moins augmenter cette limitation antédiluvienne !!! Pour la petite histoire, cette limitation n'existe pas sur les autres SGBD que nous pouvons utiliser : HSQLDB, MySQL, PostgreSQL... Je comprends mieux pourquoi les schémas d'entreprise sont truffés de noms absolument incompréhensibles. L'auto-documentation du nommage est impossible avec une limitation aussi importante.

À l'heure de l'auto-complétion omniprésente, il est courant d'avoir des variables qui atteignent 30 caractères. Je ne dis pas qu'il faut forcément des noms de variable à rallonge, mais si la longueur apporte en clarté, en maintenabilité, en compréhension, ne vous en privez surtout pas !

Très très déçu par Oracle sur ce coup là.

mercredi 17 octobre 2007

Grève : pas de problème demain ?

Sur le site de Tisséo, la RATP toulousaine, dirons-nous pour nos amis parisiens :

Le 18 octobre

[...]

Le trafic du métro ne devrait pas être affecté.

J'essaierai donc de prendre le métro demain, sinon ce sera vélo ou moto. Bon, en même temps, je n'ai que 6,5km de chez moi au boulot... Aaaah Paris, je suis content de ne plus y être :-).

- page 1 de 15