Finished airline sample.

This commit is contained in:
Arjen Poutsma
2007-06-14 22:54:21 +00:00
parent 8b1f24060a
commit b7d8f2d051
19 changed files with 240 additions and 185 deletions

View File

@@ -267,43 +267,6 @@
<artifactId>spring-mock</artifactId>
<scope>test</scope>
</dependency>
<!-- XML handling dependencies -->
<dependency>
<groupId>jdom</groupId>
<artifactId>jdom</artifactId>
</dependency>
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<scope>runtime</scope>
<exclusions>
<exclusion>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
</exclusion>
<exclusion>
<groupId>jdom</groupId>
<artifactId>jdom</artifactId>
</exclusion>
<exclusion>
<groupId>xerces</groupId>
<artifactId>xmlParserAPIs</artifactId>
</exclusion>
<exclusion>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
</exclusion>
<exclusion>
<groupId>xom</groupId>
<artifactId>xom</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>xalan</groupId>
<artifactId>xalan</artifactId>
<scope>test</scope>
</dependency>
<!-- JEE dependencies -->
<dependency>
<groupId>javax.servlet</groupId>
@@ -335,7 +298,7 @@
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>3.2.1.ga</version>
<version>3.2.4.sp1</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
@@ -371,6 +334,11 @@
<version>1.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.5.3</version>
</dependency>
<dependency>
<groupId>org.acegisecurity</groupId>
<artifactId>acegi-security</artifactId>

View File

@@ -21,6 +21,7 @@ import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
@@ -35,7 +36,7 @@ public class Flight implements Serializable {
@Id
@Column(name = "ID")
@GeneratedValue
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "NUMBER")

View File

