简体   繁体   English

Java异常在被捕获后似乎被重新抛出

[英]Java Exception Seemingly Rethrown After Being Caught

I have run into a scenario I don't understand. 我遇到了一个我不了解的场景。 I have the following web service (using a bunch of pseudo code below). 我有以下Web服务(在下面使用一堆伪代码)。

In my transaction Manager class: 在我的事务管理器类中:

Response HandleRequest(List<Object> myStuff) throws RemoteException   
{ 
    Map<Object, String> problemMap = dataManager.saveMyStuff(myStuff)

    //Nothing here gets executed because HibernateSystemExeption was mysteriously (re)thrown
    log.warn("Step 5");
    if(problemMap.size() > 0)
    {
         //Put problem objects and error messages in response
         return response;
    }
}

Then in my DataManager class I have: 然后在我的DataManager类中,我有:

Map<Object, String> saveMyStuff(List<Object> mystuff) 
{
    Session sess = getSession();
    Transaction tx = sess.beginTransaction();
    boolean successful = true;

    Map<Object, String> problems = new HashMap<Object, String>();
    for(Object o : mystuff)
    {
        try
        {
            //Do some hibernate stuff here that throws a HibernateSystemException
        }
        catch(Exception e)
        {
            log.warn("Caught an exeption!", e);
            successful = false;
            log.warn("Step 1");
            problems.put(o, "Couldn't Store object");
            log.warn("Step 2");
        }
    }

    log.warn("Step 3");
    try
    {
        if(successful)
            tx.commit;
       else
            tx.rollback();
    }
    catch(Exception e)
    {
        log.warn("Another Exception caught!", e);
    }

    log.warn("Step 4");
    return problems;
}

What happens is the exception is successfully caught in the datamanager and I see it in the log file. 发生的情况是异常已成功捕获到数据管理器中,并且我在日志文件中看到了该异常。 The code proceeds to the return statement. 代码继续执行return语句。 BUT, when it returns from the datamanager I get the SAME exception in the Transaction Manager as if it was never caught by the datamanager and that exception is passed back to the user raw as a remote exception instead of the response. 但是,当它从数据管理器返回时,我在事务管理器中得到了SAME异常,就好像它从未被数据管理器捕获一样,并且该异常作为远程异常而不是响应被传递回了用户。 Nothing in the transaction manager after the call to saveMyStuff gets executed. 在调用saveMyStuff之后,事务管理器中什么也没有执行。 It's as if the exception remains on the stack until the method returns and then gets thrown again even though it's been handled in the datamanager. 就像异常一直保留在堆栈上,直到方法返回,然后再次抛出,即使已在数据管理器中对其进行了处理。 Has anyone seen anything like this before, or know what might be happening? 有没有人看过这样的东西,或者知道会发生什么?

EDIT: After a little more experimenting it seems the issue has to do with the fact that it is a HibernateSystemException. 编辑:经过更多的试验后,似乎该问题与它是HibernateSystemException的事实有关。 If I throw a generic Exception as a test the code works as I would expect. 如果我将通用异常作为测试抛出,则代码将按预期运行。 So what is it about the HibernateSystemException that causes this strange behavior? 那么,导致这种奇怪行为的HibernateSystemException是什么呢?

EDIT 2: I've done as suggested and wrapped the transaction commit/rollback in a try/catch. 编辑2:我已经按照建议完成,并将事务提交/回滚包装在try / catch中。 The exception still makes it back to the user. 异常仍然使它返回给用户。 I've also added debug print statements. 我还添加了调试打印语句。 And in the log I see steps 1-4 printed but not 5. I also do NOT see an exception being caught from the transaction commit/rollback block. 并且在日志中,我看到打印了步骤1-4,但没有打印出步骤5。我也没有看到从事务提交/回滚块中捕获到异常。

What you describe doesn't match the Java Exception Handling logic. 您描述的内容与Java异常处理逻辑不匹配。 Therefore, something different is happening, eg the exception may get thrown by tx.rollback(). 因此,正在发生一些不同的事情,例如tx.rollback()可能引发异常。 Try including also the rollback in a try-catch and handle the Exception there. 尝试将回滚也包含在try-catch中,并在那里处理Exception。

My previous answer was not right so there goes the new code. 我之前的答案不正确,因此有了新代码。 I suggest another try catch block to make sure there's no second exception thrown. 我建议使用另一个try catch块,以确保没有引发第二个异常。

Map<Object, String> saveMyStuff(List<Object> mystuff) 
{
    Session sess = getSession();
    Transaction tx = sess.beginTransaction();
    boolean successful = true;

    Map<Object, String> problems = new HashMap<Object, String>();
    for(Object o : mystuff)
    {
        try
        {
            //Do some hibernate stuff here that throws a HibernateSystemException
        }
        catch(Exception e)
        {
            log.warn("Caught an exeption!", e);
            successful = false;
            problems.put(o, "Couldn't Store object");
        }
    }



  try
        {
            if(successful)
               tx.commit;
             else
               tx.rollback();
        }
        catch(Exception e)
        {
            log.warn("Caught an exeption!", e);
            problems.put(o, "Couldn't Store object");
        }

    return problems;
}

Okay, I found the problem. 好的,我发现了问题。 Since I was calling getSession instead of openSession the session was being implicitly flushed when the method returns. 由于我调用的是getSession而不是openSession,因此方法返回时会隐式刷新会话。 The act of flushing the session caused the second exception to be thrown. 刷新会话的行为导致引发第二个异常。 I confirmed this by explicitly flushing the session before returning and surrounding that in a try/catch. 我通过在返回并围绕在try / catch中之前显式刷新会话来确认这一点。 That caught the exception but it was still thrown when the session was flushed again upon return. 那捕获了异常,但是当返回时再次刷新会话时,它仍然被抛出。 The ultimate fix was to call openSession AND surround the session flush with a try catch block. 最终的解决方法是调用openSession并用try catch块将会话冲洗包围起来。

DataManager class: DataManager类:

Map<Object, String> saveMyStuff(List<Object> mystuff) 
{
    Session sess = getSessionFactory.openSession();
    Transaction tx = sess.beginTransaction();
    boolean successful = true;

    Map<Object, String> problems = new HashMap<Object, String>();
    for(Object o : mystuff)
    {
        try
        {
            //Do some hibernate stuff here that throws a HibernateSystemException
        }
        catch(Exception e)
        {
            log.warn("Caught an exeption!", e);
            successful = false;
            problems.put(o, "Couldn't Store object");
        }
    }

    try
    {
       if(successful)
            tx.commit;
       else
            tx.rollback();

        sess.flush();
    }
    catch(Exception e)
    {
        log.warn("Another Exception caught!", e);
    }
    finally
    {
        sess.close();
    }

    return problems;
}

Thank you everyone for all your help! 谢谢大家的帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM