Results 1 to 7 of 7

Thread: UTF-8 encoding in Spring MVC Portlet

  1. #1
    Join Date
    Jun 2008
    Posts
    5

    Default UTF-8 encoding in Spring MVC Portlet

    We are writing a jsr-168 portlet using spring-webmvc-portlet-2.5.5 however we are encountering character encoding problems when displaying any special characters. For instance the character é displays as é. If we deploy a second app with the same jsp but use getPortletContext().getRequestDispatcher("/path/file.jsp") instead of spring's org.springframework.web.portlet.DispatcherPortlet, it displays correctly. Also, if we use spring-webmvc-2.5.5 outside of the portal environment, it also displays correctly. All of our pages have character encoding set to UTF-8 and we have also tried using the org.springframework.web.filter.CharacterEncodingFi lter to force encoding to UTF-8. The text still displays incorrectly. Any idea why this is happening and how we can fix it?

    I should also point out that with debug turned on the DispatcherPortlet still indicates that it is setting the response to IS-8859-1 even with the filter supposedly forcing everything to UTF-8:
    DEBUG [org.springframework.web.portlet.DispatcherPortlet. render:1088] - Setting portlet response content type to view-determined type [text/html;charset=ISO-8859-1]

    Our web.xml is as follows:

    <web-app>

    <display-name>MyApp</display-name>

    <!-- CONTEXT PARAMS -->

    <context-param>
    <param-name>log4jConfigLocation</param-name>
    <param-value>/WEB-INF/classes/log4j.xml</param-value>
    <description>Location of the Log4j configuration file</description>
    </context-param>

    <context-param>
    <param-name>log4jRefreshInterval</param-name>
    <param-value>60000</param-value>
    <description>Milliseconds between checks to refresh log4j configuration, 60000 = 1 minute</description>
    </context-param>

    <context-param>
    <param-name>log4jExposeWebAppRoot</param-name>
    <param-value>false</param-value>
    <description>Should Log4j listener overwrite webAppRootKey? See Spring documentation for Log4j listener</description>
    </context-param>

    <context-param>
    <param-name>webAppRootKey</param-name>
    <param-value>MyApp.root</param-value>
    </context-param>

    <context-param>
    <param-name>contextPath</param-name>
    <param-value>MyApp</param-value>
    <description>The webapp name</description>
    </context-param>

    <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>WEB-INF/context/applicationContext.xml, WEB-INF/context/app/*-context.xml</param-value>
    <description>Comma-separated list of Spring context files to load to initialize the application</description>
    </context-param>

    <!-- I18N -->
    <context-param>
    <param-name>javax.servlet.jsp.jstl.fmt.localizationContex t</param-name>
    <param-value>MyAppResources</param-value>
    <description>Basename of the localized message bundles</description>
    </context-param>

    <context-param>
    <param-name>javax.servlet.jsp.jstl.fmt.fallbackLocale</param-name>
    <param-value>en_US</param-value>
    <description>Locale to use if Java Runtime does not support the web request's locale</description>
    </context-param>

    <!-- Force Char Encoding -->
    <filter>
    <filter-name>SetCharacterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEnco dingFilter</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>

    <!-- SECURITY FILTER TO PREVENT DIRECT ACCESS TO WEB-APP -->

    <filter>
    <filter-name>PortletApplicationSecurityFilter</filter-name>
    <filter-class>com.portal.PortletApplicationSecurityFilter</filter-class>
    </filter>

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

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


    <!-- LOG4J CONFIG LISTENER -->

    <listener>
    <listener-class>org.springframework.web.util.Log4jConfigList ener</listener-class>
    </listener>

    <!-- PORTLET APPLICATION CONTEXT LISTENER -->

    <listener>
    <listener-class>com.portal.PortletApplicationServletContextL istener</listener-class>
    </listener>

    <!-- SPRING APPLICATION CONTEXT LISTENER -->

    <listener>
    <listener-class>org.springframework.web.context.ContextLoade rListener</listener-class>
    </listener>

    <!-- PORTLET COMMAND SERVLET -->

    <servlet>
    <servlet-name>PortletCommandServlet</servlet-name>
    <servlet-class>com.portal.portlet.jsrcontainer.PortletComma ndServlet</servlet-class>
    </servlet>

    <!-- VIEW RENDERER SERVLET -->

    <servlet>
    <servlet-name>ViewRendererServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.ViewRenderer Servlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    </servlet>

    <!-- SERVLET MAPPINGS -->

    <servlet-mapping>
    <servlet-name>PortletCommandServlet</servlet-name>
    <url-pattern>/portletCommand/*</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
    <servlet-name>ViewRendererServlet</servlet-name>
    <url-pattern>/WEB-INF/servlet/view</url-pattern>
    </servlet-mapping>

    <!-- SESSION CONFIG -->

    <session-config>
    <session-timeout>30</session-timeout>
    </session-config>

    <!-- TAGLIB -->

    <taglib>
    <taglib-uri>/spring</taglib-uri>
    <taglib-location>/WEB-INF/taglib/spring.tld</taglib-location>
    </taglib>

    <taglib>
    <taglib-uri>/portlet</taglib-uri>
    <taglib-location>/WEB-INF/taglib/portlet.tld</taglib-location>
    </taglib>

    </web-app>

    and a clip from our portlet.xml:

    <portlet>
    <description>MyPortlet</description>
    <portlet-name>MyPortlet</portlet-name>
    <display-name>MyPortlet</display-name>
    <portlet-class>org.springframework.web.portlet.DispatcherPo rtlet</portlet-class>
    <init-param>
    <name>contextConfigLocation</name>
    <value>/WEB-INF/context/portlet/viewService.xml</value>
    </init-param>
    <expiration-cache>0</expiration-cache>
    <supports>
    <mime-type>text/html</mime-type>
    <portlet-mode>view</portlet-mode>
    <portlet-mode>config</portlet-mode>
    </supports>
    <supported-locale>en</supported-locale>
    <supported-locale>es</supported-locale>
    <portlet-info>
    <title>MyPortlet</title>
    <short-title>MyPortlet</short-title>
    <keywords>basic, portlet</keywords>
    </portlet-info>
    </portlet>
    Last edited by jhughes; Nov 25th, 2008 at 05:07 PM.

  2. #2
    Join Date
    Jun 2008
    Posts
    5

    Default

    We found a solution to our problem... but it raises a question.

    If we add:
    <property name="contentType" value="text/html;charset=UTF-8" />
    to our view resolver definition, the character encoding works.

    So the question is why does the view resolver default to ISO-8859-1 instead of using the character encoding based on the <%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" pageEncoding="UTF-8" %> at the top of the jsp?
    Last edited by jhughes; Nov 25th, 2008 at 05:43 PM.

  3. #3
    Join Date
    Sep 2004
    Location
    Arizona, USA
    Posts
    383

    Default

    Servlet filter do not get applied to portlet requests. That would (partially) explain why it works in a servlet context but not in a portlet context.

    If you remove the CharacterEncodingFilter, do you get the same behavior in a Servlet context? I assume the answer to this is yes.

    So, this does sound like the ViewResolver is not picking up the encoding properly. Which ViewResolver are you using and how is it configured?

  4. #4
    Join Date
    Oct 2006
    Posts
    228

    Default

    Looks like the DispatcherPortlet sets the content type BEFORE your jsp ever gets included - so no matter what your JSP has set this will be ignored. The DispatcherPortlet uses the default content type for the view if no content type is explicitly set on the view, this is "text/html;charset=ISO-8859-1".

    Your approach is probably the best way to overcome this, perhaps raising a jira would be appropriate.

  5. #5
    Join Date
    Sep 2004
    Location
    Arizona, USA
    Posts
    383

    Default

    Dug into the code a bit more -- here is what is happening:

    The DispatcherPortlet will set the ContentType on the RenderResponse, but only if it was not already set prior to rendering. When it is time to render, it checks to see if any ContentType was already set. If not, it gets the ContentType string from the View object and uses that (this is the debug message that you are seeing).

    The eventual call to PortletRequestDispatcher.include would not generally set the ContentType on the RenderResponse. However, the spec (and many portlet containers) require that the ContentType be explicitly set. That is why the DispatcherPortlet does it. Regardless, I think the ContentType would still be getting set this way even if the include were doing it -- the View object sets the ContentType on the ServletResponse when it renders itself using the same ContentyType value that the DispatcherPortlet is already using.

    The problem here appears to be that the ContentType on the View object is never set in the case of JSP. It just uses the default value defined in AbstractView, which is ""text/html;charset=ISO-8859-1". It does this because the JSP will set the ContentType itself when used as part of a forward, but is ignored when used as part of an include. Since all Portlet requests are includes (there is no such thing as forward in the PortletRequestDispatcher), the JSP never sets the ContentType.

    So, after all that, you would either need a special View class that could parse the view definition to determine it's ContentType (yuck) or you need to continue with the solution you already have, which is to explicitly set the ContentType somewhere else. You can continue to do this with the ViewResolver as you have already done, or you could do it in your Controller by setting the ContentType on the RenderResponse there, or you could create a HandlerInterceptor that is analogous to the CharacterEncodingFilter.

    Sorry this isn't a "happy" answer, but at least it is a comprehensive one...

  6. #6
    Join Date
    Oct 2005
    Location
    Amsterdam
    Posts
    123

    Default

    Much along the lines of what John is saying, we use a interceptor (that gets added to the DefaultAnnotationHandlerMapping bean that we use)


    Code:
    public class CharEncodingInterceptor extends HandlerInterceptorAdapter {
    	
    	private String contentType;
    	
    	public void setContentType(String contentType) {
    		this.contentType = contentType;
    	}
    
    	@Override
    	public boolean preHandleRender(RenderRequest request, RenderResponse response, Object handler) throws Exception {
    		response.setContentType(this.contentType);
    		return true;
    	}
    
    }
    Hans Westerbeek
    Software Engineer

  7. #7
    Join Date
    Jun 2011
    Location
    North West England
    Posts
    3

    Default

    We have just encountered this problem while re-platforming our portlets from Oracle Application Server 10g to WebLogic 11g (10.3). Both versions of our code use the same 2.0.8 version of the Spring framework.

    The view resolver <property name="contentType" value="text/html;charset=UTF-8" /> fix has worked for us - many thanks.

    I can see why we would need this setting on WebLogic, but I'm puzzled as to why we did not have the issue on Application Server 10g.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •