<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6538999683570325297</id><updated>2012-01-29T14:41:42.591-04:00</updated><category term='spring security'/><category term='gwt'/><category term='acegi'/><category term='hibernate'/><category term='maven'/><category term='eclipse'/><category term='architecture'/><category term='git'/><category term='java'/><category term='wicket'/><category term='spring'/><title type='text'>Sur un air de Java</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://surunairdejava.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://surunairdejava.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Cédric Thiébault</name><uri>http://www.blogger.com/profile/01915436356438533195</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>15</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6538999683570325297.post-4607087914514618553</id><published>2010-12-21T17:39:00.004-04:00</published><updated>2010-12-21T21:38:44.613-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='git'/><title type='text'>Premiers pas sous Git</title><content type='html'>&lt;p&gt;
 Je me d&amp;eacute;cide enfin &amp;agrave; succomber au buzz et tente ma chance sous &lt;a href="http://git-scm.com" target="_blank"&gt;Git&lt;/a&gt;. 
 &lt;br /&gt;
 Pas tant pour le cote d&amp;eacute;centralis&amp;eacute; que pour les merge simplifi&amp;eacute;s et les gros move lors d'important refactoring.
&lt;/p&gt;

&lt;p&gt;
 Pour tester la b&amp;ecirc;te je vais d'abord migrer des projets existants de Subversion &amp;agrave; Git en m'inspirant de cet excellent billet de Jon Maddox :
 &lt;br /&gt;
 &lt;a href="http://www.jonmaddox.com/2008/03/05/cleanly-migrate-your-subversion-repository-to-a-git-repository" target="_blank"&gt;http://www.jonmaddox.com/2008/03/05/cleanly-migrate-your-subversion-repository-to-a-git-repository&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
 &lt;a href="https://www.assembla.com" target="_blank"&gt;Assembla&lt;/a&gt; propose un h&amp;eacute;bergement Git gratuit jusqu'&amp;agrave; 2Go par repository. &lt;br /&gt;
 J'utilise &lt;a href="http://code.google.com/p/msysgit" target="_blank"&gt;msysgit&lt;/a&gt; pour Git sous Windows.
&lt;/p&gt;

&lt;p&gt;
Une fois Git install&amp;eacute;, on identifie l'utilisateur qui fera les commit:
&lt;/p&gt;

&lt;pre class="brush:shell"&gt;
git config --global user.name "Cedric Thiebault"
git config --global user.email "cedric.thiebault@gmail.com"
&lt;/pre&gt;

&lt;p&gt;
Sans cette configuration, Git utilisera directement les informations contenues dans votre profil utilisateur syst&amp;egrave;me.
&lt;/p&gt;

&lt;p&gt;
 Ensuite, il faut cr&amp;eacute;er un fichier texte qui va faire le mapping entre les users SVN et les users Git (svn-git-users.txt):
&lt;/p&gt;

&lt;pre&gt;
 cthiebault = Cedric Thiebault &amp;lt;cedric.thiebault@gmail.com&amp;gt;
&lt;/pre&gt;

&lt;p&gt;
 Nous allons maintenant r&amp;eacute;cup&amp;eacute;rer le projets et son historique depuis SVN dans un r&amp;eacute;pertoire temporaire (sous Git). Finalement, nous clonerons se projet temporaire vers un vrai repository final que nous "pousserons" vers le repository Assembla dans la branche principale (master).
&lt;/p&gt;

&lt;pre class="brush:shell"&gt;
mkdir project-tmp
cd project-tmp
git svn init https://svn-repository/project/trunk --no-metadata
git config svn.authorsfile ../svn-git-users.txt
git svn fetch
cd ..
git clone project-tmp project
cd project
git remote add project git@git.assembla.com:project.git
git push project master
&lt;/pre&gt;

&lt;p&gt;Quelques sites bien pratique pour d&amp;eacute;buter avec Git :
&lt;br /&gt;
&lt;a href="http://blog.octo.com/git-dans-la-pratique-12/" target="_blank"&gt;Git dans la pratique (1/2)&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://blog.octo.com/git-dans-la-pratique-22/" target="_blank"&gt;Git dans la pratique (2/2)&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://www.gitready.com" target="_blank"&gt;Git Ready&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://blog.gitfr.net" target="_blank"&gt;#gitfr&lt;/a&gt;&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6538999683570325297-4607087914514618553?l=surunairdejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://surunairdejava.blogspot.com/feeds/4607087914514618553/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6538999683570325297&amp;postID=4607087914514618553' title='4 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default/4607087914514618553'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default/4607087914514618553'/><link rel='alternate' type='text/html' href='http://surunairdejava.blogspot.com/2010/12/premiers-pas-sous-git.html' title='Premiers pas sous Git'/><author><name>Cédric Thiébault</name><uri>http://www.blogger.com/profile/01915436356438533195</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6538999683570325297.post-8945088659630348339</id><published>2010-04-19T16:34:00.012-04:00</published><updated>2010-04-20T10:54:23.734-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gwt'/><category scheme='http://www.blogger.com/atom/ns#' term='spring'/><category scheme='http://www.blogger.com/atom/ns#' term='acegi'/><category scheme='http://www.blogger.com/atom/ns#' term='spring security'/><title type='text'>GWT et Spring Security (ex ACEGI)</title><content type='html'>&lt;p&gt;
 Ce billet pr&amp;eacute;sentera comment rapidement s&amp;eacute;curiser une application GWT (SmartGWT en fait) en utilisant un formulaire d'authentification g&amp;eacute;r&amp;eacute; par GWT et non une page web avec un formulaire HTML classique.
&lt;/p&gt;

&lt;p&gt;
 L'application est developp&amp;eacute;e avec les outils suivants :
&lt;/p&gt;
&lt;ul style="margin-top: -5px;"&gt;
 &lt;li&gt;&lt;a href="http://code.google.com/webtoolkit" target="_blank"&gt;GWT 2.0&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://code.google.com/p/smartgwt" target="_blank"&gt;SmartGWT 2.0&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.springsource.org/about" target="_blank"&gt;Spring&lt;/a&gt; et &lt;a href="http://static.springsource.org/spring-security/site" target="_blank"&gt;Spring Security 3.0&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://noon.gilead.free.fr/gilead/" target="_blank"&gt;Gilead 1.3&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://gwt-widget.sourceforge.net" target="_blank"&gt;GWT-SL 1.0&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
 Le projet &lt;a href="http://code.google.com/p/gwt-ent" target="_blank"&gt;GWT-ent&lt;/a&gt; propose une int&amp;eacute;gration avec Spring Security mais seulement avec la version 2.5 et la qualit&amp;eacute; du code laisse &amp;agrave; d&amp;eacute;sirer...
 &lt;br /&gt;
 De plus, avec les derni&amp;egrave;res versions de Spring Security la configuration a &amp;eacute;t&amp;eacute; grandement simplifi&amp;eacute;e!
&lt;/p&gt;


&lt;h4&gt;
 Configuration du projet avec Maven
&lt;/h4&gt;

&lt;p&gt;
-- POM.xml --
&lt;/p&gt;

&lt;pre class="brush:xml"&gt;
&amp;lt;dependency&amp;gt;
  &amp;lt;groupId&amp;gt;org.springframework.security&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;spring-security-config&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;3.0.2.RELEASE&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&amp;lt;dependency&amp;gt;
  &amp;lt;groupId&amp;gt;org.springframework.security&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;spring-security-core&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;3.0.2.RELEASE&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&amp;lt;dependency&amp;gt;
  &amp;lt;groupId&amp;gt;org.springframework.security&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;spring-security-web&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;3.0.2.RELEASE&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/pre&gt;

&lt;h4&gt;
 Configuration de l'application web
&lt;/h4&gt;

&lt;p&gt;
 -- web.xml --
&lt;/p&gt;

