6

Is it possible to receive form parameter as byte array with Jersey?

I tried the following:

@Path("/someMethod")
@POST
@Produces(MediaType.TEXT_HTML)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public String someMethod(@FormParam("someParam") byte[] someParam)
{
    return "";
}

But got this error:

SEVERE: The following errors and warnings have been detected with resource and/or provider classes:
  SEVERE: Missing dependency for method public java.lang.String SomeClass.someMethod(byte[]) at parameter at index 0
  SEVERE: Missing dependency for method public java.lang.String SomeClass.someMethod(byte[]) at parameter at index 0
  SEVERE: Method, public java.lang.String SomeClass.someMethod(byte[]), annotated with POST of resource, class SomeClass, is not recognized as valid resource method.

If I change byte[] to String, everything works correctly.

The reason I need to receive data as byte[] and not as String is because data may be encoded using different charsets. It depends on the HTML document that submits data and I need to decode data correctly on server side (encoding charset is submitted in a separate parameter).

So, if I can receive data as byte[], it will solve my problem. Any other solutions are welcome as well.

Thank you!

Dima L.
  • 3,443
  • 33
  • 30
  • Wouldn't `MediaType.APPLICATION_FORM_URLENCODED` imply that it's %-encoded, so you could just use a String? I'm kind of guessing here, but if it really is raw bytes, maybe you should add @Consumes(MediaType.TEXT_PLAIN) or some other MIME type that represents raw binary data. – Tyler Jun 08 '11 at 17:18
  • Yes, it's %-encoded, and it's ok. I just post data from HTML FORM. Yes, I can use a String, but what happens is that Jersey incorrectly creates string containing special characters because Jersey needs to know charset and I post charset in a separate paramater. That's why I want to get data as byte[] and not as String, so I can correctly create String using correct charset. – Dima L. Jun 08 '11 at 18:43
  • Okay yeah, I think I misunderstood the question the first time I read it. Maybe you can dig through the Jersey source and find where it actually %-decodes and converts to a String... I wonder if Jersey is making some incorrect assumptions somewhere. Another possibility would be to consume the entire input as a `byte[]` (just leave off the `@FormParam`) and then parse it yourself. – Tyler Jun 08 '11 at 18:57

2 Answers2

2

If Jersey conforms to JAX-RS spec then the parameter may be

  1. A primitive type
  2. Have a constructor that accepts a single String argument
  3. Have a static method named valueOf that accepts a single String argument (see, for example, Integer.valueOf(String))
  4. List, Set or SortedSet, where T satisfies 2 or 3 above. The resulting collection is read-only.

as it is actually defined in the Jersey API.

If you want to use @FormParam the best you might be able to do define a ByteArray -class that handles the errors caused by the String conversion and use it as the parameter type.

Aleksi Yrttiaho
  • 8,266
  • 29
  • 36
  • 1
    The problem with String is that when I receive parameter as String, special characters get replaced by ?, so they are already lost... – Dima L. Jun 08 '11 at 19:28
  • 3
    I plowed through the jersey code and noticed that it contains `ByteArrayProvider` that consumes and produces `MediaType.APPLICATION_OCTET_STREAM` and supports `byte[].class`. Might be worth a shot? – Aleksi Yrttiaho Jun 08 '11 at 19:40
1

Thank you for your answers! I finally found a solution... Now that I see a solution, I understand that I didn't describe my problem well enough and it lead you to a different direction...

The problem was that I submit form data to the server from many different pages which use different encodings. When page uses utf-8 encoding, everything worked correctly but when page uses different encoding, special characters got lost.

The solution was to add accept-charset="utf-8" to the <FORM> html element, which caused browser to always encode form data to utf-8 encoding, which solved encoding problem on the server side.

Thank you!

Dima L.
  • 3,443
  • 33
  • 30