Como obter parâmetros de formulário no filtro de solicitação

Estou tentando obter os parâmetros de formulário de uma solicitação em um filtro de solicitação:

@Override
public ContainerRequest filter(final ContainerRequest request) {

    final Form formParameters = request.getFormParameters();

    //logic

    return request;
}

No entanto, a forma sempre parece estar vazia. oHttpRequestContext.getFormParameters() documentação diz:

Obtenha os parâmetros de formulário da entidade de solicitação.

Este método irá assegurar que a entidade requisitada seja armazenada em buffer, de forma que possa ser consumida pela aplicação.

Retorna: os parâmetros de formulário, se houver uma entidade de solicitação e o tipo de conteúdo for "application / x-www-form-urlencoded", caso contrário, uma instância que não contenha parâmetros será retornada.

Meu recurso é anotado com@Consumes("application/x-www-form-urlencoded"), embora não tenha sido correspondido até depois do filtro de solicitação - é por isso que isso não está funcionando?

Eu tentei fazer algumas pesquisas, mas não consegui encontrar nenhuma evidência conclusiva sobre se isso é possível. Houveesta discussão de 4 anos de idade, no qual Paul Sandoz diz:

Se você estiver trabalhando em filtros Jersey ou com oHttpRequestContext você pode obter os parâmetros de formulário da seguinte maneira: [link quebrado para Jersey 1.1.1HttpRequestContext.getFormParameters]

Eu também acheiesta discussão de 3 anos de idade sobre como obter campos de formulário multipart / form-data em um filtro de solicitação. Nele, Paul Sandoz usa o seguinte código:

// Buffer
InputStream in = request.getEntityInputStream();
if (in.getClass() != ByteArrayInputStream.class) {
    // Buffer input
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    try {
        ReaderWriter.writeTo(in, baos);
    } catch (IOException ex) {
        throw new ContainerException(ex);
    }
    in = new ByteArrayInputStream(baos.toByteArray());
    request.setEntityInputStream(in);
}

// Read entity
FormDataMultiPart multiPart = request.getEntity(FormDataMultiPart.class);

Eu tentei emular essa abordagem paraForm em vez disso, mas o resultado derequest.getEntityInputStream() é sempre um fluxo vazio. E olhandoa fonte degetFormParameters, esse método está, de fato, fazendo a mesma coisa já:

@Override
public Form getFormParameters() {
    if (MediaTypes.typeEquals(MediaType.APPLICATION_FORM_URLENCODED_TYPE, getMediaType())) {
        InputStream in = getEntityInputStream();
        if (in.getClass() != ByteArrayInputStream.class) {
            // Buffer input
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            try {
                ReaderWriter.writeTo(in, byteArrayOutputStream);
            } catch (IOException e) {
                throw new IllegalArgumentException(e);
            }

            in = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
            setEntityInputStream(in);
        }

        ByteArrayInputStream byteArrayInputStream = (ByteArrayInputStream) in;
        Form f = getEntity(Form.class);
        byteArrayInputStream.reset();
        return f;
    } else {
        return new Form();
    }
}

Eu não consigo descobrir o que está sugando o fluxo de entrada da entidade antes de chegar a ele. Algo em Jersey deve estar consumindo-o porque os parâmetros do formulário são posteriormente passados ​​para o método resource. O que estou fazendo errado aqui, ou isso é impossível (e por quê)?

EDITAR: Veja um exemplo de uma solicitação sendo enviada:

POST /test/post-stuff HTTP/1.1
Host: local.my.application.com:8443
Cache-Control: no-cache
Content-Type: application/x-www-form-urlencoded

form_param_1=foo&form_param_2=bar

Aqui está o (um tanto redundante)solicitação de registro:

INFO: 1 * Server in-bound request
1 > POST https://local.my.application.com:8443/test/post-stuff
1 > host: local.my.application.com:8443
1 > connection: keep-alive
1 > content-length: 33
1 > cache-control: no-cache
1 > origin: chrome-extension://fdmmgilgnpjigdojojpjoooidkmcomcm
1 > user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36
1 > content-type: application/x-www-form-urlencoded
1 > accept: */*
1 > accept-encoding: gzip,deflate,sdch
1 > accept-language: en-US,en;q=0.8
1 > cookie: [omitted]
1 > 

Aqui estão os cabeçalhos de resposta dessa solicitação, incluindo oRastreamento de Jersey:

Content-Type →application/json;charset=UTF-8
Date →Fri, 09 Aug 2013 18:00:17 GMT
Location →https://local.my.application.com:8443/test/post-stuff/
Server →Apache-Coyote/1.1
Transfer-Encoding →chunked
X-Jersey-Trace-000 →accept root resource classes: "/post-stuff"
X-Jersey-Trace-001 →match path "/post-stuff" -> "/post\-stuff(/.*)?", [...], "(/.*)?"
X-Jersey-Trace-002 →accept right hand path java.util.regex.Matcher[pattern=/post\-stuff(/.*)? region=0,11 lastmatch=/post-stuff]: "/post-stuff" -> "/post-stuff" : ""
X-Jersey-Trace-003 →accept resource: "post-stuff" -> @Path("/post-stuff") com.application.my.jersey.resource.TestResource@7612e9d2
X-Jersey-Trace-004 →match path "" -> ""
X-Jersey-Trace-005 →accept resource methods: "post-stuff", POST -> com.application.my.jersey.resource.TestResource@7612e9d2
X-Jersey-Trace-006 →matched resource method: public javax.ws.rs.core.Response com.application.my.jersey.resource.TestResource.execute(java.lang.String,java.lang.String)
X-Jersey-Trace-007 →matched message body reader: class com.sun.jersey.api.representation.Form, "application/x-www-form-urlencoded" -> com.sun.jersey.core.impl.provider.entity.FormProvider@b98df1f
X-Jersey-Trace-008 →matched message body writer: java.lang.String@f62, "application/json" -> com.sun.jersey.core.impl.provider.entity.StringProvider@1c5ddffa

Aqui está a configuração do servlet (sem problemas):

<servlet>
    <servlet-name>jersey</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>com.sun.jersey.config.property.packages</param-name>
        <param-value>com.application.my.jersey</param-value>
    </init-param>
    <init-param>
        <param-name>com.sun.jersey.spi.container.ResourceFilters</param-name>
        <param-value>com.application.my.jersey.MyFilterFactory</param-value>
    </init-param>
    <init-param>
        <param-name>com.sun.jersey.config.feature.Trace</param-name>
        <param-value>true</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

Aqui está o recurso de exemplo:

@Path("/post-stuff")
@Produces(MediaType.APPLICATION_JSON)
public final class TestResource {

    @POST
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    public Response execute(
            @FormParam("form_param_1") final String formParam1,
            @FormParam("form_param_2") final String formParam2
    ) {
        return Response.created(URI.create("/")).entity("{}").build();
    }
}

Eu estou usando Jersey 1.17.

Para os interessados, estou tentando fazer a validação dos meus próprios parâmetros, conforme descrito emJERSEY-351. Minha soluçãoAqui trabalhei para params de consulta, cookie e cabeçalho - os parâmetros de formulário estão esperando por mim.

questionAnswers(2)

yourAnswerToTheQuestion