The Source for Java Technology Collaboration

Home » java.net Forums » GlassFish » GlassFish

Thread: Exception Interceptor

Welcome, Guest Help
Login Login
Guest Settings Guest Settings
Reply to this Thread Reply to this Thread Search Forum Search Forum Back to Thread List Back to Thread List

Permlink Replies: 12 - Last Post: Jun 29, 2009 12:59 PM by: culli
culli

Posts: 39
Exception Interceptor
Posted: Jun 25, 2009 8:25 AM
  Click to reply to this thread Reply

I have a swing client that I'm trying to keep from deploying the hibernate jars with. There is a problem when hibernate exceptions happen on the server and come across to the client, it cannot deserialize them because the right classes aren't available. So to try to work around that I created an interceptor like the code below which converts the an exception's stack trace to text and makes it into a ServerSideException. The problem is all I get is "transaction marked for rollback" and never see my ServerSideException on the client. If I step through the code, I can see that the Hibernate exception (such as an InvalidValue) is occurring and getting converted to a ServerSideException. Then on the client the exception chain is: ExecutionException->EJBException->RemoteException with the message: "Transaction aborted; nested exception is: javax.transaction.RollbackException: Transaction marked for rollback." I have tried with and without the @ApplicationException, and with and without the rollback=false on it.


Is there a way to insulate the client this way?

Edit: Glassfish 2.1 (9.1.1) (build b60e-fcs)

Edit: I think this is a bug in Glassfish. EJB 3.0 spec says:
12.3.2 Exceptions
Business method interceptor methods may throw runtime exceptions or application exceptions that are
allowed in the throws clause of the business method.
AroundInvoke methods are allowed to catch and suppress exceptions and recover by calling proceed().
AroundInvoke methods are allowed to throw runtime exceptions or any checked exceptions
that the business method allows within its throws clause.

ejb-jar.xml:
<ejb-jar xmlns = "http://java.sun.com/xml/ns/javaee" 
         version = "3.0" 
         xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd">
    <interceptors>
        <interceptor>
            <interceptor-class>
                com.foo.ExceptionHandler
            </interceptor-class>
        </interceptor>
    </interceptors>
 
    <assembly-descriptor>
        <interceptor-binding>
            <ejb-name>*</ejb-name>
            <interceptor-class>com.foo.ExceptionHandler</interceptor-class>
        </interceptor-binding>
    </assembly-descriptor>
</ejb-jar>


ExceptionHandler.java:
package com.foo;
 
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
import javax.persistence.PersistenceException;
 
public class ExceptionHandler {
    @AroundInvoke
    public Object handleException(InvocationContext ctx) throws Exception {
        try {
            return ctx.proceed();
        } catch (Throwable t) {
            t.printStackTrace();
            throw new ServerSideException(t);
        }
    }
}


ServerSideException.java:
package com.foo;
 
import javax.ejb.ApplicationException;
 
@ApplicationException(rollback=true)
public class ServerSideException extends Exception {
    private String errorClass;
    private String stackTraceString;
 
    public ServerSideException(Throwable t) {
        super(t.getMessage());
        this.errorClass = t.getClass().getName();
        StringBuilder builder = new StringBuilder();
        for (StackTraceElement element : t.getStackTrace()) {
            builder.append(element.toString());
            builder.append("\n");
        }
        this.stackTraceString = builder.toString();
    }
 
    public String getErrorClass() {
        return errorClass;
    }
 
    public String getStackTraceString() {
        return stackTraceString;
    }
}


Message was edited by: culli

Message was edited by: culli

ksak

Posts: 455
Re: Exception Interceptor
Posted: Jun 25, 2009 2:43 PM   in response to: culli
  Click to reply to this thread Reply

It sounds as if the underlying persistence manager is marking the transaction for rollback. The container will still attempt to commit any transaction it started, and if the rollback fails a system exception will be thrown to the client. If you want to protect against this case you could perform the transactional work in a bean-managed transaction.

culli

Posts: 39
Re: Exception Interceptor
Posted: Jun 26, 2009 8:12 AM   in response to: ksak
  Click to reply to this thread Reply

Maybe I'm missing something, but the point of what I'm doing is that every remote call that throws an exception should change that exception into something that is more friendly to the client, and that can be deserialized consistently, without 100 gigabytes of dependencies. I don't want to code every bean with a bean managed transaction. It should work the way I have set it up according to the spec, so it's a bug in GlassFish in my opinion.

twk12345

Posts: 1
Re: Exception Interceptor
Posted: Jun 27, 2009 10:08 AM   in response to: culli
  Click to reply to this thread Reply

Shooting from the hip here but -

I believe the exception you're catching has 1 or more nested exceptions inside of it. To get to these you'll need to call t.getcause() in ServerSideException's constructor and fillin the stack traces from each nestedexception. It's like traversing thru a linked list.

Throwable getCause()
Returns the cause of this throwable or null if the cause is nonexistent or unknown.

culli

Posts: 39
Re: Exception Interceptor
Posted: Jun 27, 2009 5:06 PM   in response to: twk12345
  Click to reply to this thread Reply

Yes I have an unwrapper method that does that. That's not the point of my post though, so for simplicty I left it out.

Is there anyone that can address the point about the rollbacks that probably should not be happening?

