Home > Enterprise >  Reduce coupling in a SOAP client
Reduce coupling in a SOAP client

Time:02-24

Currently we're usign jax-ws to create and consume SOAP web services, generating java classes through the wsimport goal.

We then, create a Service class to call this web service. The code in the Service class is like this:

public WebServiceRS webServiceCall() {
  
    Security security = SecurityFactory.getTokenSecurity();
    MessageHeader header = MessageHeaderFactory.getMessageHeader(SERVICE_ACTION);

    LOGGER.info("Calling CreatePassengerNameRecordRQ webService ...");

    Holder<Security> securityHolder = new Holder<>(security);
    Holder<MessageHeader> headerHolder = new Holder<>(header);

    addHandlers(port);

    WebServiceRS webServiceRS = port.webServiceRQ(
            headerHolder,
            securityHolder,
            getRequestBody()
    );

    ...

    return webServiceRS 
}

So what we noticed and that could be problematic is that this Service class depends on the .wsdl generated files like Security, MessageHeader, WebServiceRS and so on. And so when we update the .wsdl file to a newer version the code would eventually break because of this dependency.

What we're trying to achieve, then, is a way to invert this dependency so that we can update the web service (i.e .wsdl generated classes) without changing our Service class. We're having problems because we haven't figured a pattern to solve this issue. The main difficulty seems to arise from the fact that we can't change these generated classe to implement an interface as an example.

We're interested in patterns or best practices that can loose this coupling.

CodePudding user response:

Solution 1. Use Adapter pattern

In your case, the contract of service will change and you need to sync two different objects. Adapter will provide a different interface to its subject.

  1. Create an interface for your client model
public interface ClientModel {
    String getValue();
}
  1. Create Adapter which will convert DTO to ClientModel
public class ClientModelAdapter implements ClientModel {
    private DTO dto;
    
    public ClientModelAdapter(DTO dto) {
        this.dto = dto;
    }

    @Override
    public String getValue() {
        return dto.getValue();
    }
}

public class DTO {
    private String value;

    public String getValue() {
        return value;
    }
}

What is the exact difference between Adapter and Proxy patterns?

Solution 2. Use Mapper Pattern

You can simply create a mapper between DTO and ClientModel

public class ClientModelMapper {
    ClientModel map(DTO dto) {
        ClientModel clientModel = new ClientModel();        
        clientModel.setValue(dto.getValue());
        return clientModel;        
    }
}

Mapper component that transfers the data, making sure that both DTO and client model don't need to know about each other.
In this case, you can use MapStruct framework to avoid handmade mapping.

Solution 3. Make service API backward compatible

Probably you can avoid breaking changes in SOAP service and make API backward compatible. Backwards compatibility and Web Services

CodePudding user response:

You could put in behind a proxy class. That way the only thing you would need to adapt to the change of .wsdl file would be the proxy class.

  • Related