3

I have a problem with encoding strings in RESTeasy. The problem is that chinese alphabet or any other non-latin characters are not displayed properly. If I try to print them out (or send as response) I get "?????" instead. I believe that default encoding in RESTeasy is us-ascii. Do you know how to change it to UTF-8? Maybe there is another solution to this problem?

Here is a short passage from my code:

@POST
@Path("post")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public String uploadData(@MultipartForm DataUploadForm uploadForm) {

...

//the code below is just for the purpose of presentation

String text = "some non-latin alphabet signs here"
System.out.println(text);  // "??????" is printed out

return text; //"??????" is returned
}

My resteasy-jaxrs-3.0-beta-2 is running on Tomcat 7.0.

Thank you!

Wojtek
  • 67
  • 1
  • 2
  • 7
  • Should there be a `@Produces` annotation about? (It might be at the class level.) – Donal Fellows Feb 04 '13 at 09:40
  • Thanks, I'll try it, yet I wonder whether this annotation influences what is going on inside the method (before producing the output)? In other words can it make System.out.println display proper characters? – Wojtek Feb 04 '13 at 10:55
  • If the `System.out.println()` encoding is your only actual problem, then you basically need to configure it in the side of the one responsible for presenting the stdout. If it's for example Eclipse, then head to this answer: http://stackoverflow.com/questions/13452324/arabic-letters-giving-me-output-as/13452715#13452715 Note that this has **completely nothing** to do with Tomcat/Servlets/JAX-RS/RESTeasy. – BalusC Feb 06 '13 at 13:11

6 Answers6

10

For people who come here because of the title of the question, here's a solution. In your @Consumes annotation, try setting the charset to UTF-8:

@Consumes(MediaType.MULTIPART_FORM_DATA+";charset=UTF-8");
Steve Goodman
  • 1,196
  • 10
  • 22
  • 1
    for my resteasy 2.3.2, after updating the @Consume, I'me getting the following error: Failed executing POST [TheUrl]: org.jboss.resteasy.spi.UnsupportedMediaTypeException: Cannot consume content type – davs Jul 23 '14 at 08:20
  • What are you sending in the Content-Type header of your POST request? If you copied my example directly, it needs to be "multipart/form-data". If you're not uploading files in a form, you'll need to update the MediaType accordingly. – Steve Goodman Jul 23 '14 at 13:37
3

I had the same problem migrating jaxrs1 (jersey) to resteasy 3.0.17.final.

When uploading form/multipart from a custom client, the client did send a content-type, but no charset and then resteasy assumes "us-ascii" (as per MIME RFC, according to the docs). Funny thing is that if no content-type at all is given, resteasy assumes "text/plain; charset=ISO-8859-1" (following http spec, I assume?).

Their docs propose to solve this using a RestEasy custom interceptor:

https://docs.jboss.org/resteasy/docs/3.0.2.Final/userguide/html/Multipart.html#multipart_overwrite_content_type

But this interceptor is actually deprecated and it advertises to use the jaxrs 2.0 interceptor mechanism.

Long story short, to get it to work in an implementation-independent way, you create this class:

package x.y.z;
import java.io.IOException;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.ext.ReaderInterceptor;
import javax.ws.rs.ext.ReaderInterceptorContext;
@Provider
/**
 * If charset not given (form multipart upload), default to UTF-8 and not us-ascii (MIME RFC).
 */
public class RestEasyDefaultCharsetInterceptor implements ReaderInterceptor {
    // Using string value instead of constant to limit references to RestEasy (this should be possible to set through web.xml imo)
    // private static final String RESTEASY_DEFAULT_CHARSET_PROPERTY = org.jboss.resteasy.plugins.providers.multipart.InputPart.DEFAULT_CHARSET_PROPERTY;
    private static final String RESTEASY_DEFAULT_CHARSET_PROPERTY = "resteasy.provider.multipart.inputpart.defaultCharset";
    @Override
    public Object aroundReadFrom(ReaderInterceptorContext ctx) throws IOException, WebApplicationException {
        ctx.setProperty(RESTEASY_DEFAULT_CHARSET_PROPERTY, "UTF-8");
        return ctx.proceed();
    }
}

Next, add the interceptor to web.xml: <context-param> <param-name>resteasy.providers</param-name> <param-value>
x.y.z.RestEasyDefaultCharsetInterceptor </param-value> </context-param>
Now, I don't fully understand the entire mechanism yet, but you should also be able to fix the problem on the client side by specifying the charset parameter to the content-type.

Glever
  • 31
  • 3
0

This is not about resteasy or jax-rs mate.

Check this post

There are several things you may want to look into:

  1. If the data is from DB, then you need to make sure data in DB it is encoded correctly.
  2. Your JVM environment is encoding using utf8
  3. It could be an issue of IDE, because IDE and your tomcat might running on different configurations.
Community
  • 1
  • 1
Xiangyu
  • 222
  • 2
  • 8
0

I created a webfilter. I don't know if it is the best way to do it, but for sure it does fix the issue.

@WebFilter(filterName = "CharacterEncodingFilter", urlPatterns = {"/api/*"})
public class CharacterEncodingFilter implements Filter {

public CharacterEncodingFilter() {
}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException 
{      
    // setting the charset
    response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
    chain.doFilter(request, response);
}

}

Just change the urlPatterns so it can filter your Resteasy resources.

Renann
  • 552
  • 1
  • 7
  • 12
0

This works for me

@Produces(MediaType.APPLICATION_JSON+";charset=UTF-8")
luis martinez
  • 62
  • 1
  • 9
0

If the consumer of your API cannot trivially set the charset to UTF-8 (eg: using fetch and FormData), then RestEasy defaults to use US ASCII encoding. So if you are using non-ascii characters, their encoding get garbled.
What worked for me was to consider the input form param as a byte[] and do the String conversion using the utf-8 charset myself.

@FormParam("data")
private byte[] data;
bobby
  • 2,629
  • 5
  • 30
  • 56