java tomcat utf-8 encoding issue - java

I am developing a simple web application using java/jsp/tomcat/mysql, and the most problem lies on the character encoding because I need to deal with UTF-8 encoding instead of the default 8851.
First of I'd like to describe my program structure. I am using a Servlet called Controller.java to handle all request. So in web.xml, I have a Controller servlet which takes all request from *.do.
Then this Controller will dispatch the request based on the requested URL, for example, if client asks for register.do, Controller will dispatch the request to Register.java.
And in the Register.java, there is a method which takes the request as parameter, namely:
public String perform(HttpServletRequest request) {
do something with the request...
}
So the problem is if I want to print something in UTF-8 inside this method, it will give random characters. For example, I have an Enum which stores several constants, one of the properties the Enum has is its name in Traditional Chinese. If I print it in
public static void main(Stirng[] args{
System.out.println(MyEnum.One.getChn());
logger.info(MyEnum.One.getChn());
}
This is printed correctly in Chinese. However, if I put the exact code inside the method dealing with HttpServletRequest:
public String perform(HttpServletRequest request) {
System.out.println(MyEnum.One.getChn());
logger.info(MyEnum.One.getChn());
}
They are printed as random characters, but I can see from the debug window (eclipse) that the variables are holding correct Chinese characters.
So, the same situation happens when I want to store the value from request.getParameter(). In the debug window, I can see the variable is holding correct characters, but one I print it out or try to store it in the database, it is random characters.
I don't know why the behavior acts like this, and this is blocking me from reading submitted form values and store them into database. Could someone give some hints on this?
Great thanks.

Here is a small tutorial what you need to do to make UTF-8 work in your web application:
You have to implement Filter in your application for character encoding:
public class CharacterEncodingFilter implements Filter {
#Override
public void init(FilterConfig filterConfig)
throws ServletException {
}
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
servletRequest.setCharacterEncoding("UTF-8");
servletResponse.setContentType("text/html; charset=UTF-8");
filterChain.doFilter(servletRequest, servletResponse);
}
#Override
public void destroy() {
}
}
You have to make sure that your tomcat's server.xml's file connector element has URIEncoding attribute which value is UTF-8.
<Connector port="8080"
protocol="HTTP/1.1"
connectionTimeout="20000"
URIEncoding="UTF-8"
redirectPort="8443"/>
Also you need to specify this in every JSP page:
<%#page contentType="text/html" pageEncoding="UTF-8"%>

If you need to use UTF-8 encoding (and really, everybody should be going this these days), then you can follow the "UTF-8 everywhere HOWTO" found in the Tomcat FAQ:
http://wiki.apache.org/tomcat/FAQ/CharacterEncoding#Q8
Remember that you also need to support UTF-8 in your database's text fields.
Also remember that sometimes "printing" a String with non-ASCII characters in it to a log file or the console can be affected by
The character encoding of the output stream
The character encoding of the file reader (e.g. cat/less/vi)
The character encoding of the terminal
You might be better off writing the values to a file and then using a hex editor to examine the contents to be sure that you are getting the byte values you are looking for.

Related

Wicket messes uo the encoding of strings from Javascript

In the context of a Wicket component using JavaScript, I'm sending the following string back to Wicket :
"FICHIERfichier&é'(-è_çà)=~#{[`^#]}^$ù,;!¨£%µ§êë-+¤.0²123456789.pdf"
I have to escape() this in JavaScript because otherwise Wicket interprets the ampersand as a parameter delimiter and chops the string into multiple parameters.
However, this is what I get on the Wicket side of things :
"FICHIERfichier&�'(-�_��)=~#{[`^#]}^$�,;!��%����- �.0�123456789.pdf"
Any ideas ? I've tried many unescape/decode methods to no avail...
Many Thanks !
It seems the character encoding your application uses does not support some of the sent characters.
Make sure you use a good charset in Wicket's RequestCycleSettings. By default it is UTF-8, but your application may have changed it.
In addition if you use some old version of a Servlet container then you may need to use a Servlet Filter around Wicket Filter that sets the character encoding on the HttpServletRequest. A quick googling for "Servlet filter character encoding" gives this good example: https://stackoverflow.com/a/11100412/497381.
public class CustomCharacterEncodingFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);
}
public void destroy() {
}
}

Java Web Service for existing application

