Off the record

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

vendredi 27 octobre 2017


Const - block scoped - better than var which has a global scope
Types - boolean, number, string, symbol, null, undefined
type inference : const tax = 20;

interface Puppy {

 name: string;
 age: number;


const realPuppy: Puppy = {

 name: 'Pikachu',
 age: 1


Parameterized types
const betterCats: Array<Cat> = [

 {name: 'Simba', age: 22},
 {name: 'Aslan', age: 9999}


classes and inheritance export class = pubilc

Filter is an Array method that allows you to generate a new array keeping only the truthy values that are provided from the returning callback

numbers.filter(number => number > 30)

Enums Async / Await Getters / Setters Destructuring Arrow functions

mercredi 26 juillet 2017

Playing with ncat and Python http.server

  1. open a webserver and browse

python3 -m http.server 8080

  1. open a listening socket on port 9000

ncat -l 9000

  1. upon browser call at localhost:9000 - see the HTTP GET request come in and answer it as follows :

HTTP/1.1 307 Temporary Redirect Location:

HTTP/1.1 200 OK Content-length: 10 Content-type: text/plain


  1. see 1234567890 print in the browser

mardi 25 juillet 2017

IntelliJ IDEA shortcuts

  • Errors ⌘0
  • Project ⌘1
  • Version Control ⌘9
  • Run ⌘4
  • Debug ⌘5
  • Terminal ⌥F12
  • Editor ⎋ = esc
  • Distraction free mode : ⌘⇧F12
  • Quick search action : ⇧⌘A
  • highlight usages of a symbol ⌘⇧F7
  • auto-complete ⌃Space
  • Duplicate a line ⌘D
  • Comment a line ⌘/
  • Delete a line ⌘⌫
  • statement completion ⇧⌘⏎
  • recent files ⌘E
  • navigate to class (Object) ⌘O (to file ⌘⇧O)
  • navigate within the structure of a file ⌘F12
  • search everywhere double ⇧
  • quick outline ⌥space = option space
  • show implementation ⌘⌥B (command option B)
  • Rename ⇧F6
  • Extract variable ⌥⌘V
  • Extract field ⌥⌘F
  • Extract a constant ⌥⌘C
  • Extract a method ⌥⌘M
  • Extract a parameter ⌥⌘P
  • Inline ⌥⌘N
  • Copy current file F5
  • Move F6
  • Refactor this ⌃T
  • find usages ⌥F7
  • Reformat code ⌥⌘L
  • Auto-indent lines ⌃⌥I
  • Optimize imports ⌃⌥O
  • navigate to versioning tools ctrl-V
  • Commit changes ⌘K
  • Update project ⌘T
  • Push commits ⇧⌘K
  • build project ⌘F9
  • Toggle breakpoint ⌘F8
  • Step into F7
  • Smart step into ⇧F7
  • Step over F8
  • Step out ⇧F8
  • Resume ⌥⌘R
  • Evaluate expression ⌥F8
  • sout is the keyword for System.out.println
  • iter is the foreach loop code template gen keyword

samedi 9 août 2014

Listen to any internet radio on your old vintage FM radio !

Build a simple FM transmitter with a raspberry pi and a piece of wire for the antenna

1) Get a raspberry pi

2) get whatever Linux on it

3) install sox to read internet streams : $ sudo apt-get install sox libsox-fmt-all

4) wget tar -xvf Pifm.tar.gz

5) start the bbc on 103.3FM

$ sox -v .9 -t mp3 -t wav --input-buffer 80000 -r 22050 -c 1 - | sudo /home/pi/pifm/pifm - 103.3

6) improve the range from 10cm to 100m by plugging a piece of wire in the 4th GPIO pin. I took an old headset, cut at both ends, plugged. no soldering needed, google to find which GPIO is the 4th one.

7) replace the bbc stream with France Info or France Inter or whatever stream : France Bleu Breizh, Tendance Ouest Rouen, Kiss FM dance or whatever obscure campus radio that streams on internet. Yay.

8) play your mp3s in the house sox -v .9 -t mp3 ./someCrap.mp3 -t wav -r 22050 -c 1 - | sudo /home/pi/pifm/pifm - 100

samedi 7 décembre 2013

Make a still movie with gopro and Mac

$ sips -Z 1920 *.JPG

$ mencoder mf://*.JPG -mf fps=8 -ovc xvid -xvidencopts bitrate=5000 -o output-mpeg.avi

mencoder output-mpeg.avi -o cropped.avi -vf crop=1720:1440:200:0 -ovc xvid -xvidencopts bitrate=5000

sips is a osx tool, similar tools to resize images are available on linux.

lundi 27 février 2012


Key satement : design for mobile first

Media queries : 2 ways to define :

<link href="css/phone.css" rel="stylesheet" type="text/css" media="only screen and (max-width: 400px)" >


