<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2frenchfull.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Blog d’Ippon Technologies</title>
	
	<link>http://blog.ippon.fr</link>
	<description>Les experts Java EE, Portail et SOA</description>
	<lastBuildDate>Sun, 05 Feb 2012 19:42:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/LeBlogDesExpertsJ2ee" /><feedburner:info uri="leblogdesexpertsj2ee" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:feedFlare href="http://add.my.yahoo.com/content?lg=fr&amp;url=http%3A%2F%2Ffeeds.feedburner.com%2FLeBlogDesExpertsJ2ee" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/bn/intatm_fr_1.gif">Subscribe with Mon Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2FLeBlogDesExpertsJ2ee" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://feeds.feedburner.com/LeBlogDesExpertsJ2ee" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.feedburner.com%2FLeBlogDesExpertsJ2ee" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2FLeBlogDesExpertsJ2ee" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2FLeBlogDesExpertsJ2ee" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><feedburner:feedFlare href="http://www.plusmo.com/add?url=http%3A%2F%2Ffeeds.feedburner.com%2FLeBlogDesExpertsJ2ee" src="http://plusmo.com/res/graphics/fbplusmo.gif">Subscribe with Plusmo</feedburner:feedFlare><feedburner:feedFlare href="http://www.thefreedictionary.com/_/hp/AddRSS.aspx?http%3A%2F%2Ffeeds.feedburner.com%2FLeBlogDesExpertsJ2ee" src="http://img.tfd.com/hp/addToTheFreeDictionary.gif">Subscribe with The Free Dictionary</feedburner:feedFlare><feedburner:feedFlare href="http://www.bitty.com/manual/?contenttype=rssfeed&amp;contentvalue=http%3A%2F%2Ffeeds.feedburner.com%2FLeBlogDesExpertsJ2ee" src="http://www.bitty.com/img/bittychicklet_91x17.gif">Subscribe with Bitty Browser</feedburner:feedFlare><feedburner:feedFlare href="http://www.live.com/?add=http%3A%2F%2Ffeeds.feedburner.com%2FLeBlogDesExpertsJ2ee" src="http://tkfiles.storage.msn.com/x1piYkpqHC_35nIp1gLE68-wvzLZO8iXl_JMledmJQXP-XTBOLfmQv4zhj4MhcWEJh_GtoBIiAl1Mjh-ndp9k47If7hTaFno0mxW9_i3p_5qQw">Subscribe with Live.com</feedburner:feedFlare><feedburner:feedFlare href="http://mix.excite.eu/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2FLeBlogDesExpertsJ2ee" src="http://image.excite.co.uk/mix/addtomix.gif">Subscribe with Excite MIX</feedburner:feedFlare><feedburner:feedFlare href="http://www.webwag.com/wwgthis.php?url=http%3A%2F%2Ffeeds.feedburner.com%2FLeBlogDesExpertsJ2ee" src="http://www.webwag.com/images/wwgthis.gif">Subscribe with Webwag</feedburner:feedFlare><feedburner:feedFlare href="http://www.podcastready.com/oneclick_bookmark.php?url=http%3A%2F%2Ffeeds.feedburner.com%2FLeBlogDesExpertsJ2ee" src="http://www.podcastready.com/images/podcastready_button.gif">Subscribe with Podcast Ready</feedburner:feedFlare><feedburner:feedFlare href="http://www.wikio.com/subscribe?url=http%3A%2F%2Ffeeds.feedburner.com%2FLeBlogDesExpertsJ2ee" src="http://www.wikio.com/shared/img/add2wikio.gif">Subscribe with Wikio</feedburner:feedFlare><feedburner:feedFlare href="http://www.dailyrotation.com/index.php?feed=http%3A%2F%2Ffeeds.feedburner.com%2FLeBlogDesExpertsJ2ee" src="http://www.dailyrotation.com/rss-dr2.gif">Subscribe with Daily Rotation</feedburner:feedFlare><item>
		<title>Monitorer une JVM en local</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/MIKPf_Y16vw/</link>
		<comments>http://blog.ippon.fr/2012/02/05/monitorer-une-jvm-en-local/#comments</comments>
		<pubDate>Sun, 05 Feb 2012 19:40:52 +0000</pubDate>
		<dc:creator>Fabien ARRAULT</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[jconsole]]></category>
		<category><![CDATA[JMX]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4967</guid>
		<description><![CDATA[<p>Le JDK de Sun/Oracle propose plusieurs outils et APIs pour monitorer une jvm locale et ceci, depuis le JDK 6, sans avoir besoin de configurer cette jvm de manière particulière (enfin, ca c&#8217;est dans les cas simples nous verrons qu&#8217;il faut parfois ajouter une petit option)</p> Les outils du JDK <p>Le JDK propose deux utilitaires <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/02/05/monitorer-une-jvm-en-local/">Monitorer une JVM en local</a></span>]]></description>
			<content:encoded><![CDATA[<p>Le JDK de Sun/Oracle propose plusieurs outils et APIs pour monitorer une jvm locale et ceci, depuis le JDK 6, sans avoir besoin de configurer cette jvm de manière particulière (enfin, ca c&#8217;est dans les cas simples <img src='http://blog.ippon.fr/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  nous verrons qu&#8217;il faut parfois ajouter une petit option)</p>
<h1>Les outils du JDK</h1>
<p>Le JDK propose deux utilitaires avec une interface graphique : JConsole et JVisualVM. Le premier permettant principalement d&#8217;accéder facilement aux MBeans JMX exposés par la JVM. Le deuxième étant beaucoup plus complet, en particulier si vous utilisez les plugins en téléchargement optionnel.</p>
<p>Il propose aussi des outils en ligne de commande : jps (liste des process java), jstat (statistique sur le jvm en particulier sur l&#8217;état de la mémoire), jstack (pour demander un thread dump), jmap (pour demander un heap dump),&#8230; tous présents dans le répertoire bin du JDK</p>
<p>Ces outils sont soumis à quelques restrictions :</p>
<ul>
<li>certaines sont liées à des questions de sécurité. En particulier, ils ne sont souvent utilisables que par l&#8217;utilisateur qui exécute les jvms à monitorer</li>
<li>d&#8217;autres restrictions sont moins évidentes ; une partie sont décrites ici : <a href="http://visualvm.java.net/troubleshooting.html">http://visualvm.java.net/troubleshooting.html</a></li>
</ul>
<p>Sous windows, je rencontre actuellement des problèmes lorsque je me connecte à un serveur à distance (via Remote Desktop) : généralement, il faut toujours au moins que je me connecte en mode admin (mstsc.exe /admin (ou /console dans les anciennes versions) ) pour que les outils de monitoring puisse fonctionner. Mais cela ne suffit pas toujours &#8230;</p>
<p><span id="more-4967"></span></p>
<h1>Accès programmatiques</h1>
<p>Ces outils sont très intéressants, mais il est parfois nécessaire d&#8217;accéder à des métriques particulières d&#8217;une jvm ou de l&#8217;application que la jvm héberge. Ou ils peuvent tout simplement ne pas fonctionner dans certains cas particuliers.</p>
<p>Dans la suite de ce post, je vais me focaliser sur les différentes façons d&#8217;accéder au serveur jmx des jvms en local sans avoir à configurer l&#8217;accès distant : qui peut se révéler complexe si l&#8217;on veut que cet accès reste sécurisé ( tout est dédrit ici : <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/management/agent.html">http://docs.oracle.com/javase/7/docs/technotes/guides/management/agent.html</a> )</p>
<h2>L&#8217;API Attach</h2>
<p>L&#8217;utilisation de l&#8217;API Attach pour se connecter à un serveur jmx en local est décrit sur la même page web que l&#8217;accès distant :</p>
<p><a href="http://docs.oracle.com/javase/7/docs/technotes/guides/management/agent.html#gdhkz">http://docs.oracle.com/javase/7/docs/technotes/guides/management/agent.html#gdhkz</a></p>
<p>Cette api permet essentiellement :</p>
<ul>
<li>de découvrir les jvms disponibles</li>
<li>récupérer quelques  informations sur ces jvms (propriétés système et propriétés des agents chargés)</li>
<li>charger un agent à l&#8217;intérieur de la JVM cible</li>
</ul>
<p>Cette dernière fonctionnalité permet en particulier de charger l&#8217;agent JMX si il n&#8217;est pas déjà lancé. On peut lancer l&#8217;agent jmx au démarrage de la jvm via l&#8217;option -Dcom.sun.management.jmxremote. A partir du JDK 6, c&#8217;est grâce à l&#8217;API Attach, que cette option n&#8217;est souvent plus nécessaire : l&#8217;agent peut être chargé à la demande comme montré dans l&#8217;exemple ci-dessous.</p>
<p>(ce programme nécessite que le jar tools.jar présent dans le répertoire lib du JDK soit dans le classpath)</p>
<pre class="brush: java; title: ; notranslate">
package jmx;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.File;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.List;

import javax.management.MBeanServerConnection;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.VirtualMachineDescriptor;

public class JmxAttachAPI {
	public static void main(String[] args) throws Exception {
		new JmxAttachAPI().dotIt();
	}

	static final String CONNECTOR_ADDRESS = &quot;com.sun.management.jmxremote.localConnectorAddress&quot;;

	private void dotIt() throws Exception {

		System.out.println(&quot;Available local vms : &quot;);
		List vmdList = VirtualMachine.list();
		for(VirtualMachineDescriptor vmd : vmdList) {
			System.out.printf(&quot;%s : %s%n&quot;, vmd.id() , vmd.displayName());
		}

		// Choose one vm :
		System.out.println();
        BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
        String pid = &quot;&quot;;
        while(pid.length() == 0)  {
            System.out.println(&quot;vm id ? &quot;);
            pid = stdin.readLine();
        }

        System.out.println();
        System.out.printf(&quot;Connecting to jvm : %s%n&quot;,pid);
		VirtualMachine vm = VirtualMachine.attach(pid);
		String connectorAddress = null;
		try {
			// get the connector address
			connectorAddress = vm.getAgentProperties().getProperty(CONNECTOR_ADDRESS);

			// no connector address, so we start the JMX agent
			if (connectorAddress == null) {
			   System.out.println(&quot;Agent not Started, loading it ...&quot;);
			   String agent = vm.getSystemProperties().getProperty(&quot;java.home&quot;) +
			       File.separator + &quot;lib&quot; + File.separator + &quot;management-agent.jar&quot;;
			   vm.loadAgent(agent);

			   // agent is started, get the connector address
			   connectorAddress =
			       vm.getAgentProperties().getProperty(CONNECTOR_ADDRESS);
			} else {
				System.out.println(&quot;JMX Agent already started !&quot;);
			}
		} finally {
			vm.detach();
		}

		System.out.println();
		System.out.printf(&quot;Connecting to jmx server with connectorAddress : %s%n&quot;,connectorAddress);

		// establish connection to connector server
		JMXServiceURL url = new JMXServiceURL(connectorAddress);
		JMXConnector connector = JMXConnectorFactory.connect(url);

		MBeanServerConnection con = connector.getMBeanServerConnection();

        RuntimeMXBean runtime = ManagementFactory.newPlatformMXBeanProxy(
               con, ManagementFactory.RUNTIME_MXBEAN_NAME, RuntimeMXBean.class);
        System.out.printf(&quot;Extracted classpath : %s%n&quot;,runtime.getClassPath());

	}
}
</pre>
<p>Et voici un exemple de son exécution :</p>
<pre>Available local vms :
8372 : org.apache.catalina.startup.Bootstrap start
2108 : jmx.JmxAttachAPI

vm id ?
8372

Connecting to jvm : 8372
Agent not Started, loading it ...
Connecting to jmx server with connectorAddress : service:jmx:rmi://127.0.0.1/stub/rO0ABXNyAC5qYXZheC5tYW5hZ2VtZW50LnJlbW90ZS5ybWkuUk1JU2VydmVySW1wbF9TdHViAAAAAAAAAAICAAB4cgAaamF2YS5ybWkuc2VydmVyLlJlbW90ZVN0dWLp/tzJi+FlGgIAAHhyABxqYXZhLnJtaS5zZXJ2ZXIuUmVtb3RlT2JqZWN002G0kQxhMx4DAAB4cHc6AAtVbmljYXN0UmVmMgAADzE2OS4yNTQuMTQxLjIwNAAA1Qkf/eH4sQVkBOeL7SsAAAE1TnnPy4ABAHg=

Extracted classpath : C:\products\apache-tomcat-6.0.32\bin\bootstrap.jar</pre>
<p>Après avoir listé les jvms disponibles, ce programme s&#8217;attache à la jvm sélectionné et regarde si l&#8217;agent jmx est déjà chargé (en cherchant la propriété com.sun.management.jmxremote.localConnectorAddress)</p>
<p>Si il ne la trouve pas, il demande à la jvm de charger cet agent (l&#8217;agent est dans le jar management-agent.jar présent dans le répertoire jre/lib/ de la jvm cible)</p>
<p>Notez que la JConsole fait exactement la même chose : elle l&#8217;indique d&#8217;ailleurs dans la fenêtre de connexion en affichant &#8220;Note : The management agent will be enabled on this process&#8221; sous la liste des process disponibles lorsque le process sélectionné n&#8217;a pas encore l&#8217;agent JMX chargé</p>
<p>Une fois l&#8217;adresse jmx locale récupérée, l&#8217;API Attach a terminé son travail. L&#8217;api JMX prend ensuite le relai.</p>
<p>Ici on se contente d&#8217;extraire le classpath de la JVM cible. Mais l&#8217;ensemble des MBeans JMX de la JVM sont maintenant accessibles : que ce soit les MBeans de la JVM ou les MBeans que l&#8217;application aurait exposé dans le serveur JMX de la JVM</p>
<h2>L&#8217;API MonitoredHost</h2>
<p>Dans certains cas, l&#8217;API Attach ne fonctionne pas &#8230; (lorsque la JVM est exécutée par un service windows en particulier ; du moins dans l&#8217;environnement où je travaille actuellement)</p>
<p>JConsole utilise une 2ème API pour lister les jvms et extraire des infos : sun.jvmstat.monitor.MonitoredHost. Il utilise aussi une autre api bas niveau sun.management.ConnectorAddressLink : pour récupérer l&#8217;adresse JMX local</p>
<p>La limitation principale de cette api est qu&#8217;elle n&#8217;est pas capable d&#8217;activer l&#8217;agent JMX s&#8217;il ne l&#8217;est pas déjà. Il faut donc l&#8217;avoir activer explicitement via l&#8217;option -Dcom.sun.management.jmxremote (même avec un jdk 6 ou plus)</p>
<p>Sous réserve que l&#8217;agent jmx soit activé, on peut donc accéder au serveur JMX de cette façon :</p>
<p>(ce programme, très fortement inspiré du code source de la JConsole, nécessite aussi que le jar tools.jar soit dans le classpath)</p>
<pre class="brush: java; title: ; notranslate">
package jmx;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.management.MBeanServerConnection;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import sun.jvmstat.monitor.HostIdentifier;
import sun.jvmstat.monitor.MonitoredHost;
import sun.jvmstat.monitor.MonitoredVm;
import sun.jvmstat.monitor.MonitoredVmUtil;
import sun.jvmstat.monitor.VmIdentifier;
import sun.management.ConnectorAddressLink;

public class JmxMonitoredHost {

    public static void main(String[] args) throws Exception {
        new JmxMonitoredHost().doIt();
    }

    private void doIt() throws Exception {
        MonitoredHost localMonitoredHost = MonitoredHost.getMonitoredHost(new HostIdentifier((String)null));
        Set activeVms = localMonitoredHost.activeVms();

        Map pidToAddress = new HashMap();

        System.out.println(&quot;Available local vms : &quot;);
        for(Integer vmId : activeVms) {
            String pid = vmId.toString();
            try {
              MonitoredVm localMonitoredVm = localMonitoredHost.getMonitoredVm(new VmIdentifier(pid));

              String commandLine = MonitoredVmUtil.commandLine(localMonitoredVm);
              boolean attachable = MonitoredVmUtil.isAttachable(localMonitoredVm);
              String connectorAddress = ConnectorAddressLink.importFrom(vmId.intValue());

              System.out.printf(&quot;%5s %30s %4s%n&quot;,pid,commandLine,attachable);
              pidToAddress.put(pid,connectorAddress);

              localMonitoredVm.detach();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

		// Choose one vm :
        System.out.println();
        BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
        String pid = &quot;&quot;;
        while(pid.length() == 0)  {
            System.out.println(&quot;vm id ? &quot;);
            pid = stdin.readLine();
        }

        // get the connector address
        String connectorAddress = pidToAddress.get(pid);
		System.out.println();
		System.out.printf(&quot;Connecting to jmx server with connectorAddress : %s%n&quot;,connectorAddress);

        // establish connection to connector server
        JMXServiceURL url = new JMXServiceURL(connectorAddress);
        JMXConnector connector = JMXConnectorFactory.connect(url);

        MBeanServerConnection con = connector.getMBeanServerConnection();

        RuntimeMXBean runtime = ManagementFactory.newPlatformMXBeanProxy(
        		con, ManagementFactory.RUNTIME_MXBEAN_NAME, RuntimeMXBean.class);
        System.out.printf(&quot;Extracted classpath : %s%n&quot;,runtime.getClassPath());

    }

}
</pre>
<h2>L&#8217;API LocalVirtualMachine de la JConsole</h2>
<p>La JConsole a implémenté sa propre api de découverte au dessus des apis décrites ci-dessus : sun.tools.jconsole.LocalVirtualMachine ( On pourra trouvé son code source ici par exemple : <a href="http://javasourcecode.org/html/open-source/jdk/jdk-6u23/sun/tools/jconsole/LocalVirtualMachine.java.html">http://javasourcecode.org/html/open-source/jdk/jdk-6u23/sun/tools/jconsole/LocalVirtualMachine.java.html</a>)</p>
<p>Plutôt que d&#8217;utiliser ces deux Apis directement, il est donc plus simple d&#8217;utiliser LocalVirtualMachine</p>
<p>Cela nous donne ceci :</p>
<p>( ce programme nécessite tools.jar ET jconsole.jar dans la classpath pour fonctionner ) :</p>
<pre class="brush: java; title: ; notranslate">
package jmx;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.Map;

import javax.management.MBeanServerConnection;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import sun.tools.jconsole.LocalVirtualMachine;

public class JmxJConsole {

	public static void main(String[] args) throws Exception {
		new JmxJConsole().doIt();
	}

	private void doIt() throws Exception {

		Map allVirtualMachines = LocalVirtualMachine.getAllVirtualMachines();

		System.out.println(&quot;Available local vms : &quot;);
		for(Integer vmId : allVirtualMachines.keySet()) {
			LocalVirtualMachine vm = allVirtualMachines.get(vmId);
			System.out.printf(&quot;%10s %50s %s%n&quot;,vmId,vm.displayName(),vm.isAttachable());
		}

		// Choose one vm :
        System.out.println();
        BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
        String pid = &quot;&quot;;
        while(pid.length() == 0)  {
            System.out.println(&quot;vm id ? &quot;);
            pid = stdin.readLine();
        }

        // get the connector address
        LocalVirtualMachine vm = allVirtualMachines.get(new Integer(pid));
        // load jmx agent if necessary/possible :
        vm.startManagementAgent();
        String connectorAddress = vm.connectorAddress();

        System.out.println();
		System.out.printf(&quot;Connecting to jmx server with connectorAddress : %s%n&quot;,connectorAddress);

        // establish connection to connector server
        JMXServiceURL url = new JMXServiceURL(connectorAddress);
        JMXConnector connector = JMXConnectorFactory.connect(url);

        MBeanServerConnection con = connector.getMBeanServerConnection();

        RuntimeMXBean runtime = ManagementFactory.newPlatformMXBeanProxy(
        		con, ManagementFactory.RUNTIME_MXBEAN_NAME, RuntimeMXBean.class);
        System.out.printf(&quot;Extracted classpath : %s%n&quot;,runtime.getClassPath());

	}
}
</pre>
<h1>Conclusion</h1>
<p>Avec ce dernier code, vous devriez être paré pour vous connecter en local aussi bien que JConsole et extraire vos propres métriques ou lancer des opérations de diagnostique (au hasard : lancer un heap dump) via les Apis JMX de la jvm</p>
<p>Toutefois même la JConsole n&#8217;arrive pas tout le temps à se connecter ou à voir une jvm local.</p>
<p>En cas de soucis, voici au moins trois pré-requis qui m&#8217;ont été nécessaire récemment :</p>
<ul>
<li>exécuter JConsole (ou votre code custom) avec le même utilisateur que la JVM cible</li>
<li>si vous vous connecté en remote desktop sur un serveur Windows : utiliser le mode admin : mstsc.exe /admin</li>
<li>activer explicitement l&#8217;agent jmx sur votre jvm cible (via -Dcom.sun.management.jmxremote)</li>
</ul>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/MIKPf_Y16vw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/02/05/monitorer-une-jvm-en-local/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/02/05/monitorer-une-jvm-en-local/</feedburner:origLink></item>
		<item>
		<title>Ippevent Hibernate OGM par Emmanuel Bernard le 9 février</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/7DKCdw4w94w/</link>
		<comments>http://blog.ippon.fr/2012/01/30/ippevent-hibernate-ogm-par-emmanuel-bernard-le-9-fevrier/#comments</comments>
		<pubDate>Mon, 30 Jan 2012 09:00:39 +0000</pubDate>
		<dc:creator>Antoine SABOT-DURAND</dc:creator>
				<category><![CDATA[Ippevents]]></category>
		<category><![CDATA[DataGrid]]></category>
		<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[Infinispan]]></category>
		<category><![CDATA[NoSQL]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4904</guid>
		<description><![CDATA[<p>PaaS, Cloud. Mais le vrai challenge c&#8217;est comment et où stocker vos données. Dans du NoSQL ? Peut-on utiliser une API familière ?</p> <p>L&#8217;objectif d&#8217;Hibernate OGM est d&#8217;explorer comment réutiliser Java Persistence et son API familière pour persister les entités dans une base NoSQL.</p> <p>Il offre une implémentation JPA (manipulation d&#8217;objet et requêtes JP-QL) tout <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/01/30/ippevent-hibernate-ogm-par-emmanuel-bernard-le-9-fevrier/">Ippevent Hibernate OGM par Emmanuel Bernard le 9 février</a></span>]]></description>
			<content:encoded><![CDATA[<p><img style="float: left;" src="http://www.devoxx.com/download/attachments/5014404/thumbnail.gif?version=1&amp;modificationDate=1311272361000" alt="Emmanuel Bernard" width="100" height="111" />PaaS, Cloud. Mais le vrai challenge c&#8217;est comment et où stocker vos données. Dans du NoSQL ? Peut-on utiliser une API familière ?</p>
<p>L&#8217;objectif d&#8217;Hibernate OGM est d&#8217;explorer comment réutiliser Java Persistence et son API familière pour persister les entités dans une base NoSQL.</p>
<p>Il offre une implémentation JPA (manipulation d&#8217;objet et requêtes JP-QL) tout en stockant et requêtant les données d&#8217;une grille clé/valeur (et d&#8217;autres approches NoSQL dans un second temps). Cela inclus notamment de supporter des applications JPA existantes.</p>
<p>Dans cette présentation, nous allons:</p>
<ul>
<li>faire un survol du monde (NoSQL) et voir en quoi une API comme JPA apporte un intérêt</li>
<li>voir comment Hibernate OGM stocke les entités et les associations dans la base clé/valeur et explorer les compromis fait</li>
<li>voir comment les requêtes JP-QL sont implémentés au dessus d&#8217;une technologie qui ne supporte pas la notion de requête (clé/valeur) et quel niveau peut être couvert</li>
</ul>
<p><span style="color: #ff0000;"><strong>Attention: contient des démos qui tournent !</strong></span></p>
<p>Pour vous inscrire, il vous suffit de cliquer sur le bouton ci-dessous (si vous désirez plus d&#8217;information vous pouvez aussi vous inscrire depuis notre <a title="Inscription aux Ippevents" href="http://blog.ippon.fr/inscription-aux-ippevents/">page Ippevent</a> :</p>
<div style="width: 100%; text-align: left;"><iframe frameborder="0" height="192" marginheight="5" marginwidth="5" scrolling="auto" src="http://www.eventbrite.com/tickets-external?eid=2862552973&amp;ref=etckt" width="100%"></iframe></p>
<div style="font-family: Helvetica, Arial; font-size: 10px; padding: 5px 0 5px; margin: 2px; width: 100%; text-align: left;"><a style="color: #ddd; text-decoration: none;" href="http://www.eventbrite.com/r/etckt" target="_blank">Billetterie en ligne</a><span style="color: #ddd;"> pour </span><a style="color: #ddd; text-decoration: none;" href="http://www.eventbrite.com/event/2862552973?ref=etckt" target="_blank">Ippevent Hibernate OGM: JPA pour NoSQL (par Emmanuel Bernard)</a><span style="color: #ddd;"> produit par </span><a style="color: #ddd; text-decoration: none;" href="http://www.eventbrite.com?ref=etckt" target="_blank">Eventbrite</a></div>
</div>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/7DKCdw4w94w" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/01/30/ippevent-hibernate-ogm-par-emmanuel-bernard-le-9-fevrier/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/01/30/ippevent-hibernate-ogm-par-emmanuel-bernard-le-9-fevrier/</feedburner:origLink></item>
		<item>
		<title>Ippevent Arquillian : Le film !</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/hVCEljtZbZs/</link>
		<comments>http://blog.ippon.fr/2012/01/30/ippevent-arquillian-le-film/#comments</comments>
		<pubDate>Mon, 30 Jan 2012 08:00:08 +0000</pubDate>
		<dc:creator>Antoine SABOT-DURAND</dc:creator>
				<category><![CDATA[Ippevents]]></category>
		<category><![CDATA[Vidéo]]></category>
		<category><![CDATA[Arquillian]]></category>
		<category><![CDATA[CDI]]></category>
		<category><![CDATA[EJB 3.1]]></category>
		<category><![CDATA[Java EE]]></category>
		<category><![CDATA[JUnit]]></category>
		<category><![CDATA[Tests]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4899</guid>
		<description><![CDATA[<p>Notre Ippevent du 19 janvier dernier sur Arquillian est enfin dans la boîte. Retrouvez Alexis Hassler nous présentant ce bel outil qui permet de faire du test d&#8217;intégration d&#8217;applications Java EE et bien plus encore.</p> <p></p> ]]></description>
			<content:encoded><![CDATA[<p>Notre Ippevent du 19 janvier dernier sur Arquillian est enfin dans la boîte. Retrouvez Alexis Hassler nous présentant ce bel outil qui permet de faire du test d&#8217;intégration d&#8217;applications Java EE et bien plus encore.</p>
<p><iframe src="http://player.vimeo.com/video/35683432?title=0&amp;byline=0&amp;portrait=0" width="800" height="450" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe></p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/hVCEljtZbZs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/01/30/ippevent-arquillian-le-film/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/01/30/ippevent-arquillian-le-film/</feedburner:origLink></item>
		<item>
		<title>Ippevent Bonita le remake</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/5PXxoag7EFk/</link>
		<comments>http://blog.ippon.fr/2012/01/26/ippevent-bonita-le-remake/#comments</comments>
		<pubDate>Thu, 26 Jan 2012 10:53:26 +0000</pubDate>
		<dc:creator>Antoine SABOT-DURAND</dc:creator>
				<category><![CDATA[ESB et SOA]]></category>
		<category><![CDATA[Ippevents]]></category>
		<category><![CDATA[Vidéo]]></category>
		<category><![CDATA[Bonita]]></category>
		<category><![CDATA[BPM]]></category>
		<category><![CDATA[Groovy]]></category>
		<category><![CDATA[SOA]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4879</guid>
		<description><![CDATA[<p>Notre Ippevent &#8220;Au coeur du BPM avec Bonita&#8221; du 19 mai 2012 avait connu un gros succès. Malheureusement un soucis technique nous avait empêché de diffuser la vidéo de cette conférence. Comme le sujet est important et nous sort un peu des considération purement technique de notre quotidien pour nous parler d&#8217;outils permettant de travailler <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/01/26/ippevent-bonita-le-remake/">Ippevent Bonita le remake</a></span>]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" src="http://www.bonitasoft.com/images/bonitasoft-logo.png" alt="" width="168" height="62" />Notre Ippevent &#8220;Au coeur du BPM avec Bonita&#8221; du 19 mai 2012 avait connu un gros succès. Malheureusement un soucis technique nous avait empêché de diffuser la vidéo de cette conférence. Comme le sujet est important et nous sort un peu des considération purement technique de notre quotidien pour nous parler d&#8217;outils permettant de travailler avec les gens du métier, nous avons refait cette présentation pour que chacun puisse en bénéficier.</p>
<p>Ça tombe également bien avec le partenariat que vient de signer Ippon avec BonitaSoft en ce début d&#8217;année.</p>
<p><iframe frameborder="0" height="450" src="http://player.vimeo.com/video/35679944?title=0&amp;byline=0&amp;portrait=0" width="800"></iframe></p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/5PXxoag7EFk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/01/26/ippevent-bonita-le-remake/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/01/26/ippevent-bonita-le-remake/</feedburner:origLink></item>
		<item>
		<title>La sécu c’est bien, la négliger ça craint – Un white-paper par David Martin</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/SebvDpywNPk/</link>
		<comments>http://blog.ippon.fr/2012/01/18/la-secu-cest-bien-la-negliger-ca-craint-un-white-paper-par-david-martin/#comments</comments>
		<pubDate>Wed, 18 Jan 2012 07:30:00 +0000</pubDate>
		<dc:creator>David MARTIN</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Livre Blanc]]></category>
		<category><![CDATA[habilitations]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[livre blanc]]></category>
		<category><![CDATA[sécurité]]></category>
		<category><![CDATA[white-paper]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4842</guid>
		<description><![CDATA[<p>S&#8217;il est bien un sujet qui revient régulièrement dans l&#8217;actualité, c&#8217;est la sécurité. Et bien souvent, ce n&#8217;est pas pour faire bonne presse à l&#8217;acteur concerné (La faille du PSN a coûté à Sony plusieurs dizaines de millions de dollars et une importante perte d&#8217;image plus difficilement quantifiable). Le sujet est vaste et complexe. Vaste <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/01/18/la-secu-cest-bien-la-negliger-ca-craint-un-white-paper-par-david-martin/">La sécu c&#8217;est bien, la négliger ça craint &#8211; Un white-paper par David Martin</a></span>]]></description>
			<content:encoded><![CDATA[<p>S&#8217;il est bien un sujet qui revient régulièrement dans l&#8217;actualité, c&#8217;est la sécurité. Et bien souvent, ce n&#8217;est pas pour faire bonne presse à l&#8217;acteur concerné (La faille du PSN a coûté à Sony plusieurs dizaines de millions de dollars et une importante perte d&#8217;image plus difficilement quantifiable). Le sujet est vaste et complexe. Vaste car il couvre un spectre très large de technologies pouvant souffrir de failles et qu&#8217;il convient de bien maîtriser et suivre pour contrer le risque. Complexe car les techniques mises en œuvre pour contourner les protections peuvent être extrêmement sophistiquées.<br />
En tant que développeurs d&#8217;application, il nous faut connaître les risques majeurs encourus par une application et les différentes parades qu&#8217;il convient de savoir mettre en place pour s&#8217;en prémunir. L&#8217;écosystème Java est riche et offre un panel de solutions et d&#8217;outils presque prêts à l&#8217;emploi qui permettent d&#8217;apporter une réponse fiable aux menaces les plus courantes. Ajoutez à cela des bonnes pratiques, une connaissance élargie autour de la stack d&#8217;exécution et vous détenez une base solide pour garantir à vos clients un premier niveau de sécurité tout à fait crédible.<br />
<a href="http://blog.ippon.fr/2012/01/18/la-secu-cest-bien-la-negliger-ca-craint-un-white-paper-par-david-martin/securite_applications_java_blog/" rel="attachment wp-att-4843"><img class="alignright size-medium wp-image-4843" style="margin: 10px; border: 1px solid black;" title="securite_applications_java_blog" src="http://blog.ippon.fr/wp-content/uploads/2012/01/securite_applications_java_blog-300x199.jpg" alt="La securite dans les applications Java EE" width="300" height="199" /></a><br />
Mais la sécurité, ce n’est pas seulement se protéger contre des attaques. C’est aussi savoir prendre en compte les habilitations dans une application, comprendre les enjeux de gestion des utilisateurs et de leurs droits en entreprise, savoir s’inscrire dans un environnement qui mutualise ces données. Le contrôle des accès aux ressources, l’audit des actions réalisées dans une application, etc. sont des besoins souvent exprimés par les demandeurs, peut être trop rarement au lancement des projets, pour lesquels encore une fois une connaissance des outils techniques dédiés apporte une réponse éprouvée et robuste.</p>
<p>Le livre blanc sur la sécurité des applications Java introduit le sujet sous ces différents aspects. Il présente les vulnérabilités ainsi que les solutions possibles pour y répondre. Vous y trouverez aussi les informations relatives à la gestion des identités et des droits ainsi que l&#8217;intégration de ces dimensions dans une application Java. Enfin, il aborde les différentes contraintes et enjeux fréquemment rencontrés en entreprise.</p>
<p>Si vous souhaitez approfondir le sujet de la sécurité ou tout simplement le (re)découvrir, vous pouvez <a href="http://www.ippon.fr/livres-blancs">télécharger le livre blanc dans la rubrique dédiée sur le site d’Ippon Technologies</a>.</p>
<p>Et bien évidement j&#8217;attends avec impatience vos remarques et réactions sur ce blog.</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/SebvDpywNPk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/01/18/la-secu-cest-bien-la-negliger-ca-craint-un-white-paper-par-david-martin/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/01/18/la-secu-cest-bien-la-negliger-ca-craint-un-white-paper-par-david-martin/</feedburner:origLink></item>
		<item>
		<title>Meilleurs voeux 2012 de la part d’Ippon Technologies</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/QJYiRwIliYk/</link>
		<comments>http://blog.ippon.fr/2012/01/03/meilleurs-voeux-2012-de-la-part-dippon-technologies/#comments</comments>
		<pubDate>Tue, 03 Jan 2012 13:30:11 +0000</pubDate>
		<dc:creator>Julien DUBOIS</dc:creator>
				<category><![CDATA[Ippon]]></category>
		<category><![CDATA[Ippon Technologies]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4818</guid>
		<description><![CDATA[<p></p> ]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.ippon.fr/2012/01/03/meilleurs-voeux-2012-de-la-part-dippon-technologies/image/" rel="attachment wp-att-4817"><img class="aligncenter size-full wp-image-4817" title="Bonne année 2012" src="http://blog.ippon.fr/wp-content/uploads/2012/01/image.jpeg" alt="" width="500" height="500" /></a></p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/QJYiRwIliYk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/01/03/meilleurs-voeux-2012-de-la-part-dippon-technologies/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/01/03/meilleurs-voeux-2012-de-la-part-dippon-technologies/</feedburner:origLink></item>
		<item>
		<title>Ippevent Arquillian le 19 janvier</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/N5jREmxc-Fw/</link>
		<comments>http://blog.ippon.fr/2012/01/03/ippevent-arquillian-le-19-janvier/#comments</comments>
		<pubDate>Tue, 03 Jan 2012 13:02:32 +0000</pubDate>
		<dc:creator>Antoine SABOT-DURAND</dc:creator>
				<category><![CDATA[Ippevents]]></category>
		<category><![CDATA[Arquillian]]></category>
		<category><![CDATA[Java EE]]></category>
		<category><![CDATA[Tests]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4808</guid>
		<description><![CDATA[<p>Pour débuter cette nouvelle année 2012 (que je vous souhaite bonne et heureuse), nous démarrons avec un outil novateur : Arquillian.</p> <p>Une critique fréquente faite à l&#8217;encontre Java EE est la difficulté à tester ses composants comme les EJB ou les Beans CDI. L&#8217;outil de test JBoss Arquillian apporte une réponse puissante à ce problème <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2012/01/03/ippevent-arquillian-le-19-janvier/">Ippevent Arquillian le 19 janvier</a></span>]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" src="http://www.google.fr/url?source=imglanding&amp;ct=img&amp;q=http://design.jboss.org/arquillian/logo/ui/images/success/arquillian_ui_success_256px.png&amp;sa=X&amp;ei=QIoBT_uiB4WAhQfojt3RAQ&amp;ved=0CAwQ8wc&amp;usg=AFQjCNEXcWwy3JNRVdEpxStArkPKqHKvdw" alt="" width="100" height="100" />Pour débuter cette nouvelle année 2012 (que je vous souhaite bonne et heureuse), nous démarrons avec un outil novateur : Arquillian.</p>
<p>Une critique fréquente faite à l&#8217;encontre Java EE est la difficulté à tester ses composants comme les EJB ou les Beans CDI. L&#8217;outil de test JBoss Arquillian apporte une réponse puissante à ce problème et à bien d&#8217;autres concernant les tests d&#8217;intégration.</p>
<p>Alexis Hassler, spécialiste Java EE 6 et membre éminent du Lyon Jug nous présentera lors de cet Ippevent cette solution de test nouvelle génération qui vous aidera que vous utilisez Java EE ou Spring.</p>
<p>Pour vous inscrire, il vous suffit de cliquer sur le bouton ci-dessous ou de vous rendre sur notre <a title="Inscription aux Ippevents" href="http://blog.ippon.fr/inscription-aux-ippevents/">page Ippevent</a>.</p>
<div style="width: 100%; text-align: left;"><iframe frameborder="0" height="192" marginheight="5" marginwidth="5" scrolling="auto" src="http://www.eventbrite.com/tickets-external?eid=2620461872&amp;ref=etckt" width="100%"></iframe></p>
<div style="font-family: Helvetica, Arial; font-size: 10px; padding: 5px 0 5px; margin: 2px; width: 100%; text-align: left;"><a style="color: #ddd; text-decoration: none;" href="http://www.eventbrite.com/r/etckt" target="_blank">La gestion d&#8217;événements</a><span style="color: #ddd;"> pour </span><a style="color: #ddd; text-decoration: none;" href="http://www.eventbrite.com/event/2620461872?ref=etckt" target="_blank">Ippevent Arquillian</a><span style="color: #ddd;"> produit par </span><a style="color: #ddd; text-decoration: none;" href="http://www.eventbrite.com?ref=etckt" target="_blank">Eventbrite</a></div>
</div>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/N5jREmxc-Fw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/01/03/ippevent-arquillian-le-19-janvier/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/01/03/ippevent-arquillian-le-19-janvier/</feedburner:origLink></item>
		<item>
		<title>Ippevent Springfuse : le film !</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/_XbtdE7XRVw/</link>
		<comments>http://blog.ippon.fr/2012/01/02/ippevent-springfuse-le-film/#comments</comments>
		<pubDate>Mon, 02 Jan 2012 14:26:28 +0000</pubDate>
		<dc:creator>Antoine SABOT-DURAND</dc:creator>
				<category><![CDATA[Ippevents]]></category>
		<category><![CDATA[Vidéo]]></category>
		<category><![CDATA[JSF]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[SpringFuse]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4798</guid>
		<description><![CDATA[<p>Notre Ippevent du mois dernier sur Springfuse est enfin disponible en vidéo. Venez (re)-découvrir la présentation de Florent Ramière et de Springfuse l&#8217;outil de génération de code de Jaxio.</p> <p></p> ]]></description>
			<content:encoded><![CDATA[<p>Notre Ippevent du mois dernier sur Springfuse est enfin disponible en vidéo. Venez (re)-découvrir la présentation de Florent Ramière et de Springfuse l&#8217;outil de génération de code de Jaxio.</p>
<p><iframe frameborder="0" height="350" src="http://player.vimeo.com/video/34454849?title=0&amp;byline=0&amp;portrait=0" width="600"></iframe></p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/_XbtdE7XRVw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2012/01/02/ippevent-springfuse-le-film/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2012/01/02/ippevent-springfuse-le-film/</feedburner:origLink></item>
		<item>
		<title>Pourquoi tous les consultants Ippon iront à DevoXX France</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/aMR3By3cwM8/</link>
		<comments>http://blog.ippon.fr/2011/12/16/pourquoi-tous-les-consultants-ippon-iront-a-devoxx-france/#comments</comments>
		<pubDate>Fri, 16 Dec 2011 08:00:14 +0000</pubDate>
		<dc:creator>Geoffray GRUEL</dc:creator>
				<category><![CDATA[Evénements]]></category>
		<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Ippon RH]]></category>
		<category><![CDATA[Devoxx]]></category>
		<category><![CDATA[Ippon Technologies]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4787</guid>
		<description><![CDATA[<p></p> <p>Il y a quelques semaines nous vous annoncions notre soutien en tant que sponsor de DevoXX France les 18, 19 et 20 avril 2012 à Paris.</p> <p>Alors être sponsor c&#8217;est sympa :</p> On soutient une équipe de bénévoles qui monte un événement ÉNORME, On se montre avec nos habits du dimanche, y compris avec <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/12/16/pourquoi-tous-les-consultants-ippon-iront-a-devoxx-france/">Pourquoi tous les consultants Ippon iront à DevoXX France</a></span>]]></description>
			<content:encoded><![CDATA[<p><a title="Devoxx France" href="http://www.devoxx.com/display/FR12/Accueil" target="_blank"><img title="DevoXX France 2012" src="http://blog.ippon.fr/wp-content/uploads/2011/12/FR12.png" alt="DevoXX France 2012" width="222" height="92" /></a></p>
<p>Il y a quelques semaines nous vous annoncions notre soutien en tant que sponsor de <a title="Devoxx France" href="http://www.devoxx.com/display/FR12/Accueil" target="_blank">DevoXX France</a> les 18, 19 et 20 avril 2012 à Paris.</p>
<p>Alors être sponsor c&#8217;est sympa :</p>
<ul>
<li>On soutient une équipe de bénévoles qui monte un événement ÉNORME,</li>
<li>On se montre avec nos habits du dimanche, y compris avec un slot de conférence offert (alors qu&#8217;on n&#8217;a pas le niveau tout le monde le sait),</li>
<li>On rencontre de nouveaux copains et tous les vieux copains qui eux aussi ont un stand,</li>
<li>On fait des jeux sympas, on distribue des goodies,&#8230;</li>
</ul>
<p>Maintenant quand tu es consultant Ippon, que tu passes ta vie en mission, savoir que ta boîte soutient DevoXX c&#8217;est sympa mais ça ne résoud pas ton problème : toi tu veux y être à DevoXX France. Tu as déjà envoyé un petit mail à ton manager, tu en as parlé rapido dans le couloir à ton DG et tu veux faire partie des &#8220;happy fews&#8221; qui vont avoir leurs tickets.</p>
<p>Et bien c&#8217;est fait, Ippon Technologies a décidé d&#8217;envoyer TOUS ses consultants à DevoXX France (y compris les bordelais et les nantais) et nous venons d&#8217;acheter un gros paquet de tickets en conséquence.</p>
<p>Nous considérons en effet que DevoXX France va concentrer sur 3 jours :</p>
<ul>
<li>Tout le savoir et l&#8217;innovation sur les thèmes de notre quotidien : Web, Mobile, Cloud, Agile, langages de JVM et même notre bon vieux Java EE,</li>
<li>La crème de la communauté : les JUGers, les SUGers, les Duchess,</li>
<li>La crème des speakers,</li>
<li>Le tout dans un espace d&#8217;échange convivial.</li>
</ul>
<p>Bref nous n&#8217;avons pas tergiversé et nous avons pris nos tickets pour 100 consultants.</p>
<p>Et on a même un peu de stock pour les consultants qui voudraient nous rejoindre en début d&#8217;année et qui &#8220;of course&#8221; viendront à DevoXX France avec tous les Ippons.</p>
<p>Joyeux Noël,</p>
<p>Joyeux DevoXX,</p>
<p>Geoffray</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/aMR3By3cwM8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/12/16/pourquoi-tous-les-consultants-ippon-iront-a-devoxx-france/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/12/16/pourquoi-tous-les-consultants-ippon-iront-a-devoxx-france/</feedburner:origLink></item>
		<item>
		<title>Attaque brute force, Java et parallélisme</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/5KRTVEkyFSA/</link>
		<comments>http://blog.ippon.fr/2011/12/12/attaque-brute-force-java-et-parallelisme/#comments</comments>
		<pubDate>Mon, 12 Dec 2011 14:01:22 +0000</pubDate>
		<dc:creator>Julien DUBOIS</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Scala]]></category>
		<category><![CDATA[Spring]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4755</guid>
		<description><![CDATA[<p>Ippon a lancé il y a un peu plus d&#8217;une semaine un jeu qui a eu un beau succès:</p> <p>http://blog.ippon.fr/2011/11/30/jeu-ippon-recrute-deuxieme-edition/</p> <p>Un excellent retour sur ce jeu a été fait par Sébastien Prunier, et nous allons d&#8217;ailleurs nous baser sur sa solution pour la suite de ce billet. En effet, la dernière partie du jeu consistait <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/12/12/attaque-brute-force-java-et-parallelisme/">Attaque brute force, Java et parallélisme</a></span>]]></description>
			<content:encoded><![CDATA[<p>Ippon a lancé il y a un peu plus d&#8217;une semaine un jeu qui a eu un beau succès:</p>
<p><a href="http://blog.ippon.fr/2011/11/30/jeu-ippon-recrute-deuxieme-edition/">http://blog.ippon.fr/2011/11/30/jeu-ippon-recrute-deuxieme-edition/</a></p>
<p>Un excellent retour sur ce jeu a été fait par <a href="http://sebprunier.wordpress.com/2011/12/05/dimanche-pluvieux-ippon-recrute-au-coin-du-feu/" target="_blank">Sébastien Prunier</a>, et nous allons d&#8217;ailleurs nous baser sur sa solution pour la suite de ce billet. En effet, la dernière partie du jeu consistait à faire un algorithme de &#8220;brute force&#8221; afin de déchiffrer un mot de passe. Certaines personnes ont cru, à tort, qu&#8217;il s&#8217;agissait juste de faire une boucle &#8220;while&#8221; et de tester tous les cas possibles: cela rendait le déchiffrable impossible, à moins d&#8217;avoir beaucoup de temps disponible&#8230; Bien entendu il y avait une astuce, que pas mal de monde (dont Sébastien) a trouvé: étant donné qu&#8217;il s&#8217;agissait de trouver les lettres d&#8217;un pseudo-Sudoku, il n&#8217;y avait que 9 lettres possibles, qui ne répétaient pas, soit 9! possibilités (9! = 9*8*7*6*5*4*3*2*1 = 362 880 possibilités).</p>
<p>Le code de Sébastien permet ainsi de trouver la bonne combinaison en 80 secondes (sur mon MacBook):</p>
<p><a href="https://github.com/sebprunier/IpponRecrute/blob/master/src/main/java/fr/ippon/rh/support/ForceBrute.java" target="_blank">https://github.com/sebprunier/IpponRecrute/blob/master/src/main/java/fr/ippon/rh/support/ForceBrute.java</a></p>
<p>Cependant, on peut faire plus performant: pour être exact, &#8220;probablement plus performant&#8221;, car tout dépend de vos données (plus le résultat se trouve &#8220;loin&#8221; dans notre jeu de test, plus la parallélisation va nous faire gagner du temps).</p>
<p>Nous allons pour cela voir plusieurs méthodes différentes: Node.js, Scala, Java &#8220;pur&#8221; et Spring.<br />
<span id="more-4755"></span></p>
<h2>Méthode n°1: utilisation de Node.js</h2>
<p>Plusieurs personnes ont remonté qu&#8217;en utilisant Node.js, on pourrait certainement faire mieux. Voilà un bon exemple du &#8220;hype oriented computing&#8221;, que l&#8217;on m&#8217;a déjà sorti plusieurs fois lors du challenge USI 2011: node.js n&#8217;est volontairement pas multi-threadé, pour éviter de faire du context switching et éviter d&#8217;empiler des threads (typiquement une thread par utilisateur, comme c&#8217;est le cas dans beaucoup de nos &#8220;vieux&#8221; serveurs d&#8217;applications Java qui ne font pas de NIO). Cela permet d&#8217;avoir des applications très réactives, et qui supportent beaucoup d&#8217;utilisateurs, à partir du moment où ces applications &#8220;attendent&#8221; la majeure partie du temps. C&#8217;est un cas classique d&#8217;utilisation des serveurs d&#8217;applications: ils passent une grande partie de leur temps à attendre les données provenant d&#8217;une base de données. Node.js est donc particulièrement adapté à des sites Web utilisant une base de données complexe, mais est par contre peu adapté à des sites Web faisant beaucoup de calcul en local: un excellent exemple est donné en début du post maintenant célèbre &#8220;<a href="http://teddziuba.com/2011/10/node-js-is-cancer.html" target="_blank">Node.js is Cancer</a>&#8220;.</p>
<p>Ajoutons que sur nos machines modernes, l&#8217;histoire va plutôt dans le sens inverse de Node.js: nous avons de plus en plus de coeurs, chacun étant généralement moins puissant que la génération précédente.</p>
<h2>Méthode n°2: utilisation de Scala</h2>
<p>Scala 2.9 permet d&#8217;avoir des collections utilisant automatiquement les différents coeurs de votre système: c&#8217;est en quelque sorte l&#8217;inverse de l&#8217;approche de Node.js! Vous pouvez donc itérer sur une collection, et les traitements sur cette collection utilisent alors automatiquement plusieurs threads, répartissant ainsi les traitements sur l&#8217;ensemble des coeurs du système.</p>
<pre class="brush: java; title: ; notranslate">
(1 to 1000000).toArray.par.map(_*2)
</pre>
<p>Le <strong>.par</strong> dans le code précédent dit à Scala d&#8217;utiliser les collections &#8220;parallèles&#8221;. Dans la pratique, ce code a cependant beaucoup de problèmes:</p>
<ul>
<li>Il va utiliser le framework Fork/Join de Java 7: donc si vous êtes sour Mac OS X, comme moi, cela ne va simplement fonctionner que sur une seule thread.</li>
<li>&lt;troll&gt; Il est écrit en Scala, et donc personne ne le comprend &lt;/troll&gt;</li>
</ul>
<div>Pour une critique de cette fonctionnalité, nous vous conseillons de lire <a href="http://beust.com/weblog/2011/08/15/scalas-parallel-collections/" target="_blank">ce post de Cédric Beust</a>.</div>
<h2>Méthode n°3: Java pur</h2>
<div>L&#8217;avantage de coder en Java &#8220;pur&#8221; est d&#8217;avoir enfin le niveau de contrôle voulu, avec un niveau de complexité très réduit (pas la peine de passer la semaine à apprendre un nouveau langage ou framework). Après, tout dépend de ce que l&#8217;on entend par complexité: personnellement, je préfère avoir 10 lignes de code de plus, que je comprends sans problème, plutôt que de devoir apprendre un nouveau langage, qui d&#8217;ailleurs me cache beaucoup de son fonctionnement.</div>
<div>Voici donc mon code en Java:</div>
<div>
<pre class="brush: java; title: ; notranslate">
package fr.ippon.rh.service;

import org.jasypt.util.text.BasicTextEncryptor;

import java.util.*;

/**
 * Resolution de l'etape 3 par force brute.
 *
 * @author Sébastien Prunier
 * @author Julien Dubois
 */
public class MultiForceBrute {

    // Texte a decrypter
    private static final String etape4Texte = &quot;5oi/MCVWOrk2V8bI2LY4XM4gKf/hqRnz6/d0HftJYadMv7xkIjUsTfvXyyf0kJ/D1Or0QMicOUf7YIAkAMWkbNJpLA5cgOHZvGZVC1LBGdpe0n3zY5VfyYjUIFu/0VNyLVMOAu4BaC3ncdPkh5Q0r+IQeTV+IqOOBlsozTfxeLYBJhxIUdSaXIVubo7RSPOn1Y0aLrTEZhlPkJFJhQohhOr5d0/zqre7HnFdc/9vSC3qda6VKwxd+yAhl762kOGReE4YbeMX/1wg175ruUaT4tgVYaOLXIRg0fqZYIwu37KUrOvtUD+inZSYwMpUrNSeV9Wshwoi6kBXkriEoc2Qg58b6WVfNTzGMFsRp/D4TGMx04hGg2WTT4lRPebqGl5cPm6qSeb7WET3xbJ4LUCvOgX0cDr22inxlGUgkbF7m8ApZw2kOverBgnhW+dE3amE+bP1Ac1ky4sSY0Sjeec2n4QI6hX9mwl7GBc9Ep8uF7t+XdZFmuml4/bFgxtDOpi8zQ6NYXe2/UT5S6i/hPPHHRa6OGL2ZAswBtAkcsYiw564hshKvzVOMtP05Zu19C1zY+84kmpsGbxxknSI61owCNOvF1tJitww4EmkLsIhgveV+RcmTQOiwONJET7Q9qK4RFpFuz+hu1Kel0QsMPZMlvhSsSTj+lmLHzG9nC5s4RcvLR1JeL27MvcfO0CxZx9XSYazu+LqVK2qlv+NXftT9JFx19hVIvAI/T4oM9xf3wYrLozs1GDRrPju2yVXZb91vn4TdWWIoXI8yGQ5AaHYVLNu5LVez/Q4sH/DRjjMHLGTsYpXNm/xRrwf10Aw78dO58dvUy+ClP6//0wq+9+tw4knCtZwPK6Ov1gqvCzUlp3voDO+J/7/9+OoA4OkdJv8Nsu02lWZ6/mDsrr49U8D8mJgmqze4jVLbXg61HCuzSCOhnHPtMmyfykDSFHXvSGCiuyGoWN5ObIAo/k9XxYlZNrGpwYq3aTwaKJwG1vTtLzHop0bfQ50+cz18LqynMB2t+Y5AQ9IGAvJX6nWrO/C8GBD/bE/lZT+i1XYhYJ0JB0zoadQK+AkyNNiwUe9Dv31e614zgVTGlJ/JvSQGBCAcK+wYNDK1fVY2EEWyQhlQ3BYdwcqF4myOI7wtZsPscwO1Kc8TwlPGypQ/6JG4Q5AUeXmzrXi67boN0tB4YUyG5cQk7Ehe3gaHI7rF5IGYT1id7agEcxphjRWMTo9fT9zIb2tsA9SBw+tici5y2E7xHbnEcMjF4xuGWjEy7sr8+PktLQldvcyAo0jkwlN8G6PyL7R1HcWITr8W9T3Qr4Yq3vazV16pDf7tofDEdoI9/9jt8wchTd1gCh/fnZk88TblEJqGnbrsPL+V2S+/YaLv7A7nZ1Bjy9WiQYiGnO1tgqMMbwt470eb1mIKyOcarrGcAATiEq8DxE1H8xeEpy23BtdTHJwT5COhCY+WbEWcYvCh6tBVs2PPvGSCJvClW2sR0n16kdtQiYS7uOiyOANoVy5ZygJ4jITiik3Lcfm3rE1DLaOM44DjRy1W5YTq7dXYKBsXcdoc+JmZ+7naVcBQ2q2XlZ/t2EvN9k1rVW4x7o7V7YsE2bbPqyvAxt0w1NsgVUaAsff361KxJgD7JXQXdpEyD+6KE1N+SmUOOUG22OxOZbsHy/+WPTKboQ5AMFG8pgR61TfAA6YqPakrGMKYGkpe0T+1t82Zo1t3Q+z2WxSLdRX5bslJjfuZSqqCpao40BbIEEFYAlmkTgDuKIaP4dA9o+b0M+lPjIM/mwWjxDdOraR3w0ncnyrUigGGisYsT5KHh89VHcyv94gJdMeT+5LC/7plTAd5HhMfp1Gq8f/6L1NWuhgyD/ne8VhNOuThkf53e5QzEuhUJqc8P/A68U/TG83SFgVRiPG2h06bEGC6yztEYlT/LPBQJkcB0I2Yg4BbcJRXTc6mZT54Fato3zRPYlqXdniQsxTR8w6WgVbRF93bn99lrJc9lLnqn9F8cFTG5QKp9u45yExo2Hy/0jmcpHyhaLlJP/ECuEeQK7M5H2Ro3rG2wwcAiuK0JV0meM6Isij2z4ldl2agyR2TKNgVcCynrScqFpzkEgwmPY6XuU/+qN89fgsRJ+8uuL0V1ah4zl70ymEzMYX48bI8icCIP4BFVp+mBymy2AUo7ln8zfxW4DKlZgVeyBsluDUqjn111m4oq/JkbzwlW3/D+KU9Yb52KwcHmbnpO8TcKXprhk2iJ04ak3IWY1u+pNU8WZRz3+jQWoPpIQtA8DQQdIYXrKwgXVerMsp2g4Tj0Irf5RnpcbjzXNM2A2mBo6ak/dp1I0tFK3Ue5HfSeBZ6iLBGsKii8VJPCw2AxM/JI74/Cl2BaggiMvpqAhMDyG7EhnaMZfgj+8Kd9P1hTp5nsZWGe3vnwDLLpnDqH4vER7J1uKpm3ig2XGuq3XFo7Fp6naG+B7qlSRF&quot;;

    private static long startTime;
    private static boolean stopDecryption;

    /**
     * Programme principal
     */
    public static void main(String args[]) {
        startTime = Calendar.getInstance().getTimeInMillis();

        MultiForceBrute multiForceBrute = new MultiForceBrute();
        multiForceBrute.decrypt();
    }

    private void decrypt() {
        Set passwords = new HashSet();
        permute(&quot;&quot;, &quot;ABCDEGHIJ&quot;, passwords);
        System.out.println(&quot;Password size: &quot; + passwords.size());

        int cores = Runtime.getRuntime().availableProcessors();
        System.out.println(&quot;Number of cores: &quot; + cores);
        String[] passwordArray = new String[passwords.size()];
        passwordArray = passwords.toArray(passwordArray);
        Collection partitions = new ArrayList();
        int partitionSize = passwordArray.length / cores;
        for (int c = 0; c &lt; cores; c++) {
            String[] partition = Arrays.copyOfRange(passwordArray, c * partitionSize, (c + 1) * partitionSize);
            partitions.add(partition);
        }
        for (String[] partition : partitions) {
            DecryptionThread decryptionThread = new DecryptionThread(partition);
            decryptionThread.start();
        }
    }

    /**
     * Calcul des permutations.
     *
     * @param sStart    chaine de depart.
     * @param sEnd      chaine d'arrivee.
     * @param passwords ensemble des mots de passe.
     */
    private void permute(String sStart, String sEnd, Set passwords) {
        if (sEnd.length()             passwords.add(sStart + sEnd);
        } else {
            for (int i = 0; i &lt; sEnd.length(); i++) {
                String newString = sEnd.substring(0, i) + sEnd.substring(i + 1);
                permute(sStart + sEnd.charAt(i), newString, passwords);
            }
        }
    }

    private class DecryptionThread extends Thread {

        private String[] passwords;

        DecryptionThread(String[] passwords) {
            this.passwords = passwords;
        }

        public void run() {
            for (String password : passwords) {
                if (stopDecryption) {
                    return;
                }
                try {
                    BasicTextEncryptor textEncryptor = new BasicTextEncryptor();
                    textEncryptor.setPassword(password);
                    String decryptedText = textEncryptor.decrypt(etape4Texte);
                    if (decryptedText.contains(&quot;ippon&quot;)) {
                        System.out.println(&quot;Result: &quot; +password);
                        long totalTime = Calendar.getInstance().getTimeInMillis() - startTime;
                        System.out.println(&quot;Solved in: &quot; + totalTime + &quot; ms.&quot;);
                        stopDecryption = true;
                    }
                } catch (Exception e) {
                    // Bad password !
                }
            }
        }
    }
}
</pre>
</div>
<div>Cette méthode permet de trouver la solution en <strong>seulement 15 secondes</strong> (toujours sur mon MacBook, qui utilise alors ses 8 coeurs et commence à chauffer).</div>
<h2>Méthode n°4: Spring</h2>
<p>Les trois solutions que nous avons vu, malheureusement, ne sont pas très industrielles: sur un projet en production, personne n&#8217;a envie de lancer ainsi des threads qui utilisent tous les coeurs disponibles, sans aucun contrôle.</p>
<p>Pour cela Spring propose une abstraction très intéressante, le TaskExecutor. Nous utilisons ici Spring 3.0 (<a href="http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/scheduling.html" target="_blank">voici la documentation officielle</a>), sachant qu&#8217;il est prévu que Spring 3.1 supporte le framework Fork/Join, comme Scala, mais qu&#8217;à l&#8217;heure actuelle (Spring 3.1.0.M1), la documentation n&#8217;est pas à jour.</p>
<p>Dans sa version la plus simple, ce TaskExecutor permet de définir un pool de threads:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;bean id=&quot;taskExecutor&quot; class=&quot;org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor&quot;&gt;
  &lt;property name=&quot;corePoolSize&quot; value=&quot;5&quot; /&gt;
  &lt;property name=&quot;maxPoolSize&quot; value=&quot;10&quot; /&gt;
  &lt;property name=&quot;queueCapacity&quot; value=&quot;25&quot; /&gt;
&lt;/bean&gt;</pre>
<p>Dans la pratique, ce système permet de centraliser dans un seul endroit la configuration de son pool de Thread, et de pouvoir ainsi l&#8217;optimiser:</p>
<ul>
<li>On peut bien entendu utiliser le nombre de coeurs disponibles: c&#8217;est une variable qui est tout à fait intéressante, car dans un environnement virtualisé le nombre de coeurs disponibles peut être amené à évoluer</li>
<li>On peut utiliser la configuration Spring pour modifier ces valeurs en fonction des environnements: c&#8217;est la notion de profils, qui va elle aussi apparaître avec Spring 3.1, mais qui elle est <a href="http://blog.springsource.com/2011/02/11/spring-framework-3-1-m1-released/" target="_blank">très bien documentée</a></li>
<li>On peut choisir de n&#8217;utiliser qu&#8217;un seul thread: c&#8217;est ce qui arrive en fait très souvent pour les applications Web, car on veut garder la majeure partie des coeurs disponibles pour les utilisateurs. Ainsi, l&#8217;ensemble des traitements de fond sont soumis à une seule et même thread, ce qui permet d&#8217;avoir une application toujours réactive, quels que soient les traitements lancés. L&#8217;intérêt ici est également d&#8217;utiliser la même thread pour des traitements différents.</li>
<li>On peut utiliser le pool de thread du serveur d&#8217;applications, et c&#8217;est ce que nous allons détailler plus bas.</li>
</ul>
<div>En effet, les &#8220;gros&#8221; serveurs d&#8217;applications du marché (Websphere et Weblogic) proposent leur propre système de pool de thread, autour d&#8217;une API commune appelée CommonJ. Cette API devait être standardisée, <a href="http://www.jcp.org/en/jsr/detail?id=237">et a fini par être abandonnée</a>, mais elle est toujours disponible sur ces deux serveurs.</div>
<div>Le TaskExecutor permet donc d&#8217;utiliser ces APIs sans avoir à les connaître, et bien entendu uniquement en production (on pourrait avoir un profil &#8220;dev&#8221; qui utilise un pool de thread normal, et un profil &#8220;prod&#8221; qui utilise celui de Websphere):</div>
<pre class="brush: xml; title: ; notranslate">
&lt;bean id=&quot;taskExecutor&quot; class=&quot;org.springframework.scheduling.commonj.WorkManagerTaskExecutor&quot;&gt;
    &lt;property name=&quot;workManagerName&quot; value=&quot;wm/default&quot;/&gt;
    &lt;property name=&quot;resourceRef&quot; value=&quot;false&quot;/&gt;
&lt;/bean&gt;
</pre>
<p>Cette configuration permet ainsi au administrateurs de votre serveurs d&#8217;applications de modifier le nombre de threads disponibles en fonction des besoins et des capacités disponibles, ce qui est essentiel en cas de charge importante sur le serveur.</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/5KRTVEkyFSA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/12/12/attaque-brute-force-java-et-parallelisme/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/12/12/attaque-brute-force-java-et-parallelisme/</feedburner:origLink></item>
		<item>
		<title>Jeu “Ippon Recrute”, deuxième édition</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/BglcXUPK-yo/</link>
		<comments>http://blog.ippon.fr/2011/11/30/jeu-ippon-recrute-deuxieme-edition/#comments</comments>
		<pubDate>Wed, 30 Nov 2011 09:14:39 +0000</pubDate>
		<dc:creator>Julien DUBOIS</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Recrutement]]></category>
		<category><![CDATA[Concours]]></category>
		<category><![CDATA[Ippon Technologies]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4735</guid>
		<description><![CDATA[<p>Dans le cadre de sa politique de recrutement, Ippon Technologies avait lancé en début d&#8217;année un jeu qui a eu beaucoup de succès:</p> <p>https://github.com/ippontech/IpponRecrute</p> <p>Cependant, certaines personnes ont trouvé ce jeu trop facile, et nous avions alors promis une nouvelle version plus difficile&#8230; Voici donc la deuxième édition de ce jeu!</p> Surveillez notre dépôt GitHub https://github.com/ippontech/IpponRecrute <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/11/30/jeu-ippon-recrute-deuxieme-edition/">Jeu &#8220;Ippon Recrute&#8221;, deuxième édition</a></span>]]></description>
			<content:encoded><![CDATA[<p>Dans le cadre de sa politique de recrutement, Ippon Technologies avait lancé en début d&#8217;année un jeu qui a eu beaucoup de succès:</p>
<p><a href="https://github.com/ippontech/IpponRecrute" target="_blank">https://github.com/ippontech/IpponRecrute</a></p>
<p>Cependant, certaines personnes ont trouvé ce jeu trop facile, et nous avions alors promis une nouvelle version plus difficile&#8230; Voici donc la deuxième édition de ce jeu!</p>
<ul>
<li>Surveillez notre dépôt GitHub <a href="https://github.com/ippontech/IpponRecrute" target="_blank">https://github.com/ippontech/IpponRecrute</a></li>
<li>Vendredi 2 Décembre, à 20h30, nous pousserons une nouvelle version de notre code</li>
<li>A vous de trouver la solution!</li>
</ul>
<div>Nous sélectionnerons en priorité les personnes qui ont résolu l&#8217;énigme le plus rapidement possible (donc à priori Vendredi soir 20h35&#8230; A voir si cette version est vraiment plus difficile!), ainsi que celles qui l&#8217;ont résolue de manière élégante (avec par exemple un petit script Groovy, et une explication).</div>
<div>Et bien entendu, n&#8217;oubliez pas d&#8217;aller lire nos offres d&#8217;emploi sur <a href="http://www.ippon.fr/offres-d-emploi" target="_blank">http://www.ippon.fr/offres-d-emploi</a></div>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/BglcXUPK-yo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/11/30/jeu-ippon-recrute-deuxieme-edition/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/11/30/jeu-ippon-recrute-deuxieme-edition/</feedburner:origLink></item>
		<item>
		<title>Devoxx : les évolutions de JMS 2.0</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/wC8XL9fNmiY/</link>
		<comments>http://blog.ippon.fr/2011/11/25/devoxx-les-evolutions-de-jms-2-0/#comments</comments>
		<pubDate>Fri, 25 Nov 2011 08:20:20 +0000</pubDate>
		<dc:creator>Fabien ARRAULT</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Devoxx]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Java EE]]></category>
		<category><![CDATA[JMS]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4714</guid>
		<description><![CDATA[<p>A Devoxx, j&#8217;ai assisté à la présentation de Nigel Deakin, spec lead de JMS 2.0, sur l&#8217;état actuel des travaux de l&#8217;expert group JMS. Les propositions de l&#8217;expert group sont toujours en discussion, il nous a indiqué que sa présentation était déjà un peu différente de celle qu&#8217;il avait faite à JavaOne et que ce <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/11/25/devoxx-les-evolutions-de-jms-2-0/">Devoxx : les évolutions de JMS 2.0</a></span>]]></description>
			<content:encoded><![CDATA[<p>A Devoxx, j&#8217;ai assisté à la présentation de Nigel Deakin, spec lead de JMS 2.0, sur l&#8217;état actuel des travaux de l&#8217;expert group JMS.<br />
Les propositions de l&#8217;expert group sont toujours en discussion, il nous a indiqué que sa présentation était déjà un peu différente de celle qu&#8217;il avait faite à JavaOne et que ce qu&#8217;il nous présentait n&#8217;était que provisoire.</p>
<p>Sa présentation complète est disponible depuis mardi soir ici : <a href="http://java.net/projects/jms-spec/downloads/download/JMS2.0Devoxx2011.pdf">JMS2.0Devoxx2011.pdf</a></p>
<p>Nigel a commencé par nous rappeler que JMS est une spécification stable et ayant eut beaucoup de succès (JMS 1.02b à 10 ans).<br />
Mais depuis l&#8217;éco-système Java EE a évolué, et il était temps de faire une mise à jour.</p>
<h1>Buts de cette version</h1>
<ul>
<li>Simplification de l&#8217;API</li>
<li>Intégration avec CDI</li>
<li>Clarifier les ambiguités de l&#8217;API et les relations avec les autres spécifications Java EE</li>
<li>PAAS / multi-tenancy</li>
<li>Standardisation de l&#8217;interface entre les fournisseurs JMS et les serveurs d&#8217;application</li>
<li>Standardisation de fonctionnalités proposées par les différentes implémentations JMS disponibles</li>
</ul>
<p>Je reprends ici une partie de ce qu&#8217;il nous présenté.</p>
<h1><span id="more-4714"></span><br />
Simplications de l&#8217;API existante</h1>
<p>Voici quelques exemples qui nous ont été présentés :</p>
<h2>Création des sessions  JMS</h2>
<p>Toutes les combinaisons de la signature actuelle de createSession n&#8217;ont pas forcément de sens. De plus dans un environnement Java EE les valeurs des paramètres de cette méthode sont simplement ignorés (la sémantique transactionnelle de l&#8217;EJB étant celle qui prévaut alors) :</p>
<ul>
<li>signature actuelle :</li>
</ul>
<pre class="brush: java; title: ; notranslate">
connection.createSession(transacted, deliveryMode)
</pre>
<ul>
<li>nouvelle signature pour Java SE :</li>
</ul>
<pre class="brush: java; title: ; notranslate">
connection.createSession(sessionMode)
</pre>
<ul>
<li>nouvelle signature pour Java EE :</li>
</ul>
<pre class="brush: java; title: ; notranslate">
connection.createSession()
</pre>
<h2>Implémentation de AutoCloseable</h2>
<p>Les javax.jms.Connection implémenteront java.lang.AutoCloseable ce qui permettra de les utiliser dans la construction try-with-resources du jdk 7</p>
<h2>Méthode raccourcie pour envoyer un message</h2>
<p>Lorsqu&#8217;il n&#8217;est pas nécessaire de manipuler une instance de javax.jms.Message : en particulier pour positionner un entête ou une propriété ; il sera possible d&#8217;utiliser une nouvelle signature de la méthode send sur javax.jms.MessageProducer :</p>
<pre class="brush: java; title: ; notranslate">
producer.send(String body)
</pre>
<p>au lieu de devoir créer un message JMS avant de l&#8217;envoyer via :</p>
<pre class="brush: java; title: ; notranslate">
producer.send(javax.jms.Message message)
</pre>
<h1>Création d&#8217;une nouvelle API JMS</h1>
<p>Un des problèmes de l&#8217;API JMS est qu&#8217;elle demande beaucoup de code qui n&#8217;est pas toujours utile.<br />
Ainsi rien que pour envoyer un message, elle nécessite l&#8217;obtention de nombreux objets : en particulier une ConnectionFactory,<br />
une Connection, une Session, un MessageProducer&#8230;</p>
<p>Depuis quelques semaines, l&#8217;Expert Group réfléchit donc à la création d&#8217;une nouvelle classe : MessagingContext regroupant les responsabilités de : Connection + Session + MessageProducer</p>
<p>Voici l&#8217;exemple d&#8217;utilisation que Nigel nous a donné :</p>
<pre class="brush: java; title: ; notranslate">
@Resource(mappedName=&quot;JMS/contextFactory&quot;)
ContextFactory contextFactory;
@Resource(mappedName=&quot;JMS/orderQueue&quot;)
Queue orderQueue;
public void sendMessage(String payload) {
  try (MessagingContext mCtx = contextFactory.createContext();){
    TextMessage textMessage = mCtx.createTextMessage(payload);
    mCtx.send(orderQueue,textMessage);
  }
}
</pre>
<p>Cette nouvelle API lancerait des exceptions runtime plutôt que l&#8217;exception checkée JMSException actuellement utilisée</p>
<h1>Intégration avec CDI</h1>
<p>L&#8217;Expert Group est toujours en pleine discussion sur la façon d&#8217;intégrer JMS à CDI (JSR 299 &#8211; Contexts and Dependency Injection for Java EE).<br />
J&#8217;ai repris ci-dessous les exemples d&#8217;injection qui nous ont été présentés. Mais Nigel nous a indiqué qu&#8217;ils devaient se rajouter de l&#8217;Expert Group de CDI pour valider la faisabilité de cette approche. A suivre donc.</p>
<p>Proposition pour l&#8217;injection de la nouvelle API MessageContext :</p>
<pre class="brush: java; title: ; notranslate">
@Resource(mappedName=&quot;JMS/orderQueue&quot;)
Queue orderQueue;

@Inject
@MessagingContext(lookup=&quot;JMS/contextFactory&quot;)
MessagingContext mCtx;
@Inject
TextMessage textMessage;
public void sendMessage(String payload) {
  textMessage.setText(payload);
  mCtx.send(orderQueue,textMessage);
}
</pre>
<p>Proposition pour l&#8217;injection des objets de l&#8217;ancienne API :</p>
<pre class="brush: java; title: ; notranslate">
@Inject
@JMSConnection(lookup=&quot;JMS/connFactory&quot;)
@JMSDestination(lookup=&quot;JMS/inboundQueue&quot;)
MessageProducer producer;

@Inject
TextMessage textMessage;

public void sendMessage (String payload){
  try {
    textMessage.setText(payload);
    producer.send(textMessage);
  } catch {JMSException e}
    // do something
  }
}
</pre>
<h1>De nouvelles fonctionnalités</h1>
<p>Nigel nous a présenté aussi de nouvelles fonctionnalités qui pourraient être standardisées dans cette version de la spec :</p>
<ul>
<li>&#8220;Livraison retardée&#8221; (Delivery delay) :</li>
</ul>
<p>Permettant de spécifier la date à laquelle un message sera consommable.<br />
(Weblogic Integration implèmente de cette manière les timers afin de permettre de déclencher des opérations à une date ultérieure.<br />
J&#8217;ai déjà parlé de ce type de message dans <a href="http://blog.ippon.fr/2010/06/29/gestion-des-ressources-jms-de-weblogic-en-jmx-avec-groovy-3eme-partie-acces-au-contenu-des-messages/">mon billet sur le gestion des ressources JMS</a>)</p>
<ul>
<li>Accusé de réception asynchrone (Asynchronous acknowledgement) :</li>
</ul>
<p>La méthode send redonnerait alors la main immédiatement au thread l&#8217;appelant sans attendre que le fournisseur JMS (JMS provider)<br />
valide la prise en charge du message. Une fois pris en charge, le fournisseur JMS appelerait un objet callback pour notifier l&#8217;application.</p>
<ul>
<li>la propriété JMSXDeliveryCount devient obligatoire</li>
</ul>
<p>En cas d&#8217;erreur de traitement, un message peut être remis dans une queue (lors du rollback de la transaction du consommateur).<br />
A chaque fois qu&#8217;un message est relivré par le fournisseur, celui-ci incrémente la propriété JMSXDeliveryCount.<br />
En se basant sur la valeur de cette propriété, les applications pourront prendre des décisions particulières et en particulier se prémunir<br />
contre des retry infinis. (Toutefois, la plupart des fournisseurs JMS permettent déjà de définir un nombre maximal de retry)</p>
<ul>
<li>Hiérarchies de Topic</li>
</ul>
<p>Pour reprendre l&#8217;exemple de la présentation, il est possible de définir des Topic suivant une règle de nommage hiérarchique :</p>
<ul style="list-style-type: circle;">
<li>STOCK.NASDAQ.TECH.ORCL</li>
<li>STOCK.NASDAQ.TECH.GOOG</li>
<li>STOCK.NASDAQ.TECH.ADBE</li>
<li>STOCK.NYSE.TECH.HPQ</li>
</ul>
<p>Les consommateurs pourront alors souscrire à plusieurs Topic liés en utilisant des wildcards. Par exemple :</p>
<ul style="list-style-type: circle;">
<li>STOCK.*.TECH.*</li>
<li>STOCK.NASDAQ.TECH.*</li>
</ul>
<ul style="list-style-type: disc;">
<li>Consommateurs multiples sur une souscription à un Topic</li>
</ul>
<p>Actuellement hormis dans le cadre des multiples instances d&#8217;un MDB (Message Driven Bean) sur un serveur unique, chaque consommateur d&#8217;un Topic reçoit une copie de chaque message qui y est publié (un consommateur = une souscription) ce qui limite la scalabilité de chaque souscription.<br />
Avec cette fonctionnalité, il serait possible d&#8217;associer une unique souscription à plusieurs consommateurs (plusieurs threads) potentiellement sur plusieurs JVMs : un seul des consommateurs d&#8217;une souscription recevrait alors chaque message.</p>
<ul>
<li>Réception de messages par lot (Batch delivery)</li>
</ul>
<p>Pour la réception, cela passerait par une nouvelle interface (en plus de MessageListener ) :</p>
<pre class="brush: java; title: ; notranslate">
void onMessages(Message[] messages)
</pre>
<p>Cela permettrait d&#8217;améliorer les performances de réception (une seule transaction par lot de messages).</p>
<h1>La suite</h1>
<p>Reportez-vous à la présentation référencé plus haut, pour l&#8217;ensemble des aspects que Nigel nous a présenté.</p>
<p>La finalisation de la spécification est prévue pour le 3ème trimestre 2012. Il reste encore pas mal de possibilités d&#8217;évolution. Par exemple, il semble qu&#8217;ils réfléchissent à l&#8217;introduction d&#8217;annotation permettant de cacher complètement les API JMS cf : <a href="http://java.net/projects/messageapi/pages/Annotations">http://java.net/projects/messageAPI/pages/Annotations</a></p>
<p>Si vous êtes intéressé, vous pouvez aller sur <a href="http://jms-spec.java.net">http://JMS-spec.java.net</a> et vous abonner à la mailing list <a href="mailto:users@jms-spec.java.net">users@JMS-spec.java.net</a> pour recevoir les discussions de l&#8217;expert group. Elles contiennent en particulier des liens vers des pages du wiki qui expliquent les propositions en cours de discussion.</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/wC8XL9fNmiY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/11/25/devoxx-les-evolutions-de-jms-2-0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/11/25/devoxx-les-evolutions-de-jms-2-0/</feedburner:origLink></item>
		<item>
		<title>Présentation Hibernate/NoSQL au NantesJUG et au NormandyJUG</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/M2rEM6GWEJ0/</link>
		<comments>http://blog.ippon.fr/2011/11/24/presentation-hibernatenosql-au-nantesjug-et-au-normandyjug/#comments</comments>
		<pubDate>Thu, 24 Nov 2011 07:44:04 +0000</pubDate>
		<dc:creator>Julien DUBOIS</dc:creator>
				<category><![CDATA[Evénements]]></category>
		<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Cassandra]]></category>
		<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JUG]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4696</guid>
		<description><![CDATA[<p>Julien Dubois, directeur du pôle conseil d&#8217;Ippon Technologies, va animer une conférence autour d&#8217;Hibernate et des bases de données NoSQL (en particulier Cassandra) :</p> Le 13/12/2011 à Rouen au NormandyJUG : Inscriptions Le 14/12/2011 au NantesJUG : Inscriptions Ces conférences termineront le cycle entamé sur ce thème en milieu d&#8217;année, qui ont permis de faire <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/11/24/presentation-hibernatenosql-au-nantesjug-et-au-normandyjug/">Présentation Hibernate/NoSQL au NantesJUG et au NormandyJUG</a></span>]]></description>
			<content:encoded><![CDATA[<p>Julien Dubois, directeur du pôle conseil d&#8217;Ippon Technologies, va animer une conférence autour d&#8217;Hibernate et des bases de données NoSQL (en particulier Cassandra) :</p>
<ul>
<li>Le 13/12/2011 à Rouen au NormandyJUG : <a href="http://jugevents.org/jugevents/event/42859" target="_blank">Inscriptions</a></li>
<li>Le 14/12/2011 au NantesJUG : <a href="http://jugevents.org/jugevents/event/42844" target="_blank">Inscriptions</a></li>
</ul>
<div>Ces conférences termineront le cycle entamé sur ce thème en milieu d&#8217;année, qui ont permis de faire un retour d&#8217;expérience à la communauté sur l&#8217;utilisation d&#8217;Hibernate et de Cassandra dans des environnements à forte montée en charge. Pour rappel, cette conférence a déjà eu lieu à Paris, au ToursJUG, au BreizhJUG, au JugSummerCamp et au BordeauxJUG.</div>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/M2rEM6GWEJ0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/11/24/presentation-hibernatenosql-au-nantesjug-et-au-normandyjug/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/11/24/presentation-hibernatenosql-au-nantesjug-et-au-normandyjug/</feedburner:origLink></item>
		<item>
		<title>Devoxx « Bleeding Edge » HTML 5</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/s-fTAJuReKU/</link>
		<comments>http://blog.ippon.fr/2011/11/22/devoxx-%c2%ab-bleeding-edge-%c2%bb-html-5/#comments</comments>
		<pubDate>Tue, 22 Nov 2011 08:30:46 +0000</pubDate>
		<dc:creator>Laurent SORIN</dc:creator>
				<category><![CDATA[Evénements]]></category>
		<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Devoxx]]></category>
		<category><![CDATA[HTML5]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4651</guid>
		<description><![CDATA[<p>S’il y a bien une technologie qui a fait salle comble à toutes les conférences de ce Devoxx 2011 c’est HTML 5. Quel engouement !! Et on peut dire que les intervenants ont réussi à en mettre plein la vue de l’auditoire. J’ai eu la chance d’assister (assis ) à l’une de celles qui a <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/11/22/devoxx-%c2%ab-bleeding-edge-%c2%bb-html-5/">Devoxx « Bleeding Edge » HTML 5</a></span>]]></description>
			<content:encoded><![CDATA[<p>S’il y a bien une technologie qui a fait salle comble à toutes les conférences de ce Devoxx 2011 c’est HTML 5.<br />
Quel engouement !! Et on peut dire que les intervenants ont réussi à en mettre plein la vue de l’auditoire.<br />
J’ai eu la chance d’assister (assis <img src='http://blog.ippon.fr/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  ) à l’une de celles qui a été parmi les plus réussies. Je vais tenter de vous la faire partager avec une petite revue des nouveautés (et plus…) les plus marquantes présentées durant cette conférence par Paul Kinlan.</p>
<p><span id="more-4651"></span></p>
<p><strong>On commence par du classique… mais pratique</strong></p>
<div id="attachment_4654" class="wp-caption alignright" style="width: 220px"><a href="http://dev.w3.org/html5/spec/Overview.html"><img class="size-medium wp-image-4654" title="HTML5_Logo_512" src="http://blog.ippon.fr/wp-content/uploads/2011/11/HTML5_Logo_512-300x300.png" alt="Logo HTML 5" width="210" height="210" /></a><p class="wp-caption-text">Logo HTML 5</p></div>
<p><em>Collapse</em></p>
<p>Qui n’a jamais utilisé javascript pour faire du collapse de div et bien en HTML 5 on se pose plus la question, il suffit d’utiliser la balise &lt;détail&gt; puis &lt;summary&gt; et le navigateur se charge du reste.</p>
<p><em>Une balise &lt;output&gt; au sein d’une balise &lt;form&gt;</em></p>
<p>Cette balise permet, à partir d’une donnée saisie dans une on plusieurs balise(s) input de calculer (en javascript) un résultat directement présent dans une balise &lt;ouput&gt;. Pas très impressionnant, mais encore une fois pratique.</p>
<p><em>Le WebkitSpeech</em></p>
<p>Il s’agit d’un &lt;input&gt; texte qui est simplement rempli via la reconnaissance vocale du contenu dicté au micro par l’utilisateur. Ceci permettra de rajouter un niveau d’accessibilité à des sites web de manière très simple.</p>
<p><strong>Un peu plus complexe</strong></p>
<p><em>Synchronized based animation</em></p>
<p>Le navigateur synchronise les animations Javascript selon la fréquence de l’écran du device d’exécution. Ceci permet ainsi de gagner en fluidité d’animation de navigation ou dans les jeux.</p>
<p><em>Visibilité des onglets.</em></p>
<p>Il est possible de savoir si la page courante est affichée ou masquée (via les onglets). On peu ainsi faire en sorte qu’une musique soit jouée seulement lorsque la page correspond à l’onglet affiché.  Ceci permettra d’éviter de se demander de quel onglet provient la musique quand on navigue… (Que ceux qui n’ont jamais connu ça se lèvent !)</p>
<p><em>Pré-rendering page.</em></p>
<p>Plutôt sympa, cette fonctionnalité permet de pré-charger une page derrière un lien. Lorsque l’on clique dessus, l’affichage est alors instantané !</p>
<p><em>Etat de la connexion</em></p>
<p>Une fonctionnalité sympa permet de savoir quel est l’état de notre connexion internet (connecté/pas connecté)… merci la mobilité ! On imagine derrière l’avantage d’une telle fonctionnalité comme pouvoir sauvegarder en local les données de l’utilisateur (via les nouvelles fonctionnalités de webstorage), jouer plus finement avec le cache ou tout simplement avertir l’utilisateur.</p>
<p><em>Web Intent</em></p>
<p>A l’heure où les API fleurissent sur le net (comme twitter, facebook) il n’est pas évident de les manipuler. Google a donc décidé de créer une sorte d’API simplifiée (qui maintenant sera unifiée avec Mozilla) qui permet d’utiliser celle de votre réseau social favori ou autre.<br />
Les utilisateurs d’Android y retrouveront là une forte similitude avec leur OS avec la proposition de différentes applications a l’ouverture d’un fichier (et les objets « intent » pour ceux qui en ont déjà développé).</p>
<p>Pour résumer, cela fonctionne comme suit :</p>
<p>- Un site qui propose des services d’édition d’image rajoutera la balise suivante  afin de proposer à l’utilisateur d’enregistrer ce site comme proposant un service d’édition et l’enregistrer parmis ses « favoris » :</p>
<p><code>&lt;intent<br />
action="http://webintents.org/edit"<br />
type="image/*"<br />
/&gt;</code></p>
<p>- Lorsque l’utilisateur ira sur un site qui fait appel à un « intent » pour déléguer l’édition d’une image, l’utilisateur aura le choix de faire appel à un de ses services d’édition d’image déjà enregistrés à l’étape précédente.</p>
<p>- Une fois l’édition de l’image terminée dans ce nouveau contexte, l’ « intent » est posté et l’application qui avait fait la demande de ce service reprend la main à la réception de l’  « intent ».</p>
<p><strong>Rich Multimedia</strong></p>
<p><em>Paste file</em></p>
<p>Ceci permet le drag’n’drop de fichiers depuis le bureau vers l’application et déclenche ainsi un événement qu’on implémente ensuite (ex : l’upload d&#8217;un fichier directement). Cette fonctionnalité est déjà bien connue des utilisateurs des GMail sur Chrome pour joindre des fichiers.</p>
<p><em>Camera/Microphone</em></p>
<p>Une API permet de capturer le son et la vidéo de la webcam et de les manipuler (rectifier la couleur des images, manipuler le signal sonore).</p>
<p><em>FullScreen API</em></p>
<p>On connaît bien le fullscreen des navigateurs classiques. Dans le cas de HTML 5 il s’agit d’un véritable plein écran. Via javascript/CSS on peut savoir que l’on est en plein écran et modifier complètement l’aspect  ou le comportement de la page.</p>
<p><em>WebRTC</em></p>
<p>C’est un projet proposant une API Javascript visant à faciliter l’interaction entre utilisateurs souhaitant discuter vocalement et/ou avec la vidéo.<br />
Il est actuellement supporté par Google, Mozilla et Opéra.</p>
<p><em>Audio</em></p>
<p>Enfin, la dernière partie fut consacrée à la nouvelle balise audio. Il faut savoir que de base l’accès aux données d’un signal audio est très limité. Mozilla a donc de son coté étendu l’API avec « Audio Data API » et Google a de son coté très récemment adopté « <a href="https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html"> Web Audio API</a> » du W3C. L’objectif est de réussir à faire du traitement audio poussé (chorus, delay, mixage, spatialisation et autres modulations de fréquences).</p>
<p>Aux dires du speaker, il semblerait que l’API de Firefox soit plus lente car toutes les opérations de traitement audio  sont effectuées en JavaScript alors que coté Chrome elles sont implémentées de manière sous-jacentes ( optimisé  C / C + + ). En tous les cas au vu des démos plutôt épatantes (déformation d’un signal en temps réel, affichage de spectres (style K2000), etc… ), les développeurs de jeux en auront pour leur compte.</p>
<p><strong>Conclusion</strong></p>
<p>Présentation agréable de quelques nouveautés HTML 5 même s’il a manqué quelques éléments importants (CSS 3,  Canvas, XHR 2…) alors que l’on a eu droit à des extras comme l&#8217;API Web audio ou bien les Web Intents (qui me semblent eux promis à un bel avenir).<br />
En tous cas, on sent le navigateur poussé encore à un niveau plus élevé en tant que plateforme multimédia avec pour toile de fond la volonté de la fin du Flash, l’OS semble désormais relayé au second plan.</p>
<p>La guerre entre navigateurs (sans fin ?) fait rage :</p>
<ul>
<li>Tous les codecs (audio/video)  n&#8217;étant pas supportés par tous les navigateurs, il faut en tenir compte.</li>
<li>Chaque navigateur cherche à adopter au plus vite de nouvelles spécifications poussées (tel que le Web Audio API) tout en cherchant à se distinguer par des performances accrues (tel que l&#8217;implémentation sous jacente du traitement audio) ou l&#8217;API facilitant l&#8217;accès à ces ressources.</li>
</ul>
<p><em>Articles liés à la Conférence</em> :</p>
<p><a title="HTML5 Rocks" href="http://www.html5rocks.com/">http://www.html5rocks.com/</a></p>
<p><a href="https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html">https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html</a></p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/s-fTAJuReKU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/11/22/devoxx-%c2%ab-bleeding-edge-%c2%bb-html-5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/11/22/devoxx-%c2%ab-bleeding-edge-%c2%bb-html-5/</feedburner:origLink></item>
		<item>
		<title>Paris JUG : Petites librairies Java</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/5MXUF8OMpK4/</link>
		<comments>http://blog.ippon.fr/2011/11/21/paris-jug-petites-librairies-java/#comments</comments>
		<pubDate>Mon, 21 Nov 2011 07:00:28 +0000</pubDate>
		<dc:creator>Pierre TEMPLIER</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Outils]]></category>
		<category><![CDATA[Commons Configuration]]></category>
		<category><![CDATA[GPars]]></category>
		<category><![CDATA[Guava]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Lombok]]></category>
		<category><![CDATA[ParisJUG]]></category>
		<category><![CDATA[PrettyTime]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4622</guid>
		<description><![CDATA[<p class="wp-caption-text">G. Laforge expliquant Pretty Time</p> <p>La session du Paris JUG du 8 novembre 2011 était consacrés aux petites librairies Java.</p> I. Pretty Time <p>Guillaume Laforge, leader du projet Groovy nous a présenté la librairie PrettyTime développée par Lincoln Baxter III qui travaille chez OcpSoft et RedHat. Celle-ci permet de présenter des dates sous forme <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/11/21/paris-jug-petites-librairies-java/">Paris JUG : Petites librairies Java</a></span>]]></description>
			<content:encoded><![CDATA[<div id="attachment_4703" class="wp-caption alignleft" style="width: 234px"><img class="size-medium wp-image-4703" title="Guillaume Laforge" src="http://blog.ippon.fr/wp-content/uploads/2011/11/IMG_0098-224x300.jpg" alt="" width="224" height="300" /><p class="wp-caption-text">G. Laforge expliquant Pretty Time</p></div>
<p>La session du Paris JUG du 8 novembre 2011 était consacrés aux petites librairies Java.</p>
<h2>I. Pretty Time</h2>
<p>Guillaume Laforge, leader du projet Groovy nous a présenté la librairie <a href="http://ocpsoft.com/prettytime/">PrettyTime</a> développée par Lincoln Baxter III qui travaille chez OcpSoft et RedHat. Celle-ci permet de présenter des dates sous forme de dates relatives du type : à l&#8217;instant, dans 10 minutes, il y a 3 heures. Guillaume l&#8217;utilise sur <a href="https://glaforge.appspot.com/">son blog</a> pour afficher la date des posts ce qui permet d&#8217;indiquer la date de la façon suivante : <em>Posted on 09 November, 2011 (2 days ago). </em>La librairie est constituée d&#8217;un jar n&#8217;a pas de dépendance. Elle supporte 18 langues dont le français et l&#8217;anglais et est très simple à utiliser.</p>
<p><span id="more-4622"></span></p>
<pre class="brush: java; title: ; notranslate">
// on initialise avec une date de reference
PrettyTime t = new PrettyTime(new Date(1000 * 60 * 12), new Locale(&amp;quot;fr&amp;quot;));
// on formate une date par rapport a cette date de reference
assertEquals(&amp;quot;il y a 12 minutes&amp;quot;, t.format(new Date(0)));
</pre>
<p>on peut utiliser facilement PrettyTime avec Grails ou JSF.</p>
<h2>II. GPars</h2>
<p>GPars (prononcez Jeepers) est une librairie permettant de s&#8217;adapter au multi-processeurs et au multi-coeurs en faisant de la programmation concurrente.</p>
<p>il est difficile de bien utiliser ce  que le JDK propose : threads / synchronize / wait-notify-notifyAll, qui peuvent conduire à</p>
<ul>
<li>des dead-locks, des live-locks (in interblocage qui consomme du CPU), des race conditions ou l&#8217;épuisement de ressources</li>
<li>des problèmes de gestion d&#8217;accès à la mémoire partagée</li>
</ul>
<p>Pour éviter ces problèmes, GPars propose d&#8217;utiliser l&#8217;immuabilité et le passage de messages au travers des paradigmes suivants</p>
<ul>
<li><a title="Actor" href="http://gpars.codehaus.org/Actor">Acteurs</a></li>
<li><a title="ForkJoin" href="http://gpars.codehaus.org/ForkJoin">Fork/Join</a></li>
<li><a title="Parallelizer" href="http://gpars.codehaus.org/Parallelizer">Collections parallèles</a></li>
<li><a title="Asynchronizer" href="http://gpars.codehaus.org/Asynchronizer">Executors</a></li>
<li><a title="Dataflow" href="http://gpars.codehaus.org/Dataflow">Dataflow</a></li>
<li><a title="Agent" href="http://gpars.codehaus.org/Agent">Agent</a> &#8211; an thread-safe reference to mutable state</li>
<li><a title="STM" href="http://gpars.codehaus.org/STM">STM</a> (Software Transactional Memory)</li>
<li><a title="CSP" href="http://gpars.codehaus.org/CSP">CSP</a></li>
</ul>
<h3>un exemple avec les fonctions parallèles pour les collections</h3>
<pre class="brush: groovy; title: ; notranslate">
@Grab('org.codehaus.gpars:gpars:0.12')
import static groovyx.gpars.GParsPool.withPool

defnums=1..100000
withPool(5){
def squares=nums.collectParallel{it**2}
.grepParallel{it%7==it%5}
.grepParallel{it%3==0}
println squares[0..3]+&amp;quot;...&amp;quot;+squares[-3..-1]

assertsquares[0..3]==[36,144,1089,1296]
}
</pre>
<p>on utilise un pool de taille nombre de coeurs + 1 afin de maximiser l&#8217;utilisation du CPU car souvent on a un thread qui sert à la coordination des autres et qui consomme peu de ressources. GPars a comme dépendance les librairies jsr166y et extra166y. Il dispose d&#8217;une API Java et d&#8217;une API Groovy.</p>
<p>Selon le problème que l&#8217;on a à résoudre on utilisera des outils différents. Cela est bien présenté par le graphe suivant.</p>
<p style="text-align: center;"><img class="aligncenter" src="http://blog.ippon.fr/wp-content/uploads/2011/11/GPars_when_to_use_what.png" alt="GPars when to use what" width="741" height="310" /></p>
<p>les slides de la présentation de Guillaume <a href="http://www.slideshare.net/glaforge/gpars-et-prettytime-paris-jug-2011-guillaume-laforge">ici</a></p>
<h2>III. Project Lombok (ou comment cacher la plomberie)</h2>
<p>Florent Ramière de la société Jaxio nous a présenté <a href="http://projectlombok.org/">Lombok</a>, &#8220;un outil qui sert à enlever la plomberie&#8221;. Il s&#8217;agit d&#8217;un plugin eclipse qui va générer du code technique grâce à des annotations, le source ne sera donc pas pollué par ce code technique qui existera néanmoins dans le bytecode après compilation. En utilisant Lombok on pourra donc clarifier son code et se concentrer sur d&#8217;autres parties de son code. On peut bien sûr utiliser les assistants eclipse pour générer un code similaireà celui généré par Lombok.</p>
<p>on dispose notamment des annotations suivantes</p>
<p>@Getter</p>
<p>@Setter</p>
<p>@EqualsAndHashCode</p>
<p>@RequiredArgsConstructor un constructeur avec tous les champs finaux</p>
<p>@Data est un raccourci pour @ToString, @EqualsAndHashCode, @Getter sur tous les champs et @Setter sur tous les champs non-finaux, et @RequiredArgsConstructor! à utiliser pour ses beans.</p>
<p>@Delegate permet de déléguer toutes les méthodes publiques de l&#8217;attribut annoté, excepté les méthodes présentes dans java.lang.Object.</p>
<p>@Log et ses variantes @CommonsLog, @Log4j et @Slf4j permet d&#8217;instancier une variable statique privée log</p>
<p>@Synchronized permet de générer un bloc synchronize sur une variable privée $lock ou $LOCK (dans le cas d&#8217;une méthode statique)</p>
<p>val est un type Lombok permettant d&#8217;avoir des variables &#8216;final&#8217; et de bénéficier de l&#8217;inférence de type.On peut ainsi écrire</p>
<pre class="brush: java; title: ; notranslate">
val map = new HashMap();
</pre>
<p>la page <a href="http://projectlombok.org/features/index.html">suivante</a> explique très bien le code généré par Lombok. on peut d&#8217;ailleurs si besoin générer ce code en utilisant delombok (pour GWT notamment ou si l&#8217;on veut utiliser le code générer sans dépendre de lombok). <a href="https://github.com/peichhorn/lombok-pg">lombok-pg</a> est un ensemble d&#8217;extensions pour lombok.</p>
<p>Lombok peut également être utilisé via ant, maven ou javac.</p>
<p>Au détour de ses démonstrations, florent nous a également conseillé l&#8217;outil <a href="https://code.google.com/p/awaitility/">awaitility</a> qui permet de faire des tests sur du code asynchrone</p>
<h2>IV. Apache Commons Configuration</h2>
<p><a href="https://twitter.com/#!/smanux">Emmanuel Bourg</a> est membre de la fondation Apache et est commiter sur le projet <a href="https://commons.apache.org/configuration/index.html">Apache Commons Configuratio</a> qu&#8217;il est venu nous présenter. Il s&#8217;agit d&#8217;une abstraction de la configuration d&#8217;une application qui présente une interface simple de type clé/valeur pour les données. Elle permet de gérer différents formats de données et des transformations dans les types voulus.</p>
<p>On peut gérer un format Properties amélioré</p>
<pre class="brush: java; title: ; notranslate">
list1=val1,val2,val3
list2=val1
list2=val2
list2=val3
include=chunk.properties
</pre>
<p>On peut également utiliser des fichiers XML, Property List XML, Ini ou encore une base données.</p>
<p>Plusieurs formats sont prévus : OGDL, YAML, JSON, Registry Windows, Binary Property List. Les contributions sont les bienvenues si vous voulez aider à ajouter le support des nouveaux formats. On peut combiner plusieurs configurations grâce à CompositeConfiguration. On peut également utiliser un descripteur de configuration. Commons Configuration s&#8217;intègre très bien avec la librairie d&#8217;abstraction de systeme de fichiers Apache Commons VFS.</p>
<p>Sauvegarde automatique</p>
<pre class="brush: java; title: ; notranslate">
PropertiesConfiguration config = new PropertiesConfiguration(&amp;quot;usergui.properties&amp;quot;);
config.setAutoSave(true);
</pre>
<p>Rechargement automatique (on peut également déclencher le rechargement)</p>
<pre class="brush: java; title: ; notranslate">
PropertiesConfiguration config = new PropertiesConfiguration(&amp;quot;usergui.properties&amp;quot;);
config.setReloadingStrategy(new FileChangedReloadingStrategy());
</pre>
<h2>V. Guava (N&#8217;aime pas les null)</h2>
<p><a href="http://www.thierryler.com/">Thierry Leriche-Dessirier</a> (Indépendant) et <a href="https://twitter.com/#!/eneveu">Etienne Neveu</a> (SFEIR) nous ont fait faire un tour du propriétaire de <a href="https://code.google.com/p/guava-libraries/">Guava</a>, la librairie utilitaire de Google autrefois nommée google-collections.</p>
<h3>Factory methods</h3>
<p>Inférence de type : grâce à des factory statiques on peut écrire</p>
<pre class="brush: java; title: ; notranslate">
List primeNumbers = newArrayList();
Set colors = newTreeSet();
Map ages = newHashMap();
</pre>
<p>ce qui n&#8217;est plus si intéressant que ca en Java 7 avec la notation diamant.<br />
L&#8217;initialisation de collection est également facilitée</p>
<pre class="brush: java; title: ; notranslate">
List dogs = newArrayList(Dog1, Dog2, Dog3)
</pre>
<h3>Programmation fonctionnelle</h3>
<p>On peut filtrer une collection grâce à un prédicat</p>
<pre class="brush: java; title: ; notranslate">
Iterable maleDogs = Iterables.filter(dogs,
  new Predicate() {
    public boolean apply(Dog dog) {
      return dog.getSex() == MALE;
    }
});
</pre>
<p>un predicat peut utiliser les prédicats and, in, or, not déjà définis dans la classe Predicates</p>
<pre class="brush: java; title: ; notranslate">
boolean isMilouInBoth = and(in(dogs), in(superDogs))
            .apply(new Dog(&amp;quot;Milou&amp;quot;));
</pre>
<p>on peut transformer les elements d&#8217;une liste en utilisant une <em>Function</em></p>
<pre class="brush: java; title: ; notranslate">
List chiens =
Lists.transform(dogs, new Function() {
  public Chien apply(Dog dog) {
    return new Chien(dog.getName());
  }
});
</pre>
<p>Attention ce sont des vues qui sont retournées. cela peremt d&#8217;avoir du <em>lazy-loading</em> mais la conversion sera faite autant de fois que nécessaire.<br />
Iterables.find utilise le même prédicat que pour Iterables filter mais renvoit le premier objet correspondant au predicat ou un objet par défaut si rien ne correspondait au prédicat.</p>
<pre class="brush: java; title: ; notranslate">
Dog firstMale = Iterables.find(dogs, malePredicate, DEFAULT);
</pre>
<h3>collections immuables</h3>
<p>on a des syntaxes plus concises que la syntaxe standard tout en proposant de la copie défensive.</p>
<pre class="brush: java; title: ; notranslate">
ImmutableSet.of(1, 2, 3, 5, 7);
ImmutableSet.copyOf(favoriteColors)
</pre>
<h3>base.Objects</h3>
<p>cette classe propose d&#8217;aider à la simplification de l&#8217;écriture des méthodes equals(), hashcode() ou toString()</p>
<pre class="brush: java; title: ; notranslate">
//equals
Objects.equal(name, that.name)
&amp;amp;&amp;amp; Objects.equal(weight, that.weight)
&amp;amp;&amp;amp; sex == that.sex;
// hashcode
Objects.hashCode(name, weight, sex);
//toString
Objects.toStringHelper(this)
   .add(&amp;quot;name&amp;quot;, name)
   .add(&amp;quot;weight&amp;quot;, weight)
   .add(&amp;quot;sex&amp;quot;, sex)
   .toString();
</pre>
<p>on peut créer facilement un comparateur</p>
<pre class="brush: java; title: ; notranslate">
public int compareTo(Dog other) {
  return ComparisonChain.start()
    .compare(name, other.name)
    .compare(weight, other.weight)
    .compare(sex, other.sex)
    .result();
}
</pre>
<h3>base.Preconditions</h3>
<p>on peut vérifier des paramètres</p>
<pre class="brush: java; title: ; notranslate">
this.currency = checkNotNull(currency, &amp;quot;currency cannot be null&amp;quot;);
checkArgument(amount.signum() &amp;gt;= 0, &amp;quot;must be positive: %s&amp;quot;, amount);
</pre>
<h3>base.CharMatcher</h3>
<p>il s&#8217;agit d&#8217;un outil permettant d&#8217;exprimer une expression régulière en language naturel. Il permet de remplacer avantageusement StringUtils des Apache Commons.</p>
<h3>Collections</h3>
<p>on dispose de collections n&#8217;existant pas dans le JDK</p>
<p>MultiMap : il s&#8217;agit d&#8217;une map pouvant avoir plusieurs valeurs pour une même clé</p>
<pre class="brush: java; title: ; notranslate">
Multimap favoriteColors = HashMultimap.create();
</pre>
<p>BiMap : il s&#8217;agit d&#8217;une map pouvant n&#8217;ayant pas 2 fois la même valeur</p>
<pre class="brush: java; title: ; notranslate">
BiMap favoriteColors = HashBiMap.create();
</pre>
<p>Multiset: il s&#8217;agit d&#8217;un set pouvant contenir plusieurs fois la même valeur (on peut même connaître le nombre de doublons)</p>
<pre class="brush: java; title: ; notranslate">
Multiset primeNumbers = HashMultiset.create();
</pre>
<p>Joiner et Splitter permettent de manipuler les conversions entre chaine de caractères et liste de String.<br />
En utilisant Joiner, on aura une NullPointerException si un des éléments de la liste vaut null mais l&#8217;on pourra utiliser skipNulls() ou userForNull(MY_DEFAULT) pour spécifier le comportement lorsque l&#8217;on rencontre un null.</p>
<pre class="brush: java; title: ; notranslate">
List&amp;lt;String&amp;gt; dogs = newArrayList(&amp;quot;Milou&amp;quot;, &amp;quot;Idefix&amp;quot;, &amp;quot;Rintintin&amp;quot;);
String names = Joiner.on(&amp;quot;, &amp;quot;).join(dogs);
</pre>
<p>En utilisant Splitter on peut nettoyer le résultat en utilisant trimResults() et omitEmptyStrings()</p>
<pre class="brush: java; title: ; notranslate">
Iterable&amp;lt;String&amp;gt; superDogs = Splitter.on(&amp;quot;,&amp;quot;)
   .trimResults()
   .omitEmptyStrings()
   .split(&amp;quot;Lassie, , Volt, Milou&amp;quot;);
</pre>
<h3>Cache</h3>
<h4>Memoization</h4>
<p>la memoization permet de garder en cache une unique valeur. l&#8217;exemple donné était la mise en cache du numéro de version du dernier jdk. On défini via l&#8217;utilisation d&#8217;un Supplier comment aller chercher la valeur qui nous intéresse. Celle valeur ne sera récupérée que lors du premier appel (lazy loading). Les appels suivant utiliserons le cache.</p>
<pre class="brush: java; title: ; notranslate">
private Supplier&amp;lt;JdkVersion&amp;gt; versionCache =
  Suppliers.memoize(
    new Supplier&amp;lt;JdkVersion&amp;gt;() {
      public JdkVersion get() {
        return jdkWebService.checkLatestVersion();
      }
    }
);
</pre>
<p>On peut également préciser une durée de validité du cache avec memoizeWithExpiration()</p>
<h4>Key-Value</h4>
<p>On peut construire un Cache à plusieurs entrées grâce aux classes CacheBuilder et CacheLoader</p>
<pre class="brush: java; title: ; notranslate">
private Cache&amp;lt;Long, Film&amp;gt; filmCache = CacheBuilder.newBuilder()
  .maximumSize(2000)
  .expireAfterWrite(30, TimeUnit.MINUTES)
  .build(new CacheLoader&amp;lt;Long, Film&amp;gt;() {
    public Film load(Long filmId) {
      return imdbWebService.loadFilmInfos(filmId);
    }
});
</pre>
<h2>Concurrent</h2>
<p>Guava propose d&#8217;étendre Future avec la classe ListenableFuture. On peut ainsi associer un listener à un Future.</p>
<pre class="brush: java; title: ; notranslate">
ListenableFuture&amp;lt;Result&amp;gt; future = ...
future.addListener(new Runnable() {
  public void run() {
    logger.debug(&amp;quot;Future is done&amp;quot;);
  }
}, executor);
</pre>
<p>On peut également faire de la programmation asynchrone grâce à FutureCallback. cela permet d&#8217;isoler le traitement des exceptions.</p>
<pre class="brush: java; title: ; notranslate">
Futures.addCallback(future, new FutureCallback&amp;lt;Result&amp;gt;() {
  public void onSuccess(Result result) {
    storeInCache(result);
  }
  public void onFailure(Throwable t) {
    reportError(t);
  }
});
</pre>
<p>pour utiliser des ListenableFuture on utilise un ListeningExecutorService de la façon suivante.</p>
<pre class="brush: java; title: ; notranslate">
ListeningExecutorService executor = MoreExecutors.listeningDecorator(executor);

public ListenableFuture&amp;lt;Note&amp;gt; getNote(final Film film) {
  return executor.submit(new Callable&amp;lt;Note&amp;gt;() {
    public Note call() {
      return imdbWebService.getNote(film);
    }
  });
}
</pre>
<p>En utilisant les méthodes proposées par Futures on peut facilement proposer des méthodes non bloquantes qui renvoient un Future au lieu d&#8217;une liste de notes. Cela permet au programme appelant de ne pas bloquer pendant la récupération des notes et d&#8217;effectuer d&#8217;autres traitements pendant celle-ci.</p>
<pre class="brush: java; title: ; notranslate">
ListenableFuture
&amp;lt;List&amp;lt;Note&amp;gt;&amp;gt; getNotes(Film film) {
  ListenableFuture&amp;lt;Note&amp;gt; noteImdb = imdbService.getNote(film);
  ListenableFuture&amp;lt;Note&amp;gt; noteAllo = allocineService.getNote(film);
  return Futures.allAsList(noteImdb, noteAllo);
}
</pre>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/5MXUF8OMpK4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/11/21/paris-jug-petites-librairies-java/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/11/21/paris-jug-petites-librairies-java/</feedburner:origLink></item>
		<item>
		<title>Devoxx: Les deux nouveaux candidats à la succession au langage Java</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/d-SkseNm_IU/</link>
		<comments>http://blog.ippon.fr/2011/11/18/devoxx-les-deux-nouveaux-candidats-a-la-succession-au-langage-java/#comments</comments>
		<pubDate>Fri, 18 Nov 2011 20:38:30 +0000</pubDate>
		<dc:creator>Fabien ARRAULT</dc:creator>
				<category><![CDATA[Evénements]]></category>
		<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Devoxx]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Langage]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4624</guid>
		<description><![CDATA[Deux nouveaux langages qui commencent fort <p>Lors de ce Devoxx 2011, une catégorie de sessions était consacrée aux différents langages de la JVM. Etaient présents Scala, Phantom, Groovy, JRuby, Clojure et les deux petits nouveaux révélés cette année par leur sponsor : Kotlin (JetBrains) et Ceylon (JBoss/Redhat)</p> <p>Personnellement, ce sont ces deux nouveaux langages qui <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/11/18/devoxx-les-deux-nouveaux-candidats-a-la-succession-au-langage-java/">Devoxx: Les deux nouveaux candidats à la succession au langage Java</a></span>]]></description>
			<content:encoded><![CDATA[<h1>Deux nouveaux langages qui commencent fort</h1>
<p>Lors de ce Devoxx 2011, une catégorie de sessions était consacrée aux différents langages de la JVM.<br />
Etaient présents Scala, Phantom, Groovy, JRuby, Clojure et les deux petits nouveaux révélés cette année par leur sponsor : Kotlin (JetBrains) et Ceylon (JBoss/Redhat)</p>
<p>Personnellement, ce sont ces deux nouveaux langages qui m&#8217;intéressaient le plus : j&#8217;adore la concision de Groovy mais le fait qu&#8217;il ne soit pas statiquement typée m&#8217;empêche de l&#8217;utiliser pour un projet avec un minimum d&#8217;envergure. Peut-être que l&#8217;un de ces deux langages pourra amener le meilleur de ces deux mondes&#8230;</p>
<p>Ces deux langages sont tout nouveaux et toujours en cours d&#8217;implémentation. Il n&#8217;est pas encore question de les utiliser sur de vrais projets mais nous avons pu voir durant les sessions de Devoxx que chacun avait déjà un compilateur fonctionnel et un IDE pouvant faire la démonstration de complétion, refactoring, debugging, &#8230; De quoi commencer à jouer avec a priori.</p>
<p><span id="more-4624"></span></p>
<h1>Caractéristiques</h1>
<p>Ces deux langages ont une bonne partie de leurs objectifs en commun :</p>
<ul>
<li>langage s&#8217;exécutant sur la JVM</li>
<li>statiquement typé</li>
<li>compilateur permettant de détecter plus d&#8217;erreurs</li>
<li>avoir une syntaxe plus simple et plus expressive que Java sans être aussi compliqué que Scala</li>
<li>complètement interopérable avec Java</li>
</ul>
<p>Il en ressort un grand nombre de caractéristiques communes, comme par exemple :</p>
<ul>
<li>inférence de type étendue</li>
<li>null safety (cf ci-dessous)</li>
<li>smart cast ou plus généralement des optimisations de syntaxe locale (cf ci-dessous)</li>
<li>constructeur primaire dans la syntaxe</li>
</ul>
<p>Par contre, durant la présentation de Ceylon la notion de closure n&#8217;a pas du tout été évoquée, il n&#8217;est pas clair pour moi si elle sera supporté ou non. Kotlin de son côté les supportera très bien, avec en particulier la possibilité de mettre en oeuvre des &#8220;higher-order function&#8221;.</p>
<p>Je ne peux pas faire de comparaisons précises sur la base de ces deux présentations, mais au dire de Stéphane Epardaud qui nous a présenté Ceylon avec Emmanuel Bernard : Ceylon et Kotlin ont beaucoup en commun en termes de fonctionnalités. Pour lui, Ceylon se distingue par un système de typage plus abouti ( avec en particulier les union type, intersection type, &#8230; ).</p>
<h1>Syntaxe</h1>
<p>Au niveau de la syntaxe, les deux langages restent assez accessibles aux programmeurs Java, mais s&#8217;éloignent tout de même de la syntaxe Java.<br />
Pour citer deux exemples :</p>
<ul>
<li>dans Kotlin : le type des paramètres est écrit après son nom, et le type de retour après la définition d&#8217;une fonction. Par exemple :</li>
</ul>
<pre class="brush: scala; title: ; notranslate">
fun main(args : List&lt;String&gt;) : Unit
</pre>
<ul>
<li>dans Ceylon : de nouveaux keywords sont introduits qui remplacent une partie de ceux utilisés en Java ( abstract =&gt; formal, @Overide =&gt; actual, public/protected remplacé par &#8220;shared&#8221;, &#8230;), du code peut être associé à des properties (pour implémenter le getter ou le setter associé), &#8230;</li>
</ul>
<h1>Documentation</h1>
<p>Jetbrains a très rapidement mis en place un wiki pour son langage avec pas mal de documentation et des discussions sur les choix effectués et leurs objectifs : <a href="http://confluence.jetbrains.net/display/Kotlin/Welcome">http://confluence.jetbrains.net/display/Kotlin/Welcome</a></p>
<p>Pour Ceylon, c&#8217;était plutôt le brouillard en terme de doc, la plupart des références se trouvaient dans des blogs, des présentations, &#8230; rendant difficile la création d&#8217;un communauté.</p>
<p>Jusqu&#8217;à ce matin en fait, où ils nous ont révélé une &#8220;One more thing&#8221; à la fin de la présention : le tout nouveau site de ceylon : <a href="http://www.ceylon-lang.org/">http://www.ceylon-lang.org/</a> et le github des développements en cours <a href="https://github.com/ceylon">https://github.com/ceylon</a></p>
<h1>Un petit focus sur deux des caractéristiques communes</h1>
<h2>Null safety</h2>
<p>Dans les deux langages : les références ne peuvent pas être null par défaut.<br />
Un type Integer (par exemple) correspondrait à un objet entier non null.<br />
Un type Integer? correspondrait à un objet entier pouvant être null</p>
<p>Pour accéder à un champ ou une méthode sur une référence pouvant être null, il faut absolument utiliser ?. au lieu de simplement . sans quoi le compilateur génère une erreur. Si l&#8217;objet est null : l&#8217;opérateur ?. aura pour effet d&#8217;ignorer la suite de l&#8217;expression et de renvoyer simplement null<br />
Exemple en Kotlin :</p>
<pre class="brush: groovy; title: ; notranslate">
Int? x = getAnIntegerOrNull()
print (x?.times(2)) // ici, x peut être null : il est nécessaire d'utiliser ?.
                    // pour appeler la méthode times qui correspond à l'opérateur *
if(x!=null) {
  print(x * 2)    // ici, le compilateur sait que x n'est pas null,
                  // on peut utiliser x * 2 qui est équivalent à x.times(2)
)
</pre>
<p>Exemple en Ceylon :</p>
<pre class="brush: groovy; title: ; notranslate">
Cube? cube = getCubeOrNull()
print cubs?.area()
if(exists cube) {      // permet de tester que la référence n'est pas null
  print cube.area()
} else {
  print &quot;Cube is null&quot;
}
</pre>
<h2>Smart Cast</h2>
<p>En Kotlin :</p>
<pre class="brush: groovy; title: ; notranslate">
Object object = ...
if(object is String) {
  object.substring(1)  // pas besoin de caster l'objet en String,
                       // le compilateur le déduit de la clause if
}
</pre>
<p>En Ceylon :</p>
<pre class="brush: groovy; title: ; notranslate">
Apple|Snail food = ...  // union type : food référence un objet soit de type Apple soit de type Snail.
if(is Apple food) {    // on s'assure que food est de type Apple
  food.eat()    // la méthode eat() n'existe que sur Apple, et pas sur Snail
                // dans le bloc du if, il n'est pas nécessaire de caster food en Apple pour l'appeler
}
</pre>
<p>On peut aussi considérer les deux exemples du paragraphe &#8220;null safety&#8221; comme des smarts cast : où le compilateur change le type de la référence d&#8217;un type nullable à un type non nullable.</p>
<h1>Conclusion</h1>
<p>Plus simple que Scala, ces langages pourraient répondre aux attentes de ceux qui veulent un langage sur la JVM qui soit plus expressif que Java.</p>
<p>Mais attention, Groovy les attend au tournant : la vérification statique du typage est en cours d&#8217;implémentation pour la prochaine version du langage : <a href="http://docs.codehaus.org/display/GroovyJSR/GEP+8+-+Static+type+checking">http://docs.codehaus.org/display/GroovyJSR/GEP+8+-+Static+type+checking</a></p>
<p>Il permettrait d&#8217;indiquer au compilateur d&#8217;effectuer un contrôle de type strict sur certaines classes : tout compte fait c&#8217;est peut-être juste ça que j&#8217;attendais moi ! <img src='http://blog.ippon.fr/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/d-SkseNm_IU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/11/18/devoxx-les-deux-nouveaux-candidats-a-la-succession-au-langage-java/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/11/18/devoxx-les-deux-nouveaux-candidats-a-la-succession-au-langage-java/</feedburner:origLink></item>
		<item>
		<title>Devoxx: Play! Framework 2.0</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/iVXgSjJllVY/</link>
		<comments>http://blog.ippon.fr/2011/11/17/devoxx-play-framework-2-0/#comments</comments>
		<pubDate>Thu, 17 Nov 2011 18:08:36 +0000</pubDate>
		<dc:creator>Antoine BUSCH</dc:creator>
				<category><![CDATA[Evénements]]></category>
		<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Outils]]></category>
		<category><![CDATA[Devoxx]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Play! Framework]]></category>
		<category><![CDATA[Scala]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4589</guid>
		<description><![CDATA[<p>Deuxième retour de la conférence Devoxx qui bat en ce moment même son plein à Anvers en Belgique. J&#8217;ai assisté hier matin à la session sur Play! Framework 2.0 animée par Guillaume Bort et Sadek Drobi.</p> <p></p> Introduction <p>Pour ceux qui ne connaissent pas Play! (et qui visiblemement ne lisent pas ni le blog d&#8217;Ippon, <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/11/17/devoxx-play-framework-2-0/">Devoxx: Play! Framework 2.0</a></span>]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.ippon.fr/2011/11/17/devoxx-play-framework-2-0/play_logo-2/" rel="attachment wp-att-4607"><img class="alignleft size-full wp-image-4607" title="play_logo" src="http://blog.ippon.fr/wp-content/uploads/2011/11/play_logo.png" alt="" width="136" height="50" /></a>Deuxième retour de la conférence Devoxx qui bat en ce moment même son plein à Anvers en Belgique. J&#8217;ai assisté hier matin à la session sur <a title="Play! Framework" href="http://www.playframework.org/" target="_blank">Play! Framework</a> 2.0 animée par Guillaume Bort et Sadek Drobi.</p>
<p><span id="more-4589"></span></p>
<h1>Introduction</h1>
<p>Pour ceux qui ne connaissent pas Play! (et qui visiblemement ne lisent pas ni <a title="Sous le capot de Play! Framework" href="http://blog.ippon.fr/2011/10/19/sous-le-capot-de-play-framework/">le blog d&#8217;Ippon</a>, ni <a title="Le Touilleur Express" href="http://www.touilleur-express.fr/tag/playframework/">le Touilleur Express</a>), il s&#8217;agit d&#8217;un framework orienté web, full-stack (contient toutes les briques nécessaires pour développer, déjà intégrées et configurées), et qui met l&#8217;accent sur la facilité et la rapidité de développement. Il a aussi la particularité de ne rien faire comme les autres&#8230; Pour résumer grossièrement, il s&#8217;agit d&#8217;un équivalent de Ruby on Rails pour le monde Java.</p>
<p>Guillaume Bort, créateur du framework, et Sadek Drobi, un des développeurs principaux, nous ont donc parlé de la prochaine évolution majeure du framework. Ils commencent par faire deux annonces:</p>
<ul>
<li>La sortie de la première bétâ de la future version 2.0.</li>
<li>Typesafe (la société créée par Martin Odersky et Jonas Bonér, les créateurs de Scala et d&#8217;Akka respectivement), vont intégrer officiellement Play! 2.0 dans leur stack. Une intégration naturelle puisque Play 2.0! s&#8217;appuie fortement sur Scala, Akka et sbt&#8230; Guillaume Bort en profite également pour intégrer l&#8217;Advisory Board de Typesafe, où il sera plutôt en bonne compagnie puisqu&#8217;il y rejoint James Gosling et Doug Lea.</li>
</ul>
<h1>Historique</h1>
<p>Sadek Drobi, commence par nous rappeler que le framework Play! est né chez Zenexity pour répondre aux besoins de projets réels, avant d&#8217;être rendu open source. Il nous fait un rapide rappel de l&#8217;évolution du web ces dernières années: d&#8217;abord un web statique, composé de simples pages HTML, puis un web dynamique, où on découvre que l&#8217;on peut manipuler une page dynamiquement, parfois avec certains excès, ce qui donne lieu à une phase de structuration qui est celle dans laquelle nous nous trouvons actuellement.</p>
<p>Selon Sadek Drobi, la prochaine étape qui nous attends est celle du temps réel, où les informations dans la page seront mises à jour en permanence (pensez Twitter&#8230;). Cette évolution du web entraine de nouvelles contraintes : besoin d&#8217;une gestion efficace des flux de données, une gestion plus facile de la concurrence, une meilleure élasticité au déploiement&#8230; Le but de Play! 2.0 est de répondre à ces nouveaux besoins tout en gardant la philosophie qui le caractérise: prise en main facile et intuitive, full-stack, rapidité de développement&#8230;</p>
<h1>Nouveautés</h1>
<p>Guillaume nous fait ensuite une démo rapide de la console Play! Il s&#8217;agit en fait de la console <a title="SBT" href="https://github.com/harrah/xsbt/wiki">SBT</a>. On peut y lancer des commandes comme compile ou run. SBT est wrappée dans le script &#8220;play&#8221; ce qui permet d&#8217;utiliser les même commandes que pour Play! 1.x (ex: play new, play run, play test&#8230;). On peut également lancer l&#8217;interpréteur scala depuis la console, et ainsi avoir accès directement aux classes de notre projet, y compris les templates compilées. On peut donc appeler une template à la main et voir tout de suite le HTML généré. Utile pour débogger&#8230;</p>
<p>Guillaume nous montre ensuite qu&#8217;on peut mélanger Java et Scala dans le même projet, avec le même système de recompilation à la volée, de rechargement à chaud, et d&#8217;affichage des erreurs directement dans le navigateur. Il nous présente aussi le nouveau système de templating. Exit Groovy, place à Scala.  L&#8217;avantage est que les templates sont compilées comme des fonctions Scala, et bénéficient de tous les avantages du typage fort. Si vous renommez un champ d&#8217;un bean, vous saurez dès la compilation que vous avez oublié de mettre à jour un template. Plutôt pratique&#8230;</p>
<p>Fin de la démo. Sadek reprend la parole pour nous parler des besoins grandissant d&#8217;asynchronicité pour les applications web. Lorsqu&#8217;on appelle un système externe pour récupérer des données (appel REST, WS, ou autre&#8230;), il n&#8217;est plus question de bloquer un thread de traitement des requêtes pendant qu&#8217;on attend la réponse. Lorsqu&#8217;on veut traiter un gros flux de données, il n&#8217;est pas question de tout charger en mémoire pour le traiter ensuite. Il faut mieux maîtriser la consommation des ressources (threads, CPU, mémoire). Il faut sortir des API bloquantes (genre InputStream), et mettre en place une méthode plus efficace que simplement passer un callback à une méthode asynchrone. Sadek nous dit qu&#8217;il faut faire du &#8220;reactive programming&#8221;: réagir à des évènements (une requête arrive, la réponse d&#8217;un processus long est arrivée&#8230;).</p>
<p>Il introduit ensuite la réponse de Play! à ce problème: le concept d&#8217;<strong>Iteratee</strong> et d&#8217;<strong>Enumerator</strong>. Concept apparement inspiré par le langage Haskell. De ce que j&#8217;en ai compris, il s&#8217;agit d&#8217;une sorte d&#8217;un producteur (l&#8217;Enumerator) qui notifie un consomateur (l&#8217;Iteratee) que de nouvelles données sont disponibles. L&#8217;Iteratee peut ensuite répondre de plusieurs façons:</p>
<ul>
<li><strong>Continue</strong>: envoie moi encore des données, et traite les de cette façon là.</li>
<li><strong>Stop</strong>: arrête de m&#8217;envoyer des données (et libère potentiellement les resources)</li>
<li><strong>Error</strong>: tu m&#8217;envoies des données invalides.</li>
</ul>
<p>Play! utilise Akka et le modèle d&#8217;acteur pour implémenter ces concepts. Ce point à vraiment l&#8217;air d&#8217;être une des nouveautés importantes, et je suis curieux de voir un exemple concret de mise en pratique de ce pattern&#8230;</p>
<p>Sadek nous parle ensuite de la couche de persistance. Il nous dit qu&#8217;il est illusoire pour eux d&#8217;essayer de faire une couche d&#8217;abstraction générique de la persistance, les technologies sous-jacentes étant trop différentes (bases relationnelles, bases NoSQL, etc&#8230;). Ils préfèrent implémenter des API spécifiques grâce à des modules spécifiques. Pour la version Scala, l&#8217;implémentation par défaut est Anorm (une simple couche au dessus de JDBC). Pour la version Java, EBeans est utilisé comme implémentation légère de JPA.</p>
<p>Sadek et Guillaume nous parlent ensuite de l&#8217;avantage d&#8217;utiliser SBT comme outil de build. SBT étant extensible, il est possible d&#8217;écrire des modules qui viendront étendre le cycle de vie de l&#8217;application. Par exemple, on peut déclarer des &#8220;compiled assets&#8221;, c&#8217;est à dire des resources qui seront compilées automatiquement par Play! en cas de changement, et dont les erreurs seront affichées dans le navigateur, de la même manière que pour les fichiers sources Java ou Scala. On peut par exemple gérer ainsi la compilation des CSS avec Less, ou bien des fichiers Javascript avec CoffeeScript.</p>
<h1>Conclusion</h1>
<p>En conclusion, la réécriture de Play! leur a apporté un certain nombre d&#8217;effets de bords bénéfiques, tels que de meilleures performances, mais aussi d&#8217;apporter du &#8220;type-safety&#8221; partout, y compris dans la couche présentation (les templates), et dans le fichier route (une route définie qui pointe vers une méthode de contrôleur inexistante sera détectée à la compilation).</p>
<p>Un bémol toutefois: il est à noter que Play 2.0 sera incompatible avec Play 1.x, tant au niveau des API que du moteur de templating, et qu&#8217;il n&#8217;existe pas de stratégie de migration bien définie. Les changements d&#8217;API devront être gérés à la main. Pour ce qui est des templates, il faudra soit les réécrire toutes (pas forcément très réaliste), soit espérer que quelqu&#8217;un fasse un module pour pouvoir utiliser le moteur de templating basé sur Groovy avec Play! 2.0. Les projets existants sous Play 1.x risquent de ne pas être migrés vers la version 2.0, mais combien de temps la branche 1.x sera-t-elle maintenue ? De même, Play! 2.0 propose une API Java et une API Scala. On peut se demander combien de temps ces deux APIs seront maintenues en parallèle, et si l&#8217;API Java ne sera pas dans le futur reléguée au deuxième plan.</p>
<p>Play! est souvent perçu comme le trublion des frameworks web, et génère souvent des réactions assez polarisées (on adore ou on déteste). Mais on ne peut que constater en étant à Devoxx qu&#8217;il jouit d&#8217;une popularité croissante en voyant le nombre talks lui sont consacrés cette année. Et l&#8217;annonce de son intégration à la stack Typesafe, qui offrira un support commercial, en est une preuve supplémentaire.</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/iVXgSjJllVY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/11/17/devoxx-play-framework-2-0/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/11/17/devoxx-play-framework-2-0/</feedburner:origLink></item>
		<item>
		<title>Les nouveautés de Spring 3.1 présentées à Devoxx</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/XKDwQj9XNrs/</link>
		<comments>http://blog.ippon.fr/2011/11/17/les-nouveautes-de-spring-3-1-presentees-a-devoxx/#comments</comments>
		<pubDate>Thu, 17 Nov 2011 10:02:24 +0000</pubDate>
		<dc:creator>Julien DUBOIS</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Devoxx]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Spring]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4590</guid>
		<description><![CDATA[<p>A Devoxx, il y a une session que je ne pouvais pas manquer: les nouveautés de Spring 3.1, par Costin Leau.</p> <p>En voici un résumé, avec ma propre interprétation de ses slides et mes commentaires.</p> <p>Spring est aujourd&#8217;hui un framework mature, ce qui signifie que son mode de fonctionnement et ses APIs ne changent pas <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/11/17/les-nouveautes-de-spring-3-1-presentees-a-devoxx/">Les nouveautés de Spring 3.1 présentées à Devoxx</a></span>]]></description>
			<content:encoded><![CDATA[<p>A Devoxx, il y a une session que je ne pouvais pas manquer: les nouveautés de Spring 3.1, par Costin Leau.</p>
<p>En voici un résumé, avec ma propre interprétation de ses slides et mes commentaires.</p>
<p>Spring est aujourd&#8217;hui un framework mature, ce qui signifie que son mode de fonctionnement et ses APIs ne changent pas à chaque nouvelle version. Cependant, le framework continue à évoluer en fonction des nouvelles technologies et tendances qui arrivent: essentiellement le Cloud Computing et les nouvelles versions de Java et Jave EE dans notre cas.</p>
<p>Au cours des deux dernières années, nous avons ainsi vu une explosion du nombre de plateformes sur lesquels on peut déployer son application:</p>
<ul>
<li>Java EE (JBoss 7, Glassfish 3, Websphere 8 )</li>
<li>Tomcat 7 avec les Servlets 3.0</li>
<li>Les platformes de Cloud: GAE (Jetty), Beanstalk (Tomcat), CloudFoundry (Tomcat), CloudBees (Tomcat)</li>
</ul>
<p>Ces plateformes ont un certain dénominateur commun (l&#8217;API Servlet, en particulier), mais elles ont toutes des spécificités qui font qu&#8217;elles sont plus ou moins intéressantes en fonction du besoin et du moment (car ces spécificités changent avec le temps).</p>
<p>D&#8217;où l&#8217;importance d&#8217;être portable au niveau du déployement.<br />
<span id="more-4590"></span><br />
Commençons par un rappel historique: cette portabilité du déployement a toujours été le point fort de Spring: à l&#8217;origine, nous sommes nombreux à être passés à Spring car nous voulions pouvoir déployer la même application en développement (Tomcat) qu&#8217;en production (Websphere/Weblogic).</p>
<p>D&#8217;autre part, on a classiquement 4 environnements dans lesquels on déploie son application:</p>
<ul>
<li>Le développement</li>
<li>Les tests d&#8217;intégration</li>
<li>La pré-production (&#8220;staging&#8221; en Anglais)</li>
<li>La production</li>
</ul>
<p>Comment permettre à son application de se déployer de manière portable?</p>
<ul>
<li>JNDI est la technologie d&#8217;origine, proposée par J2EE. Bien entendu, son défaut est de ne fonctionner qu&#8217;avec un container. Dans mon expérience, elle est généralement compliquée à configurer pour les équipes de production.</li>
<li>Les propriétés systèmes. C&#8217;est une solution appréciée des équipes de production, par contre en Java il nous faut un moyen d&#8217;y accéder de manière simple (ce que propose Spring).</li>
<li>Des &#8220;application contexts&#8221; Spring différents. Une solution &#8220;pure&#8221; Spring qui est très répandue.</li>
<li>Les &#8220;PlaceHolder&#8221; de Spring (avec le tag), qui est une amélioration de la méthode précédente.</li>
</ul>
<p>Spring 3.1 vient ajouter une nouveauté: les profils de beans. On peut grouper les beans par type d&#8217;environnement cible, par exemple &#8220;dev&#8221;, &#8220;test&#8221;, &#8220;prod&#8221;.</p>
<ul>
<li>Typiquement on peut avoir deux beans avec l&#8217;id &#8220;dataSource&#8221;, qui sont instanciés en fonction du profil: une dataSource de &#8220;dev&#8221; et une dataSource de &#8220;test&#8221;.</li>
<li>Cette configuration n&#8217;est pas nécessairement en XML, rappelons que Spring peut maintenant être configuré en Java (avec des annotations), ce qui permet plus de liberté dans ce cas.</li>
</ul>
<p>Ces profils peuvent être activés via une configuration XML, ou via une API Java: il faut donc activer le bon profil au démarrage, par exemple en lisant une variable d&#8217;environnement.</p>
<p>Lors de la conférence, Costin a fait un sondage: la moitié des gens utilisent la configuration XML, la moitié via Java. Précisons, pour les gens qui croient encore que Spring ne se configure que par XML, que cette configuration &#8220;pure Java&#8221; est inclue dans Spring depuis 4 ans.</p>
<p>Cette configuration Java est généralement plus concise à utiliser pour de la configuration d&#8217;infrastructure: la définition de votre data source, de votre gestionnaire de transaction, etc&#8230; Elle est également plus puissante, car on peut plus aisément faire des branchements conditionnels ou du code spécifique qu&#8217;avec du XML.</p>
<p>Cette première partie de la conférence, très intéressante, a cependant un défaut: on n&#8217;y a pas rééllement parlé des nouveautés de Spring 3.1. La deuxième partie de la conférence par contre, était plus orientée sur les nouveautés de cette version 3.1.</p>
<h4>L&#8217;abstraction du cache</h4>
<p>Evidemment, avec l&#8217;achat de Gemfire par VMWare/SpringSource, le support du cache dans Spring est une priorité de Spring 3.1. La bonne nouvelle c&#8217;est que cette abstraction fonctionne avec plusieurs &#8220;fournisseurs&#8221; de cache, et pas que Gemfire: Ehcache (Terracotta), ConcurentMap (implémentation basique mais utile pour les tests), Redis (base NoSQL également sponsorisée par VMWare). D&#8217;autre part, des implémentations Infinispan (JBoss) et Websphere eXtreme Scale (IBM) sont en train d&#8217;être contribuées. Cette fonctionnalité est particulièrement importante pour moi:</p>
<ul>
<li>La JSR Cache commence à redémarrer après des années de stagnation: c&#8217;est donc intéressant d&#8217;avoir quelque chose de déjà utilisable.</li>
<li>Dans un contexte &#8220;Cloud&#8221;, qui implique des applications multi-tenantes, avoir un cache distrbué est absolument essentiel.</li>
</ul>
<h4>Support des Servlets 3.0</h4>
<p>Spring 3.1 va supporter l&#8217;API Servlet 3.0, avec Tomcat 7 ou GlassFish 3, tout en préservant la compatibilité Servlet 2.4.<br />
On peut donc maintenant configurer son application Web sans fichier web.xml</p>
<p>Au niveau de Spring MVC, cela apporte la gestion des requêtes HTTP asynchrones. Cette fonctionnalité est particulièrement importante pour pouvoir monter en charge lorsqu&#8217;on a beaucoup de clients, et que l&#8217;on veut faire une application Web moderne, avec beaucoup d&#8217;appels Ajax (dont certains peuvent être asynchrones).</p>
<p>Au niveau de Spring MVC REST, un refactoring complet a été réalisé. Costin nous promet de meilleures performances, une API plus propre pour les utilisateurs avancés, tout en restant backward compatible.</p>
<p>A ce sujet, deux nouveautés sur l&#8217;annotation @RequestMapping sont intéressantes:</p>
<ul>
<li>&#8220;consumes&#8221;, pour indiquer le type de media consumé (le &#8220;content-type header&#8221;)</li>
<li>&#8220;produces&#8221;, pour indiquer ce que l&#8217;on produit</li>
</ul>
<p>On peut par exemple avoir la configuration suivante:<br />
<code>@RequestMapping(value="/foo", consumes="application/pdf")</code></p>
<h4>Mises à jour de librairies</h4>
<p>Au niveau de JPA, on peut désormais avoir le package scanning sans fichier persistence.xml, ce qui simplifie les applications avec une seule persistence unit.</p>
<p>Spring 3.1 va supporter nativement Hibernate 4.0, avec en particulier des packages spécifiques en fonction des versions (org.springframework.orm.hibernate3 et org.springframework.orm.hibernate4).</p>
<p>De même, Spring 3.1 supporte Quartz 2.x (nombreux changements dans l&#8217;API Quartz 2.0/2.1), avec compatibilité Quartz 1.5. D&#8217;où l&#8217;importance d&#8217;un système d&#8217;abstraction de la configuration, afin de pouvoir monter de version facilement.</p>
<h4>Spring 3.1 supporte Java 7</h4>
<ul>
<li>Utilisation au mieux de Java 7 si il est disponible, sinon Spring utilisera Java 5 ou 6 (oui Spring 3.1 est toujours compatible Java 5)</li>
<li>Support de JDBC 4.1, en particulier pour JdbcTemplate</li>
<li>Support de la nouvelle API Fork/Join arrivée avec Java 7</li>
</ul>
<p>Cette dernière nouveelle concerne la programmation concurrente dans le contexte actuel: nous avons en effet de plus en plus de cores sur nos machines, mais ils sont généralement moins puissants. Donc si on n&#8217;utilise pas tous ces cores de manière optimale, les performances sont moins bonnes que sur certaines &#8220;vieilles&#8221; machines.<br />
Spring permet donc d&#8217;avoir des pools d&#8217;objets spécialisés, qui &#8220;comprennent&#8221; l&#8217;API fork/join et s&#8217;optimisent automatiquement en fonction du nombre de cores disponibles sur le serveur.<br />
Dans un environnement &#8220;cloud&#8221; cette fonctionnalité prend tout son sens: on peut rajouter ou enlever des cores en fonction des besoins, il est donc nécessaire d&#8217;avoir une application capable de s&#8217;optimiser automatiquement en fonction de ces changements.</p>
<h4>L&#8217;avenir et Spring 3.2</h4>
<p>Peu d&#8217;informations sur Spring 3.2, si ce n&#8217;est que le focus sera sur les technologies suivantes:</p>
<ul>
<li>Java EE 7</li>
<li>JCache (JSR 107)</li>
<li>JMS 2.0</li>
<li>Bean Validation 1.1</li>
<li>JPA 2.1</li>
<li>JSF 2.2</li>
</ul>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/XKDwQj9XNrs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/11/17/les-nouveautes-de-spring-3-1-presentees-a-devoxx/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/11/17/les-nouveautes-de-spring-3-1-presentees-a-devoxx/</feedburner:origLink></item>
		<item>
		<title>Tempête sur les RIAs</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/UBtMFWahdpw/</link>
		<comments>http://blog.ippon.fr/2011/11/17/tempete-sur-les-rias/#comments</comments>
		<pubDate>Thu, 17 Nov 2011 07:13:00 +0000</pubDate>
		<dc:creator>Geoffray GRUEL</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[GWT]]></category>
		<category><![CDATA[silverlight]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4583</guid>
		<description><![CDATA[<p>Ceci n&#8217;est pas un billet de fond mais un appel à commentaires :</p> Adobe se désengage plus ou moins en douceur de Flex, MS va bientôt arrêter le support Silverlight, Google ne proposera jamais de support sur GWT. <p>De l&#8217;autre coté des serveurs les utilisateurs raffolent de ces applications enfin ergonomiques et qui fonctionnent sur <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/11/17/tempete-sur-les-rias/">Tempête sur les RIAs</a></span>]]></description>
			<content:encoded><![CDATA[<p>Ceci n&#8217;est pas un billet de fond mais un appel à commentaires :</p>
<ul>
<li>Adobe <a title="Adobe Flex" href="http://blogs.adobe.com/flex/2011/11/your-questions-about-flex.html" target="_blank">se désengage plus ou moins en douceur de Flex</a>,</li>
<li>MS va bientôt <a title="ZDNet Silverlight" href="http://www.zdnet.com/blog/microsoft/will-there-be-a-silverlight-6-and-does-it-matter/11180" target="_blank">arrêter le support Silverlight</a>,</li>
<li>Google ne proposera jamais de support sur GWT.</li>
</ul>
<p>De l&#8217;autre coté des serveurs les utilisateurs raffolent de ces applications enfin ergonomiques et qui fonctionnent sur les vieux coucous des services administratifs du CAC 40 équipé du bon vieil IE.</p>
<p>Que devons-nous faire en phase de choix :</p>
<ul>
<li>Revenir à du JS le temps que la tempête passe ?</li>
<li>Miser sur la communauté pour assurer l&#8217;avenir de Flex et de GWT ?</li>
<li>Miser sur les alternatifs : Vaadin,&#8230;?</li>
<li>Traverser la tempête vitesse grand V et mettre du HTML5 partout ?</li>
</ul>
<p>A vos commentaires.</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/UBtMFWahdpw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/11/17/tempete-sur-les-rias/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/11/17/tempete-sur-les-rias/</feedburner:origLink></item>
		<item>
		<title>Ippon Technologies sponsor de Devoxx France!!</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/XmAFtRohch0/</link>
		<comments>http://blog.ippon.fr/2011/11/16/ippon-technologies-sponsor-de-devoxx-france/#comments</comments>
		<pubDate>Wed, 16 Nov 2011 09:29:31 +0000</pubDate>
		<dc:creator>Julien DUBOIS</dc:creator>
				<category><![CDATA[Evénements]]></category>
		<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Devoxx]]></category>
		<category><![CDATA[Ippon Technologies]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4579</guid>
		<description><![CDATA[<p>LA grande nouvelle du jour est donc la tenue de Devoxx France dans 5 mois, du 18 au 20 Avril 2012 !</p> <p>Impliqué dès le début dans le projet, c’est avec enthousiasme qu’Ippon Technologies s’est engagé à devenir l’un des premiers sponsors de l’événement.</p> <p>Le projet est en cours, mais vous pouvez déjà compter sur <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/11/16/ippon-technologies-sponsor-de-devoxx-france/">Ippon Technologies sponsor de Devoxx France!!</a></span>]]></description>
			<content:encoded><![CDATA[<p>LA grande nouvelle du jour est donc la tenue de <a href="http://www.devoxx.fr" target="_blank">Devoxx France</a> dans 5 mois, du 18 au 20 Avril 2012 !</p>
<p>Impliqué dès le début dans le projet, c’est avec enthousiasme qu’Ippon Technologies s’est engagé à devenir l’un des premiers sponsors de l’événement.</p>
<p>Le projet est en cours, mais vous pouvez déjà compter sur une présence importante d’Ippon Technologies à l’événement: en tant que partenaire et sponsor de longue date des événements de la communauté Java en France, Ippon réaffirme une fois de plus son engagement dans notre plate-forme préférée!</p>
<p>Cette annonce, ainsi que la participation d’Ippon Technologies à l’événement, a été faite ce matin lors de la keynote d’ouverture de <a href="http://www.devoxx.com/display/DV11/Home" target="_blank">Devoxx 2011</a>.</p>
<p>Pour ceux qui auraient participé à l’<a href="http://www.esa.int/SPECIALS/Mars500/" target="_blank">ESA Mars 500</a>, et donc qui n’auraient pas attendu avec impatience <a href="http://www.devoxx.com/display/DV11/Home" target="_blank">Devoxx 2011</a>: il s’agit tout simplement de la plus grande conférence Java en Europe, avec 3200 personnes et les speakers les plus prestigieux.</p>
<p>Ippon Technologies a d’ailleurs envoyé une délégation de 6 de ses consultants sur place, qui vont vous tenir au courant des dernières nouveautés via ce blog, notre compte <a href="https://twitter.com/#!/ippontech" target="_blank">Twitter</a> et notre compte <a href="https://www.facebook.com/ippon.technologies" target="_blank">Facebook</a>: pour tous ceux qui n’ont pas eu la chance d’aller à Anvers cette année, cela donnera un avant-goût de <a href="http://www.devoxx.fr" target="_blank">Devoxx France</a>! Dépêchez-vous de vous inscrire, il ne reste plus que 5 mois!</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/XmAFtRohch0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/11/16/ippon-technologies-sponsor-de-devoxx-france/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/11/16/ippon-technologies-sponsor-de-devoxx-france/</feedburner:origLink></item>
		<item>
		<title>Ippevent Springfuse le 1er Décembre</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/xFBGP8sfdrk/</link>
		<comments>http://blog.ippon.fr/2011/11/14/ippevent-springfuse-le-1er-decembre/#comments</comments>
		<pubDate>Mon, 14 Nov 2011 10:08:01 +0000</pubDate>
		<dc:creator>Antoine SABOT-DURAND</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Ippevents]]></category>
		<category><![CDATA[JSF]]></category>
		<category><![CDATA[SpringFuse]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4559</guid>
		<description><![CDATA[<p>Les Ippevents se suivent et ne se ressemblent pas. Après l&#8217;atelier Git du mois dernier, nous vous invitons le jeudi 1er décembre à découvrir Celerio et sa version online &#8220;SpringFuse&#8221; développés de Jaxio. Ces boosteurs de productivité vous permettent de générer très rapidement une Webapp Spring 3.0, JSF2 / Primefaces sous Maven à partir de votre <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/11/14/ippevent-springfuse-le-1er-decembre/">Ippevent Springfuse le 1er Décembre</a></span>]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" src="http://www.springfuse.com/images/logo/springfuse.png" alt="Logo Springfuse" width="197" height="50" />Les Ippevents se suivent et ne se ressemblent pas. Après l&#8217;atelier Git du mois dernier, nous vous invitons le jeudi 1er décembre à découvrir Celerio et sa version online &#8220;<a href="http://www.springfuse.com/" target="_blank">SpringFuse</a>&#8221; développés de <a href="http://www.jaxio.com/" target="_blank">Jaxio</a>. Ces boosteurs de productivité vous permettent de générer très rapidement une Webapp Spring 3.0, JSF2 / Primefaces sous Maven à partir de votre base de données.</p>
<p><a href="http://twitter.com/framiere" target="_blank">Florent Ramière</a> l&#8217;un des fondateurs de Jaxio viendra nous présenter les outils en question et nous parler de leurs évolutions futures.</p>
<p>Rappelons que nos Ippevents sont gratuits et ouvert à tous.</p>
<p>Pour vous inscrire cliquez sur le bouton ci-dessous ou rendez-vous sur notre page <a title="Inscription aux Ippevents" href="http://blog.ippon.fr/inscription-aux-ippevents/" target="_blank">Ippevent</a>.</p>
<div style="width: 100%; text-align: left;"><iframe frameborder="0" height="192" marginheight="5" marginwidth="5" scrolling="auto" src="http://www.eventbrite.com/tickets-external?eid=2150419964&amp;ref=etckt" width="100%"></iframe></p>
<div style="font-family: Helvetica, Arial; font-size: 10px; padding: 5px 0 5px; margin: 2px; width: 100%; text-align: left;"><a style="color: #ddd; text-decoration: none;" href="http://www.eventbrite.com/r/etckt" target="_blank">Enregistrement en ligne à un événement</a><span style="color: #ddd;"> pour </span><a style="color: #ddd; text-decoration: none;" href="http://ippeventspringfuse.eventbrite.com?ref=etckt" target="_blank">Ippevent SpringFuse</a><span style="color: #ddd;"> produit par </span><a style="color: #ddd; text-decoration: none;" href="http://www.eventbrite.com?ref=etckt" target="_blank">Eventbrite</a></div>
</div>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/xFBGP8sfdrk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/11/14/ippevent-springfuse-le-1er-decembre/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/11/14/ippevent-springfuse-le-1er-decembre/</feedburner:origLink></item>
		<item>
		<title>Java : Accès directs à la mémoire (off-Heap)</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/SP_RXo4AoDQ/</link>
		<comments>http://blog.ippon.fr/2011/11/03/java-acces-directs-a-la-memoire-off-heap/#comments</comments>
		<pubDate>Thu, 03 Nov 2011 08:00:23 +0000</pubDate>
		<dc:creator>Christophe PARAGEAUD</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[ByteBuffer]]></category>
		<category><![CDATA[Garbage]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JVM]]></category>
		<category><![CDATA[off-Heap]]></category>
		<category><![CDATA[Stack]]></category>
		<category><![CDATA[sun.misc.Unsafe]]></category>
		<category><![CDATA[Threads]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4397</guid>
		<description><![CDATA[<p>La zone mémoire la plus connue d&#8217;une JVM est la heap mais ce n&#8217;est pas la seule zone de stockage disponible.</p> <p>Nous verrons comment est structurée la mémoire d&#8217;une JVM et comment allouer de l&#8217;espace en dehors de la Heap ?</p> <p>Et ce, dans le but de pouvoir conserver les données en mémoire même pour <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/11/03/java-acces-directs-a-la-memoire-off-heap/">Java : Accès directs à la mémoire (off-Heap)</a></span>]]></description>
			<content:encoded><![CDATA[<p>La zone mémoire la plus connue d&#8217;une JVM est la heap mais ce n&#8217;est pas la seule zone de stockage disponible.</p>
<p><img class="alignleft" style="margin-left: 15px; margin-right: 15px;" src="http://blog-dev.net/wp-content/uploads/2011/04/java.png" alt="" width="154" height="154" />Nous verrons comment est structurée la mémoire d&#8217;une JVM et comment allouer de l&#8217;espace en dehors de la Heap ?</p>
<p>Et ce, dans le but de pouvoir conserver les données en mémoire même pour les applications les plus consommatrices.</p>
<p>Points abordés :</p>
<ul>
<li>Quelles sont les méthodes pour instancier de la mémoire hors heap</li>
<li>Les cas d&#8217;applications (Cache, Memory Mapped File)</li>
<li>Performances</li>
<li>Problèmes rencontrés</li>
</ul>
<p><span id="more-4397"></span></p>
<h2>Introduction et théorie</h2>
<p>Voici les différentes zones que l&#8217;on peut retrouver dans un process Java :</p>
<div id="attachment_4399" class="wp-caption alignnone" style="width: 627px"><a href="http://blog.ippon.fr/2011/11/03/java-acces-directs-a-la-memoire-off-heap/structjvm/" rel="attachment wp-att-4399"><img class="size-full wp-image-4399" title="Process Java" src="http://blog.ippon.fr/wp-content/uploads/2011/10/StructJVM.png" alt="" width="617" height="106" /></a><p class="wp-caption-text">Process Java</p></div>
<p style="padding-left: 60px;">On y trouve des zones techniques : JVM, OS.</p>
<p style="padding-left: 60px;">Des zones de stockage de données : Mémoire Heap et native.</p>
<p style="padding-left: 60px;">La zone d&#8217;échange entre la JVM et l&#8217;OS : Librairies.</p>
<p>La gestion de la memoire Java est parfois assez déroutante pour les débutants : les paramètres de gestion les plus connus sont ms et mx qui régissent la taille de la Heap alors que nous venons de voir que ce n&#8217;est pas la seule zone mémoire d&#8217;une JVM.</p>
<p>Java nio a introduit le principe de mémoire off-heap (java 1.4). Java 7 l&#8217;a étendu (JSR-203/NIO2).</p>
<p>Les objets concernés sont les ByteBuffers (java.nio.ByteBuffer) avec allocation directe (maximum de  2 Go par buffer).<br />
Concrètement il s&#8217;agit d&#8217;un tableau de Bytes qui sera stocké dans la mémoire native.<br />
La nature même du stockage (sous forme binaire) impose une sérialisation/désérialisation des objets.</p>
<p>Tout d&#8217;abord le tableau suivant montre pourquoi il faut privilégier la mémoire aux autres types d&#8217;accès.</p>
<p style="text-align: left;"><span style="color: #333399;">Comparaison des coûts de lecture en fonction du type de mémoire</span></p>
<table border="1" cellspacing="0" cellpadding="1" align="center">
<tbody>
<tr align="center" valign="middle">
<th><strong>Technologie</strong></th>
<th><strong>Vitesse lecture</strong></th>
</tr>
<tr align="center" valign="middle">
<td style="text-align: center;">Mémoire (RAM)</td>
<td style="text-align: center;"> 10-60 ns</td>
</tr>
<tr align="center" valign="middle">
<td style="text-align: center;">Accès réseau</td>
<td style="text-align: center;">10000-30000 ns</td>
</tr>
<tr align="center" valign="middle">
<td style="text-align: center;">Disques SSD</td>
<td style="text-align: center;">70000-120000 ns</td>
</tr>
<tr align="center" valign="middle">
<td style="text-align: center;">Disques durs</td>
<td style="text-align: center;">3000000-10000000 ns</td>
</tr>
</tbody>
</table>
<p>La conclusion semble évidente : pour des raisons de performances, il faut privilégier la mémoire locale à tout autre type de stockage.</p>
<h3>Gabarge Collector et problématiques</h3>
<p>Longtemps la taille maximale allouée à une JVM a été limitée par différents facteurs :</p>
<ul>
<li>Architecture 32 bits du processeur.</li>
<li>Système d&#8217;exploitation hébergeant la JVM (taille maximale d&#8217;un processus, maximum de RAM supportée)</li>
</ul>
<p>Mais aussi, et c&#8217;était souvent le premier seuil atteint, par le comportement du Garbage Collector.</p>
<p>Il s&#8217;agissait de trouver le meilleur ratio entre taille de la Heap et péjoration des performances dues aux traitements du Garbage Collector.<br />
De même, bien que plus rare que dans les langages sans gestion automatique de la mémoire, un programme Java n&#8217;est pas à l&#8217;abri des fuites mémoires.</p>
<p>C&#8217;est pourquoi, malgré la multiplication des architectures et OS 64 bits, cette barière n&#8217;a que peut évoluée depuis les débuts de Java.<br />
On peut la fixer à 3-4 Go.</p>
<p>Conscients de cette limite, les éditeurs tentent de réagir.</p>
<p>Oracle à introduit le collecteur G1 (Garbage first) en version 6 de Java SE.<br />
Ce collecteur a pour but de réduire les temps de passage du GC.</p>
<p>Azul System, s&#8217;est aussi positionné, avec la Zing Virtual Machine (<a href="http://www.azulsystems.com/zing/pgc">Pauseless Garbage Collection</a>).</p>
<p>En attendant, il est tentant d&#8217;utiliser le stockage hors heap dans des applications Java.</p>
<h2>Mémoire off-heap</h2>
<p>Une belle définition sous forme de lapalissade pourrait être : « tout ce qui n&#8217;est pas dans la heap est off heap ».</p>
<p>Tout d&#8217;abord voyons comment est structurée la mémoire dans la JVM</p>
<p><a href="http://blog.ippon.fr/2011/11/03/java-acces-directs-a-la-memoire-off-heap/zonesmemoirejvm/" rel="attachment wp-att-4404"><img class="size-full wp-image-4404 aligncenter" title="ZonesMemoireJVM" src="http://blog.ippon.fr/wp-content/uploads/2011/10/ZonesMemoireJVM.png" alt="" width="700" height="262" /></a></p>
<h3>A &#8211; Zones méthodes (Method Area)</h3>
<p>Cette zone est essentiellement alimentée par le classloader.<br />
Quand la JVM charge une classe ou une interface, elle place les informations nécessaires dans cette zone.<br />
Cette zone est éligible au Garbage Collector. Quand une classe passe hors scope elle sera collectée lors du prochain passage du GC.<br />
Cette zone est partagée (accessible à tous les process de la JVM).</p>
<h4>1 &#8211; Pool constantes :</h4>
<h3><span class="Apple-style-span" style="font-size: 13px; font-weight: normal;">Contient toutes les constantes définies par l&#8217;application :</span></h3>
<p style="padding-left: 30px;">Littérales : int, long, float, double ou bien String.<br />
Références vers les types, les champs et les méthodes.</p>
<h4>2 &#8211; Code méthode :</h4>
<p>Implémentation (bytecode) de toutes les méthodes utilisées par la JVM.</p>
<h4>3 &#8211; Zone d&#8217;informations :</h4>
<p>Contient différents éléments d&#8217;information sur les classes.<br />
Champs de classe :</p>
<ul>
<li>Nom du champ.</li>
<li>Type du champ.</li>
<li>Modificateurs du champ.</li>
</ul>
<p>Méthodes :</p>
<ul>
<li>Nom de la méthode.</li>
<li>Type retourné.</li>
<li>Nombre et type des paramètres.</li>
<li>Modificateurs de la méthode.</li>
</ul>
<p>En plus pour les méthodes non abstraites ou natives :</p>
<ul>
<li>Taille de l&#8217;opérande et des variables locales (utilisée pour frame stack).</li>
<li>Table d&#8217;exception.</li>
</ul>
<h4>4 &#8211; Variables de classes</h4>
<p>Les variables de classes sont partagées par toutes les instances de la classe. De plus elles ne sont pas liées à l&#8217;instanciation d&#8217;une classe mais créées au chargement de la classe.</p>
<h3>B &#8211; Heap</h3>
<p>Lorsque la JVM doit instancier un objet java, elle le fait dans cette zone.<br />
On y retrouve les classes, les objets, les primitives Java.<br />
Cette zone est nettoyée par le GC.</p>
<p>Cette zone est partagée (accessible à tous les process de la JVM).</p>
<p>NB : il y a une seule Heap et Method Area par JVM.</p>
<h3>C &#8211; Threads</h3>
<p>Cette zone n&#8217;est pas partagée.</p>
<h4>Pointeur d&#8217;instruction :</h4>
<p>Indique la ligne de code actuellement exécutée.</p>
<h4>Java stack :</h4>
<p>Stocke les primitives et les références.</p>
<p>Stocke l&#8217;état des méthodes invoquées (non natives) par le thread, l&#8217;état comprend les variables locales à la méthode (ThreadLocal), les paramètres d&#8217;appel ainsi que la valeur retournée par la méthode.</p>
<p>Chaque état est stocké dans des frames (un par méthode) dont la durée de vie est liée au cycle d&#8217;appel de la méthode.</p>
<p><del>Cette zone est nettoyée par le GC.</del></p>
<p>Cette zone est parcourue par le GC afin d&#8217;identifier les objets non référencés dans la Heap.</p>
<h4>Frames :</h4>
<p>Trois sections compose les frames.</p>
<p><strong>Piles opérande</strong></p>
<ul>
<li>Pile FIFO 32/64 bits utilisée pour le stockage provisoire des variables ainsi que des calculs intermédiaires.</li>
</ul>
<p><strong>Données</strong></p>
<ul>
<li>Références RCP (Runtime Constant Pool).</li>
<li>Références vers le pool de constantes utilisées par le thread.</li>
<li>Résultats des retours de méthodes.</li>
</ul>
<p><strong>Variables locales</strong></p>
<ul>
<li>Tableau contenant les variables locales de la méthode. Soit les variables dont la durée de vie est celle de la méthode ainsi que les paramètres d&#8217;appel.</li>
</ul>
<div id="attachment_4405" class="wp-caption aligncenter" style="width: 314px"><a href="http://blog.ippon.fr/2011/11/03/java-acces-directs-a-la-memoire-off-heap/thread/" rel="attachment wp-att-4405"><img class="size-full wp-image-4405 " title="Thread" src="http://blog.ippon.fr/wp-content/uploads/2011/10/Thread.png" alt="" width="304" height="353" /></a><p class="wp-caption-text">Stack Frames</p></div>
<h4>Méthodes natives</h4>
<p>A l&#8217;image des Frames l&#8217;état des méthodes natives est stocké dans cette zone.<br />
Mais contrairement à ces dernières, l&#8217;organisation est dépendante de l&#8217;OS et de l&#8217;implémentation de la méthode native.</p>
<h2>Création d&#8217;objets en dehors de la heap Java</h2>
<p>L&#8217;utilisation dans un programme Java de mémoire hors heap devra répondre aux problématiques suivantes :</p>
<ul>
<li>Accéder à la mémoire hors heap.</li>
<li>Gestion de la mémoire.</li>
<li>Référencement et accès à la mémoire off-heap.</li>
</ul>
<h3>A &#8211; Java Native Access (JNA)</h3>
<p>JNA permet l&#8217;accès aux librairies natives (dll, so) à partir de code Java uniquement (sans utiliser JNI ou du C).<br />
Une interface java décrit les méthodes et les structures de la librairie native.<br />
Il n&#8217;y a pas de génération de code tout se fait au Runtime.</p>
<p>JNA est fourni avec certaines librairies natives courantes ainsi que des classes utilitaires d&#8217;accès à la mémoire native.</p>
<p>Plus d&#8217;informations :</p>
<p style="padding-left: 30px;">Documentation : <a href="http://www.root-me.org/fr/Documentation/Hacking/Java-native-code-injection.html">http://www.root-me.org/fr/Documentation/Hacking/Java-native-code-injection.html</a><br />
Site web :<a href=" https://github.com/twall/jna"> https://github.com/twall/jna</a></p>
<p>Cette librairie fournie plusieurs méthodes pour créer des objets en dehors de la heap.</p>
<pre class="brush: java; title: ; notranslate">
int value = 12345;
int offset = 0;
int size = 128;

// on crée un objet mémory
Memory m = new Memory(1024);

// on alloue l'espace mémoire
ByteBuffer buff = m.getByteBuffer(0, size);

offset = offset + size;

// On insère l'objet
buff.putInt(value);

// RAZ de la position courante du buffer
buff.flip();

// On récupère et affiche l'objet
System.out.println(buff.getInt());

// On déclare un deuxième buffer
ByteBuffer buff2 = m.getByteBuffer(offset, size);

// On insère l'objet
buff2.putInt(value + 1);

// RAZ de la position courante du buffer
buff2.flip();

// On récupère et affiche l'objet
System.out.println(buff2.getInt());

// on libère la mémoire
m.clear();

// méthode 2
// on crée un objet mémory
// et on insère directement les objets
Memory m2 = new Memory(1024);

// On insère l'objet
m2.setInt(offset, value);

// On récupère et affiche l'objet
System.out.println(m2.getInt(offset));

// on libère la mémoire
m2.clear();
</pre>
<h3>B &#8211; Utilisation de la classe ByteBuffer</h3>
<p>L&#8217;utilisation de la mémoire native avec cette API est simple, voire transparente.<br />
Deux méthodes de création d&#8217;un ByteBuffer sont disponibles :</p>
<ol>
<li>ByteBuffer.allocateDirect()</li>
<li>ByteBuffer.allocate()</li>
</ol>
<p>Seule la première méthode instancie un objet en dehors de la heap.</p>
<p>Exemple de code :</p>
<pre class="brush: java; title: ; notranslate">
byte[] bytes = ...;
// allocate native memory to store our object
ByteBuffer buf = ByteBuffer.allocateDirect(bytes.length);
buf.put(bytes);
</pre>
<p>Remarque : Le contenu stocké doit être de type tableau de byte, ce qui explique que le contenu stocké hors heap doit être sérialisable.</p>
<p><strong>Nota Bene</strong> : Ceux qui on déjà codé en C/C++ ne devront pas s&#8217;attendre a retrouver l&#8217;équivalent de malloc.<br />
En effet les possibilités offertes sont très limitées et le plus surprenant étant qu&#8217;il n&#8217;y a pas de méthode pour désallouer un objet stocké hors heap.</p>
<p>Comment ça marche alors ?<br />
En réalité une méthode de libération de la mémoire est crée automatiquement (sun.misc.Cleaner) et sera appelée par le GC lors de son prochain passage.</p>
<h4>Conclusion :</h4>
<p>Tout comme pour la heap, l&#8217;espace est libéré par le GC lorsque l&#8217;objet n&#8217;est plus référencé par le code.<br />
Tout comme la heap il n&#8217;y a pas de relation directe entre le moment ou l&#8217;objet est libérable et le moment ou il est effectivement libéré.<br />
Donc il n&#8217;y a pas de magie, les objets hors heap sont bien sensibles au GC.</p>
<p>Toutefois :</p>
<ul>
<li>Pas de phase de marquage des objets.</li>
<li>Pas de phase de compaction (réorganisation de l&#8217;espace mémoire) pendant le passage du GC.</li>
<li>Le nettoyage de la mémoire hors heap est donc plus rapide que son homologue de la heap.</li>
</ul>
<p>Il est possible d&#8217;appeler la méthode de nettoyage à tout moment (encore une fois en fouillant dans les profondeurs de l&#8217;API) :</p>
<pre class="brush: java; light: true; title: ; notranslate">
Method getCleanerMethod = buffer.getClass().getMethod(&quot;cleaner&quot;, new Class[0]);
getCleanerMethod.setAccessible(true);
sun.misc.Cleaner cleaner = (sun.misc.Cleaner)getCleanerMethod.invoke(buffer,
   new Object[0]);
cleaner.clean();
</pre>
<h3>C &#8211; Autres possibilité d&#8217;allocation directe</h3>
<h4>sun.misc.Unsafe</h4>
<p>Son utilisation est un peu plus complexe, il s&#8217;agit de la classe qui est derrière ByteBuffer.allocateDirect().<br />
Comme son nom l&#8217;indique cette classe est unsafe et doit donc être utilisée en toute connaissance de cause. En effet l’accès à une zone mémoire non allouée provoque immanquablement le crash de la JVM.<br />
Pour plus de sécurité les constructeurs sont privés et la méthode de classe getUnsafe() ne peut être appelée que par un Bootloader (et donc par la JVM elle même).</p>
<p>Heureusement il est possible de contourner cette sécurité.</p>
<p>Méthode de récupération d&#8217;une instance :</p>
<pre class="brush: java; light: true; title: ; notranslate">
private static Unsafe getUnsafeInstance() throws SecurityException,
NoSuchFieldException, IllegalArgumentException,
IllegalAccessException {
   Field theUnsafeInstance = Unsafe.class.getDeclaredField(&quot;theUnsafe&quot;);
   theUnsafeInstance.setAccessible(true);
   return (Unsafe) theUnsafeInstance.get(Unsafe.class);
}
</pre>
<p>Autres cas d&#8217;utilisation de la classe :<br />
Cette classe permet de connaître l&#8217;adresse d&#8217;un objet stocké en mémoire.<br />
Plus précisément la position d&#8217;un champ dans la zone mémoire allouée aux instances de la classe.</p>
<pre class="brush: java; title: ; notranslate">
// Récupère une instance Unsafe
Unsafe unsafe = getUnsafeInstance();

// Réserve de la mémoire directe
Long allocateMemory = unsafe.allocateMemory(10);

// Récupération de l'espace d'allocation du champs code Commune
Field field = Commune.class.getDeclaredField(&quot;codeCommune&quot;);
Long offsetCodeCommune = unsafe.objectFieldOffset(field);

// On affecte une valeur à l'emplacement du champ
unsafe.putObject(allocateMemory, offsetCodeCommune, &quot;325555&quot;);
</pre>
<p>NB : qui a dit qu&#8217;il fallait obligatoirement un setter public ?</p>
<h4>MemoryMappedFile</h4>
<p>Le contenu du fichier est mappé dans l&#8217;espace mémoire du process depuis le fichier source. Une fois le fichier chargé (ou une portion du fichier) tous les accès se font en mémoire.<br />
Il en résulte des performances extrêmes par rapport aux méthodes traditionnelles qui utilisent les accès disques.</p>
<p>Cette méthode est la plus indiquée en cas de copie partielle ou totale d&#8217;un fichier.</p>
<pre class="brush: java; title: ; notranslate">

File file = new File(path);

// Creation d'un memory-mapped file en lecture seule
FileChannel roChannel = new RandomAccessFile(file, &quot;r&quot;).getChannel();

MappedByteBuffer mbb = roChannel.map(FileChannel.MapMode.READ_ONLY, 0,
   (int) roChannel.size());

// tableau de bits utilisé pour la lectre
ByteArrayBuffer bits = new ByteArrayBuffer();

while(mbb.hasRemaining()) {
   // on lit le prochain octet
   byte b = mbb.get();
   if (b == 10 || b == 13) {
      if (!firstLine) {
         // On ignore la première ligne (entête)
         firstLine = true;
      } else {
         // on affiche le contenu du fichier
         System.out.println(bits.toString());
      }

     // on passe à une nouvelle ligne
     // on réinitialise le tableau
     bits = new ByteArrayBuffer();
     } else
       // on ajoute l'octet au tableau
       bits.write(b);
}

// on ferme le canal
roChannel.close();

// on vide le buffer
mbb.clear();
...
</pre>
<p>Particularités :</p>
<ul>
<li>L&#8217;OS charge/décharge le contenu du fichier selon les besoins.</li>
</ul>
<ul>
<li>Utile pour les fichiers extrêmement volumineux.</li>
</ul>
<ul>
<li>Ou à l&#8217;inverse lorsque seul un fragment d&#8217;un fichier est utilisé.</li>
</ul>
<h2>Exemple</h2>
<p>Mise en cache d&#8217;un extrait de la liste des communes mondiales de plus de 1000 habitants (+/- 114000) à partir d&#8217;un csv. Le code présenté a été teste avec la JVM OpenJDK 1.7 sur MAC (elle apporte un MBean de monitoring de la mémoire allouée par AllocateDirect()).</p>
<p>Quatre versions :</p>
<ol>
<li>Une classique avec une Map</li>
<li>Une directbuffer en utilisant serialisation java</li>
<li>Une directbuffer en utilisant externalizable java</li>
<li>Une unsafe</li>
</ol>
<p>1)</p>
<pre class="brush: java; title: ; notranslate">
public class MemoryCache {

private Mapdata = new HashMap();

public void put(Object key, Commune object) throws IOException {
data.put(key, object);
}

public Object get(Object key) throws ClassNotFoundException, IOException {
return data.get(key);
}
…

}
</pre>
<p>2) &amp; 3)</p>
<pre class="brush: java; title: ; notranslate">
public class NativeMemoryCache {
private Map data = new HashMap();

public void put(Object key, Serializable object) throws IOException {
 byte[] bytes = serialize(object);
 // allocate native memory to store our object
 ByteBuffer buf = ByteBuffer.allocateDirect(bytes.length);
 buf.put(bytes);
 buf.flip();
 data.put(key, buf);
}

public Object get(Object key) throws ClassNotFoundException, IOException {
 ByteBuffer buf = data.get(key).duplicate();
 byte[] bytes = new byte[buf.remaining()];
 buf.get(bytes);
 return deserialize(bytes);
}
…

}
</pre>
<p>4)</p>
<pre class="brush: java; title: ; notranslate">
public class NativeMemoryCacheUnSafe {

/**
* Création de la map pour stocker la clé
* ainsi que l'adresse de l'objet en mémoire native
*/
private Map data = new HashMap(120000);

/**
* Objet Unsafe pour accéder
* à la mémoire native
*/
private static Unsafe unsafe = null;

/**
* Offset de stockage dans la mémoire native
*/
private static Long offset = new Long(0);

static {
 try {
   unsafe = getUnsafeInstance();
 } catch (SecurityException e) {
   System.out.println(&quot;Exception de sécurité :&quot; + e);
 } catch (NoSuchFieldException e) {
   System.out.println(&quot;Impossible d'accéder au champ de la classe Unsafe :&quot; + e);
 } catch (IllegalAccessException e) {
   System.out.println(&quot;Impossible d'accéder à la classe Unsafe :&quot; + e);
 }
}

public void put(Long key, long codeCommune, String nomCommune, double latitude,
double longitude, String codePays, String codeRegion, String codeAdministratif,
int population, String timeZone) throws IOException,
SecurityException, NoSuchFieldException, IllegalArgumentException,
IllegalAccessException {
//Taille max d'un objet (bytes)
Long allocateMemory = unsafe.allocateMemory(400);

unsafe.putObject(allocateMemory, offset, new Commune(codeCommune, nomCommune, latitude,
 longitude, codePays, codeRegion, codeAdministratif, population, timeZone));

data.put(key, allocateMemory);
}

/**
* @param key identifiant unique de l'objet
* @return
* @throws ClassNotFoundException
* @throws IOException
* @throws SecurityException
* @throws NoSuchFieldException
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
public Commune get(Object key) throws ClassNotFoundException, IOException,
SecurityException, NoSuchFieldException, IllegalArgumentException,
IllegalAccessException {

 Long adresse = data.get(key);
 return (Commune)unsafe.getObject(adresse, offset);
}

…

}
</pre>
<h2>Résultats</h2>
<p><strong>used</strong> : La quantité de mémoire réellement utilisée par l&#8217;application.<br />
<strong>committed</strong> : La quantité de mémoire qui a été réservée auprès du système d&#8217;exploitation.</p>
<p><strong>Paramètres JVM</strong> : -X:+AggressiveHeap</p>
<p>Test 1.</p>
<table border="1" cellspacing="0" cellpadding="1" align="center">
<tbody>
<tr align="center" valign="middle">
<th><strong>Type de test</strong></th>
<th><strong>Classic</strong></th>
</tr>
<tr align="center" valign="middle">
<td>Temps de traitement (ms)</td>
<td>477</td>
</tr>
<tr align="center" valign="middle">
<td>Collection Count</td>
<td> 0</td>
</tr>
<tr align="center" valign="middle">
<td> Collection Time</td>
<td> 0</td>
</tr>
<tr align="center" valign="middle">
<td>Utilisation heap</td>
<td>used=229749Ko<br />
committed=2636992Ko</td>
</tr>
<tr align="center" valign="middle">
<td>Utilisation non Heap</td>
<td>used=3729Ko<br />
committed = 23744Ko</td>
</tr>
<tr align="center" valign="middle">
<td>Buffer pool<br />
(si pas de libération de la mémoire)</td>
<td>_</td>
</tr>
</tbody>
</table>
<p>Test 2.</p>
<table border="1" cellspacing="0" cellpadding="1" align="center">
<tbody>
<tr align="center" valign="middle">
<th><strong>Type de test</strong></th>
<th><strong>Direct </strong><br />
<strong>(Serializable)</strong></th>
</tr>
<tr align="center" valign="middle">
<td>Temps de traitement (ms)</td>
<td>1697</td>
</tr>
<tr align="center" valign="middle">
<td>Collection Count</td>
<td> 1</td>
</tr>
<tr align="center" valign="middle">
<td> Collection Time</td>
<td>1329</td>
</tr>
<tr align="center" valign="middle">
<td>Utilisation heap</td>
<td>used=794123Ko<br />
committed=2652352Ko</td>
</tr>
<tr align="center" valign="middle">
<td>Utilisation non Heap</td>
<td>used=4615Ko<br />
committed=23744Ko</td>
</tr>
<tr align="center" valign="middle">
<td>Buffer pool<br />
(si pas de libération de la mémoire)</td>
<td>Type : Direct<br />
Count:113576<br />
MemoryUsed:31849106<br />
Total capacity:31849106</td>
</tr>
</tbody>
</table>
<p>Test 3.</p>
<table border="1" cellspacing="0" cellpadding="1" align="center">
<tbody>
<tr align="center" valign="middle">
<th><strong>Type de test</strong></th>
<th><strong>Direct </strong><br />
<strong>(Externalizable)</strong></th>
</tr>
<tr align="center" valign="middle">
<td>Temps de traitement (ms)</td>
<td>1473</td>
</tr>
<tr align="center" valign="middle">
<td>Collection Count</td>
<td>1</td>
</tr>
<tr align="center" valign="middle">
<td> Collection Time</td>
<td>413</td>
</tr>
<tr align="center" valign="middle">
<td>Utilisation heap</td>
<td>used=288094Ko<br />
committed=2655296Ko</td>
</tr>
<tr align="center" valign="middle">
<td>Utilisation non Heap</td>
<td>used=4587Ko<br />
committed = 23744Ko</td>
</tr>
<tr align="center" valign="middle">
<td>Buffer pool<br />
(si pas de libération de la mémoire)</td>
<td>Type : Direct<br />
Count:113576<br />
MemoryUsed:16175618<br />
Total capacity:16175618</td>
</tr>
</tbody>
</table>
<p>Test 4.</p>
<table border="1" cellspacing="0" cellpadding="1" align="center">
<tbody>
<tr align="center" valign="middle">
<th><strong>Type de test</strong></th>
<th><strong>Direct</strong><br />
<strong>(Unsafe)</strong></th>
</tr>
<tr align="center" valign="middle">
<td>Temps de traitement (ms)</td>
<td>490</td>
</tr>
<tr align="center" valign="middle">
<td>Collection Count</td>
<td>0</td>
</tr>
<tr align="center" valign="middle">
<td> Collection Time</td>
<td>0</td>
</tr>
<tr align="center" valign="middle">
<td>Utilisation heap</td>
<td>used=232327Ko<br />
committed=2652480Ko</td>
</tr>
<tr align="center" valign="middle">
<td>Utilisation non Heap</td>
<td>used=3780Ko<br />
committed=23744Ko</td>
</tr>
<tr align="center" valign="middle">
<td>Buffer pool<br />
(si pas de libération de la mémoire)</td>
<td>-</td>
</tr>
</tbody>
</table>
<h2>Frameworks utilisant l&#8217;accés direct à la mémoire</h2>
<p style="padding-left: 30px;"><a href="http://www.terracotta.org/products/bigmemory">Terracota BigMemory</a> (ehcache) : stockage de données dans la mémoire native<br />
<a href="http://www.oracle.com/fr/products/middleware/coherence/index.html"> Coherence</a> : Coherence propose le stockage off heap dans son cache<br />
<a href="https://github.com/raffaeleguidi/DirectMemory"> DirectMemory</a> : Equivalent open source de Big Memory<br />
<a href="http://code.google.com/p/vanilla-java/wiki/HugeCollections"> Huge collections</a> : Framework permettant de manipuler de grande collection en utilisant la mémoire native</p>
<h3>Références</h3>
<p>Java virtual machine specifications : <a href="http://java.sun.com/docs/books/jvms/">http://java.sun.com/docs/books/jvms/</a><br />
The Structure of the Java Virtual Machine : <a href="http://java.sun.com/docs/books/vmspec/2nd-edition/html/Overview.doc.html">http://java.sun.com/docs/books/vmspec/2nd-edition/html/Overview.doc.html</a></p>
<h3>Options de la JVM relatives à la mémoire directe.</h3>
<p><strong>-d64</strong><br />
Permet de passer la JVM en mode 64bits, utile pour adresser plus de mémoire.</p>
<p><strong>-XX:MaxDirectMemorySize=</strong> ou <strong>-Dsun.nio.MaxDirectMemorySize=</strong><br />
Permet de définir la mémoire maximale réservées pour la mémoire off heap.</p>
<p><strong>-XX:+PageAlignDirectMemory</strong> ou <strong>-Dsun.nio.PageAlignDirectMemory=true</strong><br />
Permet de s&#8217;assurer qu&#8217;un espace de mémoire native est alignée sur une page mémoire. Avant le JDK7, une page entière (ou plus) était allouée quelle que soit la taille de l&#8217;objet (4096 octets sur une majorité d&#8217;OS).</p>
<h2>Conclusion</h2>
<p>L&#8217;exemple retenu n&#8217;est pas le plus favorable aux cas d&#8217;utilisation de la mémoire off-heap, c&#8217;est pourquoi il met en exergue les inconvénients de cette solution.</p>
<p>L&#8217;utilisation de la mémoire native est une solution à envisager si votre programme est très consommateur en mémoire et pas forcement pour les programmes affectés par les passages du GC.</p>
<p>Ce n&#8217;est donc pas forcement le miracle attendu dans le sens ou ne vous dispensera pas des tracas du GC.</p>
<p>De plus le programme consomme temporairement autant de heap qu&#8217;un programme traditionnel (creation d&#8217;objets avant de stocker off-heap).</p>
<p>Enfin la sérialisation est coûteuse en terme de performances (mais seuls les programmes les plus exigeants la verront comme un véritable obstacle).<br />
C&#8217;est pourquoi, sauf à utiliser la classe Unsafe, l&#8217;utilisation de la mémoire native est moins performante que son homologue Heap.</p>
<p>Conditions idéales d&#8217;utilisation de la mémoire native :</p>
<ul>
<li>Idéal quand la volumétrie de données est très importante (&gt; 2 Go).</li>
<li>Quand les données sont stables dans le temps (sinon les données sont collectées par le GC).</li>
<li>Et enfin quand les données sont sérialisables.</li>
</ul>
<p>L&#8217;utilisation des classes comme Unsafe est très dangereuse et réclamera une longue mise au point afin d&#8217;éviter un crash de la JVM avec pour seuls indices un code retour 139 (Segmentation violation) ou 134 (Dump core).<br />
Pour les programmes affectés par le passage du Garbage Collector, c&#8217;est une solution parmi d&#8217;autres :</p>
<p style="padding-left: 30px;">1. Tuning de la JVM et du GC<br />
2. Création d&#8217;un pool d&#8217;objets réutilisables (crées à l&#8217;avance et jamais libérés).</p>
<p>Le code source est disponible ici : <a href="http://blog.ippon.fr/wp-content/uploads/2011/11/IPPON_BLOG_OffHeap.zip">Source</a></p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/SP_RXo4AoDQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/11/03/java-acces-directs-a-la-memoire-off-heap/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/11/03/java-acces-directs-a-la-memoire-off-heap/</feedburner:origLink></item>
		<item>
		<title>Nouvelle version du site d’Ippon Technologies</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/LbbPP4xMcIg/</link>
		<comments>http://blog.ippon.fr/2011/10/25/nouvelle-version-du-site-ippon-technologies/#comments</comments>
		<pubDate>Tue, 25 Oct 2011 12:26:24 +0000</pubDate>
		<dc:creator>Julien DUBOIS</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Ippon Technologies]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4372</guid>
		<description><![CDATA[<p>La nouvelle version de notre site http://www.ippon.fr est en ligne !</p> <p>Au menu, nous vous proposons de nouvelles rubriques détaillant nos offres, nos compétences, nos références et partenaires&#8230; Ainsi qu&#8217;une mise à jour des parties recrutement et société, avec de nouvelles pages pour nos agences de Bordeaux et Nantes.</p> <p>Nous avons voulu mettre l&#8217;accent sur <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/10/25/nouvelle-version-du-site-ippon-technologies/">Nouvelle version du site d&#8217;Ippon Technologies</a></span>]]></description>
			<content:encoded><![CDATA[<p>La nouvelle version de notre site <a href="http://www.ippon.fr" target="_blank">http://www.ippon.fr</a> est en ligne !</p>
<p>Au menu, nous vous proposons de nouvelles rubriques détaillant nos <a href="http://www.ippon.fr/offre" target="_blank">offres</a>, nos <a href="http://www.ippon.fr/expertise-technique" target="_blank">compétences</a>, nos <a href="http://www.ippon.fr/references" target="_blank">références</a> et <a href="http://www.ippon.fr/partenaires" target="_blank">partenaires</a>&#8230; Ainsi qu&#8217;une mise à jour des parties <a href="http://www.ippon.fr/recrutement" target="_blank">recrutement</a> et <a href="http://www.ippon.fr/societe" target="_blank">société</a>, avec de nouvelles pages pour nos agences de <a href="http://www.ippon.fr/bordeaux" target="_blank">Bordeaux</a> et <a href="http://www.ippon.fr/nantes" target="_blank">Nantes</a>.</p>
<p>Nous avons voulu mettre l&#8217;accent sur l&#8217;<a href="http://www.ippon.fr/societe" target="_blank">esprit d&#8217;Ippon</a>, <a href="http://www.ippon.fr/contributions" target="_blank">notre participation aux communautés Java et agile</a>, et nous avons intégré le site avec ce blog et nos comptes <a href="https://twitter.com/#!/ippontech" target="_blank">Twitter</a> et <a href="http://www.linkedin.com/company/ippon-technologies" target="_blank">LinkedIn</a>, afin de permettre une meilleure interactivité avec nos visiteurs.</p>
<p>Au niveau technique, car nous savons que c&#8217;est ce qui intéresse avant tout les lecteurs de ce blog:</p>
<ul>
<li>En tant qu&#8217;experts Liferay, il était évident pour nous que  le site devait être entièrement développé et mis en page sur un Liferay 6. Nous avons réalisé quelques portlets spécifiques, ainsi que notre propre template, mais l&#8217;essentiel du site est réalisé avec les fonctionnalités standard de Liferay. Nous avons particulièrement apprécié :
<ul>
<li>Les nouvelles fonctionnalités de CMS proposées par Liferay 6</li>
<li>La manière dont Liferay nous permet de gérer le SEO (Search Engine Optimization), à la fois simple et puissante</li>
</ul>
</li>
<li>Nous sommes hébergés sur le cloud Ippon, qui est une plateforme <a href="http://opennebula.org/" target="_blank">Open Nebula</a> (et sur laquelle nous hébergeons également nos clients qui le désirent)</li>
<li>Nous avons géré tous nos développements sur la plateforme de développement interne d&#8217;Ippon: <a href="http://subversion.apache.org/" target="_blank">SVN</a> et <a href="http://trac.edgewall.org/" target="_blank">Trac</a> en particulier. C&#8217;est la même plateforme que nous utilisons pour les forfaits réalisés dans nos locaux.</li>
</ul>
<p>Si vous êtes encore sous IE6 il faudra attendre la semaine prochaine pour un accès dégradé.</p>
<p>Bonne navigation,</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/LbbPP4xMcIg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/10/25/nouvelle-version-du-site-ippon-technologies/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/10/25/nouvelle-version-du-site-ippon-technologies/</feedburner:origLink></item>
		<item>
		<title>Sous le capot de Play! Framework</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/TnY7x1L7u1U/</link>
		<comments>http://blog.ippon.fr/2011/10/19/sous-le-capot-de-play-framework/#comments</comments>
		<pubDate>Wed, 19 Oct 2011 08:48:01 +0000</pubDate>
		<dc:creator>Ludovic CHANE WON IN</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Play! Framework]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4288</guid>
		<description><![CDATA[<p align="LEFT">Play! Framework est un petit « nouveau » dans l&#8217;écosystème fourni des framework web Java et il a fait beaucoup parler de lui ces derniers temps. Pourquoi tant de bruit (bon ou mauvais d&#8217;ailleurs) me direz-vous ? Je n&#8217;entrerais pas dans ce débat et cet article n&#8217;est pas là pour faire l&#8217;éloge ou non de Play!. D&#8217;un <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/10/19/sous-le-capot-de-play-framework/">Sous le capot de Play! Framework</a></span>]]></description>
			<content:encoded><![CDATA[<p align="LEFT"><strong></strong><img class="alignnone size-full wp-image-4296" style="float: left; padding: 0px; margin-top: -1px; margin-right: 10px; border-width: 0px;" title="play_logo" src="http://blog.ippon.fr/wp-content/uploads/2011/10/play_logo-e1318867072992.jpg" alt="" width="200" height="140" />Play! Framework est un petit « nouveau » dans l&#8217;écosystème fourni des framework web Java et il a fait beaucoup parler de lui ces derniers temps. Pourquoi tant de bruit (bon ou mauvais d&#8217;ailleurs) me direz-vous ? Je n&#8217;entrerais pas dans ce débat et cet article n&#8217;est pas là pour faire l&#8217;éloge ou non de Play!. D&#8217;un point de vue personnel, je dirais juste que Play! m&#8217;a redonné envie de faire du développement web en java. Après c&#8217;est une question de goût.</p>
<p align="LEFT">Deux des fonctionnalités de Play! que j&#8217;apprécie particulièrement sont : <strong>le rechargement à chaud du code Java</strong> et <strong>le bytecode enhancement</strong>. Je vous propose de voir comment, sous le capot, Play! met en œuvre ces 2 fonctionnalités.</p>
<p align="LEFT"><span id="more-4288"></span></p>
<h2 align="LEFT">Introduction</h2>
<p align="LEFT">Je vais passer très vite sur la présentation de Play!. Nombreux sont ceux qui l&#8217;ont déjà fait et mieux que je ne pourrais le faire. Si c&#8217;est la première fois que vous entendez le mot Play! (dans un article en français traitant de Java), je vous invite à vous rendre sur les liens suivants :</p>
<ul>
<li>
<p align="LEFT"><a href="http://www.playframework.org/" target="_blank">site officiel</a></p>
</li>
<li>
<p align="LEFT"><a href="http://www.touilleur-express.fr/2010/02/12/version-play-de-lapplication-zencontact-de-zenika/" target="_blank">article sur le touilleur-express.fr</a></p>
</li>
<li>
<p align="LEFT"><a href="http://www.zeroturnaround.com/blog/my-top-5-play-framework-features/" target="_blank">Les 5 meilleures features de Play! Framework</a> de Toomas Römer</p>
</li>
</ul>
<h2 align="LEFT">Le rechargement à chaud</h2>
<p align="LEFT">Avec Play!, en mode développement, on démarre notre serveur, on fait joujou avec l&#8217;application, on s&#8217;aperçoit qu&#8217;il y a un bug, on ouvre son IDE favori, on corrige le bug, on recompile, on redéploie et …. et NON NON NON ! On ne recompile pas et on ne redéploie pas ! On revient juste sur son navigateur, on rafraichit la page et hop magie, le bug a disparu (enfin peut-être) ! C&#8217;est juste simplement magique mais en informatique (comme dans la vraie vie en fait), la magie ça n&#8217;existe pas. Alors comment Play! s&#8217;y prend-t-il ? Sous le capot, Play! utilise le <a href="http://www.eclipse.org/jdt/core/" target="_blank">JDT Compiler d&#8217;Eclipse</a>, celui là même utilisé par l&#8217;IDE du même nom.</p>
<p align="LEFT">Déjà, au lancement de l&#8217;application, Play! va :</p>
<ul>
<li>
<p align="LEFT">scanner le répertoire de l&#8217;application à la recherche des fichiers sources .java</p>
</li>
<li>
<p align="LEFT">compiler ces fichiers à l&#8217;aide du JDT Compiler d&#8217;Eclipse</p>
</li>
<li>
<p align="LEFT">charger les classes en mémoire</p>
</li>
</ul>
<p align="LEFT">Ensuite, à chaque requête (et en mode développement), Play! essaye de détecter tout changement du code source.</p>
<p align="LEFT">En ce qui concerne des modifications apportées à des classes existantes, Play! conserve dans une HashMap l&#8217;ensemble des classes qu&#8217;il a compilées ainsi qu&#8217;un timestamp de la dernière compilation pour chacune des classes. Il suffit alors de comparer ce timestamp à la date de dernière modification du fichier correspondant pour savoir si Play! doit recompiler la classe et la recharger. Un petit coup de <span style="color: #333333;"><em>java.lang.Instrumentation.redefineClasses(classesDefinitions)</em></span> est alors nécessaire pour redéfinir les classes modifiées. Cette redéfinition de classe possède quelques limites :</p>
<ul>
<li>
<p align="LEFT">les instances existantes des classes redéfinies ne sont pas affectées</p>
</li>
<li>
<p align="LEFT">la redéfinition ne doit pas ajouter, supprimer ou renommer des attributs ou des méthodes, changer la signature des méthodes ou modifier l&#8217;héritage. Si c&#8217;est le cas, alors Play! va stopper et recharger l&#8217;application dans son intégralité.</p>
</li>
</ul>
<p align="LEFT">Maintenant, que fait Play! si l&#8217;on a ajouté ou supprimé des classes ? A la compilation des fichiers sources, Play! calcule un hash de la concaténation de toutes les classes compilées. Ainsi, il suffit de recalculer ce hash, de le comparer au précédent afin de savoir si un différentiel de classes existe. Si c&#8217;est le cas, alors encore une fois, Play! redémarre l&#8217;application dans son intégralité.</p>
<h2 align="LEFT">Le bytecode enhancement</h2>
<p align="LEFT">Quoi ? Play! fait du bytecode enhancement ? Mais où ? Pourquoi ?… au fait c&#8217;est quoi le bytecode enhancement ? Tentons de répondre à ces questions.</p>
<p align="LEFT">Pour commencer, où est-ce que Play! fait du bytecode enhancement ? Dans les classes de modèles par exemple. Dans Play!, on peut utiliser Hibernate (à travers JPA) pour persister nos objets Java dans une base de données. Il suffit d&#8217;annoter notre classe avec <span style="color: #333333;"><em>@javax.persistence.Entity</em></span>. Ensuite Play! fournit la classe Model qu&#8217;on peut étendre pour avoir un support out of the box de JPA :</p>
<pre class="brush: java; title: ; notranslate">
@Entity
public class Person extends Model {
    public String name;
    public Integer age;
}
</pre>
<p align="LEFT">L&#8217;arbre d&#8217;héritage de Person est : <span style="color: #333333;"><em>Person</em></span> &gt; <span style="color: #333333;"><em>Model</em></span> &gt; <span style="color: #333333;"><em>GenericModel</em></span> &gt; <span style="color: #333333;"><em>JPABase</em></span>. Grâce à cet héritage on a accès à des méthodes utilitaires du type find(), findAll(), findById(), count() :</p>
<pre class="brush: java; title: ; notranslate">Person.findAll() //va retourner toutes les entités de type Person</pre>
<p align="LEFT">Mais si on regarde bien l&#8217;implémentation de ces méthodes qui se trouvent dans la classe <span style="color: #333333;"><em>GenericModel</em></span>, voici ce qu&#8217;on observe pour la méthode findAll() :</p>
<pre class="brush: java; title: ; notranslate">
public static &amp;amp;lt;T extends JPABase&amp;amp;gt; List&amp;amp;lt;T&amp;amp;gt; findAll() {
    throw new UnsupportedOperationException(&amp;amp;quot;Please annotate your JPA model with @javax.persistence.Entity annotation.&amp;amp;quot;);
}
</pre>
<p align="LEFT">Pourtant lorsqu&#8217;on utilise la méthode statique findAll(), j&#8217;ai bien le résultat attendu et non pas une exception qui m&#8217;est remontée. C&#8217;est là qu&#8217;intervient l&#8217;enhancement de bytecode. Dans Play!, ce sont les rôles des classes de type <em><span style="color: #333333;">play.classloading.enhancers.Enhancer</span></em> que d&#8217;enhancer le bytecode.</p>
<p align="LEFT">Du coup répondons à la 2ème question, qu&#8217;est ce que l&#8217;enhancement de bytecode ? C&#8217;est tout simplement le fait de manipuler le bytecode, d&#8217;avoir la possibilité de définir une nouvelle classe au runtime et de modifier une classe lorsque la JVM la charge en mémoire. Plusieurs frameworks existent pour nous faciliter cette tache : <a href="http://cglib.sourceforge.net/" target="_blank">cglib</a>, <a href="http://asm.ow2.org/" target="_blank">ASM</a> ou encore <a href="http://www.javassist.org/" target="_blank">Javaassist</a>. Et c&#8217;est ce dernier qu&#8217;utilise Play!.<br />
Revenons à notre exemple et prenons la classe <span style="color: #333333;"><em>play.db.jpa.JPAEnhancer</em></span> qui va créer les méthodes des entités JPA de notre modèle.</p>
<pre class="brush: java; title: ; notranslate">
public class JPAEnhancer extends Enhancer {
    public void enhanceThisClass(ApplicationClass applicationClass) throws Exception {
        CtClass ctClass = makeClass(applicationClass)
        if (!ctClass.subtypeOf(classPool.get(&amp;amp;quot;play.db.jpa.JPABase&amp;amp;quot;))) {
            return;
        }

        // Enhance only JPA entities
        if (!hasAnnotation(ctClass, &amp;amp;quot;javax.persistence.Entity&amp;amp;quot;)) {
            return;
        }

        [...]

        // findAll
        CtMethod findAll = CtMethod.make(&amp;amp;quot;public static java.util.List findAll() { return getJPAConfig(&amp;amp;quot;+entityName+&amp;amp;quot;.class).jpql.findAll(&amp;amp;quot;&amp;amp;quot; + entityName + &amp;amp;quot;&amp;amp;quot;); }&amp;amp;quot;, ctClass);
        ctClass.addMethod(findAll);

        [...]
    }
}
</pre>
<ul>
<li>
<p align="LEFT">Ligne 1 à 2 :les classes qui étendent <span style="color: #333333;"><em>Enhancer</em></span> doivent implémenter la méthode <span style="color: #333333;"><em>enhanceThisClass().</em></span><span style="color: #333333;"><em><br />
ApplicationClass</em></span> est une classe de Play! et représente tout simplement une classe. Ses attributs notables sont par exemple javaFile (une référence au fichier source java), javaByteCode (le bytecode compilé), enhancedBytecode (le bytecode manipulé).</p>
</li>
</ul>
<ul>
<li>
<p align="LEFT">Ligne 3 : on instancie une <span style="color: #333333;"><em>javaassist.CtClass</em></span>. <span style="color: #333333;"><em>CtClass</em></span> est une classe du framework Javaassist et représente une classe.</p>
</li>
<li>
<p align="LEFT">Ligne 4 à 6 : on vérifie que cette classe hérite de <span style="color: #333333;"><em>Play.db.jpa.JPABase</em></span>. Sinon on ne fait rien</p>
</li>
<li>
<p align="LEFT">Ligne 9 à 11 : on vérifie que cette classe est annotée avec <span style="color: #333333;"><em>@javax.persistence.Entity</em></span>. Sinon on ne fait rien</p>
</li>
<li>
<p align="LEFT">Linge 16 à 17 : on crée la méthode<span style="color: #333333;"><em> findAll()</em></span> grâce à <span style="color: #333333;"><em>javaassist.CtMethod.make()</em></span>. Notez que cette méthode prend en paramètre une <span style="color: #333333;"><em>String</em></span> représentant du code Java (pas besoin de connaître le bytecode)</p>
</li>
</ul>
<p align="LEFT">La classe <span style="color: #333333;"><em>JPAEnhancer</em></span> va donc boucler sur toutes les entités et rajouter toutes ces méthodes au runtime. D&#8217;autres Enhancer existent dans Play! tels que <span style="color: #333333;"><em>PropertiesEnhancer</em></span> et <span style="color: #333333;"><em>ControllersEnhancer</em></span>. N&#8217;hésitez pas à y jeter un coup d&#8217;oeil, le code se trouve sur Github : <a href="https://github.com/playframework/play" target="_blank">https://github.com/Playframework/Play</a></p>
<h2 align="LEFT">Conclusion</h2>
<p align="LEFT">Nous avons ouvert le capot de Play! pour voir ce qu&#8217;il s&#8217;y cachait. L&#8217;utilisation du <a href="http://www.eclipse.org/jdt/core/" target="_blank">JDT Compiler d&#8217;Eclipse</a> permet de gérer la compilation à la volée et le rechargement à chaud de l&#8217;application. Néanmoins cette fonctionnalité a ses limites : dès qu&#8217;on ajoute/supprime des classes ou qu&#8217;on modifie « trop » (changement de signature, ajout de champ, d&#8217;annotation, …) une classe, toute l&#8217;application est rechargée ce qui peut être pénalisant si l&#8217;application prend du temps à démarrer.<br />
L&#8217;enhancement de bytecode, qui permet d&#8217;enrichir nos classes au runtime, fait appel à <a href="http://www.javassist.org/" target="_blank">Javassist</a> et donne encore plus à Play! ce côté « magique ». Par contre jouer avec le bytecode, c&#8217;est sympa mais après à débugger c&#8217;est tout de suite plus compliqué. Pour cela, vous pouvez utiliser <a href="http://java.decompiler.free.fr/?q=jdgui" target="_blank">JD-GUI</a> pour désassembler les .class précompilés par Play!.<br />
Plein d&#8217;autres choses se cachent sous le capot de Play!, n&#8217;hésitez pas à l&#8217;ouvrir et à laisser un commentaire si vous découvrez quelque chose d&#8217;intéressant.</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/TnY7x1L7u1U" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/10/19/sous-le-capot-de-play-framework/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/10/19/sous-le-capot-de-play-framework/</feedburner:origLink></item>
		<item>
		<title>L’héritage de Dennis Ritchie (1941-2011)</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/HjrUZWcaDS8/</link>
		<comments>http://blog.ippon.fr/2011/10/14/lheritage-de-dennis-ritchie/#comments</comments>
		<pubDate>Fri, 14 Oct 2011 12:25:49 +0000</pubDate>
		<dc:creator>Antoine SABOT-DURAND</dc:creator>
				<category><![CDATA[Culture]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[UNIX]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4262</guid>
		<description><![CDATA[<p class="wp-caption-text">Dennis Ritchie (debout) et Ken Thompson devant un PDP-11 en 1972 Chez Bell.</p> <p>La semaine dernière, à l&#8217;occasion de la disparition de Steve Jobs, Geoffray évoquait l&#8217;héritage technologique que celui-ci avait apporté à la communauté des développeurs en général et Java EE en particulier. N&#8217;en déplaise aux intégristes (comme le Molah Stallman), aux grincheux <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/10/14/lheritage-de-dennis-ritchie/">L&#8217;héritage de Dennis Ritchie (1941-2011)</a></span>]]></description>
			<content:encoded><![CDATA[<div class="wp-caption aligncenter" style="width: 538px"><img class=" " src="http://blog-admin.wired.com/wiredenterprise/wp-content/uploads/2011/10/thompson-and-ritchie.jpg" alt="" width="528" height="422" /><p class="wp-caption-text">Dennis Ritchie (debout) et Ken Thompson devant un PDP-11 en 1972 Chez Bell.</p></div>
<p>La semaine dernière, à l&#8217;occasion de la disparition de Steve Jobs, <a title="Nous sommes tous, experts JavaEE, des enfants de Steve Jobs" href="http://blog.ippon.fr/2011/10/06/nous-sommes-tous-experts-javaee-des-enfants-de-steve-jobs/" target="_blank">Geoffray évoquait l&#8217;héritage technologique</a> que celui-ci avait apporté à la communauté des développeurs en général et Java EE en particulier. N&#8217;en déplaise aux intégristes (comme le <a href="http://www.zdnet.com/blog/hardware/richard-m-stallman-on-steve-jobs-im-not-glad-hes-dead-but-im-glad-hes-gone/15275" target="_blank">Molah Stallman</a>), aux grincheux ou aux incultes, cet apport est bien réel et la micro informatique de 2011 doit beaucoup à l&#8217;Apple II, au Macintosh ou à Next Step. Evidemment quasiment toutes ces &#8220;inventions&#8221; attribuées à Jobs ne sont que du recyclage d&#8217;idées mises au rebut par d&#8217;autres (<a href="http://en.wikipedia.org/wiki/PARC_(company)" target="_blank">Xerox pourrait aujourd&#8217;hui être à la place d&#8217;Apple ou Microsoft</a>), mais n&#8217;est-ce pas ce que tous les innovateurs font : aller plus haut en montant sur les épaules des géants qui les ont précédés ? Les épaules sur lesquelles Jobs est monté sont nombreuses, mais celles de Dennis Ritchie sont probablement les plus larges. <span style="direction: ltr;">Car si la micro-informatique doit beaucoup à Jobs, l&#8217;informatique en général doit encore plus à Dennis Ritchie qui nous a quitté le week-end dernier à l&#8217;age de 70 ans.</span><br />
 <span id="more-4262"></span></p>
<h2><span style="direction: ltr;">L&#8217;histoire</span></h2>
<h2></h2>
<p>A la fin des années 60, Ritchie travaillait aux <a href="http://en.wikipedia.org/wiki/Bell_Labs" target="_blank">Bell Laboratories</a> avec Ken Thompson au développement d&#8217;un nouvel OS : Unix. La première version du système fut écrite en assembleur, mais rapidement, ils réalisèrent qu&#8217;ils auraient besoin d&#8217;un langage de plus haut niveau pour développer la seconde version, notamment pour gérer les structures de données indispensables au différentes fonctions de l&#8217;OS. La première tentative en Fortran fut rapidement abandonnée et  Ritchie proposa de créer un  nouveau langage basé sur le language B créé par Thompson quelques années plus tôt.</p>
<p>Plusieurs légendes courrent au sujet du langage B : Thompson l&#8217;aurait nommé de la sorte d&#8217;après le nom de sa femme &#8220;Bonnie&#8221; ou moins romantique d&#8217;après le nom du language BCPL dont il était inspiré. J&#8217;avais pour ma part entendu raconté que le B était pour Bell. Toujours est-il que l&#8217;itération suivante s&#8217;appelerait logiquement le <strong>language C</strong>.</p>
<p>La langage B était interprété et comme Ritchie et Thompson avaient autant besoin de rapidité que de flexibilité, il décidèrent que le C serait compilé pour produire un code proche de la machine.</p>
<p>La première version du C n&#8217;était pas très différente de celle d&#8217;aujourd&#8217;hui quoiqu&#8217;un peu moins étoffée. Les types étaient déjà là ainsi que les fameuse structures de données (<code>struct{};</code>pour les intimes).</p>
<p>En résumé, C fut inventé pour pouvoir écrire un programme et ce programme était le noyau Unix, rien que ça&#8230;</p>
<p>En 1973, Ritchie publia un article scientifique sur le langage C et 5 ans plus tard, lui et son collègue Brian Kernighan (qui avait rédigé les premiers tutoriels sur C et qui força un peu la main de Ritchie) publièrent le classique &#8220;<a href="http://www.google.fr/url?sa=t&#038;source=web&#038;cd=5&#038;sqi=2&#038;ved=0CEkQFjAE&#038;url=http%3A%2F%2Fwww.inf.unideb.hu%2Fgrafika%2Feng%2Frtornai%2FKernighan_Ritchie_Language_C.pdf&#038;rct=j&#038;q=ritchie%20and%20kernighan&#038;ei=i_2XTpK5GoSi4gTQqaD4Aw&#038;usg=AFQjCNEe0iSo6C0EofmmKStH9SlQA3Jaqg" target="_blank">C programming language</a>&#8220;.</p>
<p>Bell ayant laissé ouvert et accessible le code source d&#8217;Unix, il se répandit avec le C dans les université comme une trainée de poudre pour atteindre le succès qu&#8217;on lui connait.</p>
<h2>L&#8217;héritage</h2>
<p>Est-il besoin d&#8217;expliquer l&#8217;importance de ces deux inventions sur ce blog ? Je ne pense pas (ou alors vous vous êtes vraiment perdu). Je résumerai juste par deux schéma trouvé sur le Web :</p>
<div id="attachment_4268" class="wp-caption aligncenter" style="width: 774px"><img class="size-full wp-image-4268 " title="Language_history_JRL" src="http://blog.ippon.fr/wp-content/uploads/2011/10/Language_history_JRL.png" alt="" width="764" height="717" /><p class="wp-caption-text">History of programming language (sur http://civilprogrammers.blogspot.com)/</p></div>
<p style="text-align: left;">dans ce premier schéma qui présente un aperçu des principaux langages par décénie et héritage, on voit bien que tous les langages utilisés aujourd&#8217;hui ont C comme ancêtre commun et gardons à l&#8217;esprit également que leur compilateur et/ou environnement d&#8217;éxécution ont été ou sont encore écrit en C.</p>
<div id="attachment_4267" class="wp-caption aligncenter" style="width: 1088px"><a href="http://blog.ippon.fr/wp-content/uploads/2011/10/Unix_history-simple.png"><img class="size-full wp-image-4267 " title="Unix_history-simple" src="http://blog.ippon.fr/wp-content/uploads/2011/10/Unix_history-simple.png" alt="" width="1078" height="695" /></a><p class="wp-caption-text">Historique simplifié d&#39;Unix (Wikipedia)</p></div>
<p style="text-align: left;">Ce deuxième schéma illustre une version simplifiée de la galaxie Unix. En parcourant ce diagramme on se rend compte qu&#8217;en dehors de Windows (qui reste donc l&#8217;OS grand public le plus propriétaire mais est malgré tout développé en C), tous les autres sont basés sur Unix. Les deux premières cases du haut c&#8217;est Ritchie, la troisième colonne c&#8217;est Steve Jobs (au passage on peut voir, que <a href="http://fr.wikipedia.org/wiki/Darwin_(informatique)" target="_blank">Darwin</a>, la version de BSD qui constitue la base de Mac OS X a son code ouvert (en fait open source mais avec une licence non reconnue par l&#8217;OSI)). Ainsi, si Jobs fait partie de l&#8217;héritage de beaucoup d&#8217;entre nous Ritchie fait partie de notre Héritage à tous.</p>
<p style="text-align: left;">C&#8217;est parfois bon de se sortir le nez le l&#8217;IDE pour se rappeler que nous avons une histoire. <span style="direction: ltr;">Car, Etre compétent ou expert techniquement ne suffit pas pour faire un bon développeur. La culture informatique doit également s&#8217;appuyer sur le passé. Comprendre la raison d&#8217;être des outils que nous utilisons et connaître leurs ancêtres est capital. Ca évite de dire des imbécilités ou de ré-inventer la roue.</span></p>
<p style="text-align: right;"><em><span style="direction: ltr;">&#8220;Celui qui ne connait pas l&#8217;histoire est condamné à la revivre&#8221;<br />
 K. Marx</span></em></p>
<pre class="brush: cpp; title: ; notranslate">
#include &amp;amp;lt;stdio.h&amp;amp;gt;

main(int argc, *char argv[]){
	if(argc!=1)
		exit(1);
	else {
		char *dennis=&amp;amp;quot;Dennis&amp;amp;quot;;
		char *world=&amp;amp;quot;World&amp;amp;quot;;
		if(strcmp(dennis,argv[0])==0) {
			printf(&amp;amp;quot;Hello %s says %s n&amp;amp;quot;,world,dennis);
			printf(&amp;amp;quot;Good bye %s says the %s n&amp;amp;quot;,dennis,world);
			exit(0);
		}
	}
</pre>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/HjrUZWcaDS8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/10/14/lheritage-de-dennis-ritchie/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/10/14/lheritage-de-dennis-ritchie/</feedburner:origLink></item>
		<item>
		<title>JPA : une magie qui se mérite (retour aux sources de JPA)</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/uSd_cZ38viw/</link>
		<comments>http://blog.ippon.fr/2011/10/11/jpa-une-magie-qui-se-merite-retour-aux-sources-de-jpa/#comments</comments>
		<pubDate>Tue, 11 Oct 2011 13:25:05 +0000</pubDate>
		<dc:creator>Antoine SABOT-DURAND</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[CDI]]></category>
		<category><![CDATA[EJB 3.1]]></category>
		<category><![CDATA[Java EE]]></category>
		<category><![CDATA[JPA]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=3820</guid>
		<description><![CDATA[<p> Cet article fait partie d&#8217;une série sur les technologies incluses dans Java EE 6. Vous pouvez également lire l&#8217;article d&#8217;introduction de cette série : Java EE 6 ici et maintenant et celui sur JSF : JSF je t&#8217;aime, moi non plus</p> <p>L&#8217;une des technologies les plus populaires dans le monde Java EE est sans aucun <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/10/11/jpa-une-magie-qui-se-merite-retour-aux-sources-de-jpa/">JPA : une magie qui se mérite (retour aux sources de JPA)</a></span>]]></description>
			<content:encoded><![CDATA[<p><em> <img class="alignleft size-full wp-image-4700" title="DB_Magic" src="http://blog.ippon.fr/wp-content/uploads/2011/10/DB_Magic.png" alt="" width="191" height="163" />Cet article fait partie d&#8217;une série sur les technologies incluses dans Java EE 6. Vous pouvez également lire l&#8217;article d&#8217;introduction de cette série :<a title="Java EE 6 ici et maintenant !" href="http://blog.ippon.fr/2011/03/21/java-ee-6-ici-et-maintenant/" target="_blank"> Java EE 6 ici et maintenant</a> et celui sur JSF : <a title="JSF je t’aime, moi non plus" href="http://blog.ippon.fr/2011/04/27/jsf-je-taime-moi-non-plus/" target="_blank">JSF je t&#8217;aime, moi non plus</a></em></p>
<p><em></em>L&#8217;une des technologies les plus populaires dans le monde Java EE est sans aucun doute JPA. Il suffit de voir le nombre de livres et d&#8217;articles sur le sujet. Toutefois, si JPA est très répandu, il s&#8217;agit aussi de l&#8217;une des spécifications Java EE les moins bien maîtrisées par les développeurs et donc une source récurrente d&#8217;échecs des projets. Fort de ce constat je ne vais pas m&#8217;apesentir sur les nouveauté de JPA 2.0 dans ce post (en dehors de l&#8217;API criteria, celles-ci sont pluôt à la marge) pour me permettre de faire un retour aux sources sur JPA qui pourra profiter à certains. Ceux qui pensent maîtriser ces concepts pourraient être quand même intéressés par la fin de la&#8217;article qui traite de l&#8217;extended persistence context et de ses mérites.</p>
<p><span id="more-3820"></span></p>
<h2>Une &#8220;magie&#8221; complexe</h2>
<p>La popularité de JPA et les échecs que cette techno engendre sont probablement liées au mélange de magie, de concepts compliqués qu&#8217;elle camoufle et de dissimulation de ces concepts au sein de frameworks destinés à faciliter son utilisation. La magie et les raccourcis offert par Spring (entre autres) permettent  de se lancer dans l&#8217;utilisation de l&#8217;outil sans avoir besoin de trop comprendre les couches sous-jacentes. Lorsque l&#8217;on arrive dans des cas concrets qui posent des problèmes, une grande partie des développeurs désinvestissent l&#8217;outil en critiquant ses limitations sans chercher à creuser plus avant. Parce que JPA nous fait sortir du confort du code pour aller nous battre avec des notions parfois mal digérés de gestion de transaction et base de données, il reste une énigme pour beaucoup. Certains développeurs pensent que le concept d&#8217;ORM en général et JPA en particulier permet de négliger SQL et les mécanismes bas niveau d&#8217;échange avec la BDD en les ramenant au rang de technologies inférieures. En pensant cela ils commettent une erreur : JPA rend l&#8217;utilisation de ces technologies plus facile et puissante mais ne nous permet pas des les occulter totalement. Il est un facilitateur pas une technologie de substitution.</p>
<h2>Les 4 piliers de JPA</h2>
<div id="attachment_4205" class="wp-caption alignright" style="width: 424px"><img class="size-full wp-image-4205  " title="Schema_JPA" src="http://blog.ippon.fr/wp-content/uploads/2011/10/Schema_JPA.png" alt="" width="414" height="618" /><p class="wp-caption-text">Schema Global du fonctionnement de JPA</p></div>
<p>JPA s&#8217;inscrit autour de ces 4 notions fondamentales :</p>
<ul>
<li>Les entités</li>
<li>Les Persistence Units (au runtime on les manipulera via la classe PersistenceManagerFactory)</li>
<li>L&#8217;Entity Manager (ou persistence manager)</li>
<li>Les transactions</li>
</ul>
<p>Le schéma ci-contre illustre le fonctionnement de JPA et comment ces 4 éléments fonctionnent ensemble. Pour synthétiser :</p>
<ul>
<li>La<strong> Persistence Unit</strong> organise les meta données qui définissent le mapping entre les entités et la base</li>
<li>La <strong>Persistence Manager Factory</strong> récupère ces metas données de la Persistence Unit et les interprètent pour créer des Persistence Manager</li>
<li>Le <strong>Persistence Mangager</strong> gère les échanges entre le code et la base de donnée, c&#8217;est à dire le cycle de vie des <strong>entités</strong></li>
<li>Enfin, le travail du Persistence Manager est englobé dans une <strong>Transaction. </strong>Cette dernière peut éventuellement gérer les opérations de plusieurs Persistence Managers comme un traitement unitaire.</li>
</ul>
<p>Sans faire un cours exhaustif, il parait intéressant de faire un point sur les concepts clés liés à chacune de ces notions clés</p>
<h2>Les transactions</h2>
<p>Les transactions ne faisant pas stricto sensu partie de JPA, mais étant une composante indispensable au fonctionnement et donc à la compréhension de cette technologie, il est intéressant de commencer notre tour d&#8217;horizon par un rappel sur les concepts liés au transactionnel. Les transactions sont en effet aussi importantes que les mécanismes de persistence décrits plus loin. Sans elles les données échangées avec la base risqueraient d&#8217;être corrompues ou incohérente. C&#8217;est pourquoi il est important de vérifier que le périmètre des transactions soit bien défini lors de l&#8217;interaction de votre code avec la base de données.</p>
<p>L&#8217;objet de ce post n&#8217;est pas de faire un cours magistral sur le transactionnel, mais il me semble intéressant de rappeler quelques concepts de base puisqu&#8217;on parle de base de données et de persistence.</p>
<h3>Retour sur les différentes APIs transactionnelles</h3>
<p>Une transaction est un regroupement d&#8217;instructions SQL effectuant un traitement fonctionnel atomique (par exemple l&#8217;ajout d&#8217;un article dans un panier d&#8217;achat accompagné d&#8217;une décrémentation des stock pour la référence concernée). Ce regroupement est orchestré à l&#8217;aide d&#8217;instructions SQL dédiées comme : BEGIN, COMMIT ou ROLLBACK. Bien sûr, si on ne souhaite pas agir à si bas niveau on aura plutôt recours en Java à des API chargées d&#8217;automatiser la gestion des transactions pour nous. A cette fin, nous disposons de trois possibilités :</p>
<ul>
<li>Les transactions gérées par JDBC</li>
<li>Les transactions de type Resource-local</li>
<li>Les transactions gérées par  JTA</li>
</ul>
<div>JDBC est hors sujet pour cet article, gardons juste à l&#8217;esprit que les appels JDBC sont toujours exécutés par défaut dans une transaction. Vous pouvez décider de gérer vous-même le début et la fin de celle-ci avec setAutocommit(false) dans une java.sql.Connection puis lorsque vous le souhaitez, lancer un commit() ou un rollback() à partir de cette même connexion. La gestion de la transaction reste simpliste et ne permettra pas de l&#8217;utiliser correctement au niveau de l&#8217;ORM,  mais elle est présente.</div>
<div>Les transactions de type Resource-Local sont elles gérées à un niveau supérieur, celui du Persistence Manager. Ce type de transaction rencontré dans Spring est axé sur la base et permet de gérer le cycle de vie de la transaction au niveau de l&#8217;ORM et d&#8217;automatiser facilement certains comportement (Rollback systématique en cas d&#8217;exception par exemple).</div>
<div>Enfin, les transactions JTA sont gérées par le container Java EE et permettent de travailler avec plusieurs datasources facilement. JTA est une spec Java EE, aussi on sera amené à l&#8217;utiliser dès qu&#8217;on voudra effectuer des tâches transactionnelles avec les EJB.</div>
<div>Pour conclure, gardez à l&#8217;esprit que la base de données ouvre et ferme une transaction à chaque opération si aucune démarcation de transaction n&#8217;est spécifiée dans votre code. C&#8217;est ce qui s&#8217;appelle la transaction implicite. Donc quand vous négligez de gérer les transactions, la base s&#8217;en charge à votre place à chaque instruction SQL y compris les lectures. Le mécanisme de la transaction étant assez coûteux, il est donc important d&#8217;opérer cette démarcation de manière explicite ne serait-ce que pour améliorer les performances de vos lectures.</div>
<p><span style="font-size: 20px; font-weight: bold;">Les entité et le Mapping</span></p>
<p>JPA permet donc d&#8217;associer des objets dans notre code à des données dans une ou plusieurs bases. Les metas données du mapping (sous forme d&#8217;annotations) apportent la souplesse indispensable qui évite d&#8217;avoir un modèle de données mémoire totalement calqué que le modèle de donnée relationnel dans la base. On pourra ainsi gérer les colonnes associées à un champ (avec @column), créer une entité sur plusieurs tables (avec @SecondaryTable) ou gérer des champs ne devant pas être stockés (avec @Transient). Bien sûr la magie n&#8217;est pas absolue et il peut arriver un moment où votre structure de base de données est trop complexe pour assurer un mapping satisfaisant et où le choix de JPA peut commencer à être remis en cause. Une notion qu&#8217;il est capitale de comprendre est la persistance transitive : les associations entre entités avec les fameux @OneToOne, @OneToMany ou @ManyToMany. Le débutant en JPA rencontrera très vite ses premiers problèmes avec ces concepts. Soit parce que les associations déclencheront des chargements en cascade et créeront des grappes d&#8217;objets monstrueuses en mémoire, soit parce qu&#8217;il aura eu recours au mécanisme de Lazy loading qui peut devenir un cauchemar si on ne maîtrise pas le cycle de vie des entités et les concepts liés au transactionnel. On se reportera à la documentation des <a href="http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html/entity.html#entity-mapping">annotations JPA </a>d&#8217;Hibernate pour avoir une liste exhaustive des possibilités de mapping disponibles dans JPA 2.</p>
<h2>La Persistence Unit</h2>
<p>C&#8217;est le point de départ du moteur JPA. Elle permet de lister les entités à manager et la façon dont elles sont mappées vers la base. Elle indique également le type de transaction utilisée lors des échanges avec la base. Elle est constituée à partir de trois parties :</p>
<ol>
<li>Les meta données sur les entités (sous forme d&#8217;annotations, elles peuvent être surchargées par du XML)</li>
<li>Le descripteur de la Persistence Unit : le fichier de configuration Peristence.xml qui permet de configurer la connexion à la base et la nature des transactions et des paramètres spécifiques à l&#8217;implémentation de JPA utilisée.</li>
<li>La Persistence Manager Factory : Objet au runtime représentant la configuration complète de la persistence unit. Cette factory permet de créer un ou plusieurs persistence manager fournissant les services nécessaires à la gestions des entités</li>
</ol>
<p>Mais n&#8217;oublions pas la plomberie JDBC sous JPA et la fameuse datasource, point de départ à la connexion vers la base&#8230;</p>
<h3>JDBC et pool de connexion</h3>
<p>JDBC reste donc la brique de base pour interagir avec la base de données et comme a priori votre application effectuera plusieurs requêtes simultanément vers la base vous avez besoin de fournir à JPA un pool de connexions JDBC. Dans un container Java EE tout cela se fait en général en définissant une data source, soit via un fichier (comme dans Glassfish ou JBoss) soit via une interface d&#8217;admin (comme dans Websphere). Cette data source est ensuite appelée via JNDI dans le fichier persistence.xml. La datasource consitue donc un pool de connexions JDBC. son rôle est de pouvoir vous fournir une connexion déjà &#8220;prête à l&#8217;emploi&#8221; (ouverte) quand vous voulez requêter la base et de faire le ménage quand un échange s&#8217;est mal passé (timeout, connexion mal fermée, etc&#8230;). Ce pool est fourni avec votre serveur d&#8217;application. exemple de data source JBoss :</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;datasources&gt;
	&lt;local-tx-datasource&gt;
		&lt;jndi-name&gt;DefaultDS&lt;/jndi-name&gt;
		&lt;connection-url&gt;jdbc:hsqldb:/Data/hypersonic/localDB&lt;/connection-url&gt;
		&lt;driver-class&gt;org.hsqldb.jdbcDriver&lt;/driver-class&gt;
		&lt;user-name&gt;sa&lt;/user-name&gt;
		&lt;password/&gt;
		&lt;min-pool-size&gt;5&lt;/min-pool-size&gt;
		&lt;max-pool-size&gt;20&lt;/max-pool-size&gt;
		&lt;idle-timeout-minutes&gt;0&lt;/idle-timeout-minutes&gt;
	&lt;/local-tx-datasource&gt;
&lt;/datasources&gt;
</pre>
<p>La plupart des containers légers permettent de faire la même chose, quasiment tous fournissent un gestionnaire de Pool JDBC. Pour les utilisateurs de Spring, il y a dans le framework de quoi déclarer un bean Datasource auquel on pourra adjoindre le pool JDBC de son choix. Je vous laisse le soin de lire cette <a href="http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html">doc croustillante</a> qui fourmille de trolls vintage sur Java EE, (heu&#8230; pardon J2EE). Toute pique mise à part, Spring sera très utile pour gérer cet aspect ainsi que les problématiques transactionnelles dans un environnement Java SE, l&#8217;alternative étant de créer ce pool dans votre code. Quoiqu&#8217;il en soit, on se gardera bien de définir sa connexion JDBC dans le fichier persistence.xml car celle-ci ne permet pas (en standard) de choisir la nature du pool utilisé. Ainsi si votre implémentation JPA est hibernate, déclarer votre connexion JDBC dans persistence.xml vous amènera à utiliser le pool de connexion Hibernate par défaut qui n&#8217;est pas recommandé en production. Des propriétés propres à Hibernate permettent dans persistence.xml d&#8217;activer d&#8217;autres gestionnaires de pool fournis par le framework comme C3PO ou Proxool. Ces gestionnaires sont également peu recommandés, on essaiera d&#8217;utiliser en priorité le gestionnaire de pool du serveur d&#8217;application.</p>
<h3>Le fichier persistence.xml</h3>
<p>Là non plus je ne rentrerai pas dans les détails de la configuration du fichier de persistence. Je donnerai juste deux versions de la même unité de persistence. L&#8217;une avec une gestion du transactionnel et de la datasource au niveau container :</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;persistence version=&quot;2.0&quot;
xmlns=&quot;http://java.sun.com/xml/ns/persistence&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd&quot;&gt;
        &lt;persistence-unit name=&quot;myPu&quot;&gt;
		&lt;provider&gt;org.hibernate.ejb.HibernatePersistence&lt;/provider&gt;
		&lt;jta-data-source&gt;java:/DefaultDS&lt;/jta-data-source&gt;
		&lt;properties&gt;
                        &lt;property name=&quot;hibernate.dialect&quot; value=&quot;org.hibernate.dialect.HSQLDialect&quot; /&gt;
		&lt;/properties&gt;
	&lt;/persistence-unit&gt;
&lt;/persistence&gt;
</pre>
<p>La persistence unit définie dans ce fichier exploite la Datasource définie plus haut. Elle utilise Hibernate comme implementation JPA d&#8217;où la propriété hibernate.dialect propre à cette implémentation. La deuxième PU, définie une connexion et un pool JDBC géré en local dans l&#8217;application (en l&#8217;occurence par Hibernate)</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;persistence version=&quot;2.0&quot;
	xmlns=&quot;http://java.sun.com/xml/ns/persistence&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
	xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd&quot;&gt;
	&lt;persistence-unit name=&quot;myPu&quot; transaction-type=&quot;RESOURCE_LOCAL&quot;&gt;
	&lt;provider&gt;org.hibernate.ejb.HibernatePersistence&lt;/provider&gt;
		&lt;properties&gt;
                        &lt;property name=&quot;javax.persistence.jdbc.driver&quot; value=&quot;org.hsqldb.jdbcDriver&quot; /&gt;
                        &lt;property name=&quot;javax.persistence.jdbc.user&quot; value=&quot;se&quot; /&gt;
			&lt;property name=&quot;javax.persistence.jdbc.password&quot; value=&quot;&quot; /&gt;
                        &lt;property name=&quot;javax.persistence.jdbc.url&quot; value=&quot;jdbc:hsqldb:/Data/hypersonic/localDB&quot; /&gt;
			&lt;property name=&quot;hibernate.dialect&quot; value=&quot;org.hibernate.dialect.HSQLDialect&quot; /&gt;
		&lt;/properties&gt;
	&lt;/persistence-unit&gt;
&lt;/persistence&gt;
</pre>
<p>Spring propose une configuration en partie propriétaire dans son fichier de configuration pour la Datasource, puis dans persistence.xml, ce qui n&#8217;est pas toujours très clair. Comme on parle ici de Java EE , on se reportera à <a href="http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html" target="_blank">la documentation du Framework printanier qui fait pousser le XML</a>,  pour plus d&#8217;informations sur ce dernier.</p>
<h3>La gestion des persistence managers</h3>
<p>La aussi il y a plusieurs possibilités pour gérer le cycle de vie des persistence manager JPA :</p>
<ol>
<li>Géré par l&#8217;application dans le code en créant des instances via le Persistence Manager Factory</li>
<li>Géré par un framework du type Spring, Seam  (si on on est sur un serveur léger). Cette solution est techniquement équivalente à la première mais vous décharge d&#8217;avoir à gérer les instanciations</li>
<li>Dans le cas d&#8217;un serveur Java EE, ceux-ci sont gérés par le container ce qui permet par exemple de partager les mêmes persistence units entre plusieurs war au sein d&#8217;un même EAR</li>
</ol>
<div>En fonction de qui gère les persistences manager (le Serveur ou l&#8217;application) on pourra utiliser différents  modes transactionnels comme on l&#8217;a vu ci-dessus.</div>
<div>Techniquement cette gestion revient à savoir qui bootstrap JPA en transformant la persistent unit en persistence manager factory.</div>
<h3>Le persistence manager Factory</h3>
<p>Le chargement de la persistence unit (par le serveur ou l&#8217;application) donne lieu à la création d&#8217;un objet immuable : le persistence manager factory (ou entity manager factory) qu&#8217;on va récupérer automatiquement dans un context Java EE  via :</p>
<pre class="brush: java; gutter: false; title: ; notranslate">
@PersistenceUnit
private EntityManagerFactory pu;
</pre>
<p>si vous devez le faire à la main (sans un container ou framework qui le fait pour vous) cela donnera</p>
<pre class="brush: java; gutter: false; title: ; notranslate">
EntityManagerFactory entityManagerFactory=Persistence.createEntityManagerFactory(&quot;my_pu&quot;);
</pre>
<p>Le code précédent bootstrap JPA et déclenche la lecture du Persistence Context &#8220;my_pu&#8221;. Ce code est comme on s&#8217;en doute extrêmement coûteux, aussi on fera en sorte de ne lancer qu&#8217;au démarrage de l&#8217;application. On travaillera rarement avec l&#8217;EntityManagerFactory et on préferera demander au container directement un EntityManager.</p>
<h2>Au coeur du Persistence manager</h2>
<p>Le persistence manager (ou entity manager, la littérature utilise l&#8217;un ou l&#8217;autre) est l&#8217;API responsable de gérer le cycle de vie des entités JPA. Au delà des échanges explicites avec la base de données,  il est en charge de vérifier l&#8217;état des entités qu&#8217;il manage pour propager les modifications automatiquement vers la base et gérer le cache  de niveau 1 permettant d&#8217;optimiser les accès SQL. Pour l&#8217;obtenir à partir du container on utilisera</p>
<pre class="brush: java; gutter: false; title: ; notranslate">
@PersistenceContext
private EntityManager em;
</pre>
<p>si on veut le faire à la main (après avoir récupéré l&#8217;entityManagerFactory avec le code &#8216;&#8221;à la main&#8221; précédent):</p>
<pre class="brush: java; gutter: false; title: ; notranslate">
EntityManager em=entityManagerFactory.createEntityManager();
</pre>
<p>Dans ce cas gardez à l&#8217;esprit que vous devrez gérer le cycle de vie de l&#8217;entityManager vous-même.</p>
<p>Une fois cela fait, nous parvenons enfin au coeur de JPA avec le Persistence Manager dont les responsabilités sont les suivantes :</p>
<ul style="list-style-type: circle;">
<li><strong>Gérer les instances des entités</strong> : l&#8217;API du Persistence manager permettent de gérer les entités. Cette API dispose des méthodes pour créer, chercher, requêter, mettre à jour et détruire les instances des entités. Ce faisant, il gère les quatre états possibles pour chaque objet entité : transient, persisté, détaché et détruit. (c.f. le schéma sur le cycle de vie ci-dessous)</li>
<li><strong>Maintenir le context de persistance (Pesistence Context en VO)</strong> : Le contexte de persistance correspond à un cache mémoire des objets entité qui ont été chargés via le persistence manager. C&#8217;est le point d&#8217;entrée pour l&#8217;optimisation des performances dans la technologie JPA. vous le connaissez probablement aussi sous le nom de <strong>cache de premier niveau. </strong>Notez aussi que le terme Persistence Context est aussi parfois utilisé à la place de Persistence Manager (ou Entity Manager <img src='http://blog.ippon.fr/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  ) bien que ce ne soit pas exactement la même chose.</li>
<li><strong>Réaliser des contrôles automatiques des objets managés</strong> (dirty checks dans le texte) : l&#8217;état des objets présents dans le contexte de persistance est automatiquement surveillé pendant toute la durée de vie de ce dernier. Quand un événement de &#8220;flush&#8221; intervient sur le persistence manager, les modifications detectées par ce mécanisme sont poussées vers la base de données  sous forme de de commandes SQL Lorsque une instance d&#8217;entité entre dans l&#8217;état &#8220;détaché&#8221; (detached) ses modifications ne sont plus surveillées.</li>
</ul>
<div><img class="alignright" title="cycle_de_vie" src="http://blog.ippon.fr/wp-content/uploads/2011/10/cycle_de_vie.png" alt="" width="313" height="249" />Le persistence manager travaille à plus haut niverau que le SQL. Grace aux annotations de mapping, il comprend que les données transitant depuis la base ont une structure objet (l&#8217;entité) et que cette structure à un cycle de vie (voir ci-contre).</div>
<div>Les instances d&#8217;entité débutent leur vie comme étant non managées (stade transient), puis elles deviennent managées ce qui leur permet d&#8217;être synchronisées avec la base de données. Si elles sont détruites cette synchronisation devient une suppression. Lorsqu&#8217;elles sont supprimées de la base ou que le persistence context est fermé elles passent à l&#8217;état détaché et ne sont plus gérées par le persistence manager.</div>
<div>L&#8217;atout majeur du persistence manager est probablement le persistence context qui donne tout son intérêt à JPA. En effet, il peut optimiser ses échanges avec la base de données en les évitant lorsqu&#8217;il detecte qu&#8217;une instance demandée est déjà dans le persistence context (souvenez-vous, c&#8217;est le cache de niveau 1). Plus intéressant encore: le persistence manager vous garantit l&#8217;unicité de chaque instance d&#8217;entité présente dans le persistence context grâce à son identifiant et son type. Conséquence : l&#8217;entity manager peut surveiller l&#8217;état des instances des entités et peut propager leurs modifications vers la base éventuellement même en cascade pour les entités ou collections associées. En outre, tant que le persistence manager reste ouvert, il est possible d&#8217;effectuer des chargements tardifs (le fameux Lazy Loading) de collections associées sans avoir à requêter le base.</div>
<div>Ces fonctionnalités font tout l&#8217;intérêt du persistence manager et le rendent bien plus riche que la simple couche d&#8217;accès aux données à laquelle on l&#8217;assimile trop souvent.</div>
<div>Cela dit pour pouvoir tirer partie de ces fonctionnalités il est important de savoir (et pouvoir) gérer le scope du persistence context.</div>
<h3>Scoper le persistence context : une approche trop souvent négligée</h3>
<p>Le persistence Manager (et par association le contexte de persistence) est souvent victime d&#8217;une méconnaissance des développeurs qui le pensent lié à la connexion avec la base ou à la durée de vie d&#8217;une transaction.  Cette erreur provient principalement des architectures stateless dont le framework Spring a fait la promotion depuis ses débuts. A cause de cette vision simpliste et restrictive, beaucoup de développeurs considèrent comme une mauvaise pratique (voire ignorent complètement) le fait de laisser ouvert le persistence manager pour une durée supérieure à une transaction ou une requête HTTP et correspondant à un cas d&#8217;utilisation de leur application. En fait le persistence manager est bien plus polyvalent que l&#8217;approche hyper partielle et pauvre prêchée par Spring. Oui, il peut être stateful (le mot est lâché), et donc laissé ouvert le temps de réaliser un cas d&#8217;utilisation complet (plusieurs écrans et actions de l&#8217;utilisateur). Contrairement à ce qu&#8217;on pourrait craindre, le persistence manager ne laissera pas la connexion vers la base ouverte tout le temps de sa durée de vie mais saura se reconnecter de manière transparente si le besoin s&#8217;en fait sentir.</p>
<p>Le mauvais réglage du scoping du Persistence Manager est la cause principale des critiques adressées à JPA. Avoir recours à des outils ou patterns qui ne permettent que de l&#8217;associer à la requête HTTP ou à la transaction en cours amène les développeurs à bricoler des solutions de contournement qui sont autant de mauvaises pratiques : comme le hideux pattern <a href="http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/orm/hibernate3/support/OpenSessionInViewInterceptor.html" target="_blank">Open Session in view</a>, une redéfinition du mapping JPA pour mettre en Fetch.Eager des associations qui auraient du rester lazy ou du requetage HSQL en pagaille pour  récupérer la grappe d&#8217;objets nécessaire pour traiter la requête et ses suites (comme des échanges Ajax par exemple). Comme je l&#8217;ai écrit dans de précédents articles, si Spring a été un apport précieux pour la mise en place de bonnes pratiques en terme d&#8217;architecture, on atteint là ses limites qui sont liées à des choix idéologiques de ses concepteurs qui n&#8217;ont autorisé pendant très longtemps qu&#8217;une approche purement stateless des architectures.</p>
<p>Ce qu&#8217;on doit faire pour que le persistence manager ait une durée de vie supérieure à la requête HTTP, c&#8217;est le gérer en mode stateful. C&#8217;est cette approche qui permettra de gérer un scope conversation comme le fait Seam 2 depuis 2006 et comme le propose CDI en standard dans Java EE 6. Cette approche nécessite de faire attention où le persistence manager est stocké, car il ne doit pas être dans un scope partagé (scope application par exemple) puisqu&#8217;il n&#8217;est pas thread safe. Voyons comment Java EE 6 gère ce mécanisme.</p>
<h2>Le peristence context étendu</h2>
<p>Depuis Java EE 5,  nous avons la possibilité de créer un persistence context étendu. Comme dit, plus haut, c&#8217;est un persistence context qui reste actif au dela de la transaction (mode par défaut du persistence context).</p>
<p>Avoir recours à un Persitence context étendu :</p>
<ul>
<li>Permet de gérer proprement le lazy loading des entités ou collections associées</li>
<li>Evite d&#8217;avoir à merger des entités détachées pour les synchroniser avec la base</li>
<li>Vous assure de n&#8217;avoir qu&#8217;une seule référence à un objet pour un id d&#8217;entité donné</li>
<li>Fonctionne avec les mécanisme d&#8217;Optimistic Locking pour supporter les unités de traitement à durée de vie longue (l&#8217;annotation JPA @Version est très utile pour ce dernier point)</li>
</ul>
<p>Le persistence context étendu doit donc résider dans un scope stateful, et non partagé. La session ou la conversation pourraient faire l&#8217;affaire, mais la gestion de son cylce de vie resterait un peu fastidieuse. C&#8217;est pourquoi, la meilleure place pour le gérer est de le placer au sein d&#8217;un EJB Session Sateful (Stateful Session Bean ou SFSB).</p>
<p>On ne va pas trop entrer dans les détails des EJB ici (je garde cela pour mon prochain post), il faut juste savoir qu&#8217;un SFSB est géré par un container spécifique qui n&#8217;a rien à voir au conteneur servlet. Notre Bean a donc un cycle de vie indépendant des scopes servlet mais pourra être manipulé depuis ces fameux scopes soit en étant injecté via @EJB, soit, encore mieux en étant injecté ou directement utilisé via CDI. Le persistence context étendu ainsi utilisé ne sera fermé que lorsque le SFSB sera recyclé.  Nous reviendrons sur tout ça dans un post ultérieur. Pour le moment voici un petit exemple que j&#8217;ai emprunté à <a href="http://www.adam-bien.com/roller/abien/entry/building_perfect_anti_facades_almost" target="_blank">Adam Bien </a>.</p>
<pre class="brush: java; highlight: [1,2,3,4,7,31]; title: ; notranslate">
@Stateful
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
@Named
@ConversationScoped
public class OrderGateway{

  @PersistenceContext(type=PersistenceContextType.EXTENDED)
  EntityManager em;

  private Load current;

  public Load find(long id){
    current = em.find(Load.class, id);
    return current;
  }

  public Load getCurrent() {
    return current;
  }

  public void create(Load load){
    em.persist(load);
    current = load;
  }

  public void remove(long id){
    Load ref = em.getReference(Load.class, id);
    em.remove(ref);
  }

  @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
  public void save(){
    //nothing to do
  }
}
</pre>
<p>La ligne 1 fait de notre classe un SFSB (EJB Stateful), la deuxième ligne désactive le support transactionnel sur l&#8217;EJB en question, la ligne 3 fait que la version CDI de cet EJB pourra être utilisé dans une page JSF via l&#8217;expression language. Et la quatrième stock le composant CDI dans le scope conversation.</p>
<p>On voit que dans le SFSB on inject un entity manger étendu en ligne 7. Diverses méthodes permettent de chercher, créer et supprimer des entités et en ligne 31 on annote une methode save() avec l&#8217;attribut REQUIRES_NEW qui va créer une transaction et la fermer dans la foulée commitant ainsi toutes les modifications effectuées (rappelez-vous l&#8217;entity manager empile les  modification jusqu&#8217;à ce qu&#8217;une transaction lui permette de pousser ces modifications). Ce scénario simplifié permet d&#8217;imaginer les possibilités offertes par l&#8217;extended persistence context.</p>
<h2>Conclusion</h2>
<p>L&#8217;empilement de technologies masquées par JPA  constitue à la fois l&#8217;origine de son succès et la principale raison des critiques que la spécification essuie. Les cas d&#8217;utilisations restreints mis en avant par Spring en ne permettant que de concevoir des architecture stateless pour les services, sont également à l&#8217;origine de pas mal de galères sur JPA. Pour utiliser cette technologie au mieux je ne vous donnerai que 3 conseils :</p>
<ul>
<li>Apprenez Java EE 6, ça ouvre des horizons.</li>
<li>Si vous ne pouvez pas travailler avec Java EE, utilisez Seam 2 qui marche très bien sur des conteneurs léger type Tomcat et qui reprend ces concepts.</li>
<li>Lisez la doc de JPA (vous pouvez commencer par <a href="http://docs.jboss.org/hibernate/entitymanager/3.5/reference/en/html/" target="_blank">ici</a>) et non pas la version Springifiée de celle-ci.</li>
</ul>
<h3><em>Bibliographie </em></h3>
<p><em>Cet Article s&#8217;appuie sur les livres suvants</em></p>
<ul>
<li><em><a href="http://www.manning.com/dallen/" target="_blank">Seam In Action</a> écrit par Dan Allen</em></li>
<li><em><a href="http://www.manning.com/bauer2/" target="_blank">Java Persistence with Hibernate</a> par Christian Bauer et Gavin King</em></li>
<li><em><a href="http://press.adam-bien.com/" target="_blank">Real World Java EE Patterns, Rethinking the best practices</a>  et  <a href="http://press.adam-bien.com/" target="_blank">Real World Java EE Night Hacks</a> par Adam Bien</em></li>
</ul>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/uSd_cZ38viw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/10/11/jpa-une-magie-qui-se-merite-retour-aux-sources-de-jpa/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/10/11/jpa-une-magie-qui-se-merite-retour-aux-sources-de-jpa/</feedburner:origLink></item>
		<item>
		<title>JSF dans le Cloud en 30 minutes</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/T1CIv0_EEvk/</link>
		<comments>http://blog.ippon.fr/2011/10/10/jsf-dans-le-cloud-en-30-minutes/#comments</comments>
		<pubDate>Mon, 10 Oct 2011 09:43:59 +0000</pubDate>
		<dc:creator>Julien DUBOIS</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[CloudBees]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JSF]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[SpringFuse]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4222</guid>
		<description><![CDATA[<p>Cet article vous propose, en environ 30 minutes, de réaliser et déployer dans le cloud une application JSF2/Spring Webflow/Spring/JPA.</p> Présentation de l’application <p>Nous allons utiliser un générateur de code (www.springfuse.com) pour réaliser notre application depuis un schéma de base de données.</p> <p>Vous pouvez bien entendu utiliser votre propre schéma de base de données, mais pour <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/10/10/jsf-dans-le-cloud-en-30-minutes/">JSF dans le Cloud en 30 minutes</a></span>]]></description>
			<content:encoded><![CDATA[<p>Cet article vous propose, en environ 30 minutes, de réaliser et déployer dans le cloud une application JSF2/Spring Webflow/Spring/JPA.</p>
<h2>Présentation de l’application</h2>
<p>Nous allons utiliser un générateur de code (<a href="http://www.springfuse.com" target="_blank">www.springfuse.com</a>) pour réaliser notre application depuis un schéma de base de données.</p>
<p>Vous pouvez bien entendu utiliser votre propre schéma de base de données, mais pour l’exemple nous nous baserons sur le schéma de l’application Tudu Lists, qui est l’application d’exemple du livre “Spring par la pratique”.</p>
<p>L’application générée va utiliser les dernière technologies disponibles actuellement:</p>
<ul>
<li>JSF 2 avec PrimeFaces, qui est aujourd’hui le meilleur jeu de composants JSF à notre avis</li>
<li>Spring Web Flow pour gérer la navigation entre les pages</li>
<li>Spring Security pour gérer la sécurité</li>
<li>Spring pour gérer la configuration de l’application, les transactions, la couche métier&#8230;</li>
<li>JPA avec Hibernate pour gérer la couche de persistence</li>
</ul>
<p>Cette application sera déployée dans le “Cloud”, en occurrence sur la plateforme <a href="http://www.cloudbees.com" target="_blank">CloudBees</a>. L’application fonctionnant sur un socle Tomcat “standard”, elle pourrait être déployée sur d’autres Clouds sans modification, par exemple sur <a href="http://www.jelastic.com/" target="_blank">Jelastic</a>. Etre indépendant du vendeur de Cloud est particulièrement important pour la pérennité de votre application, ainsi que pour la bonne maîtrise de son coût.</p>
<h2>Création de l’application dans CloudBees</h2>
<p>Inscrivez-vous sur CloudBees à cette adresse: <a href="https://grandcentral.cloudbees.com/account/signup" target="_blank">https://grandcentral.cloudbees.com/account/signup</a></p>
<p>L’inscription est gratuite, et vous n’aurez pas à donner de numéro de carte bleue (comme c’est le cas sur d’autres plateformes, par exemple <a href="http://www.heroku.com/" target="_blank">Heroku</a>).</p>
<ol>
<li>Loggez-vous sur <a href="https://grandcentral.cloudbees.com/" target="_blank">https://grandcentral.cloudbees.com/</a></li>
<li>Ajoutez les services “Applications” et “Database”. (<em>Optionnel</em>: ajoutez également le service “New Relic”, qui vous permettra de monitorer votre application)</li>
<li>Créez une nouvelle application (dans cet exemple nommée “prime”)</li>
<li>Créez une nouvelle base de données (ici aussi dénommée “prime”)</li>
</ol>
<h2>Création de la base de données</h2>
<p>Utilisez votre outil préféré de connexion à MySQL (dans notre cas MySQL Workbench, disponible gratuitement ici: <a href="http://www.mysql.fr/downloads/workbench/" target="_blank">http://www.mysql.fr/downloads/workbench/</a> ) et connectez-vous à la base que vous venez de créer (tous les paramètres sont disponibles via votre compte CloudBees):</p>
<p><img class="aligncenter" src="http://blog.ippon.fr/wp-content/uploads/2011/10/database.png" alt="" width="654" height="625" /></p>
<p>Une fois connecté, exécutez le script SQL de génération de votre base de données. Vous pouvez utiliser votre propre script, dans notre cas nous prendrons la dernière version du script de création de la base Tudu Lists:</p>
<p><a href="https://github.com/jdubois/Tudu-Lists/blob/master/src/main/sql/create_schema_mysql.sql" target="_blank">https://github.com/jdubois/Tudu-Lists/blob/master/src/main/sql/create_schema_mysql.sql</a></p>
<p>(pour avoir le fichier directement, cliquez sur “raw” en haut à droite du fichier).</p>
<p>Exécutez ce script: votre base de données est prête!</p>
<h2>Génération de l’application</h2>
<p>Connectez vous sur <a href="http://www.springfuse.com/" target="_blank">http://www.springfuse.com/</a></p>
<p>Afin de générer votre application:</p>
<ul>
<li>Dans la partie “Database”, choisissez “Reverse your own database” et renseignez les paramètres de la base MySQL que vous venez de créer.</li>
<li>Laissez les autres paramètres par défaut, en particulier celui vous proposant le type d’application à générer</li>
</ul>
<p>Le site va ensuite vous proposer d’exécuter un commande Maven de ce type:</p>
<pre>mvn -U archetype:generate -DarchetypeGroupId=com.springfuse.archetypes -DarchetypeArtifactId=quickstart -DarchetypeVersion=3.0.60 -DgroupId=fr.ippon.demo.prime -Dpackage=fr.ippon.demo.prime -DartifactId=prime -Dversion=1.0.0 -DfrontEnd=jsf2Primefaces -Demail= -DjdbcGroupId=mysql -DjdbcArtifactId=mysql-connector-java -DjdbcVersion=5.1.17 -DjdbcDriver=com.mysql.jdbc.Driver -DjdbcUser=jdubois-prime -DjdbcPassword=##### -DjdbcUrl=jdbc:mysql://ec2-174-129-9-255.compute-1.amazonaws.com/prime -DinteractiveMode=false -DarchetypeRepository=http://maven2.springfuse.com/
 cd prime</pre>
<p>Une fois ces commandes exécutées, vous avez créé votre application. Il vous reste ensuite à faire la génération de votre code à partir de la base de données:</p>
<pre>mvn -f springfuse.xml generate-sources</pre>
<p>Félicitations, votre application est générée! Vous pouvez d’ailleurs la tester en local en tapant:</p>
<pre>mvn jetty:run</pre>
<h2>Déploiement dans le Cloud</h2>
<p>Dans le pom.xml de votre application, nous allons rajouter le plugin CloudBees.</p>
<p>Dans la section nommée “RESPOSITORIES”, ajoutez un nouveau plugin juste après celui nommé “Codehaus Snapshots” (ligne 774):</p>
<pre> &lt;pluginRepository&gt;
     &lt;id&gt;bees-plugins-snapshots&lt;/id&gt;
     &lt;url&gt;http://repository-cloudbees.forge.cloudbees.com/public-snapshot/&lt;/url&gt;
     &lt;releases&gt;
         &lt;enabled&gt;false&lt;/enabled&gt;
     &lt;/releases&gt;
     &lt;snapshots&gt;
         &lt;enabled&gt;true&lt;/enabled&gt;
     &lt;/snapshots&gt;
 &lt;/pluginRepository&gt;</pre>
<p>Puis ajoutez le plugin Cloudbees dans les plugins de “build”, tout à la fin du pom.xml (ligne 957):</p>
<pre> &lt;plugin&gt;
     &lt;groupId&gt;com.cloudbees&lt;/groupId&gt;
     &lt;artifactId&gt;bees-maven-plugin&lt;/artifactId&gt;
 &lt;/plugin&gt;</pre>
<p>Ensuite allez recherchez vos clefs d’accès à CloudBees à cette URL:<br />
<a href="https://grandcentral.cloudbees.com/user/keys" target="_blank"> https://grandcentral.cloudbees.com/user/keys</a></p>
<p>Vous pouvez maintenant déployer votre application avec la commande suivante:</p>
<pre>mvn bees:deploy -Dbees.appid=jdubois/prime -Dbees.apikey=##### -Dbees.secret=#####</pre>
<p>(en mettant le bon id pour votre application, de type votrecompte/votreapplication et en remplaçant les ##### par vos clefs CloudBees).</p>
<p style="text-align: center;"><img src="http://blog.ippon.fr/wp-content/uploads/2011/10/deploy-e1318239385250.png" alt="" width="672" height="433" /></p>
<p>Votre application est maintenant lancée, vous pouvez y accéder via l’URL (en mettant l’ID de votre application et votre id utilisateur):</p>
<pre>http://votreappli.votreid.cloudbees.net/app/home</pre>
<p>(Par exemple pour voir ma version : <a href="http://prime.jdubois.cloudbees.net/app/home" target="_blank">http://prime.jdubois.cloudbees.net/app/home</a>)</p>
<p>Pour vous connecter, utilisez le login “admin” et le mot de passe “password”: SpringFuse s’est connecté à votre base de données et sécurise l’application avec les valeurs de la table “TUSER”, c&#8217;est pourquoi il ne faut pas prendre les valeurs par défaut.</p>
<h2>Pour finir</h2>
<p>L’application générée doit bien entendu être customisée avant d’être réellement utilisable, mais nous pouvons déjà voir que:</p>
<ul>
<li>L’application est performante et plutôt peu coûteuse en mémoire (environ 50 mo de RAM utilisée)</li>
<li>L’interface graphique proposée par PrimeFaces, basée sur JQuery, est particulièrement agréable</li>
<li>Spring Web Flow vous propose un système de navigation particulièrement efficace: gestion du bouton “back”, des onglets du navigateur, etc&#8230;</li>
<li>Le fait d’être basé sur une stack standard et ouverte vous permet de migrer sans problème d’un fournisseur de “Cloud” à un autre</li>
</ul>
<div>Maintenant que votre application fonctionne, n&#8217;hésitez pas à la modifier et à redéployer: CloudBees n&#8217;upload qu&#8217;un &#8220;diff&#8221; de vos changements, ce qui faut que déployer une nouvelle version est particulièrement rapide. De plus, en cas de problème, vous pouvez revenir sur une ancienne version en un clic via l&#8217;interface graphique.</div>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/T1CIv0_EEvk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/10/10/jsf-dans-le-cloud-en-30-minutes/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/10/10/jsf-dans-le-cloud-en-30-minutes/</feedburner:origLink></item>
		<item>
		<title>Ippevent CloudBees : la vidéo</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/BCUQ2Bd4dWo/</link>
		<comments>http://blog.ippon.fr/2011/10/07/ippevent-cloudbees-la-video/#comments</comments>
		<pubDate>Fri, 07 Oct 2011 15:41:14 +0000</pubDate>
		<dc:creator>Antoine SABOT-DURAND</dc:creator>
				<category><![CDATA[Ippevents]]></category>
		<category><![CDATA[Vidéo]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[CloudBees]]></category>
		<category><![CDATA[Forge]]></category>
		<category><![CDATA[Hudson]]></category>
		<category><![CDATA[Jenkins]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[Sonar]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4170</guid>
		<description><![CDATA[<p>Le 22 septembre dernier, Nicolas Deloof venait nous parler intégration continue et CloudBees. Cet Ippevent marque deux records en terme de participation et de durée. Comme (presque) à chaque fois l&#8217;événement a été filmé. Retrouvez la vidéo ci-dessous.</p> <p></p> ]]></description>
			<content:encoded><![CDATA[<p>Le 22 septembre dernier, Nicolas Deloof venait nous parler intégration continue et CloudBees. Cet Ippevent marque deux records en terme de participation et de durée. Comme (presque) à chaque fois l&#8217;événement a été filmé. Retrouvez la vidéo ci-dessous.</p>
<p><iframe src="http://player.vimeo.com/video/30143897?title=0&#038;byline=0&#038;portrait=0" width="750" height="563" frameborder="0" webkitAllowFullScreen allowFullScreen></iframe></p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/BCUQ2Bd4dWo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/10/07/ippevent-cloudbees-la-video/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/10/07/ippevent-cloudbees-la-video/</feedburner:origLink></item>
		<item>
		<title>Nous sommes tous, experts JavaEE, des enfants de Steve Jobs ;-&gt;</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/qO-Wb1fLQCA/</link>
		<comments>http://blog.ippon.fr/2011/10/06/nous-sommes-tous-experts-javaee-des-enfants-de-steve-jobs/#comments</comments>
		<pubDate>Thu, 06 Oct 2011 16:41:40 +0000</pubDate>
		<dc:creator>Geoffray GRUEL</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Apple]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4156</guid>
		<description><![CDATA[<p>Après les hommages officiels je tiens à faire un clin d’œil au pionnier des serveurs d&#8217;applications : Steve Jobs</p> <p>Ci-dessous une keynote de 1996 de présentation de WebObjects</p> <p></p> <p>Sans Steve et Next (il s&#8217;était fait viré d&#8217;Apple à l&#8217;époque) pas de révolution du web serverside :</p> Séparation des couches Modèle objet Load-balancing <p>Les Weblogic, <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/10/06/nous-sommes-tous-experts-javaee-des-enfants-de-steve-jobs/">Nous sommes tous, experts JavaEE, des enfants de Steve Jobs ;-></a></span>]]></description>
			<content:encoded><![CDATA[<p>Après les hommages officiels je tiens à faire un clin d’œil au pionnier des serveurs d&#8217;applications : Steve Jobs</p>
<p>Ci-dessous une keynote de 1996 de présentation de <a title="Wikipédi WebObjects" href="http://fr.wikipedia.org/wiki/WebObjects" target="_blank">WebObjects</a></p>
<p><iframe frameborder="0" height="315" src="http://www.youtube.com/embed/TaX25rxOY8Q?rel=0" width="420"></iframe></p>
<p>Sans Steve et <a title="NeXT" href="http://fr.wikipedia.org/wiki/NeXT" target="_blank">Next</a> (il s&#8217;était fait viré d&#8217;Apple à l&#8217;époque) pas de révolution du web serverside :</p>
<ul>
<li>Séparation des couches</li>
<li>Modèle objet</li>
<li>Load-balancing</li>
</ul>
<p>Les Weblogic, Websphere et Jboss n&#8217;existaient pas à l&#8217;époque et sont arrivés au niveau de WebObjects que 10 ans plus tard.</p>
<p>L&#8217;IDE de WebObjects était ENORME avec dés 1998 du développement web WYSIWYG par exemple.</p>
<p>Par contre WebObjects n&#8217;a pas été un succès commercial tout comme les excellents serveurs Next : pas de stratégie commerciale d&#8217;entreprise, des pricing super élevés, une ouverture tardive vers Java.</p>
<p>Bref nous sommes tous, experts JavaEE des enfants de WebObjects et donc des enfants de Steve,</p>
<p>Merci Steve,</p>
<p>Geoffray</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/qO-Wb1fLQCA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/10/06/nous-sommes-tous-experts-javaee-des-enfants-de-steve-jobs/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/10/06/nous-sommes-tous-experts-javaee-des-enfants-de-steve-jobs/</feedburner:origLink></item>
		<item>
		<title>Atelier Git le 20 Octobre avec Sébastien Douche : inscriptions ouvertes</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/QfRtgTOGYJE/</link>
		<comments>http://blog.ippon.fr/2011/10/06/atelier-git-le-20-octobre-avec-sebastien-douche-inscriptions-ouvertes/#comments</comments>
		<pubDate>Thu, 06 Oct 2011 08:03:24 +0000</pubDate>
		<dc:creator>Antoine SABOT-DURAND</dc:creator>
				<category><![CDATA[Ippevents]]></category>
		<category><![CDATA[GIT]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4134</guid>
		<description><![CDATA[<p>Les Ippevents se suivent et ne se ressemblent pas. Le prochain d&#8217;entre eux ne sera pas une conférence à proprement parler mais un atelier sur Git. Celui-ci sera animé par Sébastien Douche (@sdouche sur Twitter) bien connu des membres de la communauté pour ses nombreuses interventions sur Python, Git et l&#8217;agilité (notamment l&#8217;approche devops). Il est <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/10/06/atelier-git-le-20-octobre-avec-sebastien-douche-inscriptions-ouvertes/">Atelier Git le 20 Octobre avec Sébastien Douche : inscriptions ouvertes</a></span>]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" src="http://www.brownwebdesign.com/blog/wp-content/uploads/2011/06/git-logo.png" alt="" width="188" height="97" />Les Ippevents se suivent et ne se ressemblent pas. Le prochain d&#8217;entre eux ne sera pas une conférence à proprement parler mais un atelier sur Git. Celui-ci sera animé par <a href="http://fr.linkedin.com/in/sebastiendouche" target="_blank">Sébastien Douche</a> (<a href="http://twitter.com/#!/sdouche" target="_blank">@sdouche</a> sur Twitter) bien connu des membres de la communauté pour ses nombreuses interventions sur Python, Git et l&#8217;agilité (notamment l&#8217;approche devops). Il est également le créateur de l&#8217;excellent site <a href="http://gitfr.net/" target="_blank">GitFr</a>.</p>
<p><span id="more-4134"></span></p>
<p>Nous organisons donc avec Sébastien cet atelier de 3h gratuit et ouvert à toutes les personnes ayant déjà une expérience sous Git (les débutants risquent d&#8217;être un peu perdus).</p>
<p>Il aura lieu le <strong>20 octobre prochain</strong> dans les locaux d&#8217;Ippon à Levallois<strong> de 18h30 à 21h30</strong>. Tous les détails sut notre <a title="Inscription aux Ippevents" href="http://blog.ippon.fr/inscription-aux-ippevents/">page Ippevents</a>.</p>
<p><strong>ATTENTION</strong> : cet Ippevent est limité à 20 places donc dépêchez vous. Si vous avez un empêchement, merci de le signaler le plus tôt possible pour libérer votre place pour quelqu&#8217;un d&#8217;autre</p>
<p><strong>Pré-requis</strong>  : Les participants devront <strong>impérativement apporter leur portable</strong> pour l&#8217;Atelier. Au cas où git ne serait pas installé dessus voici les infos pour le faire :</p>
<ul>
<li><a href="http://gitfr.net/blog/2010/10/30/installer-git-sur-ubuntu/">http://gitfr.net/blog/2010/10/30/installer-git-sur-ubuntu/</a></li>
<li><a href="http://gitfr.net/blog/2010/11/01/installer-git-sur-windows/">http://gitfr.net/blog/2010/11/01/installer-git-sur-windows/</a></li>
<li><a href="http://gitfr.net/blog/2010/11/01/installer-git-sur-os-x/">http://gitfr.net/blog/2010/11/01/installer-git-sur-os-x/</a></li>
</ul>
<p>Vous pouvez également peaufiner avec les articles suivants :</p>
<ul>
<li><a href="http://gitfr.net/blog/2010/11/04/configuration-minimale-pour-demarrer/">http://gitfr.net/blog/2010/11/04/configuration-minimale-pour-demarrer/</a></li>
<li><a href="http://gitfr.net/blog/2010/11/04/taper-plus-vite-avec-la-completion/">http://gitfr.net/blog/2010/11/04/taper-plus-vite-avec-la-completion/</a></li>
<li><a href="http://gitfr.net/blog/2010/11/06/ameliorer-sa-productivite-avec-un-beau-shell/">http://gitfr.net/blog/2010/11/06/ameliorer-sa-productivite-avec-un-beau-shell/</a></li>
</ul>
<p>Enfin, Sébastien me souffle dans l&#8217;oreillette qu&#8217;il serait fortement souhaitable que les participants visionnent ou re-visionnent ses présentations fait au Paris Jug sur le site Parleys :<br />
<object width="700" height="400" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="wmode" value="direct" /><param name="flashVars" value="sv=true&amp;pageId=2366" /><param name="src" value="http://www.parleys.com/dist/share/parleysshare.swf" /><param name="flashvars" value="sv=true&amp;pageId=2366" /><param name="allowfullscreen" value="true" /><embed width="700" height="400" type="application/x-shockwave-flash" src="http://www.parleys.com/dist/share/parleysshare.swf" allowFullScreen="true" wmode="direct" flashVars="sv=true&amp;pageId=2366" flashvars="sv=true&amp;pageId=2366" allowfullscreen="true" /></object></p>
<p>et</p>
<p><object width="700" height="400" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="wmode" value="direct" /><param name="flashVars" value="sv=true&amp;pageId=2368" /><param name="src" value="http://www.parleys.com/dist/share/parleysshare.swf" /><param name="flashvars" value="sv=true&amp;pageId=2368" /><param name="allowfullscreen" value="true" /><embed width="700" height="400" type="application/x-shockwave-flash" src="http://www.parleys.com/dist/share/parleysshare.swf" allowFullScreen="true" wmode="direct" flashVars="sv=true&amp;pageId=2368" flashvars="sv=true&amp;pageId=2368" allowfullscreen="true" /></object><br />
Pour s&#8217;inscrire il suffit de remplir le formulaire ci-dessous. Tous les détails sont sur notre <a title="Inscription aux Ippevents" href="http://blog.ippon.fr/inscription-aux-ippevents/" target="_blank">Page Ippevent</a>.</p>

		<div id="usermessage8a" class="cf_info "></div><strong>Les inscriptions sont désormais closes.</strong>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/QfRtgTOGYJE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/10/06/atelier-git-le-20-octobre-avec-sebastien-douche-inscriptions-ouvertes/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/10/06/atelier-git-le-20-octobre-avec-sebastien-douche-inscriptions-ouvertes/</feedburner:origLink></item>
		<item>
		<title>Eclipse : améliorer sa productivité grâce aux raccourcis clavier</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/ZFaVoQ6Xyvs/</link>
		<comments>http://blog.ippon.fr/2011/10/03/eclipse-ameliorer-sa-productivite-grace-aux-raccourcis-clavier/#comments</comments>
		<pubDate>Mon, 03 Oct 2011 20:14:00 +0000</pubDate>
		<dc:creator>Pierre TEMPLIER</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Eclipse]]></category>
		<category><![CDATA[IDE]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4089</guid>
		<description><![CDATA[<p>L&#8217;utilisation du clavier plutôt que de la souris permet d&#8217;être plus efficace en utilisant son IDE. Eclipse regorge de raccourcis clavier qui peuvent nous simplifier la vie. Il n&#8217;est pas question de tous les connaître par coeur. Il n&#8217;est pas rare d&#8217;en découvrir en allant fouiller les menus d&#8217;eclipse.</p> <p>J&#8217;ai choisi de vous en présenter <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/10/03/eclipse-ameliorer-sa-productivite-grace-aux-raccourcis-clavier/">Eclipse : améliorer sa productivité grâce aux raccourcis clavier</a></span>]]></description>
			<content:encoded><![CDATA[<p>L&#8217;utilisation du clavier plutôt que de la souris permet d&#8217;être plus efficace en utilisant son IDE.<br />
Eclipse regorge de raccourcis clavier qui peuvent nous simplifier la vie.<br />
Il n&#8217;est pas question de tous les connaître par coeur. Il n&#8217;est pas rare d&#8217;en découvrir en allant fouiller les menus d&#8217;eclipse.</p>
<p>J&#8217;ai choisi de vous en présenter quelques uns qui me paraissent très utiles au quotidien.</p>
<h2>CTRL+SHIFT+F</h2>
<p>Effectue un formatage selon les règles configurable dans les préférences &#8220;Java&gt;Code Style&gt;Formatter&#8221;</p>
<pre class="brush: java; title: ; notranslate">
public class HelloWorld {
public static void main(String[] args)
{
String name=args[0];System.out.println(&quot;Hello&quot;
+name);
}
}
</pre>
<p>sera modifié de la façon suivante</p>
<pre class="brush: java; title: ; notranslate">
public class HelloWorld {
        public static void main(String[] args) {
                String name = args[0];
                System.out.println(&quot;Hello&quot; + name);
        }
}
</pre>
<p>on peut notamment régler :<br />
* le nombre de lignes vides consécutives<br />
* le nombre maximum de caractères par ligne (la valeur par défault de 80 n&#8217;est plus très adaptée à nos écrans)<br />
* Où et combien insérer d&#8217;espaces dans le code.</p>
<p>On peut aussi utiliser &#8216;//&#8217; pour forcer le passage à la ligne même en cas de formatage automatique.<br />
Par exemple on est sûr que le code suivant restera présenté toujours sûr le même nombre de lignes.</p>
<pre class="brush: java; title: ; notranslate">
User user = new User.Builder() //
                .withFirstName(&quot;Unknown&quot;) //
                .withLastName(&quot;Guy&quot;) //
                .withAdress(&quot;12 road of nowhere&quot;) //
                .withZipCode(01010) //
                .withCity(&quot;NowhereLand&quot;) //
                .withInterests(&quot;tennis&quot;, &quot;music&quot;, &quot;hiking&quot;, &quot;java&quot;) //
                .withRoles(Role.USER) //
                .build();
</pre>
<h2>CTRL+I (Indent)</h2>
<p>C&#8217;est le petit frère du raccourci précédent mais il se limite à l&#8217;indentation du code sélectionné.<br />
On se limite aux règles d&#8217;indentation définies dans le premier onglet des règles de formatage.</p>
<pre class="brush: java; title: ; notranslate">
public class HelloWorld {
        public static void main(String[] args)
        {
                String name=args[0];System.out.println(&quot;Hello&quot;
                                +name);
        }
}
</pre>
<h2>CTRL+SHIFT+O (Organize Imports)</h2>
<p>Permet de supprimer les imports inutilisés et d&#8217;ajouter ceux manquant en proposant un choix lorsque nécessaire. Très pratique aussi quand on récupère un bout de code sans les imports pour les retrouver de manière automagique.</p>
<p>on peut régler dans les options (Java &gt; Code Style &gt; Organize Imports)<br />
* l&#8217;ordre d&#8217;import des packages (java, javax, org, com)<br />
* le nombre d&#8217;imports sur un package à partir duquel on va importer mypackage.*<br />
* le nombre d&#8217;imports static sur une classe à partir duquel on va importer MyClass.*</p>
<h2>CTRL+O (Quick Outline)</h2>
<p>Affiche la structure de la classe dans une popup, on peut également filtre l&#8217;affichage en tapant par exemple le début de la fonction que l&#8217;on veut retrouver. on peut également filtrer avec des wildcards &#8216;?&#8217; ou &#8216;*&#8217;. Si on appuie une deuxième fois sur CTRL+O on peut également visualiser les membre hérités (aussi bien privés que publics).</p>
<p><img title="Quick outline" src="http://blog.ippon.fr/wp-content/uploads/2011/10/quick_outline.png" alt="Quick outline" /> <img title="Quick outline inherited" src="http://blog.ippon.fr/wp-content/uploads/2011/10/quick_outline_inherited.png" alt="Quick outline inherited" /></p>
<h2>ALT+SHIFT+L (Extract Local Variable)</h2>
<p>Imaginons que l&#8217;on ait une fonction qui retourne un objet. Eclipse nous proposera d&#8217;affecter cet objet à une variable dont on va saisir le nom. le nom proposé par défaut étant la plupart du temps tout à fait satisfaisant.</p>
<pre class="brush: java; title: ; notranslate">
treeGrid.getData();
</pre>
<p>devient</p>
<pre class="brush: java; title: ; notranslate">
Tree data = treeGrid.getData();
</pre>
<h2>ALT+SHIFT+M (Extract Method)</h2>
<p>On sélectionne un bout de code et la fenêtre d&#8217;extraction de méthode apparait.</p>
<h2>CTRL+SHIFT+T / CTRL+SHIT+R (Open Type/Resource)</h2>
<p>Ces deux raccourcis jumeaux permettent de facilement ouvrir le code d&#8217;un Type (Classe, Interface ou Enum) ou d&#8217;une Ressource (xml, png, properties&#8230;).<br />
On peut utiliser des wildcards pour effectuer sa recherche, notamment lorsqu&#8217;on ne se rappelle que d&#8217;une partie du nom recherché.<br />
On peut également utiliser la recherche CamelCase comme expliqué dans <a href="http://blog.ippon.fr/2010/10/11/recherche-camelcase-dans-eclipse/">ce post</a>.</p>
<h2>ALT+HAUT / ALT+BAS</h2>
<p>Déplacer des lignes de code (en respectant l&#8217;indentation), toujours beaucoup plus rapide que le couper/coller</p>
<h2>CTRL+K / CTRL+SHIFT+K</h2>
<p>Rechercher dans le fichier courant la prochaine occurence du mot sélectionné.<br />
Plus rapide que le traditionnel CTRL+F qui ouvre une popup de recherche.<br />
Il reprend néanmoins les options sélectionnées dans cette popup (Wrap search, Case sensitive et Whole word)<br />
Le premier raccourci effectue la recherche vers le bas. le second raccourci celle vers le haut.</p>
<h2>CTRL+D (Delete line)</h2>
<p>Supprimer la ligne courante, souvent plus rapide que l&#8217;utilisation d&#8217;une sélection à la souris suivie de <em>Suppr</em> ou <em>Backspace</em></p>
<h2>CTRL+L (Goto Line)</h2>
<p>Super utile pour aller chercher la ligne indiquée dans une stacktrace.<br />
<img title="go to line" src="http://blog.ippon.fr/wp-content/uploads/2011/10/goto_line.png" alt="go to line" /></p>
<h2>CTRL+1 (Quick Fix)</h2>
<p>En fonction du code sélectionné et/ou de l&#8217;endroit où l&#8217;on se trouve on aura un menu avec une liste d&#8217;actions possibles.</p>
<p>quelques exemples :<br />
* sur une ligne où on a une erreur, une liste de suggestions de corrections est proposée<br />
* sur un paramètre de méthode ou de constructeur, on peut alors l&#8217;affecter à un nouvel attribut de la classe.<br />
* sur une variable on pourra la renommer.<br />
C&#8217;est un peu le raccourci à tout faire.<br />
<img title="quick fix step 1" src="http://blog.ippon.fr/wp-content/uploads/2011/10/quickfix_assign_to_new_field.png" alt="quick fix step 1" /><br />
<img title="quick fix step 2" src="http://blog.ippon.fr/wp-content/uploads/2011/10/quickfix_assign_to_new_field_done.png" alt="quick fix step 2" /></p>
<h2>CTRL+/ (Comment)</h2>
<p>Commente ou décommente les lignes sélectionnées en les préfixant par &#8216;//&#8217;.</p>
<h2>CTRL+3 (Quick Access)</h2>
<p>Permet d&#8217;accéder rapidement aux éléments de l&#8217;interface graphique.<br />
Par exemple, vous ne vous rappelez plus où aller chercher les options de formatage. Un petit CTRL+3, on entre Formatter et hop.<br />
<img title="quick access" src="http://blog.ippon.fr/wp-content/uploads/2011/10/quick_access.png" alt="quick access" /></p>
<h2>CTRL+T (Quick Type Hierarchy)</h2>
<p>Sur une classe, donne la hiérarchie de celle-ci. Toujours pratique quand on débarque sur un projet qu&#8217;on ne maîtrise pas trop.<br />
Par défaut les sous-types sont listés. Si on appuie une 2ème fois sur CTRL+T ce sont maintenant les super-types que l&#8217;on peut voir.<br />
<img title="quick type hierarchy subtypes" src="http://blog.ippon.fr/wp-content/uploads/2011/10/quick_type_hierarchy_subtypes.png" alt="quick type hierarchy subtypes" /> <img title="quick type hierarchy supertypes" src="http://blog.ippon.fr/wp-content/uploads/2011/10/quick_type_hierarchy_supertypes.png" alt="quick type hierarchy supertypes" /></p>
<h2>CTRL+SHIFT+I (Inspect)</h2>
<p>En debug, ouvre une popup contenant la vue debug de l&#8217;objet sélectionné.</p>
<h2>CTRL+SHIFT+L (Liste des raccourcis)</h2>
<p>Ces raccourcis me sont très utiles au quotidien. Cependant les raccourcis qui vous seront très utiles ne seront certainement pas les mêmes. Chacun ayant ses petites habitudes, pas la peine d&#8217;encombrer sa mémoire avec des raccourcis inutiles. La liste des raccourcis est consultable via CTRL+SHIFT+L.<br />
Si vous identifiez une action que vous effectuez souvent, regardez s&#8217;il n&#8217;existe pas un raccourci pour celle-ci.<br />
Et vous quels sont vos raccourcis indispensables ?</p>
<div class="wp-caption alignnone" style="width: 341px"><img title="liste des raccourcis CTRL+SHIFT+L" src="http://blog.ippon.fr/wp-content/uploads/2011/10/shortcuts_list.png" alt="liste des raccourcis CTRL+SHIFT+L" width="331" height="143" /><p class="wp-caption-text">liste des raccourcis CTRL+SHIFT+L</p></div>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/ZFaVoQ6Xyvs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/10/03/eclipse-ameliorer-sa-productivite-grace-aux-raccourcis-clavier/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/10/03/eclipse-ameliorer-sa-productivite-grace-aux-raccourcis-clavier/</feedburner:origLink></item>
		<item>
		<title>Speakers Ippon au JUG et à l’Agile Tour de Nantes les 12 et 13 Octobre</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/RDD92KrGN1k/</link>
		<comments>http://blog.ippon.fr/2011/09/29/speakers-ippon-au-jug-et-sug-a-nantes-les-12-et-13-octobre/#comments</comments>
		<pubDate>Thu, 29 Sep 2011 09:00:04 +0000</pubDate>
		<dc:creator>Antoine SABOT-DURAND</dc:creator>
				<category><![CDATA[Evénements]]></category>
		<category><![CDATA[Conference]]></category>
		<category><![CDATA[JUG]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=4071</guid>
		<description><![CDATA[<p>Le 12 Octobre, j&#8217;aurai le plaisir de donner ma conférence &#8220;Stateful is Beautiful&#8221; au Jug de Nantes. Si vous avez envie d&#8217;entendre parler de Java EE 6, d&#8217;extended persistence context, d&#8217;EJB et de CDI, je vous invite à vous inscrire sur le site du JUG Nantais.</p> <p>Le lendemain, 13 Octobre, Bertrand Pinel, notre directeur technique, <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/09/29/speakers-ippon-au-jug-et-sug-a-nantes-les-12-et-13-octobre/">Speakers Ippon au JUG et à l&#8217;Agile Tour de Nantes les 12 et 13 Octobre</a></span>]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" src="http://www.myidbox.com/productimages/radio_usb_micro_retro_436_n_m.jpg" alt="" width="126" height="126" />Le 12 Octobre, j&#8217;aurai le plaisir de donner ma conférence &#8220;Stateful is Beautiful&#8221; au Jug de Nantes. Si vous avez envie d&#8217;entendre parler de Java EE 6, d&#8217;extended persistence context, d&#8217;EJB et de CDI, je vous invite à vous inscrire sur <a href="http://www.nantesjug.org/" target="_blank">le site du JUG Nantais</a>.</p>
<p>Le lendemain, 13 Octobre, Bertrand Pinel, notre directeur technique,  participera à l&#8217;Agile Tour de Nantes avec sa conférence &#8220;ScrumBut, but Scrum : concilier Scrum et le mode forfait&#8221;. Les infos et inscriptions sont disponibles sur le <a href="http://at2011.agiletour.org/fr/at2011_nantes.html" target="_blank">site de l&#8217;Agile Tour</a>.</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/RDD92KrGN1k" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/09/29/speakers-ippon-au-jug-et-sug-a-nantes-les-12-et-13-octobre/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/09/29/speakers-ippon-au-jug-et-sug-a-nantes-les-12-et-13-octobre/</feedburner:origLink></item>
		<item>
		<title>Ayez le réflexe Camel !</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/t1uEHio9c0U/</link>
		<comments>http://blog.ippon.fr/2011/09/26/ayez-le-reflexe-camel/#comments</comments>
		<pubDate>Mon, 26 Sep 2011 06:30:52 +0000</pubDate>
		<dc:creator>Antony GUILLOTEAU</dc:creator>
				<category><![CDATA[ESB et SOA]]></category>
		<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Camel]]></category>
		<category><![CDATA[ESB]]></category>
		<category><![CDATA[SOA]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=3956</guid>
		<description><![CDATA[<p>EIP, ESB, SOA &#8230; A travers ces acronymes barbares, l&#8217;utilisation d&#8217;Apache Camel (http://camel.apache.org/index.html) peut paraître effrayant.</p> <p>Il ne s&#8217;agit pas ici de vous faire un article &#8220;Camel pour les nuls&#8221; mais de vous montrer que Camel met à notre disposition offre une palette d&#8217;outils facilement intégrable à nos webapps et qui peuvent nous rendre bien <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/09/26/ayez-le-reflexe-camel/">Ayez le réflexe Camel !</a></span>]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" src="http://genevajug.ch/images/events/camel-logo.png" alt="" width="146" height="72" />EIP, ESB, SOA &#8230; A travers ces acronymes barbares, l&#8217;utilisation d&#8217;Apache Camel (<a href="http://camel.apache.org/index.html">http://camel.apache.org/index.html</a>) peut paraître effrayant.</p>
<p>Il ne s&#8217;agit pas ici de vous faire un article &#8220;Camel pour les nuls&#8221; mais de vous montrer que Camel met à notre disposition offre une palette d&#8217;outils facilement intégrable à nos webapps et qui peuvent nous rendre bien des services.</p>
<p><span id="more-3956"></span></p>
<h2>Création de notre plateforme d&#8217;exécution Camel</h2>
<p>Dans un premier temps nous allons utiliser la servlet de camel pour faciliter nos tests.</p>
<h3>Le pom.xml</h3>
<pre class="brush: xml; title: ; notranslate">
&lt;project
  xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot;
  xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
  xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd&quot;&gt;

  &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;

  &lt;groupId&gt;fr.ippon.sample&lt;/groupId&gt;
  &lt;artifactId&gt;customer&lt;/artifactId&gt;
  &lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;

  &lt;name&gt;Camel Router Application&lt;/name&gt;
  &lt;description&gt;Camel project that deploys the Camel routes as a WAR&lt;/description&gt;
  &lt;url&gt;http://www.ippon.fr&lt;/url&gt;
  &lt;packaging&gt;war&lt;/packaging&gt;

  &lt;dependencies&gt;

    &lt;!-- Camel Dependencies --&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;org.apache.camel&lt;/groupId&gt;
      &lt;artifactId&gt;camel-core&lt;/artifactId&gt;
      &lt;version&gt;2.8.1&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;org.apache.camel&lt;/groupId&gt;
      &lt;artifactId&gt;camel-spring&lt;/artifactId&gt;
      &lt;version&gt;2.8.1&lt;/version&gt;
    &lt;/dependency&gt;

    &lt;!-- Spring Web --&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;org.springframework&lt;/groupId&gt;
      &lt;artifactId&gt;spring-web&lt;/artifactId&gt;
      &lt;version&gt;3.0.5.RELEASE&lt;/version&gt;
    &lt;/dependency&gt;

    &lt;!-- logging --&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;org.slf4j&lt;/groupId&gt;
      &lt;artifactId&gt;slf4j-log4j12&lt;/artifactId&gt;
      &lt;version&gt;1.6.1&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;log4j&lt;/groupId&gt;
      &lt;artifactId&gt;log4j&lt;/artifactId&gt;
      &lt;version&gt;1.2.16&lt;/version&gt;
    &lt;/dependency&gt;

  &lt;/dependencies&gt;

  &lt;build&gt;
    &lt;defaultGoal&gt;install&lt;/defaultGoal&gt;

     &lt;plugins&gt;
      &lt;plugin&gt;
        &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
        &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
        &lt;version&gt;2.3.2&lt;/version&gt;
        &lt;configuration&gt;
          &lt;source&gt;1.6&lt;/source&gt;
          &lt;target&gt;1.6&lt;/target&gt;
        &lt;/configuration&gt;
      &lt;/plugin&gt;

      &lt;!-- plugin so you can run mvn jetty:run --&gt;
      &lt;plugin&gt;
        &lt;groupId&gt;org.mortbay.jetty&lt;/groupId&gt;
        &lt;artifactId&gt;jetty-maven-plugin&lt;/artifactId&gt;
        &lt;version&gt;7.4.5.v20110725&lt;/version&gt;
        &lt;configuration&gt;
          &lt;webAppConfig&gt;
            &lt;contextPath&gt;/&lt;/contextPath&gt;
          &lt;/webAppConfig&gt;
          &lt;scanIntervalSeconds&gt;10&lt;/scanIntervalSeconds&gt;
        &lt;/configuration&gt;
      &lt;/plugin&gt;
    &lt;/plugins&gt;
  &lt;/build&gt;

&lt;/project&gt;
</pre>
<h3>Le web.xml</h3>
<p>Ensuite il est nécessaire de déclarer la servlet camel dans le web.xml :</p>
<pre class="brush: xml; title: ; notranslate">
&lt;web-app version=&quot;2.4&quot; xmlns=&quot;http://java.sun.com/xml/ns/j2ee&quot;
xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd&quot;&gt;

  &lt;display-name&gt;Camel server&lt;/display-name&gt;

  &lt;!-- Spring configuration --&gt;
  &lt;context-param&gt;
    &lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
    &lt;param-value&gt;classpath:/context/applicationContext.xml&lt;/param-value&gt;
  &lt;/context-param&gt;
  &lt;listener&gt;
    &lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener&lt;/listener-class&gt;
  &lt;/listener&gt;

  &lt;!-- Camel servlet --&gt;
  &lt;servlet&gt;
    &lt;servlet-name&gt;CamelServlet&lt;/servlet-name&gt;
    &lt;servlet-class&gt;org.apache.camel.component.servlet.CamelHttpTransportServlet&lt;/servlet-class&gt;
    &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
  &lt;/servlet&gt;
  &lt;servlet-mapping&gt;
    &lt;servlet-name&gt;CamelServlet&lt;/servlet-name&gt;
    &lt;url-pattern&gt;/camel/*&lt;/url-pattern&gt;
  &lt;/servlet-mapping&gt;

&lt;/web-app&gt;
</pre>
<h3>Le fichier de configuration Spring</h3>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;

&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
xmlns:context=&quot;http://www.springframework.org/schema/context&quot;
xmlns:camel=&quot;http://camel.apache.org/schema/spring&quot;
xsi:schemaLocation=&quot;
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd&quot;&gt;

  &lt;camelContext xmlns=&quot;http://camel.apache.org/schema/spring&quot;&gt;
    &lt;package&gt;fr.ippon.sample.customer&lt;/package&gt;
  &lt;/camelContext&gt;

&lt;/beans&gt;</pre>
<p>La balise <code></code> permet de définir le context qui sera utilisé par Camel (<a href="http//camel.apache.org/advanced-configuration-of-camelcontext-using-spring.html" target="_blank">http://camel.apache.org/advanced-configuration-of-camelcontext-using-spring.html</a>).</p>
<p>La balise <code> </code> fonctionne de manière similaire à spring et se charge d&#8217;identifier les classes qui déclarent une route.</p>
<h3>Le RouteBuilder</h3>
<p>Nous allons maintenant créer une classe permettant de déclarer des routes (<a href="http://camel.apache.org/routes.html" target="_blank">http://camel.apache.org/routes.html</a>).</p>
<pre class="brush: java; highlight: [13]; title: ; notranslate">
package fr.ippon.sample.customer.server;

import org.apache.camel.builder.Builder;
import org.apache.camel.builder.RouteBuilder;

public class CustomerServiceRouteBuilder extends RouteBuilder {

  /**
  * @see org.apache.camel.builder.RouteBuilder#configure()
  */
  @Override
  public void configure() throws Exception {
    from(&quot;servlet:///hello&quot;).transform(Builder.constant(&quot;Hello world&quot;));
  }
}
</pre>
<p>Quelques explications :</p>
<ul>
<li><code>from("servlet:///hello")</code> permet de &#8220;capturer&#8221; les requêtes provenant de la servlet camel dont le path est hello.</li>
<li><code>transform(...)</code> permet de transformer le message.</li>
<li><code>Builder.constant("Hello world")</code> ajoute la chaîne de caractères &#8220;Hello world&#8221; dans la réponse.</li>
</ul>
<h3>Le test</h3>
<p>Pour tester notre projet, il suffit de lancer jetty via la commande <code>mvn jetty:run</code> et d&#8217;ouvrir un navigateur à l&#8217;URL <code>http://localhost:8080/camel/hello</code></p>
<pre class="brush: bash; gutter: false; title: ; notranslate">Hello word</pre>
<h2>La boîte à outils</h2>
<p>Maintenant que nous allons nous servir de notre plateforme d&#8217;exécution Camel pour tester les nombreux fonctionnalités de Camel.</p>
<h3>Appeler un bean spring</h3>
<p>Au travers du composant bean (<a href="http://camel.apache.org/bean.html" target="_blank">http://camel.apache.org/bean.html</a>), Camel offre la possibilité de router un message vers un bean spring.</p>
<p>Pour se faire, nous allons créer un service de liste de clients.</p>
<p>Le POJO</p>
<pre class="brush: java; title: ; notranslate">

package fr.ippon.sample.customer.model;
public class Customer {

  private String name;

  public Customer() {
    super();
  }

  public Customer(String name) {
    super();
    this.name = name;
  }

  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
}
</pre>
<p>L&#8217;interface du service</p>
<pre class="brush: java; title: ; notranslate">

package fr.ippon.sample.customer.service;

import java.util.List;
import fr.ippon.sample.customer.model.Customer;

public interface CustomerService {
  List&lt;Customer&gt; findAllCustomers();
  List&lt;Customer&gt; findFrenchCustomers();
  List&lt;Customer&gt; findEnglishCustomers();
}</pre>
<p>Et enfin son implémentation</p>
<pre class="brush: java; title: ; notranslate">
package fr.ippon.sample.customer.service.impl;

import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Component;
import fr.ippon.sample.customer.model.Customer;
import fr.ippon.sample.customer.service.CustomerService;

@Component(&quot;defaultCustomerService&quot;)
public class DefaultCustomerService implements CustomerService {

  @Override
  public List&amp;amp;amp;lt;Customer&amp;amp;amp;gt; findAllCustomers() {
    Lis&lt;Customer&gt; customers = new ArrayList&lt;Customer&gt;();
    customers.addAll(findFrenchCustomers());
    customers.addAll(findEnglishCustomers());
    return customers;
  }

  @Override
  public List&lt;Customer&gt; findFrenchCustomers() {
    List&lt;Customer&gt; customers = new ArrayList&lt;Customer&gt;();
    customers.add(new Customer(&quot;Jean Dupont&quot;));
    customers.add(new Customer(&quot;Paul Durand&quot;));
    return customers;
  }

  @Override
  public List&lt;Customer&gt; findEnglishCustomers() {
    List&lt;Customer&gt; customers = new ArrayList&lt;Customer&gt;();
    customers.add(new Customer(&quot;John Doe&quot;));
    customers.add(new Customer(&quot;Adam Smith&quot;));
    return customers;
  }
}</pre>
<p>Ensuite il nous faut déclarer ce service dans le context spring en modifiant le fichier applicationContext.xml :</p>
<pre class="brush: xml; title: ; notranslate">
  &lt;context:component-scan base-package=&quot;fr.ippon.sample.customer&quot; /&gt;
</pre>
<p>Maintenant nous pouvons créer une route vers ce service avec Camel (<code>fr.ippon.sample.customer.route.CustomerServiceRouteBuilder.configure()</code>)</p>
<pre class="brush: java; gutter: false; title: ; notranslate">
from(&quot;servlet:///customer/list&quot;)
.to(&quot;bean:defaultCustomerService?method=findAllCustomers&quot;);
</pre>
<p>En relançant de serveur jetty on obtient le résultat suivant à l&#8217;URL http://localhost:8080/camel/customer/list :</p>
<pre class="brush: bash; gutter: false; title: ; notranslate">
fr.ippon.sample.customer.model.Customer@2b650cea,
fr.ippon.sample.customer.model.Customer@7732ece7,
fr.ippon.sample.customer.model.Customer@305f6ed4,
fr.ippon.sample.customer.model.Customer@4965391b]
</pre>
<h3>Transformation du résultat</h3>
<p>Nous allons maintenant transformer le résultat de manière à ce que la liste puisse être affichée en XML.</p>
<p>Camel fournit un ensemble de &#8220;data format&#8221; (http://camel.apache.org/data-format.html) permettant de transformer le rendu des messages.</p>
<p>Pour afficher la liste résultante en XML à l&#8217;aide de xstream (&lt; a href=&#8221;http://camel.apache.org/xstream.html&#8221;&gt;http://camel.apache.org/xstream.html), il suffit d&#8217;ajouter la dépendance suivante dans le pom.xml</p>
<pre class="brush: xml; title: ; notranslate">
&lt;dependency&gt;
  &lt;groupId&gt;org.apache.camel&lt;/groupId&gt;
  &lt;artifactId&gt;camel-xstream&lt;/artifactId&gt;
  &lt;version&gt;2.8.1&lt;/version&gt;
&lt;/dependency&gt;
</pre>
<p>puis de créer une nouvelle route :</p>
<pre class="brush: java; gutter: false; title: ; notranslate">
from(&quot;servlet:///customer/list/xml&quot;).to(&quot;bean:defaultCustomerService?method=findAllCustomers&quot;)
.marshal().xstream();
</pre>
<p>En relançant de serveur jetty nous obtenons le résultat suivant à l&#8217;URL http://localhost:8080/camel/customer/list/xml :</p>
<pre class="brush: xml; title: ; notranslate">
&lt;list&gt;
  &lt;fr.ippon.sample.customer.model.Customer&gt;
    &lt;name&gt;Jean Dupont&lt;/name&gt;
  &lt;/fr.ippon.sample.customer.model.Customer&gt;
  &lt;fr.ippon.sample.customer.model.Customer&gt;
    &lt;name&gt;Paul Durand&lt;/name&gt;
  &lt;/fr.ippon.sample.customer.model.Customer&gt;
  &lt;fr.ippon.sample.customer.model.Customer&gt;
    &lt;name&gt;John Doe&lt;/name&gt;
  &lt;/fr.ippon.sample.customer.model.Customer&gt;
  &lt;fr.ippon.sample.customer.model.Customer&gt;
    &lt;name&gt;Adam Smith&lt;/name&gt;
  &lt;/fr.ippon.sample.customer.model.Customer&gt;
&lt;/list&gt;
</pre>
<p>Si maintenant nous souhaitons afficher la liste sous un format JSON, il suffit d&#8217;utiliser le data format JSON (<a href="http://camel.apache.org/json.html">http://camel.apache.org/json.html</a>) et de paramétrer la route suivante :</p>
<pre class="brush: java; gutter: false; title: ; notranslate">from(&quot;servlet:///customer/list/json&quot;)
.to(&quot;bean:defaultCustomerService?method=findAllCustomers&quot;)
.marshal().json();
</pre>
<p>Nous obtenons ainsi le résultat suivant :</p>
<pre class="brush: bash; gutter: false; title: ; notranslate">
{&quot;list&quot;:{&quot;fr.ippon.sample.customer.model.Customer&quot;:[{&quot;name&quot;:&quot;Jean Dupont&quot;},{&quot;name&quot;:&quot;Paul Durand&quot;},{&quot;name&quot;:&quot;John Doe&quot;},{&quot;name&quot;:&quot;Adam Smith&quot;}]}}
</pre>
<h3>Ecriture dans un fichier</h3>
<p>Camel fournit un composant permettant de gérer les fichiers (<a href="http://camel.apache.org/file2.html">http://camel.apache.org/file2.html</a>).</p>
<p>Pour enregistrer la liste des clients sous la forme XML dans un fichier, il suffit de déclarer la route suivante :</p>
<pre class="brush: java; gutter: false; title: ; notranslate">
from(&quot;servlet:///customer/list/export&quot;)
.to(&quot;bean:defaultCustomerService?method=findAllCustomers&quot;)
.marshal().xstream()
.to(&quot;file:/home/data/out/?fileName=customers.xml&quot;);
</pre>
<p>Ce composant permet également de copier automatiquement des fichiers d&#8217;un répertoire à un autre, nous évitant au passage de créer un job Quartz et un service de copie</p>
<pre class="brush: java; gutter: false; title: ; notranslate">
from(&quot;file:/home/camel/data/in&quot;).to(&quot;file:/home/camel/data/out&quot;);
</pre>
<h3>Envoi dans un mail</h3>
<p>Camel fournit également un composant permettant d&#8217;envoyer des mails (<a href="http://camel.apache.org/mail.html">http://camel.apache.org/mail.html</a>).</p>
<p>Pour cela, il est nécessaire de modifier le pom :</p>
<pre class="brush: xml; title: ; notranslate">
&lt;dependency&gt;
  &lt;groupId&gt;org.apache.camel&lt;/groupId&gt;
  &lt;artifactId&gt;camel-mail&lt;/artifactId&gt;
  &lt;version&gt;2.8.1&lt;/version&gt;
&lt;/dependency&gt;
</pre>
<p>et de déclarer la route suivante :</p>
<pre class="brush: java; title: ; notranslate">
from(&quot;servlet:///customer/list/mail&quot;).to(&quot;bean:defaultCustomerService?method=findAllCustomers&quot;)
.marshal().xstream()
  .process(new Processor() {
    @Override
    public void process(Exchange exchange) throws Exception {
      exchange.getIn().setHeader(&quot;to&quot;, &quot;waaza@yopmail.com&quot;);
      exchange.getIn().setHeader(&quot;subject&quot;, &quot;send by camel&quot;);
  }
})
.to(&quot;smtp://host?username=sender&amp;amp;amp;amp;password=password&quot;);
</pre>
<h3>Envoi sur un serveur FTP</h3>
<p>Camel fournit également un composant permettant la communication avec un serveur FTP (<a href="http://camel.apache.org/ftp2.html">http://camel.apache.org/ftp2.html</a>).</p>
<p>Pour cela, il est nécessaire de modifier le pom :</p>
<pre class="brush: xml; title: ; notranslate">
&lt;dependency&gt;
  &lt;groupId&gt;org.apache.camel&lt;/groupId&gt;
  &lt;artifactId&gt;camel-ftp&lt;/artifactId&gt;
  &lt;version&gt;2.8.1&lt;/version&gt;
&lt;/dependency&gt;
</pre>
<p>et de déclarer la route suivante :</p>
<pre class="brush: java; gutter: false; title: ; notranslate">
from(&quot;servlet:///customer/list/ftp&quot;).to(&quot;bean:defaultCustomerService?method=findAllCustomers&quot;)
.marshal().xstream()
.to(&quot;ftp://user@host:port/directory?username=user&amp;amp;amp;password=password&quot;);
</pre>
<h3>Agrégation de services</h3>
<p>Camel peut être utilisé pour réaliser de l&#8217;agrégation de service. Dans notre exemple de liste de clients, nous avons créé deux méthodes <code>findEnglishCustomers</code> et <code>findFrenchCustomers</code>.</p>
<p>L&#8217;idée est de proposer un seul et même service réalisant l&#8217;appel à ces deux méthodes.</p>
<p>Pour cela, Camel implémente le pattern multicast (<a href="http://camel.apache.org/multicast.html">http://camel.apache.org/multicast.html</a>). Il suffit alors de créer les routes suivantes :</p>
<pre class="brush: java; title: ; notranslate">
from(&quot;servlet:///customer/agregate/xml&quot;).multicast(
  new AggregationStrategy() {
    @Override
    public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
      Message newIn = newExchange.getIn();
      if (oldExchange == null) {
        return newExchange;
      }
      else {
        List oldBody = oldExchange.getIn().getBody(List.class);
        newIn.getBody(List.class).addAll(oldBody);
        return newExchange;
      }
    }
  }).parallelProcessing()
.timeout(500).to(&quot;direct:en&quot;, &quot;direct:fr&quot;).end().marshal()
.xstream();

from(&quot;direct:en&quot;).to(&quot;bean:defaultCustomerService?method=findEnglishCustomers&quot;);
from(&quot;direct:fr&quot;).to(&quot;bean:defaultCustomerService?method=findFrenchCustomers&quot;);
</pre>
<p>Quelques explications :</p>
<p>Le principe est de dispatcher le message vers les deux routes <code>direct:en</code> et <code>direct:fr</code> qui seront en charge de lister respectivement les clients anglais et les clients français.</p>
<p>Le multicast permet d&#8217;agréger ensuite les résultats en suivant la stratégie décrite par la classe interne AggregationStrategy.</p>
<h3>Conclusion</h3>
<p>J&#8217;espère vous avoir convaincu que dans certains cas Camel peut s&#8217;avérer très utile dans nos développements.</p>
<p>Il est possible d&#8217;intégrer Camel simplement dans nos Web App. Je vous invite à regarder de plus près l&#8217;ensemble des composants Camel (<a href="http://camel.apache.org/components.html" target="_blank">http://camel.apache.org/components.html</a>) ainsi que ses patterns (<a href="http://camel.apache.org/enterprise-integration-patterns.html">http://camel.apache.org/enterprise-integration-patterns.html</a>).</p>
<p>Les sources sont disponibles <a href="http://blog.ippon.fr/2011/09/26/ayez-le-reflexe-camel/customer/" rel="attachment wp-att-3973">ici </a></p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/t1uEHio9c0U" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/09/26/ayez-le-reflexe-camel/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/09/26/ayez-le-reflexe-camel/</feedburner:origLink></item>
		<item>
		<title>Le Scrum User Group @Ippon Technologies le 05 octobre</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/0xJrXixx_vM/</link>
		<comments>http://blog.ippon.fr/2011/09/19/le-scrum-user-group-ippon-technologies-le-05-octobre/#comments</comments>
		<pubDate>Mon, 19 Sep 2011 14:27:29 +0000</pubDate>
		<dc:creator>Geoffray GRUEL</dc:creator>
				<category><![CDATA[Evénements]]></category>
		<category><![CDATA[Agilité]]></category>
		<category><![CDATA[Scrum]]></category>
		<category><![CDATA[Scrum User Group]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=3939</guid>
		<description><![CDATA[<p>Bonjour,</p> <p>Nous avons grand plaisir à accueillir la prochaine soirée sur Scrum User Group le mercredi 5 octobre 2011, de 18:30 à&#8230;</p> <p>Les inscriptions sont ouvertes à l&#8217;adresse suivante : http://www.meetup.com/frenchsug/events/33361922/</p> <p>Nos salles ne sont malheureusement pas extensibles (80 places) et  je vous conseille de réserver au plus tôt.</p> <p>Nos bureaux sont à Levallois : <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/09/19/le-scrum-user-group-ippon-technologies-le-05-octobre/">Le Scrum User Group @Ippon Technologies le 05 octobre</a></span>]]></description>
			<content:encoded><![CDATA[<p>Bonjour,</p>
<p>Nous avons grand plaisir à accueillir la prochaine soirée sur Scrum User Group le mercredi 5 octobre 2011, de 18:30 à&#8230;</p>
<p>Les inscriptions sont ouvertes à l&#8217;adresse suivante : <a title="Lien Meetup Scrum User Group" href="http://www.meetup.com/frenchsug/events/33361922/" target="_blank">http://www.meetup.com/frenchsug/events/33361922/</a></p>
<p>Nos salles ne sont malheureusement pas extensibles (80 places) et  je vous conseille de réserver au plus tôt.</p>
<p>Nos bureaux sont à Levallois : 90 rue Baudin &#8211; 5 ème étage &#8211; 92300 &#8211; Levallois-Perret =&gt; <a href="http://maps.google.fr/maps?pq=ippon+technologies&amp;hl=fr&amp;sugexp=gsis,i18n%3Dtrue&amp;cp=13&amp;gs_id=1h&amp;xhr=t&amp;q=90+rue+baudin+levallois+perret&amp;client=firefox-a&amp;hs=lef&amp;rls=org.mozilla:fr:official&amp;channel=s&amp;gs_upl=&amp;bav=on.2,or.r_gc.r_pw.&amp;biw=1280&amp;bih=830&amp;um=1&amp;ie=UTF-8&amp;hq=&amp;hnear=0x47e66f78f274ac71:0x130b82c38869ed41,90+Rue+Baudin,+92300+Levallois-Perret&amp;gl=fr&amp;ei=GU93Ts_LMue3sQKv-KyMBQ&amp;sa=X&amp;oi=geocode_result&amp;ct=image&amp;resnum=3&amp;sqi=2&amp;ved=0CDYQ8gEwAg" target="_blank">PLAN</a></p>
<p>Nous sommes à égale distance (5 minutes) du métro 3 (Pont de Levallois) et de la gare SNCF de Clichy-Levallois.</p>
<p>En espérant vous voir nombreux à cette soirée agile,</p>
<p>Geoffray</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/0xJrXixx_vM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/09/19/le-scrum-user-group-ippon-technologies-le-05-octobre/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/09/19/le-scrum-user-group-ippon-technologies-le-05-octobre/</feedburner:origLink></item>
		<item>
		<title>Guérir de l’effet poisson rouge</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/U8M1bniBzkw/</link>
		<comments>http://blog.ippon.fr/2011/09/09/guerir-de-leffet-poisson-rouge/#comments</comments>
		<pubDate>Fri, 09 Sep 2011 12:57:57 +0000</pubDate>
		<dc:creator>Harold CAPITAINE</dc:creator>
				<category><![CDATA[Outils]]></category>
		<category><![CDATA[Veille]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=3912</guid>
		<description><![CDATA[<p>En tant que développeurs et veilleurs, nous utilisons au quotidien divers outils pour nous mettre à jour sur des technologies ou bien trouver des solutions à des problèmes techniques pointus. C&#8217;est lors de nos expéditions sur la toile ou de lectures de tweets que nous rencontrons bien souvent des articles qui nous intéressent mais qui <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/09/09/guerir-de-leffet-poisson-rouge/">Guérir de l&#8217;effet poisson rouge</a></span>]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.ippon.fr/2011/09/09/guerir-de-leffet-poisson-rouge/poisson/" rel="attachment wp-att-3920"><img class="alignright size-thumbnail wp-image-3920" title="poisson" src="http://blog.ippon.fr/wp-content/uploads/2011/09/poisson-150x150.jpg" alt="" width="150" height="150" /></a>En tant que développeurs et veilleurs, nous utilisons au quotidien divers outils pour nous mettre à jour sur des technologies ou bien trouver des solutions à des problèmes techniques pointus. C&#8217;est lors de nos expéditions sur la toile ou de lectures de tweets que nous rencontrons bien souvent des articles qui nous intéressent mais qui pour l&#8217;instant ne nous sont pas forcément utiles.<br />
Puis vient le jour où un collègue ou un supérieur nous pose une question sur un thème précis. Voici une des réponses qui peut survenir: &#8220;Oui bien sûr j&#8217;ai rencontré la solution à ce problème il y a quelques temps lors de mes lectures, mais alors sur quel site? ou bien était ce sur un pdf? je ne sais plus.&#8221;.<br />
Et voilà l&#8217;effet poisson rouge en action!!!<br />
&#8220;Bien sûr que de mon bocal je me rappelle le canapé dans la pièce mais alors de quelle couleur est il? Attends je fais un tour pour m&#8217;en rappeler&#8221;. Quand il s&#8217;agit d&#8217;un tour de bocal ça va mais lorsqu&#8217;il s&#8217;agit de parcourir l&#8217;immensité du web&#8230; Courage et persévérance seront nos seuls atouts.<br />
C&#8217;est à ce moment qu&#8217;un outil devient utile et nécessaire et il en existe des outils:</p>
<ol>
<li>J&#8217;utilise les bookmarks de mon navigateur, problème: impossible de les retrouver si je change de poste.</li>
<li>Je partage sur la toile via un compte tweeter par exemple, problème: il est difficile de faire des recherches rapides et précises sur ce que l&#8217;on a taggé.</li>
<li>J&#8217;utilise un outil du type firefox sync, problème je ne suis pas certains de pouvoir partager mes découvertes.</li>
</ol>
<p>Et c&#8217;est là qu&#8217;intervient pour moi l&#8217;outil magique: <strong><a title="delicious.com" href="http://delicious.com">delicious.com</a></strong>, la solution de bookmarking sociale.</p>
<p>En effet cet outil regroupe toutes les fonctionnalités qui nous intéresse.</p>
<ol>
<li>La base: je peux bookmarker mes pages qui sont stockés sur internet et donc consultable de n&#8217;importe où. De plus delicious fournit un utilitaire pour accéder depuis firefox à ses bookmarks avec un système de recherche et tag intégrée.</li>
<li>La sécurité: L&#8217;authentification se fait par login/mot de passe, mais surtout il existe la gestion de la confidentialité des bookmarks en effet parfois il m&#8217;arrive de bookmarker des pages d&#8217;intêrets personnels que je ne veux pas divulguer pour  préserver ma vie privée.</li>
<li>Le côté pratique: delicious gère la notion de tag, ainsi il est aisé de regrouper les pages par notion. Attention toutefois à ne pas exagérer!!! après 5 tags cela devient infernal pour retrouver une page précise car trop de pages répondent à la recherche du tag demandé.</li>
<li>Le côté social: Avec delicious les bookmarks sont publics donc consultables par tous mais il existe une fonctionnalité intéressante faite à la twitter, c&#8217;est la possibilité de s&#8217;abonner à la liste des tags d&#8217;autres personnes. En plus l&#8217;utilitaire firefox notifie de nouveaux tags dans votre réseau. On peut aussi envoyer directement des bookmarks à des personnes précises.</li>
</ol>
<p>Personnellement j&#8217;utilise cet outil au quotidien et je pense que c&#8217;est une solution contre cette maladie qui nous guettes tous et toutes.<br />
Essayez le pendant une durée d&#8217;un mois afin d&#8217;avoir assez de bookmark et rapidement vous verrez les bénéfices de cet outil.<br />
Si vous avez d&#8217;autres solutions n&#8217;hésitez pas à commenter cet article!!!</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/U8M1bniBzkw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/09/09/guerir-de-leffet-poisson-rouge/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/09/09/guerir-de-leffet-poisson-rouge/</feedburner:origLink></item>
		<item>
		<title>Ippevent du 22/09 la forge logicielle &amp; CloudBees, Inscriptions ouvertes</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/MaQ0VlLDCi0/</link>
		<comments>http://blog.ippon.fr/2011/09/06/ippevent-du-2209-la-forge-logicielle-cloudbees-inscriptions-ouvertes/#comments</comments>
		<pubDate>Tue, 06 Sep 2011 07:00:15 +0000</pubDate>
		<dc:creator>Julien DUBOIS</dc:creator>
				<category><![CDATA[Ippevents]]></category>
		<category><![CDATA[CloudBees]]></category>
		<category><![CDATA[Forge]]></category>
		<category><![CDATA[Maven]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=3850</guid>
		<description><![CDATA[<p>&#8220;Industrialisation&#8221;, un mot qu&#8217;on entend sur toutes les lèvres lorsqu&#8217;on parle de développement logiciel. La forge logicielle est devenue un enjeu clé pour structurer les pratiques de développement et fournir un cadre de travail productif. Si Maven est quasiment incontournable, que Git fait beaucoup parler de lui, et que l&#8217;intégration continue devient une pratique courante, <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/09/06/ippevent-du-2209-la-forge-logicielle-cloudbees-inscriptions-ouvertes/">Ippevent du 22/09 la forge logicielle &#038; CloudBees, Inscriptions ouvertes</a></span>]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" src="http://www.cloudbees.com/sites/all/themes/custom/cloudbees_zen/logo.png" alt="logo CloudBees" width="133" height="60" />&#8220;Industrialisation&#8221;, un mot qu&#8217;on entend sur toutes les lèvres lorsqu&#8217;on parle de développement logiciel. La forge logicielle est devenue un enjeu clé pour structurer les pratiques de développement et fournir un cadre de travail productif. Si Maven est quasiment incontournable, que Git fait beaucoup parler de lui, et que l&#8217;intégration continue devient une pratique courante, la forge logicielle ne se limite pas au simple build et peut accompagner les développeurs bien au delà de la simple compilation &#8211; à condition de bien maîtriser l&#8217;assemblage de nos outils !</p>
<p>Au cours de cette session animée par Nicolas De Loof, nous ferons le tour du propriétaire des outils qui constituent une forge logicielle, pour une automatisation complète des processus de développement et un gain de productivité. Nous mettrons à profit le Cloud computing pour apporter des solutions de forge logicielle clé en main montées en quelques minutes, à travers l&#8217;offre de CloudBees, où code, build, test et production sont propulsés dans le nuage.</p>
<p><em>Nicolas De Loof est Senior Engineer chez CloudBees, après avoir été Architecte Java pour de grandes SSII françaises. Techno-veilleur et développeur open-source, il a rejoint l&#8217;équipe de développement Maven en 2007, en particulier pour le support de GWT, et rédige le premier ouvrage en Français sur le sujet. Avec 14 ans d&#8217;expérience en développement dans ses bagages et de nombreuses relations dans la communauté Java, il crée en 2008 le BreizhJUG, groupe d&#8217;utilisateur Java Rennais. Il a animé plusieurs conférences sur le thème de la forge logicielle et participe activement au microcosme Java. @ndeloof | http://blog.loof.fr</em></p>
<p>Cet Ippevent aura donc lieu <strong>le 22 septembre prochain à partir de 19h dans les locaux d&#8217;Ippon à Levallois Perret</strong>. Comme toujours l&#8217;inscription est gratuite et se fait via le formulaire ci-dessous.</p>

		<div id="usermessage7a" class="cf_info "></div>
		<form enctype="application/x-www-form-urlencoded" action="/feed/#usermessage7a" method="post" class="cform inscription-ippevent " id="cforms7form">
		<fieldset class="cf-fs1">
		<legend>Inscription à l'événement du 22/09/2011</legend>
		<ol class="cf-ol">
			<li class="cf_hidden"><input type="hidden" class="cfhidden" name="Date_evt" id="Date_evt" value="22/09/2011"/></li>
			<li id="li-7-3" class=""><label for="Evenement"><span>Evénement</span></label><input readonly="readonly" type="text" name="Evenement" id="Evenement" class="single readonly" value="la forge logicielle & CloudBees"/></li>
			<li id="li-7-4" class=""><label for="Salutation"><span>Salutation</span></label><select name="Salutation" id="Salutation" class="cformselect fldrequired" >
				<option value="M.">M.</option>
				<option value="Mlle">Mlle</option>
				<option value="Mme">Mme</option>
			</select><span class="reqtxt">(requis)</span></li>
			<li id="li-7-5" class=""><label for="Prenom"><span>Prénom</span></label><input type="text" name="Prenom" id="Prenom" class="single fldrequired" value=""/><span class="reqtxt">(requis)</span></li>
			<li id="li-7-6" class=""><label for="Nom"><span>Nom</span></label><input type="text" name="Nom" id="Nom" class="single fldrequired" value=""/><span class="reqtxt">(requis)</span></li>
			<li id="li-7-7" class=""><label for="Email"><span>Email</span></label><input type="email" name="Email" id="Email" class="single fldemail fldrequired" value=""/><span class="emailreqtxt">(un email valide est requis)</span></li>
			<li id="li-7-8" class=""><label for="Societe"><span>Société</span></label><input type="text" name="Societe" id="Societe" class="single" value=""/></li>
			<li id="li-7-9" class=" cf-box-title">J'accepte de recevoir des informations de la part d'Ippon Technologies par email</li>
			<li id="li-7-9items" class="cf-box-group">
				<input type="radio" id="J-accepte-de-recevoir-des-informations-de-la-part-d-Ippon-Technologies-par-email-1" name="J-accepte-de-recevoir-des-informations-de-la-part-d-Ippon-Technologies-par-email" value="Oui" class="cf-box-b fldrequired"/><label for="J-accepte-de-recevoir-des-informations-de-la-part-d-Ippon-Technologies-par-email-1" class="cf-after"><span>Oui</span></label>
				<br />
				<input type="radio" id="J-accepte-de-recevoir-des-informations-de-la-part-d-Ippon-Technologies-par-email-2" name="J-accepte-de-recevoir-des-informations-de-la-part-d-Ippon-Technologies-par-email" value="Non" checked="checked" class="cf-box-b fldrequired"/><label for="J-accepte-de-recevoir-des-informations-de-la-part-d-Ippon-Technologies-par-email-2" class="cf-after"><span>Non</span></label>
				<br />
			</li>
		</ol>
		</fieldset>

		<fieldset class="cf_hidden">
			<legend>&nbsp;</legend>
			<input type="hidden" name="cf_working7" id="cf_working7" value="Veuillez%20patienter..."/>
			<input type="hidden" name="cf_failure7" id="cf_failure7" value="Veuillez%20remplir%20tous%20les%20champs%20obligatoires%20SVP"/>
			<input type="hidden" name="cf_codeerr7" id="cf_codeerr7" value="Please%20double-check%20your%20verification%20code."/>
			<input type="hidden" name="cf_customerr7" id="cf_customerr7" value="yyy"/>
			<input type="hidden" name="cf_popup7" id="cf_popup7" value="nn"/>
		</fieldset>
		<p class="cf-sb"><input type="submit" name="sendbutton7" id="sendbutton7" class="sendbutton" value="S'inscrire" onclick="return cforms_validate('7', false)"/></p></form><p class="linklove" id="ll7"><a href="http://www.deliciousdays.com/cforms-plugin"><em>cforms</em> contact form by delicious:days</a></p>
<p><em><br />
</em></p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/MaQ0VlLDCi0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/09/06/ippevent-du-2209-la-forge-logicielle-cloudbees-inscriptions-ouvertes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/09/06/ippevent-du-2209-la-forge-logicielle-cloudbees-inscriptions-ouvertes/</feedburner:origLink></item>
		<item>
		<title>Ippevent Flex avec Granite DS : Les Films</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/eUj_b_JpyT4/</link>
		<comments>http://blog.ippon.fr/2011/09/06/ippevent-granite-ds-les-films/#comments</comments>
		<pubDate>Tue, 06 Sep 2011 06:30:40 +0000</pubDate>
		<dc:creator>Antoine SABOT-DURAND</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Ippevents]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[GraniteDS]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=3859</guid>
		<description><![CDATA[<p>Ca y est ! Les vidéos de l&#8217;Ippevent du 23 juin dernier sont enfin disponibles. Dans cette session nous retrouvons tout d&#8217;abord William Drai qui nous présente les mérites de l&#8217;outil Granite DS et son apport conséquent sur les développemens Flex.</p> <p></p> <p>Puis, dans un second temps, Antoine Büsch, consultant chez Ippon nous présente un <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/09/06/ippevent-granite-ds-les-films/">Ippevent Flex avec Granite DS : Les Films</a></span>]]></description>
			<content:encoded><![CDATA[<p>Ca y est ! Les vidéos de l&#8217;Ippevent du 23 juin dernier sont enfin disponibles. Dans cette session nous retrouvons tout d&#8217;abord <strong>William Drai</strong> qui nous présente les mérites de l&#8217;outil Granite DS et son apport conséquent sur les développemens Flex.</p>
<p><iframe frameborder="0" height="338" src="http://player.vimeo.com/video/28628886?color=ff9933" width="601"></iframe></p>
<p>Puis, dans un second temps, <strong>Antoine Büsch</strong>, consultant chez Ippon nous présente un retour d&#8217;expérience sur l&#8217;utilisation de Granite DS lors d&#8217;un projet Flex.</p>
<p><iframe frameborder="0" height="338" src="http://player.vimeo.com/video/28632540?color=ff9933" width="601"></iframe></p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/eUj_b_JpyT4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/09/06/ippevent-granite-ds-les-films/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/09/06/ippevent-granite-ds-les-films/</feedburner:origLink></item>
		<item>
		<title>Ippon Technologies au Tours JUG</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/9yU6tUqzvKc/</link>
		<comments>http://blog.ippon.fr/2011/09/05/ippon-technologies-au-tours-jug/#comments</comments>
		<pubDate>Mon, 05 Sep 2011 13:57:41 +0000</pubDate>
		<dc:creator>Julien DUBOIS</dc:creator>
				<category><![CDATA[Evénements]]></category>
		<category><![CDATA[Cassandra]]></category>
		<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[JUG]]></category>
		<category><![CDATA[NoSQL]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=3847</guid>
		<description><![CDATA[<p>Après La Rochelle et Bordeaux, Ippon Technologies sera présent au Tours JUG le 21 Septembre 2011.</p> <p>Julien Dubois, directeur du pôle conseil de la société, y animera une présentation sur les thèmes de la montée en charge et des bases de données NoSQL, intitulée &#8220;Hibernate vs. le Cloud Computing&#8221;.</p> <p>Pour plus de détails et pour <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/09/05/ippon-technologies-au-tours-jug/">Ippon Technologies au Tours JUG</a></span>]]></description>
			<content:encoded><![CDATA[<p>Après <a title="Ippon au Jug Summer Camp" href="http://blog.ippon.fr/2011/06/06/ippon-au-jug-summer-camp/">La Rochelle</a> et <a title="Ippon au Bordeaux JUG" href="http://blog.ippon.fr/2011/08/17/ippon-au-bordeaux-jug/">Bordeaux</a>, Ippon Technologies sera présent au Tours JUG le 21 Septembre 2011.</p>
<p>Julien Dubois, directeur du pôle conseil de la société, y animera une présentation sur les thèmes de la montée en charge et des bases de données NoSQL, intitulée &#8220;Hibernate vs. le Cloud Computing&#8221;.</p>
<p>Pour plus de détails et pour vous inscrire à la soirée, <a href="http://www.toursjug.org/xwiki/bin/view/Meetings/20110921">rendez-vous sur le site du Tours JUG</a>.</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/9yU6tUqzvKc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/09/05/ippon-technologies-au-tours-jug/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/09/05/ippon-technologies-au-tours-jug/</feedburner:origLink></item>
		<item>
		<title>Retours sur la soirée “DevOps, Scrum et Kanban” du French Scrum User Group</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/0unV5xRFYKk/</link>
		<comments>http://blog.ippon.fr/2011/09/01/retours-sur-la-soiree-devops-scrum-et-kanban-du-french-scrum-user-group/#comments</comments>
		<pubDate>Thu, 01 Sep 2011 10:19:39 +0000</pubDate>
		<dc:creator>Anne GABRILLAGUES</dc:creator>
				<category><![CDATA[Evénements]]></category>
		<category><![CDATA[Agilité]]></category>
		<category><![CDATA[Devops]]></category>
		<category><![CDATA[Kanban]]></category>
		<category><![CDATA[Scrum]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=3401</guid>
		<description><![CDATA[<p></p> <p>Le French Scrum User Group organisait vendredi 24 Juin une soirée &#8220;DevOps, Scrum et Kanban&#8221; dans les locaux du Centre de Conférences Microsoft à Issy-Les-Moulineaux.  Je profite de ce billet pour partager avec vous mes retours sur les conférences présentées à cette occasion.</p> <p>Cette session comprenait les sujets suivants :</p> Introduction à Kanban, par Laurent <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/09/01/retours-sur-la-soiree-devops-scrum-et-kanban-du-french-scrum-user-group/">Retours sur la soirée &#8220;DevOps, Scrum et Kanban&#8221; du French Scrum User Group</a></span>]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" title="Logo French Scrum User Group" src="http://www.frenchsug.org/download/attachments/131074/global.logo?version=2" alt="Logo French Scrum User Group" width="177" height="60" /></p>
<p>Le French Scrum User Group organisait vendredi 24 Juin une soirée &#8220;DevOps, Scrum et Kanban&#8221; dans les locaux du Centre de Conférences Microsoft à Issy-Les-Moulineaux.  Je profite de ce billet pour partager avec vous mes retours sur les conférences présentées à cette occasion.</p>
<p>Cette session comprenait les sujets suivants :</p>
<ul>
<li>Introduction à Kanban, par <a href="http://www.laurentmorisseau.com/" target="_blank">Laurent Morisseau</a></li>
<li>Keynote &#8220;<strong>Devops &amp; Kanban : Getting to one button deploy using Kanban</strong>&#8220;, par <a href="http://agilemanagement.net/index.php/bio_dominica/">Dominica DeGrandis</a>, associée chez David J Anderson &amp; Associates</li>
<li>&#8220;<strong>Scrum &amp; Kanban, tirer le meilleur des deux</strong>&#8220;, par  <a href="http://antoine.vernois.net/dotclear/">Antoine Vernois</a> et <a href="http://www.fabrice-aimetti.fr/">Fabrice Aimetti</a></li>
</ul>
<p><span id="more-3401"></span></p>
<h2>Introduction à Kanban</h2>
<p>Cette présentation, sous titrée &#8220;Une démarche Kanban pour des enjeux Lean&#8221; a été l&#8217;occasion de rappeler les fondamentaux de Kanban en y apportant un éclairage issus de l&#8217;expérience de Laurent Morisesau sur différents projets (notamment migration). Les thèmes abordés tournent autour  :</p>
<ul>
<li>pourquoi utiliser Kanban ?</li>
<li>enjeux de la démarche Lean (optimisation du flux de production)</li>
<li>principes Kanban</li>
<li>présentation de la démarche Lean :
<ol>
<li>identifier la valeur</li>
<li>identifier la chaîne de valeur</li>
<li>créer un flux continu pièce à pièce</li>
<li>établir un flux tiré</li>
<li>rechercher la perfection</li>
</ol>
</li>
</ul>
<p><img class="aligncenter" title="Principes Lean" src="http://blog.ippon.fr/wp-content/uploads/2011/06/IMAG0010.jpg" alt="Principes Lean" width="424" height="254" /></p>
<p>J&#8217;ai surtout retenu de cette intervention les messages suivants :</p>
<ul>
<li>il faut toujours se baser sur le <strong>processus réel</strong>, même s&#8217;il n&#8217;est pas parfait, en respectant les rôles et responsabilités existants.</li>
<li>importance de la notion de flux tiré, c&#8217;est à dire la capacité de production calée en fonction du débit du haut de la chaîne, illustré notamment par les maximes suivantes :
<ul>
<li>on ne construit pas de fonctionnalités dont personne n&#8217;a besoin maintenant</li>
<li>on n&#8217;écrit pas de spécification que l&#8217;on ne peut pas développer</li>
<li>on ne code pas ce que l&#8217;on ne sait pas tester</li>
<li>on ne teste pas plus de code que ce que l&#8217;on peut déployer</li>
<li>on ne déploie pas de code qui ne sera pas utilisé</li>
</ul>
</li>
<li>démarche d&#8217;<strong>amélioration continue par petit pas</strong>, qui s&#8217;appuie sur :
<ul>
<li>amélioration des flux : cf. théorie des contraintes</li>
<li>rendre le système prédictible : cf. méthode 6 Sigma</li>
<li>réduire les limites du tableau Kanban : cf. muda de Lean</li>
</ul>
</li>
<li>existence de 2 types de limites :
<ul>
<li>limites supérieures : les limites classiques Kanban, au sens capacité maximum de prise en charge pour un état donné</li>
<li>limites inférieures, utilisées comme signaux déclencheur d&#8217;une action de planification &#8220;juste à temps&#8221;</li>
</ul>
</li>
<li>nécessité de mettre en place et de suivre des indicateurs, qui viendront alimenter la réflexion</li>
<li>importance d&#8217;une démarche pragmatique et collaborative : il ne faut pas s&#8217;interdire de tester les propositions de l&#8217;équipe.</li>
</ul>
<p style="text-align: center;"><img class="aligncenter" style="vertical-align: middle;" title="Fondamentaux Lean" src="http://blog.ippon.fr/wp-content/uploads/2011/06/IMAG0018.jpg" alt="Fondamentaux Lean" width="424" height="254" /></p>
<h2>Devops &amp; Kanban : Getting to one button deploy using Kanban</h2>
<p>Dominica a présenté à cette occasion son propre retour d&#8217;expérience au sein de Corbis, où elle a occupé un poste de responsable des déploiements (intégré à l&#8217;équipe de développement). Elle a travaillé à cette occasion sur un certain nombre de problématiques tournant autour de la durée des builds applicatifs, de la disponibilité des environnements et des déploiements et nous a expliqué en quoi l&#8217;utilisation de Kanban avait permis aux équipes d&#8217;améliorer leurs processus de travail. Au final les équipes ont gagné en compétence, en tranquillité et ont pu se concentrer sur les aspects essentiels de leur métier au lieu de passer leur temps à parer au plus urgent.</p>
<p>La mise en place s&#8217;est faite par étapes successives, démarrant assez classiquement par une phase d&#8217;identification des objectifs par l&#8217;équipe et un état des lieux de l&#8217;existant :</p>
<p><img class="alignnone" src="http://blog.ippon.fr/wp-content/uploads/2011/06/IMAG0025.jpg" alt="" width="382" height="229" /><img src="http://blog.ippon.fr/wp-content/uploads/2011/06/IMAG0029.jpg" alt="" width="382" height="229" /></p>
<p>Dominica a ensuite fait un rappel des principes Kanban :</p>
<p><img class="aligncenter" src="http://blog.ippon.fr/wp-content/uploads/2011/06/IMAG0030.jpg" alt="" width="424" height="254" /></p>
<p>Concrètement l&#8217;introduction de Kanban a donné lieu à :</p>
<ul>
<li>la prise en compte du déploiement dans le tableau de suivi de l&#8217;équipe de développement (ajout d&#8217;un état &#8220;build ready&#8221;)</li>
<li>une analyse du temps de build (identification des différentes tâches, y compris recherche d&#8217;anomalies), et un suivi de son évolution</li>
<li>l&#8217;organisation d&#8217;une réunion mensuelle d&#8217;une durée de 2h, permettant à l&#8217;équipe Déploiement de faire un point sur ses pratiques (&#8220;the good, the bad, the embarrassing&#8221;). Les équipes de développements, ainsi que les clients internes étaient présents. Cette réunion était alimentée notamment par des données financières et la liste des demandes à venir.</li>
<li>la création d&#8217;une ligne de suivi dédiée aux travaux de maintenance sur le tableau Kanban</li>
<li>la remise en question de la politique de merge initiale, latitude donnée aux équipes afin de mettre aux points et tester de nouvelles approches</li>
<li>la mise en place d&#8217;une fenêtre de &#8220;freeze&#8221; après chaque mise en production, pendant laquelle production et recette sont parfaitement identiques (aide à la résolution des anomalies constatées en production suite à la MEP)</li>
<li>l&#8217;organisation d&#8217;une session de &#8220;discussions&#8221; après chaque point quotidien, afin de limiter les interruptions en cours de journée et d&#8217;encourager les échanges</li>
</ul>
<p><img title="Devops &amp; Kanban : Getting to one button deploy using Kanban : changes to release" src="http://blog.ippon.fr/wp-content/uploads/2011/07/IMAG0049.jpg" alt="Devops &amp; Kanban : Getting to one button deploy using Kanban : changes to release" width="382" height="229" /><img title="Devops &amp; Kanban : Getting to one button deploy using Kanban : changes &amp; improvements" src="http://blog.ippon.fr/wp-content/uploads/2011/07/IMAG0050.jpg" alt="Devops &amp; Kanban : Getting to one button deploy using Kanban : changes &amp; improvements" width="382" height="229" /><img title="Devops &amp; Kanban : Getting to one button deploy using Kanban : fear driven out" src="http://blog.ippon.fr/wp-content/uploads/2011/07/IMAG0051.jpg" alt="Devops &amp; Kanban : Getting to one button deploy using Kanban : fear driven out" width="382" height="229" /></p>
<p>Les temps forts et phrases à retenir :</p>
<ul>
<li>au début était le CDD (&#8220;Chaos Driven Development&#8221;) &#8230;</li>
<li>&#8220;on ne peut pas être bon si on passe tout son temps à éteindre des incendies&#8221;</li>
<li>&#8220;transparency = Trust&#8221;, &#8220;Vulnerability = empathy&#8221;, &#8220;focus on the system, not the individual&#8221;</li>
<li>&#8220;developers incentivized by making change / Ops incentivized by keeping production stable&#8221;</li>
<li>&#8220;quality doesn&#8217;t happen on 5 hours of sleep&#8221;</li>
<li>&#8220;M is for Merge : tolerance for process exploration&#8221; concernant la mise au point d&#8217;une politique de merge adaptée</li>
<li>&#8220;Improvements were not part of a project plan : they were made as part of a continous improvement policy&#8221;.</li>
<li>&#8220;Management must create a way for improvements to occur &#8211; they are not free&#8221;</li>
<li>&#8220;A focus on cutting costs actually results in higher costs.&#8221;</li>
</ul>
<p>Elle a abordé aussi rapidement l&#8217;exemple de Spotify, qui constitue un autre bel exemple de l&#8217;utilisation de Kanban :</p>
<ul>
<li>15% du temps des équipes est provisionné sur les travaux d&#8217;amélioration continue</li>
<li>démarche bénéficiant d&#8217;un soutien très fort de la part du management au plus haut niveau</li>
<li>investissement rentable : pas de dette technique identifiée</li>
<li>une personne de l&#8217;équipe est dédiée à la gestion des problèmes et incidents, afin de protéger le reste de l&#8217;équipe des perturbations quotidiennes</li>
<li>pratique du &#8220;cross training&#8221; au sein de l&#8217;équipe : la montée en compétence de l&#8217;ensemble de l&#8217;équipe est un élément fort</li>
</ul>
<p>En bonus</p>
<ul>
<li>A lire : <ins><a href="https://www.amazon.fr/Death-Meeting-Leadership-Solving-Business/dp/0787968056/ref=sr_1_5?ie=UTF8&amp;qid=1309015597&amp;sr=8-5" hreflang="en">Death by Meeting</a> </ins>par Patrick Lencioni.</li>
<li>Pour en savoir plus sur Kanban et DevOps : group Yahoo!  <ins><a href="http://tech.groups.yahoo.com/group/kanbanops/" hreflang="en">KanbanOps</a> </ins></li>
<li>Suivre Dominica DeGrandis sur Twitter :  <ins><a href="https://twitter.com/#!/dominicad">@dominicad</a></ins></li>
</ul>
<h2>Scrum &amp; Kanban, tirer le meilleur des deux</h2>
<p>Antoine et Fabrice ont présenté une approche mixant les apports de Scrum et Kanban : &#8220;ScrumBan&#8221;. Ils ont rappelé les points communs et les différences entre ces deux méthodes, avant d&#8217;expliquer comment les combiner afin d&#8217;en tirer le meilleur parti.</p>
<p>Les temps forts et phrases à retenir :</p>
<ul>
<li>Ne soyez pas dogmatiques ! Essayez par vous-même ! Soyez agiles !</li>
<li>La chose la plus importante n&#8217;est pas votre processus,. <strong>La chose la plus importante est votre processus pour améliorer votre processus.</strong></li>
</ul>
<p><img title="Scrum &amp; Kanban : utilisation des tableaux" src="http://blog.ippon.fr/wp-content/uploads/2011/08/IMAG0069.jpg" alt="Scrum &amp; Kanban : utilisation des tableaux" width="382" height="229" /><img src="http://blog.ippon.fr/wp-content/uploads/2011/08/IMAG0070.jpg" alt="Scrum &amp; Kanban : combiner les 2 approches" width="382" height="229" /></p>
<p><img title="Scrum &amp; Kanban : des niveaux d'utilisations différents" src="http://blog.ippon.fr/wp-content/uploads/2011/08/IMAG0072.jpg" alt="Scrum &amp; Kanban : des niveaux d'utilisations différents" width="382" height="229" /></p>
<p>Je ne vais pas plagier leur très intéressante présentation, je vais me contenter de vous indiquer que les slides de la présentation sont <a href="http://www.slideshare.net/claudeaubry/kanban-scrum-tirer-le-meilleur-des-2">disponibles sur slideshare </a>. N&#8217;hésitez pas à lire <a href="http://www.infoq.com/minibooks/kanban-scrum-minibook">Kanban and Scrum &#8211; making the most of both</a>, dont il existe une traduction en français que nous devons justement à Claude Aubry, Frédéric Faure, Antoine Vernois &amp; Fabrice Aimetti.</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/0unV5xRFYKk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/09/01/retours-sur-la-soiree-devops-scrum-et-kanban-du-french-scrum-user-group/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/09/01/retours-sur-la-soiree-devops-scrum-et-kanban-du-french-scrum-user-group/</feedburner:origLink></item>
		<item>
		<title>LMAX : 6 millions d’opérations par seconde</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/feBumoHTeNM/</link>
		<comments>http://blog.ippon.fr/2011/08/29/lmax-6-millions-doperations-par-seconde/#comments</comments>
		<pubDate>Mon, 29 Aug 2011 13:43:26 +0000</pubDate>
		<dc:creator>Christophe PARAGEAUD</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Concurrency]]></category>
		<category><![CDATA[CPU]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[LMAX]]></category>
		<category><![CDATA[Threads]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=3536</guid>
		<description><![CDATA[ <p>Pour rebondir sur le challenge USI, voici un cas à part dans les architectures hautes performances et haute disponibilité.</p> <p>LMAX (http://www.lmaxtrader.co.uk : plate forme de trading) va à contre courant avec son architecture et montre que l&#8217;on peut faire du XTP uniquement avec le JDK mais non sans revoir quelques idées reçues.</p> <p>En effet alors <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/08/29/lmax-6-millions-doperations-par-seconde/">LMAX : 6 millions d&#8217;opérations par seconde</a></span>]]></description>
			<content:encoded><![CDATA[<div class="mceTemp" style="text-align: center;"><img class="alignleft size-full wp-image-3564" title="logo" src="http://blog.ippon.fr/wp-content/uploads/2011/08/logo.bmp" alt="Disruptor" /></div>
<p>Pour rebondir sur le challenge USI, voici un cas à part dans les architectures hautes performances et haute disponibilité.</p>
<p>LMAX (<a href="http://www.lmaxtrader.co.uk">http://www.lmaxtrader.co.uk</a> : plate forme de trading) va à contre courant avec son architecture et montre que l&#8217;on peut faire du XTP uniquement avec le JDK mais non sans revoir quelques idées reçues.</p>
<p>En effet alors que la tendance est :</p>
<ol>
<li>coté hardware, à multiplier le nombre de core plutôt que leur puissance brute,</li>
<li>coté logiciel à introduire le multi threading,</li>
</ol>
<p>LMAX est spécialisé dans le passage d&#8217;ordres de bourse ce qui suppose du temps réel pour l&#8217;affichage des cotations, un volume de transactions très important, le respect de l&#8217;ordonnancement des ordres et un temps réduit pour leur exécution.</p>
<p>Leur architecture est dimensionnée pour des millions d&#8217;utilisateurs, que ce soit par leur site ou bien en utilisant les API publiées.</p>
<p>LMAX peut gérer 6 millions d&#8217;ordres par seconde avec une machine tout à fait courante (2 CPU, 4 core à 3Ghz et 32Go RAM) et le tout en Java et sans framework supplémentaire.</p>
<p><span id="more-3536"></span></p>
<p>LMAX est une filiale de Betfair (site de paris en ligne) et devant les difficultés de mise au point et de maintenance ils ont décidé de revoir complètement l&#8217;architecture mise en place pour construire LMAX.</p>
<p>Ils ont tout d&#8217;abord pensé que le multithreading serait la solution idéale.</p>
<p>Après les premiers tests ils ont fait le choix délibéré de ne pas recourir au multi-thread qui comporte les inconvénients suivants :</p>
<ul style="list-style-type: circle;">
<li>Plus complexe à mettre en œuvre</li>
<li>Plus complexe à tester</li>
<li>Coût hardware plus élevé</li>
</ul>
<p>On peut modérer ce dernier point car le nombre de cœurs va directement donner le nombre de traitements possibles comme nous le verrons par la suite.</p>
<p>Plus que l&#8217;architecture mise en place, se sont les observations faites qui sont intéressantes (sur Java, sur les CPU, …) et qui parfois remettent en cause tout ce que l&#8217;on pouvait penser jusqu&#8217;alors.</p>
<p>Leur choix d&#8217;architecture et surtout les tests de performances les ont amené à faire une analyse très poussée des CPU modernes.</p>
<p>Ils se sont rendu compte que ce qui est communément admis (et sans doute vrai avec les anciens processeurs) ne l&#8217;est plus du tout aujourd&#8217;hui.</p>
<p>Ils ont donc conçu un système en adéquation avec le fonctionnement des processeurs modernes (c&#8217;est ce qu&#8217;ils nomment « mechanical sympathy »).</p>
<p>Leur besoin extrême en performance les ont entraîné bien au delà des analyses habituelles.</p>
<p>Pour vous donner une idée on entend bien souvent la maxime suivante « disk is the new tape » sous entendu que les temps de lecture/écriture sur disque sont très pénalisants en terme de performances et que les capacités actuelles des machines (fiabilité, volume) encouragent une utilisation de la mémoire uniquement.</p>
<p>Pour LMAX même les performances de la mémoire principale (RAM) ne sont pas suffisantes et ils ont tout fait pour que leur code privilégie le cache du CPU (leur code est déclaré cache safe).</p>
<p style="text-align: left;"><span style="color: #333399;">Comparaison des coûts de lecture en fonction du type de mémoire</span></p>
<table border="1" cellspacing="0" cellpadding="1" align="center">
<tbody>
<tr align="center" valign="middle">
<th><strong>Latency from CPU to&#8230;</strong></th>
<th><strong>Approx. number<br />
of CPU cycles</strong></th>
<th><strong>Approx. time<br />
in nanoseconds</strong></th>
</tr>
<tr align="center" valign="middle">
<td style="text-align: center;"> NETWORK</td>
<td style="text-align: center;"> 240,000,000 cycles</td>
<td style="text-align: center;"></td>
</tr>
<tr align="center" valign="middle">
<td style="text-align: center;"> DISK</td>
<td style="text-align: center;">41,000,000 cycles</td>
<td style="text-align: center;"></td>
</tr>
<tr align="center" valign="middle">
<td style="text-align: center;"> Main memory</td>
<td style="text-align: center;">250 cycles</td>
<td style="text-align: center;">~65ns</td>
</tr>
<tr align="center" valign="middle">
<td style="text-align: center;"> QPI bus transit<br />
between sockets</td>
<td style="text-align: center;"></td>
<td style="text-align: center;">~20ns</td>
</tr>
<tr align="center" valign="middle">
<td style="text-align: center;"> L3 cache</td>
<td style="text-align: center;">~40-45 cycles</td>
<td style="text-align: center;">~15ns</td>
</tr>
<tr align="center" valign="middle">
<td style="text-align: center;"> L2 cache</td>
<td style="text-align: center;">~10 cycles</td>
<td style="text-align: center;">~3ns</td>
</tr>
<tr align="center" valign="middle">
<td style="text-align: center;">L1 cache</td>
<td style="text-align: center;">~3-4 cycles</td>
<td style="text-align: center;">~1ns</td>
</tr>
<tr align="center" valign="middle">
<td style="text-align: center;">Register</td>
<td style="text-align: center;">1 cycle</td>
<td style="text-align: center;">&lt;1ns</td>
</tr>
</tbody>
</table>
<p>Rapidement leur exigence de performance les a obligé a abandonner tout lock de ressource car synonyme de « context switch » (en basculant d&#8217;un thread à l&#8217;autre le CPU peut écraser les valeurs contenues dans le cache).</p>
<p>En effet en cas de lock, le système donne la main à un autre thread en attendant la libération de la ressource. Ce qui implique un changement de contexte (CPU et données) et le contenu du cache est donc susceptible d&#8217;être écrasé avant d&#8217;être de nouveau chargé.</p>
<p>Il ne suffit donc pas d&#8217;utiliser les caches du processeur, encore faut il comprendre et maîtriser leur fonctionnement.</p>
<p>En terme de méthodologies rien de révolutionnaire, bien au contraire, puisqu&#8217;ils approuvent et cautionnent le TDD ainsi que la notation UML.</p>
<h2>Problématiques et phénomènes analysés :</h2>
<ul style="list-style-type: circle;">
<li>False sharing</li>
<li>Memory barrier</li>
<li>Context switch</li>
<li>CAS</li>
<li>Cache line</li>
</ul>
<p>Leur conclusion vis à vis des méthodes existantes :</p>
<ol>
<li>Les queues (java) sont coûteuses (temps de traitement et lock des ressources)</li>
<li>Le multi-threading est coûteux (contentions sur les ressources communes) et difficile a mettre en œuvre.</li>
<li>De surcroit le multi-threading n&#8217;est pas le plus efficace en terme de performances.</li>
</ol>
<p>Évidemment leur conclusion est très liée au contexte de leur étude et leur architecture ne pourra convenir à tous.</p>
<p>Parmi les contraintes ont peut citer :</p>
<p style="padding-left: 30px;">Les messages doivent être lus séquentiellement (un consommateur ne choisi pas ses messages)</p>
<p style="padding-left: 30px;">Chaque message doit donc avoir un sens au niveau fonctionnel (et non pas un ensemble de messages).</p>
<p>Cerise sur le gâteau, en plus d&#8217;une transparence assez rare sur leur architecture, ils ont décidé de faire partager leur framework qui est maintenant disponible en open source <a href="http://code.google.com/p/disruptor/">LMAX Disruptor</a>.</p>
<p>Ce qu&#8217;a mis en œuvre LMAX c&#8217;est une façon plus rapide de partager les données entre les threads, sans recourir aux mécanismes utilisés habituellement (variables synchronisées).</p>
<p>Particularités de l&#8217;architecture :</p>
<ul style="list-style-type: circle;">
<li>Utilisation du pattern Disruptor</li>
<li>Pas de base de données, tout en mémoire</li>
<li>Pas de queuing/messaging classique</li>
<li>Pas de locking</li>
</ul>
<p>NB : l&#8217;avantage de ne pas recourir à un SGBD, en plus de n&#8217;avoir qu&#8217;un seul langage de programmation (exit SQL, EJBQL, etc.), est que donc seule une JVM est nécessaire (Java 5+). Il en ressort une architecture simplifiée sans pour autant sacrifier la disponibilité.</p>
<h2><span>Pattern Disruptor</span></h2>
<p>Tout l&#8217;intérêt du pattern Disruptor réside dans la façon de produire et consommer des messages stockés dans le Ring Buffer.</p>
<p><a href="http://blog.ippon.fr/2011/08/29/lmax-6-millions-doperations-par-seconde/disruptor/" rel="attachment wp-att-3687"><img class="alignnone size-full wp-image-3687" title="Disruptor" src="http://blog.ippon.fr/wp-content/uploads/2011/08/Disruptor.png" alt="" width="574" height="158" /></a></p>
<p>Les producteurs, le Ring Buffer et les consommateurs sont chacun dans des threads différents.</p>
<p style="padding-left: 30px;"><strong>Les acteurs</strong> : Producteur, Consommateur</p>
<p style="padding-left: 30px;"><strong>Les objets</strong> : RingBuffer, Barrier</p>
<p style="padding-left: 30px;"><strong>Les stratégies</strong> : Wait, Claim</p>
<p>Cette structuration du code oblige a certaines adaptations.</p>
<p>Le traitement d&#8217;un message (le cœur du process) doit être le plus rapide possible. Si il s&#8217;agit d&#8217;un traitement long (persistance, IO, journalisation) ce traitement doit être déporté dans un process indépendant qui ne ralentira pas les autres. Ces traitements sont placés dans les consommateurs.</p>
<p>C&#8217;est le royaume de l&#8217;asynchronisme.</p>
<h2>Un peu de théorie</h2>
<h3>Compare and Swap (CAS)</h3>
<p>De nombreux processeurs modernes possèdent une instruction qui effectue une opération atomique de type comparaison et échange ou compare-and-swap (CAS) au niveau matériel.</p>
<p>Utile afin d&#8217;éviter l&#8217;utilisation des techniques habituelles d&#8217;accès concurrents telles que Sémaphores et Mutex.</p>
<p>Le principe est assez simple à implémenter en Java (ici c&#8217;est purement théorique puisque l&#8217;opération est réalisée par le CPU et non par code).</p>
<pre class="brush: java; title: ; notranslate">
@ThreadSafe
public class SimulatedCAS {
	@GuardedBy(&quot;this&quot;)
	private int value;

	public synchronized int get() {
		return value;
	}

	public synchronized int compareAndSwap(int expectedValue, int newValue) {
		int oldValue = value;
		if (oldValue == expectedValue)
			value = newValue;

		return oldValue;
	}

	public synchronized boolean compareAndSet(int expectedValue,
			int newValue) {
		return (expectedValue == compareAndSwap(expectedValue, newValue));
	}

}
</pre>
<p>Chaque client conserve l&#8217;ancienne valeur et lorsqu&#8217;il souhaite la modifier il suffit de comparer cette ancienne valeur avec la valeur actuelle et si elle est différente c&#8217;est que quelqu&#8217;un d&#8217;autre est passé par là.</p>
<h4>Support CAS dans la JVM</h4>
<p>Avant Java 5, il était impossible de forcer le processeur à utiliser une instruction CAS (à moins d&#8217;utiliser du code natif).Depuis un nouveau package à été introduit &#8220;java.util.concurrent.atomic&#8221;.</p>
<p>Les classes associées sont AtomicBoolean, AtomicInteger, AtomicLong, et AtomicReference pour les références objet.</p>
<p>CAS est plus rapide qu&#8217;un lock car :</p>
<ul style="list-style-type: circle;">
<li>Une seule instruction pour deux opérations (mise à jour conditionnelle)</li>
<li>Pas de context switch contrairement aux locks.</li>
</ul>
<p>Toutefois CAS doit se limiter aux opérations simples sur des objets simples (incrément d&#8217;un compteur par exemple) car il peut s&#8217;avérer très complexe à maitriser (et pas plus rapide plus que les locks).</p>
<p style="text-align: left;"><span style="color: #333399;">Comparaison des temps de traitement (incrément d&#8217;un long 500 millions de fois)</span></p>
<table border="1" cellspacing="0" cellpadding="1" align="center">
<tbody>
<tr>
<th style="text-align: center;"><strong>Method</strong></th>
<th style="text-align: center;"><strong>   Time (ms)   </strong></th>
</tr>
<tr align="center" valign="middle">
<td style="text-align: center;"> Single thread</td>
<td style="text-align: center;"> 300</td>
</tr>
<tr align="center" valign="middle">
<td style="text-align: center;">Single thread with lock</td>
<td style="text-align: center;">10000</td>
</tr>
<tr align="center" valign="middle">
<td style="text-align: center;">Two threads with lock</td>
<td style="text-align: center;">224000</td>
</tr>
<tr align="center" valign="middle">
<td style="text-align: center;">  Single thread with CAS</td>
<td style="text-align: center;">5700</td>
</tr>
<tr align="center" valign="middle">
<td style="text-align: center;">Two threads with CAS</td>
<td style="text-align: center;">30000</td>
</tr>
<tr align="center" valign="middle">
<td style="text-align: center;">Single thread with volatile write</td>
<td style="text-align: center;">4700</td>
</tr>
</tbody>
</table>
<h3>Memory Barrier</h3>
<p>Les barrières mémoires sont une instruction CPU qui permet d&#8217;isoler une partie des instructions du reste du code.</p>
<p>Le compilateur mais aussi le CPU peuvent réorganiser les instructions (changer l&#8217;ordre d&#8217;exécution) tant que le résultat final est le même pour des raisons de performances.</p>
<p>Les barrières mémoires indiquent au CPU et au compilateur que les instructions entourées de barrières ne doivent pas en sortir et ne doivent pas être réorganisées. De plus lorsque le CPU franchi une barrière il rafraichit systématiquement ces caches afin d&#8217;être certain que le code travaille avec la dernière valeur d&#8217;une données.</p>
<p>Le Java Memory Model précise que lorsque l&#8217;on utilise des données volatiles, alors le compilateur insère automatiquement une barrière d&#8217;écriture après une modification du champ et une barrière de lecture avant toute lecture.</p>
<p>Les barrière mémoire apporte donc une certaine sécurité dans le code pour un coût certes non négligeable mais inférieure à un lock.</p>
<p>C&#8217;est peut être la réhabilitation/redécouverte du mot clé volatile en Java.</p>
<h3>Cache Line/padding/false sharing</h3>
<p>La mémoire est stockée dans le processeur dans ce que appelle des « caches lines » (blocs contigus de mémoire).</p>
<p>Ces blocs font de 32 à 256 octets en fonction des processeurs (64 octets est la valeur la plus courante).</p>
<p>Ainsi les données stockées dans ces caches ne sont pas isolées mais sont traitées par bloc, donc si deux variables sont contenues dans le même bloc alors elles sont traitées de manière commune.</p>
<p>Ce qui signifie qu&#8217;un lock sur une des variables bloquera obligatoirement toutes les données du bloc.</p>
<p>C&#8217;est ce qu&#8217;on appelle le « false sharing ».</p>
<p>Ce qui est acceptable pour un traitement mono-thread, l&#8217;est beaucoup moins lorsque l&#8217;on travaille en multi-threads.</p>
<p>Dans le cas de l&#8217;architecture mise en place par LMAX et le pattern Disruptor un des composants que l&#8217;on doit absolument protéger est le Ring Buffer et en particulier le curseur. De manière générale il s&#8217;agit des variables de type volatile.</p>
<p>Il existe heureusement une technique pour s&#8217;affranchir de ce problème, il s&#8217;agit du padding (remplissage).</p>
<p>Plutôt que de déclarer uniquement notre curseur on va déclarer tout un ensemble de variable qui ne serviront pas mais permettront de s&#8217;assurer que l&#8217;ensemble remplisse totalement la taille du cache line.</p>
<p><span style="color: #333399;">Extrait du code du RingBuffer</span></p>
<pre class="brush: java; gutter: false; title: ; notranslate">private volatile long cursor = INITIAL_CURSOR_VALUE;
public long p8, p9, p10, p11, p12, p13, p14; // cache line padding
</pre>
<p>Au lieu d&#8217;un seul long ce sont 8 longs qui sont déclarés soit 8*taille d&#8217;un long : 64 octets.</p>
<p>Sur des processeurs utilisant des blocs de 64 octets ont est assuré que le bloc n&#8217;est pas partagés par plusieurs variables sensibles (sur une JVM 32 bits).</p>
<p>On pourrait croire cette technique contre productive (déclarer plus de variables) que ce dont on a réellement besoin mais les tests menés tendent à prouver le contraire.</p>
<p>Aperçu des performances obtenues en éliminant le false sharing (<a href="http://mechanical-sympathy.blogspot.com/2011/07/false-sharing.html">http://mechanical-sympathy.blogspot.com/2011/07/false-sharing.html</a>).</p>
<p>NB : Comme il n&#8217;est décidément pas simple d&#8217;obtenir le meilleur de Java, Java 7 est plus intelligent que ces prédécesseurs (en tout cas le compilateur) et élimine les variables inutilisées rendant obsolète la technique utilisée ci dessus.</p>
<p>Heureusement LMAX travaille déjà sur une parade (<a href="http://mechanical-sympathy.blogspot.com/2011/08/false-sharing-java-7.html">http://mechanical-sympathy.blogspot.com/2011/08/false-sharing-java-7.html</a>) en attendant un jour que Java, à l&#8217;image du C++ et du C# pour les structures, permette au développeur de gérer les caches lines pour les structures).</p>
<h2>Disruptor</h2>
<h3>Ring Buffer</h3>
<p>Le Ring Buffer est l&#8217;élément central puisque c&#8217;est lui qui stocke les messages. C&#8217;est une implémentation maison des collections Java. Afin de le rendre le plus performant possible, il est déchargé de certaines opérations habituellement dévolues à ce type de structure (cycle de vie des données, …).<br />
Caractéristiques :</p>
<ul style="list-style-type: circle;">
<li>Buffer de taille fixe (tableau d&#8217;Entry).</li>
</ul>
<ul>
<li>Si la file est pleine on remplace le premier enregistrement (principe FIFO).</li>
</ul>
<p><a href="http://blog.ippon.fr/2011/08/29/lmax-6-millions-doperations-par-seconde/rb/" rel="attachment wp-att-3727"><img class="alignnone size-full wp-image-3727" title="RB" src="http://blog.ippon.fr/wp-content/uploads/2011/08/RB.png" alt="" width="307" height="241" /></a></p>
<p>Deux pointeurs sont utilisés :</p>
<p style="padding-left: 30px;">Cursor : Dernière insertion/modification d&#8217;un consommateur ou d&#8217;un producteur.</p>
<p style="padding-left: 30px;">Next : Premier emplacement disponible dans le Ring Buffer.</p>
<p>On accède à un message par son numéro de séquence (long et non Long car plus rapide).</p>
<p>Chaque acteur accédant au Ring Buffer possède son propre compteur (emplacement actuellement accédé du Ring Buffer) et évidemment il est possible de synchroniser un producteur et un consommateur (un acteur gère son propre compteur pour les écritures mais peut lire les autres compteurs).</p>
<p>Ceci permet de gérer les multiples accès au Ring Buffer.</p>
<p>Le numéro de séquence n&#8217;est pas le numéro de slot du Ring Buffer mais un compteur incrémenté par le producteur (il augmente toujours).</p>
<p>Une fois le message consommé, l&#8217;emplacement n&#8217;est pas libéré (vidé), il est simplement disponible pour un nouveau message.</p>
<p>Un message est considéré comme consommé seulement si un accusé de réception est transmis assurant une certaine robustesse au système.</p>
<p>Une fois consommé le message est sous la responsabilité du consommateur (différence avec du queuing par exemple).</p>
<h3>Messages (Entry)</h3>
<p>Les éléments stockés sont des Entry (classe à surcharger obligatoirement, seule une classe abstraite est fournie) qui peuvent être soit directement des valeurs, soit des pointeurs vers ces valeurs. C&#8217;est pour cela que seule une classe abstraite est fournie, l&#8217;implémentation étant trop liée au contexte du projet.</p>
<p><span style="color: #333399;">Exemple simple ou le message est un long :</span></p>
<pre class="brush: java; title: ; notranslate">
public final static class ValueEntry extends AbstractEntry {
		private long value;

		public long getValue() {
			return value;
		}

		public void setValue(final long value) {
			this.value = value;
		}

		public final static EntryFactory ENTRY_FACTORY = new EntryFactory() {
			public ValueEntry create() {
				return new ValueEntry();
			}
		};
}
</pre>
<h3>Consommateur :</h3>
<p>Un même message peut être consommé par différents consommateurs en parallèle ce qui permet par exemple de gérer les logs en parallèle du traitement.</p>
<p>Définit comment est transmis le message : par copie ou par référence.</p>
<p>On peut chainer les consommateurs, ainsi un consommateur peut attendre qu&#8217;un premier consommateur ait traité la donnée avant d&#8217;intervenir (transformation, complétion du message par exemple).</p>
<p>L&#8217;implémentation d&#8217;un consommateur n&#8217;est pas aisé mais est facilité par la présence d&#8217;une implémentation par défaut « BatchConsumer » qui conviendra dans bien des cas.</p>
<p>Ainsi le consommateur implémente simplement l&#8217;interface &#8220;BatchHandler&#8221; (callback invoqué lorsqu&#8217;une nouvelle entrée est disponible), soit l&#8217;implémentation de la méthode « onAvailable(T entry) » qui sera appelée lorsqu&#8217;un nouveau message aura été déposé dans le Ring Buffer.</p>
<pre class="brush: java; title: ; notranslate">
 /*** Callback interface to be implemented for processing {@link AbstractEntry}s as they become
  * available in the {@link RingBuffer}
  * @see BatchConsumer#setExceptionHandler(ExceptionHandler) if you want to handle exceptions
  * propagated out of the handler.
  *
  * @param AbstractEntry implementation storing the data for sharing during exchange or
  * parallel coordination of an event.
  */
    public interface BatchHandler {
    /**
     * Called when a publisher has committed an {@link AbstractEntry} to the {@link RingBuffer}
     *
     * @param entry committed to the {@link RingBuffer}
     * @throws Exception if the BatchHandler would like the exception handled further up
     * the chain.
     */
    void onAvailable(T entry) throws Exception;

    /**
     * Called after each batch of items has been have been processed before the next waitFor
     * call on a {@link ConsumerBarrier}.
     *
     * This can be taken as a hint to do flush type operations before waiting once again on
     * the {@link ConsumerBarrier}.
     * The user should not expect any pattern or frequency to the batch size.
     * @throws Exception if the BatchHandler would like the exception handled further
     * up the chain. */
    void onEndOfBatch() throws Exception;
    }
</pre>
<h3>Producteur :</h3>
<p>C&#8217;est lui qui insère les messages dans le Ring Buffer.</p>
<p>Son interaction avec le Ring Buffer est le plus souvent assez simple :</p>
<p>Effectue une demande d&#8217;emplacement libre,</p>
<p>Commit le message une fois valorisé, le message est alors visible de tous.</p>
<h3>Productor Barrier :</h3>
<p>L&#8217;objet est obligatoire pour insérer des messages dans le Ring Buffer.</p>
<p>Les producteurs ne dialoguent pas directement avec le Ring Buffer mais avec le ProductorBarrier.</p>
<p>La ProductorBarrier est créée par le Ring Buffer.</p>
<h3>Consumer Barrier :</h3>
<p>Obligatoire pour consommer des messages.</p>
<p>Un consommateur accède au Ring Buffer au travers d&#8217;un ConsumerBarrier.</p>
<p>La ConsumerBarrier est créée par le Ring Buffer</p>
<h3>Consommation d&#8217;un message :</h3>
<p>Le consommateur doit connaître le numéro de séquence avant de consommer un message.</p>
<p>il peut :</p>
<ol>
<li>Interroger le Ring Buffer pour connaitre le curseur courant et obtenir le message par ce numéro de séquence.</li>
<li>Obtenir le prochain message disponible.</li>
<li>Gérer son propre compteur et interroger le Ring Buffer pour connaitre le nombre de messages disponibles avec un numéro de séquence supérieur (et les récupérer en masse).</li>
</ol>
<p>En théorie les consommateurs ne font que lire les messages, toutefois il est possible pour un consommateur d&#8217;écrire dans le Ring Buffer. La condition est qu&#8217;une entrée ne peut être modifiée que par un seul consommateur.</p>
<h3>Garbage Collecteur et Ring Buffer :</h3>
<p>Le Ring Buffer est un tableau d&#8217;Entry.</p>
<p>Sa taille est fixe et allouée dès le début, la probabilité pour que l&#8217;ensemble du Ring Buffer soit contenu dans des espaces contigus est donc forte.</p>
<p>Le Ring Buffer permet de bénéficier du cache striding.</p>
<p>Les messages consommés sont remplacés par d&#8217;autres au besoin afin de limiter la consommation de la mémoire.</p>
<p>Les messages sont évidemment recyclés par le Garbage Collector mais pas le Ring Buffer.</p>
<p>Les objets ayant une durée de vie courte ou les données qui persistent tout le temps de vie d&#8217;une application ne sont pas problématique en terme de performance du Garbage Collector.</p>
<p>Ceux qui posent problèmes sont ceux qui peuvent survivre à un Garbage Collector pour être nettoyés ensuite.</p>
<p>Concrètement ce ne sont ni les variables locales ni les variables globales mais bien celles qui s&#8217;échangent entre fonctions ou entre thread.</p>
<p>LMAX a donc cherché à les minimiser.</p>
<h3>Stratégies</h3>
<p>Lorsque l&#8217;on crée un Ring Buffer on va préciser la manière dont les messages seront consommés (consommateur) et la gestion des numéro de séquence (producteur)</p>
<h4 style="padding-left: 30px;">WaitStrategy</h4>
<p style="padding-left: 30px;">Stratégie utilisée par le consommateur en attente de messages postés par le producteur.</p>
<p style="padding-left: 30px;">BLOCKING</p>
<p style="padding-left: 60px;">Stratégie classique qui utilise un lock tant que le message n&#8217;est pas disponible, bloque le consommateur mais ne consomme pas de CPU.</p>
<p style="padding-left: 60px;">C&#8217;est la stratégie par défaut.</p>
<p style="padding-left: 30px;">YIELDING</p>
<p style="padding-left: 60px;">Cette stratégie utilise un Thread.yield() pour rendre la main au CPU évitant ainsi de bloquer les traitements.</p>
<p style="padding-left: 60px;">Cette stratégie est évidemment moins rapide mais permet de préserver les ressources.</p>
<p style="padding-left: 30px;">BUSY_SPIN</p>
<p style="padding-left: 60px;">On attend tant que la ressource n&#8217;est pas disponible mais sans poser de lock sur la ressource (la plus rapide mais mobilise CPU et consommateur).</p>
<h4 style="padding-left: 30px;">ClaimStrategy</h4>
<p style="padding-left: 30px;">Stratégie utilisée pour récupérer le prochain numéro de séquence libre (producteur).</p>
<p style="padding-left: 30px;">MULTI_THREADED : un thread pour chaque demande.</p>
<p style="padding-left: 60px;">C&#8217;est la stratégie par défaut compatible avec plusieurs producteurs.</p>
<p style="padding-left: 30px;">SINGLE_THREADED : La plus optimisée (un seul thread en écriture).</p>
<h3>Gestion des erreurs :</h3>
<p>La gestion des erreurs est particulière et surprenante.</p>
<p>Leur principe est le suivant : il n&#8217;y a pas d&#8217;erreur ! (les tests sont là pour adapter le code à toutes les éventualités).</p>
<p>Dans leur esprit une entrée (un message), ne doit pénétrer le système qu&#8217;après validation afin d&#8217;être certain qu&#8217;elle pourra être traitée correctement.</p>
<p>En cas de faille du système un autre prend le relai.</p>
<p>Leur framework ne permet pas le retour en arrière (rollback d&#8217;une transaction).</p>
<p>Toutefois pour les plus sceptiques il y a possibilité de surcharger la classe ExceptionHandler pour pouvoir exécuter du code en cas d&#8217;erreur de traitement d&#8217;une Entry.</p>
<p>NB : Seules les exceptions de type RuntimeException mettent fin au programme (après un log).</p>
<h3>Failover :</h3>
<p>Avec un tel système (event processing) il suffit de pouvoir sauvegarder les messages pour pouvoir les rejouer et donc rétablir une plateforme après un crash.</p>
<p>C&#8217;est le système retenu par LMAX. Toutefois afin d&#8217;éviter d&#8217;avoir a rejouer un trop grand nombre de messages et d&#8217;avoir un temps de rétablissement trop important il ont décider de prendre une photo (snapshot) de leur système quotidiennement (état des données en sortie) et de simplement journaliser les événements de la journée.</p>
<p>LMAX a plusieurs systèmes qui tournent en parallèle (3) mais dont un seul n&#8217;est réellement actif.</p>
<p>Chaque message est traité par l&#8217;ensemble des systèmes ce qui oblige à synchroniser les trois nœuds.</p>
<p>Ce système de cluster détecte en permanence si le maître est toujours actif (multicast). Un autre prend le relais en cas de défaillance.</p>
<p>Plus d&#8217;informations dans le Bliki de <a href="http://martinfowler.com/articles/lmax.html">Martin FOWLER</a>.</p>
<h3>Remarques et problématiques :</h3>
<p>Le pattern idéal pour le Disruptor est :</p>
<ol>
<li>Un seul producteur.</li>
<li>Plusieurs consommateurs (dans des threads différents).</li>
<li>Un seul thread par CPU (si 8 cœurs alors 8 threads maximum).</li>
</ol>
<p>Avoir un seul producteur est un gain considérable :</p>
<ul style="list-style-type: circle;">
<li>Pas de contentions sur les écritures du Ring Buffer (donc pas de lock, de CAS, etc..).</li>
<li>Gestion plus simple du curseur (dernier ajout) qui ne dépend que d&#8217;un seul traitement.</li>
<li>Un seul thread responsable des écritures.</li>
<li>Meilleure utilisation du cache CPU.</li>
</ul>
<p>Une amélioration du Disruptor est le batching effect.</p>
<p>Un consommateur conserve le numéro de séquence de la dernière entrée traitée (point de référence) ainsi lorsqu&#8217;il interroge le Ring Buffer pour savoir si un nouvel élément est disponible et que plusieurs entrées ont été mises à jour alors le Ring Buffer envoie l&#8217;ensemble des séquences ce qui permet de les traiter toutes sans multiplier les interrogations du Ring Buffer.</p>
<p>Comment s&#8217;assurer qu&#8217;un message n&#8217;est traité qu&#8217;une seule fois en cas de multiples consommateurs ?</p>
<p>Nativement impossible mais avec un peu d&#8217;ingéniosité on y arrive (par exemple si on utilise deux consommateurs un premier traitera les séquences paires, l&#8217;autre les impaires) en cas de consommateurs plus nombreux on utilisera les modulos.</p>
<p>Dans la majorité des cas un seul Ring Buffer est nécessaire même si les consommateurs sont chainés (contrairement aux queues par exemple) par contre il faut une consumerBarrier par consommateur.</p>
<h3>Comparaison des systèmes possibles (traitement en parallèle)</h3>
<p style="padding-left: 30px;"><em>Multithreading :</em> Lock sur les ressources partagées pour gérer les accès concurrents.</p>
<p style="padding-left: 30px;"><em>SEDA (staged event-driven architecture) :</em> Utilisation de queues pour les ressources partagées.</p>
<p style="padding-left: 30px;"><em>LMAX :</em> Utilisation de RingBuffer (Array non synchronisé) pour les ressources partagées.</p>
<h2>Conclusion</h2>
<p>Nous avons le cas d&#8217;une recherche extrême de la performance.</p>
<p>Heureusement que toutes les applications n&#8217;ont pas besoin de grappiller les millisecondes.</p>
<p>Le modèle choisi par LMAX n&#8217;est surement pas applicable à tous les cas mais il permet de faire évoluer des certitudes :</p>
<ul>
<li>Pour un traitement simple (un calcul) par exemple le multithreading n&#8217;est pas la solution miracle.</li>
<li>Ne partager des ressources que si on ne peut pas faire autrement.</li>
</ul>
<div>Même si la courbe d&#8217;apprentissage n&#8217;est pas très  longue on est loin de la simplicité de Java 7 Fork/Join.</div>
<div>Enfin il semblerait qu&#8217;il n&#8217;y ait pas de solution universelle, j&#8217;en veux pour preuve ce benchmark tiré de <a href="http://vanillajava.blogspot.com/2011/07/synchronized-vs-lock-performance.html">VanillaJava</a>.</div>
<div>Dans ce test on compare les performances des trois techniques suivantes :</div>
<div>
<ul style="list-style-type: circle;">
<li>Synchronized.</li>
<li>Lock.</li>
<li>Volatile (AtomicInteger).</li>
</ul>
</div>
<div>Le tableau présente le temps de traitement en secondes de 25 millions de locks (Java 6U26).</div>
<table border="1" cellspacing="0" cellpadding="1" align="center">
<tbody>
<tr>
<th>Nombre<br />
de Threads</th>
<th>Synchronized<br />
1 compteur</th>
<th>Lock<br />
1 compteur</th>
<th>AtomicInteger<br />
1 compteur</th>
<th>Synchronized<br />
2 compteurs</th>
<th>Lock<br />
2 compteurs</th>
<th>AtomicInteger<br />
2 compteurs</th>
</tr>
<tr align="center" valign="middle">
<td style="text-align: center;">1</td>
<td style="text-align: center;">0.937</td>
<td style="text-align: center;">0.786</td>
<td style="text-align: center;">0.400</td>
<td style="text-align: center;">1.532</td>
<td style="text-align: center;">1.484</td>
<td style="text-align: center;">0.569</td>
</tr>
<tr align="center" valign="middle">
<td style="text-align: center;">2</td>
<td style="text-align: center;">2.766</td>
<td style="text-align: center;">4.597</td>
<td style="text-align: center;">0.676</td>
<td style="text-align: center;">5.398</td>
<td style="text-align: center;">6.355</td>
<td style="text-align: center;">1.278</td>
</tr>
<tr align="center" valign="middle">
<td style="text-align: center;">4</td>
<td style="text-align: center;">3.904</td>
<td style="text-align: center;">1.267</td>
<td style="text-align: center;">0.694</td>
<td style="text-align: center;">6.330</td>
<td style="text-align: center;">2.657</td>
<td style="text-align: center;">1.354</td>
</tr>
<tr align="center" valign="middle">
<td style="text-align: center;">8</td>
<td style="text-align: center;">3.884</td>
<td style="text-align: center;">0.953</td>
<td style="text-align: center;">1.011</td>
<td style="text-align: center;">5.418</td>
<td style="text-align: center;">2.073</td>
<td style="text-align: center;">2.761</td>
</tr>
<tr align="center" valign="middle">
<td style="text-align: center;">16</td>
<td style="text-align: center;">3.207</td>
<td style="text-align: center;">0.869</td>
<td style="text-align: center;">1.171</td>
<td style="text-align: center;">4.817</td>
<td style="text-align: center;">1.656</td>
<td style="text-align: center;">2.800</td>
</tr>
<tr align="center" valign="middle">
<td style="text-align: center;">32</td>
<td style="text-align: center;">3.213</td>
<td style="text-align: center;">0.853</td>
<td style="text-align: center;">1.240</td>
<td style="text-align: center;">4.915</td>
<td style="text-align: center;">1.680</td>
<td style="text-align: center;">2.843</td>
</tr>
<tr align="center" valign="middle">
<td style="text-align: center;">64</td>
<td style="text-align: center;">3.322</td>
<td style="text-align: center;">0.921</td>
<td style="text-align: center;">1.269</td>
<td style="text-align: center;">5.049</td>
<td style="text-align: center;">1.639</td>
<td style="text-align: center;">2.843</td>
</tr>
</tbody>
</table>
<p>Conclusion du benchmark : moins il y a de threads, meilleures sont les performances.</p>
<p>Les performances ne sont pas linéaires avec le nombre de threads.</p>
<p>De manière globale, on peut extrapoler que les locks sont plus performants que l&#8217;utilisation des synchronized.</p>
<p>En fonction du nombre de threads, la meilleure technologie n&#8217;est pas la même. Ce qui milite fortement pour des tests systématiques lors du choix de la technologie la plus adaptée au contexte du projet.</p>
<p><strong>Compléments :</strong></p>
<p><a href="http://martinfowler.com/articles/lmax.html"> Bliki M. FOWLER</a></p>
<p><a href="http://blogs.lmax.com/">Blog équipe LMAX</a></p>
<h2>Exemple de code</h2>
<p>Le code est là pour illustrer l&#8217;utilisation du pattern Disruptor (ne chercher pas l&#8217;utilité d&#8217;un tel code moi même je la cherche encore).</p>
<p><a href="http://blog.ippon.fr/2011/08/29/lmax-6-millions-doperations-par-seconde/excode/" rel="attachment wp-att-3722"><img class="alignnone size-full wp-image-3722" title="ExCode" src="http://blog.ippon.fr/wp-content/uploads/2011/08/ExCode.png" alt="" width="562" height="175" /></a></p>
<p>Nous avons un producteur qui va poster des messages correspondant à un chiffre de 0 à 1000.</p>
<p>Nous avons divisé la tache en trois :</p>
<ul style="list-style-type: circle;">
<li>Un consommateur pour calculer le cube des chiffre pair.</li>
<li>Un consommateur pour calculer le cube des chiffre impair.</li>
<li>Un consommateur pour afficher les résultats.</li>
</ul>
<p>Le consommateur 3 (logger) a besoin des deux autres pour pouvoir fonctionner.</p>
<p>Cet exemple va donc illustrer une dépendance entre des consommateurs ainsi qu&#8217;un partage des tâches entre deux consommateurs.</p>
<p>Enfin les consommateurs de type calcul écrivent dans le Ring Buffer le résultat de l&#8217;opération.</p>
<p><strong>Code d&#8217;une Entrée</strong></p>
<pre class="brush: java; title: ; notranslate">
public final static class ValueEntry extends AbstractEntry {
	private long value;
	private long cubic;
	private String className;
	public long getCube() {
		return cubic;
	}

	public void setCube(long cube) {
		this.cubic = cube;
	}

	public long getValue() {
		return value;
	}
	public void setValue(final long value) {
		this.value = value;
	}

	public void setClassName(String className) {
		this.className = className;
	}

	public String getClassName() {
		return className;
	}

	public final static EntryFactory ENTRY_FACTORY = new EntryFactory() {
		public ValueEntry create() {
			return new ValueEntry();
		}
	};
}
</pre>
<p>Il y a trois champs :</p>
<ol>
<li>La valeur initiale.</li>
<li>Le résultat du calcul.</li>
<li>Le nom de la classe qui va permettre d&#8217;identifier le consommateur qui a effectué le traitement.</li>
</ol>
<p><strong>Code du producteur</strong></p>
<pre class="brush: java; title: ; notranslate">
for (long i = 0; i &lt; =1001; i++) {
  // Producers claim entries in sequence
  ValueEntry entry = producerBarrier.nextEntry();

  // copy data into the entry container
  entry.setValue(i);

  // make the entry available to consumers
  producerBarrier.commit(entry);
}
</pre>
<p><strong>Code des consommateurs (calcul)</strong></p>
<pre class="brush: java; title: ; notranslate">
public void onAvailable(final ValueEntry entry) throws Exception {
  // process a new entry as it becomes available.
  entry.setCube((entry.value) * (entry.value) * (entry.value));
  StackTraceElement trace = Thread.currentThread().getStackTrace()[3];
  entry.setClassName(trace.getClassName());
}
</pre>
<p><strong>Code du consommateur (logger</strong>)</p>
<pre class="brush: java; title: ; notranslate">
public void onAvailable(final ValueEntry entry) throws Exception {
 // process a new entry as it becomes available.
 System.out.println(&quot;Processing entry : &quot; + entry.getValue());
 System.out.println(&quot;Cube : &quot; + entry.getCube());
 System.out.println(&quot;Processed by : &quot; + entry.getClassName().toString());
}</pre>
<p><strong>Modification de la classe BatchConsumer</strong></p>
<p>On va modifier le consommateur fourni par défaut en deux classes distinctes, l&#8217;une traitant les séquences paires l&#8217;autre les séquences impaires.</p>
<p>Pour le consommateur impair on commence avec un décalage</p>
<pre class="brush: java; gutter: false; title: ; notranslate">
private volatile long sequence = RingBuffer.INITIAL_CURSOR_VALUE + 1;
</pre>
<p>Dans les deux consommateurs on remplace le code suivant :</p>
<pre class="brush: java; gutter: false; title: ; notranslate">for (; nextSequence &lt; = availableSequence; nextSequence++) {</pre>
<p>par :</p>
<pre class="brush: java; gutter: false; title: ; notranslate">for (; nextSequence &lt; = availableSequence; nextSequence = nextSequence + 2) {</pre>
<p><strong>Code complet</strong></p>
<pre class="brush: java; title: ; notranslate">
package disruptor;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import com.lmax.disruptor.AbstractEntry;
import com.lmax.disruptor.BatchConsumer;
import com.lmax.disruptor.BatchHandler;
import com.lmax.disruptor.ClaimStrategy;
import com.lmax.disruptor.ConsumerBarrier;
import com.lmax.disruptor.EntryFactory;
import com.lmax.disruptor.ProducerBarrier;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.WaitStrategy;

public class Disruptor {
	// Ring Buffer size
	private static int SIZE = 100;
	private static Executor EXECUTOR = Executors.newCachedThreadPool();

	// Creation of the RB with optimized claim strategy and aggressive wait
	// strategy
	private static RingBuffer ringBuffer = new RingBuffer(
			ValueEntry.ENTRY_FACTORY, SIZE,
			ClaimStrategy.Option.SINGLE_THREADED, WaitStrategy.Option.BUSY_SPIN);
	/**
	 * @param args
	 * @throws InterruptedException
	 */
	public static void main(String[] args) throws InterruptedException {
		// Callback handler which can be implemented by consumers
		final BatchHandler batchHandler = new BatchHandler() {
			public void onAvailable(final ValueEntry entry) throws Exception {
				// process a new entry as it becomes available.
				entry.setCube((entry.value) * (entry.value) * (entry.value));
				StackTraceElement trace = Thread.currentThread().getStackTrace()[3];
				entry.setClassName(trace.getClassName());
			}

			public void onEndOfBatch() throws Exception {
				// useful for flushing results to an IO device if necessary.
			}
		};

		final BatchHandler batchLoger = new BatchHandler() {
			public void onAvailable(final ValueEntry entry) throws Exception {
				// process a new entry as it becomes available.
				System.out.println(&quot;Processing entry : &quot; + entry.getValue());
				System.out.println(&quot;Cube : &quot; + entry.getCube());
				System.out.println(&quot;Processed by : &quot; + entry.getClassName().toString());

			}

			public void onEndOfBatch() throws Exception {
				// useful for flushing results to an IO device if necessary.
			}
		};

		ConsumerBarrier consumerBarrier1 = ringBuffer.createConsumerBarrier();

		// batch consumers are tied to consumerBarrier1
		BatchConsumerEven batchConsumerEven =
                                  new BatchConsumerEven(consumerBarrier1, batchHandler);
		BatchConsumerOdd batchConsumerOdd =
                                  new BatchConsumerOdd(consumerBarrier1, batchHandler);

		// consumerBarrier2 is tied to consumers batchConsumerEven and
		// batchConsumerOdd
		ConsumerBarrier consumerBarrier2 = ringBuffer.createConsumerBarrier(batchConsumerEven,
                                 batchConsumerOdd);

		// log consumer is tied to consumerBarrier2
		BatchConsumer logConsumer = new BatchConsumer(consumerBarrier2, batchLoger);

		// Each consumer can run on a separate thread
		EXECUTOR.execute(batchConsumerEven);
		EXECUTOR.execute(batchConsumerOdd);
		EXECUTOR.execute(logConsumer);

		// Producer code
		ProducerBarrier producerBarrier = ringBuffer.createProducerBarrier(logConsumer);

		for (long i = 0; i &lt; = 1001; i++) {
			// Producer claims entries in sequence
			ValueEntry entry = producerBarrier.nextEntry();

			// copy data into the entry container
			entry.setValue(i);

			// make the entry available to consumers
			producerBarrier.commit(entry);
		}

		// Give 1 sec to end before exit
		Thread.sleep(1000);
		System.exit(0);
	}

	public final static class ValueEntry extends AbstractEntry {
		private long value;
		private long cubic;
		private String className;

		public long getCube() {
			return cubic;
		}
		public void setCube(long cube) {
			this.cubic = cube;
		}

		public long getValue() {
			return value;
		}
		public void setValue(final long value) {
			this.value = value;
		}

		public void setClassName(String className) {
			this.className = className;
		}
		public String getClassName() {
			return className;
		}

		public final static EntryFactory ENTRY_FACTORY = new EntryFactory() {
			public ValueEntry create() {
				return new ValueEntry();
			}
		};
	}
}
</pre>
<p>A noter la taille du Ring Buffer, alors que l&#8217;on envisage de traiter 1000 données, on ne déclare qu&#8217;une taille de 100.</p>
<p>C&#8217;est pour illustrer le principe de recyclage des entrées du Ring Buffer.</p>
<p>De plus la taille est obligatoirement de type 2<sup>n</sup> (soit 128 dans notre cas).</p>
<p><strong>Affichage en sortie (Extrait)</strong></p>
<pre class="brush: plain; gutter: false; title: ; notranslate">Processing entry : 0
Cube : 0
Processed by : disruptor.BatchConsumerEven

Processing entry : 1
Cube : 1
Processed by : disruptor.BatchConsumerOdd

Processing entry : 2
Cube : 8
Processed by : disruptor.BatchConsumerEven

Processing entry : 3
Cube : 27
Processed by : disruptor.BatchConsumerOdd

Processing entry : 4
Cube : 64
Processed by : disruptor.BatchConsumerEven

Processing entry : 5
Cube : 125
Processed by : disruptor.BatchConsumerOdd

Processing entry : 6
Cube : 216
Processed by : disruptor.BatchConsumerEven

Processing entry : 7
Cube : 343
Processed by : disruptor.BatchConsumerOdd</pre>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/feBumoHTeNM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/08/29/lmax-6-millions-doperations-par-seconde/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/08/29/lmax-6-millions-doperations-par-seconde/</feedburner:origLink></item>
		<item>
		<title>Judo – Bravo Fred</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/ZMinjmChkAI/</link>
		<comments>http://blog.ippon.fr/2011/08/23/judo-bravo-fred/#comments</comments>
		<pubDate>Tue, 23 Aug 2011 19:44:51 +0000</pubDate>
		<dc:creator>Geoffray GRUEL</dc:creator>
				<category><![CDATA[Détente]]></category>
		<category><![CDATA[Evénements]]></category>
		<category><![CDATA[Fred Jossinet]]></category>
		<category><![CDATA[Judo]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=3529</guid>
		<description><![CDATA[<p>Notre collègue Frédérique Jossinet a terminé au pied du podium aujourd&#8217;hui aux Championnats du Monde, éliminée en quart de finale par la japonaise Fukumi qui finira médaille d&#8217;argent.</p> <p>Je ne suis pas un expert en judo et je ne me permettrai pas de commenter le sportif. Par contre j&#8217;ai vu aujourd&#8217;hui sur le tatami de <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/08/23/judo-bravo-fred/">Judo &#8211; Bravo Fred</a></span>]]></description>
			<content:encoded><![CDATA[<p>Notre collègue Frédérique Jossinet a terminé au pied du podium aujourd&#8217;hui aux Championnats du Monde, éliminée en quart de finale par la japonaise Fukumi qui finira médaille d&#8217;argent.</p>
<p>Je ne suis pas un expert en judo et je ne me permettrai pas de commenter le sportif. Par contre j&#8217;ai vu aujourd&#8217;hui sur le tatami de Bercy une athlète affutée qui dégageait un réel plaisir dans le combat et une énorme détermination.</p>
<p>Le chemin vers Londres 2012 continue pour Fred et toute l&#8217;équipe Ippon Technologies est avec toi pour tes prochaines échéances,</p>
<p>Retrouvez le communiqué de presse sur l&#8217;arrivée de Frédérique dans nos équipes : <a title="Communiqué de presse Frédérique Jossinet" href="http://www.ippon.fr/web/guest/actu/communiques" target="_blank">http://www.ippon.fr/web/guest/actu/communiques</a></p>
<p>Retrouvez les réactions de Frédérique sur l&#8217;Equipe.fr : <a title="Réactions de Fred sur L'Equipe.fr" href="http://www.lequipe.fr/Judo/breves2011/20110823_183810_jossinet-c-est-le-jeu.html" target="_blank">http://www.lequipe.fr/Judo/breves2011/20110823_183810_jossinet-c-est-le-jeu.html</a></p>
<p>A suivre,</p>
<p>Geoffray</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/ZMinjmChkAI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/08/23/judo-bravo-fred/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/08/23/judo-bravo-fred/</feedburner:origLink></item>
		<item>
		<title>Ippon au Bordeaux JUG</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/Cj2gfyoB-P4/</link>
		<comments>http://blog.ippon.fr/2011/08/17/ippon-au-bordeaux-jug/#comments</comments>
		<pubDate>Wed, 17 Aug 2011 08:15:44 +0000</pubDate>
		<dc:creator>Julien DUBOIS</dc:creator>
				<category><![CDATA[Evénements]]></category>
		<category><![CDATA[Cassandra]]></category>
		<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[JUG]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=3521</guid>
		<description><![CDATA[<p>Ippon Technologies a ouvert cette année son agence de Bordeaux, et c&#8217;est donc tout naturellement que nous allons participer au JUG local, le Bordeaux JUG.</p> <p>A ce titre, Julien Dubois, directeur du pôle conseil d&#8217;Ippon Technologies, viendra réaliser une conférence sur Hibernate et le cloud computing le 20 Septembre.</p> <p>Cette conférence sera l&#8217;occasion de partager <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/08/17/ippon-au-bordeaux-jug/">Ippon au Bordeaux JUG</a></span>]]></description>
			<content:encoded><![CDATA[<p>Ippon Technologies a ouvert cette année son agence de Bordeaux, et c&#8217;est donc tout naturellement que nous allons participer au JUG local, le Bordeaux JUG.</p>
<p>A ce titre, Julien Dubois, directeur du pôle conseil d&#8217;Ippon Technologies, viendra réaliser une conférence sur Hibernate et le cloud computing le 20 Septembre.</p>
<p>Cette conférence sera l&#8217;occasion de partager ensemble sur les nouvelles tendances de notre métier: le NoSQL, les systèmes de cache distribué&#8230; mais aussi de faire le point sur des technologies plus classiques, comme Hibernate ou les bases de données &#8220;traditionnelles&#8221;, et de voir quelles sont les problématiques (et solutions!) couramment rencontrées.</p>
<p>Rendez-vous sur le site du Bordeaux JUG pour plus de détails ainsi que pour vous inscrire: <a href="http://bordeauxjug.org/20110920_HibernateVsCloudComputing">http://bordeauxjug.org/20110920_HibernateVsCloudComputing</a></p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/Cj2gfyoB-P4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/08/17/ippon-au-bordeaux-jug/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/08/17/ippon-au-bordeaux-jug/</feedburner:origLink></item>
		<item>
		<title>Quand Ippon rencontre Fred Jossinet… (Gagnez des places aux championnats du monde de Judo!)</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/jF2qCWBtZBA/</link>
		<comments>http://blog.ippon.fr/2011/08/09/quand-ippon-rencontre-fred-jossinet-gagnez-des-places-aux-championnats-du-monde-de-judo/#comments</comments>
		<pubDate>Tue, 09 Aug 2011 15:43:43 +0000</pubDate>
		<dc:creator>Julien DUBOIS</dc:creator>
				<category><![CDATA[Détente]]></category>
		<category><![CDATA[Sport et business]]></category>
		<category><![CDATA[Fred Jossinet]]></category>
		<category><![CDATA[Judo]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=3511</guid>
		<description><![CDATA[<p>Championnats d&#8217;Europe d&#8217;Istanbul, Grand Chelem à Rio, Stages d&#8217;entraînements Commando, Fred Jossinet enchaîne compétitions et entraînements en vue des Jeux Olympiques 2012.</p> <p>Malgré ce planning ultra chargé, Fred a créé la surprise lors de la soirée d&#8217;inauguration des nouveaux locaux d&#8217;Ippon. D&#8217;abord par sa présence qui a ravie tous les Ipponniens (normal!) et par l&#8217;annonce <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/08/09/quand-ippon-rencontre-fred-jossinet-gagnez-des-places-aux-championnats-du-monde-de-judo/">Quand Ippon rencontre Fred Jossinet&#8230; (Gagnez des places aux championnats du monde de Judo!)</a></span>]]></description>
			<content:encoded><![CDATA[<p>Championnats d&#8217;Europe d&#8217;Istanbul, Grand Chelem à Rio, Stages d&#8217;entraînements Commando, Fred Jossinet enchaîne compétitions et entraînements en vue des Jeux Olympiques 2012.</p>
<p>Malgré ce planning ultra chargé, Fred a créé la surprise lors de la soirée d&#8217;inauguration des nouveaux locaux d&#8217;Ippon. D&#8217;abord par sa présence qui a ravie tous les Ipponniens (normal!) et par l&#8217;annonce de Stéphane Nomis ensuite:<br />
<strong>&#8220;Frédérique Jossinet, médaillée aux JO de 2004, quatre fois médaillée aux Championnats du Monde, rejoint l&#8217;équipe Ippon Technologies&#8221;</strong></p>
<p>Ce partenariat avec la Fédération Française de Judo permet à la grande judokate française d&#8217;intégrer l&#8217;entreprise tout en préparant les Jeux Olympiques 2012. Diplômée de l&#8217;ESSEC, lorsque Fred ne sera pas sur le tatami, elle mènera des actions de fonds sur des projets commerciaux et marketing pour le compte de la Direction Commerciale d&#8217;IPPON Technologies. Nous avons signé officiellement le contrat avec la FFDJ devant les médias le 26 juillet à Bourges lors des entraînements de préparation aux JO.</p>
<p>Nous souhaitons donc chaleureusement la bienvenue à Fred! Et en fervents supporters, nous soutiendrons avec enthousiasme notre grande star lors des prochaines compétitions, rediffusées en direct chez Ippon Technologies.</p>
<p>Et puisque nous parlons des prochaines compétitions&#8230;.</p>
<p style="text-align: left;"><strong>Le prochain grand évènement du Judo, ce sont les Mondes qui se dérouleront à Paris du 23 au 28 août 2011. Pour l&#8217;occasion Ippon Technologies a réservé une loge pour toute la durée des compétitions et vous offre la possibilité d&#8217;aller soutenir Fred et nos athlètes français.</strong></p>
<p style="text-align: center;"><strong></strong><br />
<a href="https://spreadsheets.google.com/a/ippon.fr/spreadsheet/viewform?formkey=dFBZc0RLeTh2NmdrR1Y0ZjNub3UtdWc6MQ" target="_blank"> Le nombre de places est limité et mis en jeu ici</a></p>
<p style="text-align: left;">Il vous suffit de trouver les bonnes réponses au quizz pour vous inscrire au jeu et un tirage au sort désignera les gagnants! A vous de jouer et bonne chance! Les grands gagnants seront annoncés le 17 août.</p>
<div>Vous connaissez sans nul doute Frédéric Jossinet mais avez vous déjà vu son palmarès ?</div>
<table>
<tbody>
<tr>
<th>Année</th>
<th>Competition</th>
<th>Rang</th>
<th>Discipline</th>
<th>Lieu</th>
</tr>
<tr>
<td>2011</td>
<td>Ch. d&#8217;Europe</td>
<td>3</td>
<td>48 kg</td>
<td>Istanbul (TUR)</td>
</tr>
<tr>
<td>2009</td>
<td>Ch. du Monde</td>
<td>3</td>
<td>48 kg</td>
<td>Rotterdam (HOL)</td>
</tr>
<tr>
<td>2009</td>
<td>Ch. d&#8217;Europe</td>
<td>1</td>
<td>48 kg</td>
<td>Tbilissi (GEO)</td>
</tr>
<tr>
<td>2008</td>
<td>Ch. d&#8217;Europe</td>
<td>2</td>
<td>48 kg</td>
<td>Lisbonne (POR)</td>
</tr>
<tr>
<td>2007</td>
<td>Ch. du Monde</td>
<td>3</td>
<td>48 kg</td>
<td>Rio de Janeiro (BRE)</td>
</tr>
<tr>
<td>2007</td>
<td>Ch. d&#8217;Europe</td>
<td>3</td>
<td>48 kg</td>
<td>Belgrade (SER)</td>
</tr>
<tr>
<td>2006</td>
<td>Ch. d&#8217;Europe</td>
<td>3</td>
<td>48 kg</td>
<td>Tampere (FIN)</td>
</tr>
<tr>
<td>2005</td>
<td>Ch. du Monde</td>
<td>2</td>
<td>48 kg</td>
<td>Le Caire (EGY)</td>
</tr>
<tr>
<td>2005</td>
<td>Ch. d&#8217;Europe</td>
<td>2</td>
<td>48 kg</td>
<td>Rotterdam (HOL)</td>
</tr>
<tr>
<td>2004</td>
<td>JO</td>
<td>2</td>
<td>48 kg</td>
<td>Athènes (GRE)</td>
</tr>
<tr>
<td>2004</td>
<td>Ch. d&#8217;Europe</td>
<td>3</td>
<td>48 kg</td>
<td>Bucarest (ROU)</td>
</tr>
<tr>
<td>2003</td>
<td>Ch. du Monde</td>
<td>2</td>
<td>48 kg</td>
<td>Osaka (JAP)</td>
</tr>
<tr>
<td>2002</td>
<td>Ch. d&#8217;Europe</td>
<td>1</td>
<td>48 kg</td>
<td>Maribor (SLV)</td>
</tr>
<tr>
<td>2001</td>
<td>Ch. d&#8217;Europe</td>
<td>1</td>
<td>48 kg</td>
<td>Paris (FRA)</td>
</tr>
</tbody>
</table>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/jF2qCWBtZBA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/08/09/quand-ippon-rencontre-fred-jossinet-gagnez-des-places-aux-championnats-du-monde-de-judo/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/08/09/quand-ippon-rencontre-fred-jossinet-gagnez-des-places-aux-championnats-du-monde-de-judo/</feedburner:origLink></item>
		<item>
		<title>Pourquoi Firefox ou Java ne reconnaissent pas ce certificat SSL si chèrement payé ?</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/5UacIbxIA-c/</link>
		<comments>http://blog.ippon.fr/2011/07/23/pourquoi-firefox-ou-java-ne-reconnaissent-pas-ce-certificat-ssl-si-cherement-payee/#comments</comments>
		<pubDate>Sat, 23 Jul 2011 13:16:49 +0000</pubDate>
		<dc:creator>Fabien ARRAULT</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Certificat]]></category>
		<category><![CDATA[SSL]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=3474</guid>
		<description><![CDATA[<p>Je suis récemment retombé sur un problème avec un certificat SSL que je n&#8217;avais pas eut le temps d&#8217;analyser assez profondemment la première fois mais dont l&#8217;explication parait pourtant évidente après coup &#8230;</p> Le Problème <p>Soit un site web exposé en HTTPS disons sur le nom de domaine mon.domaine.fr avec un certificat tout beau et tout <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/07/23/pourquoi-firefox-ou-java-ne-reconnaissent-pas-ce-certificat-ssl-si-cherement-payee/">Pourquoi Firefox ou Java ne reconnaissent pas ce certificat SSL si chèrement payé ?</a></span>]]></description>
			<content:encoded><![CDATA[<p>Je suis récemment retombé sur un problème avec un certificat SSL que je n&#8217;avais pas eut le temps d&#8217;analyser assez profondemment la première fois mais dont l&#8217;explication parait pourtant évidente après coup &#8230;</p>
<h1>Le Problème</h1>
<p>Soit un site web exposé en HTTPS disons sur le nom de domaine mon.domaine.fr avec un certificat tout beau et tout neuf fraichement signé par une autorité de certification plus que reconnue (VeriSign dans mon cas).</p>
<p>Et pourtant lorsque je m&#8217;y connecte avec mon application Java, la JVM m&#8217;insulte à coup de : <em>javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target</em><br />
L&#8217;utilisation de la toute dernière version de la JVM n&#8217;y change rien.</p>
<p>Idem côté Firefox : l&#8217;accès avec un FireFox 5.0 (donc très récent) fraichement installé génère le warning suivant :</p>
<p style="font-family: Courier New, Courier, mono;">This Connection is Untrusted (&#8230;)<br />
mon.domaine.fr uses an invalid security certificate.<br />
The certificate is not trusted because no issuer chain was provided.<br />
(Error code: sec_error_unknown_issuer)</p>
<p><em>(Bon d&#8217;accord, avec cette version de FireFox, le message d&#8217;erreur est pourtant plus que significatif si on prend le temps de le comprendre&#8230;)</em></p>
<p>Si on ajoute un exception de sécurité à Firefox, la communication HTTPS fonctionne correctement. Le serveur semble donc être bien configuré pour gérer le SSL &#8230;</p>
<p>Pourtant le certificat exposé est bien signé par VeriSign. En particulier, le champ issuer/émetteur du certificat contient :</p>
<pre>CN = VeriSign Class 3 International Server CA - G3
OU = Terms of use at https://www.verisign.com/rpa (c)10
OU = VeriSign Trust Network
O = "VeriSign, Inc."
C = US</pre>
<p>Alors quoi ? Les certificats fraichement signés par une autorité reconnue ne fonctionnent pas par défaut ni avec Firefox ni avec Java ? Ca serait inquiétant non ? Surtout vu le prix qu&#8217;ils coûtent&#8230;</p>
<p>Heureusement il n&#8217;en est rien, ces certificats sont bien valides et toutes les versions de Firefox et toutes les versions de Java doivent pouvoir fonctionner avec sans avoir à les configurer au préalable.</p>
<p>Le problème ici est du côté du serveur&#8230;</p>
<h1>Un peu de background sur les certificats</h1>
<p>Un certificat est un document électronique qui contient en autre :</p>
<ul>
<li>une identité (dans notre cas l&#8217;identité d&#8217;un serveur via son nom DNS)</li>
<li>une clef publique (associée à une clef privée détenue uniquement par le possesseur du certificat )</li>
<li>l&#8217;identité de l&#8217;émetteur du certificat (l&#8217;autorité de certification ayant signé le certificat)</li>
<li>une signature électronique garantissant l&#8217;intégrité du certificat ainsi que le fait que l&#8217;autorité de certification reconnait la véracité des informations du certificat.</li>
</ul>
<p>La signature peut-être vérifiée à l&#8217;aide de la clef publique de l&#8217;émetteur.<br />
Cette clef publique est mis à disposition à l&#8217;aide d&#8217;un certificat propre à l&#8217;émetteur. Celui-ci est aussi signé électroniquement éventuellement par une troisième autorité de certification. Et ainsi de suite &#8230;</p>
<p>On obtient alors une chaine de certification :<br />
<em>certificat A est signé par B, dont le certificat B est signé par C, etc &#8230;</em></p>
<p>Au bout de la chaîne, on trouve le certificat d&#8217;une autorité de certification racine qui est auto-signé (c&#8217;est à dire signée avec la clef privée associée à sa propre clef publique)</p>
<p>Il suffit normalement que votre navigateur ou votre application fasse confiance à l&#8217;un des certificats de la chaîne pour que le premier certificat soit lui aussi reconnu comme digne de confiance et que la communication SSL puisse s&#8217;établir sans erreur ou warning.</p>
<p>Les certificats émis par VeriSign ne sont pas directement signés par leur certificat racine. Ils sont signés par un certificat intermédiaire. (A noter : VeriSign utilise plusieurs certificats racine et plusieurs certificats intermédiaires suivant le niveau de sécurité et les autres options demandées &#8230;)</p>
<p>Dans notre cas, on a :</p>
<ul>
<li>le certificat de notre domaine mon.domaine.fr signé par &#8220;VeriSign Class 3 International Server CA &#8211; G3&#8243;</li>
<li>le certificat intermédiaire &#8221;VeriSign Class 3 International Server CA &#8211; G3&#8243; signé par &#8220;VeriSign Class 3 Public Primary Certification Authority &#8211; G5&#8243;</li>
<li>le certificat racine &#8220;VeriSign Class 3 Public Primary Certification Authority &#8211; G5&#8243;</li>
</ul>
<p>Avec à la fois Java et Firefox qui font confiance par défaut au certificat racine &#8220;VeriSign Class 3 Public Primary Certification Authority &#8211; G5&#8243; &#8230;</p>
<p>( Note : pour la jvm, vous pouvez connaître la liste des autorités de confiance <strong>par défaut</strong> via cette commande : keytool -list -v -keystore %JDK_HOME%\jre\lib\security\cacerts -storepass changeit )</p>
<h1>L&#8217;explication</h1>
<p>Normalement, on a donc tout bon :</p>
<ul>
<li>le serveur nous expose un certificat valide faisant partie d&#8217;une chaine de confiance</li>
<li>nous faisons confiance à la racine de cette chaine</li>
</ul>
<p>Pourquoi cela ne fonctionne-t-il pas ??</p>
<p>Le problème ici c&#8217;est que le serveur ne nous exposait <strong>QUE</strong> le certificat de mon.domaine.fr &#8230;</p>
<p>Il est donc impossible pour la jvm ou pour Firefox de savoir que l&#8217;émetteur : &#8220;VeriSign Class 3 International Server CA &#8211; G3&#8243; a quelque part un certificat signé par &#8220;VeriSign Class 3 Public Primary Certification Authority &#8211; G5&#8243; (auquel ils font confiance)</p>
<p>Pour que cela fonctionne, il faut que le serveur envoie non seulement le certificat de mon.domaine.fr mais aussi le certificat intermédiaire associé à &#8220;VeriSign Class 3 International Server CA &#8211; G3&#8243; &#8230;</p>
<p>Une fois que l&#8217;on sait où chercher, la confirmation du diagnostique est simple :</p>
<ul>
<li>pour une application cliente java, on peut activer les debug ssl via l&#8217;option &#8220;-Djavax.net.debug=ssl&#8221;<br />
La chaîne de certificats exposés par le serveur sera alors tracée sur la sortie standard après une ligne &#8220;*** Certificate chain&#8221; (et juste avant que la jvm vous insulte car elle ne fait pas confiance au certificat <img src='http://blog.ippon.fr/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  )<br />
Si il y a qu&#8217;un seul certificat, on a bien le problème de configuration évoqué ici.<br />
Avec un serveur web correctement configuré, la chaîne contiendra normalement plusieurs certificats.</li>
<li>on peut aussi utiliser cette commande de openssl si il est disponible sur votre système :<br />
openssl s_client -showcerts -connect mon.domaine.fr:443<br />
Elle affichera en particulier l&#8217;ensemble des certificats qui sont envoyés par le serveur.</li>
</ul>
<h1>Les solutions</h1>
<h2>Vous ne pouvez pas modifier le serveur https</h2>
<p>Sans avoir la main sur le serveur web mal configuré, pas d&#8217;autre choix que de faire avec&#8230;</p>
<p>Il faut récupérer le certificat intermédiaire (sur le site de VeriSign) et l&#8217;ajouter aux certificats de confiance de votre navigateur et/ou de votre application java cliente.</p>
<p>Vous noterez que seul le certificat intermédiaire, celui ayant signé le certificat du serveur, est nécessaire. C&#8217;est généralement une mauvaise idée de mettre directement le certificat du serveur car lorsqu&#8217;il expirera il faudra obligatoirement le mettre à jour avec son remplaçant. Alors qu&#8217;il y a des chances que son remplaçant soit signé par le même certificat intermédiaire et alors tout continuera à fonctionner sans modification.</p>
<p>Dans une application java cliente, si vous avez une bonne raison, vous pouvez aussi bypasser complètement les contrôles de la JVM comme l&#8217;a expliqué Pierre-Alain ici : <a href="http://blog.ippon.fr/2008/10/20/certificats-auto-signe-et-communication-ssl-en-java/">http://blog.ippon.fr/2008/10/20/certificats-auto-signe-et-communication-ssl-en-java/</a></p>
<h2>Vous pouvez corriger la configuration du serveur https</h2>
<p>Si vous pouvez modifier ou faire modifier le serveur Web posant problème, c&#8217;est évidemment la meilleure solution.</p>
<p>Cette page web : <a href="http://www.ssl247.fr/support/install/">http://www.ssl247.fr/support/install/</a>, explique comment configurer correctement de nombreux serveurs ou load-balancer avec en particulier la façon d&#8217;installer le certificat intermédiaire pour qu&#8217;il soit exposé au client avec le certificat du serveur.</p>
<p>Une bonne nouvelle pour nous qui faisons du Java :<br />
si vous avez généré votre Certificat Signing Request (CSR) à l&#8217;aide de keytool (ou un outil encapsulant ces fonctionnalités), il ne vous permettra pas d&#8217;importer la réponse avec le certificat signé, si le keystore utilisé ne contient pas déjà l&#8217;ensemble de la chaîne de certification. La chaine de certification est donc obligatoirement disponible dans le keystore.</p>
<p>Après cela dépend de votre serveur d&#8217;application.<br />
Pour Tomcat par exemple (voir aussi <a href="http://tomcat.apache.org/tomcat-7.0-doc/config/http.html#SSL_Support">configuration des connecteurs tomcat</a>) :</p>
<ul>
<li>avec l&#8217;implémention Java du connecteur https, Tomcat expose directement l&#8217;ensemble de la chaîne présente dans le keystore</li>
<li>par contre avec l&#8217;implémentation APR du connecteur https, il est possible de mal le configurer, exactement comme pour le module mod_ssl de Apache httpd : dans les deux cas, l&#8217;option <a href="http://httpd.apache.org/docs/2.0/mod/mod_ssl.html#sslcertificatechainfile">SSLCertificateChainFile </a>est celle qu&#8217;il ne faut pas oublier de configurer.</li>
</ul>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/5UacIbxIA-c" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/07/23/pourquoi-firefox-ou-java-ne-reconnaissent-pas-ce-certificat-ssl-si-cherement-payee/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/07/23/pourquoi-firefox-ou-java-ne-reconnaissent-pas-ce-certificat-ssl-si-cherement-payee/</feedburner:origLink></item>
		<item>
		<title>Comment gagner au Challenge USI 2011?</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/e51brstt9O4/</link>
		<comments>http://blog.ippon.fr/2011/07/11/comment-gagner-au-challenge-usi-2011/#comments</comments>
		<pubDate>Mon, 11 Jul 2011 09:13:23 +0000</pubDate>
		<dc:creator>Julien DUBOIS</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Cassandra]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[usi2011]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=3453</guid>
		<description><![CDATA[<p>Déjà évoqué dans ce précédent billet, le Challenge USI 2011 s’est terminé la semaine dernière lors de l’Université du SI, événement sponsorisé par Octo Technologies.</p> <p>L’équipe n°10 (Florent Ramière/Jaxio, Nicolas Romanetti/Jaxio, Bernard Pons/Banque de France, Julien Dubois/Ippon Technologies) a terminé 2ème, à un cheveu de l’équipe gagnante (équipe n°6, composée de membres de Xebia). Les <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/07/11/comment-gagner-au-challenge-usi-2011/">Comment gagner au Challenge USI 2011?</a></span>]]></description>
			<content:encoded><![CDATA[<p>Déjà évoqué dans <a href="http://blog.ippon.fr/2011/06/15/netty-et-cassandra-en-finale-du-challenge-usi-2011/">ce précédent billet</a>, le Challenge USI 2011 s’est terminé la semaine dernière lors de l’Université du SI, événement sponsorisé par Octo Technologies.</p>
<p>L’équipe n°10 (Florent Ramière/Jaxio, Nicolas Romanetti/Jaxio, Bernard Pons/Banque de France, Julien Dubois/Ippon Technologies) a terminé 2ème, à un cheveu de l’équipe gagnante (équipe n°6, composée de membres de Xebia). Les technologies utilisées par ces deux équipes sont relativement proches, à la différence près du système de back-end:</p>
<ul>
<li>Gemfire: une solution de cache distribué qui est un produit commercial vendu par la société VMWare, pour l’équipe n°6,</li>
<li>Cassandra: une base de données NoSQL distribuée, qui est une solution Open Source de la fondation Apache, pour l’équipe n°10</li>
</ul>
<p>Nous vous proposons ici de détailler plusieurs des choix qui ont clairement fait la différence.</p>
<p>En effet:</p>
<ul>
<li>Les deux premières équipes ont tenu respectivement 200 000 et 210 000 connections simultanées</li>
<li>La 3ème équipe a tenu 40 000 connections</li>
<li>Les autres équipes n’ont pas pu dépasser les 12 000 connections</li>
</ul>
<p>Tout d’abord, la première chose qui a fait la différence n’est pas technique, mais humaine: il est clair que ces deux équipes ont passé énormément de temps sur le challenge, sans doute beaucoup plus que la plupart des autres équipes.</p>
<p>Ensuite, passons à la technique: les deux premières équipes ayant réalisé leur application en Java, en utilisant Netty, on peut en conclure un certain nombre de faits:</p>
<ul>
<li>Java est très bien adapté pour de la haute volumétrie. En l’occurrence, les solutions Java ont ici battu des solutions codées en C, node.js, akka.io&#8230; Non seulement le monde a changé (Java tient la charge sur de la haute volumétrie, et peut se battre avec des applications en C), mais les nouvelles solutions à la mode (Node.js et akka.io) ont encore du chemin à faire.</li>
<li>Plus spécifiquement, ce sont des solutions Java fortement optimisées qui ont gagné. Par exemple, certains compétiteurs ont utilisé Tomcat. C’est un grand classique de l’informatique: une solution spécialisée est toujours plus performante qu’une solution généraliste. Il ne faut donc pas en conclure que les serveurs d’application Java EE ne sont pas prêts pour ce niveau de charge: ils sont juste moins adaptés qu’un programme spécialisé, d’autant plus que les contraintes du challenge étaient très particulières au niveau HTTP (en particulier le fait de bloquer des requêtes HTTP, ce qui était une simplification de ce que l’on appelle habituellement du “long polling”).</li>
<li>Le back-end posant problème, les solutions les plus performantes sont celles qui ont le plus minimisé les accès à ce back-end. Pour les deux solutions gagnantes, les écritures sont toutes asynchrones, afin de ne jamais bloquer de thread utilisée par Netty. D’autre part, les lectures sont réduites grâce à de nombreuses astuces: utilisation d’un hash pour éviter de devoir relire le login/mot de passe de l’utilisateur à chaque requête, le stockage de certaines données du jeu dans un cookie de manière à éviter à avoir à les relire en base&#8230; Par contre l’équipe n°6 utilisait un état stocké dans une session HTTP distribuée avec Gemfire, tandis que l’équipe n°10 avait une architecture “stateless” avec des données de session stockées dans un cookie.</li>
<li>Une bonne utilisation de l’infrastructure est également primordiale: le tuning de l’OS et de la JVM font une différence énorme. Ubuntu, en standard, ne peut pas supporter ce type de charge, c’est pourquoi sa configuration a du être largement modifiée. Mais il y avait également un avantage à l’équipe qui connaissait bien les faiblesses de l’infrastructure virtualisée fournie: en effet, la configuration VMWare n’allouait que 2 gigas de RAM, pouvant monter à 4 en cas de charge. Il est donc probable que l’équipe n°6, qui a limité sa JVM à 2 Giga, a eu là un avantage: l’utilisation de l’ensemble de la RAM “virtuelle” par l’équipe n°10 ayant probablement fait s’écrouler les machines physiques hôtes. Enfin, l’équipe n°10 a fait l’erreur de sacrifier une machine pour faire des IP virtuelles avec LVS, alors que l’équipe n°6 a mieux géré ses ressources en répartissant cette configuration sur toutes leurs machines: étant donné que le test final n’était que sur 10 machines, cela leur a donc donné un net avantage en termes de puissance de calcul.</li>
</ul>
<p>Malheureusement la plateforme de test n’a permis que de faire un test avec 10 machines virtuelles en parallèle, et nous ne pouvons donc pas savoir si l’une de ces architectures pouvait effectivement tenir le million d’utilisateurs simultanés, sur 100 machines distribuées, ce qui était l’objectif fiinal du jeu. On voit en effet ici que les contraintes de RAM et de nombre de machines disponibles ont eu un impact important sur les tests réalisés. L’un des effets principaux de la virtualisation a été de cacher aux compétiteurs les CPUs et la RAM rééllement disponibles, ainsi que la configuration réseau exacte, ce qui a eu un effet très négatif sur le tuning, et donc sur les performances finales.</p>
<p>L’équipe n°10 est en train de nettoyer son code avant de le mettre à disposition de tous sur GitHub: nous ne manquerons pas de vous tenir informés sur ce blog et via Twitter.</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/e51brstt9O4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/07/11/comment-gagner-au-challenge-usi-2011/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/07/11/comment-gagner-au-challenge-usi-2011/</feedburner:origLink></item>
		<item>
		<title>Netty et Cassandra en finale du challenge USI 2011</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/T5v5EdsYUu4/</link>
		<comments>http://blog.ippon.fr/2011/06/15/netty-et-cassandra-en-finale-du-challenge-usi-2011/#comments</comments>
		<pubDate>Wed, 15 Jun 2011 08:18:19 +0000</pubDate>
		<dc:creator>Julien DUBOIS</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Cassandra]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[usi2011]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=3388</guid>
		<description><![CDATA[ <p>Le challenge USI 2011 est une compétition organisée par Octo Technologies, qui vise à réaliser une application Web qui survit à des conditions extrêmes:</p> 1 000 000 d’utilisateurs connectés en même temps Avec des connexions HTTP longues Et des serveurs qui plantent de manière aléatoire <p>Vous trouverez plus d’informations sur le site du challenge.</p> <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/06/15/netty-et-cassandra-en-finale-du-challenge-usi-2011/">Netty et Cassandra en finale du challenge USI 2011</a></span>]]></description>
			<content:encoded><![CDATA[<div>
<p>Le challenge USI 2011 est une compétition organisée par Octo Technologies, qui vise à réaliser une application Web qui survit à des conditions extrêmes:</p>
<ul>
<li>1 000 000 d’utilisateurs connectés en même temps</li>
<li>Avec des connexions HTTP longues</li>
<li>Et des serveurs qui plantent de manière aléatoire</li>
</ul>
<p>Vous trouverez plus d’informations sur <a href="http://sourceforge.net/p/usi2011/home/">le site du challenge</a>.</p>
<p>Sur les 20 équipes qui ont participé au challenge, une dizaine a pu rendre une application testable, et 3 ont été sélectionnées pour la finale, dont l’équipe n°10.</p>
<p>L’équipe n°10 c’est:</p>
<ul>
<li>Florent Ramière, de <a href="http://www.jaxio.com/">Jaxio</a> (twitter <a href="https://twitter.com/#!/framiere">@framiere</a>)</li>
<li>Nicolas Romanetti, de <a href="http://www.jaxio.com/">Jaxio</a> (twitter <a href="https://twitter.com/#!/nromanetti">@nromanetti</a>)</li>
<li>Bernard Pons, de la Banque de France (twitter <a href="https://twitter.com/#!/ponsbernard">@ponsbernard</a>)</li>
<li>Julien Dubois, d’Ippon Technologies (twitter <a href="https://twitter.com/#!/juliendubois">@juliendubois</a>)</li>
</ul>
<p>Vous pouvez suivre l’équipe sur twitter <a href="https://twitter.com/#!/usi2011_jaxio">@usi2011_jaxio</a></p>
<p>L’application réalisée est entièrement développée en Java, suite à une étude de différentes technologies concurrentes, en particulier <a href="http://nodejs.org/">node.js</a>, <a href="http://nginx.org/">nginx</a> et <a href="http://www.zeromq.org/">zeromq</a>.</p>
<p>En effet, le challenge pose deux problèmes bien particuliers:</p>
<ul>
<li>Tenir un grand nombre de connexions HTTP en parallèle</li>
<li>Avoir un back-end qui supporte une montée en charge linéaire et des crashs aléatoires</li>
</ul>
<div>Pour ce qui est des connexions HTTP, nos tests nous ont montré que l’on pouvait faire aussi bien que nginx ou node.js avec du Java. C’est pour cette raison que nous avons choisi <a href="http://www.jboss.org/netty">JBoss Netty</a> pour notre frontal. Pour information, une autre équipe finaliste (Xebia) a choisi <a href="http://deftserver.appspot.com/">Deft</a>, qui est une solution Java assez proche, il semble donc que ce soit le meilleur choix à faire pour tenir la charge. Voilà qui devrait surprendre pas mal de monde&#8230;<br />
Cependant, il faut noter qu’il s’agit de solutions développées spécifiquement pour ce challenge, et qu’un serveur d’application Java classique est totalement incapable de tenir ce genre de charge.&nbsp;</p>
<p>Concernant le back-end, nous avons choisi <a href="http://cassandra.apache.org/">Apache Cassandra</a>, qui est une solution NoSQL permettant d’excellentes performances en écriture (ce qui est l’un des gros problèmes du challenge), ainsi qu’une très bonne bonne montée en charge.</p>
</div>
<div>Notre retour sur Cassandra est positif: l’outil est impressionnant en terme d’architecture technique et propose des fonctionnalités tout simplement révolutionnaires pour qui est habitué aux technologies SQL “standard”. De plus, la documentation est particulièrement bien soignée, en particulier lorsque l’on recherche des informations sur la performance:</div>
<ul>
<li><a href="http://wiki.apache.org/cassandra/">Le Wiki de Cassandra</a> (voir la partie “advanced setup and tuning”)</li>
<li><a href="http://www.datastax.com/docs/0.8/index">La documentation fournie par DataStax</a>, une société qui vend des outils et du support sur Cassandra</li>
<li>Et bien entendu l’excellent “<a href="http://oreilly.com/catalog/0636920010852">Cassandra: the definitive guide</a>” chez O’Reilly</li>
</ul>
<p>Ce choix de Cassandra nous a renforcé dans l’utilisation d’un front-end Java, car nous n’avons pas trouvé de solution satisfaisante pour nous connecter à Cassandra depuis les autres technologies étudiées (avec node.js par exemple).</p>
<p>Le jeu n’étant pas encore fini, nous donnerons plus tard dans ce blog les détails de différentes stratégies et tunings que nous avons utilisées sur notre système, en particulier au niveau de la configuration de Cassandra, des JVMs et de l’OS (un Ubuntu server).</p>
<p>En attendant, nous souhaitons bonne chance à nos concurrents!</p>
</div>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/T5v5EdsYUu4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/06/15/netty-et-cassandra-en-finale-du-challenge-usi-2011/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/06/15/netty-et-cassandra-en-finale-du-challenge-usi-2011/</feedburner:origLink></item>
		<item>
		<title>Qu’attendez-vous de JMS 2.0?</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/AxSNs8AWqPw/</link>
		<comments>http://blog.ippon.fr/2011/06/14/quattendez-vous-de-jms-2-0/#comments</comments>
		<pubDate>Tue, 14 Jun 2011 09:55:45 +0000</pubDate>
		<dc:creator>Julien DUBOIS</dc:creator>
				<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JMS]]></category>
		<category><![CDATA[JSR 343]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=3383</guid>
		<description><![CDATA[<p>Ce post est écrit par Julien Dubois, membre de l&#8217;expert group JMS 2.0, et directeur du pôle conseil d&#8217;Ippon Technologies.</p> <p>JMS est une spécification très utilisée en entreprise, mais son API est relativement ancienne, ce qui est vite frustrant lorsqu&#8217;on l&#8217;utilise. C&#8217;est d&#8217;ailleurs l&#8217;une des raisons du succès de Spring JMS. Heureusement, l&#8217;expert group JSR <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/06/14/quattendez-vous-de-jms-2-0/">Qu&#8217;attendez-vous de JMS 2.0?</a></span>]]></description>
			<content:encoded><![CDATA[<p>Ce post est écrit par Julien Dubois, membre de l&#8217;expert group JMS 2.0, et directeur du pôle conseil d&#8217;Ippon Technologies.</p>
<p>JMS est une spécification très utilisée en entreprise, mais son API est relativement ancienne, ce qui est vite frustrant lorsqu&#8217;on l&#8217;utilise. C&#8217;est d&#8217;ailleurs l&#8217;une des raisons du succès de Spring JMS. Heureusement, l&#8217;expert group JSR 343 (&#8220;JMS 2.0&#8243;) vient d&#8217;être formé afin de mettre à jour la spécification:</p>
<p><a href="http://java.net/projects/jms-spec/pages/Home">http://java.net/projects/jms-spec/pages/Home</a></p>
<p>Ce type de spécification a tendance à durer de nombreuses années: JMS 1.1 date de 2002, cela va donc bientôt faire une dizaine d&#8217;années! D&#8217;où l&#8217;importance de participer à son élaboration.</p>
<p>En tant que membre de l&#8217;expert group qui met en place cette spécification, je vous propose donc de participer sur ce blog, en Français, et de nous dire ce que vous voulez voir apparaître (et disparaître!) de la spécification JMS.</p>
<p>Voici ma proposition actuelle:</p>
<ol>
<li>Configuration de JMS
<ul>
<li>l&#8217;API JMS ne devrait pas dépendre de JNDI, afin qu&#8217;elle soit utilisable en dehors d&#8217;un serveur d&#8217;application complet (on pourrait alors l&#8217;utiliser sans problème dans Tomcat, un batch, ou un ESB léger).</li>
<li>Le pooling des ressources JMS devrait être inclus dans cette configuration</li>
<li>Il y a aujourd&#8217;hui <a href="http://agoncal.wordpress.com/2011/06/10/debate-and-what-about-configuration-in-java-ee-7/">un débat sur la configuration dans JEE 7</a>, lancé par Antonio Goncalves, et JMS 2.0 devrait y participer.</li>
</ul>
</li>
<li>Simplification de l&#8217;API JMS
<ul>
<li>Certaines parties de l&#8217;API JMS ne sont pas claires, par exemple sur ce qui concerne l&#8217;acknowledgement des messages. Nous devrions juste avoir &#8221;auto&#8221;, &#8220;client&#8221;, &#8220;dups-ok&#8221; et &#8220;transacted&#8221;, comme ce qui est proposé dans Spring JMS.</li>
<li>Il devrait y avoir une API plus simple pour envoyer et recevoir des messages, comme fourni par le JMSTemplate de Spring. Des librairies utilitaires et des wrappers ne devraient pas être nécessaires pour des cas d&#8217;utilisation simples.</li>
</ul>
</li>
<li>Les annotations
<ul>
<li>Comme toute spécification moderne, il faut pouvoir utiliser les annotations pour la configuration.</li>
</ul>
</li>
<li>Des MDB partout
<ul>
<li>Les Message-Driven Beans ne devraient pas être réservés aux seuls serveurs d&#8217;application. Nous devrions avoir des &#8220;message-driven POJOs&#8221; tels que fournis par Spring JMS, en utilisant des annotations sur un objet Java simple.</li>
</ul>
</li>
<li>Le clustering et le failover
<ul>
<li>Le thème de JEE 7 étant &#8220;le cloud&#8221;, il devrait y avoir des options de configuration du clustering et du failover dans la spécification. Par exemple, il faudrait pouvoir configurer le failover comme proposé par ActiveMQ <a href="http://activemq.apache.org/failover-transport-reference.html">dans sa documentation</a>. Il faudrait également avoir un système de callback pour gérer les cas d&#8217;erreurs.</li>
</ul>
</li>
<li>Les batchs
<ul>
<li>Il faudrait pouvoir envoyer les messages par batch et non un par un.</li>
</ul>
</li>
</ol>
<p>Une autre proposition, qui revient régulièrement mais que nous n&#8217;avons pas repris, est celle de pouvoir envoyer des messages avec une date définie de réception. Par exemple, un producteur de message pourrait envoyer tous ses messages dans la journée, en disant qu&#8217;ils ne devront être délivrés que à minuit au destinataire.</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/AxSNs8AWqPw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/06/14/quattendez-vous-de-jms-2-0/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/06/14/quattendez-vous-de-jms-2-0/</feedburner:origLink></item>
		<item>
		<title>Ippon au Jug Summer Camp</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/NI36RgZdb-I/</link>
		<comments>http://blog.ippon.fr/2011/06/06/ippon-au-jug-summer-camp/#comments</comments>
		<pubDate>Mon, 06 Jun 2011 09:00:21 +0000</pubDate>
		<dc:creator>Julien DUBOIS</dc:creator>
				<category><![CDATA[Evénements]]></category>
		<category><![CDATA[Expertise Java]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JUG]]></category>
		<category><![CDATA[JugSummerCamp]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=3380</guid>
		<description><![CDATA[<p>Le Jug Summer Camp, c&#8217;est LA conférence Java de la rentrée, qui aura lieu à La Rochelle le 16 Septembre 2011. La première édition avait été exceptionnelle: des conférences de très haut niveau, une excellente ambiance (la conférence a lieu sur le port de La Rochelle&#8230;), et une organisation sans faille!</p> <p>Ippon sera bien entendu <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/06/06/ippon-au-jug-summer-camp/">Ippon au Jug Summer Camp</a></span>]]></description>
			<content:encoded><![CDATA[<p>Le <a href="https://sites.google.com/site/jugsummercamp/home">Jug Summer Camp</a>, c&#8217;est LA conférence Java de la rentrée, qui aura lieu à La Rochelle le 16 Septembre 2011. La première édition avait été exceptionnelle: des conférences de très haut niveau, une excellente ambiance (la conférence a lieu sur le port de La Rochelle&#8230;), et une organisation sans faille!</p>
<p>Ippon sera bien entendu présent à cette conférence, avec la conférence &#8220;Hibernate vs. le Cloud Computing&#8221; animée par Julien Dubois.</p>
<p>Les inscriptions <a href="https://sites.google.com/site/jugsummercamp/inscriptions-1">sont ouvertes depuis ce matin</a>, dépêchez-vous de vous inscrire car les places pour ce type de conférence partent très vite en ce moment (comme l&#8217;a montré le <a href="http://www.breizhcamp.org/">BreizhCamp</a>, où nous serons également présents). Pour les Parisiens, n&#8217;oubliez pas que La Rochelle est à moins de 3 heures de TGV de la capitale, et qu&#8217;il vaut mieux arriver la veille car il y aura très certainement un restaurant sur le port le soir.</p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/NI36RgZdb-I" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/06/06/ippon-au-jug-summer-camp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/06/06/ippon-au-jug-summer-camp/</feedburner:origLink></item>
		<item>
		<title>Témoignage DGA au Liferay Symposium le 15/06 à Paris</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/_z59MVDiz4M/</link>
		<comments>http://blog.ippon.fr/2011/06/01/temoignage-dga-au-liferay-symposium-le-1506-a-paris/#comments</comments>
		<pubDate>Wed, 01 Jun 2011 06:00:20 +0000</pubDate>
		<dc:creator>Geoffray GRUEL</dc:creator>
				<category><![CDATA[Portail]]></category>
		<category><![CDATA[DGA]]></category>
		<category><![CDATA[Liferay]]></category>
		<category><![CDATA[Liferay symposium]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=3366</guid>
		<description><![CDATA[<p></p> <p>Le premier Liferay Symposium aura lieu à Paris le mercredi 15 juin.</p> <p>Le programme s&#8217;annonce riche et les speakers de qualité.</p> <p>La DGA présentera avec Ippon Technologies à cette occasion la nouvelle version du projet Espace Partenaires qui est en production sur Liferay depuis maintenant plus de 5 ans et qui vient de migrer <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/06/01/temoignage-dga-au-liferay-symposium-le-1506-a-paris/">Témoignage DGA au Liferay Symposium le 15/06 à Paris</a></span>]]></description>
			<content:encoded><![CDATA[<p><a rel="attachment wp-att-3368" href="http://blog.ippon.fr/2011/06/01/temoignage-dga-au-liferay-symposium-le-1506-a-paris/french_sympoisum_banner-2/"><img class="alignleft size-full wp-image-3368" title="French_Sympoisum_Banner" src="http://blog.ippon.fr/wp-content/uploads/2011/05/French_Sympoisum_Banner1.jpg" alt="" width="696" height="205" /></a></p>
<p>Le premier <a title="Liferay Symposium" href="http://www.liferay.com/events/liferay-symposiums/france-2011" target="_blank">Liferay Symposium</a> aura lieu à Paris le mercredi 15 juin.</p>
<p>Le <a title="Agenda Liferay Symposium Paris" href="http://www.liferay.com/web/guest/events/liferay-symposiums/france-2011/agenda" target="_blank">programme</a> s&#8217;annonce riche et les speakers de qualité.</p>
<p>La DGA présentera avec Ippon Technologies à cette occasion la nouvelle version du projet Espace Partenaires qui est en production sur Liferay depuis maintenant plus de 5 ans et qui vient de migrer sur la version Enterprise Edition de Liferay.</p>
<p>L&#8217;Espace Partenaires est un système d&#8217;information, mis en place par la DGA, qui donne aux acteurs du secteur de la Défense la possibilité de travailler en collaboration via un réseau sécurisé et privé.</p>
<p>La session vous proposera 5 ans de retour d&#8217;expérience sur Liferay avec un focus particulier sur les problématiques de gestion des communautés, de sécurité et de migration.</p>
<p>Les inscriptions au Symposium sont ouvertes sur <a title="Enregistrement Liferay Symposium Paris" href="http://www.regonline.co.uk/builder/site/Default.aspx?EventID=954625" target="_blank">le site de Liferay</a></p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/_z59MVDiz4M" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/06/01/temoignage-dga-au-liferay-symposium-le-1506-a-paris/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/06/01/temoignage-dga-au-liferay-symposium-le-1506-a-paris/</feedburner:origLink></item>
		<item>
		<title>Ippevent “GraniteDS, pierre angulaire de Flex”, inscriptions ouvertes</title>
		<link>http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/ZJZ1pn4d5H8/</link>
		<comments>http://blog.ippon.fr/2011/05/30/ippevent-graniteds-pierre-angulaire-de-flex-inscriptions-ouvertes/#comments</comments>
		<pubDate>Mon, 30 May 2011 10:53:35 +0000</pubDate>
		<dc:creator>Antoine SABOT-DURAND</dc:creator>
				<category><![CDATA[Ippevents]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[GraniteDS]]></category>
		<category><![CDATA[RIA]]></category>

		<guid isPermaLink="false">http://blog.ippon.fr/?p=3359</guid>
		<description><![CDATA[<p>Le 23 juin prochain aura lieu le dernier Ippevent de la saison : &#8220;GraniteDS, pierre angulaire de Flex&#8221;. Cet événement sera animé par William Drai co-fondateur du framework qui nous présentera cette solution Open Source performante de communication Flex / Java. En bonus Antoine Büsch fera un retour d&#8217;expérience d&#8217;utilisation sur un projet récent chez <span style="color:#777"> . . . &#8594; Lire la suite: <a href="http://blog.ippon.fr/2011/05/30/ippevent-graniteds-pierre-angulaire-de-flex-inscriptions-ouvertes/">Ippevent &#8220;GraniteDS, pierre angulaire de Flex&#8221;, inscriptions ouvertes</a></span>]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" src="http://www.granitedataservices.com/wp-content/themes/cocomonio/css/style_green/logo.png" alt="" width="119" height="55" />Le 23 juin prochain aura lieu le dernier Ippevent de la saison : &#8220;GraniteDS, pierre angulaire de Flex&#8221;. Cet événement sera animé par William Drai co-fondateur du framework qui nous présentera cette solution Open Source performante de communication Flex / Java. En bonus Antoine Büsch fera un retour d&#8217;expérience d&#8217;utilisation sur un projet récent chez un client dans le secteur de l&#8217;environnement.</p>
<p>Flex n’est pas le framework de RIA qui vient en premier à l&#8217;esprit des développeurs Java lorsqu&#8217;il s&#8217;agit de faire des choix techniques. Pourtant, c&#8217;est un choix qui peut être pertinent pour des projets entreprise, d&#8217;autant plus que des solutions matures de communication entre les mondes Flex et Java existent.</p>
<p>Alors si vous hésitez à utiliser Flex pour votre prochain projet à cause des difficultés d&#8217;interopérabilité avec Java ou  si vous souhaitez abandonner une solution propriétaire et couteuse de communication avec Flex, cet Ippevent est fait pour vous.</p>
<p>Pour vous inscrire, il vous suffit de remplir le formulaire ci-dessous ou d&#8217;aller sur notre page <a title="Inscription aux Ippevents" href="http://blog.ippon.fr/inscription-aux-ippevents/">Ippevent</a>.</p>

		<div id="usermessage7a" class="cf_info "></div>
		<form enctype="application/x-www-form-urlencoded" action="/feed/#usermessage7a" method="post" class="cform inscription-ippevent " id="cforms7form">
		<fieldset class="cf-fs1">
		<legend>Inscription à l'événement du 22/09/2011</legend>
		<ol class="cf-ol">
			<li class="cf_hidden"><input type="hidden" class="cfhidden" name="Date_evt" id="Date_evt" value="22/09/2011"/></li>
			<li id="li-7-3" class=""><label for="Evenement"><span>Evénement</span></label><input readonly="readonly" type="text" name="Evenement" id="Evenement" class="single readonly" value="la forge logicielle & CloudBees"/></li>
			<li id="li-7-4" class=""><label for="Salutation"><span>Salutation</span></label><select name="Salutation" id="Salutation" class="cformselect fldrequired" >
				<option value="M.">M.</option>
				<option value="Mlle">Mlle</option>
				<option value="Mme">Mme</option>
			</select><span class="reqtxt">(requis)</span></li>
			<li id="li-7-5" class=""><label for="Prenom"><span>Prénom</span></label><input type="text" name="Prenom" id="Prenom" class="single fldrequired" value=""/><span class="reqtxt">(requis)</span></li>
			<li id="li-7-6" class=""><label for="Nom"><span>Nom</span></label><input type="text" name="Nom" id="Nom" class="single fldrequired" value=""/><span class="reqtxt">(requis)</span></li>
			<li id="li-7-7" class=""><label for="Email"><span>Email</span></label><input type="email" name="Email" id="Email" class="single fldemail fldrequired" value=""/><span class="emailreqtxt">(un email valide est requis)</span></li>
			<li id="li-7-8" class=""><label for="Societe"><span>Société</span></label><input type="text" name="Societe" id="Societe" class="single" value=""/></li>
			<li id="li-7-9" class=" cf-box-title">J'accepte de recevoir des informations de la part d'Ippon Technologies par email</li>
			<li id="li-7-9items" class="cf-box-group">
				<input type="radio" id="J-accepte-de-recevoir-des-informations-de-la-part-d-Ippon-Technologies-par-email-1" name="J-accepte-de-recevoir-des-informations-de-la-part-d-Ippon-Technologies-par-email" value="Oui" class="cf-box-b fldrequired"/><label for="J-accepte-de-recevoir-des-informations-de-la-part-d-Ippon-Technologies-par-email-1" class="cf-after"><span>Oui</span></label>
				<br />
				<input type="radio" id="J-accepte-de-recevoir-des-informations-de-la-part-d-Ippon-Technologies-par-email-2" name="J-accepte-de-recevoir-des-informations-de-la-part-d-Ippon-Technologies-par-email" value="Non" checked="checked" class="cf-box-b fldrequired"/><label for="J-accepte-de-recevoir-des-informations-de-la-part-d-Ippon-Technologies-par-email-2" class="cf-after"><span>Non</span></label>
				<br />
			</li>
		</ol>
		</fieldset>

		<fieldset class="cf_hidden">
			<legend>&nbsp;</legend>
			<input type="hidden" name="cf_working7" id="cf_working7" value="Veuillez%20patienter..."/>
			<input type="hidden" name="cf_failure7" id="cf_failure7" value="Veuillez%20remplir%20tous%20les%20champs%20obligatoires%20SVP"/>
			<input type="hidden" name="cf_codeerr7" id="cf_codeerr7" value="Please%20double-check%20your%20verification%20code."/>
			<input type="hidden" name="cf_customerr7" id="cf_customerr7" value="yyy"/>
			<input type="hidden" name="cf_popup7" id="cf_popup7" value="nn"/>
		</fieldset>
		<p class="cf-sb"><input type="submit" name="sendbutton7" id="sendbutton7" class="sendbutton" value="S'inscrire" onclick="return cforms_validate('7', false)"/></p></form><p class="linklove" id="ll7"><a href="http://www.deliciousdays.com/cforms-plugin"><em>cforms</em> contact form by delicious:days</a></p>
<img src="http://feeds.feedburner.com/~r/LeBlogDesExpertsJ2ee/~4/ZJZ1pn4d5H8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ippon.fr/2011/05/30/ippevent-graniteds-pierre-angulaire-de-flex-inscriptions-ouvertes/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://blog.ippon.fr/2011/05/30/ippevent-graniteds-pierre-angulaire-de-flex-inscriptions-ouvertes/</feedburner:origLink></item>
	</channel>
</rss>

