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

BeR*_*ive 2 java swing future swingworker

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

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

SwingWorker(后台线程)

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

    return orderClient.placeOrder( ... );
}
Run Code Online (Sandbox Code Playgroud)

主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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

该行发生错误:

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

正如Java声称的那样,永远不会抛出异常.

exception PlaceOrderException is never thrown in body of corresponding try statement
Run Code Online (Sandbox Code Playgroud)

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

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

Ale*_*yak 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);
    }
Run Code Online (Sandbox Code Playgroud)