处理Web服务中的空指针异常

时间:2011-08-12 14:49:59

标签: java web-services nullpointerexception

我正在编写一个web服务,在webservice中逐个读取一堆记录,处理它们并将它们存储到数据库中。

如果记录中缺少某个字段,则会创建一个包含缺失信息的错误对象,并将其作为响应发回。

尽管我已经完成了所有空检查,但可能会出现一些空指针异常,因为我无法控制进入服务的记录。

如果说是第45条记录,则会发生NPE,服务中断。而不是这样,我希望服务继续并处理下一条记录。

所以,如果我在这种情况下捕获NPE或者有任何更好的替代方案,是否可以。我已经读过,不推荐捕捉NPE,但不确定我是否必须违反规则。

4 个答案:

答案 0 :(得分:2)

如果无法使用null检查停止NullPointerException,那么唯一的选择是捕获它。但是,我无法想到空检查不能阻止NullPointerException

的实例

答案 1 :(得分:1)

如果需要空指针,我发现捕获NullPointerException没问题。我认为它比500亿(如果不是零)更清洁......

答案 2 :(得分:0)

如果由无效记录导致NPE,并且您无法控制记录,那么您的逻辑应该在处理之前尝试验证记录。执行此操作的最佳方法是循环遍历每条记录,检查有效格式,跟踪无效行。验证后,如果存在任何无效行,您可以将它们以有意义的格式报告回UI。否则继续进行实际处理。

List<String> invalidRows = new ArrayList<String>();

for each row {
    if (row is missing x) {
        invalidRows.add("Record " + rowNumber + " is missing X");
    }
    if (row is missing y) {
        invalidRows.add("Record " + rowNumber + " is missing Y");
    }
}

if (invalidRows.isEmpty()) {
    //process
}
else {
    format and return error message using data collected
}

(请注意,使用List<String>是一个常规示例 - 您应该以对您的情况最有意义的方式存储并格式化此信息。)

此方法的替代方法是在同一循环中进行验证和处理,跟踪无效行并处理有效行。最后,用户界面可以报告有多少成功,哪些失败。

此外,可以将Web服务包装在最后防御中,以使未处理的异常更容易被客户端UI管理和使用,或者至少更容易阅读:

@WebMethod(operationName = "myMethod")
public String myMethod() {
    try {
        //logic
        return "done";
    }
    catch (Throwable error) {
        //returns formatted String representing error - UI should check for this
        return MyExceptionFormatter.formatUnhandled(error); 
    }
}

您的自定义格式将汇集一个更有意义的String,表示异常,可能是XML格式。这完全取决于客户端UI的期望。

答案 3 :(得分:0)

虽然你不应该一般地抓住NPE,但是如果你知道你做了什么就可以接受它们。你应该避免捕获NPE而不是像

那样在复杂的链中重新抛出它们
try {
    a.getB().getC().getD();
} catch (NullPointerException e) {
    // only the stack trace indicates where the exception occured
}

让我们说在上面的示例中,您希望NPE被抛到getD()上,尝试将您的代码重构为

C c = a.getB().getC();
try {
    c.getD();
} catch (NullPointerException e) {
    // you know that either `c` is null or that the exception was thrown in `getD()`
}

我的2美分......如果你知道NPE可以在WS请求中发生,你应该相应地保护它:

if (c != null) {
    // do something (getD() can still throw a NPW)
    c.getD();
} else {
}