tuscany-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Sebastian Millies (JIRA)" <...@tuscany.apache.org>
Subject [jira] Created: (TUSCANY-3665) RMIServiceBindingProvider handles InvocationTargetException incorrectly
Date Thu, 02 Sep 2010 15:30:55 GMT
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.


Mime
View raw message