&lt;pre class="brush:xml"&gt;
&amp;lt;web-app id="gwtSecurity"&amp;gt;

  &amp;lt;context-param&amp;gt;
    &amp;lt;param-name&amp;gt;contextConfigLocation&amp;lt;/param-name&amp;gt;
    &amp;lt;param-value&amp;gt;
      classpath:applicationContext.xml
      classpath:applicationContext-security.xml
    &amp;lt;/param-value&amp;gt;
  &amp;lt;/context-param&amp;gt;

  &amp;lt;filter&amp;gt;
    &amp;lt;filter-name&amp;gt;springSecurityFilterChain&amp;lt;/filter-name&amp;gt;
    &amp;lt;filter-class&amp;gt;org.springframework.web.filter.DelegatingFilterProxy&amp;lt;/filter-class&amp;gt;
  &amp;lt;/filter&amp;gt;

  &amp;lt;filter-mapping&amp;gt;
    &amp;lt;filter-name&amp;gt;springSecurityFilterChain&amp;lt;/filter-name&amp;gt;
    &amp;lt;url-pattern&amp;gt;/*&amp;lt;/url-pattern&amp;gt;
  &amp;lt;/filter-mapping&amp;gt;

  &amp;lt;listener&amp;gt;
    &amp;lt;listener-class&amp;gt;org.springframework.web.context.ContextLoaderListener&amp;lt;/listener-class&amp;gt;
  &amp;lt;/listener&amp;gt;

  &amp;lt;listener&amp;gt;
    &amp;lt;listener-class&amp;gt;org.springframework.security.web.session.HttpSessionEventPublisher&amp;lt;/listener-class&amp;gt;
  &amp;lt;/listener&amp;gt;

  &amp;lt;servlet&amp;gt;
    &amp;lt;servlet-name&amp;gt;rpc-dispatcher&amp;lt;/servlet-name&amp;gt;
    &amp;lt;servlet-class&amp;gt;org.springframework.web.servlet.DispatcherServlet&amp;lt;/servlet-class&amp;gt;
  &amp;lt;/servlet&amp;gt;

  &amp;lt;servlet-mapping&amp;gt;
    &amp;lt;servlet-name&amp;gt;rpc-dispatcher&amp;lt;/servlet-name&amp;gt;
    &amp;lt;url-pattern&amp;gt;*.rpc&amp;lt;/url-pattern&amp;gt;
  &amp;lt;/servlet-mapping&amp;gt;

  [...]

&amp;lt;/web-app&amp;gt;
&lt;/pre&gt;

&lt;h4&gt;
 Configuration de Spring Security
&lt;/h4&gt;

&lt;p&gt;
 Ici, nous indiquons &amp;agrave; Spring d'utiliser notre UserService pour acc&amp;eacute;der aux utilisateurs ainsi que le SHA pour crypter les mots de passe.
 &lt;br /&gt;
 Nous ne prot&amp;eacute;geons aucune URL puisque notre application est h&amp;eacute;berg&amp;eacute;e sur une unique page.
 &lt;br /&gt;
 Nous avons &amp;eacute;t&amp;eacute; oblig&amp;eacute; de red&amp;eacute;finir le RememberMeServices pour forcer le alwaysRemember &amp;agrave; vrai. par d&amp;eacute;faut Spring s'attend &amp;agrave; recevoir un param&amp;egrave;tre dans l'URL qui lui demanderait de se souvenir de cet utilisateur lors du prochain acc&amp;egrave;s. Comme nous utilisons des appels RPC, nous ne pouvons pas passer ce param&amp;egrave;tre dans le request.
&lt;/p&gt;

&lt;p&gt;
 -- applicationContext-security.xml --
&lt;/p&gt;

&lt;pre class="brush:xml"&gt;
&amp;lt;beans xmlns="http://www.springframework.org/schema/beans" xmlns:security="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd"&amp;gt;

  &amp;lt;security:authentication-manager alias="authenticationManager"&amp;gt;
    &amp;lt;security:authentication-provider user-service-ref="userService"&amp;gt;
      &amp;lt;security:password-encoder hash="sha" /&amp;gt;
    &amp;lt;/security:authentication-provider&amp;gt;
  &amp;lt;/security:authentication-manager&amp;gt;

  &amp;lt;security:http auto-config="true"&amp;gt;
    &amp;lt;security:intercept-url pattern="/*" access="IS_AUTHENTICATED_ANONYMOUSLY" /&amp;gt;
    &amp;lt;security:intercept-url pattern="/css/**" filters="none" /&amp;gt;
    &amp;lt;security:intercept-url pattern="/images/**" filters="none" /&amp;gt;
    &amp;lt;security:logout logout-url="/logout" logout-success-url="/gwt.html" /&amp;gt;
    &amp;lt;security:remember-me key="gwtSecurity" /&amp;gt;
  &amp;lt;/security:http&amp;gt;

  &amp;lt;bean id="rememberMeServices" class="org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices"&amp;gt;
    &amp;lt;property name="alwaysRemember" value="true" /&amp;gt;
    &amp;lt;property name="userDetailsService" ref="userService" /&amp;gt;
    &amp;lt;property name="key" value="gwtSecurity" /&amp;gt;
  &amp;lt;/bean&amp;gt;

&amp;lt;/beans&amp;gt;
&lt;/pre&gt;

&lt;h4&gt;
 Configuration de la servlet pour les appels RPC
&lt;/h4&gt;

&lt;p&gt;
 On utilise ici Gilead et GWT-SL.
 &lt;br /&gt;
 -- rpc-dispatcher-servlet.xml --
&lt;/p&gt;

&lt;pre class="brush:xml"&gt;
&amp;lt;beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"&amp;gt;

  &amp;lt;bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"&amp;gt;
    &amp;lt;property name="mappings"&amp;gt;
      &amp;lt;map&amp;gt;
        &amp;lt;entry key="/user.rpc" value-ref="userRemoteService" /&amp;gt;
        &amp;lt;entry key="/security.rpc" value-ref="securityRemoteService" /&amp;gt;
        [...]
      &amp;lt;/map&amp;gt;
    &amp;lt;/property&amp;gt;
  &amp;lt;/bean&amp;gt;

  &amp;lt;bean id="abstractGileadRPCServiceExporter" class="org.gwtwidgets.server.spring.gilead.GileadRPCServiceExporter" abstract="true"&amp;gt;
    &amp;lt;property name="beanManager" ref="persistentBeanManager" /&amp;gt;
  &amp;lt;/bean&amp;gt;

  &amp;lt;bean id="userRemoteService" parent="abstractGileadRPCServiceExporter"&amp;gt;
    &amp;lt;property name="service" ref="userService" /&amp;gt;
    &amp;lt;property name="serviceInterfaces" value="service.user.UserRemoteService" /&amp;gt;
  &amp;lt;/bean&amp;gt;

  &amp;lt;bean id="securityRemoteService" parent="abstractGileadRPCServiceExporter"&amp;gt;
    &amp;lt;property name="service" ref="securityService" /&amp;gt;
    &amp;lt;property name="serviceInterfaces" value="service.security.SecurityRemoteService" /&amp;gt;
  &amp;lt;/bean&amp;gt;

  [...]

&amp;lt;/beans&amp;gt;
&lt;/pre&gt;

&lt;h4&gt;
 Implementation du service d'authentification
&lt;/h4&gt;

&lt;p&gt;
 Le Authentication Manager de Spring doit pouvoir r&amp;eacute;cup&amp;eacute;rer un utilisateur par son nom d'usager. Ici c'est la class UserService qui impl&amp;eacute;mentera l'interface org.springframework.security.core.userdetails.UserDetailsService pour pouvoir &amp;ecirc;tre utilis&amp;eacute; par le Authentication Manager de Spring.
&lt;/p&gt;

&lt;pre class="brush:java"&gt;
@Service("userService")
@Transactional(readOnly = true)
public class UserServiceImpl implements UserService, UserDetailsService {

  [...]

  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
    if (StringUtils.isBlank(username)) throw new UsernameNotFoundException(username);

    User user = findByLogin(username);
    if (user == null) throw new UsernameNotFoundException(username);

    List&amp;lt;GrantedAuthority&amp;gt; authorities = new ArrayList&amp;lt;GrantedAuthority&amp;gt;(user.getPermissions().size());
    for (String perm : user.getPermissions()) {
      authorities.add(new GrantedAuthorityImpl(perm));
    }

    boolean enabled = user.isActive();
    boolean accountNonExpired = true;
    boolean accountNonLocked = true;
    boolean credentialsNonExpired = true;
    return new org.springframework.security.core.userdetails.User(username, user.getPassword(), enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
  }

}
&lt;/pre&gt;

&lt;p&gt;
 Dans notre cas, on ne vas pas d'authentifier par un formulaire HTML qui posterait vers une adresse g&amp;eacute;r&amp;eacute; par Spring Security car tout est g&amp;eacute;r&amp;eacute; en Javascript et on ne veut pas quitter la page courante.
 &lt;br /&gt;
 Il va donc falloir d&amp;eacute;finir un service que l'on pourra appeler via RPC pour ouvrir une session. Ce service s'occupera de g&amp;eacute;rer aussi le "Remember Me".
&lt;/p&gt;

&lt;pre class="brush:java"&gt;
@Service("securityService")
public class SecurityServiceImpl implements SecurityService {

  @Resource
  private AuthenticationManager authenticationManager;

  @Resource
  private RememberMeServices rememberMeServices;

  @Override
  public boolean login(String username, String password, boolean rememberMe) {
    try {
      Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
      SecurityContextHolder.getContext().setAuthentication(authentication);
      if (rememberMe) {
        rememberMeServices.loginSuccess(ServletUtils.getRequest(), ServletUtils.getResponse(), authentication);
      }      
      return authentication.isAuthenticated();
    } catch (AuthenticationException e) {
      if (rememberMe) {
        rememberMeServices.loginFail(ServletUtils.getRequest(), ServletUtils.getResponse());
      }
      return false;
    }
  }

  [...]

}
&lt;/pre&gt;

&lt;p&gt;
 Finalement, il en reste plus qu'&amp;agrave; notre interface (ici avec SmartGWT) &amp;agrave; appeler notre service d'authentification :
&lt;/p&gt;

&lt;pre class="brush:java"&gt;
public class LoginForm extends DynamicForm {

  private SecurityRemoteServiceAsync securityService = GWT.create(SecurityRemoteService.class);

  TextItem login;
  PasswordItem password;
  CheckboxItem rememberMe;

  [...]

  void login() {
    securityService.login(username, password, remeberMe,
        new AsyncCallback&amp;lt;Boolean&amp;gt;() {
          public void onFailure(Throwable caught) {
            loginFailed();
          }

          public void onSuccess(Boolean success) {
            if (success) {
              // user successfully logged in
            } else {
              loginFailed();
            }
          }
        });
  }

}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6538999683570325297-8945088659630348339?l=surunairdejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://surunairdejava.blogspot.com/feeds/8945088659630348339/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6538999683570325297&amp;postID=8945088659630348339' title='7 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default/8945088659630348339'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default/8945088659630348339'/><link rel='alternate' type='text/html' href='http://surunairdejava.blogspot.com/2010/04/gwt-et-spring-security-anciennement.html' title='GWT et Spring Security (ex ACEGI)'/><author><name>Cédric Thiébault</name><uri>http://www.blogger.com/profile/01915436356438533195</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6538999683570325297.post-5312436530281091478</id><published>2008-09-26T15:18:00.012-04:00</published><updated>2010-04-20T09:35:54.716-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wicket'/><title type='text'>Wicket: Checkbox, AbstractCheckBoxModel  et enum</title><content type='html'>&lt;p&gt;
 Voici maintenant 3 semaines que je travaille avec
 &lt;a href="http://wicket.apache.org/" target="_blank"&gt;Wicket&lt;/a&gt; et je dois dire que je suis vraiment impressionné par la
 vitesse de développement avec ce framework.
 &lt;br /&gt;
 Ça prend un petit peu de temps pour se familiariser avec l'approche "component oriented" mais une fois que l'on a
 compris... ça dépote :-)
&lt;/p&gt;

&lt;p&gt;
 Seul petit défaut à mon avis : la documentation!
 &lt;br /&gt;
 Quand on vient du monde merveilleusement documenté de Spring, Wicket est un peu dur...
&lt;/p&gt;

&lt;p&gt;
 Dans le billet d'aujourd'hui, je présenterais comment afficher une liste de checkbox pour toutes les valeurs d'un enum.
 &lt;br /&gt;
 Je n'utilise pas de radio car je veux pouvoir désélectionner tous les checkbox (ie la valeur nulle est permise).
 &lt;br /&gt;
 En fait c'est exactement le fonctionnement d'une liste de radio (un seul choix possible) mais je peux tout
 désélectionner , ce qui n'est pas possible avec les radios.
&lt;/p&gt;

&lt;p&gt;
 &lt;input type="checkbox" id="ie"&gt;
 &lt;label for="ie"&gt;
  Internet Explorer
 &lt;/label&gt;
 &lt;br /&gt;
 &lt;input type="checkbox" id="firefox"&gt;
 &lt;label for="firefox"&gt;
  Firefox
 &lt;/label&gt;
 &lt;br /&gt;
 &lt;input type="checkbox" id="opera"&gt;
 &lt;label for="opera"&gt;
  Opera
 &lt;/label&gt;
 &lt;br /&gt;
 &lt;input type="checkbox" id="chrome"&gt;
 &lt;label for="chrome"&gt;
  Chrome
 &lt;/label&gt;
&lt;/p&gt;

&lt;p&gt;
 Évidemment dans l'exemple ci-dessus, le choix n'est pas unique mais c'est juste pour montrer à quoi ça va ressembler à
 la fin... ;-)
&lt;/p&gt;

&lt;p&gt;
 Pour commencer, mes
 &lt;b&gt;enum&lt;/b&gt; implémentent l'interface suivante qui permet de connaître le label correspondant à chaque enum.
&lt;/p&gt;

&lt;pre class="brush:java"&gt;
public interface LabeledEnum {
  String getLabel();
} 
&lt;/pre&gt;

&lt;pre class="brush:java"&gt;
public enum Browser implements LabeledEnum {

  IE, FIREFOX, OPERA, CHROME;

  public String getLabel() {
    return "browser." + name();
  }
  
}
&lt;/pre&gt;

&lt;pre class="brush:java"&gt;
browser.IE=Internet Explorer
browser.FIREFOX=Firefox
browser.OPERA=Opera
browser.CHROME=Chrome
&lt;/pre&gt;

&lt;p&gt;
 Le composant
 &lt;a href="http://www.wicketframework.org/apidocs/wicket/markup/html/form/CheckBox.html" target="_blank"&gt;Checkbox&lt;/a&gt; ne
 travaille qu'avec un Model de type boolean. Donc je ne peux pas lui passer directement mon enum.
 &lt;br /&gt;
 Il faut utiliser par la classe
 &lt;a href="http://wicketframework.org/wicket-extensions/apidocs/wicket/extensions/model/AbstractCheckBoxModel.html"
  target="_blank"&gt;AbstractCheckBoxModel&lt;/a&gt; pour transformer mon enum en boolean.
&lt;/p&gt;

&lt;pre class="brush:java"&gt;
public class EnumCheckBoxModel extends AbstractCheckBoxModel {

  private static final long serialVersionUID = 1L;

  private final IModel model;
  private final LabeledEnum enumValue;

  public EnumCheckBoxModel(IModel model, LabeledEnum enumValue) {
    this.model = model;
    this.enumValue = enumValue;
  }

  @Override
  public boolean isSelected() {
    return model.getObject() == enumValue;
  }

  @Override
  public void select() {
    model.setObject(enumValue);
  }

  @Override
  public void unselect() {
    model.setObject(null);
  }

}
&lt;/pre&gt;

&lt;p&gt;
 Et voici enfin le code de mon composant :
&lt;/p&gt;

&lt;pre class="brush:java"&gt;
public class EnumCheckBoxes&amp;lt;TEnum extends Enum&amp;lt;?&amp;gt; &amp;amp; LabeledEnum&amp;gt; extends Panel {

  private static final long serialVersionUID = 1L;

  TEnum[] enumList;
  IModel checkBoxModel;

  public EnumCheckBoxes(String id, IModel checkBoxModel, Class&amp;lt;TEnum&amp;gt; enumClass) {
    this(id, checkBoxModel, enumClass.getEnumConstants());
  }

  public EnumCheckBoxes(String id, IModel checkBoxModel, TEnum... enumList) {
    super(id);
    this.checkBoxModel = checkBoxModel;
    this.enumList = enumList;
    createComponent();
  }

  private void createComponent() {

    // div that will be refreshed via ajax when user select a checkbox
    final WebMarkupContainer listViewContainer = new WebMarkupContainer("listContainer");
    listViewContainer.setOutputMarkupId(true);

    final ListView listView = new ListView("list", new Model((Serializable) Arrays.asList(enumList))) {
      private static final long serialVersionUID = 1L;

      @Override
      protected void populateItem(ListItem item) {
        TEnum labeledEnum = (TEnum) item.getModelObject();

        CheckBox checkBox = new CheckBox("input", new EnumCheckBoxModel(checkBoxModel, labeledEnum));
        checkBox.setLabel(new ResourceModel(labeledEnum.getLabel()));

        // don't use OnChangeAjaxBehavior because of IE event propagation for checkbox onchange
        checkBox.add(new AjaxFormComponentUpdatingBehavior("onclick") {
          private static final long serialVersionUID = 1L;

          @Override
          protected void onUpdate(AjaxRequestTarget target) {
            target.addComponent(listViewContainer);
          }
        });
        item.add(checkBox);
        item.add(new SimpleFormComponentLabel("label", checkBox));
      }

    };
    listViewContainer.add(listView);
    add(listViewContainer);
  }

}
&lt;/pre&gt;

&lt;pre class="brush:html"&gt;
&amp;lt;html xmlns:wicket&amp;gt;
  &amp;lt;wicket:panel&amp;gt;

    &amp;lt;div wicket:id="listContainer"&amp;gt;
      &amp;lt;div wicket:id="list"&amp;gt;
        &amp;lt;div class="checkboxWithLabel"&amp;gt;
          &amp;lt;input type="checkbox" wicket:id="input" /&amp;gt;
          &amp;lt;label wicket:id="label"&amp;gt; &amp;lt;/label&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;

  &amp;lt;/wicket:panel&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6538999683570325297-5312436530281091478?l=surunairdejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://surunairdejava.blogspot.com/feeds/5312436530281091478/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6538999683570325297&amp;postID=5312436530281091478' title='2 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default/5312436530281091478'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default/5312436530281091478'/><link rel='alternate' type='text/html' href='http://surunairdejava.blogspot.com/2008/09/wicket-checkbox-abstractcheckboxmodel.html' title='Wicket: Checkbox, AbstractCheckBoxModel  et enum'/><author><name>Cédric Thiébault</name><uri>http://www.blogger.com/profile/01915436356438533195</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6538999683570325297.post-5934520594913477453</id><published>2008-09-11T14:11:00.002-04:00</published><updated>2010-04-20T09:37:54.746-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wicket'/><category scheme='http://www.blogger.com/atom/ns#' term='maven'/><title type='text'>Wicket &amp; Maven packaging (fichiers html, css, js...)</title><content type='html'>&lt;p&gt;Si vous utilisez Maven pour packager votre appplication Wicket, n'oubliez pas de modifier le POM.xml pour inclure
les fichiers html, css, js, etc. dans votre war (ou jar). &lt;br /&gt;
A moins que vous placiez tous ces fichiers non-java sous &lt;span style="font-style: italic;"&gt;src/main/resources&lt;/span&gt; au
lieu de &lt;span style="font-style: italic;"&gt;src/main/java&lt;/span&gt; (ça fait quand même bizarre de voir tous ces fichiers
non-java à coté des classes).&lt;/p&gt;

&lt;pre class="brush:xml"&gt;
&amp;lt;build&amp;gt;
 &amp;lt;resources&amp;gt;
  &amp;lt;resource&amp;gt;
   &amp;lt;directory&amp;gt;src/main/java&amp;lt;/directory&amp;gt;
   &amp;lt;includes&amp;gt;
    &amp;lt;include&amp;gt;**/*&amp;lt;/include&amp;gt;
   &amp;lt;/includes&amp;gt;
   &amp;lt;excludes&amp;gt;
    &amp;lt;exclude&amp;gt;**/*.java&amp;lt;/exclude&amp;gt;
   &amp;lt;/excludes&amp;gt;
  &amp;lt;/resource&amp;gt;
 &amp;lt;/resources&amp;gt;
&amp;lt;/build&amp;gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6538999683570325297-5934520594913477453?l=surunairdejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://surunairdejava.blogspot.com/feeds/5934520594913477453/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6538999683570325297&amp;postID=5934520594913477453' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default/5934520594913477453'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default/5934520594913477453'/><link rel='alternate' type='text/html' href='http://surunairdejava.blogspot.com/2008/09/wicket-maven-packaging-fichiers-html.html' title='Wicket &amp; Maven packaging (fichiers html, css, js...)'/><author><name>Cédric Thiébault</name><uri>http://www.blogger.com/profile/01915436356438533195</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6538999683570325297.post-8622402707905842707</id><published>2008-08-27T09:49:00.014-04:00</published><updated>2010-04-20T09:40:36.016-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wicket'/><category scheme='http://www.blogger.com/atom/ns#' term='spring'/><title type='text'>Wicket &amp; Spring</title><content type='html'>&lt;p&gt;Depuis le temps que j'entends parler de Wicket, je me lance enfin dans l'aventure :-) &lt;br /&gt;
J'essayerais ici de décrire les différentes étapes de la migration d'une application &lt;a
 href="http://springframework.org/"&gt;Spring MVC 2.5&lt;/a&gt; / &lt;a href="http://springframework.org/webflow"&gt;Weblow 2.0&lt;/a&gt; / &lt;a
 href="http://www.hibernate.org/"&gt;Hibernate&lt;/a&gt; vers &lt;a href="http://wicket.apache.org/"&gt;Wicket 1.3.4&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Pour démarrer, je suis parti des articles du &lt;a href="http://blog.xebia.fr"&gt;blog Xebia France&lt;/a&gt; qui sont
vraiment bien fait... Merci à eux!&lt;/p&gt;

&lt;ul style="margin-top: -5px;"&gt;
 &lt;li&gt;&lt;a href="http://blog.xebia.fr/2008/02/14/hands-on-wicket-partie-1/"&gt;Hands on Wicket 1 : Quickstart &amp;
 config&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://blog.xebia.fr/2008/02/22/hands-on-wicket-partie-2//"&gt;Hands on Wicket 2 : Page, model &amp;
 navigation&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://blog.xebia.fr/2008/03/07/hands-on-wicket-partie-3/"&gt;Hands on Wicket 3 : Session,
 formulaire &amp; Spring&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://blog.xebia.fr/2008/04/23/hands-on-wicket-partie-4/"&gt;Hands on Wicket 4 : Templating &amp;
 internationalisation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Premier problème : Spring!&lt;/h4&gt;
&lt;p&gt;Après avoir ajouté mes dépendances dans le POM.xml, Spring en peut loader les contextes :&lt;/p&gt;

&lt;pre class="brush:java"&gt;
ERROR org.springframework.web.context.ContextLoader.initWebApplicationContext:205 - Context initialization failed
org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from class path resource [applicationContext-service.xml]; nested exception is java.lang.NoSuchMethodError: org.springframework.util.ClassUtils.isPresent(Ljava/lang/String;Ljava/lang/ClassLoader;)Z
Caused by: 
java.lang.NoSuchMethodError: org.springframework.util.ClassUtils.isPresent(Ljava/lang/String;Ljava/lang/ClassLoader;)Z
 at org.springframework.context.annotation.AnnotationConfigUtils.&amp;lt;clinit&amp;gt;(AnnotationConfigUtils.java:75)
 at org.springframework.context.annotation.AnnotationConfigBeanDefinitionParser.parse(AnnotationConfigBeanDefinitionParser.java:45)
&lt;/pre&gt;

&lt;p&gt;La librairie &lt;b&gt;wicket-spring&lt;/b&gt; dépend de spring 2.0 et non de la dernière version 2.5.x. &lt;br /&gt;
Il faut donc juste exclure le Spring de Wicket comme suit dans le pom.xml du projet :&lt;/p&gt;

&lt;pre class="brush:xml"&gt;
&amp;lt;dependency&amp;gt;
 &amp;lt;groupId&amp;gt;org.apache.wicket&amp;lt;/groupId&amp;gt;
 &amp;lt;artifactId&amp;gt;wicket-spring&amp;lt;/artifactId&amp;gt;
 &amp;lt;version&amp;gt;${wicket.version}&amp;lt;/version&amp;gt;
 &amp;lt;exclusions&amp;gt;
  &amp;lt;exclusion&amp;gt;
   &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
   &amp;lt;artifactId&amp;gt;spring&amp;lt;/artifactId&amp;gt;
  &amp;lt;/exclusion&amp;gt;
 &amp;lt;/exclusions&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/pre&gt;

&lt;h4&gt;Internationalisation&lt;/h4&gt;

&lt;p&gt;Tous mes traductions sont dans un seul fichier properties et je ne veux pas les séparer par page ou déplacer et
renommer ce fichier à la racine de l'application Wicket.&lt;/p&gt;

&lt;p&gt;En cherchant un peu, je suis tombé sur ce blog : &lt;br /&gt;
&lt;a href="http://www.jroller.com/eyallupu/entry/spring_as_a_message_provider"&gt;http://www.jroller.com/eyallupu/entry/spring_as_a_message_provider&lt;/a&gt;
&lt;br /&gt;
Il propose ici d'utiliser le MessageSource de Spring directement dans Wicket. &lt;br /&gt;
Ça marche parfaitement bien :-)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6538999683570325297-8622402707905842707?l=surunairdejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://surunairdejava.blogspot.com/feeds/8622402707905842707/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6538999683570325297&amp;postID=8622402707905842707' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default/8622402707905842707'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default/8622402707905842707'/><link rel='alternate' type='text/html' href='http://surunairdejava.blogspot.com/2008/08/wicket-spring.html' title='Wicket &amp; Spring'/><author><name>Cédric Thiébault</name><uri>http://www.blogger.com/profile/01915436356438533195</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6538999683570325297.post-142281757603238964</id><published>2007-11-27T11:30:00.001-04:00</published><updated>2010-04-20T09:49:41.998-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='maven'/><title type='text'>Intégration native de Maven à Eclipse</title><content type='html'>&lt;p&gt;
  Enfin un support natif de Maven dans Eclipse!
  &lt;br /&gt;
  &lt;a href="http://www.eclipse.org/proposals/iam"&gt;The Eclipse Integration for Apache Maven&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
  Mais a priori il va falloir s'armer de patience : première release en septembre 2008.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6538999683570325297-142281757603238964?l=surunairdejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://surunairdejava.blogspot.com/feeds/142281757603238964/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6538999683570325297&amp;postID=142281757603238964' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default/142281757603238964'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default/142281757603238964'/><link rel='alternate' type='text/html' href='http://surunairdejava.blogspot.com/2007/11/intgration-de-maven-eclipse.html' title='Intégration native de Maven à Eclipse'/><author><name>Cédric Thiébault</name><uri>http://www.blogger.com/profile/01915436356438533195</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6538999683570325297.post-3806173322017726367</id><published>2007-06-22T10:51:00.001-04:00</published><updated>2010-04-20T09:51:19.154-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='hibernate'/><title type='text'>Hibernate Annotations - @CollectionOfElements</title><content type='html'>&lt;p&gt;
 Depuis la version 3.1 de Hibernate Annotations (il me semble), on peut enfin avoir une collection de types primitifs 
 (&lt;code&gt;String&lt;/code&gt; par exemple) gr&amp;acirc;ce &amp;agrave; &lt;code&gt;@CollectionOfElements&lt;/code&gt;.
 &lt;br /&gt;
 Avant &amp;ccedil;a, on &amp;eacute;tait un peu bloqu&amp;eacute; avec des affaires comme un champ texte qui contient la liste s&amp;eacute;par&amp;eacute;e par des virgules
 (ou un autre caract&amp;egrave;re), ou alors une entit&amp;eacute; g&amp;eacute;r&amp;eacute;e par Hibernate qui ne contient qu'une ID et la primitive &amp;agrave; stocker
 :-(
 &lt;br /&gt;
 &lt;br /&gt;
 Attention cependant, l'annotation &lt;code&gt;@org.hibernate.annotations.CollectionOfElements&lt;/code&gt;
 est sp&amp;eacute;cifique &amp;agrave; Hibernate. Elle ne fait pas partie des sp&amp;eacute;cifications JPA...
&lt;/p&gt;

&lt;pre class="brush:java"&gt;
@Entity
public class User {
  @CollectionOfElements
  private Set&amp;lt;String&amp;gt; nicknames;
}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6538999683570325297-3806173322017726367?l=surunairdejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://surunairdejava.blogspot.com/feeds/3806173322017726367/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6538999683570325297&amp;postID=3806173322017726367' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default/3806173322017726367'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default/3806173322017726367'/><link rel='alternate' type='text/html' href='http://surunairdejava.blogspot.com/2007/06/hibernate-annotations.html' title='Hibernate Annotations - @CollectionOfElements'/><author><name>Cédric Thiébault</name><uri>http://www.blogger.com/profile/01915436356438533195</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6538999683570325297.post-439734378533789891</id><published>2007-06-06T10:50:00.001-04:00</published><updated>2010-04-20T09:53:30.689-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><title type='text'>Inversion de contrôle et injection de dépendances</title><content type='html'>&lt;p&gt;
 Excellent article sur la différence entre l'inversion de contrôle et l'injection de dépendances. La confusion est
 souvent faites entre les deux: on pense, à tort, que c'est la même chose...
 &lt;br /&gt;
 &lt;a href="http://colmsmyth.blogspot.com/2007/06/little-clarity-inversion-of-control-and.html#links"&gt;S'mythology - A
  Little Clarity - Inversion of Control and Dependency Injection&lt;/a&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6538999683570325297-439734378533789891?l=surunairdejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://surunairdejava.blogspot.com/feeds/439734378533789891/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6538999683570325297&amp;postID=439734378533789891' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default/439734378533789891'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default/439734378533789891'/><link rel='alternate' type='text/html' href='http://surunairdejava.blogspot.com/2007/06/inversion-de-contrle-et-injection-de.html' title='Inversion de contrôle et injection de dépendances'/><author><name>Cédric Thiébault</name><uri>http://www.blogger.com/profile/01915436356438533195</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6538999683570325297.post-7959208138578722728</id><published>2007-06-05T10:16:00.002-04:00</published><updated>2010-04-20T09:54:38.037-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='hibernate'/><category scheme='http://www.blogger.com/atom/ns#' term='maven'/><title type='text'>NoClassDefFoundError: ReflectionManager</title><content type='html'>&lt;code&gt; NoClassDefFoundError: org/hibernate/annotations/common/reflection/ReflectionManager &lt;/code&gt;
&lt;br /&gt;
&lt;p&gt;En mettant à jour Hibernate Annotations à la dernière version (3.3.0.ga) via Maven2 (qui semble enfin avoir les
dernières versions de Hibernate), j'avais cette exception : &lt;br /&gt;
&lt;b&gt;NoClassDefFoundError: org/hibernate/annotations/common/reflection/ReflectionManager&lt;/b&gt; &lt;br /&gt;
&lt;br /&gt;

C'est que le POM de Hibernate Annotations est incomplet.... Il manque la dépendance à &lt;b&gt;hibernate-commons-annotations&lt;/b&gt;.
&lt;br /&gt;
Donc en attendant que le POM de Hibernate Annotations soit corrigé ( &lt;a
 href="http://jira.codehaus.org/browse/MAVENUPLOAD-1532"&gt;http://jira.codehaus.org/browse/MAVENUPLOAD-1532&lt;/a&gt;), ajoutez
dans le POM de votre projet la dépendance à hibernate-commons-annotations 3.3.0.ga.&lt;/p&gt;

&lt;pre class="brush:xml"&gt;
&amp;lt;dependency&amp;gt;
  &amp;lt;groupId&amp;gt;org.hibernate&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;hibernate-commons-annotations&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;3.3.0.ga&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6538999683570325297-7959208138578722728?l=surunairdejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://surunairdejava.blogspot.com/feeds/7959208138578722728/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6538999683570325297&amp;postID=7959208138578722728' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default/7959208138578722728'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default/7959208138578722728'/><link rel='alternate' type='text/html' href='http://surunairdejava.blogspot.com/2007/06/noclassdeffounderror-reflectionmanager.html' title='NoClassDefFoundError: ReflectionManager'/><author><name>Cédric Thiébault</name><uri>http://www.blogger.com/profile/01915436356438533195</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6538999683570325297.post-7395583550524936979</id><published>2007-06-01T13:05:00.001-04:00</published><updated>2010-04-20T09:57:02.226-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='spring'/><title type='text'>Convention over configuration - Spring MVC</title><content type='html'>&lt;p&gt;
 &lt;i&gt;Convention plut&amp;ocirc;t que configuration&lt;/i&gt; en bon fran&amp;ccedil;ais : il est inutile de pr&amp;eacute;ciser des
 d&amp;eacute;tails lorsqu'ils respectent des conventions &amp;eacute;tablies (
 &lt;a href="http://fr.wikipedia.org/wiki/Ruby_on_Rails"&gt;Wikipedia&lt;/a&gt;). On en entend de plus en plus parler avec la
 popularit&amp;eacute; grandissante de Ruby On Rails.
 &lt;br /&gt;
 Le but de ce post est de r&amp;eacute;duire un peu la taille des fichiers de configuration de Spring qui peuvent vite
 devenir tr&amp;eacute;s gros...
&lt;/p&gt;

&lt;h4&gt;
 Autowire des controlleurs
&lt;/h4&gt;
&lt;p&gt;
 Pour commencer on peut utiliser le
 &lt;a href="http://static.springframework.org/spring/docs/2.0.x/reference/beans.html#beans-factory-autowire"&gt;autowiring&lt;/a&gt;
 lors de la d&amp;eacute;finition de nos beans. Spring va effectuer les r&amp;eacute;solutions automatiquement soit par type,
 soit par nom.
 &lt;br /&gt;
 Dans l'exemple suivant, je d&amp;eacute;finis le autowire par defaut pour tout le contexte :
&lt;/p&gt;

&lt;p&gt;
-- default-servlet.xml --
&lt;/p&gt;

&lt;pre class="brush:xml"&gt;
&amp;lt;beans xmlns="http://www.springframework.org/schema/beans" default-autowire="byName"&amp;gt;
  &amp;lt;bean id="userController" class="x.y.z.userController" autowire="default" /&amp;gt;
&amp;lt;/beans&amp;gt;
&lt;/pre&gt;

&lt;p&gt;
 L'utilisation du autowire n'est pas recommand&amp;eacute;e par les d&amp;eacute;veloppeurs de Spring pour les projets de grande
 taille mais je pense vraiment qu'au niveau du MVC ca ne pose pas de probl&amp;egrave;mes.
&lt;/p&gt;

&lt;h4&gt;
 Mapping des controlleurs
&lt;/h4&gt;
&lt;p&gt;
 La plupart du temps les URLs ressemblent aux noms des controlleurs... En utilisant le
 &lt;code&gt;
  ControllerClassNameHandlerMapping
 &lt;/code&gt;
 Spring va chercher dans la liste des controlleurs enregistr&amp;eacute;s ceux dont le nom (moins le suffixe Controller)
 match l'url. Par exemple :
&lt;/p&gt;
&lt;pre&gt;- WelcomeController &amp;lt;--&amp;gt; '/welcome*'
- DisplayShoppingCartController &amp;lt;--&amp;gt; '/displayshoppingcart*'&lt;/pre&gt;

&lt;p&gt;
 Dans le cas de
 &lt;code&gt;
  MultiActionController
 &lt;/code&gt;
 , le mapping se fera comme suit :
&lt;/p&gt;
&lt;pre&gt;- UserController &amp;lt;--&amp;gt; '/user/*'
- UserController.edit(...) &amp;lt;--&amp;gt; '/user/edit.htm'&lt;/pre&gt;

&lt;h4&gt;
 Mapping des vues (jsp ou autres)
&lt;/h4&gt;
&lt;p&gt;
 Pour les parties plus statique des sites, il est idiot de cr&amp;eacute;er un controlleur par page... La classe
 &lt;code&gt;
  UrlFilenameViewController
 &lt;/code&gt;
 transforme une URL en chemin sur le disque pointant vers la vue correspondante :
&lt;/p&gt;

&lt;pre&gt;/users/list.htm --&amp;gt; /users/list&lt;/pre&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;
 Si on met tout ca ensemble dans la configuration du servlet de Spring, on obtient :
&lt;/p&gt;

&lt;p&gt;-- default-servlet.xml --&lt;/p&gt;
&lt;pre class="brush:xml"&gt;
&amp;lt;beans xmlns="http://www.springframework.org/schema/beans" default-autowire="byName"&amp;gt;

  &amp;lt;bean id="userController" class="x.y.z.userController" autowire="default" /&amp;gt;

  &amp;lt;!-- jsp view resolver that points to /jsp folder --&amp;gt;
  &amp;lt;bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"&amp;gt;
    &amp;lt;property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /&amp;gt;
    &amp;lt;property name="prefix" value="/jsp/" /&amp;gt;
    &amp;lt;property name="suffix" value=".jsp" /&amp;gt;
  &amp;lt;/bean&amp;gt;

  &amp;lt;bean id="fileNameViewController" class="org.springframework.web.servlet.mvc.UrlFilenameViewController" /&amp;gt;

  &amp;lt;!-- maps request URLs to Controller names --&amp;gt;
  &amp;lt;bean id="urlMappingWithControllers" class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" /&amp;gt;

  &amp;lt;bean id="urlMappingNoControllers" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"&amp;gt;
    &amp;lt;property name="mappings"&amp;gt;
      &amp;lt;props&amp;gt;
        &amp;lt;prop key="*"&amp;gt;fileNameViewController&amp;lt;/prop&amp;gt;
      &amp;lt;/props&amp;gt;
    &amp;lt;/property&amp;gt;
  &amp;lt;/bean&amp;gt;

&amp;lt;/beans&amp;gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6538999683570325297-7395583550524936979?l=surunairdejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://surunairdejava.blogspot.com/feeds/7395583550524936979/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6538999683570325297&amp;postID=7395583550524936979' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default/7395583550524936979'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default/7395583550524936979'/><link rel='alternate' type='text/html' href='http://surunairdejava.blogspot.com/2007/06/convention-over-configuration-spring.html' title='Convention over configuration - Spring MVC'/><author><name>Cédric Thiébault</name><uri>http://www.blogger.com/profile/01915436356438533195</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6538999683570325297.post-5782498073054119955</id><published>2007-05-30T11:12:00.001-04:00</published><updated>2010-04-20T09:57:52.504-04:00</updated><title type='text'>En java et en musique :)</title><content type='html'>&lt;p&gt;
 Quelques petits liens pour coder Java sur un air de Java ;-)
&lt;br /&gt;
 &lt;a href="http://www.radioblogclub.com/open/138797/JAVA%20-%20Sexe%20accordeon%20et%20alcool"&gt;Java - Sexe,
  accord&amp;eacute;on et alcool&lt;/a&gt;
 &lt;br /&gt;
 &lt;a href="http://www.radioblogclub.com/open/136944/La%20Java%20Martienne"&gt;Boris Vian - La Java Martienne&lt;/a&gt;
 &lt;br /&gt;
 &lt;a href="http://www.radioblogclub.com/open/132692/%28fr%29%20Boris%20Vian%20-%20La%20java%20des%20bombes%20atomiques"&gt;Boris
  Vian - La Java des bombes atomiques&lt;/a&gt;
 &lt;br /&gt;
 &lt;a href="http://www.radioblogclub.com/open/62271/frehel%20la%20java%20bleue%20"&gt;La Java bleue&lt;/a&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6538999683570325297-5782498073054119955?l=surunairdejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://surunairdejava.blogspot.com/feeds/5782498073054119955/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6538999683570325297&amp;postID=5782498073054119955' title='1 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default/5782498073054119955'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default/5782498073054119955'/><link rel='alternate' type='text/html' href='http://surunairdejava.blogspot.com/2007/05/en-java-et-en-musique.html' title='En java et en musique :)'/><author><name>Cédric Thiébault</name><uri>http://www.blogger.com/profile/01915436356438533195</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6538999683570325297.post-218059650836495965</id><published>2007-05-23T12:43:00.002-04:00</published><updated>2010-04-20T10:00:18.161-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='maven'/><title type='text'>Maven2 et MyEclipse</title><content type='html'>&lt;p&gt;
 &lt;a href="http://www.myeclipseide.com"&gt;MyEclipse&lt;/a&gt; ne supporte pas officiellement Maven2 mais en utilisant le plugin
 &lt;a href="http://m2eclipse.codehaus.org"&gt;m2eclipse&lt;/a&gt; on peut s'en sortir assez facilement....
 &lt;br /&gt;
 &lt;br /&gt;
 Selon le standard d&amp;eacute;finit par Maven les classes devraient &amp;ecirc;tre compil&amp;eacute;es dans le r&amp;eacute;pertoire
 &lt;i&gt;target&lt;/i&gt;, mais si l'on veut utiliser MyEclipse pour d&amp;eacute;ployer l'application (Hot deployment) il faut que
 nous compilions les classes vers
 &lt;i&gt;src/main/webapp/WEB-INF/classes&lt;/i&gt;.
 &lt;br /&gt;
 L'id&amp;eacute;al serait que MyEclipse supporte le d&amp;eacute;ploiement des classes compil&amp;eacute;es dans diff&amp;eacute;rents
 r&amp;eacute;pertoires vers le serveur comme &amp;ccedil;a nous pourrions suivre le standard Maven et compiler vers
 &lt;i&gt;target&lt;/i&gt; mais ce n'est pas encore le cas...
 &lt;br /&gt;
 &lt;br /&gt;
 Attention : lorsque l'on d&amp;eacute;ploit avec MyEclipse, on perd la fonctionnalit&amp;eacute; des
 &lt;a href="http://maven.apache.org/guides/getting-started/index.html#How%20do%20I%20filter%20resource%20files?"&gt;filtres&lt;/a&gt;
 de Maven :-(
 &lt;br /&gt;
 &lt;br /&gt;
 Dans les propri&amp;eacute;t&amp;eacute;s du projet web, d&amp;eacute;finir le
 &lt;b&gt;webrootdir&lt;/b&gt; &amp;agrave;
 &lt;i&gt;src/main/webapp&lt;/i&gt; et configurer le fichier
 &lt;b&gt;.classpath&lt;/b&gt; comme suit :
&lt;/p&gt;
&lt;pre class="brush:xml"&gt;
&amp;lt;classpath&amp;gt;
  &amp;lt;classpathentry kind="src" path="src/main/java" output="src/main/webapp/WEB-INF/classes" /&amp;gt;
  &amp;lt;classpathentry kind="src" path="src/main/resources" output="src/main/webapp/WEB-INF/classes" /&amp;gt;
  &amp;lt;classpathentry kind="src" path="src/test/java" output="target/test-classes" /&amp;gt;
  &amp;lt;classpathentry kind="src" path="src/test/resources" output="target/test-classes" /&amp;gt;
  &amp;lt;classpathentry kind="output" path="src/main/webapp/WEB-INF/classes" /&amp;gt;
  &amp;lt;classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER" /&amp;gt;
  &amp;lt;classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER" /&amp;gt;
&amp;lt;/classpath&amp;gt; 
&lt;/pre&gt;

&lt;p&gt;
 Le plus gros probl&amp;egrave;me dans tout &amp;ccedil;a, c'est que MyEclipse d&amp;eacute;ploit tous les jars d&amp;eacute;finis dans
 le POM... m&amp;ecirc;me ceux qui ne servent qu'&amp;agrave; la compilation (scope=provided). Par exemple les fichiers
 servlet-api.jar et jsp-api.jar seront copi&amp;eacute;s dans
 &lt;i&gt;WEB-INF/lib&lt;/i&gt; et cela peut cr&amp;eacute;er des probl&amp;egrave;mes au d&amp;eacute;marrage du serveur web.
 &lt;br /&gt;
 En attendant le support officiel de Maven2 par MyEclipse, il nous reste &amp;agrave; effacer ces fichiers manuellement ou
 &amp;agrave; ne pas les inclure dans le POM :(
 &lt;br /&gt;
 &lt;br /&gt;
 La communaut&amp;eacute; des utilisateurs de MyEclipse pousse de plus en plus fort pour le support officiel de Maven2 et certains
 proposent d&amp;eacute;j&amp;agrave; des solutions qui ne semblent pas demander une tonne de code pour exploiter le plugin m2eclipse
 (l&amp;eacute;g&amp;egrave;rement adapt&amp;eacute;) et d&amp;eacute;ployer seulement les jar d&amp;eacute;finis pour le runtime.... Patience donc!
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6538999683570325297-218059650836495965?l=surunairdejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://surunairdejava.blogspot.com/feeds/218059650836495965/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6538999683570325297&amp;postID=218059650836495965' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default/218059650836495965'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default/218059650836495965'/><link rel='alternate' type='text/html' href='http://surunairdejava.blogspot.com/2007/06/maven2-et-myeclipse.html' title='Maven2 et MyEclipse'/><author><name>Cédric Thiébault</name><uri>http://www.blogger.com/profile/01915436356438533195</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6538999683570325297.post-4562241806010569088</id><published>2007-05-22T09:43:00.001-04:00</published><updated>2010-04-20T10:01:11.244-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><title type='text'>Mac vs PC.... Java vs Ruby</title><content type='html'>&lt;p&gt;
 Dans le style des publicités
 &lt;b&gt;Mac vs PC&lt;/b&gt;, voici
 &lt;b&gt;Java vs Ruby&lt;/b&gt; vu par des adeptes de Ruby on rails... Evidemment :)
&lt;/p&gt;

&lt;object width="425" height="350"&gt;
 &lt;param name="movie" value="http://www.youtube.com/v/PQbuyKUaKFo"&gt;&lt;/param&gt;
 &lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;
 &lt;embed src="http://www.youtube.com/v/PQbuyKUaKFo" type="application/x-shockwave-flash" wmode="transparent" width="425"
  height="350"&gt;&lt;/embed&gt;
&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6538999683570325297-4562241806010569088?l=surunairdejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://surunairdejava.blogspot.com/feeds/4562241806010569088/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6538999683570325297&amp;postID=4562241806010569088' title='1 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default/4562241806010569088'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default/4562241806010569088'/><link rel='alternate' type='text/html' href='http://surunairdejava.blogspot.com/2007/05/mac-vs-pc-java-vs-ruby.html' title='Mac vs PC.... Java vs Ruby'/><author><name>Cédric Thiébault</name><uri>http://www.blogger.com/profile/01915436356438533195</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6538999683570325297.post-1513548807653594459</id><published>2007-05-16T15:24:00.002-04:00</published><updated>2010-04-20T10:02:36.421-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='maven'/><title type='text'>Version des dépendances avec Maven2</title><content type='html'>&lt;p&gt;
 Voici quelques petits trucs pratique pour all&amp;eacute;ger les POM de Maven2 dans les projets multi-modules...
&lt;/p&gt;
&lt;p&gt;
 Classiquement chaque POM d&amp;eacute;fini ses d&amp;eacute;pendances comme suit :
&lt;/p&gt;
&lt;p&gt;-- pom.xml --&lt;/p&gt;
&lt;pre class="brush:xml"&gt;
&amp;lt;project&amp;gt;
  &amp;lt;dependencies&amp;gt;
    &amp;lt;dependency&amp;gt;
      &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
      &amp;lt;artifactId&amp;gt;spring-webmvc&amp;lt;/artifactId&amp;gt;
      &amp;lt;version&amp;gt;2.0.5&amp;lt;/version&amp;gt;
      &amp;lt;exclusions&amp;gt;
        &amp;lt;exclusion&amp;gt;
          &amp;lt;groupId&amp;gt;struts&amp;lt;/groupId&amp;gt;
          &amp;lt;artifactId&amp;gt;struts&amp;lt;/artifactId&amp;gt;
        &amp;lt;/exclusion&amp;gt;
      &amp;lt;/exclusions&amp;gt;
    &amp;lt;/dependency&amp;gt;
  &amp;lt;/dependencies&amp;gt;
&amp;lt;/project&amp;gt;
&lt;/pre&gt;
&lt;p&gt;
 Si plusieurs modules utilisent Spring MVC, on ne veut pas dupliquer ce code dans chaque POM... On d&amp;eacute;finit la
 configuration de la d&amp;eacute;pendance dans le POM parent et on inclus seulement la d&amp;eacute;pendance dans les modules
 sans sp&amp;eacute;cifier la version ni les exclusions.
&lt;/p&gt;
&lt;p&gt;-- pom.xml parent --&lt;/p&gt; 
&lt;pre class="brush:xml"&gt;
&amp;lt;project&amp;gt;
  &amp;lt;groupId&amp;gt;demo&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;parent&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;1.0-SNAPSHOT&amp;lt;/version&amp;gt;
  &amp;lt;modules&amp;gt;
    &amp;lt;module&amp;gt;child&amp;lt;/module&amp;gt;
  &amp;lt;/modules&amp;gt;
  &amp;lt;dependencyManagement&amp;gt;
    &amp;lt;dependencies&amp;gt;
      &amp;lt;dependency&amp;gt;
        &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;spring-webmvc&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;2.0.5&amp;lt;/version&amp;gt;
        &amp;lt;exclusions&amp;gt;
          &amp;lt;exclusion&amp;gt;
            &amp;lt;groupId&amp;gt;struts&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;struts&amp;lt;/artifactId&amp;gt;
          &amp;lt;/exclusion&amp;gt;
        &amp;lt;/exclusions&amp;gt;
      &amp;lt;/dependency&amp;gt;
    &amp;lt;/dependencies&amp;gt;
  &amp;lt;/dependencyManagement&amp;gt;
&amp;lt;/project&amp;gt;
&lt;/pre&gt;

&lt;p&gt;-- pom.xml child --&lt;/p&gt;
&lt;pre class="brush:xml"&gt; 
&amp;lt;project&amp;gt;
  &amp;lt;artifactId&amp;gt;child&amp;lt;/artifactId&amp;gt;
  &amp;lt;parent&amp;gt;
    &amp;lt;groupId&amp;gt;demo&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;child&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;1.0-SNAPSHOT&amp;lt;/version&amp;gt;
  &amp;lt;/parent&amp;gt;  
  &amp;lt;dependencies&amp;gt;
    &amp;lt;dependency&amp;gt;
      &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
      &amp;lt;artifactId&amp;gt;spring-webmvc&amp;lt;/artifactId&amp;gt;
    &amp;lt;/dependency&amp;gt;
  &amp;lt;/dependencies&amp;gt;
&amp;lt;/project&amp;gt;
&lt;/pre&gt;
&lt;p&gt;
 Dernier petit truc pour simplifer la gestion des version des d&amp;eacute;pendances : au lieu de hardcoder la version de la
 d&amp;eacute;pendance dans sa d&amp;eacute;finition, on peut utiliser des 'properties'. Par exemple pour Spring o&amp;ugrave; l'on
 d&amp;eacute;pend de plusieurs jars, on peut facilement upgrader en modifiant seulement la propri&amp;eacute;t&amp;eacute;
 'spring.version'.
&lt;/p&gt;
&lt;p&gt;-- pom.xml --&lt;/p&gt;
&lt;pre class="brush:xml"&gt;
&amp;lt;project&amp;gt;
  &amp;lt;dependencyManagement&amp;gt;
    &amp;lt;dependencies&amp;gt;
      &amp;lt;dependency&amp;gt;
        &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;spring-core&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;${spring.version}&amp;lt;/version&amp;gt;
      &amp;lt;/dependency&amp;gt;
      &amp;lt;dependency&amp;gt;
        &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;spring-dao&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;${spring.version}&amp;lt;/version&amp;gt;
      &amp;lt;/dependency&amp;gt;
      &amp;lt;dependency&amp;gt;
        &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;spring-hibernate3&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;${spring.version}&amp;lt;/version&amp;gt;
      &amp;lt;/dependency&amp;gt;
    &amp;lt;/dependencies&amp;gt;
  &amp;lt;/dependencyManagement&amp;gt;
  &amp;lt;properties&amp;gt;
    &amp;lt;spring.version&amp;gt;2.0.4&amp;lt;/spring.version&amp;gt;
  &amp;lt;/properties&amp;gt;
&amp;lt;/project&amp;gt;
&lt;/pre&gt;
&lt;p&gt;
 Au passage, le site
 &lt;a href="http://www.mvnrepository.com"&gt;mvnrepository.com&lt;/a&gt; est un bon outils pour trouver les jars publi&amp;eacute;s
 dans Maven2 et surtout pour trouver lesquels ont &amp;eacute;t&amp;eacute; d&amp;eacute;plac&amp;eacute;...
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6538999683570325297-1513548807653594459?l=surunairdejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://surunairdejava.blogspot.com/feeds/1513548807653594459/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6538999683570325297&amp;postID=1513548807653594459' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default/1513548807653594459'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default/1513548807653594459'/><link rel='alternate' type='text/html' href='http://surunairdejava.blogspot.com/2007/05/version-des-dpendances-avec-maven2.html' title='Version des dépendances avec Maven2'/><author><name>Cédric Thiébault</name><uri>http://www.blogger.com/profile/01915436356438533195</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6538999683570325297.post-7434285575984762862</id><published>2007-05-14T10:02:00.003-04:00</published><updated>2010-05-03T14:31:26.703-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><title type='text'>UTF-8 encoding</title><content type='html'>&lt;p&gt;Apr&amp;egrave;s plusieurs heures pass&amp;eacute;es &amp;agrave; trouver mon erreur d'encodage UTF-8, voici un petite liste
des points &amp;agrave; v&amp;eacute;rifier sur une application web.&lt;/p&gt;
&lt;p&gt;Mon environnement :&lt;/p&gt;
&lt;ul style="margin-top: -5px;"&gt;
 &lt;li&gt;MySQL&lt;/li&gt;
 &lt;li&gt;Hibernate&lt;/li&gt;
 &lt;li&gt;Spring MVC&lt;/li&gt;
 &lt;li&gt;Velocity (pour les mails)&lt;/li&gt;
 &lt;li&gt;Tomcat&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;MySQL&lt;/h4&gt;
&lt;p&gt;V&amp;eacute;rifier que les tables et les champs textes utilisent le charset UTF-8 :&lt;/p&gt;
&lt;pre class="brush:sql"&gt;CREATE TABLE [...] DEFAULT CHARSET=utf8;&lt;/pre&gt;

&lt;h4&gt;Hibernate&lt;/h4&gt;
&lt;p&gt;-- hibernate.cfg.xml --&lt;/p&gt;
&lt;pre class="brush:xml"&gt;
&amp;lt;hibernate-configuration&amp;gt;
  &amp;lt;session-factory&amp;gt;
    &amp;lt;property name="hibernate.connection.useUnicode"&amp;gt;true&amp;lt;/property&amp;gt;
    &amp;lt;property name="hibernate.connection.characterEncoding"&amp;gt;utf-8&amp;lt;/property&amp;gt;
  &amp;lt;/session-factory&amp;gt;
&amp;lt;/hibernate-configuration&amp;gt;
&lt;/pre&gt;

&lt;h4&gt;Spring framework&lt;/h4&gt;
&lt;p&gt;Utiliser le servlet filter &lt;code&gt; CharacterEncodingFilter &lt;/code&gt; dans le web.xml afin de forcer l'encodage.
Attention de bien positionner ce filtre en premi&amp;egrave;re position dans la liste des diff&amp;eacute;rents filtres!&lt;/p&gt;
&lt;p&gt;-- web.xml --&lt;/p&gt;
&lt;pre class="brush:xml"&gt;
&amp;lt;web-app&amp;gt;
  &amp;lt;filter&amp;gt;
    &amp;lt;filter-name&amp;gt;encodingFilter&amp;lt;/filter-name&amp;gt;
    &amp;lt;filter-class&amp;gt;org.springframework.web.filter.CharacterEncodingFilter&amp;lt;/filter-class&amp;gt;
    &amp;lt;init-param&amp;gt;
      &amp;lt;param-name&amp;gt;encoding&amp;lt;/param-name&amp;gt;
      &amp;lt;param-value&amp;gt;UTF-8&amp;lt;/param-value&amp;gt;
    &amp;lt;/init-param&amp;gt;
    &amp;lt;init-param&amp;gt;
      &amp;lt;param-name&amp;gt;forceEncoding&amp;lt;/param-name&amp;gt;
      &amp;lt;param-value&amp;gt;true&amp;lt;/param-value&amp;gt;
    &amp;lt;/init-param&amp;gt;
  &amp;lt;/filter&amp;gt;
&amp;lt;/web-app&amp;gt;&lt;/pre&gt;

&lt;h4&gt;Velocity et mails&lt;/h4&gt;
&lt;p&gt;Lors du load des templates Velocity, sp&amp;eacute;cifier l'encodage UTF-8.&lt;/p&gt;
&lt;pre class="brush:java"&gt;
String content = VelocityEngineUtils.mergeTemplateIntoString(velocityEngine, fileName, "UTF-8", tokens);
&lt;/pre&gt;
&lt;p&gt;Encoder aussi les mails. Dans mon cas avec &lt;code&gt;MimeMessageHelper&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="brush:java"&gt;
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
&lt;/pre&gt;

&lt;h4&gt;JSP&lt;/h4&gt;
&lt;p&gt;D&amp;eacute;finir l'encodage des JSP.&lt;/p&gt;
&lt;pre class="brush:xml"&gt;
&amp;lt;%@ page contentType="text/html; charset=UTF-8"%&amp;gt;
&amp;lt;%@ page pageEncoding="UTF-8"%&amp;gt;
&lt;/pre&gt;

&lt;h4&gt;Tomcat&lt;/h4&gt;
&lt;p&gt;Si apr&amp;egrave;s tout &amp;ccedil;a vous avez encore des probl&amp;egrave;mes, vous pouvez toujours essayer de configurer
Tomcat mais je pense que &amp;ccedil;a ne changera pas grand chose...&lt;/p&gt;
&lt;p&gt;-- server.xml --&lt;/p&gt;
&lt;pre class="brush:xml"&gt;
&amp;lt;Server&amp;gt;
  &amp;lt;Service&amp;gt;
    &amp;lt;Connector URIEncoding="UTF-8" useBodyEncodingForURI="true" [...] /&amp;gt;
  &amp;lt;/Service&amp;gt;
&amp;lt;/Server&amp;gt;
&lt;/pre&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;Tous ces points ne sont surement pas n&amp;eacute;cessaire... il faut que je v&amp;eacute;rifie. Je pense que l'encodage
au niveau de la base de donn&amp;eacute;es, du web.xml et des mails (Velocity et MimeMessage) est suffisant mais cette liste
peut ammener des indices &amp;agrave; d'autres qui rencontrent ce genre de probl&amp;egrave;mes... &lt;br /&gt;
&lt;br /&gt;
Dans mon cas, le probl&amp;egrave;me venait du servlet filter d'encodage de Spring : il n'&amp;eacute;tait pas en
premi&amp;egrave;re position :-(&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6538999683570325297-7434285575984762862?l=surunairdejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://surunairdejava.blogspot.com/feeds/7434285575984762862/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6538999683570325297&amp;postID=7434285575984762862' title='12 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default/7434285575984762862'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6538999683570325297/posts/default/7434285575984762862'/><link rel='alternate' type='text/html' href='http://surunairdejava.blogspot.com/2007/05/utf-8-encoding.html' title='UTF-8 encoding'/><author><name>Cédric Thiébault</name><uri>http://www.blogger.com/profile/01915436356438533195</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>12</thr:total></entry></feed>