@media screen and (min-width: 900px) {

 .class {
   background: #666;


Websockets !

vendredi 16 décembre 2011

C# - WPF

using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Media.Effects;
using System.Windows.Controls;
using System.Media;

namespace WPFApplication
    class Program
        static void Main(string[] args)
            Window win = new Window();
            win.Title = "Hello world";  

            win.Height = 383;
            win.Width = 480;

            // change background color
            win.Background = new LinearGradientBrush(Colors.LightSeaGreen, Colors.Yellow, 45.0);

            // add an eventHandler to be run on window initialization
            win.Initialized += new EventHandler(w_Initialized);

            win.AddHandler(Control.MouseLeftButtonDownEvent, new RoutedEventHandler(OnClick));

            Application app = new Application();


        static void OnClick(object sender, RoutedEventArgs e)
            if (e.Source is Ellipse)
                SoundPlayer sp = new

        static void w_Initialized(object window, EventArgs e)
            Ellipse ellipse = new Ellipse();

            // add new eventsHandler to interact with the mouse
            ellipse.MouseEnter += new System.Windows.Input.MouseEventHandler(ellipse_MouseEnter);
            ellipse.MouseLeave += new System.Windows.Input.MouseEventHandler(ellipse_MouseLeave);
            ellipse.Width = 100;
            ellipse.Stroke = Brushes.Red;
            ellipse.StrokeThickness = 1;

            ImageBrush brush = new ImageBrush();
            ImageSourceConverter imageSourceConverter = new ImageSourceConverter();
            brush.ImageSource = (ImageSource) imageSourceConverter.ConvertFrom(@"c:\paper.jpg");
            ellipse.Fill = brush;

            ((Window)window).Content = ellipse;


        static void ellipse_MouseEnter(object sender, EventArgs e) {
            Ellipse ellipse = (Ellipse)sender;
            OuterGlowBitmapEffect effect = new OuterGlowBitmapEffect();
            effect.GlowColor = Colors.DeepPink;
            effect.GlowSize = 10;
            ellipse.BitmapEffect = effect;
        static void ellipse_MouseLeave(object sender, EventArgs e)
            Ellipse ellipse = (Ellipse)sender;
            ellipse.BitmapEffect = null;

jeudi 15 décembre 2011

C# - WCF services

Define a service to expose logic. Expose the interface to this logic at a certain endpoint, certain channel (in our case BasicHTTPBinding).
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using DM.PetShop;

namespace ConsoleApplication1
    class Program
        static void Main(string[] args)
            // service relies on an implementation   
            ServiceHost host = new ServiceHost(typeof(OrderService));

            // service is exposed through the intreface (i.e. contract)
            host.AddServiceEndpoint(typeof(IOrderContract), new BasicHttpBinding(), "http://localhost:9000/PetShop");

            // open the service ("fire and forget" call)

            // make sure the service doesn't die and print status
            Console.Title = String.Format("{0} is running ...", host.Description.Endpoints[0].Address);
            Console.Write("Server started. Press enter to stop..."); 

            // close after receiving a keystroke
            Console.WriteLine("Server stoppped. Press enter to quit...");

Here is the contract (a.k.a. interface) that will be exposed to the world
using System.ServiceModel;

namespace DM.PetShop
    [ServiceContract(Name = "PetShopOrderContract", Namespace = Constants.SERVICE_NAMESPACE)]
    public interface IOrderContract
        [OperationContract(Name = "PlaceOrder", Action = "PlaceOrder", ReplyAction = "PlaceOrderReply")]
        void PlaceOrder(string orderData);
Here the implementation (note the annotations,most important part)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;

namespace DM.PetShop
    [ServiceBehavior(Name = "DM.PetShop.OrderService", Namespace = Constants.SERVICE_NAMESPACE)]
    public class OrderService : IOrderContract
        public void PlaceOrder(string orderData)
            Console.WriteLine("Diagnostic message !");
Then write a client :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Channels;
using IOrderContractChannelFactory = System.ServiceModel.ChannelFactory;
using DM.PetShop;

namespace Project_Client1
    class Client1App
        static void Main(string[] args)
            IOrderContractChannelFactory factory = new IOrderContractChannelFactory(new BasicHttpBinding());
            IOrderContract channel = factory.CreateChannel(new EndpointAddress("http://localhost:9000/PetShop/"));
            channel.PlaceOrder("1 parrot");

            IClientChannel clientChannel = (IClientChannel)channel;
                if (clientChannel.State != CommunicationState.Closed)

mercredi 14 décembre 2011

Multithreading in C# (Java relies on the same foundation though)

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Threading;
using System.Collections.Generic;
using System.Diagnostics;

/// Summary description for JokeServer
public static class MOTDServer
    static Queue MessageQueue = new Queue();
    static Random rng = new Random();
    static Thread ProducerThread;

    static string[] Messages =
            "A bird in the hand is worth two in the bush",
            "A rolling stone gathers no moss",
            "A penny saved is a penny earned",
            "I'd rather have a bottle in front of me than a frontal lobotomy",
            "When life hands you lemons, make lemonade"

    private static void Init()
        ProducerThread = new Thread(ProduceMessages);
        ProducerThread.Priority = ThreadPriority.Lowest;

    public static string GetNextMessage()
        if (ProducerThread == null)

        string retval = null;

            while(MessageQueue.Count == 0)
            retval = MessageQueue.Dequeue();

        return retval;

    static void ProduceMessages()
        for (; ; )
            if (MessageQueue.Count == 0)

            Thread.Sleep(rng.Next(5000) + 2000);
            Debug.WriteLine("finished waiting");

C# - delegates and asynchronous programming

    // define the delegate needed for async calls below
    delegate List GetQuoteDelegate(DateTime dt);

    // Use Async invocation to request the quotes in parallel
    List[] GetQuotes(DateTime dt)
        ReservationServices reservationService = new ReservationServices();
        List[] retval = new List[3];

        List getQuoteDelegates = new List();


        CountdownEvent cde = new CountdownEvent(3);

        for(int i=0; i<3; i++)
            int localI = i;
            GetQuoteDelegate getQuoteDelegate = getQuoteDelegates[i];
                iar => {
                    retval[localI] = (List)getQuoteDelegate.EndInvoke(iar);

        // wait for all to be finished

        return retval;

lundi 12 décembre 2011

C# training - one more.

Material : sj qvn

Iterators and anonymous methods

- yield keyword - internal and external iterations - anonymous methods : for throwaway methods ...
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace ConsoleApplication1
    class Program
        static void Main(string[] args)
            foreach (int i in DivisibleBy(0, 50, 5))

        static IEnumerable DivisibleBy(int min, int max,int divisor) {
            for (int i = min; i < max; i++)
                if (i % divisor == 0) {
                    yield return i;


    class X_Enumerable : IEnumerable { 

        private int min;
        private int max;
        private int divisor;

        public X_Enumerable(int min, int max, int divisor)
            this.min = min;
            this.max = max;
            this.divisor = divisor;
        public IEnumerator GetEnumerator() {
            return new X_Enumerator(min, max, divisor); 

    class X_Enumerator : IEnumerator
        int min;
        int max;
        int divisor;
        int current;

        public X_Enumerator(int min, int max,int divisor)
            this.max = max;
            this.divisor = divisor;

        public Object Current
            get { return current; }

        public bool MoveNext()
            while (current % divisor != 0) {
                if (current == max) {
                    return false;
            return true;

        public void Reset()

        public void Dispose()
            throw new NotImplementedException();

LINQ to Objects

- anonymous types :
var p = new { Name = "Andy", Age = 21 };@@
using System;
using System.Collections.Generic;
using System.Text;

namespace LINQBase
    class Program
        static void Main(string[] args)
            var people = new List();
            people.Add(new Person { Name = "Nick", Height = 1.30m });
            people.Add(new Person { Name = "Jay", Height = 1.80m });
            people.Add(new Person { Name = "Bob", Height = 2.30m });

            foreach (var littlePerson in people.Where(p => p.Height < 2))

    public class Person
        public decimal Height { get; set; }
        public string Name { get; set; }

    public static class Utils {
        public static IEnumerable Where(this IEnumerable items, Predicate condition)
            foreach (T item in items)
                if (condition(item))
                    yield return item;


    CLR via C#, Second Edition
      Jeffrey Richter
    .Net 2.0
    .Net General
    Creating Workflow Services and Durable Services (MSDN)
    .Net 3.5
    Service Composition
    Data Binding with Windows Forms 2.0
      Brian Noyes
    .Net 2.0
    Windows Forms
    Essential ASP.NET 2.0
      Fritz Onion
      Keith Brown
    .Net 2.0
    Web Apps
    Essential ASP.NET With Examples in C#
      Fritz Onion
    .Net 2.0
    Web Apps
    Essential C# 2.0
      Mark Michaelis
    .Net 2.0
    C# Language
    Essential Windows Presentation Foundation
      Chris Anderson
    .Net 3.0
    Presentation Foundation
    Essential Windows Workflow Foundation
      Dharma Shukla
      Bob Schmidt
    .Net 3.0
    Workflow Foundation
    Learning WCF
      Michele Bustamante
    .Net 3.0
    Communication Foundation
    LINQ in Action
      Fabrice Marguerie
      Steve Eichert
      Jim Wooley
    .Net 3.5
    Programming .NET Components, 2nd Edition
      Juval Lowy
    .Net 2.0
    .Net General
    Programming WCF Services
      Juval Lowy
    .Net 3.0
    Communication Foundation
    Programming Windows Workflow Foundation
      K. Scott Allen
    .Net 3.0
    Workflow Foundation
    Smart Client Deployment with ClickOnce
      Brian Noyes
    .Net 2.0
    Windows Forms
    Understanding Windows CardSpace
      Vittorio Bertocci
      Garrett Serack
      Caleb Baker
    .Net 3.0
    Windows Forms 2.0 Programming (2nd Edition)
      Chris Sells
      Michael Weinhardt
    .Net 2.0
    Windows Forms
    Windows Presentation Foundation Unleashed
      Adam Nathan
    .Net 3.0
    Presentation Foundation

public class Book
        // Book properties
        public string Category { get; set; }
        public string Topic { get; set; }
        public string Title { get; set; }
        public decimal Price { get; set; }
        public string[] Authors { get; set; }
        public string WebSite { get; set; }

        // Book description
        public override string ToString()
            string output = string.Format("{0} by {1}",
                Title, string.Join(", ", this.Authors));
            output += string.Format("
{2}", Category, Topic, Price.ToString("c")); return output; } }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;

namespace LinqToXmlLab
    static class RssFeed
        public static XElement GetBooksXml(string url)
            XElement xml = XElement.Load(url); 
            return xml;

        public static List GetBooks(XElement xml)
            XNamespace ns = "";

            IEnumerable booksQuery = from b in xml.Elements(ns + "book") select
                new Book { Title = (string)b.Element(ns + "title"),
                           Category = (string)b.Element(ns + "category"),
                           Topic = (string)b.Element(ns+"topic"),
                           Price = (decimal)b.Element(ns + "price"),
                           WebSite = (string)b.Element(ns + "link"),
                           Authors = (from a in b.Element(ns + "authors").Elements(ns + "author") select (string)a).ToArray()

            return booksQuery.ToList();

        public static XElement GetFeedXml(List books) { 
            XElement xml = new XElement("rss", 
                new XAttribute("version", "2.0"), 
                new XElement("channel", 
                    new XElement("title", "Essential .Net Reading"), 
                    new XElement("link", "http://localhost:12345/books/"), 
                    new XElement("description", ".Net developer reading"), 
                    from b in books orderby b.Category, b.Topic, b.Title select new XElement(
                        new XElement("title", b.Title), 
                        new XElement("link", b.WebSite), 
                        new XElement("description", b)))); 
            return xml; 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Xml.Linq;

namespace LinqToXmlLab
    class Program
        static void Main(string[] args)
            HttpListener listener = new HttpListener();
            Console.WriteLine("Rss Feed Service is running");
            Console.WriteLine("Press Ctrl+C to terminate ...");

            while (true)
                HttpListenerContext ctx = listener.GetContext();
                using (StreamWriter writer = new StreamWriter(ctx.Response.OutputStream))
                    // Load xml from file
                    string url = @"..\..\books.xml";
                    XElement booksXml = RssFeed.GetBooksXml(url);

                    // Get books list
                    List books = RssFeed.GetBooks(booksXml);

                    // Convert books list to xml
                    XElement feedXml = RssFeed.GetFeedXml(books);

                    // Send xml to the reponse stream

samedi 2 juillet 2011

Who is occupying *my* port?

Annoying bind exception...
If it looks like : Address already in use

Then you might start your inquiry with the following command :

Windows : netstat -nab

OSX / Unix : lsof -i :9000


WTF, Firefox (might be Windows though) is responsible for the port occupation. Shut down Firefox, kill the annoying issue !

-> lsof == list open files -> man lsof

mardi 21 juin 2011

C# training day 7 : Dependency injection with MEF

Dummy example in just one class :

Lire la suite

lundi 20 juin 2011

C# training day 6

XAML, WPF and converters Write a stupid app that has 2 text boxes, each time a number is entered in the first, the second receives the double, and the first should as well reflect the second one if the second is changed.

Lire la suite

jeudi 9 juin 2011

C# training day 2

Today it is about getting familiar with the delegates and events programming paradigms (C# implementation of the observer pattern, Listeners in Java)

Lire la suite

lundi 6 juin 2011

C# training day 1

I'm getting serious about C# and had a course today on the basics : - C# overview - Visual Studio - Projects and assemblies - Collections - Generics We were finally given 2 exercises.

Lire la suite

mardi 23 juin 2009

Attending Jazoon

Weather is quite bad here in Zürich but well, I don't mind too much as I'll be attending Jazoon, THE java dev conference in Europe. I'll be blogging mainly for my employer but I'll tweet a lot, stay tuned :

Right now, opening keynote by James Gosling ! Edit 12:10 James Gosling's keynote was excellent, presenting shocking numbers and funny projects, in a nutshell :

  • 10 billions Java enabled devices in the world (yes billions)
  • 15 millions downloads of the JRE Java Runtime Environment a week
  • 6 millions Java developpers

Projects mentioned, built on Java (of course) :

  • brazilian healthcare system
  • hadron collider in Geneva
  • the Oyster card (London tube pass system)
  • project transforming a 6000 pounds lincoln car into an electric car, power management done by Java o' course

Then James did a little demo of the 2 ground breaking features of Java EE6, annotated servlets and EJB injection in servlets. I knew already about it, but it remains extremely handy and simplifies the EE development a great deal !

The talk closed with a little Java FX note and the future of computers, heading to massively parrallel computing instead of increasing GHz on single cores.

Afternoon sessions i attended were "RIA, security broken by design" and "JSF and Ajax @ Credit Suisse", quite obvious for the second one !
The RIA session was mostly about demoing XSS attacks and why using a framework is a good idea to enhance the security, nothing much. On the other hand, the CS-Jsf and Ajax session by Micha Kiener was extremely interesting and will hopefully impact my daily work as of Q3 2009. (Wait a minute Q3, really?).

Jazoon updates are starting to pop all around the blogosphere, in french even...Great !

dimanche 8 février 2009

Applets, Ajax ou Flex?

Pour donner suite à cet article.

D'un point de vue pragmatique, j'aurais plus comparé des frameworks dans un premier temps. Applet, par exemple n'en a pas à ma connaissance, il faudra tout programmer de A à Z, et comprendre les détails de la techno. Pour faire une RIA, ça va être long. Très long. Personne ne fait ça, c'est clair.

Ajax, à l'opposé dispose de très nombreux frameworks qui permettront d'aller directement à l'essentiel.

  • lightweight, javascript uniquement (Dojo, Striptaculous)
    • plus de contrôle
    • indépendance entre les technos UI et serveur
    • nombreux widgets
    • API pour la communication avec le serveur
  • end-to-end (.Net Ajax framework, IceFaces, Appcelerator)
    • pas de javascript
    • style de développement identique aux applis non Ajax (tags générant du HTML et du JS)
    • dépendance accrue entre les widgets et la techno serveur

Dans la mesure ou l'on parle d'un business model de développement en interne, les coûts vont être pour 0.2 dans le dev et 0.6 dans la maintenance (licences, serveurs etc sont probablement négligeables).

Avec la mobilité permanente des développeurs, investir dans une techno jeune et très marketée comme Ajax, c'est s'assurer une certaine perennité et des coûts de maintenance bas. Qui ne connait pas Ajax dans le principe...
A l'inverse, quel développeur veut marquer sur son cv "2008-2010 : développement d'applets".

Pour Flex, comme toute techno propriétaire, les ressources de dév et maintenance coûteront plus chers "par tête", mais seront probablement plus productives, de par l'intégration et la qualité de l'outillage.

Pour revenir au concret, mes récentes tentatives avec JSF puis iceFaces ont été bien accueillies par les développeurs (Ajax framework de .Net pour les Microsoft boys). Solutions maintenant éprouvées, légères, qui couvrent la majorité des besoins, simples à maintenir dans le sens ou elles sont standard.
Applets? Plusieurs legacy en ont, et c'est un véritable cauchemar en maintenance...
Allez un peu de recherche sur JavaFX maintenant !

lundi 5 janvier 2009

Java certificates...code snippet.

 * Copyright 2006 Sun Microsystems, Inc.  All Rights Reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.



public class InstallCert {

	public static void main(String[] args) throws Exception {
		String host;
		int port;
		char[] passphrase;
		if ((args.length == 1) || (args.length == 2)) {
			String[] c = args[0].split(":");
			host = c[0];
			port = (c.length == 1) ? 443 : Integer.parseInt(c[1]);
			String p = (args.length == 1) ? "changeit" : args[1];
			passphrase = p.toCharArray();
		} else {
					.println("Usage: java InstallCert [:port] [passphrase]");

		File file = new File("jssecacerts");
		if (file.isFile() == false) {
			char SEP = File.separatorChar;
			File dir = new File(System.getProperty("java.home") + SEP + "lib"
					+ SEP + "security");
			file = new File(dir, "jssecacerts");
			if (file.isFile() == false) {
				file = new File(dir, "cacerts");
		System.out.println("Loading KeyStore " + file + "...");
		InputStream in = new FileInputStream(file);
		KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
		ks.load(in, passphrase);

		SSLContext context = SSLContext.getInstance("TLS");
		TrustManagerFactory tmf = TrustManagerFactory
		X509TrustManager defaultTrustManager = (X509TrustManager) tmf
		SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);
		context.init(null, new TrustManager[] { tm }, null);
		SSLSocketFactory factory = context.getSocketFactory();

				.println("Opening connection to " + host + ":" + port + "...");
		SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
		try {
			System.out.println("Starting SSL handshake...");
			System.out.println("No errors, certificate is already trusted");
		} catch (SSLException e) {

		X509Certificate[] chain = tm.chain;
		if (chain == null) {
			System.out.println("Could not obtain server certificate chain");

		BufferedReader reader = new BufferedReader(new InputStreamReader(;

		System.out.println("Server sent " + chain.length + " certificate(s):");
		MessageDigest sha1 = MessageDigest.getInstance("SHA1");
		MessageDigest md5 = MessageDigest.getInstance("MD5");
		for (int i = 0; i < chain.length; i++) {
			X509Certificate cert = chain[i];
			System.out.println(" " + (i + 1) + " Subject "
					+ cert.getSubjectDN());
			System.out.println("   Issuer  " + cert.getIssuerDN());
			System.out.println("   sha1    " + toHexString(sha1.digest()));
			System.out.println("   md5     " + toHexString(md5.digest()));

				.println("Enter certificate to add to trusted keystore or 'q' to quit: [1]");
		String line = reader.readLine().trim();
		int k;
		try {
			k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1;
		} catch (NumberFormatException e) {
			System.out.println("KeyStore not changed");

		X509Certificate cert = chain[k];
		String alias = host + "-" + (k + 1);
		ks.setCertificateEntry(alias, cert);

		OutputStream out = new FileOutputStream("jssecacerts");, passphrase);

				.println("Added certificate to keystore 'jssecacerts' using alias '"
						+ alias + "'");

	private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();

	private static String toHexString(byte[] bytes) {
		StringBuilder sb = new StringBuilder(bytes.length * 3);
		for (int b : bytes) {
			b &= 0xff;
			sb.append(HEXDIGITS[b >> 4]);
			sb.append(HEXDIGITS[b & 15]);
			sb.append(' ');
		return sb.toString();

	private static class SavingTrustManager implements X509TrustManager {

		private final X509TrustManager tm;
		private X509Certificate[] chain;

		SavingTrustManager(X509TrustManager tm) { = tm;

		public X509Certificate[] getAcceptedIssuers() {
			throw new UnsupportedOperationException();

		public void checkClientTrusted(X509Certificate[] chain, String authType)
				throws CertificateException {
			throw new UnsupportedOperationException();

		public void checkServerTrusted(X509Certificate[] chain, String authType)
				throws CertificateException {
			this.chain = chain;
			tm.checkServerTrusted(chain, authType);


Highlighted by Syntaxhighlighter...What a nice tool !

lundi 8 septembre 2008


Development, a great job !

jeudi 4 septembre 2008

Chrome, the browser, by google

J'ai commençé un peu à tester le nouveau browser, nos amis canadiens diraient "butineur" ou navigateur, et la rapidité de chargement des pages est tout simplement incroyable. Comme d'habitude chez google la version mac est en retard, mais je l'attend avec impatience. Les grosses différences avec Firefox (le seul browser crédible sur cette terre avec Safari) sont

  • la présence des onglets non plus sous la barre d'adresse mais tout en haut de l'interface
  • l'incroyable rapidité
  • la promesse (il faut tester) de ne jamais rester bloqué sur un onglet mort
  • les onglets "détachables"

Les techies ont produit une petit bande dessinée dans le pur esprit google, amusante, sympathique et assez technique. Allez testez le !

mardi 3 juin 2008

Inject properties via a file with Spring

Easy !

<bean id="SAPconnectionProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location">

This configuration will create at runtime a Properties object and fill it with the properties contained in
Then i just have to inject this bean in a containing bean, which has indeed a member such as described below :

private Properties SAPconnectionProperties;
And appropriate getter and setter of course...

mardi 27 mai 2008

Spring, listener et ApplicationContext.

Dans le fichier de configuration web.xml de notre application, il est possible de déclarer des éléments "listener". Que font-ils? Comment Spring s'initialise grâce à eux?

Une classe listener implémenter l'une des deux super classe suivantes :

  • ServletContextListener
  • HttpSessionListener

Dans le premier cas, il faudra obligatoirement implémenter la méthode suivante : public void contextInitialized(ServletContextEvent ce)

Dans le second cas, il faudra implémenter entre autres : ublic void sessionCreated(HttpSessionEvent se)

A quoi tout cela peut il bien servir?
Oui exact, c'est ça, on obtient tout simplement ce qu'on appelle un hook sur les événements suivants (respectivement) :

  • création d'un ServletContext
  • création d'une session

Revenons en à Spring. Dés que l'application est démarrée, il nous faut le fameux "ApplicationContext Spring".
Très simplement, on va choisir de démarrer ce dernier par le biais d'une classe listener, qui sera déclarée dans le fichier web.xml comme suit :


Et bien sûr il existe une configuration par défaut pour le nom de fichier. S'il est déclaré comme suit, le listener le trouvera sans plus de configuration :
<param-value>/WEB-INF/classes/applicationContext.xml, /WEB-INF/classes/resources.xml</param-value>

Voila voila...(A noter qu'en fait, petit malin, j'ai passé deux fichiers de config).

vendredi 28 mars 2008

JEE authentication best practices for the web

4 authentication methods to identify a user with JAAS over HTTP

  • basic authentication : the popup asking for login/password, not encrypting anything :-C
  • digest-authentication : same as basic, with password encryption. Not a really nice user experience (login popups remind of the 90's :( )
  • certificate based authentication : HTTPS, using SSL, secured socket layer. first the usual PKI handshake (asymetric encryption) then the usual symetric encryption for performance. (A variant of this authentication is also managed for installations providing users PKI certificates, chip card format for example)
  • form based authentication, the usual HTML form...

How do i do that?

-> form based authentication, most often used :

  • add a security constraint and a security role in web.xml :
       <web-resource-name>All JSP direct access</web-resource-name>  
        No Access  

     <description>NO Access</description>  
  • edit the web.xml file to add a login-config block :

Then config your JAAS realm. Done. ;-)
-> Seriously. I'll complete the article later.

mercredi 26 mars 2008

Java annotations

Brief review of the Java annotations.

standard annotations
  • @Deprecated
  • @SuppressWarnings
  • @Override
  • @Inherited
  • @Retention(RetentionPolicy.SOURCE / RetentionPolicy.CLASS / RetentionPolicy.RUNTIME)
  • @Target(ElementType.CONSTRUCTOR / ElementType.METHOD / ElementType.PACKAGE / ElementType. ) (Note that more than one ElementType is allowed here).
additional annotations

Here we go. Now we want to developp our own annotation. Example...

 public @interface TODO { 
 	String value(); 
 	Level  level() default Level.NORMAL; 
 	public static enum Level { MINEUR, NORMAL, IMPORTANT }; 

This will be used as follows :

 @TODO(value="whatever message we want here describing the TODO...", level=NORMAL) 

Afterwards, we will have to tell the APT (annotation processing tool) what he is supposed to do with those annotations.
Source :

jeudi 14 février 2008

Récapitulatif sur l'API Java "Collections"

Un objet Collection modélise tout groupe d'objets Java.
Collection est une interface générale qui définit les méthodes suivantes :

 public boolean add(Object o); 
 public boolean addAll(Collection<? extends Object> c); 
 public void clear(); 
 public boolean contains(Object o); 
 public boolean containsAll(Collection<?> c); 
 public boolean isEmpty(); 
 public Iterator<Object> iterator(); 
 public boolean remove(Object o); 
 public boolean removeAll(Collection<?> c); 
 public boolean retainAll(Collection<?> c); 
 public int size(); 
 public Object toArray(); 
 public <T> T toArray(T a); 

Code Java d'une implémentation de test de Collection.

Traverser une collection

  1. Classiquement, avec un Iterator, ce qui est la bonne et l'unique manière de faire si l'on veut
    1. filtrer ou retirer des éléments (méthode remove())
    2. Itérer sur des collections multiples en parallèle
  2. Plus élegamment avec la nouvelle boucle for de Java 5 (2005, plus si nouvelle en fait...) (cf Note du JCP à propos de cette nouvelle boucle)
    for (String myCollectionItem : myCollection) {

Les sous interfaces de Collection (incluses dans le JDK, faîtes moi parvenir celles que vous avez écrites ;-) sont les suivantes :


Groupe d'objet dans lequel les doublons ne sont pas admis...
Aucune méthode ajoutée dans cette interface (tout est hérité de Collection)

  • HashSet : implémentation reposant sur une hashtable, meilleure performance
    • accès en temps constant, indépendant donc du nombre d'éléments
    • "null" est permis
    • l'implémentation n'est PAS threadsafe. (Voir le wrapper adapté si besoin)
  • TreeSet : set ordonné d'éléments (parfois beaucoup plus pratique, donc beaucoup plus coûteux)
    • la relation d'ordre utilisée pour le tri est celle implémentée par la méthode equals() de l'objet contenu dans le TreeSet...Classique.
    • temps d'éxecution en log(n) pour les opérations de base add remove et contain.
    • l'implémentation n'est PAS threadsafe.
  • LinkedHashSet implémentation basée sur une linkedlist...
    • l'insertion d'un élément déja présent ne modifie pas son emplacement (au sens de l'itération sur le set)
    • l'implémentation n'est PAS threadsafe.

Sun API page for Set


Collection d'objets ordonnée, dans laquelle on navigue par index.
Implémentation concrètes du JDK :

  • Linkedlist (liste chaînée) :
    • non synchronisée
    • adaptée à certains besoins style "queues"
  • Arraylist
    • Implémentation se redimensionnant automatiquement (resizable capacity)
    • non synchronisée
  • Vector
    • similaire à Arraylist, mais synchronisé/threadsafe, donc plus coûteux.

Sun API page for List


  • nouvelle collection (Java 5, 2005...)

Sun API page for List


Objet référençant des paires clés-valeurs. Evidemment, il n'est pas possible de dupliquer un clé.
A noter, la Map modélise l'abstraction mathématique connue sous le nom de fonction...Voila. :-)
Performance analogues aux hashsets...

  • HashMap<K, V>
  • LinkedHashMap<K, V>
  • TreeMap<K, V>
  • HashTable a été revue pour implémenter l'interface.

Sun API page for Map

Chacune des implémentation de List, Map et Set ont leurs avantages et leurs inconvénients, et c'est au développeur de choisir celle qui répond le mieux à ses besoins, dans un cadre de performance, optimisation de la consommation mémoire ou CPU...
Et les bon vieux tableaux? Non. Ils n'implémentent pas Collection. Il existe cependant une passerelle, la méthode toArray().

mercredi 30 janvier 2008

Transformation isdentité avec XSLT

Cette transformation peut être adaptée à souhait selon le but.
Dans la majorité des cas, migration de données, XML vers XML, avec une structure différente, ou encore pour éliminer du contenu sans information (tags inutiles etc.).

<xsl:stylesheet version="1.0" xmlns:xsl="">
   <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
   <xsl:template match="node() | @*">
         <xsl:apply-templates select="node() | @*"/>

mardi 15 janvier 2008

Outillage pour HTTP

La librairie "Jakarta HTTP components" du projet Apache fournit de nombreux utilitaires pour construire simplement des requêtes HTTP, simuler un proxy ou encore intégrer du HTTP dans un client lourd.

lundi 14 janvier 2008

Browse DOM elements with Javascript

Browse all the tables of your document, for example :

  for (var i=0;i<document.getElementsByTagName("table").length;i++) {
     alert("Table "+i+" : "+document.getElementsByTagName("table")i.innerHTML);

jeudi 6 décembre 2007

Forward de ports...

Bon. On a besoin de tester un produit dont la license est limitée à l'usage sur l'hôte localhost? Bon. Une petite manip simple peut nous aider à le tester quand même sur des hôtes distants.
Il suffit en fait d'ouvrir un port d'écoute localement (comme le fait tout serveur) par exemple le port XXX. Bon. On lie ensuite ce port via une connection distante sur le protocole ssh à la machine distante. Et le tour est joué. Le navigateur demande l'url localhost port XXX : http://localhost:XXX et le système d'exploitation sait qu'il faut alors faire suivrela demande à la machine distante via la connection ssh préalablement ouverte...
Mais ça le browser n'en a pas connaissance. Il croit que le serveur contacté est bien local. Magie.

Donc la commande magique pour ouvrir le port local vers le port distant via ssh :
ssh –L local_port: remote_machine_name:remote_port login@remote_machine_name


mercredi 5 décembre 2007

Paradigmes objet et relationel

Paradigme : Un paradigme est une représentation du monde, une manière de voir les choses [...] wikipedia.
La suite? ->

Lire la suite

mardi 4 décembre 2007

Tomcat, JNDI et resources factories.

Configuration(s) de JNDI

Tomcat offre un service de nommage JNDI, par webapp depuis la version 5.5. Comment le configurer et y accéder?
Il faut, si l'on veut insérer une information dans le context général, commun à toutes les applications tournant sur le serveur, ajouter les lignes suivantes dans $TOMCAT_HOME/conf/context.xml : (exmple pour une datasource)

  <Resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource"

Si l'on veut restreindre l'acessibilité du contexte à une application web, il suffit de créer un fichier context.xml contenant les lignes ci-dessus (dans un tag <context></context>) dans le répertoire META-INF de la webapp et de déployer sous forme d'archive web (war).

On accédera ensuite à l'objet avec un code de type

Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");

if (envCtx == null)
   throw new Exception("Boom - No Context");
   DataSource ds = (DataSource) envCtx.lookup("jdbc/TestDB");
   if (ds != null) {
      Connection conn = ds.getConnection();
      // etc etc...

A noter que le registre JNDI de Tomcat est readonly, il n'est donc pas modifiable par programmation. On ne peut le configurer qu'au démarrage du serveur ou lors du déploiement d'une application...

Les "resources factories" proposées par Tomcat

Donc non seulement le service JNDI de Tomcat nous a permis de référencer une source de données, nous permettant ainsi de nous affranchir d'un nommage (et d'un paramétrage) dans l'application elle même, mais en plus, comme on le voit dans le code ci-dessus, Tomcat nous simplifie encore une étape en construisant pour nous l'objet Java Datasource directement, sur la base des infos JNDI.
Tomcat dispose en effet de "ressources factories", dans le cas ci-dessus, nous avons utilisé la "datasource factory". Ok quelles sont les autres?
De base, Tomcat fournit les factories suivante :

  • JDBC datasource factory
  • Javamail session factory
  • Javabean factory (similaire à Spring, en un sens)

On peut ensuite intégrer sa propre factory d'objet à Tomcat si l'on en ressent le besoin, une custom factory en fait...
Plus ici.

lundi 3 décembre 2007

Générer un fichier war avec Ant

De manière automatisée, il suffit de dire à Ant ou est le descripteur de déploiement web.xml, les classes Java et le tour est joué :

<target name="war" depends="compile">
   <war destfile="hibernate-tutorial.war" webxml="web.xml">
       <lib dir="${librarydir}">
         <exclude name="jsdk*.jar"/>
       <classes dir="${targetdir}"/>

vendredi 30 novembre 2007

Les basiques de la base de donnée HSQL

HSQLDB est un SGBD (systême de gestion de base de données) qui offre une alternative simplifiée pour le prototypage et le développement rapide d'application.
Ô joie, un client qui permet de se connecter à la base et de regarder un peu ce qu'il s'y passe est livré avec. Plus besoin de télécharger Squirrel SQL, le driver JDBC pour HSQL...Déja 20 minutes de gagnées.

Bref, on télécharge ici :, on dézippe, et on copie le jar nommé hsqldb.jar contenu dans le dossier lib de notre projet.
Ensuite, on peut lancer le serveur HSQL à la ligne de commande : java -classpath lib/hsqldb.jar org.hsqldb.Server

Ou si on est un inconditionnel de Ant :
<java classname="org.hsqldb.Server" fork="yes">
<fileset dir="./lib" includes="*.jar"/>

Log de démarrage classique...

Ensuite on peut démarrer le client pour passer des commandes SQL : java -classpath lib/hsqldb.jar org.hsqldb.util.DatabaseManager -driver org.hsqldb.jdbcDriver -url jdbc:hsqldb:hsql://localhost/ -user sa

Ou cible Ant once again :

<java classname="org.hsqldb.util.DatabaseManager" fork="yes">
<classpath path="./lib" />
<arg value="-driver" />
<arg value="org.hsqldb.jdbcDriver" />
<arg value="-url" />
<arg value="jdbc:hsqldb:hsql://localhost/" />
<arg value="-user" />
<arg value="sa" />

Hop. On passe quelques commandes SQL par exemple celles décrites ici pour créer un schéma et les autres...

Récupérer l'archive du projet Eclipse avec le fichier Ant qui va bien :

La documentation complète en français.

vendredi 23 novembre 2007

JVM trace capabilities

In the old Unix world, a huge toolset was used to trace, optimize, analyze the software behavior.
With Java, you might easily use the wrong implementation of an API thus getting lousy performance. Or you might just write crappy/unadapted/inefficient code (What?).
Sun's JVM's offer a way to track performance bottlenecks in various ways, with the java option HPROF. Some examples :
Before :

   java MyJavaProg

After :

   java -Xrunhprof:cpu=samples,depth=15,file=trace.log MyJavaProg

The JVM hprof command supports different options, depending on the java version you have. Check which one you have with :

   java -Xrunhprof:help

On my machine (Java 1.4.2, i know...) :

The hidden part of the Iceberg?

mercredi 7 novembre 2007

Extreme programming [republié/révisé]

cette n-ième nouvelle méthode de développement logiciel a le mérite d'apporter des réponses concrêtes à des problèmes récurrents sur les projets de taille moyenne et grande : l'intégration, le travail en groupe, les spécifications/expressions de besoins, la documentation...

Lire la suite

mardi 30 octobre 2007

Lister un répertoire en filtrer selon les extensions...

File dir = new File("./");

FilenameFilter filter = new FilenameFilter();
public boolean accept(File dir, String name) {
return name.endsWith(".log");
// notre tableau de strings avec les noms des fichiers présents...
String files = dir.list(filter);

mercredi 17 octobre 2007

Another ant trick

need to print the ant version at build, just because?

<echo message="******************** " />
<echo message="${ant.version}" />
<echo message="******************** " />

Done !
Java version?

<echo message="******************** " />
<echo message="${}" />
<echo message="******************** " />

Secure copy over the network with ant :

<scp todir="${username}:${password}@${host}:${destination_dir}" trust="true">
<fileset dir="${src_dir}"/>

This ant task, however, needs additional libs : check for the keyword scp here... Afterwards, if you use Eclipse to run ant, you need to do the following :

Go into Eclipse then click on Window->Preferences->ant->Runtime, then select 'Ant Home Entries (Default). Click on the button 'Add External JARs'. Locate the jar file you copied, select it and hit 'OK'.

Need to tell Ant about the proxy?
set ANT_OPTS=-Dhttp.proxyHost=myproxy -Dhttp.proxyPort=3128

jeudi 4 octobre 2007

Nouveau magasin en ligne Sunrise

Sunrise, opérateur télécom actif depuis une dizaine d'année sur le marché Suisse, livre son nouveau magasin en ligne 8-)
La mission a été longue mais tout se termine dans les temps, nous sommes passé en production depuis ce matin ! Le shop est consultable par tous à l'adresse suivante :

Le site est entièrement disponible en 3 langues, Allemand, Français et Italien, il permet de commander des forfaits, des téléphones mobiles ainsi que des cartes pour se connecter à internet par le réseau mobile de Sunrise.

mardi 17 juillet 2007

Windows - "minimize all windows" shortcut

This stupid shortcut disappeared from the taskbar?
Open Notepad, copy paste the following code :


Then save the file on the desktop naming it XXX.scf
Here you go.

mardi 26 juin 2007

Why do we need setters and getters actually?

don't use public attributes, use getters and setters
This can be read everywhere and everybody knows that. But why? What is the reason behind that? Well...
It's because you don't want people to flatten your cat.8-O
Ok here is your code :
public class Cat {
public int size;

And here is your buddy's code :
public static void main(String args) {
Cat myCat = new Cat();
myCat.size = 0;

Here we are. Now the poor cat looks like a pile of pancake. Weight watchers pancakes even.
The goal of writing getters and setters (right names for these actually being accessors and mutators, but who cares) is to protect the cat from the being flattened :
public class Cat {
private int size;
public int getSize() {
return size;
public void setSize(int size) {
if(size > 5)
this.size = size;

The cat cannot be flattened. The size attribute is private and can be changed only via the setter.
This concept seems pretty straightforward. However, it is one of the main reason the 3 tiers architecture is so successful these days :
View <-> Business comps <-> Data
Instead accessing the data directly, you have to use the business components to modify the data, and those business components contain the business rules and prevent some crazy things to happen on the data !

Getters and setters in Eclipse

vendredi 8 juin 2007

Tester son proxy sous cygwin

Un petit outil bien pratique vient avec Cygwin, curl. Celui-ci permet d'afficher le code HTML d'une page web par exemple. Utile si on veut tester qu'on a accès à internet via Cygwin, et que ping est...interdit ! Pourr setter le proxy dans Cygwin ou dans toute console tournant sous Windows, il faut setter la variable http_proxy :

export http_proxy=""

Après quoi :

curl retourne le code HTML de la page de garde de Google...

Voila. Maintenant, rien à voir, les stats du blog :

Jui Aou Sep Oct Nov Déc Jan Fév Mar Avr Mai

jeudi 31 mai 2007

L'histoire du tunnel SSH

Construire un tunnel crypté de sa machine locale à chez soi ou à un site distant est parfois souhaitable.

Lire la suite

vendredi 11 mai 2007

Use dates with ant

Need to generate a jar file including the current date in your ant script?
Here :

<tstamp/> <!-- extract the system date to the ant environment -->
<jar destfile="${build}/${DSTAMP}-${TSTAMP}" etc.

Hope that helps someone somewhere !

dimanche 18 mars 2007

Burning utilities on Unix/Linux/Mac Os X

Build an iso file from a cd/dv/usb key/directory

  1. check the mounted medias : diskutil list
  2. unmount the media : diskutil unmountDisk /dev/disk1
  3. extract the iso file : dd if=/dev/disk1 of=my_file.iso bs=2048

Burn the iso file on a cd/dvd :

hdiutil burn my_file.iso
Usb key / SD card : diskutil list to identify where the key is
Go to the disk utility in Apps -> Utilities and unmount all partitions of this usb key dd if=myiso.iso of=/dev/dikSomething Done...

mercredi 21 février 2007

XML update...

Under which conditions is my XML document valid?

  1. the document validates the xml formatting rules :
    • XML documents must have a root element
    • XML elements must have a closing tag
    • XML tags are case sensitive
    • XML elements must be properly nested
    • XML attribute values must always be quoted
    • check everything regarding your XML document syntax with this online validator
  2. the document validates against the DTD !

What are XML data islands?

Data islands are a way to introduce xml data in an HTML document in Internet Explorer only ;-( with the special HTML tag <xml>.
This is very very very probable that you do not want to do that because it will NOT be supported by any other browser
More on XML data islands

XML namespace

Namespaces are usually used to avoid conflicts between tags having the same name but not the same meaning (semantically differents ;-) ).
Example : xmlns:namespace-prefix="namespaceURI"

The CDATA tag

All text in an XML document will be parsed by the parser.
Only text inside a CDATA section will be ignored by the parser.
Example : <!CDATA[ myjavascript code... ]>

vendredi 16 février 2007

Tuning the logging level in Tomcat

Little tip in case ou want to have HIGHER level of logging from tomcat (version 5.5 or higher), because he fails to do something but just says failure ;-)
Tomcat, out of the box, does not include any logging library. However, if you want to make some fine-tuning on the logging, he is ready to achieve your configuration.
At startup (my guess...) Tomcat checks if some special configuration has to be applied, via the "bridge" interface commons logging . This library can be described as a logging implementation abstraction layer. If so, he applies it. Commons logging interface hides the actual implementation, that is, you can use either log4j or any alternative behind the scenes.
Anyway, drop the commons logging and log4j jar files in the common/lib directory, write a file in the common/classes directory, and you should be fine. example :

log4j.rootLogger=ERROR, A1

# Print the date in ISO 8601 format
log4j.appender.A1.layout.ConversionPattern=%d %t %-5p %c - %m%n

Pour tester tout ça, rapatriez ce petit projet JSF dans eclipse, ant compile et deploy...

Environment variables in Java

also looking for two lines of code to access the Tomcat directory seamlessly?
Works for any environment variable o' course...

public static void main(String args) {
String tomcatHome = System.getenv("TOMCAT_HOME");
System.out.println("Tomcat Home vaut : "+tomcatHome);

vendredi 9 février 2007


Finalement, la frontière entre les specs fonctionnelles et techniques est souvent trop peu marquée, de même que la frontière entre les spécifications techniques et l'architecture... Voila quelques exemples tout bêtes qui m'en ont fait comprendre plus que les absconces définitions habituelles :

Les spécifications fonctionnelles (le plus facile) décrivent des comportements et aspects du systême:

  • authentification
  • navigation
  • contenu des vues

Les spécifications techniques décrivent des qualités du systême, par exemple :

  • scalabilité
  • performance
  • résistance aux pannes (exemple tolérance 99.9%)

On en vient à MDA : model driven architecture, qui est une nouvelle approche de la conception logicielle.
MDA tend à découpler au maximum la conception et l'architecture, et également à produire directement le code à partir du modèle.
La conception traite les spécifications fonctionnelles et l'architecture les specs techniques.
Ainsi, si l'on conçoit un modèle conceptuel implémentant les spécifications fonctionnelles, et que l'on a un traducteur modèle->architectureX qui va produire le code selon l'architecture X, on obtient les effets suivants :

  • chaque modification des spécifications implique une modification du modèle, et une nouvelle génération (automatique !) du systême.
  • Si finalement l'architecture X ne répond pas ou répond mal aux specs techniques, on change le traducteur et on prend modèle->architectureY, ce qui génère automatiquement une solution technique totalement diffèrente, mais implémentant exactement de la même manière les specs fonctionnelles !

C'est presque magique. Plus qu'à acheter les traducteurs...Voila le problème...Ils ne sont pas en rayon chez Monoprix ou Migros et en écrire un soi même, c'est comme pour les langues. Si on sait juste dire bonjour en chinois on fera un traducteur qui ne sait faire qu'un "hello world".
MDA reste une technologie extrêmement prometteuse, en particulier pour la création de maquettes. Lorsqu'on a construit un traducteur incluant un pan raisonnable d'une technologie, il est possible de construire une application avec des fonctionnalités basiques en quelques minutes.
Avec deux traducteurs, exemple Java EE et .Net, on pourra aller jusqu'à effectuer des comparatifs d'architecture.

Article sur wikipedia

lundi 5 février 2007

Syntaxe wiki Dotclear

Pour publier un article sur un blog Dotclear, on peut écrire directement en html, ce qui est mal, pour les raisons décrites ici, ou écrire dans un syntaxe wiki somme toute très simple. Par malheur, cette syntaxe est propre à Dotclear et n'est qu'à peu près compatible avec la syntaxe wiki de wikipedia par exemple.
Bref, le pense-bête que je perd tout le temps est ici, et en particulier, il dit comment publier

  • du code : @@code@@
  • insérer du HTML, parce que parfois on n'a pas le choix, par exemple si l'on veut insérer un clip Vimeo ;-) :

mon code html avec <br/> saut de lignes <i>en italique</i>
donnera :

mon code html avec
saut de lignes en italique