jueves, 6 de noviembre de 2014

...proxying a SOAP service with 3 faults in SwitchYard

This document describes a problem that I’ve faced with SwitchYard due to one of it’s known issues/features/limitations.

Problem

I needed to create a proxy service for a SOAP Web Service where I had a contract with 3 faults.

public interface CustomerListServicePortType {
    public CustomerListResponse getCustomerList(CustomerListRequest parameters) throws
            GeneralError, CustomerNotFound, InvalidUserCredentials;
}
SwitchYard has one limitation, it only accepts contracts with one Exception type (as well as only accepts one single input type). When I created the initial service for this, and deployed my service, I had SwitchYard telling me about this:
org.switchyard.SwitchYardException: SWITCHYARD010005: Service operations on a Java interface can only throw one type of exception.
One option could be to modify the contract, but as this is to proxy a legacy service, I need to maintain my contract, so I looked into various options, out of which I’ll describe the one that was the easiest for me.

Solution

I created an internal Contract, for my service, to only have one single Exception:
public interface CustomerListServicePortType {
    public CustomerListResponse getCustomerList(CustomerListRequest parameters) throws
            CustomerListException;
}
Use transformers to map from and to the original exceptions to my new "unique" exception. As when doing SOAPFault handling, what really gets marshalled/unmarshalled is the FaultInfo, I decided to keep the original FaultInfo in my new Exception:
import org.w3c.dom.Element;

public class CustomerListException extends Exception {

    private Element faultInfo;

    public CustomerListException(Element cause) {
        faultInfo = cause;
    }

    public Element getFaultInfo() {
        return faultInfo;
    }
}
And my tranformers where so simple, that I was happy not having to deal with DOM parsing and Element, and all that stuff.
public final class ExceptionTransformers {

   @Transformer(from = "{http://common/errorcodes}invalidUserCredentials")
   public CustomerListException InvalidUserCredentialsToCustomerListEx(Element from) {
      CustomerListException fe = new CustomerListException(from);
      return fe;
   }

   @Transformer(from = "{http://common/errorcodes}generalError")
   public CustomerListException transformGeneralErrorToCustomerListEx(Element from) {
      CustomerListException fe = new CustomerListException(from);
      return fe;
   }

   @Transformer(from = "{http://common/errorcodes}customerNotFound")
   public CustomerListException transformCustomerNotFoundToCustomerListEx(Element from) {
      CustomerListException fe = new CustomerListException(from);
      return fe;
   }

   @Transformer(to = "{http://common/errorcodes}customerNotFound")
   public Element transformCustomerListExToCustomerNotFound(CustomerListException e){
      return e.getFaultInfo();
   }

   @Transformer(to = "{http://common/errorcodes}generalError")
   public Element transformCustomerListExToGeneralError(CustomerListException e){
      return e.getFaultInfo();
   }

   @Transformer(to = "{http://common/errorcodes}invalidUserCredentials")
   public Element transformCustomerListExToInvalidUserCredentials(CustomerListException e){
      return e.getFaultInfo();
   }
}
These transformers gets registered as Java transformers (due to the @Transform annotation).
And everything works like a charm

1 comentario:

Rick dijo...

Excelente! Gracias!