lundi 14 mai 2007

UTF-8 encoding



Après plusieurs heures passées à trouver mon erreur d'encodage UTF-8, voici un petite liste des points à vérifier sur une application web.

Mon environnement :

  • MySQL
  • Hibernate
  • Spring MVC
  • Velocity (pour les mails)
  • Tomcat

MySQL

Vérifier que les tables et les champs textes utilisent le charset UTF-8 :

CREATE TABLE [...] DEFAULT CHARSET=utf8;

Hibernate

-- hibernate.cfg.xml --

<hibernate-configuration>
  <session-factory>
    <property name="hibernate.connection.useUnicode">true</property>
    <property name="hibernate.connection.characterEncoding">utf-8</property>
  </session-factory>
</hibernate-configuration>

Spring framework

Utiliser le servlet filter CharacterEncodingFilter dans le web.xml afin de forcer l'encodage. Attention de bien positionner ce filtre en première position dans la liste des différents filtres!

-- web.xml --

<web-app>
  <filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
      <param-name>forceEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
</web-app>

Velocity et mails

Lors du load des templates Velocity, spécifier l'encodage UTF-8.

String content = VelocityEngineUtils.mergeTemplateIntoString(velocityEngine, fileName, "UTF-8", tokens);

Encoder aussi les mails. Dans mon cas avec MimeMessageHelper.

MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");

JSP

Définir l'encodage des JSP.

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page pageEncoding="UTF-8"%>

Tomcat

Si après tout ça vous avez encore des problèmes, vous pouvez toujours essayer de configurer Tomcat mais je pense que ça ne changera pas grand chose...

-- server.xml --

<Server>
  <Service>
    <Connector URIEncoding="UTF-8" useBodyEncodingForURI="true" [...] />
  </Service>
</Server>

Conclusion

Tous ces points ne sont surement pas nécessaire... il faut que je vérifie. Je pense que l'encodage au niveau de la base de données, du web.xml et des mails (Velocity et MimeMessage) est suffisant mais cette liste peut ammener des indices à d'autres qui rencontrent ce genre de problèmes...

Dans mon cas, le problème venait du servlet filter d'encodage de Spring : il n'était pas en première position :-(

12 commentaires:

Éric a dit...

Dans un servlet context pour faire du jdbc direct, j'ai déjà eu besoin d'avoir un URL funky comme ça:

jdbc:mysql://localhost/zoum3?useUnicode=true&characterEncoding=utf8&useOldUTF8Behavior=true

dgirard a dit...

Si l'on fait du build avec Maven 2, il faut penser à rajouter ceci :
http://maven.apache.org/plugins/maven-resources-plugin/examples/encoding.html

Olivier J. a dit...

Autre possibilité pour tomcat, toujours au niveau de la balise Connector, utiliser l'attribut useBodyEncodingForURI.
Ceci permet d'avoir certaines pages en UTF-8 d'autre non (pratique pendant une phase de migration sur une grosse webapp ou on est pas sûre d'avoir tout changé).

Et pour les servlets, autre possibilité qui ne nécéssite pas de modifier le web.xml, mettre ça dans le code (doGet) :
request.setCharacterEncoding("UTF-8");

neilujnoilleb a dit...

Et pour passer toute la JVM en UTF-8 par défaut, il suffit d'ajouter :

-Dfile.encoding=UTF-8

à la ligne de lancement de Tomcat par exemple (pratique aussi).

LudoO a dit...

Ne pas oublier le filter-mapping...

<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

Pierre a dit...

Précision à propos de Tomcat : Il est suggéré la ligne suivante :
<Connector URIEncoding="UTF-8" useBodyEncodingForURI="true" [...] />
Cette instruction concerne l'encodage des URL (qui peuvent contenir des accents, ex : http://fr.wikipedia.org/wiki/%C3%89t%C3%A9).
Cette URL est encodée en UTF-8 (%C3%89 correspond à 'é'). Pour Tomcat, l'encodage par défaut est l'ISO-8859-1. Il est donc nécessaire de préciser useBodyEncodingForURI="true".
Cela fait que l'URL a le même encodage que le corps de la page. (qui peut être défini par servletRequest.setCharacterEncoding("UTF-8"); dans la méthode doPost).

Olivier Debas a dit...

Attention, avec l'option de JVM -Dfile.encoding=UTF-8 au lancement de Tomcat, toutes les applications héritent de cet encodage. Ce qui empêche le déploiement d'applications fonctionnant en "ISO Latin 1".

Yoann a dit...

Eclipse
-------
Il s'agit de gérer les ressouces fichiers du projet en mode UTF-8. Depuis
le menu Window, Preferences :

General, Editors, Text Editors, Spelling, Dictionaries, Encoding : UTF-8
General, Workspaces, Text file encoding : UTF-8
General, Content Types : tout passer en UTF-8

Anonyme a dit...

Et aussi :

http://support.jalios.com/jcms/jx_21247/jcms-55-utf-8

Anonyme a dit...

je ne peux pas m'empecher de vous ecrire enfin de vous remercier pour ce cadeau.Franchement j'ai galeré avant de trouver cette solution.
il m'a suffit juste d'ajoute

URIEncoding="UTF-8"
useBodyEncodingForURI="true"

et tout marche bien

Anonyme a dit...

Bravo pour l'option du Connector Tomcat pour les formulaire soumis en GET.

j'ai galéré 3 h avant de trouver

yobo a dit...

Spring : Gestion du message source suite soucis utf-8 + tot utiliser :
<bean id="messageSource";
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages"/>
<property name="defaultEncoding" value="UTF-8"/>
</bean>
avec un fichier messages.properties encodé en utf-8