Added stockquote sample

This commit is contained in:
Arjen Poutsma
2013-11-20 16:14:38 +01:00
parent de31a7d4da
commit 070f72cb33
22 changed files with 573 additions and 2 deletions

View File

@@ -12,12 +12,13 @@ additional instructions.
- [echo](./echo) - a simple sample that shows a bare-bones Echo service
- [mtom](./mtom) - shows how to use MTOM and JAXB2 marshalling
- [stockquote](./stockquote) - shows how to use WS-Addressing and the Java 6 HTTP Server
- [tutorial](./tutorial) - contains the code from the Spring-WS tutorial
## Running the Server
Most of the sample apps can be built and run using the following commands from
within the sample's folder.
within the ``server`` folder.
```sh
$ ./gradlew tomcatRun

View File

@@ -1,4 +1,4 @@
# Spring Web Service Tutorial
# Echo Sample
This sample shows a bare-bones echoing service. Incoming messages are handled
via DOM, and a simple 'business logic' service is used to obtain the result.

31
stockquote/README.md Normal file
View File

@@ -0,0 +1,31 @@
# Stock Quote Sample
This sample shows a Stock Quote service. Incoming messages are routed via
WS-Addressing, and SOAP message content is handled using JAXB2. Additionally,
this sample uses the HTTP server built into Java 6.
## Running the Server
The server can be built and run using the following command from
within the ``server`` folder.
```sh
$ ./gradlew runServer
```
## Running the Client(s)
There is a separate ``client`` directory containing clients that connect to the
server. You can run these clients by using the following command from within
each of client subdirectories:
```sh
$ gradle runClient
```
## License
[Spring Web Services] is released under version 2.0 of the [Apache License].
[Spring Web Services]: http://projects.spring.io/spring-ws
[Apache License]: http://www.apache.org/licenses/LICENSE-2.0

19
stockquote/build.gradle Normal file
View File

@@ -0,0 +1,19 @@
subprojects {
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
repositories {
maven { url 'http://repo.spring.io/libs-release' }
}
dependencies {
testCompile("junit:junit:4.10")
testCompile("org.easymock:easymock:3.1")
}
}
task wrapper(type: Wrapper) {
gradleVersion = '1.8'
}

6
stockquote/client/jax-ws/.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
target
*.iml
.classpath
.project
.settings

View File

@@ -0,0 +1,38 @@
configurations {
wsimport
}
ext.springWsVersion = '2.1.4.RELEASE'
task wsImport {
ext.outputDir = "${buildDir}/classes/wsimport"
ext.wsdl = "${projectDir}/../../server//src/main/resources/org/springframework/ws/samples/stockquote/ws/stockquote.wsdl"
inputs.files wsdl
outputs.dir outputDir
doLast() {
project.ant {
taskdef name: "wsimport", classname: "com.sun.tools.ws.ant.WsImport",
classpath: configurations.wsimport.asPath
mkdir(dir: outputDir)
wsimport(destdir: outputDir, wsdl: wsdl,
package: "org.springframework.ws.samples.stockquote.client.jaxws") {
produces(dir: outputDir, includes: "**/*.class")
}
}
}
}
dependencies {
compile("org.springframework.ws:spring-ws-core:$springWsVersion")
compile(files(wsImport.outputDir).builtBy(wsImport))
runtime("log4j:log4j:1.2.16")
wsimport "com.sun.xml.ws:jaxws-tools:2.1.7"
}
task runClient(dependsOn: 'classes', type:JavaExec) {
main = "org.springframework.ws.samples.stockquote.client.jaxws.Main"
classpath = sourceSets.main.runtimeClasspath
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.samples.stockquote.client.jaxws;
import java.net.URL;
import javax.xml.namespace.QName;
/**
* Simple client that calls the <code>StockQuote</code> operations using JAX-WS.
*
* @author Arjen Poutsma
*/
public class Main {
public static void main(String[] args) throws Exception {
StockService service;
if (args.length == 0) {
service = new StockService();
}
else {
QName serviceName = new QName("http://www.springframework.org/spring-ws/samples/stockquote", "StockSoap11");
service = new StockService(new URL(args[0]), serviceName);
}
Stock stock = service.getStockSoap11();
StockQuoteRequest request = new StockQuoteRequest();
request.getSymbol().add("FABRIKAM");
request.getSymbol().add("CONTOSO");
System.out.format("Requesting quotes for %s%n", request.getSymbol());
StockQuoteResponse response = stock.stockQuote(request);
System.out.format("Got %d results%n", response.getStockQuote().size());
for (StockQuote quote : response.getStockQuote()) {
System.out.println();
System.out.println("Symbol: " + quote.getSymbol());
System.out.println("\tName:\t\t\t" + quote.getName());
System.out.println("\tLast Price:\t\t" + quote.getLast());
System.out.println("\tPrevious Change:\t" + quote.getChange() + "%");
}
}
}

View File

@@ -0,0 +1,6 @@
target
*.iml
.classpath
.project
.settings

View File

@@ -0,0 +1,11 @@
ext.springWsVersion = '2.1.4.RELEASE'
dependencies {
compile("org.springframework.ws:spring-ws-core:$springWsVersion")
runtime("log4j:log4j:1.2.16")
}
task runClient(dependsOn: 'classes', type:JavaExec) {
main = "org.springframework.ws.samples.stockquote.client.sws.StockClient"
classpath = sourceSets.main.runtimeClasspath
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright 2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.samples.stockquote.client.sws;
import java.io.IOException;
import java.net.URI;
import javax.xml.transform.Source;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.ws.client.core.support.WebServiceGatewaySupport;
import org.springframework.ws.soap.addressing.client.ActionCallback;
import org.springframework.xml.transform.ResourceSource;
import org.springframework.xml.transform.StringResult;
public class StockClient extends WebServiceGatewaySupport {
private Resource request;
private URI action;
public void setRequest(Resource request) {
this.request = request;
}
public void setAction(URI action) {
this.action = action;
}
public void quotes() throws IOException {
Source requestSource = new ResourceSource(request);
StringResult result = new StringResult();
getWebServiceTemplate().sendSourceAndReceiveToResult(requestSource, new ActionCallback(action), result);
System.out.println();
System.out.println(result);
System.out.println();
}
public static void main(String[] args) throws IOException {
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext.xml", StockClient.class);
StockClient stockClient = (StockClient) applicationContext.getBean("stockClient");
stockClient.quotes();
}
}

View File

@@ -0,0 +1,7 @@
log4j.rootLogger=WARN, stdout
log4j.logger.org.springframework.ws=DEBUG
log4j.logger.org.springframework.xml=DEBUG
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" 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-2.5.xsd">
<bean id="stockClient" class="org.springframework.ws.samples.stockquote.client.sws.StockClient">
<property name="defaultUri" value="http://localhost:8080/StockService"/>
<property name="request"
value="classpath:org/springframework/ws/samples/stockquote/client/sws/quotesRequest.xml"/>
<property name="action"
value="http://www.springframework.org/spring-ws/samples/stockquote/StockService/GetQuote"/>
</bean>
</beans>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<StockQuoteRequest xmlns="http://www.springframework.org/spring-ws/samples/stockquote">
<Symbol>FABRIKAM</Symbol>
<Symbol>CONTOSO</Symbol>
</StockQuoteRequest>

6
stockquote/server/.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
target
*.iml
.classpath
.project
.settings

View File

@@ -0,0 +1,60 @@
configurations {
jaxb
}
ext.springVersion = '3.2.4.RELEASE'
ext.springWsVersion = '2.1.4.RELEASE'
task genJaxb {
ext.sourcesDir = "${buildDir}/generated-sources/jaxb"
ext.classesDir = "${buildDir}/classes/jaxb"
ext.schema = "${projectDir}/src/main/resources/org/springframework/ws/samples/stockquote/ws/stockquote.wsdl"
inputs.files schema
outputs.dir classesDir
doLast() {
project.ant {
taskdef name: "xjc", classname: "com.sun.tools.xjc.XJCTask",
classpath: configurations.jaxb.asPath
mkdir(dir: sourcesDir)
mkdir(dir: classesDir)
xjc(destdir: sourcesDir, schema: schema,
package: "org.springframework.ws.samples.stockquote.schema") {
arg(value: "-wsdl")
produces(dir: sourcesDir, includes: "**/*.java")
}
javac(destdir: classesDir, source: 1.6, target: 1.6, debug: true,
debugLevel: "lines,vars,source",
classpath: configurations.jaxb.asPath) {
src(path: sourcesDir)
include(name: "**/*.java")
include(name: "*.java")
}
copy(todir: classesDir) {
fileset(dir: sourcesDir, erroronmissingdir: false) {
exclude(name: "**/*.java")
}
}
}
}
}
task runServer(dependsOn: 'classes', type:JavaExec) {
main = "org.springframework.ws.samples.stockquote.Driver"
standardInput = System.in
classpath = sourceSets.main.runtimeClasspath
}
dependencies {
compile("org.springframework.ws:spring-ws-core:$springWsVersion")
compile("org.springframework.ws:spring-ws-support:$springWsVersion")
compile(files(genJaxb.classesDir).builtBy(genJaxb))
runtime("log4j:log4j:1.2.16")
jaxb "com.sun.xml.bind:jaxb-xjc:2.1.7"
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.samples.stockquote;
import java.io.IOException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Driver {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext.xml", Driver.class);
System.out.println();
System.out.println("Press [Enter] to shut down...");
System.in.read();
applicationContext.close();
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright 2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.samples.stockquote.ws;
import java.util.GregorianCalendar;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import org.springframework.ws.samples.stockquote.schema.StockQuote;
import org.springframework.ws.samples.stockquote.schema.StockQuoteRequest;
import org.springframework.ws.samples.stockquote.schema.StockQuoteResponse;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.soap.addressing.server.annotation.Action;
import org.springframework.ws.soap.addressing.server.annotation.Address;
@Endpoint
@Address("http://localhost:8080/StockService")
// optional
public class StockService {
private DatatypeFactory datatypeFactory;
public StockService() throws DatatypeConfigurationException {
datatypeFactory = DatatypeFactory.newInstance();
}
@Action(value = "http://www.springframework.org/spring-ws/samples/stockquote/StockService/GetQuote",
output = "http://www.springframework.org/spring-ws/samples/stockquote/StockService/Quotes")
public StockQuoteResponse getStockQuotes(StockQuoteRequest request) {
StockQuoteResponse response = new StockQuoteResponse();
XMLGregorianCalendar now = datatypeFactory.newXMLGregorianCalendar(new GregorianCalendar());
for (String symbol : request.getSymbol()) {
StockQuote quote = new StockQuote();
quote.setSymbol(symbol);
quote.setDate(now);
if ("FABRIKAM".equals(symbol)) {
quote.setName("Fabrikam, Inc.");
quote.setLast(120.00);
quote.setChange(5.5);
}
else {
quote.setName("Contoso Corp.");
quote.setLast(50.07);
quote.setChange(1.15);
}
response.getStockQuote().add(quote);
}
return response;
}
}

View File

@@ -0,0 +1,7 @@
log4j.rootLogger=WARN, stdout
log4j.logger.org.springframework.ws=DEBUG
log4j.logger.org.springframework.xml=DEBUG
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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-2.5.xsd">
<import resource="ws/applicationContext-ws.xml"/>
<bean id="httpServer" class="org.springframework.remoting.support.SimpleHttpServerFactoryBean">
<property name="contexts">
<map>
<entry key="/StockService.wsdl" value-ref="wsdlHandler"/>
<entry key="/StockService" value-ref="soapHandler"/>
</map>
</property>
</bean>
<bean id="soapHandler" class="org.springframework.ws.transport.http.WebServiceMessageReceiverHttpHandler">
<property name="messageFactory" ref="messageFactory"/>
<property name="messageReceiver" ref="messageReceiver"/>
</bean>
<bean id="wsdlHandler" class="org.springframework.ws.transport.http.WsdlDefinitionHttpHandler">
<property name="definition" ref="wsdlDefinition"/>
</bean>
</beans>

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd
http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-1.5.xsd">
<bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"/>
<bean id="messageReceiver" class="org.springframework.ws.soap.server.SoapMessageDispatcher">
<property name="endpointAdapters">
<bean class="org.springframework.ws.server.endpoint.adapter.GenericMarshallingMethodEndpointAdapter">
<property name="marshaller" ref="marshaller"/>
<property name="unmarshaller" ref="marshaller"/>
</bean>
</property>
<property name="endpointMappings" ref="endpointMapping"/>
</bean>
<bean id="endpointMapping" class="org.springframework.ws.soap.addressing.server.AnnotationActionEndpointMapping">
<property name="messageSenders">
<bean class="org.springframework.ws.transport.http.HttpUrlConnectionMessageSender"/>
</property>
<property name="preInterceptors">
<bean class="org.springframework.ws.soap.server.endpoint.interceptor.SoapEnvelopeLoggingInterceptor"/>
</property>
</bean>
<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="contextPath" value="org.springframework.ws.samples.stockquote.schema"/>
</bean>
<bean id="wsdlDefinition" class="org.springframework.ws.wsdl.wsdl11.SimpleWsdl11Definition">
<property name="wsdl" value="classpath:/org/springframework/ws/samples/stockquote/ws/stockquote.wsdl"/>
</bean>
<bean class="org.springframework.ws.samples.stockquote.ws.StockService"/>
</beans>

View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
xmlns:tns="http://www.springframework.org/spring-ws/samples/stockquote"
targetNamespace="http://www.springframework.org/spring-ws/samples/stockquote">
<wsdl:types>
<xsd:schema xmlns:tns="http://www.springframework.org/spring-ws/samples/stockquote"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
targetNamespace="http://www.springframework.org/spring-ws/samples/stockquote">
<xsd:element name="StockQuoteRequest">
<xsd:complexType>
<xsd:sequence>
<xsd:element maxOccurs="unbounded" minOccurs="0" name="Symbol" type="tns:StockSymbol"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="StockQuoteResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element maxOccurs="unbounded" minOccurs="0" name="StockQuote" type="tns:StockQuote"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:simpleType name="StockSymbol">
<xsd:restriction base="xsd:string">
<xsd:pattern value="[A-Z]+"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="StockQuote">
<xsd:sequence>
<xsd:element minOccurs="0" name="Symbol" type="tns:StockSymbol"/>
<xsd:element minOccurs="1" name="Last" type="xsd:double"/>
<xsd:element minOccurs="1" name="Date" type="xsd:dateTime"/>
<xsd:element minOccurs="1" name="Change" type="xsd:double"/>
<xsd:element minOccurs="0" name="Name" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
</wsdl:types>
<wsdl:message name="StockQuoteRequest">
<wsdl:part element="tns:StockQuoteRequest" name="StockQuoteRequest"/>
</wsdl:message>
<wsdl:message name="StockQuoteResponse">
<wsdl:part element="tns:StockQuoteResponse" name="StockQuoteResponse"/>
</wsdl:message>
<wsdl:portType name="Stock">
<wsdl:operation name="StockQuote">
<wsdl:input message="tns:StockQuoteRequest" name="StockQuoteRequest"
wsaw:Action="http://www.springframework.org/spring-ws/samples/stockquote/StockService/GetQuote"/>
<wsdl:output message="tns:StockQuoteResponse" name="StockQuoteResponse"
wsaw:Action="http://www.springframework.org/spring-ws/samples/stockquote/StockService/Quotes"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="StockSoap11" type="tns:Stock">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsaw:UsingAddressing wsdl:required="true"/>
<wsdl:operation name="StockQuote">
<soap:operation soapAction=""/>
<wsdl:input name="StockQuoteRequest">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="StockQuoteResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="StockService">
<wsdl:port binding="tns:StockSoap11" name="StockSoap11">
<soap:address location="http://localhost:8080/StockService"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

View File

@@ -0,0 +1,2 @@
include "server", "client:jax-ws", "client:spring-ws"