Marina Vatkina
Re: Exception Interceptor
Posted: Jun 29, 2009 10:38 AM   in response to: culli
  Click to reply to this thread Reply

Can you check if there is no exception in the server.log from commit/rollback?
If there is, it's not clear which exception should be propagated to the client
- the rollback exception or the application exception.

thanks,
-marina

glassfish@javadesktop.org wrote:
> Yes I have an unwrapper method that does that. That's not the point of my post though, so for simplicty I left it out.
>
> Is there anyone that can address the point about the rollbacks that probably should not be happening?
> [Message sent by forum member 'culli' (culli)]
>
> http://forums.java.net/jive/thread.jspa?messageID=353286
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@glassfish.dev.java.net
> For additional commands, e-mail: users-help@glassfish.dev.java.net
>


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@glassfish.dev.java.net
For additional commands, e-mail: users-help@glassfish.dev.java.net


culli

Posts: 39
Re: Exception Interceptor
Posted: Jun 29, 2009 11:22 AM   in response to: Marina Vatkina
  Click to reply to this thread Reply

I can verify that no other exception is showing in the log except the "marked for rollback". I turned everything up to Trace in the logging at one point to try to get more detail, but after a lot of looking I didn't find anything that helped.

If I turn off the @AroundInvoke interceptor, the real exceptions come through just fine, such as Hibernate Validator's InvalidStateException. With the interceptor catching that and throwing my ServerSideException, then only the rollback exception comes through.

Marina Vatkina
Re: Exception Interceptor
Posted: Jun 29, 2009 11:25 AM   in response to: culli
  Click to reply to this thread Reply

Is transaction marked for rollback at the time you catch the exception?

thanks,
-marina

glassfish@javadesktop.org wrote:
> I can verify that no other exception is showing in the log except the "marked for rollback". I turned everything up to Trace in the logging at one point to try to get more detail, but after a lot of looking I didn't find anything that helped.
>
> If I turn off the @AroundInvoke interceptor, the real exceptions come through just fine, such as Hibernate Validator's InvalidStateException. With the interceptor catching that and throwing my ServerSideException, then only the rollback exception comes through.
> [Message sent by forum member 'culli' (culli)]
>
> http://forums.java.net/jive/thread.jspa?messageID=353453
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@glassfish.dev.java.net
> For additional commands, e-mail: users-help@glassfish.dev.java.net
>


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@glassfish.dev.java.net
For additional commands, e-mail: users-help@glassfish.dev.java.net


culli

Posts: 39
Re: Exception Interceptor
Posted: Jun 29, 2009 12:12 PM   in response to: Marina Vatkina
  Click to reply to this thread Reply

How do I find that out inside the @AroundInvoke method (handleException in my case)? I have the InvocationContext, but I'm not seeing how to get information about the transaction from that level.

Marina Vatkina
Re: Exception Interceptor
Posted: Jun 29, 2009 12:20 PM   in response to: culli
  Click to reply to this thread Reply

Good question. Can you try looking up the TransactionSynchronizationRegistry?

thanks,
-marina

glassfish@javadesktop.org wrote:
> How do I find that out inside the @AroundInvoke method (handleException in my case)? I have the InvocationContext, but I'm not seeing how to get information about the transaction from that level.
> [Message sent by forum member 'culli' (culli)]
>
> http://forums.java.net/jive/thread.jspa?messageID=353466
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@glassfish.dev.java.net
> For additional commands, e-mail: users-help@glassfish.dev.java.net
>


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@glassfish.dev.java.net
For additional commands, e-mail: users-help@glassfish.dev.java.net


culli

Posts: 39
Re: Exception Interceptor
Posted: Jun 29, 2009 12:59 PM   in response to: Marina Vatkina
  Click to reply to this thread Reply

Awesome! session.setRollbackOnly() in my catch blocks solves this. Thanks!

culli

Posts: 39
Re: Exception Interceptor
Posted: Jun 29, 2009 12:23 PM   in response to: culli
  Click to reply to this thread Reply

Nevermind, I figured that part out:
@Resource
private javax.ejb.SessionContext session;


Which shows that session.getRollbackOnly() == false.

Marina Vatkina
Re: Exception Interceptor
Posted: Jun 29, 2009 12:42 PM   in response to: culli
  Click to reply to this thread Reply

Then the commit/rollback fails and that what the client is told about. I added
logging of the exception in beforeCompletion but I'm not sure if it made it to
v2.1, so try setting Hibernate log levels to finest to see the actual cause.
There is also an open bug to propagate the exception from the beforeCompletion
to the client that should be fixed in v3.

Check if setting rollback only solves your problem.

HTH,
-marina

glassfish@javadesktop.org wrote:
> Nevermind, I figured that part out:
> @Resource
> private javax.ejb.SessionContext session;
>
>
> Which shows that session.getRollbackOnly() == false.
> [Message sent by forum member 'culli' (culli)]
>
> http://forums.java.net/jive/thread.jspa?messageID=353469
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@glassfish.dev.java.net
> For additional commands, e-mail: users-help@glassfish.dev.java.net
>


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@glassfish.dev.java.net
For additional commands, e-mail: users-help@glassfish.dev.java.net





 XML java.net RSS