如何捕捉Future的特定抛出异常?

时间:2012-11-29 22:48:59

标签: java swing swingworker future

我最近继承了一些遗留代码,这些代码大量使用内部类来实现线程。这些内部类使当前的JFrame代码单片化,因此我正在重新分解代码以便使用SwingWorker类。

我的SwingWorker类对Web服务进行了大量的API调用,然后返回结果。由于这是异步的,这显然最好在线程内完成。目前,webservice的工作方式需要一些身份验证调用来验证请求。这些调用显然可以返回错误。我想要做的是,如果这些webservice调用未进行身份验证,则从SwingWorker内抛出自定义异常。使用标准Future模式,我有类似于以下内容的代码:

SwingWorker(后台主题)

@Override
protected String doInBackground() throws Exception {
    if (!authenticationClient.authenticate(userid)) {
        throw new PlaceOrderException("Failed to authenticate client");
    }

    return orderClient.placeOrder( ... );
}

主GUI(EDT主题)

// On the EDT
PlaceOrderWorker placeOrderWorker = new PlaceOrderWorker( ... ) {
    // This method is invoked when the worker is finished its task
    @Override
    protected void done(){
        try {
            String orderID = get();

            // Update some GUI elements using the orderID

        } catch(PlaceOrderException e) {
            JOptionPane.showMessageDialog(this, "Please review your order", e.getMessage(), JOptionPane.ERROR_MESSAGE, null);
        } catch (Exception e) {
            LOGGER.error("Error placing order", e);
        }
    }
}

错误发生在该行:

catch(PlaceOrderException e) {
    JOptionPane.showMessageDialog(this, "Please review your order", e.getMessage(), JOptionPane.ERROR_MESSAGE, null);
} 

因为Java声称从未抛出此异常。

exception PlaceOrderException is never thrown in body of corresponding try statement

现在我知道调用get将导致从线程中重新抛出异常 - 它可以抛出PlaceOrderException。我怎样才能抓住这个特定的例外?我将代码结构化的原因是,后台线程中可以抛出许多异常,我希望通过JDialog提示用户。我在主GUI类中声明done方法的原因是我需要在EDT线程中实例化JDialog s。这让我有了一些很好的解耦。

有人知道使用instanceof捕获此特定异常的方法吗?或者你能建议一个更好的模式使用吗?也许SwingWorker是错误的选择?

1 个答案:

答案 0 :(得分:6)

抓住ExecutionException,然后调查其原因:

    try {
        String orderID = get();

        // Update some GUI elements using the orderID

    } catch(ExecutionException e) {
        Throwable cause = e.getCause( );
        if ( cause instanceof PlaceOrderException )
        {
            JOptionPane.showMessageDialog(
              this,
              "Please review your order",
              cause.getMessage(),
              JOptionPane.ERROR_MESSAGE,
              null
            );
        }
        else
        {
          LOGGER.error("Error placing order", e);
        }
    } catch (Exception e) {
        LOGGER.error("Error placing order", e);
    }