This page describes how to generate a client to call a few popular web services that are available on the web.
Requirements:
- Desktop Computer
- Maven 2
We will be generating clients for the following web services
- IP2Geo (http://ws.cdyne.com/ip2geo/ip2geo.asmx?wsdl)
- Currency Converter (http://webservice.webserviceshare.com/currencyconverter/rates.asmx?WSDL)
- Bible Web Service (http://www.webservicex.net/BibleWebservice.asmx?wsdl)
Before we can start to use any of the above web services we need to create a new Java project in Eclipse. Name the project
Go ahead and create a new java project in eclipse and save the following pom.xml file to the main folder.
<?xml version="1.0" encoding="UTF-8"?> <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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.vermatech</groupId> <artifactId>TestApacheCXFClient</artifactId> <packaging>war</packaging> <version>1.0.1-SNAPSHOT</version> <name>TestApacheCXFClient</name> <url>http://maven.apache.org</url> <build> <sourceDirectory>src</sourceDirectory> <resources><resource><directory>src</directory></resource></resources> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.0.2</version> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.15</version> <exclusions> <exclusion> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> </exclusion> <exclusion> <groupId>javax.jms</groupId> <artifactId>jms</artifactId> </exclusion> <exclusion> <groupId>com.sun.jdmk</groupId> <artifactId>jmxtools</artifactId> </exclusion> <exclusion> <groupId>com.sun.jmx</groupId> <artifactId>jmxri</artifactId> </exclusion> <exclusion> <groupId>javax.activation</groupId> <artifactId>activation</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf</artifactId> <version>2.1</version> <type>pom</type> <scope>compile</scope> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>2.2.4</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http-jetty</artifactId> <version>2.2.4</version> <type>jar</type> <scope>compile</scope> </dependency> </dependencies> </project>
regenerate the project by dropping to the command line and typing:
mvn eclipse:clean eclipse:eclipse
IP2Geo
This web service accepts an ip address and returns some information about it.
We start by getting the wsdl and saving it to our project as
document.wsdl
We insert the following into the pom.xml file in the plugins section.
<plugin> <groupId>org.apache.cxf</groupId> <artifactId>cxf-codegen-plugin</artifactId> <version>2.2.4</version> <executions> <execution> <id>generate-sources</id> <phase>generate-sources</phase> <configuration> <sourceRoot>generated/cxf</sourceRoot> <wsdlOptions> <wsdlOption> <wsdl>document.wsdl</wsdl> </wsdlOption> </wsdlOptions> </configuration> <goals> <goal>wsdl2java</goal> </goals> </execution> </executions> </plugin>
To generate the code type the following at the command prompt inside your eclipse project:
mvn generate-sources
- Return to eclipse and refresh the project.
- You will see additional files added to the /generated/cxf folder within the project.
- Copy these files to the folder where your javasource files are located.
Create a simple client that calls these web services.
SimpleClientApp.java
package test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.cdyne.ws.IP2GeoSoap;
import com.cdyne.ws.IPInformation;
public class HelloWorldClientApp {
public static void main(String args[]) throws Exception {
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"app-context.xml"});
IP2GeoSoap ip2Geo = (IP2GeoSoap) context.getBean("ip2Geo");
IPInformation ipInformation = ip2Geo.resolveIP("12.12.12.12", "0");
System.out.println("City: " + ipInformation.getCity());
System.out.println("State: " + ipInformation.getStateProvince());
System.out.println("Country: " + ipInformation.getCountry());
}
}
The above program initialized the spring application context and gets a bean that represents the web service. It invokes a method called “resolveIp()” to get a ipInformation object. Next it simply displays the values on the console.
One thing to note here is that the client code does not need all the files the wsdl2java has generated for us. We can trim down the generated code by deleting some classes we dont need.
We first start with the ObjectFactory. At this point it does not look like the object factory provides any benefit.
Delete the following
- ObjectFactory.java
- IP2GeoHttpGet.java
- IP2GeoHttpPost.java
Modify
- IP2GeoSoap.java and comment out the following line…
- @XmlSeeAlso({ObjectFactory.class})
- Delete the IP2GeoHttpGet.java and IP2GeoHttpPost.java as these methods will not be used to access the service
- Delete the IP2Geo.java class because we will use spring to generate the proxy that will access the service.
- Delete the ObjectFactory.java, ResolveIP.java, and ResolveIPResponse.java files as well
- Fix any compile issues that may arise from doing the deletes
You should only be left with 3 class files in your package
- IP2GeoSoap.jvaa
- IPInformation.java
- package-info.java
Next you need to make your app-context.xml should look like this… this file is located at the top package.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<jaxws:client id="ip2Geo"
serviceClass="com.cdyne.ws.IP2GeoSoap"
address="http://ws.cdyne.com/ip2geo/ip2geo.asmx" />
</beans>
Testing the program
Create a class in the test package.
HelloWorldClientApp.java
package test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.cdyne.ws.IP2GeoSoap;
import com.cdyne.ws.IPInformation;
public class HelloWorldClientApp {
public static void main(String args[]) throws Exception {
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"app-context.xml"});
IP2GeoSoap ip2Geo = (IP2GeoSoap) context.getBean("ip2Geo");
IPInformation ipInformation = ip2Geo.resolveIP("12.12.12.12", "0");
System.out.println("City: " + ipInformation.getCity());
System.out.println("State: " + ipInformation.getStateProvince());
System.out.println("Country: " + ipInformation.getCountry());
}
}
Run the program
you should get output similar to the following
log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext).
log4j:WARN Please initialize the log4j system properly.
Nov 6, 2009 6:07:51 PM org.apache.cxf.bus.spring.BusApplicationContext getConfigResources
INFO: No cxf.xml configuration file detected, relying on defaults.
Nov 6, 2009 6:07:52 PM org.apache.cxf.service.factory.ReflectionServiceFactoryBean buildServiceFromClass
INFO: Creating Service {http://ws.cdyne.com/}IP2GeoSoapService from class com.cdyne.ws.IP2GeoSoap
City: Anchorage
State: AK
Country: United States
Currency Converter
We will now investigate how to convert over the currency conversion web service that can be accessed using the following wsdl.
http://webservice.webserviceshare.com/currencyconverter/rates.asmx?WSDL
We start by saving the file to
document.wsdl
To generate the code type the following:
Open a command prompt and cd to the project’s folder
mvn generate-sources
you should see the following output
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building TestApacheCXFClient
[INFO] task-segment: [generate-sources]
[INFO] ------------------------------------------------------------------------
[INFO] [cxf-codegen:wsdl2java {execution: generate-sources}]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2 seconds
[INFO] Finished at: Fri Nov 06 18:23:44 EST 2009
[INFO] Final Memory: 25M/534M
[INFO] ------------------------------------------------------------------------
Return to the eclipse project and click refresh.
At this point you should see new files under the project /generated/cxf/com/websevriceshare folder.
We quickly identify that CurrencyConverterSoap.java is the main interface class for the web service. This class has the following methods
- getRates
- getSupportedCurrencies
- getRatesInAllCurrencies
- getConvertedAmount
- getConvertedAmountInAllCurrencies
Create a package com.websvriceshare (spelled incorrectly I know but do it anyway) and paste in all the generated code. We will run the project as-is.
We test he web service by defining the following in your spring configuration file…
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<jaxws:client id="currencyConverter"
serviceClass="com.websevriceshare.CurrencyConverterSoap"
address="http://webservice.webserviceshare.com/currencyconverter/rates.asmx" />
</beans>
Define the following test code
HelloWorldClientApp.java
package test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.websevriceshare.CurrencyConverterSoap;
import com.websevriceshare.CurrencyListRow;
public class HelloWorldClientApp {
public static void main(String args[]) throws Exception {
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"app-context.xml"});
CurrencyConverterSoap currencyConverter = (CurrencyConverterSoap) context
.getBean("currencyConverter");
System.out.println("These currencies are supported: ");
for (CurrencyListRow row : currencyConverter.getSupportedCurrencies().getCurrencyListRow()) {
System.out.println(row.getCurrencyName());
}
}
}
Run the class and you should get output to the console that looks like this…
log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext).
log4j:WARN Please initialize the log4j system properly.
Nov 6, 2009 6:44:04 PM org.apache.cxf.bus.spring.BusApplicationContext getConfigResources
INFO: No cxf.xml configuration file detected, relying on defaults.
Nov 6, 2009 6:44:04 PM org.apache.cxf.service.factory.ReflectionServiceFactoryBean buildServiceFromClass
INFO: Creating Service {http://websevriceshare.com/}CurrencyConverterSoapService from class com.websevriceshare.CurrencyConverterSoap
These currencies are supported:
Albanian Lek
Algerian Dinar
Argentine Peso
Aruba Florin
Australian Dollar
Bahamian Dollar
...
Yemen Riyal
Zambian Kwacha
Zimbabwe Dollar
Croatian Kuna
Russian Rouble
Once we are comfortable that its running we will start deleting un-necessary code that was generated.
Bible Web Service
This web service list all versus by Book Title ,Chapter and Verse from the Kings James version Bible
Download the source of the wsdl and again put it into document.wsdl
re-run the command to generate the sources and copy the generated sources to its package under the src folder. This time the source code got generated into the net.webservicex package. We create a similar package in our src folder within our project.
We quickly look at the generated classes once they have been moved over to our source folder and find out that BibleWebserviceSoap.java is the main web service class. It contains the following methods. All of them return a String. This is unfortunate since whomever is implementing the web service will need to parse the xml. It would have been better for the web service author to create a complex Type object and save the client programmers some time.
- getBibleWordsbyKeyWord
- getBookTitles
- getBibleWordsByChapterAndVerse
- getBibleWordsByBookTitleAndChapter
Modify the spring configuration file to generate the proxy for this service.
<jaxws:client id="bibleWebService"
serviceClass="net.webservicex.BibleWebserviceSoap"
address="http://www.webservicex.net/BibleWebservice.asmx" />
Create a client program to test the service
package test;
import net.webservicex.BibleWebserviceSoap;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class HelloWorldClientApp {
public static void main(String args[]) throws Exception {
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"app-context.xml"});
BibleWebserviceSoap bibleWebService = (BibleWebserviceSoap) context
.getBean("bibleWebService");
System.out.println(bibleWebService.getBookTitles());
}
}
This is the output we get.
<NewDataSet>
<Table>
<Book>1</Book>
<BookTitle>Genesis</BookTitle>
</Table>
<Table>
<Book>2</Book>
<BookTitle>Exodus</BookTitle>
</Table>
<Table>
<Book>3</Book>
<BookTitle>Leviticus</BookTitle>
</Table>
<Table>
<Book>4</Book>
<BookTitle>Numbers</BookTitle>
</Table>
Once we are comfortable with this we delete any un-necessary code.
We have successfully generated code that calls 3 web services using the Apache CXF framework.
Thats All for now!!!
0 Responses to “Accessing a Web Service using Apache CXF and Spring Framework Take 2”