19 Commits

Author SHA1 Message Date
Greg Turnquist
db286b73f1 Upgrade to Spring Boot 1.5.9.RELEASE 2017-11-30 11:06:30 -06:00
Augusto Toledo
1985a85c19 Change old ‘weather service’ references to the ‘stock market service’ 2017-11-14 14:09:18 +00:00
ma
c128804ac5 args parameter added
Added args parameter to SpringApplication.run method to support command line arguments
2017-11-08 10:03:50 +00:00
Greg Turnquist
ef22c0322d Upgrade to Spring Boot 1.5.8.RELEASE 2017-10-17 15:42:14 -05:00
Greg Turnquist
c96d6e8e4f Upgrade to Spring Boot 1.5.7.RELEASE 2017-09-13 13:15:15 -05:00
Jay Bryant
506745d1a2 Added See Also links (#21)
At the bottom of the document (above the footer), I added links to other guides that readers may find to be useful.
2017-08-11 14:55:30 -05:00
Greg Turnquist
4bb2c01474 Upgrade to Spring Boot 1.5.6.RELEASE 2017-07-27 10:04:21 -05:00
Greg Turnquist
dda3c483f7 Upgrade to Spring Boot 1.5.5.RELEASE 2017-07-26 12:23:00 -05:00
Greg Turnquist
a2e2c2d7c2 Upgrade to Spring Boot 1.5.3.RELEASE 2017-04-21 09:20:02 -05:00
Greg Turnquist
1c036c8093 Upgrade to Spring Boot 1.5.2.RELEASE 2017-03-03 11:12:55 -06:00
Greg Turnquist
69d1c5f793 Upgrade to Spring Boot 1.5.1.RELEASE 2017-01-30 23:29:36 -06:00
Greg Turnquist
c6783ee869 Upgrade to Spring Boot 1.5.0.RELEASE 2017-01-30 11:38:03 -06:00
Greg Turnquist
1b7fa858a0 Set maven pom.xml to Spring Boot 1.4.4.RELEASE 2017-01-26 12:47:34 -06:00
Greg Turnquist
2c03bf2281 Upgrade to Spring Boot 1.4.4.RELEASE 2017-01-26 12:37:09 -06:00
Dave Syer
a625386b76 Switch to quote service (SOAP endpoint actually exists)
The weather service we had been using no longer exists and there
doesn't seem to be a simple publicly available alternative
(everyone is using plain HTTP these days). So this change converts
the sample to a public SOAP service that does stock quotes.

Fixes gh-9
2017-01-16 11:00:22 +00:00
Greg Turnquist
537578d624 Upgrade to Spring Boot 1.4.3.RELEASE 2016-12-22 22:32:28 -06:00
KC Baltz
62359bb948 Adding a comment to help others avoid a mistake
I think "hello.wsdl" sounds too much like a file name and not a package.  My colleague changed one and not the other and didn't see the problem.  I think this comment would help.
2016-12-20 11:58:34 +00:00
Greg Turnquist
c1060bbb5a Upgrade plugin from spring-boot to o.s.boot 2016-11-30 10:06:22 -06:00
Greg Turnquist
4182b71081 Upgrade to Spring Boot 1.4.2.RELEASE 2016-11-08 11:52:23 -06:00
9 changed files with 86 additions and 120 deletions

View File

@@ -6,7 +6,7 @@ projects: [spring-ws]
:toc:
:project_id: gs-consuming-web-service
:spring_version: current
:spring_boot_version: 1.4.1.RELEASE
:spring_boot_version: 1.5.9.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[]

View File

@@ -7,14 +7,14 @@ buildscript {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.4.1.RELEASE")
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.9.RELEASE")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'
apply plugin: 'org.springframework.boot'
repositories {
mavenCentral()
@@ -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

View File

@@ -10,7 +10,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELEASE</version>
<version>1.5.9.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>

View File

@@ -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());
};
}

View 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;
}
}

View File

@@ -6,19 +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
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;

View File

@@ -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");
}
}
}

View File

@@ -7,14 +7,14 @@ buildscript {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.4.1.RELEASE")
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.9.RELEASE")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'
apply plugin: 'org.springframework.boot'
repositories {
mavenCentral()
@@ -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

View File

@@ -10,7 +10,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELEASE</version>
<version>1.5.9.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>