I am aware of the use of the @FormParam annotation on method parameters, but I think you should be able to have objects completely populated from the form contents.
Assume class "User" is defined like so:
class User {
public User() { }
String name;
String password;
// getters and setters go here
}
Now say your client will be submitting something like this:
POST /users HTTP/1.1 Content-type: application/x-www-form-urlencoded .. other headers .. name=jeff&password=qweqqeqwe
Now you should be able to declare a resource method like this:
@PATH("/users") @POST @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public Response post(user) { // code goes about its business with a fully populated user object }
This is how I would expect things to work, from having dealt with numerous web application frameworks.
The exceptions I get when I try something like this suggest to me that it's trying to parse the form data as JAXB, which obviously isn't right.
Is there some magical way to do this that I just haven't found yet? Short of writing your own MessageBodyReader to deal with the raw form data. I've tried that, but which seems like more than should be required since Jersey already knows how to parse forms.
I feel like I must be missing something obvious.
Just for reference, here is the code I gimped up to make this sorta work. Yes, deprecated HttpUtils, I know. I didn't really feel like digging to find the non-deprecated proper replacement.
import java.io.IOException; import java.io.InputStream; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Type; import javax.ws.rs.*; import javax.ws.rs.core.*; import javax.ws.rs.ext.*; import java.util.*; import org.apache.commons.beanutils.*; import javax.servlet.http.HttpUtils; @Provider @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public class FormReader implements MessageBodyReader { public boolean isReadable(Class arg0, Type arg1, Annotation[] arg2) { return true; } public Object readFrom(Class arg0, Type arg1, Annotation[] arg2, MediaType arg3, MultivaluedMap arg4, final InputStream arg5) throws IOException, WebApplicationException { try { Object bean = arg0.newInstance(); Object contentLength = arg4.getFirst("Content-Length"); int length = Integer.parseInt( String.valueOf(contentLength)); javax.servlet.ServletInputStream sin = new javax.servlet.ServletInputStream() { @Override public int read() throws IOException { return arg5.read(); } }; Map badIdea = HttpUtils.parsePostData(length, sin); BeanUtils.populate(bean, badIdea); return bean; } catch(InstantiationException e) { throw new WebApplicationException(e); } catch (IllegalAccessException e) { throw new WebApplicationException(e); } catch (InvocationTargetException e) { throw new WebApplicationException(e); } } }