Compare commits
16 Commits
1.4.3.RELE
...
1.5.10.REL
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
13aa315842 | ||
|
|
db286b73f1 | ||
|
|
1985a85c19 | ||
|
|
c128804ac5 | ||
|
|
ef22c0322d | ||
|
|
c96d6e8e4f | ||
|
|
506745d1a2 | ||
|
|
4bb2c01474 | ||
|
|
dda3c483f7 | ||
|
|
a2e2c2d7c2 | ||
|
|
1c036c8093 | ||
|
|
69d1c5f793 | ||
|
|
c6783ee869 | ||
|
|
1b7fa858a0 | ||
|
|
2c03bf2281 | ||
|
|
a625386b76 |
73
README.adoc
73
README.adoc
@@ -6,7 +6,7 @@ projects: [spring-ws]
|
||||
:toc:
|
||||
:project_id: gs-consuming-web-service
|
||||
:spring_version: current
|
||||
:spring_boot_version: 1.4.3.RELEASE
|
||||
:spring_boot_version: 1.5.10.RELEASE
|
||||
:icons: font
|
||||
:source-highlighter: prettify
|
||||
|
||||
@@ -14,10 +14,10 @@ This guide walks you through the process of consuming a link:/understanding/SOAP
|
||||
|
||||
== What you'll build
|
||||
|
||||
You will build a client that fetches weather data from a remote, WSDL-based web service using http://en.wikipedia.org/wiki/SOAP[SOAP].
|
||||
You can find out more about the weather service at http://wiki.cdyne.com/index.php/CDYNE_Weather
|
||||
You will build a client that fetches stock market quotes data from a remote, WSDL-based web service using http://en.wikipedia.org/wiki/SOAP[SOAP].
|
||||
You can find out more about the quote service at http://www.webservicex.com/stockquote.asmx?op=GetQuote.
|
||||
|
||||
The service provides weather forecasts based on a zipcode. You will be able to use your own zip code.
|
||||
The service provides stock market quotes. You will be able to use your own ticker symbol.
|
||||
|
||||
|
||||
== What you'll need
|
||||
@@ -44,7 +44,7 @@ only for server-side web services. That starter brings on board things like embe
|
||||
== Generate domain objects based on a WSDL
|
||||
|
||||
The interface to a SOAP web service is captured in a http://en.wikipedia.org/wiki/Web_Services_Description_Language[WSDL]. JAXB provides an easy means to generate Java classes from a WSDL (or rather: the XSD contained in the `<Types/>` section of the WSDL).
|
||||
The WSDL for the weather service can be found at http://wsf.cdyne.com/WeatherWS/Weather.asmx?wsdl.
|
||||
The WSDL for the quote service can be found at http://www.webservicex.com/stockquote.asmx?WSDL.
|
||||
|
||||
To generate Java classes from the WSDL in maven, you need the following plugin setup:
|
||||
|
||||
@@ -66,41 +66,41 @@ As gradle does not have a JAXB plugin (yet), it involves an ant task, which make
|
||||
|
||||
In both cases, the JAXB domain object generation process has been wired into the build tool's lifecycle so there are no extra steps to run.
|
||||
|
||||
== Create a weather service client
|
||||
== Create a stock market quotes service client
|
||||
|
||||
To create a web service client, you simply have to extend the http://docs.spring.io/spring-ws/sites/2.0/apidocs/org/springframework/ws/client/core/support/WebServiceGatewaySupport.html[WebServiceGatewaySupport] class and code your operations:
|
||||
|
||||
`src/main/java/hello/WeatherClient.java`
|
||||
`src/main/java/hello/QuoteClient.java`
|
||||
[source,java]
|
||||
----
|
||||
include::complete/src/main/java/hello/WeatherClient.java[]
|
||||
include::complete/src/main/java/hello/QuoteClient.java[]
|
||||
----
|
||||
|
||||
The client contains two methods: `getCityForecastByZip` which does the actual SOAP exchange, and `printResponse` which prints the received response. We will focus on the former method.
|
||||
The client contains one method: `getQuote` which does the actual SOAP exchange.
|
||||
|
||||
In this method, both the `GetCityForecastByZIP` and the `GetCityForecastByZIPResponse` classes are derived from the WSDL and were generated in the JAXB generation process described in the previous step.
|
||||
It creates the `GetCityForecastByZIP` request object and set it with the `zipCode` parameter.
|
||||
After printing out the zip code, it uses the http://docs.spring.io/spring-ws/sites/2.0/apidocs/org/springframework/ws/client/core/WebServiceTemplate.html[WebServiceTemplate] supplied by the `WebServiceGatewaySupport` base class to do the actual SOAP exchange.
|
||||
It passes the `GetCityForecastByZIP` request object, as well as a `SoapActionCallback` to pass on a http://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383528[SOAPAction] header with the request, as the WSDL described that it needed this header in the `<soap:operation/>` elements.
|
||||
It casts the response into a `GetCityForecastByZIPResponse` object, which is then returned.
|
||||
In this method, both the `GetQuote` and the `GetQuoteResponse` classes are derived from the WSDL and were generated in the JAXB generation process described in the previous step.
|
||||
It creates the `GetQuote` request object and sets it up with the `ticker` parameter.
|
||||
After printing out the ticker code, it uses the http://docs.spring.io/spring-ws/sites/2.0/apidocs/org/springframework/ws/client/core/WebServiceTemplate.html[WebServiceTemplate] supplied by the `WebServiceGatewaySupport` base class to do the actual SOAP exchange.
|
||||
It passes the `GetQuote` request object, as well as a `SoapActionCallback` to pass on a http://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383528[SOAPAction] header with the request, as the WSDL described that it needed this header in the `<soap:operation/>` elements.
|
||||
It casts the response into a `GetQuoteResponse` object, which is then returned.
|
||||
|
||||
== Configuring web service components
|
||||
|
||||
Spring WS uses Spring Framework's OXM module which has the `Jaxb2Marshaller` to serialize and deserialize XML requests.
|
||||
|
||||
`src/main/java/hello/WeatherConfiguration.java`
|
||||
`src/main/java/hello/QuoteConfiguration.java`
|
||||
[source,java]
|
||||
----
|
||||
include::complete/src/main/java/hello/WeatherConfiguration.java[]
|
||||
include::complete/src/main/java/hello/QuoteConfiguration.java[]
|
||||
----
|
||||
|
||||
The `marshaller` is pointed at the collection of generated domain objects and will use them to both serialize and deserialize between XML and link:/understanding/POJO[POJOs].
|
||||
|
||||
The `weatherClient` is created and configured with the URI of the weather service shown up above. It is also configured to use the JAXB marshaller.
|
||||
The `quoteClient` is created and configured with the URI of the weather service shown up above. It is also configured to use the JAXB marshaller.
|
||||
|
||||
== Make the application executable
|
||||
|
||||
This application is packaged up to run from the console and retrieve a single weather forecast for a given zip code.
|
||||
This application is packaged up to run from the console and retrieve the stock value for a given symbol.
|
||||
|
||||
`src/main/java/hello/Application.java`
|
||||
[source,java]
|
||||
@@ -108,9 +108,9 @@ This application is packaged up to run from the console and retrieve a single we
|
||||
include::complete/src/main/java/hello/Application.java[]
|
||||
----
|
||||
|
||||
The `main()` method defers to the http://docs.spring.io/spring-boot/docs/{spring_boot_version}/api/org/springframework/boot/SpringApplication.html[`SpringApplication`] helper class, providing `WeatherConfiguration.class` as an argument to its `run()` method. This tells Spring to read the annotation metadata from `WeatherConfiguration` and to manage it as a component in the link:/understanding/application-context[Spring application context].
|
||||
The `main()` method defers to the http://docs.spring.io/spring-boot/docs/{spring_boot_version}/api/org/springframework/boot/SpringApplication.html[`SpringApplication`] helper class, providing `QuoteConfiguration.class` as an argument to its `run()` method. This tells Spring to read the annotation metadata from `QuoteConfiguration` and to manage it as a component in the link:/understanding/application-context[Spring application context].
|
||||
|
||||
NOTE: This application is hard coded to look up zip code 94304, Palo Alto, CA. Towards the end of this guide, you'll see how to plug in a different zip code without editing the code.
|
||||
NOTE: This application is hard coded to look up symbol 'MSFT' which correspond to Microsoft Corporation. Towards the end of this guide, you'll see how to plug in a different symbol without editing the code.
|
||||
|
||||
include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/master/build_an_executable_jar_subhead.adoc[]
|
||||
|
||||
@@ -120,40 +120,29 @@ include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/
|
||||
Logging output is displayed. The service should be up and running within a few seconds.
|
||||
|
||||
```
|
||||
Requesting forecast for 94304
|
||||
Requesting quote for MSFT
|
||||
|
||||
Forecast for Palo Alto, CA
|
||||
2013-01-03 Partly Cloudy °-57°
|
||||
2013-01-04 Partly Cloudy 41°-58°
|
||||
2013-01-05 Partly Cloudy 41°-59°
|
||||
2013-01-06 Partly Cloudy 44°-56°
|
||||
2013-01-07 Partly Cloudy 41°-60°
|
||||
2013-01-08 Partly Cloudy 42°-60°
|
||||
2013-01-09 Partly Cloudy 43°-58°
|
||||
<StockQuotes><Stock><Symbol>MSFT</Symbol><Last>62.70</Last>...</StockQuotes>
|
||||
```
|
||||
|
||||
You can plug in a different zip code by typing `java -jar build/libs/gs-consuming-web-service-0.1.0.jar 34769`
|
||||
You can plug in a different ticker by typing `java -jar build/libs/gs-consuming-web-service-0.1.0.jar ORCL`
|
||||
|
||||
```
|
||||
Requesting forecast for 34769
|
||||
Requesting quote for ORCL
|
||||
|
||||
<StockQuotes><Stock><Symbol>ORCL</Symbol><Last>39.26</Last>...</StockQuotes>
|
||||
|
||||
Forecast for Saint Cloud, FL
|
||||
2014-02-18 Sunny 51°-79°
|
||||
2014-02-19 Sunny 55°-81°
|
||||
2014-02-20 Sunny 59°-84°
|
||||
2014-02-21 Partly Cloudy 63°-85°
|
||||
2014-02-22 Partly Cloudy 63°-84°
|
||||
2014-02-23 Partly Cloudy 63°-82°
|
||||
2014-02-24 Partly Cloudy 62°-80°
|
||||
```
|
||||
|
||||
== Summary
|
||||
|
||||
Congratulations! You've just developed a client to consume a SOAP-based web service with Spring.
|
||||
|
||||
Congratulations! You've just developed a client to consume a SOAP-based web service with Spring.
|
||||
|
||||
== See Also
|
||||
|
||||
The following guides may also be helpful:
|
||||
|
||||
* https://spring.io/guides/gs/producing-web-service/[Producing a SOAP web service]
|
||||
* https://spring.io/guides/gs/spring-boot/[Building an Application with Spring Boot]
|
||||
|
||||
include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/master/footer.adoc[]
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ buildscript {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.4.3.RELEASE")
|
||||
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.10.RELEASE")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ repositories {
|
||||
task genJaxb {
|
||||
ext.sourcesDir = "${buildDir}/generated-sources/jaxb"
|
||||
ext.classesDir = "${buildDir}/classes/jaxb"
|
||||
ext.schema = "http://wsf.cdyne.com/WeatherWS/Weather.asmx?wsdl"
|
||||
ext.schema = "http://www.webservicex.com/stockquote.asmx?WSDL"
|
||||
|
||||
outputs.dir classesDir
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>1.4.3.RELEASE</version>
|
||||
<version>1.5.10.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
@@ -51,7 +51,7 @@
|
||||
<generatePackage>hello.wsdl</generatePackage>
|
||||
<schemas>
|
||||
<schema>
|
||||
<url>http://wsf.cdyne.com/WeatherWS/Weather.asmx?wsdl</url>
|
||||
<url>http://www.webservicex.com/stockquote.asmx?WSDL</url>
|
||||
</schema>
|
||||
</schemas>
|
||||
</configuration>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
package hello;
|
||||
|
||||
import hello.wsdl.GetCityForecastByZIPResponse;
|
||||
import hello.wsdl.GetQuoteResponse;
|
||||
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
@@ -12,18 +12,19 @@ import org.springframework.context.annotation.Bean;
|
||||
public class Application {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class);
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
@Bean
|
||||
CommandLineRunner lookup(WeatherClient weatherClient) {
|
||||
CommandLineRunner lookup(QuoteClient quoteClient) {
|
||||
return args -> {
|
||||
String zipCode = "94304";
|
||||
String ticker = "MSFT";
|
||||
|
||||
if (args.length > 0) {
|
||||
zipCode = args[0];
|
||||
ticker = args[0];
|
||||
}
|
||||
GetCityForecastByZIPResponse response = weatherClient.getCityForecastByZip(zipCode);
|
||||
GetQuoteResponse response = quoteClient.getQuote(ticker);
|
||||
System.err.println(response.getGetQuoteResult());
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
32
complete/src/main/java/hello/QuoteClient.java
Normal file
32
complete/src/main/java/hello/QuoteClient.java
Normal file
@@ -0,0 +1,32 @@
|
||||
|
||||
package hello;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.ws.client.core.support.WebServiceGatewaySupport;
|
||||
import org.springframework.ws.soap.client.core.SoapActionCallback;
|
||||
|
||||
import hello.wsdl.GetQuote;
|
||||
import hello.wsdl.GetQuoteResponse;
|
||||
|
||||
public class QuoteClient extends WebServiceGatewaySupport {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(QuoteClient.class);
|
||||
|
||||
public GetQuoteResponse getQuote(String ticker) {
|
||||
|
||||
GetQuote request = new GetQuote();
|
||||
request.setSymbol(ticker);
|
||||
|
||||
log.info("Requesting quote for " + ticker);
|
||||
|
||||
GetQuoteResponse response = (GetQuoteResponse) getWebServiceTemplate()
|
||||
.marshalSendAndReceive("http://www.webservicex.com/stockquote.asmx",
|
||||
request,
|
||||
new SoapActionCallback("http://www.webserviceX.NET/GetQuote"));
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,20 +6,21 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
|
||||
|
||||
@Configuration
|
||||
public class WeatherConfiguration {
|
||||
public class QuoteConfiguration {
|
||||
|
||||
@Bean
|
||||
public Jaxb2Marshaller marshaller() {
|
||||
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
|
||||
// this package must match the package in the <generatePackage> specified in pom.xml
|
||||
// this package must match the package in the <generatePackage> specified in
|
||||
// pom.xml
|
||||
marshaller.setContextPath("hello.wsdl");
|
||||
return marshaller;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WeatherClient weatherClient(Jaxb2Marshaller marshaller) {
|
||||
WeatherClient client = new WeatherClient();
|
||||
client.setDefaultUri("http://ws.cdyne.com/WeatherWS");
|
||||
public QuoteClient quoteClient(Jaxb2Marshaller marshaller) {
|
||||
QuoteClient client = new QuoteClient();
|
||||
client.setDefaultUri("http://www.webservicex.com/stockquote.asmx");
|
||||
client.setMarshaller(marshaller);
|
||||
client.setUnmarshaller(marshaller);
|
||||
return client;
|
||||
@@ -1,58 +0,0 @@
|
||||
|
||||
package hello;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import hello.wsdl.Forecast;
|
||||
import hello.wsdl.ForecastReturn;
|
||||
import hello.wsdl.GetCityForecastByZIP;
|
||||
import hello.wsdl.GetCityForecastByZIPResponse;
|
||||
import hello.wsdl.Temp;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.ws.client.core.support.WebServiceGatewaySupport;
|
||||
import org.springframework.ws.soap.client.core.SoapActionCallback;
|
||||
|
||||
public class WeatherClient extends WebServiceGatewaySupport {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(WeatherClient.class);
|
||||
|
||||
public GetCityForecastByZIPResponse getCityForecastByZip(String zipCode) {
|
||||
|
||||
GetCityForecastByZIP request = new GetCityForecastByZIP();
|
||||
request.setZIP(zipCode);
|
||||
|
||||
log.info("Requesting forecast for " + zipCode);
|
||||
|
||||
GetCityForecastByZIPResponse response = (GetCityForecastByZIPResponse) getWebServiceTemplate()
|
||||
.marshalSendAndReceive(
|
||||
"http://wsf.cdyne.com/WeatherWS/Weather.asmx",
|
||||
request,
|
||||
new SoapActionCallback("http://ws.cdyne.com/WeatherWS/GetCityForecastByZIP"));
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public void printResponse(GetCityForecastByZIPResponse response) {
|
||||
|
||||
ForecastReturn forecastReturn = response.getGetCityForecastByZIPResult();
|
||||
|
||||
if (forecastReturn.isSuccess()) {
|
||||
log.info("Forecast for " + forecastReturn.getCity() + ", " + forecastReturn.getState());
|
||||
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
|
||||
for (Forecast forecast : forecastReturn.getForecastResult().getForecast()) {
|
||||
|
||||
Temp temperature = forecast.getTemperatures();
|
||||
|
||||
log.info(String.format("%s %s %s°-%s°", format.format(forecast.getDate().toGregorianCalendar().getTime()),
|
||||
forecast.getDesciption(), temperature.getMorningLow(), temperature.getDaytimeHigh()));
|
||||
log.info("");
|
||||
}
|
||||
} else {
|
||||
log.info("No forecast received");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,7 +7,7 @@ buildscript {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.4.3.RELEASE")
|
||||
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.10.RELEASE")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ repositories {
|
||||
task genJaxb {
|
||||
ext.sourcesDir = "${buildDir}/generated-sources/jaxb"
|
||||
ext.classesDir = "${buildDir}/classes/jaxb"
|
||||
ext.schema = "http://wsf.cdyne.com/WeatherWS/Weather.asmx?wsdl"
|
||||
ext.schema = "http://www.webservicex.com/stockquote.asmx?WSDL"
|
||||
|
||||
outputs.dir classesDir
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>1.4.3.RELEASE</version>
|
||||
<version>1.5.10.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
@@ -51,7 +51,7 @@
|
||||
<generatePackage>hello.wsdl</generatePackage>
|
||||
<schemas>
|
||||
<schema>
|
||||
<url>http://wsf.cdyne.com/WeatherWS/Weather.asmx?wsdl</url>
|
||||
<url>http://www.webservicex.com/stockquote.asmx?WSDL</url>
|
||||
</schema>
|
||||
</schemas>
|
||||
</configuration>
|
||||
|
||||
Reference in New Issue
Block a user