Dynamic SOAP web service endpoint address

Every one prefers REST API’s now a days but hard luck lots of back end systems are SOAP XML based. There are some nice benefits e.g a contract (WSDL xsd) and of course web service client code generation that can easily be integrated into the client application.

However you can have several environments continuous integration, staging and production and the web service endpoint to the target SOAP service most likely will be different for all three environments so how to manage the WSDL files in an application? how to point to a different endpoint in test environment and in a different one in production?

Following is an approach that have worked quite well for me in a standard Java maven web project.

1. Download and place the WSDL (plus any required xsd schema files) to directory
src->main->resources->wsdl

2. We would also like to generate the client and source files so we apply the Apache CXF plugin in POM.xml
(this step is optional incase you already have the sources as a jar etc.)

<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>2.7.8</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<sourceRoot>${project.basedir}/src/generated/TestService/</sourceRoot>
<wsdlOptions>
<wsdlOption>
<wsdl>${project.basedir}/src/main/resources/wsdl/TestWebservice.wsdl</wsdl>
<wsdlLocation>wsdl/TestWebservice.wsdl</wsdlLocation>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>

Now when you do mvn clean install you will get the generated sources.

3. Now you have the client code generated to access the web service I would suggest writing a wrapper class that creates a web service client instance. This class also has a webserviceEndPointURL as a property.

public class TestWebserviceWrapper {
        private String webserviceEndPoint;
        public TestWebserviceWrapper(String webserviceEndPoint) {
                     this.webserviceEndPoint = webserviceEndPoint;
       }


      public TestPortType getWebServiceClient() {
                 TestPortType testPortType = new TestWSServiceagent()
               .getCIACSAPortTypeEndpoint();
             ((BindingProvider) testPortType).getRequestContext().put(
              BindingProvider.ENDPOINT_ADDRESS_PROPERTY,                       webserviceEndPoint);
         return testPortType;
     }
}

No magic just override the BindingProvider.ENDPOINT_ADDRESS_PROPERTY with the one set in wrapper constructor.

Now in your code just instantiate the wrapper class (or create a bean and inject) set the proper URL in constructor and use the endpoint of your choice  🙂

About: Muhammad Ali

I am a Java and Tibco expert. I have Master's degree in software engineering of distributed systems from Royal Institute of technology KTH Stockholm Sweden and I am an expert software engineer and integrator with over a decade of industry experience from Europe, Gulf and Asia regions. I am a strong opensource believer and encourage "sharing as caring" principle.