@@ -19,6 +19,7 @@ import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
@@ -30,7 +31,7 @@ import javax.persistence.Table;
public class Passenger implements Serializable {
@Id
@GeneratedValue
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private Long id;

View File

@@ -23,6 +23,7 @@ import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
@@ -38,7 +39,7 @@ import org.joda.time.LocalDate;
public class Ticket implements Serializable {
@Id
@GeneratedValue
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "ISSUE_DATE")

View File

@@ -17,8 +17,10 @@ package org.springframework.ws.samples.airline.service;
import java.util.List;
import org.acegisecurity.annotation.Secured;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ws.samples.airline.domain.Flight;
import org.springframework.ws.samples.airline.domain.FrequentFlyer;
import org.springframework.ws.samples.airline.domain.Passenger;
@@ -30,6 +32,7 @@ import org.springframework.ws.samples.airline.domain.Ticket;
*
* @author Arjen Poutsma
*/
@Transactional(readOnly = true)
public interface AirlineService {
/**
@@ -69,6 +72,7 @@ public interface AirlineService {
* @see org.springframework.ws.samples.airline.domain.Passenger
* @see org.springframework.ws.samples.airline.domain.FrequentFlyer
*/
@Transactional(rollbackFor = {NoSuchFlightException.class, NoSeatAvailableException.class})
Ticket bookFlight(String flightNumber, DateTime departureTime, List<Passenger> passengers)
throws NoSuchFlightException, NoSeatAvailableException;
@@ -77,5 +81,6 @@ public interface AirlineService {
*
* @return the amount of frequent flyer miles
*/
@Secured({"ROLE_FREQUENT_FLYER"})
int getFrequentFlyerMileage();
}

View File

@@ -17,12 +17,15 @@
package org.springframework.ws.samples.airline.service;
import org.joda.time.DateTime;
import org.springframework.ws.soap.server.endpoint.annotation.FaultCode;
import org.springframework.ws.soap.server.endpoint.annotation.SoapFault;
/**
* Exception thrown when a specified flight cannot be found.
*
* @author Arjen Poutsma
*/
@SoapFault(faultCode = FaultCode.CLIENT)
public class NoSuchFlightException extends Exception {
private String flightNumber;

View File

@@ -17,12 +17,10 @@ package org.springframework.ws.samples.airline.service.impl;
import java.util.List;
import org.acegisecurity.annotation.Secured;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.ws.samples.airline.dao.FlightDao;
import org.springframework.ws.samples.airline.dao.TicketDao;
@@ -61,7 +59,6 @@ public class AirlineServiceImpl implements AirlineService {
this.frequentFlyerSecurityService = frequentFlyerSecurityService;
}
@Transactional(rollbackFor = {NoSuchFlightException.class, NoSeatAvailableException.class})
public Ticket bookFlight(String flightNumber, DateTime departureTime, List<Passenger> passengers)
throws NoSuchFlightException, NoSeatAvailableException {
Assert.notEmpty(passengers, "No passengers given");
@@ -96,7 +93,6 @@ public class AirlineServiceImpl implements AirlineService {
return ticketDao.save(ticket);
}
@Transactional(readOnly = true)
public Flight getFlight(Long id) throws NoSuchFlightException {
Flight flight = flightDao.getFlight(id);
if (flight != null) {
@@ -107,7 +103,6 @@ public class AirlineServiceImpl implements AirlineService {
}
}
@Transactional(readOnly = true)
public List<Flight> getFlights(String fromAirportCode,
String toAirportCode,
LocalDate departureDate,
@@ -127,9 +122,10 @@ public class AirlineServiceImpl implements AirlineService {
return flights;
}
@Transactional(readOnly = true)
@Secured({"ROLE_FREQUENT_FLYER"})
public int getFrequentFlyerMileage() {
if (logger.isDebugEnabled()) {
logger.debug("Using " + frequentFlyerSecurityService + " for security");
}
FrequentFlyer frequentFlyer = frequentFlyerSecurityService.getCurrentlyAuthenticatedFrequentFlyer();
return frequentFlyer != null ? frequentFlyer.getMiles() : 0;
}

View File

@@ -19,5 +19,13 @@ package org.springframework.ws.samples.airline.ws;
/** @author Arjen Poutsma */
public interface AirlineWebServiceConstants {
String BOOK_FLIGHT_REQUEST = "BookFlightRequest";
String GET_FLIGHTS_REQUEST = "GetFlightsRequest";
String GET_FREQUENT_FLYER_MILEAGE_RESPONSE = "GetFrequentFlyerMileageResponse";
String NAMESPACE = "http://www.springframework.org/spring-ws/samples/airline/schemas";
String GET_FREQUENT_FLYER_MILEAGE_REQUEST = "GetFrequentFlyerMileageRequest";
}

View File

@@ -0,0 +1,44 @@
/*
* 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.ws;
import org.springframework.ws.samples.airline.service.AirlineService;
import org.springframework.ws.server.endpoint.AbstractDomPayloadEndpoint;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
* Endpoint that returns the amount of frequent flyer miles for the currently logged in user. Secured via a WS-Security
* UsernameToken
*
* @author Arjen Poutsma
*/
public class GetFrequentFlyerMileageEndpoint extends AbstractDomPayloadEndpoint implements AirlineWebServiceConstants {
private final AirlineService airlineService;
public GetFrequentFlyerMileageEndpoint(AirlineService airlineService) {
this.airlineService = airlineService;
}
protected Element invokeInternal(Element ignored, Document responseDocument) throws Exception {
int mileage = airlineService.getFrequentFlyerMileage();
Element response = responseDocument.createElementNS(NAMESPACE, GET_FREQUENT_FLYER_MILEAGE_RESPONSE);
response.setTextContent(Integer.toString(mileage));
return response;
}
}

View File

@@ -58,7 +58,7 @@ public class MarshallingAirlineEndpoint implements AirlineWebServiceConstants {
private static final Log logger = LogFactory.getLog(MarshallingAirlineEndpoint.class);
private AirlineService airlineService;
private final AirlineService airlineService;
private ObjectFactory objectFactory = new ObjectFactory();
@@ -72,7 +72,7 @@ public class MarshallingAirlineEndpoint implements AirlineWebServiceConstants {
*
* @param request the JAXB2 representation of a <code>&lt;GetFlightsRequest&gt;</code>
*/
@PayloadRoot(localPart = "GetFlightsRequest", namespace = NAMESPACE)
@PayloadRoot(localPart = GET_FLIGHTS_REQUEST, namespace = NAMESPACE)
public GetFlightsResponse getFlights(GetFlightsRequest request) throws DatatypeConfigurationException {
if (logger.isDebugEnabled()) {
logger.debug("Received GetFlightsRequest '" + request.getFrom() + "' to '" + request.getTo() + "' on " +
@@ -106,7 +106,7 @@ public class MarshallingAirlineEndpoint implements AirlineWebServiceConstants {
* @param request the JAXB2 representation of a <code>&lt;BookFlightRequest&gt;</code>
* @return the JAXB2 representation of a <code>&lt;BookFlightResponse&gt;</code>
*/
@PayloadRoot(localPart = "BookFlightRequest", namespace = NAMESPACE)
@PayloadRoot(localPart = BOOK_FLIGHT_REQUEST, namespace = NAMESPACE)
public JAXBElement<Ticket> bookFlight(BookFlightRequest request)
throws NoSeatAvailableException, DatatypeConfigurationException, NoSuchFlightException {
if (logger.isDebugEnabled()) {
@@ -143,18 +143,4 @@ public class MarshallingAirlineEndpoint implements AirlineWebServiceConstants {
return SchemaConversionUtils.toSchemaType(domainTicket);
}
/**
* This endpoint method uses marshalling to handle message with a <code>&lt;GetFrequentFlyerMileageRequest&gt;</code>
* payload.
*
* @param ignored is ignored
* @return the JAXB2 representation of a <code>&lt;GetFrequentFlyerMileageResponse&gt;</code>
*/
@PayloadRoot(localPart = "GetFrequentFlyerMileageRequest", namespace = NAMESPACE)
public JAXBElement<Integer> getFrequentFlyerMileage(JAXBElement<String> ignored) {
logger.debug("Received GetFrequentFlyerMileageRequest request");
int result = airlineService.getFrequentFlyerMileage();
return objectFactory.createGetFrequentFlyerMileageResponse(result);
}
}

View File

@@ -63,11 +63,11 @@ public class XPathAirlineEndpoint implements AirlineWebServiceConstants {
private static final Log logger = LogFactory.getLog(XPathAirlineEndpoint.class);
private AirlineService airlineService;
private final AirlineService airlineService;
private ObjectFactory objectFactory = new ObjectFactory();
private Marshaller marshaller;
private final Marshaller marshaller;
public XPathAirlineEndpoint(AirlineService airlineService, Marshaller marshaller) {
Assert.notNull(airlineService, "airlineService must not be null");
@@ -84,7 +84,7 @@ public class XPathAirlineEndpoint implements AirlineWebServiceConstants {
* @param departureDateString the string representation of the departure date
* @param serviceClassString the string representation of the service class
*/
@PayloadRoot(localPart = "GetFlightsRequest", namespace = NAMESPACE)
@PayloadRoot(localPart = GET_FLIGHTS_REQUEST, namespace = NAMESPACE)
public Source getFlights(@XPathParam("//tns:from")String from,
@XPathParam("//tns:to")String to,
@XPathParam("//tns:departureDate")String departureDateString,
@@ -115,7 +115,7 @@ public class XPathAirlineEndpoint implements AirlineWebServiceConstants {
* @param passengerNodes the passenger nodes
* @param frequentFlyerNodes the frequent flyer nodes
*/
@PayloadRoot(localPart = "BookFlightRequest", namespace = NAMESPACE)
@PayloadRoot(localPart = BOOK_FLIGHT_REQUEST, namespace = NAMESPACE)
public Source bookFlight(@XPathParam("//tns:flightNumber")String flightNumber,
@XPathParam("//tns:departureTime")String departureTimeString,
@XPathParam("//tns:passengers/tns:passenger")NodeList passengerNodes,
@@ -161,17 +161,5 @@ public class XPathAirlineEndpoint implements AirlineWebServiceConstants {
}
}
/**
* This endpoint method uses XPath to handle message with a <code>&lt;GetFrequentFlyerMileageRequest&gt;</code>
* payload.
*/
@PayloadRoot(localPart = "GetFrequentFlyerMileageRequest", namespace = NAMESPACE)
public Source getFrequentFlyerMileage() {
logger.debug("Received GetFrequentFlyerMileageRequest request");
int result = airlineService.getFrequentFlyerMileage();
JAXBElement<Integer> response = objectFactory.createGetFrequentFlyerMileageResponse(result);
return new MarshallingSource(marshaller, response);
}
}

View File

@@ -25,7 +25,6 @@
</description>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">

View File

@@ -1,42 +1,30 @@
<?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">
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<description>
This application context contains the WS-Security and Acegi beans.
</description>
<aop:config>
<aop:pointcut id="getFrequentFlyerMileage"
expression="execution(* org.springframework.ws.samples.airline.service.AirlineService+.*(..))"/>
<aop:advisor advice-ref="methodSecurityInterceptor" pointcut-ref="getFrequentFlyerMileage"/>
</aop:config>
<bean id="securityService"
class="org.springframework.ws.samples.airline.security.AcegiFrequentFlyerSecurityService">
<description>
A transactional security service used to obtain Frequent Flyer information.
A security service used to obtain Frequent Flyer information.
</description>
<property name="frequentFlyerDao" ref="frequentFlyerDao"/>
<constructor-arg ref="frequentFlyerDao"/>
</bean>
<!-- ===================== WS-SECURITY ============================== -->
<bean id="secureMapping" class="org.springframework.ws.soap.server.endpoint.mapping.SoapActionEndpointMapping">
<description>
This SOAP Action endpoint mapping is used for endpoints that are secured via WS-Security. It uses a
securityInterceptor to validate incoming messages.
</description>
<property name="mappings">
<props>
<prop key="http://www.springframework.org/spring-ws/samples/airline/GetFrequentFlyerMileage">
getFrequentFlyerMileageEndpoint
</prop>
</props>
</property>
<property name="interceptors">
<list>
<bean class="org.springframework.ws.soap.server.endpoint.interceptor.SoapEnvelopeLoggingInterceptor"/>
<ref local="wsSecurityInterceptor"/>
</list>
</property>
</bean>
<bean id="wsSecurityInterceptor" class="org.springframework.ws.soap.security.xwss.XwsSecurityInterceptor">
<description>
This interceptor validates incoming messages according to the policy defined in 'securityPolicy.xml'.
@@ -53,6 +41,7 @@
</property>
</bean>
<!-- ======================== ACEGI AUTHENTICATION ======================= -->
<bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
@@ -76,7 +65,7 @@
<ref local="authenticationManager"/>
</property>
<property name="accessDecisionManager">
<bean class="org.acegisecurity.vote.UnanimousBased">
<bean class="org.acegisecurity.vote.AffirmativeBased">
<property name="decisionVoters">
<bean class="org.acegisecurity.vote.RoleVoter"/>
</property>

View File

@@ -1,53 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?><!--
~ 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.
-->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<tx:annotation-driven/>
<bean id="airlineService" class="org.springframework.ws.samples.airline.service.impl.AirlineServiceImpl">
<description>
The Airline business service. It requires a flight DAO and ticket DAO to work. The
frequentFlyerSecurityService property is not required, so we use a property to configure it.
</description>
<constructor-arg ref="flightDao"/>
<constructor-arg ref="ticketDao"/>
<property name="frequentFlyerSecurityService" ref="securityService"/>
</bean>
<bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory">
<description>
The MessageFactory is used to create new SOAP messages from incoming requests. It is referenced to in
airline-servlet.xml.
</description>
</bean>
<!--
<bean id="airlineService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="target" ref="airlineServiceTarget"/>
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributes">
<props>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="book*">PROPAGATION_REQUIRED</prop>
</props>
</property>
-->
<!-- Remove the following line if you want to disable WS-Security and Acegi -->
<!--
<property name="postInterceptors" ref="methodSecurityInterceptor"/>
</bean>
-->
</beans>

View File

@@ -10,9 +10,7 @@
<param-value>
classpath:org/springframework/ws/samples/airline/dao/jpa/applicationContext-jpa.xml
classpath:org/springframework/ws/samples/airline/service/applicationContext.xml
<!-- Remove the following line if you want to disable WS-Security and Acegi -->
<!--classpath:org/springframework/ws/samples/airline/security/applicationContext-security.xml-->
<!--classpath:org/springframework/ws/samples/airline/ws/applicationContext-ws.xml-->
classpath:org/springframework/ws/samples/airline/security/applicationContext-security.xml
</param-value>
</context-param>
<listener>

View File

@@ -8,23 +8,36 @@
<!-- ===================== ENDPOINTS ===================================== -->
<!--
<bean id="marshallingEndpoint" class="org.springframework.ws.samples.airline.ws.MarshallingAirlineEndpoint">
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 JAXB2 marshalling.
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="xpathEndpoint" class="org.springframework.ws.samples.airline.ws.XPathAirlineEndpoint">
<bean id="getFrequentFlyerMileageEndpoint"
class="org.springframework.ws.samples.airline.ws.GetFrequentFlyerMileageEndpoint">
<description>
This endpoint handles the Airline Web Service messages using XPath expressions and JAXB2 marshalling.
This endpoint handles get frequent flyer mileage requests.
</description>
<constructor-arg ref="airlineService"/>
<constructor-arg ref="marshaller"/>
</bean>
<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<description>
The JAXB 2 Marshaller is used by the endpoints.
@@ -33,9 +46,14 @@
<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
@@ -52,10 +70,40 @@
</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}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.MarshallingMethodEndpointAdapter">
<description>
This adapter allows for methods that need and returns marshalled objects. The MarshallingEndpoint
@@ -75,25 +123,44 @@
</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 exceptions to SOAP Faults. The business logic exceptions
NoSeatAvailableException and NoSuchFlightException are explictely mapped. Both
UnmarshallingException andValidationFailureException are mapped to a SOAP Fault with a "Sender" fault code.
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.ws.samples.airline.service.NoSuchFlightException">CLIENT</prop>
<prop key="org.springframework.ws.samples.airline.service.NoSeatAvailableException">SERVER</prop>
<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 ============================== -->

View File

@@ -0,0 +1,55 @@
/*
* 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.airline.ws;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import junit.framework.TestCase;
import static org.easymock.EasyMock.*;
import org.springframework.ws.samples.airline.service.AirlineService;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class GetFrequentFlyerMileageEndpointTest extends TestCase {
private GetFrequentFlyerMileageEndpoint endpoint;
private AirlineService airlineServiceMock;
private Document document;
protected void setUp() throws Exception {
airlineServiceMock = createMock(AirlineService.class);
endpoint = new GetFrequentFlyerMileageEndpoint(airlineServiceMock);
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
document = documentBuilder.newDocument();
}
public void testGetFrequentFlyerMileage() throws Exception {
expect(airlineServiceMock.getFrequentFlyerMileage()).andReturn(42);
replay(airlineServiceMock);
Element response = endpoint.invokeInternal(null, document);
assertNotNull("Invalid response", response);
verify(airlineServiceMock);
}
}

View File

@@ -189,16 +189,4 @@ public class MarshallingAirlineEndpointTest extends TestCase {
verify(airlineServiceMock);
}
public void testGetFrequentFlyerMileage() throws Exception {
JAXBElement<String> request = objectFactory.createGetFrequentFlyerMileageRequest(null);
expect(airlineServiceMock.getFrequentFlyerMileage()).andReturn(42);
replay(airlineServiceMock);
JAXBElement<Integer> response = endpoint.getFrequentFlyerMileage(request);
assertEquals("Invalid amount of miles received", 42, response.getValue().intValue());
verify(airlineServiceMock);
}
}

View File

@@ -69,16 +69,5 @@ public class XPathAirlineEndpointTest extends TestCase {
return domainFlight;
}
public void testGetFrequentFlyerMileage() throws Exception {
expect(airlineServiceMock.getFrequentFlyerMileage()).andReturn(42);
replay(airlineServiceMock);
Source response = endpoint.getFrequentFlyerMileage();
assertNotNull("Invalid response", response);
verify(airlineServiceMock);
}
}