Here's a way to read the form entity without relying on implementation specific classes, i.e. it will work with both Jersey (v2) or CXF (v3).
@Provider
public class AFilter implements ContainerRequestFilter {
@Context
private Providers providers;
@Override
public void filter(ContainerRequestContext request) throws IOException {
if (!request.hasEntity() || !MediaTypes.typeEqual(APPLICATION_FORM_URLENCODED_TYPE, request.getMediaType())) {
// if not a form ...
return;
}
ByteArrayInputStream resettableIS = toResettableStream(request.getEntityStream());
Form form = providers.getMessageBodyReader(Form.class, Form.class, new Annotation[0], APPLICATION_FORM_URLENCODED_TYPE)
.readFrom(Form.class, Form.class, new Annotation[0], APPLICATION_FORM_URLENCODED_TYPE, null, resettableIS);
// do something with Form
resettableIS.reset();
request.setEntityStream(resettableIS);
}
@Nonnull
private ByteArrayInputStream toResettableStream(InputStream entityStream) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = entityStream.read(buffer)) > -1) {
baos.write(buffer, 0, len);
}
baos.flush();
return new ByteArrayInputStream(baos.toByteArray());
}
}
This works well and has the benefit of using only JAX-RS API thus is is portable.
Note however that CXF 2.x uses JAX-RS API 2.0-m10 which do not have the Form
class yet. In this case one can simply replace Form.class
by the MultivaluedMap.class
at the price of some unchecked / raw type warnings.