Well, it looks like I found a solution to my problem.

Problem: I have a stateless session EJB that throws a CreateException in 
ejbCreate(). In a clustered environment, I believe this should cause the client 
proxy to fail-over to another node. The current behavior in JBoss 3.2.6 is to 
throw the CreateException back to the client wrapped in an 
UndeclaredThrowableException. The client proxy just propogates the 
UndeclaredThrowableException all the way back up the call chain without failing 
over.

Solution: I wrote my own interceptor that catches CreateExceptions and throws 
back a GenericClusteringException. The client proxy will fail-over when it 
receives a GenericClusteringException with status set to not completed.

Here is the code to my interceptor, in case anyone is interested.

  | package com.itgssi.util.jboss.ejb;
  | 
  | import javax.ejb.CreateException;
  | 
  | import org.jboss.ejb.plugins.AbstractInterceptor;
  | import org.jboss.ha.framework.interfaces.GenericClusteringException;
  | import org.jboss.invocation.Invocation;
  | 
  | /**
  |  * <p>
  |  * <code>CreateExceptionHandlerInterceptor</code> handles CreateExceptions
  |  * during invocations to an EJB. In order for these exceptions to cause the
  |  * client to fail-over in a clustered environment, they get converted to
  |  * <code>GenericClusteringException</code>s.
  |  * </p>
  |  * <p>
  |  * <em>NOTE:</em> for this interceptor to work propertly, it must come 
BEFORE
  |  * <code>org.jboss.ejb.plugins.CleanShutdownInterceptor</code>.
  |  * <code>CleanShutdownInterceptor</code> will change the status on
  |  * <code>GenericClusteringException</code> s that pass through it to MAYBE,
  |  * which will not cause the client to fail-over. This is the behavior in 
JBoss
  |  * 3.2.6; I'm not sure about other versions.
  |  * </p>
  |  * 
  |  * @author anguyen
  |  */
  | public class CreateExceptionHandlerInterceptor extends AbstractInterceptor {
  | 
  |    /**
  |     * This invocation handles <code>CreateException</code>s thrown by
  |     * other invokers further down the chain. The current behavior is
  |     * to log the <code>CreateException</code>'s message as a warning
  |     * and throw a <code>GenericClusteringException</code> with a
  |     * completed status of NO. Clients of a clustered EJB should
  |     * interpret this exception as an indication that the EJB
  |     * is unavailable on this node and fail-over to another node.
  |     */
  |    public Object invoke(Invocation mi) throws Exception {
  |       try {
  |          return getNext().invoke(mi);
  |       }
  |       catch (CreateException e) {
  |          handleCreateException(e);
  |          // if handle create exception doesn't throw an exception....
  |          throw e;
  |       }
  |       catch (Exception e) {
  |          Throwable rootCause = e;
  |          while ((rootCause = rootCause.getCause()) != null) {
  |             // loop until we get to the root cause
  |          }
  |          if (rootCause instanceof CreateException) {
  |             handleCreateException((CreateException) rootCause);
  |          }
  |          // if the root cause is not a CreateException, rethrow
  |          // the original exception
  |          throw e;
  |       }
  |    }
  | 
  |    void handleCreateException(CreateException e) throws Exception {
  |       String message = "EJB creation failed on node";
  |       log.warn(message);
  |       log.debug("Stack Trace", e);
  |       throw new 
GenericClusteringException(GenericClusteringException.COMPLETED_NO, message);
  |    }
  | }
  | 

To use this interceptor, I created a custom container for my EJB in jboss.xml.

  | <?xml version="1.0" encoding="UTF-8"?>
  | <!DOCTYPE jboss PUBLIC "-//JBoss//DTD JBOSS 3.0//EN" 
"http://www.jboss.org/j2ee/dtd/jboss_3_0.dtd";>
  | 
  | <jboss>
  | 
  |    <enterprise-beans>
  | 
  |      <!--
  |        To add beans that you have deployment descriptor info for, add
  |        a file to your XDoclet merge directory called jboss-beans.xml that 