I am currently doing an internship where I have an existing java project that essentially processes strings and gives you an output with informations about it. I am now told to do an web interface for it, with an input field, a button to send a request, and a field for displaying the output. I was given the advice to look into REST web services. Since I have never done anything web related before, I read tons of materials, and am now a bit confused. Please tell me if I got the following points correctly.
For the webservice, I can use JAX-RS, so I will use a class like that:
#Path( "result/{input}" )
public class ResultResource
{
#GET
#Produces( MediaType.TEXT_PLAIN )
public String message(#PathParam("input") String input)
{
return myApplication.processInput(input);
}
}
Now I am unsure: Can I create the web interface (button, input fields) with a jsp file or a html file? So that when the button is clicked, the url "..result/input" is called and I somehow have to read the result from the page and display it in my results field.
To make it runnable on a server, I have to deploy my REST-servlet above on tomcat / jetty.
Would be pleased to get some answers, because I am a bit lost.
You can do this in a jsp file, you just use normal html for your form and button etc.
In your form do action="/yourServlet?param=yourInput" method="post".
And then in your servlet you can make a doPost method which will get your parameter like:
public void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException
{
String input = request.getParameter("yourInput");
doSomething(input);
}
and then do whatever you want it to. You can then send it back to the desired page with
request.getRequestDispatcher("/yourPage.jsp").forward(request, response);
This should also be in your doPost. Your response here can be what you did to your input and you can then make a result field in yourPage.
To make it runnable you can indeed put in on a tomcat server.

Tomcat concurrency

I want to use servlet concurrently.
Of course, There is lots of questions related with this subject, but my servlet still works in sequential.
I'm using servlet with Tomcat8, which uses Jena triplestore (with Apache Jena Lib)
My servlet is called within ajax from html, and return data with response.getWriter().write() method.
Each browser is blocked while servlet is running, but it would not matter with concurrent work of servlet I think (because it is each browser's work)
I attach here my server.xml setting:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
maxThreads="300"
acceptCount="200"
minSpareThreads="100"
/>
and doGet method:
#Override
public void init(ServletConfig conf) throws ServletException {
System.out.println("Servlet Run");
}
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
String data = request.getParameter("data");
String[] spdata = data.split("\\|");
String sen = spdata[0];
String name = spdata[1];
String id = spdata[2];
System.out.println(sen + ' ' + name + ' ' + id);
int user = id.hashCode();
System.out.println("Load Init");
DialogSystemForTomcat d = new DialogSystemForTomcat(user);
System.out.println("After Init");
System.out.println("Sentence: "+sen);
String rtn = d.runJob(name, sen);
response.getWriter().write(rtn);
System.out.println("Return: "+rtn);
}
As you can see, I call another Java class within doGet() method which really processes my input.
(real process is done within d.runjob() method)
It is working sequentially for all inputs now, but I want to work in concurrent for all inputs.
What should I change? Please help.
=========================================
After...
I worked to make process as faster as possible.
But I could not make it concurrent.
Each browser is blocked while servlet is running, but it would not matter with concurrent work of servlet I think (because it is each browser's work)
You are mistaken. Servlets are concurrent, except for the obsolete SingleThreadModel which you aren't using, and unless they contain synchronized methods or blocks, which this one doesn't, or semaphores, ditto. Ergo this code is concurrent, unless the processing in the unnamed class is synchronized or uses a semaphore of some kind.
NB You have an error in the init() method. It must call super.init(conf). See the Javadoc.

Bad special character encoding with RESTEasy

I am developing a web application with jboss eap 6.3 which uses resteasy rest framework, I have got a bad encoding problem with special characters passed as FormParam in a POST resources, for example:
#POST
#Path("/post")
public Response createTask(#FormParam("param") String param) {
LOGGER.info("HELLO POST XML. "+param);
return Response.ok(param).build();
}
If I pass a thing like abc èèè i will get a stuff like "abc èà èà è", with jersey rest framework this issue don'exists.
What should i do?
Thanks
RESTEasy solution
Since RESTEasy interprets the request for you using a servlet, your best bet is to use a servlet filter to set the request character encoding:
public class CharacterEncodingFilter implements javax.servlet.Filter {
// ...
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
request.setCharacterEncoding("UTF-8");
filterChain.doFilter(request, response);
}
}
Reference How to set charset for my web application?
JBoss solution
To ensure that the application server receives the request parameters in the correct encoding from client requests, you have to configure the connector. For JBoss AS (before version 7) change:
<jboss_install>/server/deploy/jbossweb.sar/server.xml
or in other JBoss AS versions:
<jboss_install>/server/(default)/deploy/jboss-web.deployer/server.xml
to set the connector URIEncoding:
<Connector port="8080" URIEncoding="UTF-8" />
Reference JBoss Seam documentation: 16.1 Internationalizing your app.
This configuration is done differently by changing standalone.xml in JBoss AS 7 and later, as in this answer (also answered in JBossDeveloper forum).
Server independent solution
Since the above is a JBoss dependent solution, my answer would not be complete without providing a server-independent solution.
The most basic is to use a context parameter indicating the character encoding choice for all forms in the application. Setting the context parameter is done in the WEB-INF/web.xml file.
<context-param>
<param-name>PARAMETER_ENCODING</param-name>
<param-value>UTF-8</param-value>
</context-param>
Then your application can read the context parameter and can set the request character encoding before reading any request parameters. You can set the request encoding in either a Java Servlet or in JSP syntax:
<%
String paramEncoding = application.getInitParameter("PARAMETER_ENCODING");
request.setCharacterEncoding(paramEncoding);
String name = request.getParameter("NAME");
%>
Reference Character Conversions from Browser to Database.
Database involvement
You may still have to set the character encoding of your database, otherwise you can lose information as in this diagram:
Reference Character Conversions from Browser to Database.
Miscellaneous
Additional information at Character encoding JSP -displayed wrong in JSP but not in URL and for Tomcat at HttpServletRequest - setCharacterEncoding seems to do nothing.
You can also set the default encoding for the JVM.
A bug titled "Text responses should default to charset UTF-8" was fixed in RESTEasy version 2.3.7.
I just declared in my project jboss-web.xml default encoding, and this solved the problem
<jboss-web>
<default-encoding>UTF-8</default-encoding>
</jboss-web>

How do I specify a query string in Tomcat's <servlet-mapping> <url-pattern>?

I am running Tomcat 5.5.4 and have a servlet running with no problems. However, I'd like to set up a mapping to only launch the servlet when a URL containing a particular query string is submitted.
Right now in web.xml I have:
<servlet-mapping>
<servlet-name>MyServer</servlet-name>
<url-pattern>/go/*</url-pattern>
</servlet-mapping>
If a browser submits http://localhost/MyServer/go?P=123 the servlet is launched and all is well. However, I'd like to only launch that servlet if the URL is exactly as just shown. Unfortunately, right now if the URL is http://localhost/MyServer/go?P=AnyDarnThing the servlet still launches. I have tried setting up the following:
<url-pattern>/go?P=123</url-pattern>
but this results in The requested resource (/MyServer/go) is not available.
I've tried numerous variations (quoting the string, ...) on the above URL pattern but I always get the above error. I notice that if I (for debugging purposes) drop the "?" as in
<url-pattern>/goP=123</url-pattern>
I no longer get the error message and the server launches (but, of course, it doesn't respond to the "query string" because it's not properly formed.) This suggest to me that the "?" is causing a problem in the mapping. I've tried replacing it with its URL special character equivalent as follows:
<url-pattern>/go%3FP=123</url-pattern>
but this gives the same result just described above when I tried dropping the "?" altogether.
I realize I can let the servlet get launched when any query string is submitted and then "ignore" the request for all but the one I care about but there is a reason I'd prefer to not have the servlet launched to begin with. So, my question is, how can I configure the servlet so that it is only launched when a specific query string is included?
Thank you.
You can't do that. The url-pattern is pretty limited.
If you want to have distinct actions taken based on a GET parameter, you can do that manually. In the doGet() method of the servlet have a simple if-clause and invoke different methods depending on the query string / get param.
You can't do that using URL patterns.
You can achive this using filters. Implement a filter which will forward to the Servlet only if the query params exists.
Here is the how the filter will look like:
public class ServletAcessFilter implements Filter
{
public void init(FilterConfig filterConfig) throws ServletException
{
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException
{
//validate the request, check if the request can be forwarded to servlet.
if(request.getParameter("P").equalsIgnoreCase("123")){
filterChain.doFilter(request, response);
} else {
//write what you want to do if the request has no access
//below code will write 404 not found, you can do based on your requirement
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setStatus(404);
}
}
public void destroy()
{
}
}
Define the filter in the web.xml like this:
<filter>
<filter-name>ServletAccessFilter</filter-name>
<filter-class>com.ServletAcessFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ServletAccessFilter</filter-name>
<url-pattern>/go/*</url-pattern>
</filter-mapping>
To add to Bozho response, you may also try to move to Clean URLs
This will greatly increase your options in terms of URL pattern matching, and, in particular, may significantly ease configuration of a fronting reverse proxy if you ever need one.

Categories

Resources