Velocity Encoding Charset Error

First, set some properties for velocity engine. Set vm file reading path. use file read-mode not resource read-mode.

// set velocity path, if you don't do these, you will get Resource not found exception.
Properties p = new Properties();
p.setProperty("resource.loader", "file");
p.setProperty("class.resource.loader.class","org.apache.velocity.runtime.resource.loader.FileResourceLoader");
// where is your vms path, set it
p.setProperty("file.resource.loader.path", realPath + "/vm");
// set output encoding
// nearly almost articals said the following will work, but it won't
p.setProperty(Velocity.INPUT_ENCODING, Constant.DEFAULT_ENCODING);
p.setProperty(Velocity.OUTPUT_ENCODING, Constant.DEFAULT_ENCODING);
p.setProperty("contentType", "text/html;charset="+Constant.DEFAULT_ENCODING);
Velocity.init(p);

The above code should be write in beginning of use any of velocity objects. In Spring or Java web application, you should write them into Servlet context listener.
If you use ascii word. There will no error encoding. But if you use gb2312 or UTF-8. You will find something weird. The above code dose not work. So I use response output to solve those encoding problem. In web application, we always use response.getOutputStream() to write something back. But now, we should construct output stream to write correct encoding word to the page. So velocity can encoding them correctly. The following code will help you.

String encoding = "utf-8";
// If you use UTF-8 encoding in your application
Writer writer = new PrintWriter(new PrintStream(resp.getOutputStream(), true, encoding));
// velocity will find abc.vm in your file path folder.
String pageName = "abc";
Template template = Velocity.getTemplate(pageName);
VelocityContext context = new VelocityContext();
context.put("test", new String("hello".getBytes(encoding), encoding));
// here velocity will use the writer to write correct encoding words to response stream. So we can see the correct words showed by our page.
template.merge(context, writer);

If you use jetty to run your web application, it works fine.
But maybe you use windows resin to run war package. Sometimes, error encoding comes again. There is something wrong with your resin application. You should change config file in resin conf folder. In conf/resin.xml( resin 4.0+ ), add <character-encoding>UTF-8</character-encoding> in < web-app-default >. Like following:

< web-app-default >
<character-encoding>UTF-8</character-encoding>
...
< /web-app-default >
And you should use correct charset to start your resin. Else resin will use default charset of your operation system.

java -Dfile.encoding=UTF-8 -jar lib/resin.jar

Addition, if you use spring framework, don't forget the encoding filter :

<filter>
<filter-name>characterEncodingFilter</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>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
In encoding or charset error. You should consider the following :

  • environment (like resin, jetty, eclipse and etc.)
  • Input (from outside, like user input, or reading from database )
  • Output (to outside, like page presented, or writing to database or file)
  • Process (maybe you encode words twice or more, or encode them to some other different charset)