将war部署到AWS时,HttpServletRequest的主体为空

时间:2013-12-06 05:16:48

标签: java maven amazon-web-services elastic-beanstalk google-glass

我在本地计算机上运行时发现代码行为不一致。 AWS Elastic Beanstalk。该代码将接收Google Glass的通知。

代码段如下所示:

public class NotifyServlet extends HttpServlet implements WeiboConstants{
    private static final Logger LOG = Logger.getLogger(NotifyServlet.class.getSimpleName());

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        // Respond with OK and status 200 in a timely fashion to prevent redelivery
        response.setContentType("text/html");
        Writer writer = response.getWriter();
        writer.append("OK");
        writer.close();

        LOG.info("perpare reading");

        BufferedReader notificationReader =
            new BufferedReader(new InputStreamReader(request.getInputStream()));
        String notificationString = "";

        LOG.info("begin reading ");
        // Count the lines as a very basic way to prevent Denial of Service attacks
        int lines = 0;
        while (notificationReader.ready()) {
            LOG.info("reading");
            notificationString += notificationReader.readLine();
            lines++;

            // No notification would ever be this long. Something is very wrong.
            if (lines > 1000) {
                throw new IOException("Attempted to parse notification payload that was unexpectedly long.");
            }
        }

        LOG.info("got raw notification " + notificationString);

        JsonFactory jsonFactory = new JacksonFactory();

Google的服务器将执行POST,这是单独注册的:

Subscription subscription = MirrorClient.insertSubscription(credential, "https://mirrornotifications.appspot.com/forward?url=http://foo.elasticbeanstalk.com/notify", userId,
                        "timeline");

在我的本地计算机上进行测试时,我运行 mvn jetty:运行并将上述代码中的foo更改为my ip address:8080

我可以收到谷歌的通知:

{“collection”:“timeline”,“itemId”:“5cbf8f54-822d-4a8e-9a9f-508687bbb9e2”,“operation”:“INSERT”,“userToken”:“105242333117256730066”,“userActions”:[{ “type”:“LAUNCH”}]}

但是当我打包战争(mvn war:war)并部署到AWS时,我可以从日志中看到它已成功注册到Google,我从Google获得 POST 在/ notify上,但似乎正文是空的,如下面的日志所示:

Dec 06, 2013 5:01:55 AM com.google.glassware.NotifyServlet doPost
INFO: perpare reading
Dec 06, 2013 5:01:55 AM com.google.glassware.NotifyServlet doPost
INFO: begin reading 
Dec 06, 2013 5:01:55 AM com.google.glassware.NotifyServlet doPost
INFO: got raw notification 
Dec 06, 2013 5:01:55 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [notify] in context with path [] threw exception
java.lang.IllegalArgumentException: no JSON input found

如何进一步调试?

更新

我将相同的war文件部署到运行Jetty而不是Tomcat的服务器上,它运行正常,似乎是Tomcat特有的问题?

1 个答案:

答案 0 :(得分:0)

要进一步调试,您可以尝试将通知直接发布到http://foo.elasticbeanstalk.com/notify

如果这导致相同的行为,我会仔细查看BufferedReader.ready()作为循环条件。

ready()是一种非阻塞方法。这意味着如果由于某种原因BufferedReader的实例没有准备好立即返回数据,那么该方法将立即返回false并且将完全跳过循环。

然后调试的下一步是注释ready()并直接阻止readLine()以确认您的servlet收到有效负载。

<强>更新

看来Jetty和Tomcat确实有不同的BufferedReader.ready()实现。

以下是我在进一步研究后发现的相关Stack Overflow问题:BufferedReader ready method