contains
  |        the <session></session>, <entity></entity> and 
<message-driven></message-driven>
  |        markup for those beans.
  |      -->
  | 
  |       <session>
  |          <ejb-name>MySLSB</ejb-name>
  |          <jndi-name>ejb/MySLSB</jndi-name>
  |          <configuration-name>My Clustered Stateless 
SessionBean</configuration-name>
  |           <clustered>true</clustered>
  |           <cluster-config>
  |               <partition-name>DefaultPartition</partition-name>
  |               
<home-load-balance-policy>org.jboss.ha.framework.interfaces.RoundRobin</home-load-balance-policy>
  |               
<bean-load-balance-policy>org.jboss.ha.framework.interfaces.RoundRobin</bean-load-balance-policy>
  |           </cluster-config>
  | 
  |       </session>
  | 
  |    </enterprise-beans>
  | 
  |    <resource-managers>
  |    </resource-managers>
  | 
  |   <!--
  |     | for container settings, you can merge in jboss-container.xml
  |     | this can contain <invoker-proxy-bindings/> and 
<container-configurations/>
  |   -->
  |    <container-configurations>
  |       <container-configuration>
  |          <container-name>My Clustered Stateless SessionBean</container-name>
  |          <call-logging>false</call-logging>
  |          
<invoker-proxy-binding-name>clustered-stateless-rmi-invoker</invoker-proxy-binding-name>
  |          <container-interceptors>
  |             <!-- This interceptor must come before CleanShutdownInterceptor 
to work properly -->
  |             
<interceptor>com.itgssi.util.jboss.ejb.CreateExceptionHandlerInterceptor</interceptor>
  |             
<interceptor>org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor</interceptor>
  |             
<interceptor>org.jboss.ejb.plugins.CleanShutdownInterceptor</interceptor>
  |             <interceptor>org.jboss.ejb.plugins.LogInterceptor</interceptor>
  |             
<interceptor>org.jboss.ejb.plugins.SecurityInterceptor</interceptor>
  |             <!-- CMT -->
  |             <interceptor 
transaction="Container">org.jboss.ejb.plugins.TxInterceptorCMT</interceptor>
  |             <interceptor transaction="Container" 
metricsEnabled="true">org.jboss.ejb.plugins.MetricsInterceptor</interceptor>
  |             <interceptor 
transaction="Container">org.jboss.ejb.plugins.StatelessSessionInstanceInterceptor</interceptor>
  |             <!-- BMT -->
  |             <interceptor 
transaction="Bean">org.jboss.ejb.plugins.StatelessSessionInstanceInterceptor</interceptor>
  |             <interceptor 
transaction="Bean">org.jboss.ejb.plugins.TxInterceptorBMT</interceptor>
  |             <interceptor transaction="Bean" 
metricsEnabled="true">org.jboss.ejb.plugins.MetricsInterceptor</interceptor>
  |             
<interceptor>org.jboss.resource.connectionmanager.CachedConnectionInterceptor</interceptor>
  |          </container-interceptors>
  |          
<instance-pool>org.jboss.ejb.plugins.StatelessSessionInstancePool</instance-pool>
  |          <instance-cache></instance-cache>
  |          <persistence-manager></persistence-manager>
  |          <container-pool-conf>
  |             <MaximumSize>100</MaximumSize>
  |          </container-pool-conf>
  |       </container-configuration>
  | 
  |    </container-configurations>
  | </jboss>
  | 
I used the standard Clustered Stateless SessionBean container as a template.  
You could also modify the default Clustered Stateless SessionBean container and 
just add the interceptor there.

Kudos to the JBoss developers for giving us the hooks necessary to come up with 
these kinds of solutions.


View the original post : 
http://www.jboss.org/index.html?module=bb&op=viewtopic&p=3872917#3872917

Reply to the post : 
http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=3872917


-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users.
Discover which products truly live up to the hype. Start reading now.
http://ads.osdn.com/?ad_id=6595&alloc_id=14396&op=click
_______________________________________________
JBoss-user mailing list
JBoss-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jboss-user

Reply via email to