Off the record

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

jeudi 5 juillet 2018

Docker on glcoud

1 sudo apt-get update

   2  sudo apt-get install nginx
   3  sudo apt-get update
   4  sudo apt-get install nginx
   5  nginx -v
   6  curl
   7  sudo systemctl start nginx
   8  sudo systemctl status nginx
   9  curl
  10  sudo apt-get install
  11  sudo docker images
  12  sudo docker pull nginx:1.10.0
  13  sudo docker images
  14  sudo dpkg -l | grep nginx
  15  sudo systemctl stop nginx
  16  sudo dpkg -l | grep nginx
  17  sudo docker pull nginx:1.10.3
  18  sudo apt-get update
  19  sudo apt-get install nginx
  20  sudo dpkg -l | grep nginx
  21  sudo docker images
  22  sudo docker remove nginx:1.10.0
  23  docker help
  24  sudo docker rm nginx:1.10.0
  25  sudo docker rmi nginx:1.10.0
  26  sudo docker images
  27  sudo dpkg -l | grep nginx
  28  sudo docker images
  29  sudo docker run -d nginx 1.10.3
  30  sudo docker images
  31  sudo docker rim nginx:latest
  32  sudo docker rmi nginx:latest
  33  docker ps
  34  sudo docker ps
  35  sudo docker rmi nginx
  36  sudo docker run -d nginx:1.10.3
  37  sudo docker ps
  38  sudo docker run -d nginx:1.10.3
  39  sudo docker ps
  40  sudo docker run -d nginx:1.10.0
  41  sudo docker ps
  42  sudo docker stop ngingx:1.10.0
  43  sudo docker stop
  44  sudo docker stop %1
  45  sudo docker stop f7eb5251903e
  46  sudo docker ps
  47  sudo docker inspect 9fd0e1a65bc4
  48  curl
  49  sudo docker ps
  50  sud docker inspect pensive_morse
  51  sud docker inspect --format ' .NetworkSettings.IPAddress ' pensive_morse
  52  sudo docker inspect pensive_morse
  53  sudo docker inspect --format ' .NetworkSettings.IPAddress ' pensive_morse
  54  CN='pensive_morse'
  55  sudo docker inspect --format ' .NetworkSettings.IPAddress ' $CN
 133  sudo docker build -t 1.0.0 .
 134  cat Dockerfile
 135  sudo docker images
 143  sudo docker inspect hungry_tesla
 144  curl
 145  curl
 146  curl
 147  sudo docker ps
 148  sudo docker inspect heuristic_payne
 149  curl
 150  sudo docker ps
 151  sudo docker ps -a
 152  sudo docker ps -aq
 154  curl
 155  sudo docker inspect heuristic_payne
 156  curl
 158  sudo docker inspect hungry_tesla
 159  curl
 160  docker tag -h
 161  sudo docker tag monolith:1.0.0 nicolasb/monolith:1.0.0
 162  sudo docker login
 163  sudo docker push nicolasb/monolith:1.0.0
 165  sudo docker tag hello:1.0.0 nicolasb/hello:1.0.0
 166  sudo docker push nicolasb/hello:1.0.0
 167  sudo docker tag hello:1.0.0 nicol4sb/hello:1.0.0
 168  sudo docker push nicol4sb/hello:1.0.0
 169  sudo docker tag monolith:1.0.0 nicol4sb/monolith:1.0.0
 170  sudo docker push nicolasb/monolith:1.0.0
 171  sudo docker push nicol4sb/monolith:1.0.0
 172  sudo docker ps
 173  sudo docker tag monolith:1.0.0 nicol4sb/auth:1.0.0
 174  sudo docker tag auth:1.0.0 nicol4sb/auth:1.0.0
 175  sudo docker push nicol4sb/auth:1.0.0

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

lundi 11 septembre 2017


Git clone abc/def/something.git

git status

git checkout -b my-branch

# some edits

git status

git add my-file-to-commit

git status // tells you in which branch you're working and changes

git commit // commits what is to be comitted

git push origin my-branch // pushes changes from my-branch to the original repo

git status

Docker and continuous deployment workshop

docker volume ls

docker ps -a

docker start

docker stop

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 28 février 2015

test hard drive speed

dd if=/dev/zero bs=100k of=/Users/nick/tstfile count=1024 2>&1 | grep sec | awk '{print $1 / 1024 / 1024 / $5, "MB/sec" }'

disque normal : 33,3333 MB/sec

SSD : 133.884 MB/sec

lundi 16 février 2015


  • Mad men
  • True detective
  • House of cards
  • top of the lake
  • Elementary
  • The good wife (suggested by wife, ironically)
  • Breaking bad
  • Downton abbey

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

mercredi 18 mai 2011

Read a file in Java (with somewhat recent APIs...)

FileReader fr = new FileReader(fileLocation); // read a file

BufferedReader br = new BufferedReader(fr);

String tmp = br.readLine();

while (tmp != null) { content.append(tmp + "\n"); tmp = br.readLine(); } br.close();

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 !

mercredi 4 mars 2009

Big numbers

