La maldita codificación de caracteres
Esta semana he estado trabajando en un proyecto y me vino a la cabeza este artículo de Joel Spolsky sobre codificación de caracteres, porque nuestra aplicación (que por suerte está en fase de desarrollo) mostraba serios problemas de codificación en los diferentes navegadores con los que probábamos.
Vamos a ver, todos nuestros ficheros estaban en UTF-8 y los ficheros JSP tenían su correspondiente encabezado con la etiqueta meta indicando que la codificación es efectivamente UTF-8, ¿por qué razón el navegador detecta que están en ISO-8859-1?
Después de estar un rato buscando y leyendo información al respecto, he encontrado este interesante filtro creado por la gente de Spring que permite forzar la codificación de caracteres en el descriptor de la aplicación (web.xml).
Al introducir esta modificación en la aplicación, el navegador ya detecta que las páginas están en codificación UTF-8 ... !problema resuelto! ... pues no, en realidad ahora estamos peor que antes, no se ve bien en UTF-8 y se ve aún peor en ISO-8859-1. ¿Qué está ocurriendo aquí? A mi compañero Pablo se le ocurre abrir los fichero en un editor diferente al IDE que estamos utilizando, IntelliJ IDEA, y nos sorprende ver que la codificación es ... ANSI as UTF-8?!?!?! por lo que cambiamos a UTF-8 y volvemos a cargar la página, ahora todo se ve correctamente. Si a ti también te ha pasado esto seguro que te has quedado con la misma cara de incógnita que Pablo y yo, pero bueno ya tenemos la solución, y decidimos dejar el filtro encodingFilter porque nos asegura que aunque se nos olvide utilizar el tag meta con la información de codificación de las páginas, la aplicación funcionará bien.
Un rato más tarde estamos realizando la tarea de internacionalización de la aplicación, cambiando los literales por las etiquetas de los messages.properties correspondientes (los ficheros son cargados por el message source de Spring, ya que estamos usando Spring MVC) y cuando probamos la aplicación, resulta que la codificación es errónea de nuevo. Hoy no es nuestro día, pero el error debe estar en los ficheros .properties para la internacionalización, pues no, están perfectamente codificados y el resto no se ha cambiado. Aquí hay algo que no hemos visto o alguien no nos ha contado, de nuevo a googlear para ver cual es el problema y encontramos este fantástico artículo, sencillo y directo al grano. Pues claro ... si Java carga los .properties como ISO-8859-1 aunque el resto sea UTF-8 tenemos un problema, pero aquí llega de nuevo Spring a nuestro rescate y basta con cambiar ResourceBundleMessageSource por ReloadableResourceBundleMessageSource en nuestro applicationContext.xml o el fichero que se haya utilizado en cada caso concreto, y todo funciona de nuevo.
Cual es la moraleja de hoy, pues primero desquitarme con IntelliJ IDEA porque nos ha tenido un rato más perdidos que un pulpo en un garaje, y segundo recordar a todo aquel que no haya leído el artículo del señor Spolsky que lo haga :-) Querido Joel ... nosotros ya hemos resuelto nuestros problemas de codificación, no nos ponga en su lista negra :-P
Vamos a ver, todos nuestros ficheros estaban en UTF-8 y los ficheros JSP tenían su correspondiente encabezado con la etiqueta meta indicando que la codificación es efectivamente UTF-8, ¿por qué razón el navegador detecta que están en ISO-8859-1?
Después de estar un rato buscando y leyendo información al respecto, he encontrado este interesante filtro creado por la gente de Spring que permite forzar la codificación de caracteres en el descriptor de la aplicación (web.xml).
<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>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>
Al introducir esta modificación en la aplicación, el navegador ya detecta que las páginas están en codificación UTF-8 ... !problema resuelto! ... pues no, en realidad ahora estamos peor que antes, no se ve bien en UTF-8 y se ve aún peor en ISO-8859-1. ¿Qué está ocurriendo aquí? A mi compañero Pablo se le ocurre abrir los fichero en un editor diferente al IDE que estamos utilizando, IntelliJ IDEA, y nos sorprende ver que la codificación es ... ANSI as UTF-8?!?!?! por lo que cambiamos a UTF-8 y volvemos a cargar la página, ahora todo se ve correctamente. Si a ti también te ha pasado esto seguro que te has quedado con la misma cara de incógnita que Pablo y yo, pero bueno ya tenemos la solución, y decidimos dejar el filtro encodingFilter porque nos asegura que aunque se nos olvide utilizar el tag meta con la información de codificación de las páginas, la aplicación funcionará bien.
Un rato más tarde estamos realizando la tarea de internacionalización de la aplicación, cambiando los literales por las etiquetas de los messages.properties correspondientes (los ficheros son cargados por el message source de Spring, ya que estamos usando Spring MVC) y cuando probamos la aplicación, resulta que la codificación es errónea de nuevo. Hoy no es nuestro día, pero el error debe estar en los ficheros .properties para la internacionalización, pues no, están perfectamente codificados y el resto no se ha cambiado. Aquí hay algo que no hemos visto o alguien no nos ha contado, de nuevo a googlear para ver cual es el problema y encontramos este fantástico artículo, sencillo y directo al grano. Pues claro ... si Java carga los .properties como ISO-8859-1 aunque el resto sea UTF-8 tenemos un problema, pero aquí llega de nuevo Spring a nuestro rescate y basta con cambiar ResourceBundleMessageSource por ReloadableResourceBundleMessageSource en nuestro applicationContext.xml o el fichero que se haya utilizado en cada caso concreto, y todo funciona de nuevo.
<bean class="org.springframework.context.support.ReloadableResourceBundleMessageSource" id="messageSource">
<property name="basename" value="classpath:messages">
<property name="defaultEncoding" value="UTF-8">
</bean>
Cual es la moraleja de hoy, pues primero desquitarme con IntelliJ IDEA porque nos ha tenido un rato más perdidos que un pulpo en un garaje, y segundo recordar a todo aquel que no haya leído el artículo del señor Spolsky que lo haga :-) Querido Joel ... nosotros ya hemos resuelto nuestros problemas de codificación, no nos ponga en su lista negra :-P
Comentarios
El caso es que nosotros tenemos un problema no descrito pero del mismo tipo con el tema de los encodings. Tenemos aplicado el filtro para encodings de Spring y todo funciona perfecto en los submit y en la recuperacion dedes base de datos.
Resulta que en el metodo "setupForm" de un formulario, usando Spring MVC, intentamos poner como valor por defecto en el campo del pais "España", con la sorpresa de que cuando se carga el formulario nos aparece "Espa√±a". Ya no se por donde buscar.
A ver si tuvieras una idea de por donde tirar.
Gracias de antemano.
Saludos.
Gracias en cualquier caso y espero que le sirva a alguien mas.
La verdad es que no habría pensado en Maven (estaba pensando más bien la codificación de los ficheros fuentes o similar) aunque cierto es que nosotros también probamos por ese lado en nuestro caso aunque sin efecto alguno, porque como has podido leer nosotros teníamos otro problema diferente.
De todas maneras muchas gracias por la aportación que espero que sirva a alguien.
La verdad es que no habría pensado en Maven (estaba pensando más bien la codificación de los ficheros fuentes o similar) aunque cierto es que nosotros también probamos por ese lado en nuestro caso aunque sin efecto alguno, porque como has podido leer nosotros teníamos otro problema diferente.
De todas maneras muchas gracias por la aportación que espero que sirva a alguien.