Generating SOAP webservice client stubs using Apache-CXF, Maven, Eclipse

How to create WSDL-first Java SOAP webservice client using CXF, Maven, and Eclipse.

Recently we wanted to build a Soap webservice client to invoke some operations in the production server. The client is supposed to be used by support staff and they have some determined set of operations to be performed on a daily basis. It turned out giving them a jar with command line options required for their operations.
In this post let me try to show how to generate the client stubs and invoke an operation. We will use CXF tool called wsdl2java to turn the WSDL into Java client code and Maven for dependencies and generating the code. We will use Eclipse as the IDE.

1. SOAP Service WSDL for our example:
For this example let us get the CDyne free GetStockQuote WSDL from here. You can right-click the link and save the WSDL to a location in your system.

2. Eclipse Maven Project and POM file:

  • Create a new Maven project in eclipse with artifactId as stockquote. See pom below for the options.
  • Place the downloaded WSDL at location stockquote/src/main/resources/
  • Add the maven dependencies and the required plugins as below.

 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
      <modelVersion>4.0.0</modelVersion>  
      <groupId>com.sqadev</groupId>  
      <artifactId>stockquote</artifactId>  
      <version>0.0.1-SNAPSHOT</version>  
      <name>Stock Quote client</name>  
      <properties>  
           <cxf.version>3.1.7</cxf.version>  
           <java.version>1.8</java.version>  
      </properties>  
      <dependencies>  
           <dependency>  
                <groupId>org.apache.cxf</groupId>  
                <artifactId>cxf-rt-frontend-jaxws</artifactId>  
                <version>${cxf.version}</version>  
           </dependency>  
           <dependency>  
                <groupId>org.apache.cxf</groupId>  
                <artifactId>cxf-rt-transports-http</artifactId>  
                <version>${cxf.version}</version>  
           </dependency>  
      </dependencies>  
           <build>  
           <plugins>  
           <!--Generate Java stub from WSDL at build time -->  
                <plugin>  
                     <groupId>org.apache.cxf</groupId>  
                     <artifactId>cxf-codegen-plugin</artifactId>  
                     <version>${cxf.version}</version>  
                     <executions>  
                          <execution>  
                               <id>generate-sources</id>  
                               <phase>generate-sources</phase>  
                               <configuration>  
                                    <sourceRoot>${basedir}/generated/cxf/src/main/java</sourceRoot>  
                                    <wsdlOptions>  
                                         <wsdlOption>  
                                              <wsdl>${basedir}/src/main/resources/delayedstockquote.wsdl</wsdl>  
                                              <extraargs>  
                                                   <extraarg>-client</extraarg>  
                                                   <extraarg>-impl</extraarg>  
                                                   <extraarg>-verbose</extraarg>  
                                              </extraargs>  
                                         </wsdlOption>  
                                    </wsdlOptions>  
                               </configuration>  
                               <goals>  
                                    <goal>wsdl2java</goal>  
                               </goals>  
                          </execution>  
                     </executions>  
                </plugin>  
                <!-- Add the generated sources, this avoids having to copy generated sources to build location -->  
       <plugin>  
         <groupId>org.codehaus.mojo</groupId>  
         <artifactId>build-helper-maven-plugin</artifactId>  
         <version>1.12</version>  
         <executions>  
           <execution>  
             <id>add-source</id>  
             <phase>generate-sources</phase>  
             <goals>  
               <goal>add-source</goal>  
             </goals>  
             <configuration>  
               <sources>  
                 <source>${basedir}/generated/cxf/src/main/java</source>  
               </sources>  
             </configuration>  
           </execution>  
         </executions>  
       </plugin>  
           </plugins>  
           </build>  
 </project>  

  • If you get undefined element declaration exception, please refer here to fix it.
  • We use cxf-codegen-plugin to run wsdl2java to generate our Java code into ${basedir}/generated/cxf/src/main/java
  • In eclipse java code is generated using Maven generate-sources. Right click the project stockquote -> Run as -> Maven generate-sources.
  • On successful build the source files will be generated in the new folder /generated/cxf/src/main/java.
  • Four client are generated as DelayedStockQuoteHttpGet_DelayedStockQuoteHttpGet_Client, ...HttpPost_Client and ...Soap_Client, ...Soap12_Client version. See eclipse screenshot below:




3. Running the Client:
Now that we have the client code generate, let us try to check if it's working.
Update one of the client code to check if the request/response works fine.
Sample code after updating DelayedStockQuoteSoap_DelayedStockQuoteSoap_Client:

................
 DelayedStockQuote ss = new DelayedStockQuote(wsdlURL, SERVICE_NAME);  
     DelayedStockQuoteSoap port = ss.getDelayedStockQuoteSoap();   
     {  
     System.out.println("Invoking getQuote...");  
     java.lang.String _getQuote_stockSymbol = "VZ";  
     java.lang.String _getQuote_licenseKey = "0";  
     com.cdyne.ws.QuoteData _getQuote__return = port.getQuote(_getQuote_stockSymbol, _getQuote_licenseKey);  
     System.out.println("getQuote.result = " + _getQuote__return.getCompanyName());  
     System.out.println("getQuote.result.Verizon.lastTradeAmt = " + _getQuote__return.lastTradeAmount);  
     }  
     {  
     System.out.println("Invoking getQuoteDataSet...");  
     java.lang.String _getQuoteDataSet_stockSymbols = "";  
     java.lang.String _getQuoteDataSet_licenseKey = "";  
     com.cdyne.ws.GetQuoteDataSetResponse.GetQuoteDataSetResult _getQuoteDataSet__return = port.getQuoteDataSet(_getQuoteDataSet_stockSymbols, _getQuoteDataSet_licenseKey);  
     System.out.println("getQuoteDataSet.result=" + _getQuoteDataSet__return);  
     }  
................

In eclipse right click on the file and select "Run As" --> "Java Application".
Sample result as below:
 Nov 12, 2016 11:52:45 PM org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean buildServiceFromWSDL  
 INFO: Creating Service {http://ws.cdyne.com/}DelayedStockQuote from WSDL: file:/C:/mysoftware/eclipse_wrkspce/stockquote/src/main/resources/delayedstockquote.wsdl  
 Invoking getQuote...  
 getQuote.result = Verizon Communications Inc. Com  
 getQuote.result.Verizon.lastTradeAmt = 46.69  
 Invoking getQuoteDataSet...  
 getQuoteDataSet.result=com.cdyne.ws.GetQuoteDataSetResponse$GetQuoteDataSetResult@9573584  
 Invoking getQuickQuote...  
 getQuickQuote.result=0  

Looks like our client is fetching results...
Src code in GitHub.
Next(in another post) we will see how we can build a jar with cmd line options to make some soap request/response.

No comments:

Post a Comment