RMIServiceBindingProvider handles InvocationTargetException incorrectly
-----------------------------------------------------------------------

                 Key: TUSCANY-3665
                 URL: https://issues.apache.org/jira/browse/TUSCANY-3665
             Project: Tuscany
          Issue Type: Bug
    Affects Versions: Java-SCA-1.6
         Environment: JDK 1.6.0_18, Windows XP
            Reporter: Sebastian Millies


I have made a service available through the RMI-Binding as follows:

<composite xmlns="http://www.osoa.org/xmlns/sca/1.0";
    xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.0";
    targetNamespace="http://tuscanyscatours.com/";
    name="currencyconverter2">

    <component name="CurrencyConverter2" 
promote="CurrencyConverter2/CurrencyConverter">
        <implementation.java 
class="com.tuscanyscatours.currencyconverter.impl.CurrencyConverterImpl" />
        <service name="CurrencyConverter">
            <interface.java 
interface="com.tuscanyscatours.currencyconverter.CurrencyConverter" />
            <tuscany:binding.rmi host="localhost" port="1099" 
serviceName="CurrencyConverterRMI"/>
        </service>
    </component>
</composite>

The service is allowed to throw a checked Exception. Here are the interface and 
implementation:

@Remotable
public interface CurrencyConverter extends java.rmi.Remote
{
   // intended to throw a checked exception
  double getExchangeRate( String fromCurrencyCode, String toCurrencyCode ) 
throws RemoteException,
      CurrencyConverterFault_Exception;
}

@Service(interfaces = { CurrencyConverter.class })
public class CurrencyConverterImpl extends UnicastRemoteObject implements 
CurrencyConverter
{
  public CurrencyConverterImpl() throws RemoteException  { }

  public double getExchangeRate( String fromCurrencyCode, String toCurrencyCode 
)
      throws CurrencyConverterFault_Exception
  {
      // note the use of JAX-WS artifacts. The fault bean class has been made 
serializable, so this works over RMI as well
      CurrencyConverterFault faultBean = new CurrencyConverterFault();
      faultBean.setMessage( "Unknown target currency: " + toCurrencyCode);
      throw new CurrencyConverterFault_Exception( "Currency conversion fault", 
faultBean );
  }
}

When I call the service, I expect a CurrencyConverterFault_Exception to be 
thrown. This is exactly what happens
when I use a pure Java RMI client (or a webservice client when I also provide 
binding.ws):

   Registry registry = LocateRegistry.getRegistry( "localhost" );
   String name = "CurrencyConverterRMI";
   CurrencyConverter converter = (CurrencyConverter) registry.lookup( name );
   try
   {
     System.out.println( "ExchangeRate = " + converter.getExchangeRate( "XYZ", 
"GBP" ) );   // (*)
   }
   catch( CurrencyConverterFault_Exception e ) 
   {
     System.out.println( e.getFaultInfo().getMessage() );
   }

However, when I deploy the composite in the Tuscany runtime and access it over 
the RMI binding, I get a 
java.rmi.UnexpectedException instead:

    SCADomain scaDomain = 
SCADomain.newInstance("currency-converter-rmi.composite");
    CurrencyConverter converter = scaDomain.getService( 
CurrencyConverter.class, "CurrencyConverter2/CurrencyConverter" );
    try
    {
      System.out.println( "ExchangeRate = " + converter.getExchangeRate( "XYZ", 
"GBP" ) );   // (**)
    }
    catch( CurrencyConverterFault_Exception e )  // <-- not caught
    {
      System.out.println( e.getMessage() ); 
    }
    catch( Exception e )
    {
      System.out.println( "UnexpectedException: " + e.getMessage() ); // <-- 
here
    }

The reason may be a mistake in 
org.apache.tuscany.sca.binding.rmi.provider.RMIServiceBindingProvider#createRmiService.
I believe the MessageInterceptor that is set as a callback does not handle 
InvocationTargetExceptions correctly. In particular,
it seems to confuse the "cause" and "targetException" attributes of 
InvocationTargetExceptions. I have inserted some code
as follows to test this hypothesis:

   enhancer.setCallback(new MethodInterceptor() {
            public Object intercept(Object arg0, Method method, Object[] args, 
MethodProxy arg3) throws Throwable {
                try {
                    return invokeTarget(JavaInterfaceUtil.findOperation(method, 
serviceInterface.getOperations()), args);
                } catch (InvocationTargetException e) {
                    final Throwable targetException = e.getTargetException();   
        // <-- insert
                    for (Class<?> declaredType : method.getExceptionTypes()) {  
   // <-- insert
                        if (declaredType.isInstance(targetException)) {         
                  // <-- insert
                            throw targetException;                              
                                    // <-- insert
                        }                                                       
                                                      // <-- insert
                    }                                                           
                                                      // <-- insert
                    final Throwable cause = e.getCause();
           
With this change, the two calls in lines (*) and (**) behave identically, as it 
should be, because now the 
java.rmi.server.RemoteObjectInvocationHandler finds a declared exception type 
that is assignable from the thrown
exception type (which it doesn't if it is simply passed an 
InvocationTargetException).

Perhaps bug TUSCANY-2406 is related.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to