GDP France 2007 : 1892 Billions EUR[1]
State budget France 2007 : 355 Billions EUR [2]

GDP world 2007 : 78 360 Billions USD[3]
Average daily trading volume on the FX market : 4000 Billions USD[4]
Average daily trading volume in NYSE : 87 Billions USD[5]

Paulson plan : 700 Billions USD[6]
USA federal budget : 2979 Billions USD[7]

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 !

lundi 16 juin 2008

Update an XML node with Java and XPathAPI

Once you have the Document object, and want to update a Node...

Element e = (Element) XPathAPI.selectSingleNode((Node) document.getDocumentElement(), xpath);

That's it.

-> Might be smart to check that e is not null before trying to set the content ! :-)

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...

vendredi 30 mai 2008

do you believe this is in China?

do you believe this is in China?
Originally uploaded by Emili@.
Photo d'une église située à Chengdu en Chine (prise au Holga !) qui a été depuis totalement détruite par le tremblement de terre, cf les commentaires...

La présence missionaire dans ce coin date des premières missions du Sichuan qui ont démarré vers le milieu du XVIIIéme. Plus d'infos quelqu'un?

Concernant la ville de Chengdu, sa taille a justifié la présence d'un consulat français depuis le début du XXéme siècle, et le deuxième consul de Chengdu, Albert Bodard était le père de Lucien Bodard qui écrira plus tard une série de cinq bouquins sur la guerre d'Indochine que je vous recommande si ça vous intéresse et/ou que vous n'arrivez pas à dormir.

Mais c'est ou en fait Chengdu?
Les missions étrangères de Paris en Chine
Un peu d'histoire de la présence française à Chngdu

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).

lundi 26 mai 2008


Le buzz monte autour de Twitter, et commoncraft, qui avait fait une vidéo géniale pour expliquer ont récidivé sur twitter. Enjoy ->

Lire la suite

vendredi 23 mai 2008

Zattoo dispo en France...

Ici à Zürich, plus précisément à Oerlikon, tout près de chez nous, s'est développée une société qui propose un logiciel de télé via internet. Du streaming comme on dit. La chose s'appelle zattoo (deux t deux o) et ça marche tout à fait correctement.
Du coup on regarde "plus belle la vie", mais ça c'est mal.
Bref beaucoup de gens qui sont passés chez nous auraient aimé bénéficier de Zattoo en France, mais jusqu'à récemment, le service n'était offert qu'en Suisse.
Voila donc la news, zattoo est disponible en France.
Rendez-vous sur pour installer le logiciel et regarder la télé dés que vous êtes connecté à internet. Claaaaasse. Pleins de chaînes super utiles telles que gustoTV en plus...Que demande le peuple?
La breaking news ici. Tiens 4 mois de retard sur celle-là !

mercredi 21 mai 2008

Spam et hébergement

Juste un rapide article pour signaler que free adopte désormais une politique agressive pour contrôler les spams sur les blogs, sous dotclear en particulier.
En pratique, si vous avez dotclear 1.x et un antispam tel que spamplemousse qui redirige les spams vers la base de données et que vous ne videz pas régulièrement la table en question, free bloque votre compte. Premier et avant dernier avertissement.
Pour réactiver le compte, il faut aller dans la console d'administration de free :
Ensuite il faut cliquer sur réactiver mon compte (libellé approximatif là...)
Après quoi free vous informe de la raison pour laquelle votre compte a été bloqué, et vous invite à ne pas faire de boulette dans le futur, à vider proprement les tables de spam etc.
Et dans un délai de 24h (72h pour le deuxième et dernier avertissement) le compte est réactivé.
En conséquence, pour ceux qui ne checkent pas leur tabe de spam régulièrement, spamclear est un plugin qui permet de vider automatiquement les spams, sans les écrire en base...Juste pour être sur ;-)
Toutes les infos détaillées sur ce blocage et les plugins pour remédier à cette facheuse situation :

lundi 14 avril 2008 c'est quoi?

Le site de "social bookmarking" a quatre ans et déja des centaines de milliards d'utilisateurs dans la galaxie. Pas vous? Regardez la vidéo qui suit, ça explique comment delicious c'est trop bien et tout et tout.

Lire la suite

mardi 8 avril 2008

Flickr video...

Voila, flickr annonce la possibilité de charger des vidéos désormais, limitées en durée à 90 secondes. Quand même.
Petit bonus pour ceux qui font des très grosses photos, la limite de taille de photo n'est plus de 10 mégas mais de 20 ! Pratique pour tous ceux qui scannent, du film ou des photos.
Pour les autres ça le deviendra vite avec l'arrivée d'appareils photo avec des plus gros capteurs. The bigger the better?
Sinon j'ai testé, ça fonctionne sans soucis...

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 :

vendredi 7 mars 2008

Thank you gmail...

jeudi 21 février 2008

Crise des subprimes

Les "primes" -> personnes physiques ou morales présentant une solvalibilité correcte, sans risque élevés. Les gens à qui une banque prête classiquement de l'argent.
Les subprimes -> emprunteurs moins solvables, avec un risque ou un historique de faillite, de défaut de paiement etc.

Lire la suite

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.