<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	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/"
	>

<channel>
	<title>OCTO talks ! &#187; REST</title>
	<atom:link href="http://blog.octo.com/tag/rest/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.octo.com</link>
	<description>Le blog d&#039;OCTO Technology, cabinet d&#039;architectes en systèmes d&#039;information</description>
	<lastBuildDate>Fri, 03 Feb 2012 13:46:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Les implémentations JAX-RS (2)</title>
		<link>http://blog.octo.com/les-implementations-jax-rs-2/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=les-implementations-jax-rs-2</link>
		<comments>http://blog.octo.com/les-implementations-jax-rs-2/#comments</comments>
		<pubDate>Tue, 15 Mar 2011 13:01:10 +0000</pubDate>
		<dc:creator>Cyril PODER</dc:creator>
				<category><![CDATA[Architecture et technologies]]></category>
		<category><![CDATA[CXF]]></category>
		<category><![CDATA[JAX-RS]]></category>
		<category><![CDATA[jersey]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[RESTEasy]]></category>

		<guid isPermaLink="false">http://blog.octo.com/?p=19770</guid>
		<description><![CDATA[Dans l&#8217;article précédent nous avions abordé la mise en œuvre des implémentations JAX-RS Jersey et RESTEasy ainsi que celles de CXF et Restlet. Nous nous intéresserons dans cette seconde partie aux tests unitaires. Avant d&#8217;entrer dans le détail je souhaiterais attirer votre attention sur le fait que toutes ces implémentations offrent la possibilité de faire [...]
Suggestion d'articles :<ol>
<li><a href='http://blog.octo.com/jax-rs-cxf-vs-jersey-vs-resteasy/' rel='bookmark' title='Les implémentations JAX-RS (1)'>Les implémentations JAX-RS (1)</a></li>
<li><a href='http://blog.octo.com/la-strategie-de-test-dune-architecture-rest-13-test-dintegration/' rel='bookmark' title='La stratégie de test d&#8217;une architecture REST (2/3) &#8211; Test d’intégration'>La stratégie de test d&#8217;une architecture REST (2/3) &#8211; Test d’intégration</a></li>
<li><a href='http://blog.octo.com/la-strategie-de-test-d-une-architecture-rest-1-3-test-unitaire-dune-ressource/' rel='bookmark' title='La stratégie de test d&#8217;une architecture REST (1/3) &#8211; Test unitaire d’une ressource'>La stratégie de test d&#8217;une architecture REST (1/3) &#8211; Test unitaire d’une ressource</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fblog.octo.com%252Fles-implementations-jax-rs-2%252F%22%2C%20%22style%22%3A%20%22small%22%2C%20%22title%22%3A%20%22Les%20impl%C3%A9mentations%20JAX-RS%20%282%29%22%20%7D);"></div>
<p>Dans l&#8217;<a href="http://blog.octo.com/jax-rs-cxf-vs-jersey-vs-resteasy/">article</a> précédent nous avions abordé la mise en œuvre des implémentations JAX-RS Jersey et RESTEasy ainsi que celles de CXF et Restlet.</p>
<p>Nous nous intéresserons dans cette seconde partie aux <strong>tests unitaires</strong>.<br />
<span id="more-19770"></span><br />
Avant d&#8217;entrer dans le détail je souhaiterais attirer votre attention sur le fait que toutes ces implémentations offrent la possibilité de faire tourner des tests dans des <strong>serveurs embarqués</strong>, ce qui tient du <strong>test d&#8217;intégration</strong> et non du test unitaire.</p>
<p>Voyons maintenant dans quelle mesure chaque implémentation offre la possibilité de mocker le serveur.</p>
<h2>CXF</h2>
<p>Grosse déception ici : CXF n&#8217;offre pas de framework de test permettant de mocker le serveur&#8230;</p>
<p>On est donc limité à priori à tester nos services dans le serveur embarqué Jetty&#8230;</p>
<p>Il est cependant possible de s&#8217;en sortir en utilisant les <strong>classes de test de Spring</strong> :</p>

<div class="wp_codebox"><table><tr id="p197706"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="code" id="p19770code6"><pre class="java" style="font-family:monospace;">@RunWith<span style="color: #009900;">&#40;</span>SpringJUnit4ClassRunner.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span>
@ContextConfiguration<span style="color: #009900;">&#40;</span>locations <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> <span style="color: #0000ff;">&quot;classpath:testMockContext.xml&quot;</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> TestMockService <span style="color: #009900;">&#123;</span>
	@Autowired
	<span style="color: #000000; font-weight: bold;">private</span> ServletTransportFactory servletTransportFactory<span style="color: #339933;">;</span>
&nbsp;
	@Test
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> testGet1<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">IOException</span>, ServletException <span style="color: #009900;">&#123;</span>
		MockHttpServletRequest request <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> MockHttpServletRequest<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;GET&quot;</span>, <span style="color: #0000ff;">&quot;/someResource/1&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		request.<span style="color: #006633;">setContent</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> <span style="color: #000066; font-weight: bold;">byte</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		MockHttpServletResponse response <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> MockHttpServletResponse<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		ServletDestination destinationForPath <span style="color: #339933;">=</span> servletTransportFactory.<span style="color: #006633;">getDestinationForPath</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		destinationForPath.<span style="color: #006633;">invoke</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> MockServletContext<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>, request, response<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		assertEquals<span style="color: #009900;">&#40;</span>HttpServletResponse.<span style="color: #006633;">SC_OK</span>, response.<span style="color: #006633;">getStatus</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		assertEquals<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;{<span style="color: #000099; font-weight: bold;">\&quot;</span>someBean<span style="color: #000099; font-weight: bold;">\&quot;</span>:[{<span style="color: #000099; font-weight: bold;">\&quot;</span>someAttribute<span style="color: #000099; font-weight: bold;">\&quot;</span>:<span style="color: #000099; font-weight: bold;">\&quot;</span>someValue<span style="color: #000099; font-weight: bold;">\&quot;</span>}]}&quot;</span>,
				response.<span style="color: #006633;">getContentAsString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p><strong>MockHttpServletRequest</strong>, <strong>MockHttpServletResponse</strong> et <strong>MockServletContext</strong> sont des classes de <strong>spring-test</strong>.<br />
Afin d&#8217;avoir accès à la <strong>ServletTransportFactory</strong> il vous faudra importer le fichier cxf-servlet.xml dans votre configuration Spring de test :</p>

<div class="wp_codebox"><table><tr id="p197707"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p19770code7"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;import</span> <span style="color: #000066;">resource</span>=<span style="color: #ff0000;">&quot;classpath:META-INF/cxf/cxf-servlet.xml&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span></pre></td></tr></table></div>

<p>Enfin, l&#8217;appel à setContent, ligne 10, est nécessaire pour ne pas provoquer de NullPointerException de la part de CXF qui effectue un appel à getInputStream sur la requête sans vérifier si la valeur de retour de la méthode est null ou non.</p>
<h2>Jersey</h2>
<p>Jersey met à disposition du développeur un framework de test plutôt complet. La <a href="http://jersey.java.net/nonav/documentation/latest/user-guide.html#test-framework">documentation</a> est malheureusement un peu avare d&#8217;exemples et si l&#8217;utilisation de Spring avec les serveurs embarqués ne pose pas de problèmes particuliers, c&#8217;est une autre histoire dès lors que l&#8217;on souhaite utiliser le module jersey-test-framework-inmemory.</p>
<p>Afin d&#8217;utiliser le framework de test de Jersey, vos classes de test doivent en principe hériter de <strong>JerseyTest</strong> qui fait tout le travail d&#8217;initialisation et de configuration dans son constructeur qui n&#8217;a du coup <strong>pas accès aux beans Spring</strong>.</p>
<p>Afin d&#8217;avoir un test qui tourne avec le module de test inmemory et Spring, le résultat final ressemblera du coup à peu près à ceci :</p>

<div class="wp_codebox"><table><tr id="p197708"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
</pre></td><td class="code" id="p19770code8"><pre class="java" style="font-family:monospace;">@RunWith<span style="color: #009900;">&#40;</span>SpringJUnit4ClassRunner.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span>
@ContextConfiguration<span style="color: #009900;">&#40;</span>locations <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> <span style="color: #0000ff;">&quot;classpath:WEB-INF/applicationContext.xml&quot;</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> TestServiceInMemory <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">private</span> JerseyTest jersey<span style="color: #339933;">;</span>
&nbsp;
	@Autowired
	SomeService someService<span style="color: #339933;">;</span>
&nbsp;
	@Before
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> before<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Exception</span> <span style="color: #009900;">&#123;</span>
		jersey <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> JerseyTest<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> InMemoryTestContainerFactory<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #000000; font-weight: bold;">protected</span> com.<span style="color: #006633;">sun</span>.<span style="color: #006633;">jersey</span>.<span style="color: #006633;">test</span>.<span style="color: #006633;">framework</span>.<span style="color: #006633;">AppDescriptor</span> configure<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
				DefaultResourceConfig rc <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> DefaultResourceConfig<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				rc.<span style="color: #006633;">getSingletons</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>someService<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				rc.<span style="color: #006633;">getClasses</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>org.<span style="color: #006633;">codehaus</span>.<span style="color: #006633;">jackson</span>.<span style="color: #006633;">jaxrs</span>.<span style="color: #006633;">JacksonJsonProvider</span>.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				<span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000000; font-weight: bold;">new</span> LowLevelAppDescriptor.<span style="color: #006633;">Builder</span><span style="color: #009900;">&#40;</span>rc<span style="color: #009900;">&#41;</span>.<span style="color: #006633;">contextPath</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;poc-jersey&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">build</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
		jersey.<span style="color: #006633;">setUp</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	@Test
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> testGet1<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #003399;">String</span> result <span style="color: #339933;">=</span> jersey.<span style="color: #006633;">resource</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">path</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/someResource/1&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span>.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		assertEquals<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;{<span style="color: #000099; font-weight: bold;">\&quot;</span>someBean<span style="color: #000099; font-weight: bold;">\&quot;</span>:[{<span style="color: #000099; font-weight: bold;">\&quot;</span>someAttribute<span style="color: #000099; font-weight: bold;">\&quot;</span>:<span style="color: #000099; font-weight: bold;">\&quot;</span>someValue<span style="color: #000099; font-weight: bold;">\&quot;</span>}]}&quot;</span>, result<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	@After
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> after<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Exception</span> <span style="color: #009900;">&#123;</span>
		jersey.<span style="color: #006633;">tearDown</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<h2>RESTEasy</h2>
<p>Tout comme Jersey, RESTEasy fournit tout un framework de test. Là aussi la <a href="http://docs.jboss.org/resteasy/docs/2.0.0.GA/userguide/html_single/index.html#RESTEasy_Server-side_Mock_Framework">documentation</a> est plutôt succincte, mais en revanche son intégration avec Spring s&#8217;est avérée nettement plus simple voire intuitive.</p>
<p>A titre d&#8217;exemple voici le même test que précédemment adapté au framework de test de RESTEasy :</p>

<div class="wp_codebox"><table><tr id="p197709"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
</pre></td><td class="code" id="p19770code9"><pre class="java" style="font-family:monospace;">@RunWith<span style="color: #009900;">&#40;</span>SpringJUnit4ClassRunner.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span>
@ContextConfiguration<span style="color: #009900;">&#40;</span>locations <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> <span style="color: #0000ff;">&quot;classpath:WEB-INF/applicationContext.xml&quot;</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> TestMockedService <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">private</span> Dispatcher dispatcher <span style="color: #339933;">=</span> MockDispatcherFactory.<span style="color: #006633;">createDispatcher</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	@Autowired
	<span style="color: #000000; font-weight: bold;">private</span> SomeService someService<span style="color: #339933;">;</span>
&nbsp;
	@Before
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> before<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		dispatcher.<span style="color: #006633;">getRegistry</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">addSingletonResource</span><span style="color: #009900;">&#40;</span>someService<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	@Test
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> testGet1<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> URISyntaxException <span style="color: #009900;">&#123;</span>
		MockHttpRequest request <span style="color: #339933;">=</span> MockHttpRequest.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/someResource/1&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		MockHttpResponse response <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> MockHttpResponse<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		dispatcher.<span style="color: #006633;">invoke</span><span style="color: #009900;">&#40;</span>request, response<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		assertEquals<span style="color: #009900;">&#40;</span>HttpServletResponse.<span style="color: #006633;">SC_OK</span>, response.<span style="color: #006633;">getStatus</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		assertEquals<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;{<span style="color: #000099; font-weight: bold;">\&quot;</span>someBean<span style="color: #000099; font-weight: bold;">\&quot;</span>:[{<span style="color: #000099; font-weight: bold;">\&quot;</span>someAttribute<span style="color: #000099; font-weight: bold;">\&quot;</span>:<span style="color: #000099; font-weight: bold;">\&quot;</span>someValue<span style="color: #000099; font-weight: bold;">\&quot;</span>}]}&quot;</span>, response.<span style="color: #006633;">getContentAsString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>On appréciera la simplicité du code.<br />
Mon cœur qui balançait jusqu&#8217;à présent entre Jersey et RESTEasy penche cette fois définitivement en faveur de RESTEasy.</p>
<h2>Restlet</h2>
<p>Restlet est un peu à part puisqu&#8217;il propose sa propre API qui ne nécessite pas de tourner dans un serveur d&#8217;application. De fait il est relativement facile d&#8217;écrire des tests unitaires avec ce framework :</p>

<div class="wp_codebox"><table><tr id="p1977010"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="code" id="p19770code10"><pre class="java" style="font-family:monospace;">@RunWith<span style="color: #009900;">&#40;</span>SpringJUnit4ClassRunner.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span>
@ContextConfiguration<span style="color: #009900;">&#40;</span>locations <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> <span style="color: #0000ff;">&quot;classpath:WEB-INF/applicationContext.xml&quot;</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> TestMockedService <span style="color: #009900;">&#123;</span>
&nbsp;
	@Autowired
	<span style="color: #000000; font-weight: bold;">private</span> MyJaxrsApplication jaxrsApplication<span style="color: #339933;">;</span>
&nbsp;
	@Test
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> testGet1<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> URISyntaxException, <span style="color: #003399;">IOException</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #003399;">Request</span> request <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">Request</span><span style="color: #009900;">&#40;</span><span style="color: #003399;">Method</span>.<span style="color: #006633;">GET</span>, <span style="color: #0000ff;">&quot;/someResource/1&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		request.<span style="color: #006633;">getResourceRef</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">setBaseRef</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		request.<span style="color: #006633;">setOriginalRef</span><span style="color: #009900;">&#40;</span>request.<span style="color: #006633;">getResourceRef</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		request.<span style="color: #006633;">setRootRef</span><span style="color: #009900;">&#40;</span>request.<span style="color: #006633;">getResourceRef</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getBaseRef</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		Response response <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Response<span style="color: #009900;">&#40;</span>request<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		jaxrsApplication.<span style="color: #006633;">getJaxRsRestlet</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">handle</span><span style="color: #009900;">&#40;</span>request, response<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		assertEquals<span style="color: #009900;">&#40;</span>HttpServletResponse.<span style="color: #006633;">SC_OK</span>, response.<span style="color: #006633;">getStatus</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getCode</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		assertEquals<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;{<span style="color: #000099; font-weight: bold;">\&quot;</span>someBean<span style="color: #000099; font-weight: bold;">\&quot;</span>:[{<span style="color: #000099; font-weight: bold;">\&quot;</span>someAttribute<span style="color: #000099; font-weight: bold;">\&quot;</span>:<span style="color: #000099; font-weight: bold;">\&quot;</span>someValue<span style="color: #000099; font-weight: bold;">\&quot;</span>}]}&quot;</span>, response.<span style="color: #006633;">getEntity</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getText</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<h2>Performances</h2>
<p>Un dernier élément intéressant est celui des <strong>performances</strong>. J&#8217;utilise pour ma part le plugin <a href="http://code.google.com/p/infinitest/">Infinitest</a> pour Eclipse, il est donc essentiel que mes tests s&#8217;exécutent le plus rapidement possible.<br />
Le tableau suivant inclut les résultats obtenus pour le même test avec, puis sans serveur embarqué. Chaque implémentation utilisant un serveur embarqué différent j&#8217;ai indiqué le nom de ce dernier à chaque fois :</p>
<table cellspacing="0">
<tbody>
<tr style="font-weight: bold; background-color: #003366; color: #ffffff; text-align: center">
<td style="border: 1px solid #003366; border-right-color : white">Implémentation</td>
<td style="border: 1px solid #003366; border-right-color : white; border-left-color : white">Serveur</td>
<td style="border: 1px solid #003366; border-right-color : white; border-left-color : white">Durée du test avec serveur embarqué</td>
<td style="border: 1px solid #003366; border-left-color : white">Avec serveur mocké</td>
</tr>
<tr>
<td style="border: 1px solid #003366;">CXF</td>
<td style="border: 1px solid #003366;">Jetty</td>
<td style="border: 1px solid #003366;">1.6s</td>
<td style="border: 1px solid #003366;">1.4s</td>
</tr>
<tr>
<td style="border: 1px solid #003366;" rowspan="2">Jersey</td>
<td style="border: 1px solid #003366;">Grizzly</td>
<td style="border: 1px solid #003366;">3s</td>
<td style="border: 1px solid #003366;" rowspan="2">1.4s</td>
</tr>
<tr>
<td style="border: 1px solid #003366;">Embedded Glassfish</td>
<td style="border: 1px solid #003366;">4.4s</td>
</tr>
<tr>
<td style="border: 1px solid #003366;">RESTEasy</td>
<td style="border: 1px solid #003366;">TJWS</td>
<td style="border: 1px solid #003366;">0.8s</td>
<td style="border: 1px solid #003366;">0.7s</td>
</tr>
<tr>
<td style="border: 1px solid #003366;">Restlet</td>
<td style="border: 1px solid #003366;">Jetty</td>
<td style="border: 1px solid #003366;">1.2s</td>
<td style="border: 1px solid #003366;">0.9s</td>
</tr>
</tbody>
</table>
<h2>Conclusion</h2>
<p>Si la communauté derrière Jersey est semble-t-il plus active que celle derrière RESTEasy (impression personnelle basée uniquement sur la fréquence de sortie des milestones), ce dernier me paraît plus mature et surtout mieux pensé, surtout lorsque l&#8217;on aborde la question des tests unitaires.</p>
<p>CXF qui est pour sa part très puissant nécessite davantage de travail de configuration que ses deux concurrents. Il lui &laquo;&nbsp;suffirait&nbsp;&raquo; pourtant d&#8217;un mécanisme de détection automatique des services JAX-RS (et pourquoi pas JAX-WS ?) et des providers disponibles, ainsi que d&#8217;un vrai framework de test pour venir sérieusement les titiller.</p>
<p>Restlet, enfin, n&#8217;étant pas de base une implémentation de JAX-RS, fait plus figure de curiosité dans ce comparatif, même si côté performances dans les tests unitaires il s&#8217;en sort en seconde position derrière RESTEasy&#8230;</p>
<p>Au final, si à mon sens RESTEasy est aujourd&#8217;hui en tête, les quatre frameworks évoluent rapidement et mon classement pourrait être complètement chamboulé d&#8217;ici quelques mois. Il faut donc les surveiller de près&#8230; En outre, je ne me suis intéressé dans ces deux articles qu&#8217;au standard JAX-RS et il serait sans doute intéressant de voir ce qu&#8217;auraient à offrir d&#8217;autres framework REST tels que Restlet bien sûr, mais aussi Spring.</p>
<p>Pour finir voici un tableau récapitulatif :</p>
<table cellspacing="0">
<tbody>
<tr style="font-weight: bold; background-color: #003366; color: #ffffff; text-align: center">
<td style="border: 1px solid #003366; border-right-color : white">Implémentation</td>
<td style="border: 1px solid #003366; border-right-color : white; border-left-color : white">Configuration</td>
<td style="border: 1px solid #003366; border-right-color : white; border-left-color : white">Code</td>
<td style="border: 1px solid #003366; border-left-color : white">Tests</td>
</tr>
<tr>
<td style="border: 1px solid #003366;">CXF</td>
<td style="border: 1px solid #003366;">*</td>
<td style="border: 1px solid #003366;">***</td>
<td style="border: 1px solid #003366;">**</td>
</tr>
<tr>
<td style="border: 1px solid #003366;">Jersey</td>
<td style="border: 1px solid #003366;">***</td>
<td style="border: 1px solid #003366;">***</td>
<td style="border: 1px solid #003366;">*</td>
</tr>
<tr>
<td style="border: 1px solid #003366;">RESTEasy</td>
<td style="border: 1px solid #003366;">***</td>
<td style="border: 1px solid #003366;">***</td>
<td style="border: 1px solid #003366;">***</td>
</tr>
<tr>
<td style="border: 1px solid #003366;">Restlet</td>
<td style="border: 1px solid #003366;">**</td>
<td style="border: 1px solid #003366;">*</td>
<td style="border: 1px solid #003366;">***</td>
</tr>
</tbody>
</table>
<p>A noter que la note <strong>configuration</strong> tient compte de la qualité de la documentation et que dans le cas de Restlet les notes ne tiennent compte que de son utilisation dans le cadre bien particulier défini dans ces deux articles.</p>

 <img src="http://blog.octo.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=19770" width="1" height="1" style="display: none;" /><p>Suggestion d'articles :</p><ol>
<li><a href='http://blog.octo.com/jax-rs-cxf-vs-jersey-vs-resteasy/' rel='bookmark' title='Les implémentations JAX-RS (1)'>Les implémentations JAX-RS (1)</a></li>
<li><a href='http://blog.octo.com/la-strategie-de-test-dune-architecture-rest-13-test-dintegration/' rel='bookmark' title='La stratégie de test d&#8217;une architecture REST (2/3) &#8211; Test d’intégration'>La stratégie de test d&#8217;une architecture REST (2/3) &#8211; Test d’intégration</a></li>
<li><a href='http://blog.octo.com/la-strategie-de-test-d-une-architecture-rest-1-3-test-unitaire-dune-ressource/' rel='bookmark' title='La stratégie de test d&#8217;une architecture REST (1/3) &#8211; Test unitaire d’une ressource'>La stratégie de test d&#8217;une architecture REST (1/3) &#8211; Test unitaire d’une ressource</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.octo.com/les-implementations-jax-rs-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Les implémentations JAX-RS (1)</title>
		<link>http://blog.octo.com/jax-rs-cxf-vs-jersey-vs-resteasy/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=jax-rs-cxf-vs-jersey-vs-resteasy</link>
		<comments>http://blog.octo.com/jax-rs-cxf-vs-jersey-vs-resteasy/#comments</comments>
		<pubDate>Wed, 02 Mar 2011 09:15:30 +0000</pubDate>
		<dc:creator>Cyril PODER</dc:creator>
				<category><![CDATA[Architecture et technologies]]></category>
		<category><![CDATA[CXF]]></category>
		<category><![CDATA[JAX-RS]]></category>
		<category><![CDATA[jersey]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[RESTEasy]]></category>

		<guid isPermaLink="false">http://blog.octo.com/?p=19042</guid>
		<description><![CDATA[Il y a quelque temps l&#8217;envie de développer une petite application Java RESTFul m&#8217;a pris subitement. Je me suis donc penché sur les différentes implémentations JAX-RS et voici le résultat de mon investigation. Je me suis tout de même posé quelques contraintes : que mon code Java soit complètement indépendant de l&#8217;implémentation JAX-RS choisie ; [...]
Suggestion d'articles :<ol>
<li><a href='http://blog.octo.com/les-implementations-jax-rs-2/' rel='bookmark' title='Les implémentations JAX-RS (2)'>Les implémentations JAX-RS (2)</a></li>
<li><a href='http://blog.octo.com/la-strategie-de-test-dune-architecture-rest-13-test-dintegration/' rel='bookmark' title='La stratégie de test d&#8217;une architecture REST (2/3) &#8211; Test d’intégration'>La stratégie de test d&#8217;une architecture REST (2/3) &#8211; Test d’intégration</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fblog.octo.com%252Fjax-rs-cxf-vs-jersey-vs-resteasy%252F%22%2C%20%22style%22%3A%20%22small%22%2C%20%22title%22%3A%20%22Les%20impl%C3%A9mentations%20JAX-RS%20%281%29%22%20%7D);"></div>
<p>Il y a quelque temps l&#8217;envie de développer une petite application Java RESTFul m&#8217;a pris subitement. Je me suis donc penché sur les différentes implémentations JAX-RS et voici le résultat de mon investigation.</p>
<p>Je me suis tout de même posé quelques contraintes :</p>
<ul>
<li>que mon code Java soit complètement indépendant de l&#8217;implémentation JAX-RS choisie ;</li>
<li>pouvoir facilement intégrer mes services avec Spring ;</li>
<li>ne produire et consommer que du JSON en utilisant l&#8217;API Jackson ;</li>
<li>pouvoir facilement mettre en place des tests unitaires.</li>
</ul>
<p>Ce qui m&#8217;amène à comparer trois implémentations : <a href="http://cxf.apache.org">CXF</a> (version 2.3.2), <a href="http://jersey.java.net/">Jersey</a> (version 1.5), <a href="http://www.jboss.org/resteasy">RESTEasy</a> (version 2.1.0.GA) et <a href="http://www.restlet.org/">Restlet</a> (version 2.0.5).<br />
<span id="more-19042"></span><br />
CXF, Jersey et RESTEasy utilisent <a href="http://jettison.codehaus.org/">Jettison</a> pour produire et consommer du JSON. Or <strong>Jettison</strong> est un outil de <strong>mapping JSON/XML</strong> or je souhaite effectuer un simple <strong>mapping POJO/JSON</strong>. Raison pour laquelle j&#8217;opte pour <a href="http://jackson.codehaus.org/">Jackson</a>.</p>
<p>Je partirai du principe qu&#8217;une certaine connaissance de <strong>JAX-RS</strong>, <strong>Spring</strong> et <strong>Maven</strong> est acquise par mes lecteurs.</p>
<p>Concernant les performances, je ne m&#8217;attarderai pas dessus car il s&#8217;avère qu&#8217;elles se tiennent dans un mouchoir de poche.</p>
<p>Les sources sont disponibles sur <a href="https://github.com/cpoder/poc-jax-rs">Github</a>.</p>
<p>Sans plus attendre, revêtons notre bleu de travail, calons notre crayon derrière l&#8217;oreille et mettons les mains dans le cambouis&#8230;</p>
<h2>Le service</h2>
<p>Voici le code &#8211; on ne peut plus simple &#8211; du service que l&#8217;on se propose de déployer :</p>

<div class="wp_codebox"><table><tr id="p1904220"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
</pre></td><td class="code" id="p19042code20"><pre class="java" style="font-family:monospace;">@Path<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/someResource&quot;</span><span style="color: #009900;">&#41;</span>
@Service
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> SomeService <span style="color: #009900;">&#123;</span>
	@Resource
	<span style="color: #000000; font-weight: bold;">private</span> BeanRepo beanRepo<span style="color: #339933;">;</span>
&nbsp;
	@GET
	@Produces<span style="color: #009900;">&#40;</span>MediaType.<span style="color: #006633;">APPLICATION_JSON</span><span style="color: #009900;">&#41;</span>
	<span style="color: #000000; font-weight: bold;">public</span> List<span style="color: #339933;">&lt;</span>SomeBean<span style="color: #339933;">&gt;</span> getSomeBeans<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000000; font-weight: bold;">return</span> beanRepo.<span style="color: #006633;">getAll</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	@GET
	@Produces<span style="color: #009900;">&#40;</span>MediaType.<span style="color: #006633;">APPLICATION_JSON</span><span style="color: #009900;">&#41;</span>
	@Path<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;{index}&quot;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #000000; font-weight: bold;">public</span> SomeBean getSomeBean<span style="color: #009900;">&#40;</span>@PathParam<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;index&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #000066; font-weight: bold;">int</span> index<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000000; font-weight: bold;">return</span> beanRepo.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>index<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	@PUT
	@Consumes<span style="color: #009900;">&#40;</span>MediaType.<span style="color: #006633;">APPLICATION_JSON</span><span style="color: #009900;">&#41;</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> saveSomeBean<span style="color: #009900;">&#40;</span>SomeBean someBean<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		beanRepo.<span style="color: #006633;">save</span><span style="color: #009900;">&#40;</span>someBean<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>On remarquera l&#8217;utilisation des annotations @Produces et @Consumes qui indiquent que l&#8217;on ne produit et consomme ici que du JSON.</p>
<h2>CXF</h2>
<p>On ne présente plus CXF, la stack par excellence pour développer des services en Java supportant tous types de transports et de protocoles et aux performances qui ne sont plus à démontrer.</p>
<p>Et si vous n&#8217;êtes toujours pas convaincus, allez donc jeter un œil aux articles référencés <a href="http://cxf.apache.org/resources-and-articles.html">ici</a> ou <a href="http://blog.octo.com/cxf-ou-axis-quelques-chiffres/">là</a>.</p>
<p>Certains argueront qu&#8217;utiliser CXF pour du REST c&#8217;est comme aller chercher un couteau suisse pour ouvrir une bière quand un simple décapsuleur était à portée de main&#8230;</p>
<h3>Dépendances</h3>
<p>La documentation de CXF est très bien fournie à ce niveau. Cependant l&#8217;artifact Maven cxf-rt-frontend-jaxrs ramène toutes les dépendances permettant d&#8217;effectuer des mappings XML ainsi que Jettison, ce dont je n&#8217;ai pas besoin.</p>
<p>Afin de n&#8217;importer que le strict nécessaire mon POM ressemble donc à ceci :</p>

<div class="wp_codebox"><table><tr id="p1904221"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
</pre></td><td class="code" id="p19042code21"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.apache.cxf<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>cxf-rt-frontend-jaxrs<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>${cxf.version}<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #808080; font-style: italic;">&lt;!-- Since we use jackson, we can get rid of Jettison and all XML stuff --&gt;</span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exclusions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.apache.xmlbeans<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>xmlbeans<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>com.sun.xml.bind<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>jaxb-impl<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.codehaus.woodstox<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>woodstox-core-asl<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.codehaus.jettison<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>jettison<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>cxf-rt-databinding-aegis<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.apache.cxf<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/exclusions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<h3>Configuration Spring</h3>
<p>CXF gérant différents types de transports et de protocoles, il nécessite <strong>davantage de configuration</strong> que ses &laquo;&nbsp;concurrents&nbsp;&raquo; avec notamment l&#8217;import des fichiers de configuration CXF, le namespace jaxrs à définir et enfin la déclaration et configuration systématique de chaque service&#8230;</p>
<p>En outre la documentation n&#8217;explique pas très clairement comment intégrer Jackson et si vous êtes nouveau sur CXF il vous faudra parcourir toute la documentation avant de comprendre comment ajouter un provider à un service REST (ce qui en fin de compte n&#8217;est pas bien compliqué comme le montre la suite).</p>
<p>L&#8217;essentiel de la documentation se trouve <a href="http://cxf.apache.org/docs/jax-rs-basics.html#JAX-RSBasics-Registeringcustomproviders">ici</a> et <a href="http://cxf.apache.org/docs/jax-rs-data-bindings.html#JAX-RSDataBindings-ConfiguringJSONprovider">là</a>. Pour faire court, le principe est de fournir un provider JSON à nos services :</p>

<div class="wp_codebox"><table><tr id="p1904222"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code" id="p19042code22"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;jaxrs:server</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;someService&quot;</span> <span style="color: #000066;">transportId</span>=<span style="color: #ff0000;">&quot;http://cxf.apache.org/transports/http&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;jaxrs:serviceBeans<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bean</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;com.octo.rest.SomeService&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/jaxrs:serviceBeans<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;jaxrs:providers<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bean</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;org.codehaus.jackson.jaxrs.JacksonJsonProvider&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/jaxrs:providers<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/jaxrs:server<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Simple certes, mais <strong>il faut le faire pour chaque service</strong> !</p>
<p>On notera l&#8217;attribut <strong>transportId</strong> sur la balise jaxrs:server, qui par défaut vaut http://schemas.xmlsoap.org/wsdl/http (donc du SOAP, ce qui n&#8217;est pas vraiment ce que l&#8217;on veut).</p>
<p>Il est possible de ne pas avoir à redéfinir le provider pour chacun de ses services, mais il faut creuser un peu dans les classes de CXF. En l&#8217;occurrence il suffit de manipuler directement la ProviderFactory :</p>

<div class="wp_codebox"><table><tr id="p1904223"><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code" id="p19042code23"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bean</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;org.apache.cxf.jaxrs.provider.ProviderFactory&quot;</span> <span style="color: #000066;">factory-method</span>=<span style="color: #ff0000;">&quot;getSharedInstance&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;userProviders&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bean</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;org.codehaus.jackson.jaxrs.JacksonJsonProvider&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/bean<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Bref CXF qui est génial pour faire du SOAP et du RPC dans tous les sens dans des architectures hétérogènes tout en garantissant d&#8217;excellentes performances n&#8217;est ici clairement pas la solution la plus pratique à mettre en œuvre.</p>
<h2>Jersey</h2>
<p>C&#8217;est l&#8217;implémentation de référence de JAX-RS, simple, efficace et performante.</p>
<p>Afin d&#8217;utiliser Jackson avec Jersey il nous faut :</p>
<ul>
<li>importer l&#8217;artefact <strong>jersey-json</strong></li>
<li>mettre à <strong>true</strong> la propriété <strong>com.sun.jersey.api.json.POJOMappingFeature</strong> au niveau de la servlet Jersey dans le web.xml. Cette propriété indique que l&#8217;on souhaite mapper nos POJO  directement sur du JSON au lieu du XML.</li>
</ul>
<p>Ce dernier point est parfaitement expliqué dans la <a href="http://jersey.java.net/nonav/documentation/latest/user-guide.html#d4e878">documentation</a> par ailleurs assez complète.</p>
<p>Enfin, la configuration Spring est on ne peut plus simple puisqu&#8217;il suffit d&#8217;activer la gestion des annotations.</p>
<h3>Dépendances</h3>
<p>Là encore un nettoyage est nécessaire si l&#8217;on ne souhaite importer que l&#8217;essentiel :</p>

<div class="wp_codebox"><table><tr id="p1904224"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
</pre></td><td class="code" id="p19042code24"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>com.sun.jersey.contribs<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>jersey-spring<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.5<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>com.sun.jersey<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>jersey-json<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.5<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exclusions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.codehaus.jackson<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>jackson-core-asl<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.codehaus.jackson<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>jackson-mapper-asl<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>jaxb-impl<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>com.sun.xml.bind<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>jettison<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.codehaus.jettison<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/exclusions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Jersey est donc extrêmement simple à mettre en œuvre et s&#8217;avère largement suffisant pour mon utilisation.</p>
<h2>RESTEasy</h2>
<p>Pour finir voici l&#8217;implémention de JBoss de JAX-RS. Ses avantages sont principalement :</p>
<ul>
<li>son intégration assez poussée avec le serveur <strong>JBoss</strong></li>
<li>son intégration avec, outre Spring, <strong>Spring-MVC</strong>, <strong>Guice</strong>, <strong>Seam</strong></li>
</ul>
<p>Comme les autres implémentations, RESTEasy utilise Jettison par défaut comme provider JSON. Pour utiliser Jackson, il suffit d&#8217;importer l&#8217;artefact resteasy-jackson-provider et le tour est joué.</p>
<p>J&#8217;ajouterai que RESTEasy fournit probablement la documentation la plus complète des trois implémentations.</p>
<h3>Dépendances</h3>
<p>Une fois de plus il faudra faire du nettoyage dans le POM :</p>

<div class="wp_codebox"><table><tr id="p1904225"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
</pre></td><td class="code" id="p19042code25"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.jboss.resteasy<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>resteasy-spring<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>2.1.0.GA<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exclusions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.jboss.resteasy<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>resteasy-jaxb-provider<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>resteasy-jettison-provider<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.jboss.resteasy<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/exclusions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.jboss.resteasy<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>resteasy-jackson-provider<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>2.1.0.GA<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exclusions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.codehaus.jackson<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>jackson-core-asl<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.codehaus.jackson<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>jackson-mapper-asl<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/exclusions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>On notera qu&#8217;alors que l&#8217;artefact resteasy-jackson-provider n&#8217;importe bien que l&#8217;essentiel, ce qui offre un avantage intéressant comparé à ses concurrents. resteasy-spring importe malheureusement indirectement des providers via resteasy-core qu&#8217;il me faut exclure.</p>
<h2>Restlet</h2>
<p>Restlet est initialement une solution Java RESTFul conçue pour fonctionner de <strong>manière autonome</strong> contrairement aux frameworks précédents.<br />
Restlet propose néanmoins diverses extensions dont une offrant la possibilité de le faire fonctionner au sein d&#8217;un conteneur de <a href="http://wiki.restlet.org/docs_2.1/13-restlet/28-restlet/81-restlet.html">servlets</a>, une autre offrant le support <a href="http://wiki.restlet.org/docs_2.1/13-restlet/28-restlet/57-restlet.html">JAX-RS</a> et une autre le support de <a href="http://wiki.restlet.org/docs_2.1/13-restlet/28-restlet/70-restlet.html">Spring</a>.<br />
Par conséquent cette partie de l&#8217;article n&#8217;est pas forcément pertinente dans le sens où elle montre une <strong>utilisation de Restlet plutôt bancale</strong>, mais me semble néanmoins intéressante.</p>
<h3>Dépendances</h3>
<p>Un petit nettoyage du POM s&#8217;impose pour ne garder que l&#8217;essentiel :</p>

<div class="wp_codebox"><table><tr id="p1904226"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
</pre></td><td class="code" id="p19042code26"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.restlet.jee<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.restlet.ext.jaxrs<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>2.0.5<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exclusions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>jaxb-impl<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>com.sun.xml.bind<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>jaxb-api<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>javax.xml.bind<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.restlet.lib.org.json<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.restlet.jee<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>stax-api<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>javax.xml.stream<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/exclusions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.restlet.jee<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.restlet.ext.spring<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>2.0.5<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exclusions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>spring-webmvc<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.springframework<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/exclusion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/exclusions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<h3>Un peu de code</h3>
<p>Il va nous falloir un minimum de code supplémentaire qui va servir de glue entre Restlet, JAX-RS, Spring et mon conteneur de servlets.<br />
Cette &laquo;&nbsp;glue&nbsp;&raquo; se limite à une classe :</p>

<div class="wp_codebox"><table><tr id="p1904227"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
</pre></td><td class="code" id="p19042code27"><pre class="java" style="font-family:monospace;">@<span style="color: #003399;">Component</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;jaxrsApp&quot;</span><span style="color: #009900;">&#41;</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> MyJaxrsApplication <span style="color: #000000; font-weight: bold;">extends</span> JaxRsApplication <span style="color: #009900;">&#123;</span>
	@Autowired
	<span style="color: #000000; font-weight: bold;">public</span> MyJaxrsApplication<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> ApplicationContext context<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000000; font-weight: bold;">super</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		add<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> Application<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #000000; font-weight: bold;">private</span> Set<span style="color: #339933;">&lt;</span>Class<span style="color: #339933;">&lt;?&gt;&gt;</span> classes <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> HashSet<span style="color: #339933;">&lt;</span>Class<span style="color: #339933;">&lt;?&gt;&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #000000; font-weight: bold;">private</span> Set<span style="color: #339933;">&lt;</span>Object<span style="color: #339933;">&gt;</span> singletons <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> HashSet<span style="color: #339933;">&lt;</span>Object<span style="color: #339933;">&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#123;</span>
				<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>context.<span style="color: #006633;">getBeansWithAnnotation</span><span style="color: #009900;">&#40;</span>Path.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
					<span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">Object</span> bean <span style="color: #339933;">:</span> context.<span style="color: #006633;">getBeansWithAnnotation</span><span style="color: #009900;">&#40;</span>Path.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">values</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
						classes.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>bean.<span style="color: #006633;">getClass</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				singletons.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> JacksonJsonProvider<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span>
&nbsp;
			@Override
			<span style="color: #000000; font-weight: bold;">public</span> Set<span style="color: #339933;">&lt;</span>Class<span style="color: #339933;">&lt;?&gt;&gt;</span> getClasses<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
				<span style="color: #000000; font-weight: bold;">return</span> classes<span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span>
&nbsp;
			@Override
			<span style="color: #000000; font-weight: bold;">public</span> Set<span style="color: #339933;">&lt;</span>Object<span style="color: #339933;">&gt;</span> getSingletons<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
				<span style="color: #000000; font-weight: bold;">return</span> singletons<span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span>
		<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		setObjectFactory<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">ObjectFactory</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #339933;">&lt;</span>T<span style="color: #339933;">&gt;</span> T getInstance<span style="color: #009900;">&#40;</span>Class<span style="color: #339933;">&lt;</span>T<span style="color: #339933;">&gt;</span> jaxRsClass<span style="color: #009900;">&#41;</span>
					<span style="color: #000000; font-weight: bold;">throws</span> InstantiateException <span style="color: #009900;">&#123;</span>
				<span style="color: #000000; font-weight: bold;">return</span> context.<span style="color: #006633;">getBean</span><span style="color: #009900;">&#40;</span>jaxRsClass<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span>
		<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Je n&#8217;entrerai pas ici dans le détail du fonctionnement de Restlet &#8211; ce qui serait hors sujet -, néanmoins certains éléments nécessitent quelques précisions.<br />
La classe Application est celle de la JSR-311 dont les méthodes getClasses et getSingletons sont censées retourner les classes ou singletons correspondant à des ressources REST ou des providers.<br />
Il semblerait logique de fournir les ressources REST via la méthode getSingletons en allant les chercher dans le conteneur IoC de Spring. Malheureusement Restlet ne permet cela pour l&#8217;instant que pour les providers, les ressources devant nécessairement être fournies par la méthode getClasses.<br />
Fort heureusement, la classe JaxRsApplication possède la méthode setObjectFactory qui va nous permettre de définir de quelle manière Restlet va instancier les classes renvoyées par la méthode getClasses.<br />
Il faut ensuite configurer la servlet SpringServerServlet dans le web.xml en lui fournissant en paramètre le nom du bean Spring correspondant à l&#8217;application Restlet :</p>

<div class="wp_codebox"><table><tr id="p1904228"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code" id="p19042code28"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;servlet<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;servlet-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Restlet<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;servlet-class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.restlet.ext.spring.SpringServerServlet<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet-class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;init-param<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;param-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.restlet.application<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/param-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;param-value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>jaxrsApp<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/param-value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/init-param<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;load-on-startup<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/load-on-startup<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;servlet-mapping<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;servlet-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Restlet<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;url-pattern<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>/*<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/url-pattern<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet-mapping<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<h2>Conclusion</h2>
<p>Nous voici arrivés à la fin de la première partie de ce tour d&#8217;horizon des implémentations JAX-RS.</p>
<p>Que peut-on conclure à l&#8217;issue de cette première partie ?</p>
<p>CXF est incontestablement très <strong>puissant</strong>, et justement trop en l&#8217;occurrence. D&#8217;un autre côté, si pour une raison quelconque je devais passer à une <strong>architecture hétérogène</strong>, je sais qu&#8217;un passage vers CXF serait parfaitement envisageable et que la transition se ferait sans douleurs, puisque consistant essentiellement en un <strong>travail de configuration Spring</strong> (certes rébarbatif).</p>
<p>Concernant Restlet, comme dit précédemment, ce n&#8217;est pas vraiment une utilisation normale du framework qui est proposée ici, celui-ci se positionnant plus comme une <strong>alternative à JAX-RS</strong>.</p>
<p>Jersey et RESTEasy offrent <strong>simplicité</strong> et <strong>performance</strong> et collent parfaitement à mes besoins.</p>
<p>A mon sens, le choix entre RESTEasy et Jersey dépendra en partie du choix du serveur d&#8217;application : si vous optez pour JBoss, RESTEasy offre des avantages certains.</p>
<p>D&#8217;un autre côté la communauté derrière le projet Jersey, dont la dernière version date de janvier, semble bien plus active que celle de RESTEasy.</p>
<p>Reste toutefois un point essentiel à aborder : les tests, que nous verrons dans un prochain article et qui pourraient bien faire pencher la balance.</p>
<p>En attendant vous pouvez déjà jeter un oeil aux <a href="https://github.com/cpoder/poc-jax-rs">sources</a>.</p>

 <img src="http://blog.octo.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=19042" width="1" height="1" style="display: none;" /><p>Suggestion d'articles :</p><ol>
<li><a href='http://blog.octo.com/les-implementations-jax-rs-2/' rel='bookmark' title='Les implémentations JAX-RS (2)'>Les implémentations JAX-RS (2)</a></li>
<li><a href='http://blog.octo.com/la-strategie-de-test-dune-architecture-rest-13-test-dintegration/' rel='bookmark' title='La stratégie de test d&#8217;une architecture REST (2/3) &#8211; Test d’intégration'>La stratégie de test d&#8217;une architecture REST (2/3) &#8211; Test d’intégration</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.octo.com/jax-rs-cxf-vs-jersey-vs-resteasy/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Alfresco est il une solution pour votre entreprise ?</title>
		<link>http://blog.octo.com/alfresco-est-il-une-solution-pour-votre-entreprise/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=alfresco-est-il-une-solution-pour-votre-entreprise</link>
		<comments>http://blog.octo.com/alfresco-est-il-une-solution-pour-votre-entreprise/#comments</comments>
		<pubDate>Sun, 05 Jul 2009 17:33:48 +0000</pubDate>
		<dc:creator>Rémy SAISSY</dc:creator>
				<category><![CDATA[Architecture et technologies]]></category>
		<category><![CDATA[collaboratif]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[REST]]></category>

		<guid isPermaLink="false">http://blog.octo.com/?p=3834</guid>
		<description><![CDATA[En ce moment, on entend beaucoup parler de collaboratif, d&#8217;entreprise 2.0, de wiki, &#8230; et aussi d&#8217;Alfresco. Logiciel libre, grosse communauté, architecture logicielle très proche de celle de Documentum mais avec des technologies plus récentes, Alfresco est une solution de gestion électronique de documents qui a semble-t-il tout pour plaire. Cela dit tout le monde [...]
Suggestion d'articles :<ol>
<li><a href='http://blog.octo.com/architecture-dynamique/' rel='bookmark' title='Architecture Dynamique basée sur la solution Grails'>Architecture Dynamique basée sur la solution Grails</a></li>
<li><a href='http://blog.octo.com/la-federation-d%e2%80%99identite-en-entreprise/' rel='bookmark' title='La fédération d’identité en entreprise'>La fédération d’identité en entreprise</a></li>
<li><a href='http://blog.octo.com/tours-jug-apache-maven-mise-en-uvre-en-entreprise/' rel='bookmark' title='Tours JUG &#8211; Apache Maven, mise en œuvre en entreprise'>Tours JUG &#8211; Apache Maven, mise en œuvre en entreprise</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fblog.octo.com%252Falfresco-est-il-une-solution-pour-votre-entreprise%252F%22%2C%20%22style%22%3A%20%22small%22%2C%20%22title%22%3A%20%22Alfresco%20est%20il%20une%20solution%20pour%20votre%20entreprise%20%3F%22%20%7D);"></div>
<p style="text-align: justify;">En ce moment, on entend beaucoup parler de collaboratif, d&#8217;entreprise 2.0, de wiki, &#8230; et aussi d&#8217;<a href="http://www.alfresco.com/">Alfresco</a>.</p>
<p style="text-align: justify;">Logiciel libre, grosse communauté, architecture logicielle très proche de celle de <a href="http://www.documentum.com/">Documentum</a> mais avec des technologies plus récentes, Alfresco est une solution de gestion électronique de documents qui a semble-t-il tout pour plaire.</p>
<p style="text-align: justify;">Cela dit tout le monde sait bien que la solution ultime et universelle n&#8217;existe pas et en vertu de cela je vous propose de faire une petite revue de l&#8217;adéquation entre des besoins courants et la manière dont Alfresco y répond, l&#8217;objectif étant de vous fournir un premier aperçu de ce qu&#8217;est Alfresco.</p>
<p style="text-align: justify;">Cet article n&#8217;a pas pour but de vous &laquo;&nbsp;vendre&nbsp;&raquo; ou de vous décourager d&#8217;utiliser Alfresco mais simplement de donner un aperçu des possibilités du produit. N&#8217;hésitez pas à me faire part de vos remarques, demandes d&#8217;informations, &#8230;</p>
<p><span id="more-3834"></span></p>
<p style="text-align: justify;">
<h3 style="text-align: justify;"><em><strong>J&#8217;ai besoin de stocker mes données de façon organisée.</strong></em></h3>
<p style="text-align: justify;">Si votre besoin s&#8217;arrête à cela, un partage <a href="http://fr.wikipedia.org/wiki/Network_File_System">NFS</a> ou <a href="http://fr.wikipedia.org/wiki/CIFS">CIFS</a> sera amplement suffisant.</p>
<p style="text-align: justify;">Si par contre vous avez besoin &laquo;&nbsp;d&#8217;intelligence&nbsp;&raquo; dans cette organisation des données, Alfresco pourrait répondre à votre besoin car il intègre un mécanisme d&#8217;orchestration d&#8217;actions qui peuvent se déclencher lorsque l&#8217;on touche à son dépôt de données. Pour faire simple il est possible d&#8217;enchaîner des actions à l&#8217;ajout, la modification ou la suppression d&#8217;une donnée sur le dépôt. Ces dernières pouvant aller de la simple copie à la transformation d&#8217;un format à un autre en passant par la notification automatique des ayant droit sur la donnée.</p>
<h3 style="text-align: justify;"><em>J&#8217;ai besoin de capitaliser sur une base de connaissances.</em></h3>
<p style="text-align: justify;">Cela tombe bien, Alfresco est justement avant tout une solution de gestion documentaire !</p>
<p style="text-align: justify;">Dans Alfresco, toute donnée ajoutée est stockée en un point bien identifié sur un support de stockage de masse. La suppression d&#8217;une donnée ne la supprime pas du support mais la met en quinzaine voire plus longtemps si vous préférez. De cette manière, vous limitez le risque de perte accidentelle d&#8217;information.</p>
<h3 style="text-align: justify;"><em><strong>J&#8217;ai besoin de mettre en place des workflows complexes des directions métiers sur les données stockées.</strong></em></h3>
<p style="text-align: justify;">Alfresco utilise le moteur de workflow <a href="http://www.jboss.org/jbossjbpm/">JBPM</a> ce qui lui permet de traiter des workflows allant de la simple validation d&#8217;un document par un tiers à des processus complexes entièrement modélisés avec jBPM Process Designer par exemple.</p>
<p style="text-align: justify;">En outre, les mécanismes d&#8217;orchestration d&#8217;actions sur le dépôt de données permettent de transformer, déplacer, copier, envoyer par courriel, &#8230; toute donnée stockée sur Alfresco.</p>
<h3 style="text-align: justify;"><em><strong>J&#8217;ai besoin de pouvoir enrichir les données stockées.</strong></em></h3>
<p style="text-align: justify;">Alfresco repose entièrement sur un mécanisme de modèle de données. Toute donnée stockée, des utilisateurs et leurs droits d&#8217;accès aux documents en passant par les répertoires sont des éléments d&#8217;un modèle de données.</p>
<p style="text-align: justify;">Je dis &#8216;un&#8217; et non &#8216;le&#8217; parce que la solution est faîte de sorte que les développements spécifiques, les besoins métiers tels que l&#8217;enrichissement des données stockées sont effectués sous la forme de l&#8217;adjonction de modèles de données personnalisés au modèle livré d&#8217;origine.</p>
<p style="text-align: justify;">Et puis de toutes façons, même d&#8217;origine, il y a déjà plusieurs modèles de données dans Alfresco à savoir :</p>
<ul style="text-align: justify;">
<li> un pour les types de données comme les répertoires, les images, les documents;</li>
<li>un pour les habilitations;</li>
<li>un pour les workflows.</li>
</ul>
<p style="text-align: justify;">Enrichir est quelque chose de naturel et facile à effectuer pour Alfresco.</p>
<h3 style="text-align: justify;"><em><strong>J&#8217;ai besoin de gérer finement les droits d&#8217;accès à mes données.</strong></em></h3>
<p style="text-align: justify;">Si les habilitations par défaut ne conviennent pas, Alfresco permet de définir son propre modèle de permission. Autrement, sachez que les accès peuvent se gérer au niveau donnée, au niveau répertoire, que des quotas utilisateurs peuvent être appliqués.</p>
<p style="text-align: justify;">En outre, Alfresco gère des rôles. Mais qu&#8217;est ce qu&#8217;un rôle ? Juste un ensemble de permissions. On affecte des rôles à des utilisateurs ou des groupes d&#8217;utilisateurs par donnée ou par répertoire.</p>
<p style="text-align: justify;">Par défaut, les rôles suivants sont proposés, libre à vous de les enrichir :</p>
<ul style="text-align: justify;">
<li> administrateur;</li>
<li>coordinateur;</li>
<li>collaborateur;</li>
<li>contributeur;</li>
<li>éditeur;</li>
<li>lecteur.</li>
</ul>
<p style="text-align: justify;">Nous pourrons en parler plus longuement dans un autre article.</p>
<h3 style="text-align: justify;"><em><strong>J&#8217;ai besoin d&#8217;avoir un accès distant à mes données.</strong></em></h3>
<p style="text-align: justify;">Alfresco propose plusieurs méthodes d&#8217;accès aux données.</p>
<h4 style="text-align: justify;">L&#8217;interface <em>web-client</em></h4>
<p style="text-align: justify;">Interface web historique du produit, elle n&#8217;évolue plus aujourd&#8217;hui. Cette interface présente plusieurs particularités :</p>
<ul>
<li>accès quasi-exhaustif aux fonctionnalités de l&#8217;outil ce qui la rend inutilisable pour un utilisateur lambda;</li>
<li>panneau d&#8217;administration bien fourni (gestion des groupes, des utilisateurs, des rôles, du dépôt, des workflows, &#8230;);</li>
<li>capacité à être adaptée moyennant un peu de configuration (des xml à modifier et écrire peuvent influer sur tous les boutons de l&#8217;interface);</li>
<li>doit tourner sur la même instance que le coeur d&#8217;Alfresco, la partie gestion documentaire.</li>
</ul>
<p>Je vous déconseille d&#8217;utiliser cette interface sauf pour des besoins d&#8217;administration. Pour les métiers, il vaut souvent mieux développer une interface correspondant aux attentes se basant sur les API d&#8217;accès distant d&#8217;Alfresco.</p>
<h4>L&#8217;interface share</h4>
<p>Share est le nouveau client léger proposé par Alfresco. Il s&#8217;agit d&#8217;un site collaboratif orienté utilisateurs et non administrateur. Pas de panneau d&#8217;administration donc mais un fonctionnement sur le mode d&#8217;un portail comme Liferay consommant des services provenant du coeur d&#8217;Alfresco au travers de l&#8217;API REST.</p>
<h4 style="text-align: justify;">API REST et SOAP</h4>
<p>Alfresco expose ses fonctionnalités sous la forme d&#8217;une API REST eǵalement appelée Webscript et d&#8217;une API SOAP.</p>
<p>Ces deux API sont très complètes et permettent de concevoir des interfaces client léger ou lourd qui tourneront sur un serveur autre que le serveur de gestion documentaire, lui permettant ainsi de se concentrer sur sa tâche principale, la gestion documentaire.</p>
<h4>L&#8217;API CMIS</h4>
<p>Dernière née des API disponibles pour communiquer avec Alfresco, <a href="http://wiki.alfresco.com/wiki/CMIS">CMIS</a> a été implémenté dans Alfresco 3 dans un effort d&#8217;intéropérabilité des accès aux dépôts de solutions de gestion documentaire. Concrètement, cette norme défini une interface standard pour accéder à un dépôt documentaire qu&#8217;il soit sous Alfresco, sous Sharepoint ou d&#8217;autres.</p>
<h4>JCR et JCR over RMI</h4>
<p>Si vous en avez besoin (intégration Liferay par exemple), le dépôt Alfresco implémente la norme JCR (JSR-170). Cette dernière peut être accédée en local ou au travers de RMI. Cependant, cette méthode est déconseillée par Alfresco qui mets plus l&#8217;accent sur le REST et sur l&#8217;API CMIS.</p>
<p>Actuellement nous avons un projet de plateforme collaborative basée sur Alfresco chez un client et ce dernier y est utilisé comme socle pour la gestion documentaire.</p>
<p>Dans les besoins exprimés, trois grandes catégories ont été dégagées :</p>
<ul>
<li>les besoins d&#8217;administration de la plateforme;</li>
<li>les besoins d&#8217;accès à des données enrichies par le métier au travers d&#8217;une interface très ergonomique et graphiquement léchée;</li>
<li>les besoins de type portail favorisant un travail collaboratif.</li>
</ul>
<p>Ces trois types de besoins se retrouvent dans les modes d&#8217;accès proposés par Alfresco. L&#8217;administration est donc assurée par le panneau d&#8217;administration de l&#8217;interface web-client, les accès aux données enrichies par le métier se font au travers d&#8217;une interface REST consommée par un client léger Flex répondant aux attentes d&#8217;ergonomie et de graphisme et les besoins de type portail collaboratif sont traité avec l&#8217;interface share qui nous fourni une plateforme sur laquelle nous pouvons agencer des composants existants et ajouter ceux dont la partie métier requiert un développement spécifique.</p>
<p>Au final, nous obtenons un ensemble cohérent, performant et évolutif et nous avons gagné du temps par rapport à un développement spécifique à 100%.</p>
<h3><em><strong>Je veux intégrer Alfresco avec le portail Liferay.</strong></em></h3>
<p style="text-align: justify;">Nous avons eu un demande de ce type pour un client qui voulait utiliser Alfresco avec Liferay comme portail.</p>
<p style="text-align: justify;">Bien qu&#8217;Alfresco prétende qu&#8217;il s&#8217;intègre très bien avec Liferay, en pratique, nous avons constaté qu&#8217;il ne s&#8217;agit pas d&#8217;une intégration mais plutôt d&#8217;une communication. En fait, la norme portlet permet d&#8217;intégrer des contenus récupérés sous la forme de code HTML. C&#8217;est ce qu&#8217;Alfresco propose avec quelques portlets codées grâce à son API Webscripts mais elles sont surtout là en temps que preuve de concept que les Webscripts peuvent retourner des contenus HTML intégrables dans Liferay au travers d&#8217;une portlet de type iframe.</p>
<p style="text-align: justify;">Charge donc à votre équipe de développement de concevoir les portlets et éventuellement des services REST côté Alfresco pour réaliser l&#8217;intégration. C&#8217;est la conclusion à laquelle nous en sommes venu eu égard aux besoins métiers du client et à l&#8217;inadéquation des Webscripts proposés par défaut. Cela dit, il était quelque peu prévisible qu&#8217;Alfresco ne prévoit pas le besoin spécifique demandé par notre client. L&#8217;essentiel ici est qu&#8217;Alfresco propose tout l&#8217;outillage nécessaire pour réaliser cette communication facilement et rapidement. En outre, si vous souhaitez que Liferay utilise Alfresco comme fond documentaire, c&#8217;est possible puisque les deux sont compatibles JCR (JSR-170).</p>
<h3 style="text-align: justify;"><em><strong>J&#8217;ai l&#8217;obligation de m&#8217;interfacer avec l&#8217;annuaire d&#8217;entreprise et je ne veux pas de mécanisme de provisioning tiré par les cheveux.</strong></em></h3>
<p style="text-align: justify;">Aucun problème ! Alfresco repose sur la LDAPFactory standard de la JVM. De fait, il supporte parfaitement l&#8217;intégration avec un annuaire LDAP, que ce soit AD, OpenLDAP ou un autre.</p>
<p style="text-align: justify;">Certains annuaires ont des champs non standards. Alfresco gère facilement cela au niveau de ses fichiers de configuration.</p>
<p style="text-align: justify;">Le provisioning par défaut est de créé un compte à la racine du dépôt. Cela peut être paramétré facilement et si un provisioning plus complexe est à mettre en oeuvre (création de dossier personnel et copie de données, &#8230;). Alfresco propose un mécanisme de modèle de dossiers et permet aussi de tout simplement développer une classe de provisioning spécifique.</p>
<p style="text-align: justify;">Le déprovisioning par défaut est de ne pas supprimer le dossier personnel. Là encore, ce comportement peut être facilement modifié en modifiant la classe implémentant le mécanisme de déprovisioning.</p>
<p style="text-align: justify;">Les opérations de synchronisation dans Alfresco sont ordonnancées par quartz. Ce dernier permet de configurer la fréquence des synchronisations tout comme dans une crontab standard.</p>
<p style="text-align: justify;">En outre, Alfresco supporte plusieurs annuaires et fait une distinction entre synchronisation des utilisateurs et synchronisation des groupes. De cette manière, il est facile d&#8217;adapter sa configuration aux contraintes du SI.</p>
<p style="text-align: justify;">Enfin, si vos annuaires limitent le nombre de réponses possibles, Alfresco, à partir de sa version 3.2 et dès maintenant dans la version labs supporte la pagination des requêtes LDAP.</p>
<h3 style="text-align: justify;">Quartz ? Mais je ne veux pas de mécanisme d&#8217;ordonnancement interne dans les applications de mon système d&#8217;information</h3>
<p>Pas de problème, Quartz est fourni par défaut et est configuré grâce à des beans Spring. Moyennant un peu de configuration et probablement quelques développements pour certaines tâches ne disposant pas de service REST ou SOAP exposé, il est tout à fait possible de le désactiver et de d&#8217;insérer ses tâches dans votre ordonnanceur central.</p>
<p>À titre d&#8217;exemple, nous avons failli le faire à un moment pour un client souhaitant que la synchronisation LDAP soit effectuée par son ordonnanceur central. Il faut savoir que dans Alfresco la synchronisation LDAP se fait en deux temps :</p>
<ul>
<li>extraction du contenu à synchroniser et création d&#8217;un fichier XML représentant les utilisateurs, groupes, &#8230;;</li>
<li>insertion de ce contenu dans Alfresco.</li>
</ul>
<p>Nous avons donc deux tâches, deux classes et un XML dont la structure est connue.</p>
<p>Pour sortir la synchronisation du produit, il suffisait de :</p>
<ul>
<li> coder un petit script aux normes de l&#8217;ordonnanceur central qui générerait l&#8217;XML attendu par Alfresco;</li>
<li>l&#8217;insérer dans Alfresco en exécutant un programme Java d&#8217;import fourni dans le WAR d&#8217;Alfresco.</li>
</ul>
<p>Petit problème cependant, ledit programme JAVA requiert de couper le serveur Alfresco durant la mise à jour&#8230; Pas de problèmes là non plus, il suffit alors de coder le service REST manquant pour effectuer l&#8217;import et plus besoin de couper le serveur. Ce service est assez simple puisque toute la mécanique d&#8217;import étant déjà présente dans Alfresco, il n&#8217;a qu&#8217;à récupérer un fichier XML.</p>
<h3 style="text-align: justify;"><em><strong>La sécurité me demande des flux en &#8216;s&#8217; partout.</strong></em></h3>
<p style="text-align: justify;">Aucun problème, les flux LDAPS ou HTTPS sont parfaitement supportés.</p>
<h3 style="text-align: justify;"><strong><em>Je dois mettre en place du SSO en interne et une connexion LDAP en externe.</em><br />
</strong></h3>
<p style="text-align: justify;">Kerberos, NTLM, CAS, JAAS faîtes votre choix, le chaînage d&#8217;authentification est également supporté dans le cas où, par exemple, un accès extranet est mis en place avec un couple login/mot de passe et qu&#8217;un accès intranet utilise Kerberos.</p>
<h3 style="text-align: justify;"><em><strong>Je veux une solution fonctionnant en grappe.</strong></em></h3>
<p style="text-align: justify;">Alfresco est prévu pour ce type de configuration. L&#8217;effort de configuration spécifique est donc minimal.</p>
<p style="text-align: justify;">En revanche, il faut savoir que si le mode grappe est supporté par défaut pour les instances d&#8217;Alfresco, toutes les instances doivent utiliser la même base de donnée et le même dépôt de données.</p>
<h3 style="text-align: justify;"><em><strong>Base de données ? Mais je croyais que tout était sur un support de stockage !</strong></em></h3>
<p style="text-align: justify;">En effet, c&#8217;est le cas pour toutes les données ayant un contenu.</p>
<p style="text-align: justify;">Les utilisateurs, les répertoires (mais pas leur contenu), les méta-informations que vous avez utilisé pour enrichir vos données et vos workflows sont stockés sur une base de données qui en pratique n&#8217;est pas très chargée. Un simple MySQL suffit amplement.</p>
<h3 style="text-align: justify;"><em><strong>Quels sont les bases de données supportées ?</strong></em></h3>
<p style="text-align: justify;">Oracle, MSSQL, MySql, PostreSQL, Derby, &#8230; Le choix est large. De plus, la charge sur la base est minimale, Alfresco n&#8217;utilisant pas de schémas complexes et reposant massivement sur son indexeur, sur Hibernate et sur EHCache.</p>
<h3 style="text-align: justify;"><em><strong>Et pour le stockage, quels sont les pré-requis ?</strong></em></h3>
<p style="text-align: justify;">Le dépôt de données à besoin d&#8217;un support ayant surtout une capacité de stockage en accord avec vos besoins.</p>
<p style="text-align: justify;">L&#8217;indexation des données représente en moyenne 30% du volume total de données stockées sur le dépôt. De plus, l&#8217;indexation étant effectuée sur un support de stockage (Lucene est la technologie utilisée), il est plus que recommandé d&#8217;utiliser un disque très rapide supportant les opérations de vérrouillage de fichiers).</p>
<h3 style="text-align: justify;"><em><strong>Je veux segmenter mes données sur plusieurs dépôts</strong>.</em></h3>
<p style="text-align: justify;">Alfresco est aussi prévu pour ce type de configuration bien que l&#8217;exercice soit un peu plus complexe à configurer. En outre, vous avez toujours une seule base de données possible et donc la procédure de sauvegarde doit prendre en compte le fait que pour une base de données, deux dépôts physiques devront être sauvegardés.</p>
<p style="text-align: justify;">Dans le cas où vous auriez en tête une partie interne ayant tout le dépôt et une partie externe, exposée sur internet qui ne doit avoir qu&#8217;un sous ensemble de données et en lecture seule, sachez que pour Alfresco ce n&#8217;est qu&#8217;un cas particulier d&#8217;une configuration en mode grappe. En pratique, il s&#8217;agit de mettre l&#8217;instance &laquo;&nbsp;lecture seule&nbsp;&raquo; en mode grappe avec l&#8217;instance accès complet et de configurer son index pour qu&#8217;il ne traite qu&#8217;un sous ensemble des données.</p>
<p style="text-align: justify;">Nous avons récemment rencontré un cas similaire à Octo et notre solution a été une troisième voie qui évite la mise en place d&#8217;un second serveur Alfresco; consommer un service REST côté Alfresco permettant de récupérer ledit sous ensemble de données qui est marqué par un tag.</p>
<h3 style="text-align: justify;"><em><strong>Je veux une solution simple à déployer et à mettre à jour.</strong></em></h3>
<p style="text-align: justify;">Actuellement, Alfresco ne fonctionne qu&#8217;avec tomcat. L&#8217;application est livrée sous la forme d&#8217;un WAR que vous déployez et c&#8217;est tout !</p>
<p style="text-align: justify;">Si vous souhaitez le faire fonctionner sur Jetty, Jboss, ou encore Websphere, un effort de développement est à prévoir pour corriger les bugs empêchant la portabilité du produit.</p>
<h3 style="text-align: justify;"><em><strong>Je veux un traçage fin des évènements</strong>.</em></h3>
<p style="text-align: justify;">Alfresco dispose d&#8217;un mécanisme d&#8217;audit qui, une fois activé, permet de suivre à la trace les évènements sur chaque objet du dépôt. À configurer avec précaution pour éviter de faire exploser la taille de la base de données et de trop ralentir le serveur.</p>
<h3 style="text-align: justify;"><em><strong>Je veux un socle extensible.</strong></em></h3>
<p style="text-align: justify;">Basé sur Spring avec les mécanismes exposés plus haut, Alfresco est particulièrement adapté si vous souhaitez l&#8217;utiliser comme un socle sur lequel prendront place des projets métiers nécessitant de capitaliser sur les informations.</p>
<h3 style="text-align: justify;"><em><strong>J&#8217;ai besoin d&#8217;un wiki.</strong></em></h3>
<p style="text-align: justify;">Alfresco s&#8217;interface avec mediaWiki. Toutefois, si votre besoin de limite au wiki, il peut être plus intéressant de n&#8217;installer que mediaWiki et de le relier éventuellement à Alfresco plus tard, le jour où le besoin de mise en place de ce dernier sera réel.</p>
<h3 style="text-align: justify;"><em><strong>J&#8217;ai besoin de solutions collaboratives avec un client léger.</strong></em></h3>
<p style="text-align: justify;">Alfresco propose des interfaces web tels que share. Cependant, il ne couvre pas tous les besoins et surtout son développement peut être fastidieux. En effet, ce n&#8217;est pas le domaine où Alfresco excelle, pas le portail collaboratif aussi il vaut mieux considérer un interfaçage d&#8217;une solution collaborative plus poussée avec Alfresco au travers de REST ou de SOAP.</p>
<p style="text-align: justify;">Le mieux est encore de profiter des possibilités de communication offertes avec Alfresco et de mélanger les types d&#8217;accès en fonction des besoins. Comme expliqué plus haut, cela nous a permis de répondre efficacement à un besoin client récemment.</p>
<h3 style="text-align: justify;"><em><strong>Je veux que mes équipes soient rapidement opérationnelles pour mes développements spécifiques.</strong></em></h3>
<p style="text-align: justify;">La nature extensible et libre d&#8217;Alfresco est particulièrement adaptée pour une prise en main assez rapide. De plus, une véritable communauté est présente notamment au travers des forums et l&#8217;architecture logicielle propre et claire du produit fait que le recours au support développement n&#8217;est pas souvent nécessaire même pour un développeur Java junior.</p>
<p style="text-align: justify;">Attention tout de même, il est important de connaître Spring, Java 6 et tomcat pour pouvoir rapidement prendre en main le produit.</p>
<h3 style="text-align: justify;"><em><strong>Je veux faire de l&#8217;Agile.</strong></em></h3>
<p style="text-align: justify;">C&#8217;est tout à fait possible et c&#8217;est ce qu&#8217;Octo fait chez ses clients. Toutefois, sachez qu&#8217;appliquer strictement du TDD (développpement dirigé par les tests) avec Alfresco peut parfois se révéler être une tâche ardue, la totalité du code n&#8217;étant pas couvert par les tests et l&#8217;execution des tests unitaires demandant le lancement d&#8217;une mini instance d&#8217;Alfresco. Une personne expérimentées sur Alfresco est alors un bon moyen d&#8217;éviter bien des pertes de temps.<br />
Nous avons rencontré pas mal de problèmes pour mettre en place les tests unitaires REST avec Alfresco à cause de quelques loudeurs comme la nécessités de lancer un mini Alfresco pour effectuer les tests unitaires. Cela dit, dans 80% des cas, les tests unitaires n&#8217;ont pas posé de problèmes et le produit étant libre, cela facilite et accélère grandement le dépannage en cas de blocage ce qui n&#8217;est pas négligeable.</p>

 <img src="http://blog.octo.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=3834" width="1" height="1" style="display: none;" /><p>Suggestion d'articles :</p><ol>
<li><a href='http://blog.octo.com/architecture-dynamique/' rel='bookmark' title='Architecture Dynamique basée sur la solution Grails'>Architecture Dynamique basée sur la solution Grails</a></li>
<li><a href='http://blog.octo.com/la-federation-d%e2%80%99identite-en-entreprise/' rel='bookmark' title='La fédération d’identité en entreprise'>La fédération d’identité en entreprise</a></li>
<li><a href='http://blog.octo.com/tours-jug-apache-maven-mise-en-uvre-en-entreprise/' rel='bookmark' title='Tours JUG &#8211; Apache Maven, mise en œuvre en entreprise'>Tours JUG &#8211; Apache Maven, mise en œuvre en entreprise</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.octo.com/alfresco-est-il-une-solution-pour-votre-entreprise/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Versioning de services REST</title>
		<link>http://blog.octo.com/versioning-de-services-rest/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=versioning-de-services-rest</link>
		<comments>http://blog.octo.com/versioning-de-services-rest/#comments</comments>
		<pubDate>Tue, 12 May 2009 07:00:53 +0000</pubDate>
		<dc:creator>Benjamin Magnan</dc:creator>
				<category><![CDATA[Architecture et technologies]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[SOA]]></category>
		<category><![CDATA[Versioning]]></category>

		<guid isPermaLink="false">http://blog.octo.com/?p=2838</guid>
		<description><![CDATA[Introduction Le versioning de service est un thème à part entière dans les architectures orientée service tant il structure l&#8217;évolutivité d&#8217;un service. Les architectures REST n&#8217;échappent pas à la règle. Posant les principes généraux de l&#8217;architecture, Roy Fielding n&#8217;en a pas pour autant décrit tous les méandres. Il n&#8217;appartient donc qu&#8217;à nous, développeurs et architectes, [...]
Suggestion d'articles :<ol>
<li><a href='http://blog.octo.com/versioning-des-services-principes-et-elements-darchitecture%e2%80%a6/' rel='bookmark' title='Versioning des services: principes et éléments d&#8217;architecture…'>Versioning des services: principes et éléments d&#8217;architecture…</a></li>
<li><a href='http://blog.octo.com/des-principes-rest-pour-realiser-du-mashup/' rel='bookmark' title='Des principes (ou quelques idées&#8230;) REST et du Mashup'>Des principes (ou quelques idées&#8230;) REST et du Mashup</a></li>
<li><a href='http://blog.octo.com/la-strategie-de-test-dune-architecture-rest-13-test-dintegration/' rel='bookmark' title='La stratégie de test d&#8217;une architecture REST (2/3) &#8211; Test d’intégration'>La stratégie de test d&#8217;une architecture REST (2/3) &#8211; Test d’intégration</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fblog.octo.com%252Fversioning-de-services-rest%252F%22%2C%20%22style%22%3A%20%22small%22%2C%20%22title%22%3A%20%22Versioning%20de%20services%20REST%22%20%7D);"></div>
<h2>Introduction</h2>
<p>Le versioning de service est un thème à part entière dans les architectures orientée service tant il structure l&#8217;évolutivité d&#8217;un service. Les architectures REST n&#8217;échappent pas à la règle. Posant les principes généraux de l&#8217;architecture, Roy Fielding n&#8217;en a pas pour autant décrit tous les méandres. Il n&#8217;appartient donc qu&#8217;à nous, développeurs et architectes, de définir ce qu&#8217;est le versioning des services REST en respectant ces principes. Ce billet traitera donc la problématique de versioning des services REST.</p>
<p><span id="more-2838"></span></p>
<h2>Quand versionne-t-on ? </h2>
<p><strong><em>Les types de changement</em></strong></p>
<p>Il existe différents types de changements</p>
<ul>
<li>On peut être amené à modifier des règles métiers soit parce qu’elles évoluent, soit parce qu’elles sont « bugfixées ». </li>
<li>On peut être amené à enrichir la signature du service pour répondre à de nouveaux besoins.</li>
</ul>
<p>Souvent le premier cas n’a pas d’impact sur la signature du service et nous le laisserons volontairement en dehors du scope de cet article même si quelques problématiques de versioning se posent. </p>
<p>Dans le  second cas, les évolutions de signature (c&#8217;est-à-dire principalement des paramètres d’appels et de réponse) peuvent être soit compatible avec les versions antérieures soit incompatibles.</p>
<p><strong><em>Changement compatible</em></strong></p>
<p>Ce sont les changements qui respectent le principe de compatibilité ascendante. Ces changements n’ont aucun impact sur les clients  existants, pour peu qu’ils soient correctement implémentés. </p>
<p>C&#8217;est-à-dire qu’il respecte les pratiques suivantes :</p>
<ul>
<li>Le client ne doit pas tenir compte de l’ordre des éléments dans une représentation (XML par exemple)</li>
<li>Le client ne doit pas échouer lorsque des éléments sont rajoutés dans une représentation (XML par exemple)</li>
<li>Le client ne doit pas échouer lorsque de nouveaux codes retours sont ajoutés</li>
<li>Le client d’une représentation ne doit pas échouer lorsqu’une nouvelle représentation est ajoutée</li>
</ul>
<p> Par exemple, pour une ressource Album représentée en XML :</p>

<div class="wp_codebox"><table><tr id="p283837"><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code" id="p2838code37"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;album<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Dark Side of the Moon<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/album<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>L’ajout d’un champ ne modifie en rien la structuration précédente du message.</p>

<div class="wp_codebox"><table><tr id="p283838"><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code" id="p2838code38"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;album<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Dark Side of the Moon<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Roger Waters<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/album<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Les clients existants ne doivent pas être impactés.</p>
<p><em><strong>Les changements incompatibles</strong></em></p>
<p>Les changements dit incompatibles impactent directement les clients existants. Sur l’exemple précédent, si un ou plusieurs clients utilisent l’élément « artist », le fait de passer d’un artiste par album à une liste d’artistes par album rend cet élément inutilisable par ces clients.</p>

<div class="wp_codebox"><table><tr id="p283839"><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code" id="p2838code39"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;album<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Dark Side of the Moon<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artists<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Roger Waters<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>David Gilmour <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artists<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/album<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Un client, même codé selon les règles de l’art du parsing XML, ne pourra pas absorber la modification. (nom, granularité, type, …)</p>
<p><strong><em>Quand versionner une représentation ?</em></strong></p>
<p>Les changements compatibles correspondront donc à un changement mineur, les changements incompatibles seront des changements majeurs. Ce sont ces derniers qui obligent une montée de version du service. On changera donc de version  lorsque qu’un changement de comportement du service entraîne :</p>
<ul>
<li>un changement incompatible </li>
<li>la création d’un lien vers une nouvelle ressource </li>
<li>la dépréciation d’une ressource.</li>
</ul>
<h2>Le versioning en REST</h2>
<p>Il existe plusieurs moyens de versionner. </p>
<p><strong><em>Le versioning via URL</em></strong></p>
<p>La première réponse à ce problème de versioning a été de rajouter un paramètre identifiant la version dans l’URL de la ressource.</p>
<p>Par exemple la version 1 d’une ressource album avec une représentation XML :</p>

<div class="wp_codebox"><table><tr id="p283840"><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code" id="p2838code40"><pre class="xml" style="font-family:monospace;">GET http://.../v1/albums/12133
&nbsp;
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;album<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>The dark side of the moon<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>The pink floyds<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/album<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Et  la version 2 de la même ressource album avec une représentation XML aussi :</p>

<div class="wp_codebox"><table><tr id="p283841"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code" id="p2838code41"><pre class="xml" style="font-family:monospace;">GET http://.../v2/albums/12133
&nbsp;
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;album<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>The dark side of the moon<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artists<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Roger Waters<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>David Guilmour<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Nick Mason<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Rick Wright<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artists<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>		
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/album<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Ce versioning est inspirée du modèle SOAP où la version est portée dans l’adressage du service. A chaque nouvelle version d’un service on définie une nouvelle URL et un nouveau schéma WSDL associé.</p>
<p>Cette approche ne nous satisfait pas sur plusieurs points :</p>
<blockquote><p><strong>Rupture avec les principes REST :</strong></p></blockquote>
<p>La plus importante est que cette approche est en rupture avec un des principes de REST : une ressource est identifiée par une URI sous entendu durable et stable dans le temps<br />
L’introduction de la version dans l’URI implique de définir une URI différente par version de la ressource maintenue par le serveur.<br />
Dans l’exemple précédent deux URI permettent d’accéder à la ressource Album.</p>
<p>De plus cette approche donne l’impression aux utilisateurs que l’album dans une version de l’API est une ressource différente du même album dans une autre version. Hors, ce qui a changé ici n’est pas la ressource mais une de ces représentations (la représentation au format XML pour être complet).</p>
<blockquote><p><strong>Exposition de paramètres techniques :</strong></p></blockquote>
<p>Cette approche rend visible directement au client une partie de la complexité de la gestion des versions de l’API.<br />
En effet, nous faisons apparaître dans l’URI un paramètre purement technique, le numéro de version, alors que l’URI représente la dénomination fonctionnelle et unique de la ressource.</p>
<p><strong><em>Best practice REST</em></strong></p>
<blockquote><p><strong>« Content negotiation »</strong></p></blockquote>
<p>Une autre approche qui s’appuie sur le mécanisme de négociation de contenu du protocole http réponds entre autre à ces limitations. Revenons en deux mots sur la négociation de contenu : ce mécanisme permet à un client d’une ressource web de spécifier quelle(s) représentation(s) il préfère obtenir.</p>
<p>Techniquement parlant cette information se trouve dans la requête http dans une entête appelée Accept header. Voici un exemple de requête avec négociation de contenu :</p>

<div class="wp_codebox"><table><tr id="p283842"><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code" id="p2838code42"><pre class="xml" style="font-family:monospace;">GET http://... /albums/12133
Accept : text/xml, application/json 
…</pre></td></tr></table></div>

<p>Le serveur répondra de préférence un fragment XML, s’il le gère, une structure de données JSON dans le cas contraire.<br />
Les types définis dans l’Accept header peuvent être soit des media types standardisés soit des types personnalisés.</p>
<blockquote><p><strong>Versioning par Accept</strong></p></blockquote>
<p>Selon la philosophie REST le client spécifie dans sa requête la représentation de la ressource à laquelle il souhaite accéder. Ceci est fait au travers du mécanisme de négociation de contenu explicité ci-dessus.</p>
<p>Ce mécanisme permet donc de véhiculer les informations liées aux différentes versions de l’API. Le client spécifie dans le Accept Header quelles sont les versions d’une représentation d’une ressource qu’il souhaite avoir, par ordre de préférence.</p>
<p>La gestion des versions de service REST au travers de ce mécanisme a un prérequis : l’introduction de media types non standard.</p>
<p>Si nous reprenons l’exemple du versioning précédent les types créés seront :</p>
<ul>
<li>application/vnd.octo.music-v1+xml associé au schéma XML de la version 1 de la représentation XML de l’album</li>
<li>application/vnd.octo.music-v2+xml associé au schéma XML de la version 2 de la représentation XML de l’album</li>
</ul>
<p>Par exemple la requête pour accéder à la version 1 de la ressource album avec une représentation XML :</p>

<div class="wp_codebox"><table><tr id="p283843"><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code" id="p2838code43"><pre class="xml" style="font-family:monospace;">GET http://.../albums/12133
Accept : application/vnd.octo.music-v1+xml 
&nbsp;
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;album<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>The dark side of the moon<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>The pink floyds<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/album<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Et la requête pour accéder à la version 2 de la ressource album avec une représentation XML :</p>

<div class="wp_codebox"><table><tr id="p283844"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code" id="p2838code44"><pre class="xml" style="font-family:monospace;">GET http://.../albums/12133
Accept : application/vnd.octo.music-v2+xml 
&nbsp;
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;album<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>The dark side of the moon<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artists<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Roger Waters<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>David Guilmour<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Nick Mason<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Rick Wright<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artists<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>		
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/album<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<h2>Conclusion</h2>
<p>La principale solution apportée au problème de versioning de services REST a été d’introduire le numéro de version dans l’URI. Nous lui préférons la solution utilisant la négociation de contenu et le versioning de représentations plus que ressources.<br />
Ceci pour plusieurs raisons :</p>
<ul>
<li>Le versioning via URI enfreint un des principes fondamentaux de REST : Une URI  Une ressource</li>
<li>Dans la philosophie REST les échanges sont pilotés par le client, c’est le client qui sait quelle représentation il peut manipuler. Ceci autant pour le format des données (xml, json, html, …) que pour la version de ces données. Ces deux cas doivent être traités au travers du même mécanisme : la négociation de contenu et le champ Accept Header.
</li>
<li>La négociation de contenu permet au client de définir les versions de représentation qu’il souhaite recevoir par ordre de préférence</li>
<li>
Les principaux framework REST offrent des fonctionnalités natives de gestion de contenu coté client et serveur</li>
</ul>
<p>Dans un article futur nous pourrons décrire l’architecture technique/applicative impliquée par la gestion de versions via Accept Header. Nous pourrons ainsi répondre aux questions : Comment mettre à disposition une nouvelle version d’un service ? Comment supporter coté serveur deux versions majeures d’un service en même temps ? Comment connaître les versions utilisées par les clients du service ?</p>
<p><strong>Benoît Guillou &#038; Benjamin Magnan</strong></p>

 <img src="http://blog.octo.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=2838" width="1" height="1" style="display: none;" /><p>Suggestion d'articles :</p><ol>
<li><a href='http://blog.octo.com/versioning-des-services-principes-et-elements-darchitecture%e2%80%a6/' rel='bookmark' title='Versioning des services: principes et éléments d&#8217;architecture…'>Versioning des services: principes et éléments d&#8217;architecture…</a></li>
<li><a href='http://blog.octo.com/des-principes-rest-pour-realiser-du-mashup/' rel='bookmark' title='Des principes (ou quelques idées&#8230;) REST et du Mashup'>Des principes (ou quelques idées&#8230;) REST et du Mashup</a></li>
<li><a href='http://blog.octo.com/la-strategie-de-test-dune-architecture-rest-13-test-dintegration/' rel='bookmark' title='La stratégie de test d&#8217;une architecture REST (2/3) &#8211; Test d’intégration'>La stratégie de test d&#8217;une architecture REST (2/3) &#8211; Test d’intégration</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.octo.com/versioning-de-services-rest/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>La stratégie de test d&#8217;une architecture REST (2/3) &#8211; Test d’intégration</title>
		<link>http://blog.octo.com/la-strategie-de-test-dune-architecture-rest-13-test-dintegration/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=la-strategie-de-test-dune-architecture-rest-13-test-dintegration</link>
		<comments>http://blog.octo.com/la-strategie-de-test-dune-architecture-rest-13-test-dintegration/#comments</comments>
		<pubDate>Tue, 24 Feb 2009 16:29:06 +0000</pubDate>
		<dc:creator>Benoit Guillou</dc:creator>
				<category><![CDATA[Architecture et technologies]]></category>
		<category><![CDATA[développements]]></category>
		<category><![CDATA[intégration]]></category>
		<category><![CDATA[jersey]]></category>
		<category><![CDATA[productivité]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[services]]></category>
		<category><![CDATA[SOA]]></category>
		<category><![CDATA[tests]]></category>
		<category><![CDATA[webservices]]></category>

		<guid isPermaLink="false">http://blog.octo.com/?p=835</guid>
		<description><![CDATA[Cet article est le deuxième d’une série de 3 articles traitant de la stratégie de test d’une architecture REST. Il fait suite au billet sur le test unitaire d’une ressource REST. Pour rappel nous allons, par l’exemple, mettre en pace une stratégie de test sur un code d’exposition de web services REST en Java. L&#8217;exemple [...]
Suggestion d'articles :<ol>
<li><a href='http://blog.octo.com/la-strategie-de-test-d-une-architecture-rest-1-3-test-unitaire-dune-ressource/' rel='bookmark' title='La stratégie de test d&#8217;une architecture REST (1/3) &#8211; Test unitaire d’une ressource'>La stratégie de test d&#8217;une architecture REST (1/3) &#8211; Test unitaire d’une ressource</a></li>
<li><a href='http://blog.octo.com/rest-en-java-avec-la-jsr-311/' rel='bookmark' title='REST en JAVA avec la JSR-311'>REST en JAVA avec la JSR-311</a></li>
<li><a href='http://blog.octo.com/versioning-de-services-rest/' rel='bookmark' title='Versioning de services REST'>Versioning de services REST</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fblog.octo.com%252Fla-strategie-de-test-dune-architecture-rest-13-test-dintegration%252F%22%2C%20%22style%22%3A%20%22small%22%2C%20%22title%22%3A%20%22La%20strat%C3%A9gie%20de%20test%20d%27une%20architecture%20REST%20%282%2F3%29%20-%20Test%20d%E2%80%99int%C3%A9gration%22%20%7D);"></div>
<p>Cet article est le deuxième d’une série de 3 articles traitant de la stratégie de test d’une architecture REST. Il fait suite au <a href="http://blog.octo.com/la-strategie-de-test-d-une-architecture-rest-1-3-test-unitaire-dune-ressource/">billet </a>sur le test unitaire d’une ressource REST. Pour rappel nous allons, par l’exemple, mettre en pace une stratégie de test sur un code d’exposition de web services REST en Java. L&#8217;exemple de code se basera sur le framework REST Jersey, implémentation de référence de Sun de la JSR-311 déjà présentée dans un précédent <a href="http://blog.octo.com/rest-en-java-avec-la-jsr-311/">article </a>. Le but de ces trois articles est de présenter un harnais de tests pouvant couvrir la mise en place de Web services REST. Ce deuxième article s’attardera sur les tests d’intégration tandis qu’un prochain article traitera des tests de recette.<br />
<span id="more-835"></span></p>
<h3>USE CASE (Rappel)</h3>
<p>RESTune est une application fictive de vente de musique en ligne. Cette application permet :</p>
<ul>
<li>de lister l&#8217;ensemble des albums : GET http://&#8230;/albums</li>
<li>de récupérer un album en fournissant son identifiant : GET http://&#8230;/albums/12133</li>
<li>de créer un album : POST http://&#8230;/albums</li>
</ul>
<h4>Architecture générale de l&#8217;application (Rappel)</h4>
<p>RESTune est une application Java classique n-tiers :</p>
<ul>
<li>une couche DAO (framework Hibernate)</li>
<li>une couche Service</li>
<li>une couche Webservice (framework Jersey + JAXB pour la sérialisation / désérialisation)</li>
<li>une gestion des beans par le framework Spring</li>
</ul>
<h3>Le test d’intégration</h3>
<p>Par définition, le test d’intégration valide la cohérence d’une fonctionnalité dans son ensemble. Dans le cas de l’implémentation d’une ressource REST, il est nécessaire de traverser toutes les couches de l’application &#8211; de l&#8217;appel HTTP au WS REST jusqu&#8217;à la base de données dans notre exemple. Cette fois, l&#8217;ensemble de notre pile logicielle Spring + Hibernate + Jaxb + Jersey sera mise en jeu. Le but n&#8217;est bien évidemment pas de tester les frameworks mais l&#8217;utilisation qui en est faite et la cohérence de l&#8217;ensemble.</p>
<h4>Environnement léger de test d’intégration</h4>
<p>Le dispositif présenté ci-dessus permet de disposer sur le poste développeur d’un serveur d’application (Jetty) et d’une base de données en mémoire (HSQLDB). Ces deux outils ont, en autres, la particularité d’être légers et rapides. L’intérêt de ce dispositif est de créer un contexte se rapprochant le plus possible de la réalité (serveur d’application + base de données) tout en ne sacrifiant pas les performances. Cette plateforme permet d’exécuter des tests sur le poste développeur tout en s’autorisant à passer sur une plateforme d’intégration moyennant configuration (via Maven par exemple – cf <a name="maven"></a>).</p>
<p>La classe de test AbstractWebRunnerTestCase permet de lancer un Jetty, de déployer l&#8217;application RESTune décrite par son fichier web.xml. L’utilisation du <a href="http://blogs.sun.com/sandoz/entry/jersey_client_api">client Jersey</a> permet de simplifier la manipulation de ressources REST par rapport à un client HTTP tel HTTPClient. A noter que ce client, prévu initialement pour faciliter les tests unitaires du framework Jersey, est un maintenant un composant a part entière du framework. Il peut donc permettre de réaliser la partie Cliente d’une application REST, tout comme tester une autre implémentation REST que Jersey (RESTLET, RESTeasy, …).</p>

<div class="wp_codebox"><table><tr id="p83551"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
</pre></td><td class="code" id="p835code51"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">abstract</span> <span style="color: #000000; font-weight: bold;">class</span> AbstractWebRunnerTestCase <span style="color: #009900;">&#123;</span>
<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">int</span> port <span style="color: #339933;">=</span> <span style="color: #cc66cc;">9797</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">String</span> url<span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> Server server<span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> Client client<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">protected</span> AbstractWebRunnerTestCase<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
<span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">url</span> <span style="color: #339933;">=</span> <span style="color: #003399;">String</span>.<span style="color: #006633;">format</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;http://localhost:%s/&quot;</span>, port<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #666666; font-style: italic;">// Helper pour manipuler les ressources</span>
<span style="color: #000000; font-weight: bold;">protected</span> WebResource getResource<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> relativeUrl<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
<span style="color: #003399;">String</span> realUrl <span style="color: #339933;">=</span> url <span style="color: #339933;">+</span> relativeUrl<span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">return</span> client.<span style="color: #006633;">resource</span><span style="color: #009900;">&#40;</span>realUrl<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
@BeforeClass
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">void</span> setUp<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Exception</span> <span style="color: #009900;">&#123;</span>
server <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Server<span style="color: #009900;">&#40;</span>port<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// On lance le serveur Jetty</span>
WebAppContext webAppContext <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> WebAppContext<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;src/main/webapp&quot;</span>, <span style="color: #0000ff;">&quot;/&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
webAppContext.<span style="color: #006633;">setConfigurationClasses</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">String</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#123;</span> <span style="color: #0000ff;">&quot;org.mortbay.jetty.webapp.WebInfConfiguration&quot;</span>,
<span style="color: #0000ff;">&quot;org.mortbay.jetty.webapp.WebXmlConfiguration&quot;</span>, <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
server.<span style="color: #006633;">addHandler</span><span style="color: #009900;">&#40;</span>webAppContext<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> server.<span style="color: #006633;">start</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// Création d'un client Jersey client = Client.create();</span>
<span style="color: #009900;">&#125;</span>
@AfterClass
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">void</span> tearDown<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Exception</span> <span style="color: #009900;">&#123;</span>
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>server <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
server.<span style="color: #006633;">stop</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Prenons l’exemple de la recherche d’album par identifiant : GET http://&#8230;/albums/{id}</p>
<p>Le code à tester</p>

<div class="wp_codebox"><table><tr id="p83552"><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code" id="p835code52"><pre class="java" style="font-family:monospace;">@GET
@Path<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/{id}&quot;</span><span style="color: #009900;">&#41;</span>
@Produces<span style="color: #009900;">&#40;</span>MediaType.<span style="color: #006633;">APPLICATION_XML</span><span style="color: #009900;">&#41;</span>
<span style="color: #000000; font-weight: bold;">public</span> AlbumXmlBean getAlbumById<span style="color: #009900;">&#40;</span>@PathParam<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;id&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #003399;">Long</span> id<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> AlbumNotFoundException <span style="color: #009900;">&#123;</span>
Album album <span style="color: #339933;">=</span> albumService.<span style="color: #006633;">getAlbumById</span><span style="color: #009900;">&#40;</span>id<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000000; font-weight: bold;">new</span> AlbumXmlBean<span style="color: #009900;">&#40;</span>album<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Méthode testée unitairement, il reste cependant à vérifier :<br />
- Le Verbe http autorisé (configuré par l’annotation @GET)<br />
- Le MediaType autorisé @Produces(MediaType.APPLICATION_XML)<br />
- L&#8217;utilisation des Providers / ExceptionMappers (cf JSR-311)<br />
- L’Enchainement des traitements et intégration des couches applicatives (JAXB, appel au DAO, appel à la DB).</p>
<h3>Exemple de test d’intégration du cas Nominal</h3>
<p>Ce test traverse l’ensemble des couches de l’application, de l’appel HTTP à l’appel à la base de données. Il permet de valider entièrement la réponse en vérifiant le code retour http et le contenu de la réponse.</p>

<div class="wp_codebox"><table><tr id="p83553"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
</pre></td><td class="code" id="p835code53"><pre class="java" style="font-family:monospace;">@RunWith<span style="color: #009900;">&#40;</span>SpringJUnit4ClassRunner.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span>
@ContextConfiguration<span style="color: #009900;">&#40;</span>locations <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> <span style="color: #0000ff;">&quot;classpath:applicationContext.xml&quot;</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> AlbumsResourceIntTest <span style="color: #000000; font-weight: bold;">extends</span> AbstractWebRunnerTestCase <span style="color: #009900;">&#123;</span>
@Autowired
HibernateTemplate hibernateTemplate<span style="color: #339933;">;</span>
@Test
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> getAlbumByIdNominalCase<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
<span style="color: #666666; font-style: italic;">// Setup</span>
Album kidA <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Album<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 kidA.<span style="color: #006633;">setReleaseDate</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">Date</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 kidA.<span style="color: #006633;">setTitle</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Kid A&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 hibernateTemplate.<span style="color: #006633;">save</span><span style="color: #009900;">&#40;</span>kidA<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 AlbumXmlBean expectedKidAXmlBean <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> AlbumXmlBean<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 expectedKidAXmlBean.<span style="color: #006633;">setId</span><span style="color: #009900;">&#40;</span>kidA.<span style="color: #006633;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 expectedKidAXmlBean.<span style="color: #006633;">setTitle</span><span style="color: #009900;">&#40;</span>kidA.<span style="color: #006633;">getTitle</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 <span style="color: #666666; font-style: italic;">// Test</span>
WebResource resource <span style="color: #339933;">=</span> getResource<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;albums/&quot;</span> <span style="color: #339933;">+</span> kidA.<span style="color: #006633;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Assert</span>
<span style="color: #666666; font-style: italic;">// Validation du code retour</span>
ClientResponse clientResponse <span style="color: #339933;">=</span> resource.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>ClientResponse.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> assertEquals<span style="color: #009900;">&#40;</span>Status.<span style="color: #006633;">OK</span>.<span style="color: #006633;">getStatusCode</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>, clientResponse.<span style="color: #006633;">getStatus</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Validation de l'entité contenu dans la réponse</span>
AlbumXmlBean retrievedAlbumXmlBean <span style="color: #339933;">=</span> resource.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>AlbumXmlBean.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
assertNotNull<span style="color: #009900;">&#40;</span>retrievedAlbumXmlBean<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
assertEquals<span style="color: #009900;">&#40;</span>expectedKidAXmlBean, retrievedAlbumXmlBean<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#91;</span>...<span style="color: #009900;">&#93;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<h3>Les possibilités offertes par Maven Gestion des configurations<a></a></h3>
<p>Les tests d’intégration peuvent être exécutés à deux niveaux grâce à la gestion <a href="http://maven.apache.org/guides/introduction/introduction-to-profiles.html">profils Maven</a>. En effet, Maven offre la possibilité, par simple configuration, de gérer différents environnements (développeur, intégration, recette, production par exemple).</p>
<h4>Test d’intégration développeur</h4>
<p>Sur le poste développeur, priorité à la rapidité d’exécution. Etant donné qu’il y a un appel HTTP + JDBC, on ne se place plus dans une problématique de test unitaire mais bien de test d’intégration. Ces tests pourraient donc être qualifiés de tests d’intégration développeur.</p>

<div class="wp_codebox"><table><tr id="p83554"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p835code54"><pre class="dos" style="font-family:monospace;">mvn test –Pdeveloppement</pre></td></tr></table></div>

<p>Moyennant configuration dans le POM, les tests seront exécutés dans un environnement « développement » (Jetty + HSQLDB).</p>
<h4>Test d’intégration</h4>
<p>Le test d’intégration se doit de s’effectuer dans un environnement le plus proche possible de celui de production. Ce profil chargera donc l’environnement d’intégration complet : on peut par exemple garder Jetty pour l’exécution des tests mais attaquer la base d’intégration (avec ses propres données, son propres schémas, …). Plus complet mais aussi plus long à tester ! Ce genre de tests pourra être évité sur le poste du développeur et être exécuté par l’automate de build (tous les soirs par exemple).</p>

<div class="wp_codebox"><table><tr id="p83555"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p835code55"><pre class="dos" style="font-family:monospace;">mvn test –Pintegration</pre></td></tr></table></div>

<p>Il est donc possible de séparer les tests unitaires des tests d’intégration grâce à la configuration Maven.<br />
Le plugin Jetty</p>

<div class="wp_codebox"><table><tr id="p83556"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p835code56"><pre class="dos" style="font-family:monospace;">mvn jetty:run</pre></td></tr></table></div>

<p>Le plugin Jetty (maven-jetty-plugin) permet de pouvoir lancer un serveur d’application léger et de déployer l’application en cours de développement. Un fois lancé, Jetty prend automatiquement en compte les modifications de code et de configuration. Cela peut notamment servir de démo pour que vous puissiez tester avec votre browser web préféré. Il est possible par exemple avec Firefox et son plugin Poster de tester le POST d’un XML sur une url.</p>
<h3>Conclusion</h3>
<p>Les tests d’intégration permettent de tester l’ensemble de la fonctionnalité offerte par la ressource, en invoquant l’ensemble de la pile logicielle. Ces tests sont par essence plus longs à jouer. La plateforme de test Jetty + HSQLDB est une réelle alternative permettant de tester au plus vite, dans un environnement plus riche que celui proposé par les tests unitaires. Maven offre de plus la possibilité de pouvoir piloter l’environnement sur lesquels ces tests sont exécutés par simple configuration. L’automate de build pourra alors construire l’application en exécutant au préalable les tests d’intégration sur une plateforme plus complète. Ces tests permettent de mitiger les risques sur :</p>
<ul>
<li>Les codes retour et le contenu des réponses</li>
<li>L’utilisation des annotations du framework Jersey</li>
<li>MIME Type</li>
<li>L’utilisation des Providers  / ExceptionMapper</li>
<li>L’URI de la ressource</li>
<li>La sérialisation / désérialisation des objets</li>
</ul>
<p>Prochainement, nous étudierons plus en détails le test de recette d’une ressource REST. Pour être plus précis, ce dernier article exposera un moyen de réaliser et d’automatiser <a href="http://www.dotnetguru.org/articles/dossiers/fitnesse/article.htm" class="broken_link">les tests de recette</a>, autre moyen de valider/assurer la non-régression d’un service et d’avoir un feedback au plus tôt.</p>
<p>NB : Le code de RESTune est disponible <a href="http://forge.octo.com/svn/java/trunk/octo-samples/jersey-rest-sample/">ici</a>.</p>

 <img src="http://blog.octo.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=835" width="1" height="1" style="display: none;" /><p>Suggestion d'articles :</p><ol>
<li><a href='http://blog.octo.com/la-strategie-de-test-d-une-architecture-rest-1-3-test-unitaire-dune-ressource/' rel='bookmark' title='La stratégie de test d&#8217;une architecture REST (1/3) &#8211; Test unitaire d’une ressource'>La stratégie de test d&#8217;une architecture REST (1/3) &#8211; Test unitaire d’une ressource</a></li>
<li><a href='http://blog.octo.com/rest-en-java-avec-la-jsr-311/' rel='bookmark' title='REST en JAVA avec la JSR-311'>REST en JAVA avec la JSR-311</a></li>
<li><a href='http://blog.octo.com/versioning-de-services-rest/' rel='bookmark' title='Versioning de services REST'>Versioning de services REST</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.octo.com/la-strategie-de-test-dune-architecture-rest-13-test-dintegration/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>La stratégie de test d&#8217;une architecture REST (1/3) &#8211; Test unitaire d’une ressource</title>
		<link>http://blog.octo.com/la-strategie-de-test-d-une-architecture-rest-1-3-test-unitaire-dune-ressource/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=la-strategie-de-test-d-une-architecture-rest-1-3-test-unitaire-dune-ressource</link>
		<comments>http://blog.octo.com/la-strategie-de-test-d-une-architecture-rest-1-3-test-unitaire-dune-ressource/#comments</comments>
		<pubDate>Tue, 17 Feb 2009 15:29:19 +0000</pubDate>
		<dc:creator>Benoit Guillou</dc:creator>
				<category><![CDATA[Architecture et technologies]]></category>
		<category><![CDATA[développements]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[jersey]]></category>
		<category><![CDATA[productivité]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[services]]></category>
		<category><![CDATA[tests]]></category>

		<guid isPermaLink="false">http://new-blog.octo.com/?p=733</guid>
		<description><![CDATA[Cet article est le premier d’une série de 3 articles traitant de la stratégie de test d’une architecture REST. Il fait suite au billet sur les types de test utilisés sur un projet Agile. Par l&#8217;exemple, nous allons mettre en place une stratégie de tests sur un code d&#8217;exposition de web services REST en Java. L&#8217;exemple [...]
Suggestion d'articles :<ol>
<li><a href='http://blog.octo.com/la-strategie-de-test-dune-architecture-rest-13-test-dintegration/' rel='bookmark' title='La stratégie de test d&#8217;une architecture REST (2/3) &#8211; Test d’intégration'>La stratégie de test d&#8217;une architecture REST (2/3) &#8211; Test d’intégration</a></li>
<li><a href='http://blog.octo.com/rest-en-java-avec-la-jsr-311/' rel='bookmark' title='REST en JAVA avec la JSR-311'>REST en JAVA avec la JSR-311</a></li>
<li><a href='http://blog.octo.com/versioning-de-services-rest/' rel='bookmark' title='Versioning de services REST'>Versioning de services REST</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fblog.octo.com%252Fla-strategie-de-test-d-une-architecture-rest-1-3-test-unitaire-dune-ressource%252F%22%2C%20%22style%22%3A%20%22small%22%2C%20%22title%22%3A%20%22La%20strat%C3%A9gie%20de%20test%20d%27une%20architecture%20REST%20%281%2F3%29%20-%20Test%20unitaire%20d%E2%80%99une%20ressource%22%20%7D);"></div>
<p>Cet article est le premier d’une série de 3 articles traitant de la stratégie de test d’une architecture REST. Il fait suite au <a href="http://blog.octo.com/quels-sont-les-types-de-tests-que-l%E2%80%99on-utilise-sur-un-projet-agile">billet</a> sur les types de test utilisés sur un projet Agile. Par l&#8217;exemple, nous allons mettre en place une stratégie de tests sur un code d&#8217;exposition de web services REST en Java. L&#8217;exemple de code se basera sur le framework REST Jersey, RI de Sun de la JSR-311 déjà présenté dans un précédent <a href="http://blog.octo.com/index.php/2008/09/27/145-rest-en-java-avec-la-jsr-311">article</a>. Le but de ces trois articles est de présenter un harnais de tests pouvant couvrir la mise en place de Web services REST. Ce premier article s’attardera sur les tests unitaires tandis que les suivants étudieront les tests d’intégration puis les tests de recette.</p>
<p><span id="more-733"></span></p>
<h3>Use Case</h3>
<p>RESTune est une application fictive de vente de musique en ligne. Cette application permet :</p>
<ul>
<li>de lister l&#8217;ensemble des albums : <code>GET http://.../albums</code></li>
<li>de récupérer un album en fournissant son identifiant : <code>GET http://.../albums/12133</code></li>
<li>de créer un album : <code>POST http://.../albums</code></li>
</ul>
<h3>Architecture générale de l&#8217;application</h3>
<p>RESTUne est une application Java classique n-tiers :</p>
<ul>
<li>une couche DAO (framework Hibernate)</li>
<li>une couche Service</li>
<li>une couche Webservice (framework Jersey + JAXB pour la sérialisation / désérialisation)</li>
<li>une gestion des beans par le framework Spring</li>
</ul>
<p style="text-align: center;"><img class="aligncenter" src="http://blog.octo.com/wp-content/uploads/2009/02/architecturegenerale.png" alt="Architecture générale" /></p>
<h3>Le test unitaire</h3>
<p>Le test unitaire est le premier maillon de la stratégie de test. Partant de la loi du <span>Defect Cost Increase </span>(plus un défaut est détecté tard, plus il coûte cher), le test unitaire (ou test du développeur) joue un rôle crucial. Il permet de valider que le code développé est conforme aux intentions du développeur. Partant du principe que tout test rejouable est de facto un test de non-regression, l’ensemble des tests unitaires d’une application constitue un patrimoine inestimable. Un test est par définition répétable, automatique, indépendant mais surtout pour le développeur impatient, il doit être rapide ! Nous allons donc mettre en place une stratégie de test unitaire légère et rapide.<br />
Pour rappel, <span>Michaël Feathers</span> définit dans <span>Working Effectively With Legacy Code</span> un test unitaire de la façon suivante :</p>
<ul>
<li> Il ne communique pas avec la base de données</li>
<li>Il ne communique pas avec d’autres ressources sur le réseau</li>
<li>Il ne manipule pas un ou plusieurs fichiers</li>
<li>Il peut s’exécuter en même temps que les autres tests unitaires</li>
<li>On ne doit pas faire quelque chose de spécial, comme éditer un fichier de configuration, pour l’exécuter</li>
</ul>
<p style="text-align: center;"><img class="aligncenter" src="http://blog.octo.com/wp-content/uploads/2009/02/tu1.png" alt="Test unitaire" /></p>
<h3>Le pattern &laquo;&nbsp;couche d’exposition fine&nbsp;&raquo;</h3>
<p>Le test unitaire se borne à valider la couche d&#8217;exposition de services. Dans les applications Web classiques, il est préférable de ne laisser que très peu de logique au niveau de la couche présentation. D’un point de vue design, l’application y gagne en lisibilité et en testabilité. Il est facile de faire le parallèle avec la couche d’exposition. Plus elle sera fine et ne comportera des données propres à l’exposition, plus elle sera simple à tester. En REST, l&#8217;exposition de services se fait bien entendu au moyen de ressources.</p>
<p>La JSR-311 se basant sur des beans annotés, il est simple de tester unitairement ces beans hors de tout contexte. Nous allons donc tester notre ressource Album en isolation.<br />
Le code d’exposition de la ressource est le suivant :</p>
<pre>@Singleton
@Path("/albums")
public class AlbumsResource { 

@Context
private UriInfo uriInfo;
@Inject
AlbumService albumService;
[...]
@POST
@Produces(MediaType.APPLICATION_XML)
@Consumes(MediaType.APPLICATION_XML)
public Response postAlbum(AlbumXmlBean albumXmlBean)
{
Album album = albumXmlBeanToAlbum(albumXmlBean);
try {
albumService.save(album);
}
catch (AlbumAlreadyExists e) {
return Response.status(Status.CONFLICT).entity("Album with title " + album.getTitle() + " already exists").build();
}
AlbumXmlBean albumXmlBeanAfterSave = albumToAlbumXmlBean(album);
// Building URI
UriBuilder uriBuilder = uriInfo.getAbsolutePathBuilder();
URI uri = uriBuilder.path(albumXmlBeanAfterSave.getId().toString()).build();
return Response.created(uri).entity(albumXmlBeanAfterSave).build();
}
[...]
}</pre>
<h3>Le pattern Mock Object</h3>
<p>Le pattern Mock Object ou bouchonnage permet d’isoler ma ressource Album de ses dépendances et de se conformer à la définition de test unitaire faite par Feathers. Nous allons donc mocker les couches inférieures grâce au framework <a href="http://unitils.org/summary.html">Unitils</a>. Unitils est un framework qui permet de simplifier les tests unitaires. Il permet entre autres de simplifier l’écriture de Mock grâce à <a href="http://www.easymock.org/">EasyMock</a>.</p>
<pre>@RunWith(UnitilsJUnit4TestClassRunner.class)
public class AlbumsResourceUTest {
// Objet du test
@TestedObject
AlbumsResource albumsResource;

// Mock + injection dans l'objet du test
@RegularMock
@InjectIntoByType
AlbumService albumService;

// Mock + injection dans l'objet du test
@RegularMock
@InjectIntoByType
UriInfo uriInfo;

// Simple mock
@Mock
UriBuilder uriBuilder;
[...]
}</pre>
<p>Easymock permet en un minimum de code de disposer d&#8217;objet mocké que l&#8217;on va pouvoir maîtriser afin de mener à bien nos tests. Pour information, la méthode <code>EasyMock.expect(…)</code> permet de valider l&#8217;utilisation des objets mockés (nombre d&#8217;appel, arguments, …) tout en manipulant leur comportement.</p>
<h3>Exemple : Test unitaire du cas nominal</h3>
<p>Ce test permet de valider le comportement nominal du service. Il vérifie la réponse de la ressource, le code retour ainsi que l&#8217;appel à la méthode sous-jacente <code>albumService.save()</code>.</p>
<pre>@Test
public void postAlbumNominalCase() throws URISyntaxException {
// Setup
Album album = new Album(); album.setTitle("In Rainbows");
album.setId(new Long(32));
albumXmlBean.setTitle("In Rainbows");
albumXmlBean.setId(album.getId());
URI expectedUri = new URI("http://test");

// Mock expectations
albumService.save(album);
EasyMock.expect(uriInfo.getAbsolutePathBuilder()).andReturn(uriBuilder);
EasyMock.expect(uriBuilder.path(album.getId().toString())).andReturn(uriBuilder);
EasyMock.expect(uriBuilder.build()).andReturn(expectedUri); EasyMockUnitils.replay();

// Test
Response response = albumsResource.postAlbum(albumXmlBean);

// Asserts
assertEquals(Status.CREATED.getStatusCode(), response.getStatus());
AlbumXmlBean returnedAlbumXmlBean = (AlbumXmlBean) response.getEntity();
assertTrue(response.getMetadata().containsKey("Location"));

URI returnedUri = (URI) response.getMetadata().get("Location").get(0);
assertEquals(expectedUri, returnedUri); assertEquals(albumXmlBean, returnedAlbumXmlBean);</pre>
<p>Il est dès lors possible de construire tous les cas de test en pilotant ces mocks. Par exemple le test suivant valide qu’à la levée d’une exception <code>AlbumAlreadyExistsException</code>, le web service renvoie un code retour CONFLICT (409) :</p>
<h3>Conclusion</h3>
<p>Les tests unitaires sur un service web permettent de tester en isolation une ressource (sans Spring + Hibernate + Jaxb + Jersey). Quand on connait le contexte que traine chacun de ces frameworks, on s&#8217;aperçoit qu&#8217;on arrive à tester au maximum notre ressource de manière simple (manipulation de POJOs). Ces tests seront d’autant plus fréquemment rejoués qu’ils sont rapides à exécuter et participeront donc à la qualité générale de l’application. A travers ces tests, il est possible de valider que la ressource mise en place est conforme aux intentions du développeur :</p>
<ul>
<li>en vérifiant l&#8217;appel aux méthodes sous-jacente (vérification de l&#8217;appel de méthodes, des arguments)</li>
<li>en simulant les exceptions et en validant le comportement de la couche d&#8217;exposition</li>
<li>en validant les codes retours et le contenu des réponses répondant aux différents use cases du service</li>
</ul>
<p>Le test unitaire est le premier maillon du harnais de tests. Nous verrons dans les articles suivants dans quelle mesure les tests d&#8217;intégration et les tests de recette participent eux aussi à la mise en place d&#8217;une stratégie de test efficace.</p>
<p>Rq : Vous pouvez me <a href="mailto:bguillou@octo.com">contacter </a>si vous désirez le code complet de RESTune</p>

 <img src="http://blog.octo.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=733" width="1" height="1" style="display: none;" /><p>Suggestion d'articles :</p><ol>
<li><a href='http://blog.octo.com/la-strategie-de-test-dune-architecture-rest-13-test-dintegration/' rel='bookmark' title='La stratégie de test d&#8217;une architecture REST (2/3) &#8211; Test d’intégration'>La stratégie de test d&#8217;une architecture REST (2/3) &#8211; Test d’intégration</a></li>
<li><a href='http://blog.octo.com/rest-en-java-avec-la-jsr-311/' rel='bookmark' title='REST en JAVA avec la JSR-311'>REST en JAVA avec la JSR-311</a></li>
<li><a href='http://blog.octo.com/versioning-de-services-rest/' rel='bookmark' title='Versioning de services REST'>Versioning de services REST</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.octo.com/la-strategie-de-test-d-une-architecture-rest-1-3-test-unitaire-dune-ressource/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Des principes (ou quelques idées&#8230;) REST et du Mashup</title>
		<link>http://blog.octo.com/des-principes-rest-pour-realiser-du-mashup/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=des-principes-rest-pour-realiser-du-mashup</link>
		<comments>http://blog.octo.com/des-principes-rest-pour-realiser-du-mashup/#comments</comments>
		<pubDate>Wed, 21 Jan 2009 22:41:12 +0000</pubDate>
		<dc:creator>Olivier Mallassi</dc:creator>
				<category><![CDATA[Architecture et technologies]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[RIA]]></category>
		<category><![CDATA[SOA]]></category>

		<guid isPermaLink="false">http://new-blog.octo.com/2009/01/21/des-principes-rest-pour-realiser-du-mashup/</guid>
		<description><![CDATA[<p>Lorsqu'on parle de ressource et de REST en général, on associe souvent la notion de services, une représentation XML ou JSON d'un résultat, d'une donnée...On ne pense que rarement à la notion de ressource comme pouvant retourner une IHM ou une portion d'IHM, c'est-à-dire, de la donnée mise en forme.</p> <p>Ici, l'idée est simple : utiliser des ressources REST - proposant une représentation HTML - pour agréger et construire une nouvelle IHM côté client, dans le navigateur. </p>
Suggestion d'articles :<ol>
<li><a href='http://blog.octo.com/rest-en-java-avec-la-jsr-311/' rel='bookmark' title='REST en JAVA avec la JSR-311'>REST en JAVA avec la JSR-311</a></li>
<li><a href='http://blog.octo.com/versioning-de-services-rest/' rel='bookmark' title='Versioning de services REST'>Versioning de services REST</a></li>
<li><a href='http://blog.octo.com/la-strategie-de-test-dune-architecture-rest-13-test-dintegration/' rel='bookmark' title='La stratégie de test d&#8217;une architecture REST (2/3) &#8211; Test d’intégration'>La stratégie de test d&#8217;une architecture REST (2/3) &#8211; Test d’intégration</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fblog.octo.com%252Fdes-principes-rest-pour-realiser-du-mashup%252F%22%2C%20%22style%22%3A%20%22small%22%2C%20%22title%22%3A%20%22Des%20principes%20%28ou%20quelques%20id%C3%A9es...%29%20REST%20et%20du%20Mashup%22%20%7D);"></div>
<p>Lorsqu&#8217;on parle de ressource et de REST en général, on associe souvent la notion de services, une représentation XML ou JSON d&#8217;un résultat, d&#8217;une donnée&#8230;On ne pense que rarement à la notion de ressource comme pouvant retourner une IHM ou une portion d&#8217;IHM, c&#8217;est-à-dire, de la donnée mise en forme.</p>
<p>Ici, l&#8217;idée est simple : utiliser des ressources REST &#8211; proposant une représentation HTML &#8211; pour agréger et construire une nouvelle IHM côté client, dans le navigateur.</p>
<p><span id="more-185"></span></p>
<p>Une caractéristique intéressante de REST et des ressources est ce que l&#8217;on appelle la représentation ; la possibilité de fournir la même donnée sous des formats différents. Il est possible de spécifier le format dans l&#8217;url ou dans des en-têtes http. Peu importe en fait, la même donnée peut être fournie à la fois sous la forme XML, JSON et pourquoi pas HTML.</p>
<p>Comme dirait l&#8217;autre : &nbsp;&raquo; y a plus qu&#8217;à &laquo;&nbsp;&#8230;alors utilisons une page HTML &nbsp;&raquo; maitre &nbsp;&raquo; qui agrège, au niveau du navigateur, des ressources REST ; à la fois un flux HTML, et une image qui dans notre exemple sera dynamiquement générée par Google Chart :</p>
<p><img src="/wp-content/uploads/images/figure1(2).png" alt="" width="682" height="250" align="middle" /></p>
<p>La page &nbsp;&raquo; maitre &nbsp;&raquo; fournit simplement un champ de saisie dans lequel l&#8217;utilisateur saisit un identifiant client. Les ressources GuiRessources et GoogleCharts sont alors demandées&#8230;La ressource GuiRessource retourne un fragment HTML qui permet de présenter un détail de personne (ici son nom, son adresse&#8230;) le tout mis en forme (dans cet exemple, simplement l&#8217;utilisation de type &nbsp;&raquo; bold &laquo;&nbsp;). La ressource est simplement implémentée comme suit (avec Jersey) :</p>

<div class="wp_codebox"><table><tr id="p18557"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
</pre></td><td class="code" id="p185code57"><pre class="java" style="font-family:monospace;">@Path<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/GuiRessource&quot;</span><span style="color: #009900;">&#41;</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> GuiRessource <span style="color: #009900;">&#123;</span>
 @GET
 @Produces<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;text/html&quot;</span><span style="color: #009900;">&#41;</span>
 @Path<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/{id}&quot;</span><span style="color: #009900;">&#41;</span>
 <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">String</span> getGui<span style="color: #009900;">&#40;</span>@PathParam<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;id&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #003399;">String</span> id<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  Client client <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">getClient</span><span style="color: #009900;">&#40;</span>id<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #003399;">StringBuffer</span> buffer <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">StringBuffer</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  buffer.<span style="color: #006633;">append</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;client id: &quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  buffer.<span style="color: #006633;">append</span><span style="color: #009900;">&#40;</span>id<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  buffer.<span style="color: #006633;">append</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;
&lt;div id=&quot;</span><span style="color: #0000ff;">&quot;&gt;  buffer.append(client.getPortefolio1());
  buffer.append(&quot;</span><span style="color: #339933;">&lt;/</span>div<span style="color: #339933;">&gt;</span>
<span style="color: #0000ff;">&quot;);
&nbsp;
  buffer.append(&quot;</span>
<span style="color: #339933;">&lt;</span>div id<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;&quot;</span><span style="color: #339933;">&gt;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">//etc</span>
  buffer.<span style="color: #006633;">append</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;&lt;/div&gt;
&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">return</span> buffer.<span style="color: #006633;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Je vous passe la configuration du web.xml afin de prendre en compte la servlet Jersey. Etant une ressource, cette dernière peut facilement être requêtée, typiquement dans un navigateur. Dans notre exemple, voilà ce que ca donne pour la ressource cliente identifiée par le nombre 3.</p>
<p><strong><img src="/wp-content/uploads/images/figure2.png" alt="" width="609" height="184" align="middle" /></strong></p>
<p><strong> </strong>La seconde ressource est en fait basée sur Google Chart. Il y a peu à dire&#8230;Google Charts affiche des graphiques différent suivant l&#8217;url spécifiée. Il est ainsi possible de spécifier le type de graphique, bien entendu les  données du graphique&#8230;(saisissez cette url <a href="http://chart.apis.google.com/chart?cht=p3&amp;chco=339933&amp;chs=450x150&amp;chd=t:10,50&amp;chl=Class1|Class2|">http://chart.apis.google.com/chart?cht=p3&amp;chco=339933&amp;chs=450&#215;150&amp;chd=t:10,50&amp;chl=Class1|Class2|</a> dans votre navigateur préféré&#8230;).</p>
<p>Reste alors à agréger tout cela, et c&#8217;est presque uniquement du JavaScript (en même temps vous étiez plus ou moins prévenu&#8230;)</p>

<div class="wp_codebox"><table><tr id="p18558"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code" id="p185code58"><pre class="html" style="font-family:monospace;">&nbsp;
&lt;script src=&quot;...&quot;&gt;&lt;!--mce:0--&gt;&lt;/script&gt;
&nbsp;
clientId :
&lt;input id=&quot;clientId&quot; type=&quot;text&quot; /&gt;
&lt;div id=&quot;GuiRessources&quot; style=&quot;background-color: #dddddd&quot;&gt;  Gui Ressources&lt;/div&gt;
&lt;div id=&quot;results&quot;&gt;&lt;/div&gt;
&lt;div style=&quot;float: left;&quot;&gt;
 &lt;img id=&quot;chart&quot; src=&quot;&amp;lt;a href=&quot; alt=&quot;&quot; /&gt;http://chart.apis.google.com/ &quot;
 class=&quot;totable&quot; /&amp;gt;&lt;/div&gt;</pre></td></tr></table></div>

<p>Le code de la page maître propose 3 grandes parties :</p>
<ul>
<li>Une méthode loadRessource() qui réalise un GET sur la ressource Client</li>
<li>Une méthode reloadChart() qui provoque l&#8217;accès à Google Chart et l&#8217;affichage du graphique</li>
<li>Une partie HTML qui permet l&#8217;affichage du champ de saisie du clientId et qui provoque l&#8217;appel aux méthodes précédentes sur la perte de focus.</li>
</ul>
<p>A l&#8217;exécution, les ressources interagissent, l&#8217;intégration se réalise et donne lieu aux écrans suivants :</p>
<p><img src="/wp-content/uploads/images/figure3.png" alt="" width="609" height="316" align="middle" /></p>
<p>Il s&#8217;agit là d&#8217;une façon simplissime d&#8217;intégrer de l&#8217;IHM au niveau du navigateur et de proposer des ressources ayant potentiellement une représentation au format HTML et donc une mise en forme partageable, réutilisable.</p>
<p>Reste à ne pas tomber dans les extrêmes&#8230;</p>

 <img src="http://blog.octo.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=185" width="1" height="1" style="display: none;" /><p>Suggestion d'articles :</p><ol>
<li><a href='http://blog.octo.com/rest-en-java-avec-la-jsr-311/' rel='bookmark' title='REST en JAVA avec la JSR-311'>REST en JAVA avec la JSR-311</a></li>
<li><a href='http://blog.octo.com/versioning-de-services-rest/' rel='bookmark' title='Versioning de services REST'>Versioning de services REST</a></li>
<li><a href='http://blog.octo.com/la-strategie-de-test-dune-architecture-rest-13-test-dintegration/' rel='bookmark' title='La stratégie de test d&#8217;une architecture REST (2/3) &#8211; Test d’intégration'>La stratégie de test d&#8217;une architecture REST (2/3) &#8211; Test d’intégration</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.octo.com/des-principes-rest-pour-realiser-du-mashup/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>One day @ Devoxx</title>
		<link>http://blog.octo.com/one-day-devoxx/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=one-day-devoxx</link>
		<comments>http://blog.octo.com/one-day-devoxx/#comments</comments>
		<pubDate>Wed, 10 Dec 2008 20:34:17 +0000</pubDate>
		<dc:creator>Olivier Mallassi</dc:creator>
				<category><![CDATA[Actualité]]></category>
		<category><![CDATA[devoxx]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[silverlight]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[Usabilité]]></category>

		<guid isPermaLink="false">http://new-blog.octo.com/2008/12/10/one-day-devoxx/</guid>
		<description><![CDATA[<p>Devoxx: Dev comme Développeur, Voxx comme voix...en bref, la voix du développeur. <br />C'est ainsi que débute la keynotes de la première édition de Devoxx, en fait la Nième du plus connu Javapolis et pour illustrer cette "voix", rien de mieux que celle d'un <a href="http://www.dailymotion.com/video/x189aq_best-beatboxer-ever-22_extreme">beat boxer</a> ; franchement terrible!</p>
Suggestion d'articles :<ol>
<li><a href='http://blog.octo.com/last-day-devoxx/' rel='bookmark' title='Last day @Devoxx'>Last day @Devoxx</a></li>
<li><a href='http://blog.octo.com/another-day-devoxx/' rel='bookmark' title='Another day @ Devoxx'>Another day @ Devoxx</a></li>
<li><a href='http://blog.octo.com/les-grandes-tendances-de-devoxx-2011/' rel='bookmark' title='Les grandes tendances de Devoxx 2011'>Les grandes tendances de Devoxx 2011</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fblog.octo.com%252Fone-day-devoxx%252F%22%2C%20%22style%22%3A%20%22small%22%2C%20%22title%22%3A%20%22One%20day%20%40%20Devoxx%22%20%7D);"></div>
<p>Devoxx: Dev comme Développeur, Voxx comme voix&#8230;en bref, la voix du développeur.<br />
C&#8217;est ainsi que débute la keynotes de la première édition de Devoxx, en fait la Nième du plus connu Javapolis et pour illustrer cette &laquo;&nbsp;voix&nbsp;&raquo;, rien de mieux que celle d&#8217;un <a href="http://www.dailymotion.com/video/x189aq_best-beatboxer-ever-22_extreme">beat boxer</a> ; franchement terrible !</p>
<p><span id="more-164"></span></p>
<h3>javaFX à l&#8217;honneur de la Keynote</h3>
<p>De la keynote matinale, l&#8217;envie est de ne retenir que la présentation sur JavaFX. Ils voulaient nous faire rêver mais on a vu des applications embarquant des vidéos&#8230;bref difficile d&#8217;imaginer de applications de gestion. JavaFX semble être une réponse de Sun au Adobe de Flex mais il reste quelques limitations:<br />
- La plateforme. Là où Flex fonctionne sur un plugin présent sur une immense majorité des navigateurs, javaFX nécessite un JRE, une JVM<br />
- Les nouvelles versions de JavaFX propose de faciliter l&#8217;intégration avec des outils classiques des designers comme PhotoShop et Illustrator. Reste que l&#8217;intégration avec Flex sera trés certainement plus évidente ne serait-ce que parce qu&#8217;il s&#8217;agit de la même compagnie et qu&#8217;ils ont bien compris cet enjeu de <a href="http://labs.adobe.com/technologies/flashcatalyst">rapprochement des développeurs et des designers </a><br />
- On pourrait penser que JavaFX présente l&#8217;avantage du langage Java &#8211; massivement maitrisé -. Mais en fait javaFX est aussi proche de Java qu&#8217;ActionScript.</p>
<h3>Java7 et les APIs concurrentielles</h3>
<p>L&#8217;implémentation qui a été faite des Threads depuis la première version de Java jusqu&#8217;à Java5 permettait de gérer l&#8217;asynchronisme plus que le parallélisem; ie. l&#8217;utilisation des multi coeurs. Java 5 introduit les Executor et les Tasks pour faciliter ce découpage en tâche d&#8217;assez haut niveau. java 7 veut utiliser au maximum les avancés des processeurs et faciliter la résolution de tâche qui peuvent être parallélisée au niveau d&#8217;une JVM (on ne parle pas ici de système distribué&#8230;). Les Apis fork/join facilite les opérations de tri de tableau, parcours d&#8217;arbre&#8230;Cette session est également l&#8217;occasion de découvrir comment fonctionne les piles dans ce type d&#8217;implémentation, un mécanisme de &laquo;&nbsp;work stealing&nbsp;&raquo; où chaque Worker Thread gère sa pile en FIFO et où les Worker Thread &laquo;&nbsp;amis&nbsp;&raquo; ont le droit de dépiler la pile des autres en FILO&#8230;</p>
<h3>Et si le futur des RIAs était à Flex?</h3>
<p>Autant vous le dire tout de suite, la session est &laquo;&nbsp;sponsorisé&nbsp;&raquo; par Adobe :o) mais sera l&#8217;occasion de voir de surprenantes démonstrations, de celles qui font imaginer de nouveaux patterns d&#8217;usabilité mais égalemnet d&#8217;apprendre quelques nouveautés de la prochaine mouture de Flex : Gumbo.<br />
- le rapprochement Designer/Développeur. Des initiatives comme <a href="http://labs.adobe.com/technologies/flashcatalyst/">Catalyst</a>, un nouveau format de fichier qui permet d&#8217;exporter/importer des  fichiers d&#8217;outils comme Photoshop ou Illustrator vers Flex<br />
- des améliorations de l&#8217;existant qui permettent de mieux séparer le code de logique de la définition du visuel; ie Spark Component Architecture. La définition du visuel peut se faire dans une sorte de fichier XML où l&#8217;on peut définir l&#8217;ensemble des comportements visuels des composants graphiques)<br />
- des améliorations du modèle d&#8217;animations qui permettent la 3D, l&#8217;ajout d&#8217;effets. Ces améliorations sont principalement possibles grâce aux évolutions de la plateforme d&#8217;exécution: le player Flash<br />
- le rapprochement de Spring, l&#8217;idée étant de faciliter l&#8217;intégration de plateforme type BlazeDS ou Lifecycle (pour son &laquo;&nbsp;presque équivalent&nbsp;&raquo; commercial)<br />
- la nouvelle version du Flex Builder qui outille le développement jusqu&#8217;à faciliter le binding de table sur des DataGrid.</p>
<h3>Quelques sessions sur JEE6</h3>
<p>Une présentation de JPA 2.0 qui s&#8217;enrichi par rapport à sa précédente version.<br />
- les options de mapping (nouvelles possibilités sur les jointures, PK&#8230;)<br />
- la gestion des locks optimistes ou pessimistes. Certaines APIs évoluent également et permettent de mutualiser des opérations comme la sélection de l&#8217;objet et son lock&#8230;<br />
- JP-QL reprend le principe des Criterias déjà présents dans Hibernate ou comment créer dynamiquement une requête</p>
<p>Et Web Beans qui cherche à standardiser Seam et cherche à proposer une couche de liant au dessus des composants déjà présents dans JEE (EJB, JSF Managed Bean&#8230;). L&#8217;idée principale reste de pouvoir agencer, l&#8217;ensemble de ces composants via des annotations spécifiques, le tout en masquant le composant Java; ie EJB, Java Bean, JSF Managed Bean. L&#8217;envie de standardisation va un peu plus loin en gérant les notions de scope (classiquement un scope session, request&#8230;) et en proposant des mécanismes &#8211; au final complexes &#8211; permettant de remplacer au déploiement les implémentations à utiliser.</p>
<p>C&#8217;est séduisant mais cela parait complexe&#8230;</p>
<h3>Silverlight</h3>
<p>Une assistance beaucoup moins nombreuse que pour la sesssion Flex. Pourtant ces deux sessions se sont beaucoup ressemblées :<br />
- des widgets graphiques impressionants comme le &laquo;&nbsp;deep zoom&nbsp;&raquo;<br />
- un fort accent sur la relation designer/développeur<br />
- des outils de dévéloppements productifs (Visual Studio ou eclipse pour les uns, Expression Blend ou la suite Adobe pour les autres)<br />
A noter : la possibilité d&#8217;utiliser un panel de langage de développement (C#, vb.NET ou ruby).</p>
<h3>Un nouvel acronyme : le BDD ou Behaviour Driven Desgin (et non pas Business Driven Developpement :o) )</h3>
<p>L&#8217;idée générale : &laquo;&nbsp;du TDD où le test est écrit via un DSL&nbsp;&raquo;. Cette approche rejoint celle poussée par les méthodes agiles et le pilotage par les tests: décrire fonctionnellement le système avant même de savoir comment il sera implémenté.<br />
Il s&#8217;agit alors de décrire le test via un langage plutôt fonctionnel (Given, when, then) et d&#8217;y ajouter des closures (qui jouent le rôle de fixtures dans des solutions comme Greenpepper ou Fitnesse) permettant de s&#8217;interfacer avec le &laquo;&nbsp;System Under Test&nbsp;&raquo;. De la même manière, les assertions disposent d&#8217;une sémantique plus riche du type shouldBe plutôt qu&#8217;un simple assertEquals.</p>
<p>C&#8217;est un peu le même principe que des Fitnesse et des GreenPepper; à l&#8217;exception du wiki et en imaginant que le code des fixtures est fusionné avec la description fonctionnelle du test.</p>
<h3>Des patterns et anti-patterns REST</h3>
<p>Une session intéressante qui repose les points importants de REST :<br />
1) Tout à un identifiant matérialisé par une URI<br />
2) Lier les ressources les unes aux autres<br />
3) Utiliser les verbes GET/POST/PUT/DELETE et donc éviter le &laquo;&nbsp;tunneling&nbsp;&raquo; sur POST et GET<br />
4) Une ressource peut avoir plusieurs représentation (en conservant l&#8217;URI)<br />
5) L&#8217;architecture REST est par essence sans état (Stateless)</p>
<p>L&#8217;objectif principal étant d&#8217;utiliser au maximum les possibilités du protocole HTTP et les services offerts par l&#8217;infrastructure comme les mécanismes de cache, de proxy ou d&#8217;indexation par des moteurs de recherche par exemple. Une piqure de rappel pragmatique qui fait du bien sans attaquer SOAP.</p>
<h3>Envers (sans jeu de mot) et le versionning d&#8217;objet</h3>
<p>Un framework s&#8217;intégrant nativement à hibernate et permettant par annotation de versionner les objets et de réaliser en quelque sorte une piste d&#8217;audit (ajout de metadata). Il devient alors possible de requêter un objet dans une certaine version, de savoir qui a modifié quelle propriété : un SVN pour Hibernate ;-).<br />
Une limitation soulevée pendant la présentation reste l&#8217;augmentation des accès/écritures en base. A chaque modification, insertion de la version principale de l&#8217;objet, une insertion est réalisée pour conserver les modifications.</p>
<p>Voilà pour l&#8217;essentiel de la journée.  Stay tuned!</p>
<p><strong>By Fabrice Robini, Benoit Lafontaine, Olivier Mallassi</strong></p>

 <img src="http://blog.octo.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=164" width="1" height="1" style="display: none;" /><p>Suggestion d'articles :</p><ol>
<li><a href='http://blog.octo.com/last-day-devoxx/' rel='bookmark' title='Last day @Devoxx'>Last day @Devoxx</a></li>
<li><a href='http://blog.octo.com/another-day-devoxx/' rel='bookmark' title='Another day @ Devoxx'>Another day @ Devoxx</a></li>
<li><a href='http://blog.octo.com/les-grandes-tendances-de-devoxx-2011/' rel='bookmark' title='Les grandes tendances de Devoxx 2011'>Les grandes tendances de Devoxx 2011</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.octo.com/one-day-devoxx/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sécurité des services web – 1ère partie</title>
		<link>http://blog.octo.com/securite-des-services-web-1ere-partie/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=securite-des-services-web-1ere-partie</link>
		<comments>http://blog.octo.com/securite-des-services-web-1ere-partie/#comments</comments>
		<pubDate>Thu, 04 Dec 2008 17:00:07 +0000</pubDate>
		<dc:creator>Xavier Vaccari</dc:creator>
				<category><![CDATA[Architecture et technologies]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[sécurité]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[web-services]]></category>

		<guid isPermaLink="false">http://new-blog.octo.com/2008/12/04/securite-des-services-web-1ere-partie/</guid>
		<description><![CDATA[<p>Cet article est la première partie d'une série de posts concernant la sécurité des services web.</p> <p>Nous allons présenter dans cette première partie un aperçu de la norme WS-Security pour les services SOAP et les différentes possibilités pour sécuriser des services web.</p>
Suggestion d'articles :<ol>
<li><a href='http://blog.octo.com/initiation-a-la-securite-des-web-services/' rel='bookmark' title='Initiation à la sécurité des Web Services'>Initiation à la sécurité des Web Services</a></li>
<li><a href='http://blog.octo.com/refactoring-net-avec-uml-1ere-partie/' rel='bookmark' title='Refactoring .NET avec UML, 1ère partie'>Refactoring .NET avec UML, 1ère partie</a></li>
<li><a href='http://blog.octo.com/problemes-courants-imprecision-des-calculs-mathematiques-1ere-partie/' rel='bookmark' title='Problèmes courants: Imprécision des calculs mathématiques (1ère partie)'>Problèmes courants: Imprécision des calculs mathématiques (1ère partie)</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fblog.octo.com%252Fsecurite-des-services-web-1ere-partie%252F%22%2C%20%22style%22%3A%20%22small%22%2C%20%22title%22%3A%20%22S%C3%A9curit%C3%A9%20des%20services%20web%20%E2%80%93%201%C3%A8re%20partie%22%20%7D);"></div>
<p>Cet article est la première partie d&#8217;une série de posts concernant la sécurité des services web.</p>
<p>Nous allons présenter dans cette première partie un aperçu de la norme WS-Security pour les services SOAP et les différentes possibilités pour sécuriser des services web.</p>
<p><span id="more-170"></span></p>
<p>Les architectures SOA se sont généralisées petit à petit au sein des entreprises pour construire des systèmes capables d&#8217;offrir des fonctionnalités partagées via des services.</p>
<p>Ces services peuvent être internes et ne concerner qu&#8217;une organisation ou être ouverts sur l&#8217;extérieur dans le cadre d&#8217;échanges B2B.</p>
<p>Dès lors que l&#8217;on propose de la valeur ajoutée ou transporte des données dites sensibles, ces services sont alors confrontés à des buts contradictoires :</p>
<ul>
<li>Exposer de l&#8217;information et la rendre facilement accessible à un tiers (personne ou système)</li>
<li>Sécuriser l&#8217;information pour la rendre uniquement consommable par des personnes ou des systèmes habilités à la voir et à l&#8217;utiliser.</li>
</ul>
<p>La sécurité est au cœur des préoccupations des entreprises pour garantir la cohérence et la pérennité des systèmes. Pour ce faire, la sécurité doit être prise en compte dès la conception des services web et ceci à tous les niveaux :</p>
<ul>
<li>Conception, spécification</li>
<li>Architecture</li>
<li>Développement</li>
<li>Déploiement</li>
<li>Exécution &amp; exploitation</li>
</ul>
<p>Au-delà du tout sécuritaire, une approche pragmatique de la sécurité pilotée par les risques est préférable. Rappelons les fonctions de sécurité disponibles qui pourront s&#8217;appliquer à des services:</p>
<ul>
<li><strong>Authentification</strong> : le mécanisme qui permet de vérifier l&#8217;identité d&#8217;une personne/d&#8217;un système</li>
<li><strong>Habilitation</strong> : le droit d&#8217;accéder ou non à une fonctionnalité, à une donnée</li>
<li><strong>Intégrité</strong> (ou signature) : la non modification d&#8217;une donnée échangée</li>
<li><strong>Imputabilité</strong> : traçabilité des actions d&#8217;un individu sur un système</li>
<li><strong>Confidentialité</strong> (ou chiffrement) : la non lisibilité de la donnée par un tiers ne partageant pas un secret</li>
</ul>
<p>Les stacks de sécurité des web services (WS-Security &amp; co) sont à priori complexes et chers à mettre en œuvre. Toutefois, on peut trouver des exemples concrets où ces solutions ont un réel intérêt (signature des messages par exemple).</p>
<p>Nous allons présenter dans cet article un aperçu de la norme WS-Security pour les services SOAP et les différentes possibilités pour sécuriser des services web.</p>
<h3>WS-Security</h3>
<p>WS-Security est un standard pour sécuriser des services web SOAP uniquement. Ce dernier aborde les aspects classiques comme l&#8217;authentification, l&#8217;habilitation mais également des besoins plus rares comme le chiffrement, la signature. Cette norme s&#8217;applique uniquement au niveau des messages échangés et n&#8217;a aucun impact sur le protocole et le transport choisis. Il repose sur l&#8217;ajout d&#8217;éléments dans les headers/en-têtes SOAP. Ce standard appelé aussi WSS (Web Services Security) tente de normaliser les échanges sécurisés de messages et de garantir l&#8217;interopérabilité entre systèmes.</p>
<p>Des Profiles sont disponibles pour couvrir l&#8217;ensemble des problématiques liées à la sécurité (authentification, chiffrement et signature). Le consortium OASIS vise la standardisation des spécifications WS-* pour permettre une meilleure interopérabilité entre les technologies.</p>
<h4>Authentification</h4>
<p>L&#8217;authentification s&#8217;appuie sur la notion de token c&#8217;est à dire des headers SOAP capables de véhiculer les credentials (typiquement un login et un mot de passe) jusqu&#8217;au service cible. Le niveau de confidentialité de ces données échangées peut également être choisi (hash de password, chiffrement des données,.).</p>
<p>Les principaux tokens disponibles sont :</p>
<ul>
<li><strong>User Name Token</strong> : échange de couples login/mot de passe</li>
<li><strong>SAML Token</strong> : échange de données d&#8217;authentification au format XML SAML</li>
<li><strong>X509 Token</strong> : échange de données d&#8217;authentification par certificat (authentification forte)</li>
</ul>
<p>D&#8217;autres tokens permettent de l&#8217;authentification via des systèmes tiers comme Kerberos.</p>
<p>Voici un exemple de header avec un token user name non chiffré :</p>

<div class="wp_codebox"><table><tr id="p17059"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="code" id="p170code59"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;s11</span> :Envelope <span style="color: #000066;">xmlns:S11</span>=<span style="color: #ff0000;">&quot;...&quot;</span> <span style="color: #000066;">xmlns:wsse</span>=<span style="color: #ff0000;">&quot;...&quot;</span> <span style="color: #000066;">xmlns:wsu</span>= <span style="color: #ff0000;">&quot;...&quot;</span> <span style="color: #000000; font-weight: bold;">&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/s11<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;s11</span> :Header <span style="color: #000000; font-weight: bold;">&gt;</span></span>
...
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;wsse</span> :Security<span style="color: #000000; font-weight: bold;">&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/wsse<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;wsse</span> :UsernameToken<span style="color: #000000; font-weight: bold;">&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/wsse<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;wsse</span> :Username<span style="color: #000000; font-weight: bold;">&gt;</span></span>NNK<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/wsse<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;wsse</span> :Password <span style="color: #000066;">Type</span>=<span style="color: #ff0000;">&quot;...#PasswordDigest&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
weYI3nXd8LjMNVksCKFV8t3rgHh3Rw==<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/wsse<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;wsse</span> :Nonce<span style="color: #000000; font-weight: bold;">&gt;</span></span>WScqanjCEAC4mQoBE07sAQ==<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/wsse<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;">&lt; wsu:Created<span style="color: #000000; font-weight: bold;">&gt;</span></span>2003-07-16T01:24:32Z<span style="color: #009900;">&lt; /wsu:Created<span style="color: #000000; font-weight: bold;">&gt;</span></span>
&nbsp;
&nbsp;
...
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/s11<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
...</pre></td></tr></table></div>

<h4>Chiffrement</h4>
<p>Le chiffrement peut se faire via différents algorithmes, symétriques ou asymétriques. La norme WS-Security permet l&#8217;envoi de métadonnées du client de web service au web service cible (end-point) afin de décrire la méthode de chiffrement utilisée et permettre des échanges de clé si besoin.</p>
<p>Les messages sont constitués de plusieurs parties (header, message), chacune pouvant être chiffrée ou non selon la configuration choisie.</p>
<p>Voici un exemple de chiffrement du corps du message avec un certificat X509 :</p>

<div class="wp_codebox"><table><tr id="p17060"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="code" id="p170code60"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;s11</span> :Envelope <span style="color: #000066;">xmlns:S11</span>=<span style="color: #ff0000;">&quot;...&quot;</span> <span style="color: #000066;">xmlns:wsse</span>=<span style="color: #ff0000;">&quot;...&quot;</span> <span style="color: #000066;">xmlns:wsu</span>=<span style="color: #ff0000;">&quot;...&quot;</span> <span style="color: #000066;">xmlns:ds</span>=<span style="color: #ff0000;">&quot;...&quot;</span> <span style="color: #000066;">xmlns:xenc</span>=<span style="color: #ff0000;">&quot;...&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/s11<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;s11</span> :Header<span style="color: #000000; font-weight: bold;">&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;wsse</span> :Security<span style="color: #000000; font-weight: bold;">&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;xenc</span> :ReferenceList<span style="color: #000000; font-weight: bold;">&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;xenc</span> :DataReference <span style="color: #000066;">URI</span>=<span style="color: #ff0000;">&quot;#bodyID&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/xenc<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/wsse<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/s11<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;s11</span> :Body<span style="color: #000000; font-weight: bold;">&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;xenc</span> :EncryptedData <span style="color: #000066;">Id</span>=<span style="color: #ff0000;">&quot;bodyID&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;ds</span> :KeyInfo<span style="color: #000000; font-weight: bold;">&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/ds<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;ds</span> :KeyName<span style="color: #000000; font-weight: bold;">&gt;</span></span>CN=Hiroshi Maruyama, C=JP<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/ds<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/xenc<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;xenc</span> :CipherData<span style="color: #000000; font-weight: bold;">&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/xenc<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;xenc</span> :CipherValue<span style="color: #000000; font-weight: bold;">&gt;</span></span>...//le message chiffré// <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/xenc<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
&nbsp;
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/s11<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Ainsi, plutôt que d&#8217;utiliser une couche de transport gérant la confidentialité des données, on chiffre tout ou partie du message.</p>
<h4>Signature</h4>
<p>L&#8217;objectif de la signature est de garantir l&#8217;origine du message en échangeant un jeton chiffré avec un secret partagé (clé symétrique ou asymétrique). Elle se  se fait via des certificats X509 et peut être appliquée sur des messages en clair ou chiffrés selon la configuration choisie.</p>
<p>Comme pour le chiffrement, il est possible de signer à la fois le corps des messages mais également leurs en-têtes.</p>
<p>Voici un exemple de header WS-Security avec une signature du corps du message à base de certificat X509 :</p>

<div class="wp_codebox"><table><tr id="p17061"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="code" id="p170code61"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;s11</span> :Envelope <span style="color: #000066;">xmlns:S11</span>=<span style="color: #ff0000;">&quot;...&quot;</span> <span style="color: #000066;">xmlns:wsse</span>=<span style="color: #ff0000;">&quot;...&quot;</span> <span style="color: #000066;">xmlns:wsu</span>=<span style="color: #ff0000;">&quot;...&quot;</span> <span style="color: #000066;">xmlns:ds</span>=<span style="color: #ff0000;">&quot;...&quot;</span> <span style="color: #000066;">xmlns:xenc</span>=<span style="color: #ff0000;">&quot;...&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/s11<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;s11</span> :Header<span style="color: #000000; font-weight: bold;">&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;wsse</span> :Security<span style="color: #000000; font-weight: bold;">&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;xenc</span> :ReferenceList<span style="color: #000000; font-weight: bold;">&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;xenc</span> :DataReference <span style="color: #000066;">URI</span>=<span style="color: #ff0000;">&quot;#bodyID&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/xenc<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/wsse<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/s11<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;s11</span> :Body<span style="color: #000000; font-weight: bold;">&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;xenc</span> :EncryptedData <span style="color: #000066;">Id</span>=<span style="color: #ff0000;">&quot;bodyID&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;ds</span> :KeyInfo<span style="color: #000000; font-weight: bold;">&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/ds<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;ds</span> :KeyName<span style="color: #000000; font-weight: bold;">&gt;</span></span>CN=Hiroshi Maruyama, C=JP<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/ds<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/xenc<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;xenc</span> :CipherData<span style="color: #000000; font-weight: bold;">&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/xenc<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;xenc</span> :CipherValue<span style="color: #000000; font-weight: bold;">&gt;</span></span>...//le message chiffré// <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/xenc<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
&nbsp;
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/s11<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<h3>WS-Security : une norme de plus en plus accessible</h3>
<p>La norme WS-Security est vaste mais la complexité inhérente à la norme est de plus en plus masquée et devient même dans certains cas complètement externe aux développements applicatifs.</p>
<p>En Java par exemple, l&#8217;adoption de nouveaux frameworks et leur intégration avec Spring a favorisé la mise en place de WS-Security par simple déclaration au niveau de la configuration Spring. Un service SOAP peut donc intégrer un chiffrement ou une signature par simple ajout d&#8217;un bloc XML.</p>
<p>Des constructeurs d&#8217;appliances comme IBM vont également dans ce sens en proposant des boitiers dédiés à la sécurité des web services. Ces derniers sont capables de modifier à la volée des messages SOAP pour leur appliquer des fonctions de sécurité.</p>
<h3>Où placer la sécurité ? Jusqu&#8217;où aller ?</h3>
<p>Les fonctionnalités d&#8217;un système n&#8217;étant pas exposées aux mêmes risques et cela de façon uniforme, l&#8217;approche sécuritaire pilotée par les risques permet d&#8217;ajuster le niveau de combinaison et donc d&#8217;ajuster les coûts et délais induits lors de la mise en œuvre/exploitation.</p>
<p>Généralement, la plupart des services web implémentés dans les entreprises n&#8217;embarquent pas de brique sécurité à proprement parler et les organisations ont plutôt tendance à s&#8217;appuyer, dans la plupart des cas, sur les procédures et matériels existants pour la gérer au niveau de l&#8217;infrastructure. Cette démarche a l&#8217;avantage de ne pas ou peu impacter les développements applicatifs.</p>
<p>La mise en place de tout ou partie des 5 fonctions citées précédemment doit être étudiée selon le besoin de chaque contexte. Il sera ainsi possible de trouver le meilleur compromis pour mitiger les risques en combinant ces fonctions. Voici quelques exemples de combinaisons possibles :</p>
<ul>
<li><strong>Contrôle d&#8217;accès aux services</strong> : utiliser un réseau sécurisé par des firewalls pour limiter la consommation de services à telle ou telle machine.</li>
<li><strong>Confidentialité des données échangées over HTTP</strong> : HTTPS pour le transport des données</li>
<li><strong>Confidentialité et intégrité pour des messages XML over HTTP</strong>: HTTPS pour le transport, signature personnalisée ajoutée dans le message XML</li>
<li><strong>Confidentialité et intégrité pour des messages SOAP</strong> : HTTPS pour le transport, signature du message avec WS-Security</li>
<li>.</li>
</ul>
<p>Le déploiement de la sécurité autour des services web va être principalement guidé par les contraintes de mise en œuvre (légale ou réglementaire de non répudiation, de confidentialité des données), le besoin en terme de confidentialité des données et la topologie des équipes infra, sécurité et projet au sein de l&#8217;entreprise :</p>
<ul>
<li>Le niveau de maitrise par les équipes de développement des frameworks et outils (IDE, stack SOAP ou REST, intégration sur les serveurs de développement),</li>
<li>Le niveau de maitrise par les équipes de production des briques d&#8217;infrastructure et éventuellement des frameworks utilisés sur les projets (firewalls, reverse-proxy, appliance XML, PKI/Certificats.),</li>
<li>La facilité de communication entre ces équipes est donc nécessaire pour mettre en production des services sécurisés et fluidifier les échanges,</li>
<li>Les besoins d&#8217;interopérabilité entre les systèmes exposant ou consommant des services sécurisés.</li>
</ul>
<p><img src="/wp-content/uploads/images/soa/secu-communication-equipes.png" alt="" /></p>
<p>Voici quelques exemples de combinaisons que nos architectes retrouvent souvent chez des clients.</p>
<h4>Utiliser la sécurité des infrastructures</h4>
<p><img src="/wp-content/uploads/images/soa/securite-infra.png" alt="" /></p>
<ul>
<li>Réseaux séparés ou de confiance (firewalls)</li>
<li>(optionnel) VPN pour la confidentialité sur l&#8217;extranet/internet</li>
<li>(optionnel) Authentification éventuellement déléguée à un VPN</li>
</ul>
<p>Dans ce cas, la sécurisation repose intégralement sur les briques réseau. Elle n&#8217;impacte pas les équipes de développement ce qui rend la sécurité complètement transverse à l&#8217;application. Ce cas d&#8217;utilisation s&#8217;applique dans des échanges B2B avec des partenaires (réseau VPN dédié entre le producteur et le consommateur de services) ou dans les intranets.</p>
<h4>S&#8217;appuyer sur les protocoles standards</h4>
<p><img src="/wp-content/uploads/images/soa/securite-protocole.png" alt="" /></p>
<ul>
<li>HTTP pour le protocole</li>
<li>SSL pour la confidentialité</li>
<li>Basic Auth pour l&#8217;authentification (user, mot de passe) (granularité au niveau de l&#8217;application)</li>
</ul>
<p>Ces briques sont communes et maitrisées par l&#8217;ensemble des technologies utilisées dans les entreprises (Java, .Net, C/C++, Progiciels, .). Le pattern repose entièrement sur le protocole (HTTP+SSL) et permet d&#8217;assurer à la fois l&#8217;authentification et la confidentialité (les messages transite en clair dans un tuyau crypté HTTPS).</p>
<p>Cette typologie est la plus répandue aujourd&#8217;hui. On peut l&#8217;utiliser à la fois pour des échanges internes à l&#8217;entreprise pour des services sensibles que pour relations B2B classiques utilisant l&#8217;Internet (ex: banque qui fait de l&#8217;assurance vie en marque blanche). Ce mode de sécurisation est flexible puisque l&#8217;accueil de nouveaux clients ne nécessite aucune modification de configuration existante (pas de réseau à créer contrairement à la précédente).</p>
<h5>S&#8217;appuyer sur les couches applicatives et des normes telles que WS-Security</h5>
<p><img src="/wp-content/uploads/images/soa/securite-couches-applicatives.png" alt="" /></p>
<ul>
<li>HTTP (synchrone) ou JMS (asynchrone) pour le protocole</li>
<li>Authentification par Username Token en WS-Security</li>
<li>Chiffrement des messages via WS-Security</li>
</ul>
<p>Cette solution est plus complexe à mettre en œuvre puisqu&#8217;elle impacte les couches applicatives et nécessite que les messages soient échangés en SOAP.</p>
<p>En revanche, l&#8217;application de la sécurité au niveau du message permet sa circulation sur un transport non sécurisé (http sur Internet par exemple) et une interopérabilité accrue.</p>
<p>Cette solution est intéressante dans le cas de services très ouverts sur Internet qui doivent garantir un fort niveau de confidentialité/intégrité du message.</p>
<p><strong>La suite de cette série d&#8217;articles illustrera quelques uns de ces cas d&#8217;application.</strong></p>
<h3>Références</h3>
<ul>
<li>Octo Livre Blanc <a hreflang="fr" href="http://www.octo.com/Services-Web--Choix-Architecturaux.8/Publications">« Services Web : Choix Architecturaux »</a></li>
<li>Octo <a hreflang="fr" href="http://www.octo.com/com/com_gdi.html" class="broken_link">« Gestion des identités »</a></li>
<li><a hreflang="fr" href="http://74.125.77.132/search?q=cache:tDchHKAzrugJ:www.oasis-open.org/committees/download.php/16782/wss-v1.1-spec-os-UsernameTokenProfile.pdf&amp;hl=en&amp;ct=clnk&amp;cd=2&amp;gl=us&amp;client=firefox-a" class="broken_link">OASIS User Name Token Profile</a></li>
<li><a hreflang="fr" href="http://www.oasis-open.org/committees/download.php/16790/wss-v1.1-spec-os-SOAPMessageSecurity.pdf">Spécification WS-Security</a></li>
<li><a hreflang="fr" href="http://fr.wikipedia.org/wiki/Security_Assertion_Markup_Language">Définition SAML</a></li>
</ul>

 <img src="http://blog.octo.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=170" width="1" height="1" style="display: none;" /><p>Suggestion d'articles :</p><ol>
<li><a href='http://blog.octo.com/initiation-a-la-securite-des-web-services/' rel='bookmark' title='Initiation à la sécurité des Web Services'>Initiation à la sécurité des Web Services</a></li>
<li><a href='http://blog.octo.com/refactoring-net-avec-uml-1ere-partie/' rel='bookmark' title='Refactoring .NET avec UML, 1ère partie'>Refactoring .NET avec UML, 1ère partie</a></li>
<li><a href='http://blog.octo.com/problemes-courants-imprecision-des-calculs-mathematiques-1ere-partie/' rel='bookmark' title='Problèmes courants: Imprécision des calculs mathématiques (1ère partie)'>Problèmes courants: Imprécision des calculs mathématiques (1ère partie)</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.octo.com/securite-des-services-web-1ere-partie/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>De la réussite durable d’une démarche SOA</title>
		<link>http://blog.octo.com/de-la-reussite-durable-dune-demarche-soa/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=de-la-reussite-durable-dune-demarche-soa</link>
		<comments>http://blog.octo.com/de-la-reussite-durable-dune-demarche-soa/#comments</comments>
		<pubDate>Fri, 21 Nov 2008 22:59:53 +0000</pubDate>
		<dc:creator>Olivier Mallassi</dc:creator>
				<category><![CDATA[Méthodologie et conduite du changement]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[services]]></category>
		<category><![CDATA[SOA]]></category>

		<guid isPermaLink="false">http://new-blog.octo.com/2008/11/21/de-la-reussite-durable-dune-demarche-soa/</guid>
		<description><![CDATA[<p align="justify">Trop souvent les démarches SOA adressent uniquement les problématiques d'architectures techniques et fonctionnelles,  au dépend des enjeux humains et organisationnels inhérents à la transformation qu'impose la SOA au SI.</p>]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fblog.octo.com%252Fde-la-reussite-durable-dune-demarche-soa%252F%22%2C%20%22style%22%3A%20%22small%22%2C%20%22title%22%3A%20%22De%20la%20r%C3%A9ussite%20durable%20d%E2%80%99une%20d%C3%A9marche%20SOA%22%20%7D);"></div>
<p align="justify">Trop souvent les démarches SOA adressent uniquement les problématiques d&#8217;architectures techniques et fonctionnelles,  au dépend des enjeux humains et organisationnels inhérents à la transformation qu&#8217;impose la SOA au SI.</p>
<p><span id="more-161"></span></p>
<h3>La SOA doit aider à fédérer une communauté de partenaires et à maintenir l&#8217;adaptabilité du SI</h3>
<p align="justify"><strong>Dans les échanges qu&#8217;a l&#8217;entreprise avec ses partenaires extérieurs divers</strong>, la nécessité de mettre en place et d&#8217;utiliser des services ne se discute plus. L&#8217;entreprise s&#8217;ouvre, s&#8217;interconnecte, fournit et consomme de l&#8217;information, participe à des chaînes de valeur : <strong>cherche à fédérer autour de sa plateforme</strong>. Dans <strong>l&#8217;extension de cette approche vers l&#8217;intérieur</strong>, l&#8217;entreprise cherche à maitriser les processus métier et à répondre à des enjeux tels que le <strong>cross-selling</strong>, le <strong>respect du time-to-market</strong> de nouveaux produits, la possibilité d&#8217;absorber des reconfigurations sectorielles&#8230;<br /><strong>La DSI occupe une place prépondérante dans cette transformation</strong> et les enjeux invoqués se déclinent alors essentiellement dans la mutualisation des règles métiers, la gouvernance et la qualité de la donnée, la gestion des échanges inter/intra entreprise, <strong>la recherche de l&#8217;efficacité des projets informatiques</strong> (en favorisant par exemple l&#8217;interopérabilité des applications de générations ou de technologies différentes) et <strong>l&#8217;adaptabilité du SI aux évolutions métiers</strong>. </p>
<h3>Le SI &nbsp;&raquo; mute &nbsp;&raquo; d&#8217;un SI en silos vers un SI proposant des services partagés</h3>
<p align="justify">Un consensus semble établi sur le fait que la SOA est un des meilleurs candidats pour adresser l&#8217;ensemble de ces enjeux. Mais les SI d&#8217;aujourd&#8217;hui sont constitués d&#8217;applications et de sources de données variées, basées sur des technologies hétérogènes et souvent gérées par des organisations cloisonnées. La SOA tire ses gênes de cette complexité et propose <strong>une architecture qui présente fonctions et informations du SI sous forme de &laquo;&nbsp;services&nbsp;&raquo; interopérables</strong> et faiblement couplés. <strong>L&#8217;architecture du SI s&#8217;organise </strong>alors à travers la factorisation des éléments communs, l&#8217;élimination des redondances, la réutilisation de services <strong>avec comme conséquence la &laquo;&nbsp;mutation&nbsp;&raquo; d&#8217;un SI en silo vers un SI proposant des services partagés</strong> </p>
<p align="center"><img height="283" alt="" width="464" align="middle" src="/wp-content/uploads/images/silo-soa.png" /></p>
<p align="left">  Reste qu&#8217;une telle <strong>mise en oeuvre est souvent synonyme de désillusions voire de douleurs</strong>&#8230;</p>
<ul>
<li>
<div align="justify"><strong>une augmentation drastique des dépendances entre les applications et les équipes</strong> avec des difficultés lors de la planification des développements, lors de la définition et la mise à disposition des contrats de services, des impacts sur les processus de gestion des évolutions ou de correction des anomalies qui doit prendre en compte les divers consommateurs, un &nbsp;&raquo; run &nbsp;&raquo; qui peut avoir à assurer la disponibilité de multiples versions de services, la promesse de découplage qui fait oublier que l&#8217;ensemble des applications mises à contribution risquent de devoir s&#8217;aligner sur le SLA le plus exigeant </div>
</li>
<li>
<div align="justify"><strong>une mise en oeuvre prématurée d&#8217;outils comme les ESB ou les BPM</strong>. Utiliser à bon escient et dans des organisations suffisamment matures, ces outils permettent d&#8217;optimiser certains comportements (sécurité, routage, administration&#8230;). A l&#8217;inverse, ils peuvent devenir une contrainte et une source de complexité</div>
</li>
<li>
<div align="justify"><strong>une approche uniquement &nbsp;&raquo; bottom-up &nbsp;&raquo; qui mène à des échanges points à points non maitrisés</strong> et une très faible réutilisabilité</div>
</li>
<li>
<div align="justify"><strong>une approche uniquement &nbsp;&raquo; top-down &nbsp;&raquo; qui imagine des SI &nbsp;&raquo; tout services &laquo;&nbsp;</strong> ; créant des formats pivots &nbsp;&raquo; a priori &nbsp;&raquo; alors que beaucoup d&#8217;applications ne sont pas prêtes ou normalisant &nbsp;&raquo; à tout va &nbsp;&raquo; les référentiels au risque de limiter la performance générale des services</div>
</li>
</ul>
<h3>Une démarche SOA doit se décliner sur trois axes : les technologies, l&#8217;architecture du SI et les aspects organisationnels et humains</h3>
<p align="justify"><strong>La mise en oeuvre d&#8217;une architecture SOA doit être pragmatique et dimensionnée en fonction de la complexité de l&#8217;architecture cible et de la maturité de l&#8217;organisation</strong> pour supporter humainement, techniquement et financièrement cette architecture. </p>
<p align="justify">Mais quelque soit le niveau de complexité et de maturité, <strong>la réalisation d&#8217;une architecture SOA se décline sur trois axes: les technologies, l&#8217;architecture du SI et les aspects organisationnels et humains</strong>. </p>
<p align="justify"><strong>L&#8217;axe technologique embrasse l&#8217;ensemble des aspects de l&#8217;architecture applicative et de l&#8217;expertise technique et vise à plus de simplicité</strong>. L&#8217;émergence d&#8217;architectures dites &laquo;&nbsp;orientées ressources&nbsp;&raquo; (ROA) et plus légères que les approches dites &laquo;&nbsp;classiques&nbsp;&raquo; (SOAP) rebattent les cartes et promettent de meilleures interopérabilité et productivité mais cela nécessite d&#8217;appliquer des principes d&#8217;architecture différents et potentiellement complémentaires. Parallèlement, la sécurisation des services doit privilégier une approche pilotée par les risques plutôt qu&#8217;une approche totalement sécuritaire et permettre l&#8217;utilisation de moyens techniques adaptés en termes de propriétés et de coûts. Enfin, les différentes plateformes de développement sont relativement matures mais reste à maîtriser leur déploiement (contract-first, code-first), industrialiser leur utilisation afin que leur usage dans le flux de développement ne soit un frein ni à la productivité, ni à la testabilité.  </p>
<p align="justify"><strong>Le second axe regroupe les disciplines de l&#8217;architecture de SI, la modélisation des processus métier et promeut des architectures simples et évolutives,  des standards opérationnels</strong>. Il est aujourd&#8217;hui nécessaire de mixer approche organique et approche légaliste. L&#8217;approche organique, permet de faire &nbsp;&raquo; émerger &nbsp;&raquo; des services au sein de projets et facilite la découverte d&#8217;une direction opérable à coûts et risques optimisés à partir d&#8217;un existant en terme de code, de compétences techniques et fonctionnelles. Mais cette approche sera cadrée par l&#8217;approche légaliste permettant d&#8217;aligner les différents acteurs sur une intention commune, une vision partagée. De ce mélange des deux approches apparaît une direction unique et utile : des modèles et des standards applicables rapidement par les projets et améliorés de façon continue grâce au &laquo;&nbsp;retour terrain&nbsp;&raquo;. </p>
<p align="justify">Enfin <strong>l&#8217;organisation et les dynamiques d&#8217;équipes devront évoluer pour &laquo;&nbsp;s&#8217;aligner&nbsp;&raquo; sur ces notions de &laquo;&nbsp;services&nbsp;&raquo; et intégrer un mode de développement lui aussi distribué</strong>. Des aspects souvent oubliés mais qui imposent à l&#8217;organisation de se transformer pour faire émerger des équipes responsables (c&#8217;est à dire garantes de la sémantique, de l&#8217;intéropérabilité, de la non régression, du SLA&#8230;) des services. Cette mise en oeuvre du changement, passera par l&#8217;adaptation des processus de développement, de l&#8217;organisation du travail et par la remise en cause de la classique contractualisation entre équipes. Cette transformation se traduira par une spécialisation des équipes par &nbsp;&raquo; bouquet de services &laquo;&nbsp;, une diminution des chaines de responsabilités afin de polariser les équipes sur un unique but qu&#8217;est le &laquo;&nbsp;service&nbsp;&raquo;, une évolution des processus de développement vers du plus &laquo;&nbsp;itératif-incrémental&nbsp;&raquo;. </p>
<p align="justify">Quant à <strong>la Gouvernance</strong>, cette dernière <strong>aura à charge de préciser les standards à appliquer sur chacun des ces trois axes</strong>. </p>
<p align="justify">Ainsi, pour que l&#8217;augmentation des dépendances entre services et équipes n&#8217;aboutisse pas à une paralysie générale lors de la transformation du SI vers une architecture de services, les équipes devront maîtriser les outils et méthodes de l&#8217;amélioration continue : développement incrémental et itératif, testabilité du SI, architecture organique, standards émergeants, responsabilisation des hommes</p>
<div align="left"><font size="2"></font><font color="#808080">Issu de discussions &nbsp;&raquo; endiablées &nbsp;&raquo; avec Damien Joguet, Dominique Jocal, Eric Biernat et Pierre Pezziardi    ;o)</font></div>

 <img src="http://blog.octo.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=161" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.octo.com/de-la-reussite-durable-dune-demarche-soa/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

