Java NoHttpResponseException作为运行时异常抛出,即使是已检查的异常

Java NoHttpResponseException作为运行时异常抛出,即使是已检查的异常,java,exception,apache-httpclient-4.x,amazon-sqs,Java,Exception,Apache Httpclient 4.x,Amazon Sqs,我遇到了一个奇怪的问题,org.apache.http.NoHttpResponseException作为未检查的异常抛出,即使它是已检查的异常,因为它扩展了java.io.IOException。。。从下面发布的stacktrace可以看出,我得到了一个异常,应该在编译时作为未检查的运行时异常进行检查 我得到的异常的堆栈跟踪如下(我的类在包中:com.example.staticsite): 在我的代码中引发异常的方法是: public class SqsReceiverImpl implem

我遇到了一个奇怪的问题,
org.apache.http.NoHttpResponseException
作为未检查的异常抛出,即使它是已检查的异常,因为它扩展了
java.io.IOException
。。。从下面发布的stacktrace可以看出,我得到了一个异常,应该在编译时作为未检查的运行时异常进行检查

我得到的异常的堆栈跟踪如下(我的类在包中:
com.example.staticsite
):

在我的代码中引发异常的方法是:

public class SqsReceiverImpl implements SqsReceiver {
    private AmazonSQS client;
    private String queueUrl;

    @Inject
    public SqsReceiverImpl(AmazonSQS client,@Assisted String queueUrl) {        
        this.client = client;
        this.queueUrl = queueUrl;
    }

    public List<String> receiveReceipt() throws SqsReceiverException {
        if(queueUrl == null)
            throw new SqsReceiverException(SqsReceiverException.MESSAGE_NO_QUEURURL);
        ReceiveMessageRequest request = new ReceiveMessageRequest();
        request.setMaxNumberOfMessages(10);
        request.setQueueUrl(queueUrl);
        request.setWaitTimeSeconds(20);
    
        ReceiveMessageResult results = null;
        try {
            results = client.receiveMessage(request);
        }
        catch(OverLimitException oe){
            throw new SqsReceiverException("OverLimitException thrown");
        }
        catch(AmazonServiceException oe){
            throw new SqsReceiverException("AmazonServiceException thrown");
        }
        catch(AmazonClientException oe){
            throw new SqsReceiverException("AmazonClientException thrown");
        } 
pom文件依赖项声明如下:

public class SqsReceiverException extends Exception{

    public SqsReceiverException(String messageNoQueururl) {
        super(messageNoQueururl);
    }
    public static final String MESSAGE_NO_QUEURURL = "Queue url not found. Se the queue url";
}
  <dependencies>
      <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
       <version>4.11</version>
       <scope>test</scope>
    </dependency>
    <dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>
<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-java-sdk-sqs</artifactId>
    <version>1.10.12</version>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>1.10.19</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>com.google.inject</groupId>
    <artifactId>guice</artifactId>
    <version>4.0</version>
</dependency>
<dependency>
  <groupId>com.google.inject.extensions</groupId>
  <artifactId>guice-assistedinject</artifactId>
  <version>4.0</version>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.4</version>
</dependency>
</dependencies>
lastReset
应该对抛出的异常负责,我不明白的是,异常日志是如何记录的
org.apache.http.NoHttpResponseException

stacktrace前的行始终为:

2017-09-15 07:41:39 INFO  AmazonHttpClient:496 - Unable to execute HTTP request: sqs.eu-west-1.amazonaws.com failed to respond

我猜你是堆栈跟踪格式化的受害者

我认为你把
lastReset()
指为罪魁祸首是对的。这就是您看到的
抛出IOException
从堆栈跟踪中消失的地方。此方法显然抛出了一个
AmazonClientException
(运行时异常),其中包含原始的
NoHttpResponseException

您可以使用如下代码段来模拟:

throw new AmazonClientException("Oh no!", new NoHttpResponseException("The AWS server doesn't like you"));
如果我将这行代码插入到现有的Java应用程序中(本例中为Spring Boot),这就是我在Eclipse控制台中看到的:

没有出现AmazonClientexException的迹象!直到,我向右滚动:

亚马逊决定在未经检查的例外情况下使用,并且

因此,他们确实(我很确定)将您的
IOException
包装在运行时异常中,通过“对您处理的错误进行细粒度控制”来“帮助”您,尽管这并不总是显而易见的

尽管如此,我可能是错的。如果我是对的,我希望在堆栈顶部看到您的自定义
SqsReceiverException
,因为您确实捕获了
AmazonClientException

在堆栈跟踪之前,如果没有标准输出的最后几行,很难确定。如果我不合适,你能把它们寄出去吗

更新

更新问题时使用的行(
AmazonHttpClient:496
)是打印堆栈跟踪的行。当您将一个
Throwable
传递到
log.info()
时,将打印堆栈跟踪。在打包并重新抛出异常之前,正在记录此跟踪

所以这一点似乎被“吞下”:

我无法与丢失的
SqsReceiverException
通话。但是我不认为
DefaultRequestDirector.execute()
的签名是假的,我也不认为我们正在处理一个编译器错误

也许您可以将
oe.printStackTrace()
添加到
catch(AmazonClientException oe)
块中

最后,我建议使用调试器逐步完成这一过程。要模拟生产问题,只需将断点设置为
DefaultHttpResponseParser:140
,并在执行此行后,将
i
更改为-1。然后逐步向上返回堆栈,一直返回到代码


我还在
AmazonHttpClient:971
上设置了一个断点,这样我就可以更改
重试次数
,避免循环四次。

您使用的AmazonQS客户端是什么风格的?异步版本确实很奇怪,因为异常类型也没有改变,而且它实际上只是一个IOException。它在客户端到amazon端运行?它在amazon EC2实例上运行,amazon Red hat linux AMI“并且最后一次重置应该对引发的异常负责,我不明白的是,记录的异常怎么可能是org.apache.http.NoHttpResponseException”>>您能详细说明一下吗?NoHttpResponseException是IOException,因此它被捕获并记录…异常消息:
org.apache.http.NoHttpResponseException:sqs.eu-west-1.amazonaws.com未能响应
应该是
目标服务器未能响应代码中的
。该消息是否在问题中更新?用始终在stacktrace之前的行更新了结尾处的问题,在stacktrace之前或之后没有其他相关行。我在日志文件中根本没有
SqsReceiverException
。这是最奇怪的事情。@aleroot谢谢你更新这个问题。我已经相应地更新了我的答案。
2017-09-15 07:41:39 INFO  AmazonHttpClient:496 - Unable to execute HTTP request: sqs.eu-west-1.amazonaws.com failed to respond
throw new AmazonClientException("Oh no!", new NoHttpResponseException("The AWS server doesn't like you"));
com.amazonaws.AmazonClientException: Unable to execute HTTP request: sqs.us-east-1.amazonaws.com failed to respond
    at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:500)
    at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:310)
    at com.amazonaws.services.sqs.AmazonSQSClient.invoke(AmazonSQSClient.java:2419)
    at com.amazonaws.services.sqs.AmazonSQSClient.receiveMessage(AmazonSQSClient.java:1130)
    at httptest.Main.main(Main.java:32)
Caused by: