Added JMS support & client.

This commit is contained in:
Arjen Poutsma
2007-11-11 19:58:18 +00:00
parent 5359621bb5
commit ccd808918f
11 changed files with 364 additions and 160 deletions

View File

@@ -4,6 +4,7 @@
<target name="clean-all">
<ant dir="axis1" target="clean"/>
<ant dir="jax-ws" target="clean"/>
<ant dir="jms" target="clean"/>
<ant dir="saaj" target="clean"/>
<ant dir="spring-ws" target="clean"/>
</target>
@@ -11,6 +12,7 @@
<target name="run-all">
<ant dir="axis1" target="run"/>
<ant dir="jax-ws" target="run"/>
<ant dir="jms" target="run"/>
<ant dir="saaj" target="run"/>
<ant dir="spring-ws" target="run"/>
</target>

View File

@@ -0,0 +1,59 @@
<?xml version="1.0"?>
<project name="spring-ws-airline-sample-saaj-client" default="build"
xmlns:artifact="urn:maven-artifact-ant">
<property name="bin.dir" value="bin"/>
<property name="src.dir" value="src"/>
<target name="init">
<typedef resource="org/apache/maven/artifact/ant/antlib.xml" uri="urn:maven-artifact-ant">
<classpath>
<pathelement location="${basedir}/../../../maven-artifact-ant-2.0.4-dep.jar"/>
</classpath>
</typedef>
<artifact:remoteRepository id="java.net" url="https://maven-repository.dev.java.net/nonav/repository"
layout="legacy"/>
<artifact:dependencies pathId="compile.classpath">
<remoteRepository refid="java.net"/>
<dependency groupId="javax.xml.soap" artifactId="saaj-api" version="1.3"/>
<dependency groupId="org.apache.activemq" artifactId="activemq-core" version="4.1.1"/>
<dependency groupId="org.springframework.ws" artifactId="spring-ws-core" version="1.1-SNAPSHOT"/>
</artifact:dependencies>
<artifact:dependencies pathId="runtime.classpath">
<remoteRepository refid="java.net"/>
<dependency groupId="com.sun.xml.messaging.saaj" artifactId="saaj-impl" version="1.3"/>
<dependency groupId="org.springframework.ws" artifactId="spring-ws-support" version="1.1-SNAPSHOT"/>
<dependency groupId="org.springframework" artifactId="spring-jms" version="2.0.7"/>
</artifact:dependencies>
</target>
<target name="build" depends="init">
<mkdir dir="${bin.dir}"/>
<javac srcdir="${src.dir}" destdir="${bin.dir}" debug="true">
<classpath refid="compile.classpath"/>
</javac>
<copy todir="${bin.dir}">
<fileset dir="${src.dir}">
<exclude name="**/*.java"/>
</fileset>
</copy>
</target>
<target name="clean">
<delete dir="${bin.dir}"/>
</target>
<target name="run" depends="build">
<java classname="org.springframework.ws.samples.airline.client.jms.JmsClient" fork="true" failonerror="true">
<classpath refid="compile.classpath"/>
<classpath refid="runtime.classpath"/>
<classpath location="${bin.dir}"/>
</java>
</target>
</project>

View File

@@ -0,0 +1,10 @@
SPRING WEB SERVICES
This directory contains a client for the Airline Web Service that uses JMS: Java Message Service. The client can be run
from the provided ant file, by calling "ant run".
JMS Client Sample table of contents
---------------------------------------------------
* src - The source files for the client
* build.xml - Ant build file with a 'build' and a 'run' target

View File

@@ -0,0 +1,7 @@
log4j.rootLogger=WARN, stdout
log4j.logger.org.springframework.ws=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,48 @@
/*
* 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.airline.client.jms;
import java.io.IOException;
import javax.jms.JMSException;
import javax.xml.soap.SOAPException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.stream.StreamResult;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.ws.client.core.support.WebServiceGatewaySupport;
import org.springframework.xml.transform.StringSource;
/** @author Arjen Poutsma */
public class JmsClient extends WebServiceGatewaySupport {
private static final String PAYLOAD =
"<airline:GetFlightsRequest xmlns:airline=\"http://www.springframework.org/spring-ws/samples/airline/schemas/messages\">" +
"<airline:from>AMS</airline:from>" + "<airline:to>VCE</airline:to>" +
"<airline:departureDate>2006-01-31</airline:departureDate>" + "</airline:GetFlightsRequest>";
public void getFlights() throws SOAPException, IOException, TransformerException, JMSException {
getWebServiceTemplate().sendSourceAndReceiveToResult(new StringSource(PAYLOAD), new StreamResult(System.out));
}
public static void main(String[] args) throws Exception {
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext.xml", JmsClient.class);
JmsClient jmsClient = (JmsClient) applicationContext.getBean("jmsClient", JmsClient.class);
jmsClient.getFlights();
}
}

View File

@@ -0,0 +1,19 @@
<?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.0.xsd">
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616"/>
</bean>
<bean id="jmsClient" class="org.springframework.ws.samples.airline.client.jms.JmsClient">
<property name="defaultUri" value="jms:RequestQueue"/>
<property name="messageSenders">
<bean class="org.springframework.ws.transport.jms.JmsMessageSender">
<property name="connectionFactory" ref="connectionFactory"/>
</bean>
</property>
</bean>
</beans>

View File

@@ -124,6 +124,11 @@
<artifactId>spring-oxm-tiger</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-support</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-security</artifactId>
@@ -146,7 +151,6 @@
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jpa</artifactId>
<version>${spring.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
@@ -166,6 +170,10 @@
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-mock</artifactId>
@@ -175,16 +183,23 @@
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>stax</groupId>
@@ -305,6 +320,17 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-core</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<version>10.3.1.4</version>
<scope>runtime</scope>
</dependency>
<!-- Test dependencies -->
<dependency>
<groupId>org.easymock</groupId>

View File

@@ -5,8 +5,8 @@
1. INTRODUCTION
Features a web service on top of an airline reservation system, backed by a database. The web service works by using XML
Marshalling techniques (JAXB2), and XPath in combination with XPath queries to pull information from a message. All
messages follow the airline.xsd schema in src/main/webapp.
Marshalling techniques (JAXB2), and XPath in combination with XPath queries to pull information from a message.
Additionally, the Airline service has JMS support. All messages follow the messages.xsd schema in src/main/webapp.
Multiple clients are available, showing interoperability with Axis 1, SAAJ, C#, and more.

View File

@@ -0,0 +1,188 @@
<?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:oxm="http://www.springframework.org/spring-ws/schema/oxm"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/spring-ws/schema/oxm http://www.springframework.org/spring-ws/schema/oxm/spring-oxm-1.1.xsd">
<bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"/>
<bean id="messageReceiver" class="org.springframework.ws.soap.server.SoapMessageDispatcher"/>
<!-- ===================== ENDPOINTS ===================================== -->
<!--
The marshallingEndpoint and xpathEndpoint handle the same messages. So, you can only use one of them at the
same time. This is done for illustration purposes only, typically you would not create two endpoints which
handle the same messages.
-->
<bean id="marshallingEndpoint" class="org.springframework.ws.samples.airline.ws.MarshallingAirlineEndpoint">
<description>
This endpoint handles the Airline Web Service messages using JAXB2 marshalling.
</description>
<constructor-arg ref="airlineService"/>
</bean>
<!--
<bean id="xpathEndpoint" class="org.springframework.ws.samples.airline.ws.XPathAirlineEndpoint">
<description>
This endpoint handles the Airline Web Service messages using XPath expressions and JAXB2 marshalling.
</description>
<constructor-arg ref="airlineService"/>
<constructor-arg ref="marshaller"/>
</bean>
-->
<bean id="getFrequentFlyerMileageEndpoint"
class="org.springframework.ws.samples.airline.ws.GetFrequentFlyerMileageEndpoint">
<description>
This endpoint handles get frequent flyer mileage requests.
</description>
<constructor-arg ref="airlineService"/>
</bean>
<oxm:jaxb2-marshaller id="marshaller" contextPath="org.springframework.ws.samples.airline.schema"/>
<!-- ===================== ENDPOINT MAPPINGS ============================== -->
<!--
The endpoint mappings map from a request to an endpoint. Because we only want the security interception to
occur for the GetFrequentFlyerMileageEndpoint, we define two mappings: one with the securityInterceptor, and
a general one without it.
-->
<bean id="annotationMapping" class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping">
<description>
Detects @PayloadRoot annotations on @Endpoint bean methods. The MarshallingAirlineEndpoint
has such annotations. It uses two interceptors: one that logs the message payload, and the other validates
it accoring to the 'airline.xsd' schema file.
</description>
<property name="interceptors">
<list>
<bean class="org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor"/>
<bean class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor">
<property name="schemas" value="/messages.xsd"/>
<property name="validateRequest" value="true"/>
<property name="validateResponse" value="true"/>
</bean>
</list>
</property>
<property name="order" value="1"/>
</bean>
<bean id="secureMapping" class="org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping">
<description>
This endpoint mapping is used for endpoints that are secured via WS-Security. It uses a
securityInterceptor, defined in applicationContext-security.xml, to validate incoming messages.
</description>
<property name="mappings">
<props>
<prop key="{http://www.springframework.org/spring-ws/samples/airline/schemas/messages}GetFrequentFlyerMileageRequest">
getFrequentFlyerMileageEndpoint
</prop>
</props>
</property>
<property name="interceptors">
<list>
<bean class="org.springframework.ws.soap.server.endpoint.interceptor.SoapEnvelopeLoggingInterceptor"/>
<ref bean="wsSecurityInterceptor"/>
</list>
</property>
<property name="order" value="2"/>
</bean>
<!-- ===================== ENDPOINT ADAPTERS ============================== -->
<!--
Endpoint adapters adapt from the incoming message to a specific object or method signature. Because this
example application uses three different endpoint programming models, we have to define three adapters. This
is done for illustration purposes only, typically you would use one adapter, for instance the
MarshallingMethodEndpointAdapter.
-->
<bean class="org.springframework.ws.server.endpoint.adapter.GenericMarshallingMethodEndpointAdapter">
<description>
This adapter allows for methods that need and returns marshalled objects. The MarshallingEndpoint
uses JAXB 2 objects.
</description>
<constructor-arg ref="marshaller"/>
</bean>
<bean class="org.springframework.ws.server.endpoint.adapter.XPathParamAnnotationMethodEndpointAdapter">
<description>
This adapter allows for methods that use @XPathParam annotations. The XPathAirlineEndpoint uses JAXB2 these.
</description>
<property name="namespaces">
<props>
<prop key="messages">http://www.springframework.org/spring-ws/samples/airline/schemas/messages</prop>
</props>
</property>
</bean>
<bean class="org.springframework.ws.server.endpoint.adapter.PayloadEndpointAdapter">
<description>
This adapter allows for endpoints which implement the PayloadEndpoint interface. The Get
FrequentFlyerMileageEndpoint implements this interface.
</description>
</bean>
<!-- ===================== ENDPOINT EXCEPTION RESOLVER ===================== -->
<!--
Endpoint exception resolvers can handle exceptions as they occur in the Web service. We have two sorts of
exceptions we want to handle: the business logic exceptions NoSeatAvailableException and NoSuchFlightException,
which both have a @SoapFault annotation, and other exceptions, which don't have the annotation. Therefore, we
have two exception resolvers here.
-->
<bean class="org.springframework.ws.soap.server.endpoint.SoapFaultAnnotationExceptionResolver">
<description>
This exception resolver maps exceptions with the @SoapFault annotation to SOAP Faults. The business logic
exceptions NoSeatAvailableException and NoSuchFlightException have these.
</description>
<property name="order" value="1"/>
</bean>
<bean class="org.springframework.ws.soap.server.endpoint.SoapFaultMappingExceptionResolver">
<description>
This exception resolver maps other exceptions to SOAP Faults. Both UnmarshallingException and
ValidationFailureException are mapped to a SOAP Fault with a "Client" fault code.
All other exceptions are mapped to a "Server" error code, the default.
</description>
<property name="defaultFault" value="SERVER"/>
<property name="exceptionMappings">
<props>
<prop key="org.springframework.oxm.UnmarshallingFailureException">CLIENT,Invalid request</prop>
<prop key="org.springframework.oxm.ValidationFailureException">CLIENT,Invalid request</prop>
</props>
</property>
<property name="order" value="2"/>
</bean>
<!-- ===================== JMS TRANSPORT ===================================== -->
<bean id="broker" class="org.apache.activemq.broker.BrokerFactory" factory-method="createBroker" init-method="start">
<constructor-arg value="broker:tcp://localhost:61616?persistent=false"/>
</bean>
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616"/>
</bean>
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destinationName" value="RequestQueue"/>
<property name="messageListener">
<bean class="org.springframework.ws.transport.jms.WebServiceMessageListener">
<property name="messageFactory" ref="messageFactory"/>
<property name="messageReceiver" ref="messageReceiver"/>
</bean>
</property>
</bean>
</beans>

View File

@@ -11,6 +11,7 @@
classpath:org/springframework/ws/samples/airline/dao/jpa/applicationContext-jpa.xml
classpath:org/springframework/ws/samples/airline/service/applicationContext.xml
classpath:org/springframework/ws/samples/airline/security/applicationContext-security.xml
classpath:org/springframework/ws/samples/airline/ws/applicationContext-ws.xml
</param-value>
</context-param>
<listener>

View File

@@ -3,162 +3,6 @@
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.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd">
<!-- ===================== ENDPOINTS ===================================== -->
<!--
The marshallingEndpoint and xpathEndpoint handle the same messages. So, you can only use one of them at the
same time. This is done for illustration purposes only, typically you would not create two endpoints which
handle the same messages.
-->
<bean id="marshallingEndpoint" class="org.springframework.ws.samples.airline.ws.MarshallingAirlineEndpoint">
<description>
This endpoint handles the Airline Web Service messages using JAXB2 marshalling.
</description>
<constructor-arg ref="airlineService"/>
</bean>
<!--
<bean id="xpathEndpoint" class="org.springframework.ws.samples.airline.ws.XPathAirlineEndpoint">
<description>
This endpoint handles the Airline Web Service messages using XPath expressions and JAXB2 marshalling.
</description>
<constructor-arg ref="airlineService"/>
<constructor-arg ref="marshaller"/>
</bean>
-->
<bean id="getFrequentFlyerMileageEndpoint"
class="org.springframework.ws.samples.airline.ws.GetFrequentFlyerMileageEndpoint">
<description>
This endpoint handles get frequent flyer mileage requests.
</description>
<constructor-arg ref="airlineService"/>
</bean>
<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<description>
The JAXB 2 Marshaller is used by the endpoints.
</description>
<property name="contextPath" value="org.springframework.ws.samples.airline.schema"/>
</bean>
<!-- ===================== ENDPOINT MAPPINGS ============================== -->
<!--
The endpoint mappings map from a request to an endpoint. Because we only want the security interception to
occur for the GetFrequentFlyerMileageEndpoint, we define two mappings: one with the securityInterceptor, and
a general one without it.
-->
<bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping">
<description>
Detects @PayloadRoot annotations on @Endpoint bean methods. The MarshallingAirlineEndpoint
has such annotations. It uses two interceptors: one that logs the message payload, and the other validates
it accoring to the 'airline.xsd' schema file.
</description>
<property name="interceptors">
<list>
<bean class="org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor"/>
<bean class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor">
<property name="schemas" value="/messages.xsd"/>
<property name="validateRequest" value="true"/>
<property name="validateResponse" value="true"/>
</bean>
</list>
</property>
<property name="order" value="1"/>
</bean>
<bean id="secureMapping" class="org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping">
<description>
This endpoint mapping is used for endpoints that are secured via WS-Security. It uses a
securityInterceptor, defined in applicationContext-security.xml, to validate incoming messages.
</description>
<property name="mappings">
<props>
<prop key="{http://www.springframework.org/spring-ws/samples/airline/schemas/messages}GetFrequentFlyerMileageRequest">
getFrequentFlyerMileageEndpoint
</prop>
</props>
</property>
<property name="interceptors">
<list>
<bean class="org.springframework.ws.soap.server.endpoint.interceptor.SoapEnvelopeLoggingInterceptor"/>
<ref bean="wsSecurityInterceptor"/>
</list>
</property>
<property name="order" value="2"/>
</bean>
<!-- ===================== ENDPOINT ADAPTERS ============================== -->
<!--
Endpoint adapters adapt from the incoming message to a specific object or method signature. Because this
example application uses three different endpoint programming models, we have to define three adapters. This
is done for illustration purposes only, typically you would use one adapter, for instance the
MarshallingMethodEndpointAdapter.
-->
<bean class="org.springframework.ws.server.endpoint.adapter.GenericMarshallingMethodEndpointAdapter">
<description>
This adapter allows for methods that need and returns marshalled objects. The MarshallingEndpoint
uses JAXB 2 objects.
</description>
<constructor-arg ref="marshaller"/>
</bean>
<bean class="org.springframework.ws.server.endpoint.adapter.XPathParamAnnotationMethodEndpointAdapter">
<description>
This adapter allows for methods that use @XPathParam annotations. The XPathAirlineEndpoint uses JAXB2 these.
</description>
<property name="namespaces">
<props>
<prop key="messages">http://www.springframework.org/spring-ws/samples/airline/schemas/messages</prop>
</props>
</property>
</bean>
<bean class="org.springframework.ws.server.endpoint.adapter.PayloadEndpointAdapter">
<description>
This adapter allows for endpoints which implement the PayloadEndpoint interface. The Get
FrequentFlyerMileageEndpoint implements this interface.
</description>
</bean>
<!-- ===================== ENDPOINT EXCEPTION RESOLVER ===================== -->
<!--
Endpoint exception resolvers can handle exceptions as they occur in the Web service. We have two sorts of
exceptions we want to handle: the business logic exceptions NoSeatAvailableException and NoSuchFlightException,
which both have a @SoapFault annotation, and other exceptions, which don't have the annotation. Therefore, we
have two exception resolvers here.
-->
<bean class="org.springframework.ws.soap.server.endpoint.SoapFaultAnnotationExceptionResolver">
<description>
This exception resolver maps exceptions with the @SoapFault annotation to SOAP Faults. The business logic
exceptions NoSeatAvailableException and NoSuchFlightException have these.
</description>
<property name="order" value="1"/>
</bean>
<bean class="org.springframework.ws.soap.server.endpoint.SoapFaultMappingExceptionResolver">
<description>
This exception resolver maps other exceptions to SOAP Faults. Both UnmarshallingException and
ValidationFailureException are mapped to a SOAP Fault with a "Client" fault code.
All other exceptions are mapped to a "Server" error code, the default.
</description>
<property name="defaultFault" value="SERVER"/>
<property name="exceptionMappings">
<props>
<prop key="org.springframework.oxm.UnmarshallingFailureException">CLIENT,Invalid request</prop>
<prop key="org.springframework.oxm.ValidationFailureException">CLIENT,Invalid request</prop>
</props>
</property>
<property name="order" value="2"/>
</bean>
<!-- ===================== WSDL DEFINITION ============================== -->