Search code examples
javaloggingjbossresteasy

@FormParameter data becomes null after reading and setting the same data in ContainerRequestContext entityStream


I have implemented filter and I have called getEntityStream of ContainerRequestContext and set the exact value back by using setEntitystream. If i use this filter then @FormParameter data becomes null and if i don't use filter then everything will be fine (as I am not calling getEntityStream) and i have to use filter to capture request data.

Note: I am getting form params from MultivaluedMap formParams but not from @FormParameter.

Environment :- Rest Easy API with Jboss Wildfly 8 server.

            @Provider
            @Priority(Priorities.LOGGING)
            public class CustomLoggingFilter implements ContainerRequestFilter, ContainerResponseFilter{

                final static Logger log = Logger.getLogger(CustomLoggingFilter.class);

                @Context
                private ResourceInfo resourceInfo;

                @Override
                public void filter(ContainerRequestContext requestContext)
                        throws IOException {
                    MDC.put("start-time", String.valueOf(System.currentTimeMillis()));

                    String entityParameter = readEntityStream(requestContext);

                    log.info("Entity Parameter :"+entityParameter);
                }

                private String readEntityStream(ContainerRequestContext requestContext){
                    ByteArrayOutputStream outStream = new ByteArrayOutputStream();
                    final InputStream inputStream = requestContext.getEntityStream();
                    final StringBuilder builder = new StringBuilder();

                    int read=0;
                    final byte[] data = new byte[4096];
                    try {
                        while ((read = inputStream.read(data)) != -1) {
                            outStream.write(data, 0, read);
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                    byte[] requestEntity = outStream.toByteArray();
                    if (requestEntity.length == 0) {
                        builder.append("");
                    } else {
                        builder.append(new String(requestEntity));
                    }
                    requestContext.setEntityStream(new ByteArrayInputStream(requestEntity) );
                        return builder.toString();
                    }
                    return null;
                }
            }          



    class customResource
    {

    //// This code is not working
    @POST
    @Path("voiceCallBack")
    @ApiOperation(value = "Voice call back from Twilio")
    public void voiceCallback(@FormParam("param") String param)
    {
        log.info("param:" + param);
    }

    // This code is working

    @POST
    @Path("voiceCallBackMap")
    @ApiOperation(value = "Voice call back from Twilio")
    public void voiceCallbackMap(final MultivaluedMap<String, String> formParams)
    {
        String param = formParams.getFirst("param");
    }
}

please suggest me solution & Thanks in Advance.


Solution

  • I found during run time that instance of the entity stream (from http request) is of type org.apache.catalina.connector.CoyoteInputStream (I am using jboss-as-7.1.1.Final). But we are setting entity stream with the instance of java.io.ByteArrayInputStream. So Resteasy is unable to bind individual formparmeters.

    There are two solutions for this you can use any one of them :

    1. Use this approach How to read JBoss Resteasy's servlet request twice while maintaing @FormParam binding?
    2. Get form parameters like this:
         @POST
         @Path("voiceCallBackMap")
         @ApiOperation(value = "Voice call back from Twilio")
         public void voiceCallbackMap(final MultivaluedMap<String, String> formParams)
    
         {
             String param = formParams.getFirst("param");
         }