diff --git a/core/src/main/java/org/springframework/ws/client/core/support/WebServiceGatewaySupport.java b/core/src/main/java/org/springframework/ws/client/core/support/WebServiceGatewaySupport.java index 22d348c5..7f684381 100644 --- a/core/src/main/java/org/springframework/ws/client/core/support/WebServiceGatewaySupport.java +++ b/core/src/main/java/org/springframework/ws/client/core/support/WebServiceGatewaySupport.java @@ -122,7 +122,7 @@ public abstract class WebServiceGatewaySupport implements InitializingBean { * * @see org.springframework.ws.client.core.WebServiceTemplate#marshalSendAndReceive */ - public void setMarshaller(Marshaller marshaller) { + public final void setMarshaller(Marshaller marshaller) { webServiceTemplate.setMarshaller(marshaller); } diff --git a/samples/airline/client/build.xml b/samples/airline/client/build.xml new file mode 100644 index 00000000..07d3a819 --- /dev/null +++ b/samples/airline/client/build.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/samples/airline/client/cs/bin/airline.exe b/samples/airline/client/cs/bin/airline.exe index 8938e7bb..aeba45fb 100755 Binary files a/samples/airline/client/cs/bin/airline.exe and b/samples/airline/client/cs/bin/airline.exe differ diff --git a/samples/airline/client/cs/src/AirlineService.cs b/samples/airline/client/cs/src/AirlineService.cs index 123c63f9..948a9290 100644 --- a/samples/airline/client/cs/src/AirlineService.cs +++ b/samples/airline/client/cs/src/AirlineService.cs @@ -13,6 +13,7 @@ // namespace Spring.Ws.Samples.Airline.Client.CSharp { + /// [System.Web.Services.WebServiceBinding(Name="AirlinePort", Namespace="http://www.springframework.org/spring-ws/samples/airline/definitions")] [System.Diagnostics.DebuggerStepThroughAttribute()] @@ -26,7 +27,7 @@ namespace Spring.Ws.Samples.Airline.Client.CSharp { [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://www.springframework.org/spring-ws/samples/airline/GetFlights", ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Bare, Use=System.Web.Services.Description.SoapBindingUse.Literal)] [return: System.Xml.Serialization.XmlArray(ElementName="GetFlightsResponse", Namespace="http://www.springframework.org/spring-ws/samples/airline/schemas")] [return: System.Xml.Serialization.XmlArrayItem(ElementName="flight", IsNullable=false)] - public Flight[] GetFlights([System.Xml.Serialization.XmlElement(Namespace="http://www.springframework.org/spring-ws/samples/airline/schemas")] MessageGetFlightsRequest GetFlightsRequest) { + public Flight[] GetFlights([System.Xml.Serialization.XmlElementAttribute(Namespace="http://www.springframework.org/spring-ws/samples/airline/schemas")] MessageGetFlightsRequest GetFlightsRequest) { object[] results = this.Invoke("GetFlights", new object[] { GetFlightsRequest}); return ((Flight[])(results[0])); @@ -43,8 +44,8 @@ namespace Spring.Ws.Samples.Airline.Client.CSharp { } [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://www.springframework.org/spring-ws/samples/airline/BookFlight", ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Bare, Use=System.Web.Services.Description.SoapBindingUse.Literal)] - [return: System.Xml.Serialization.XmlElement("BookFlightResponse", Namespace="http://www.springframework.org/spring-ws/samples/airline/schemas")] - public Ticket BookFlight([System.Xml.Serialization.XmlElement(Namespace="http://www.springframework.org/spring-ws/samples/airline/schemas")] MessageBookFlightRequest BookFlightRequest) { + [return: System.Xml.Serialization.XmlElementAttribute("BookFlightResponse", Namespace="http://www.springframework.org/spring-ws/samples/airline/schemas")] + public Ticket BookFlight([System.Xml.Serialization.XmlElementAttribute(Namespace="http://www.springframework.org/spring-ws/samples/airline/schemas")] MessageBookFlightRequest BookFlightRequest) { object[] results = this.Invoke("BookFlight", new object[] { BookFlightRequest}); return ((Ticket)(results[0])); @@ -61,8 +62,8 @@ namespace Spring.Ws.Samples.Airline.Client.CSharp { } [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://www.springframework.org/spring-ws/samples/airline/GetFrequentFlyerMileage", ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Bare, Use=System.Web.Services.Description.SoapBindingUse.Literal)] - [return: System.Xml.Serialization.XmlElement("GetFrequentFlyerMileageResponse", Namespace="http://www.springframework.org/spring-ws/samples/airline/schemas")] - public int GetFrequentFlyerMileage([System.Xml.Serialization.XmlElement(Namespace="http://www.springframework.org/spring-ws/samples/airline/schemas")] object GetFrequentFlyerMileageRequest) { + [return: System.Xml.Serialization.XmlElementAttribute("GetFrequentFlyerMileageResponse", Namespace="http://www.springframework.org/spring-ws/samples/airline/schemas")] + public int GetFrequentFlyerMileage([System.Xml.Serialization.XmlElementAttribute(Namespace="http://www.springframework.org/spring-ws/samples/airline/schemas")] object GetFrequentFlyerMileageRequest) { object[] results = this.Invoke("GetFrequentFlyerMileage", new object[] { GetFrequentFlyerMileageRequest}); return ((int)(results[0])); @@ -80,8 +81,8 @@ namespace Spring.Ws.Samples.Airline.Client.CSharp { } /// - [System.Xml.Serialization.XmlType(Namespace="http://www.springframework.org/spring-ws/samples/airline/schemas")] - [System.Xml.Serialization.XmlRoot("GetFlightsRequest", Namespace="http://www.springframework.org/spring-ws/samples/airline/schemas")] + [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.springframework.org/spring-ws/samples/airline/schemas")] + [System.Xml.Serialization.XmlRootAttribute("GetFlightsRequest", Namespace="http://www.springframework.org/spring-ws/samples/airline/schemas")] public class MessageGetFlightsRequest { /// @@ -91,7 +92,7 @@ namespace Spring.Ws.Samples.Airline.Client.CSharp { public string to; /// - [System.Xml.Serialization.XmlElement(DataType="date")] + [System.Xml.Serialization.XmlElementAttribute(DataType="date")] public System.DateTime departureDate; /// @@ -117,7 +118,7 @@ namespace Spring.Ws.Samples.Airline.Client.CSharp { } /// - [System.Xml.Serialization.XmlType(Namespace="http://www.springframework.org/spring-ws/samples/airline/schemas")] + [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.springframework.org/spring-ws/samples/airline/schemas")] public class Flight { /// @@ -140,7 +141,7 @@ namespace Spring.Ws.Samples.Airline.Client.CSharp { } /// - [System.Xml.Serialization.XmlType(Namespace="http://www.springframework.org/spring-ws/samples/airline/schemas")] + [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.springframework.org/spring-ws/samples/airline/schemas")] public class Airport { /// @@ -154,8 +155,8 @@ namespace Spring.Ws.Samples.Airline.Client.CSharp { } /// - [System.Xml.Serialization.XmlType(Namespace="http://www.springframework.org/spring-ws/samples/airline/schemas")] - [System.Xml.Serialization.XmlRoot("BookFlightRequest", Namespace="http://www.springframework.org/spring-ws/samples/airline/schemas")] + [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.springframework.org/spring-ws/samples/airline/schemas")] + [System.Xml.Serialization.XmlRootAttribute("BookFlightRequest", Namespace="http://www.springframework.org/spring-ws/samples/airline/schemas")] public class MessageBookFlightRequest { /// @@ -171,7 +172,7 @@ namespace Spring.Ws.Samples.Airline.Client.CSharp { } /// - [System.Xml.Serialization.XmlType(Namespace="http://www.springframework.org/spring-ws/samples/airline/schemas")] + [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.springframework.org/spring-ws/samples/airline/schemas")] public class Name { /// @@ -182,15 +183,15 @@ namespace Spring.Ws.Samples.Airline.Client.CSharp { } /// - [System.Xml.Serialization.XmlType(Namespace="http://www.springframework.org/spring-ws/samples/airline/schemas")] - [System.Xml.Serialization.XmlRoot("BookFlightResponse", Namespace="http://www.springframework.org/spring-ws/samples/airline/schemas")] + [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.springframework.org/spring-ws/samples/airline/schemas")] + [System.Xml.Serialization.XmlRootAttribute("BookFlightResponse", Namespace="http://www.springframework.org/spring-ws/samples/airline/schemas")] public class Ticket { /// public long id; /// - [System.Xml.Serialization.XmlElement(DataType="date")] + [System.Xml.Serialization.XmlElementAttribute(DataType="date")] public System.DateTime issueDate; /// @@ -200,5 +201,4 @@ namespace Spring.Ws.Samples.Airline.Client.CSharp { /// public Flight flight; } - } diff --git a/samples/airline/client/cs/src/main.cs b/samples/airline/client/cs/src/main.cs index 6b5953b3..359717e4 100644 --- a/samples/airline/client/cs/src/main.cs +++ b/samples/airline/client/cs/src/main.cs @@ -11,7 +11,7 @@ namespace Spring.Ws.Samples.Airline.Client.CSharp { if (args.Length > 0) { service.Url = args[0]; } else { - service.Url = "http://localhost:8080/airline/Airline"; + service.Url = "http://localhost:8080/airline/services"; } // Get all flights on 31st Januari, 2006 from Amsterdam to Venice MessageGetFlightsRequest getFlightsRequest = new MessageGetFlightsRequest(); diff --git a/samples/airline/client/readme.txt b/samples/airline/client/readme.txt index 8287fccb..3a9d9a29 100644 --- a/samples/airline/client/readme.txt +++ b/samples/airline/client/readme.txt @@ -1,7 +1,10 @@ SPRING WEB SERVICES +All clients can be run from the provided ant file, by calling "ant run-all". + Client table of contents --------------------------------------------------- +* build.xml - Ant build file with a 'run-all' target * axis1 - A client for the airline service written in Java using JAX-RPC (Axis 1). * cs - A client for the airline service written in C#. * jax-ws - A client for the airline service written in Java using JAX-WS. diff --git a/samples/airline/client/saaj/src/org/springframework/ws/samples/airline/client/saaj/GetFlights.java b/samples/airline/client/saaj/src/org/springframework/ws/samples/airline/client/saaj/GetFlights.java index 790894a4..4e101c49 100644 --- a/samples/airline/client/saaj/src/org/springframework/ws/samples/airline/client/saaj/GetFlights.java +++ b/samples/airline/client/saaj/src/org/springframework/ws/samples/airline/client/saaj/GetFlights.java @@ -117,7 +117,7 @@ public class GetFlights { } public static void main(String[] args) throws Exception { - String url = "http://localhost:8080/airline/Airline"; + String url = "http://localhost:8080/airline/services"; if (args.length > 0) { url = args[0]; } diff --git a/samples/airline/client/saaj/src/org/springframework/ws/samples/airline/client/saaj/GetFrequentFlyerMileage.java b/samples/airline/client/saaj/src/org/springframework/ws/samples/airline/client/saaj/GetFrequentFlyerMileage.java index 0a75b2f4..dff99b15 100644 --- a/samples/airline/client/saaj/src/org/springframework/ws/samples/airline/client/saaj/GetFrequentFlyerMileage.java +++ b/samples/airline/client/saaj/src/org/springframework/ws/samples/airline/client/saaj/GetFrequentFlyerMileage.java @@ -69,10 +69,8 @@ public class GetFrequentFlyerMileage { private SOAPMessage createGetMileageRequest() throws SOAPException { SOAPMessage message = messageFactory.createMessage(); - message.getMimeHeaders().addHeader("SOAPAction", - "\"http://www.springframework.org/spring-ws/samples/airline/GetFrequentFlyerMileage\""); SOAPEnvelope envelope = message.getSOAPPart().getEnvelope(); - Name getFlightsRequestName = envelope.createName("GetFrequentFlyerMileage", GetFrequentFlyerMileage.PREFIX, + Name getFlightsRequestName = envelope.createName("GetFrequentFlyerMileageRequest", GetFrequentFlyerMileage.PREFIX, GetFrequentFlyerMileage.NAMESPACE_URI); message.getSOAPBody().addBodyElement(getFlightsRequestName); return message; @@ -130,7 +128,7 @@ public class GetFrequentFlyerMileage { } public static void main(String[] args) throws Exception { - String url = "http://localhost:8080/airline/Airline"; + String url = "http://localhost:8080/airline/services"; if (args.length < 2) { System.err.println( "Usage: java org.springframework.ws.samples.airline.client.saaj.GetFrequentFlyerMileage " + diff --git a/samples/airline/pom.xml b/samples/airline/pom.xml index dca5dd99..bce3bbaf 100644 --- a/samples/airline/pom.xml +++ b/samples/airline/pom.xml @@ -1,4 +1,6 @@ - + spring-ws-samples org.springframework.ws @@ -8,7 +10,19 @@ airline war Spring WS Airline Sample + + + + maven-javadoc-plugin + + ${basedir}/../../src/main/javadoc/javadoc.css + + + + + hsqldb @@ -23,10 +37,10 @@ org.hsqldb.jdbcDriver sa - + jdbc:hsqldb:hsql://localhost/airline org.hibernate.dialect.HSQLDialect - + @@ -70,7 +84,7 @@ airline jdbc:mysql://localhost/airline org.hibernate.dialect.MySQLInnoDBDialect - + @@ -114,7 +128,7 @@ airline jdbc:postgresql://localhost/airline org.hibernate.dialect.PostgreSQLDialect - + @@ -148,11 +162,19 @@ The following values are for using an in-memory database, which is used for testing --> org.hsqldb.jdbcDriver sa - + jdbc:hsqldb:mem:airline org.hibernate.dialect.HSQLDialect create-drop + + + java.net + Java.net Repository for Maven2 + http://download.java.net/maven/1/ + legacy + + @@ -173,23 +195,27 @@ org.apache.maven.plugins - maven-antrun-plugin + maven-compiler-plugin + + 1.5 + 1.5 + + + + com.sun.tools.xjc.maven2 + maven-jaxb-plugin generate-sources - - - - - - - ${project.build.directory}/generated-sources/main/java - - run + generate + + org.springframework.ws.samples.airline.schema + src/main/webapp/WEB-INF/xsd + @@ -201,11 +227,11 @@ org.springframework.ws - spring-ws-core + spring-ws-core-tiger org.springframework.ws - spring-oxm + spring-oxm-tiger org.springframework.ws @@ -224,7 +250,8 @@ org.springframework - spring-hibernate3 + spring-jpa + ${spring.version} org.springframework @@ -238,6 +265,7 @@ org.springframework spring-mock + test @@ -276,37 +304,34 @@ xalan test + + + javax.servlet + servlet-api + + + taglibs + standard + 1.1.2 + javax.xml.bind jaxb-api - 1.0 + 2.1 com.sun.xml.bind jaxb-impl - 1.0.6 - compile - - - com.sun.xml.bind - jaxb-libs - 1.0.6 - compile - - - com.sun.xml.bind - jaxb-xjc - 1.0.6 + 2.1.3 runtime - - com.sun.msv.datatype.xsd - xsdlib - 20060615 - compile - + + org.hibernate + hibernate-entitymanager + 3.2.1.ga + org.hibernate hibernate @@ -340,6 +365,12 @@ joda-time 1.4 + + joda-time + joda-time-jsptags + 1.0 + runtime + org.acegisecurity acegi-security @@ -375,10 +406,22 @@ - joda-time - joda-time-hibernate - 0.8 - runtime + org.acegisecurity + acegi-security-tiger + 1.0.3 + + + org.springframework + spring-aop + + + + + + org.easymock + easymock + test + 2.2 diff --git a/samples/airline/src/main/java/org/springframework/ws/samples/airline/dao/FlightDao.java b/samples/airline/src/main/java/org/springframework/ws/samples/airline/dao/FlightDao.java index 7a19c1e8..dc8c18c5 100644 --- a/samples/airline/src/main/java/org/springframework/ws/samples/airline/dao/FlightDao.java +++ b/samples/airline/src/main/java/org/springframework/ws/samples/airline/dao/FlightDao.java @@ -25,10 +25,12 @@ import org.springframework.ws.samples.airline.domain.ServiceClass; public interface FlightDao { - List findFlights(String fromAirportCode, String toAirportCode, Interval interval, ServiceClass serviceClass) + List findFlights(String fromAirportCode, String toAirportCode, Interval interval, ServiceClass serviceClass) throws DataAccessException; + Flight getFlight(Long id); + Flight getFlight(String flightNumber, DateTime departureTime); - void update(Flight flight); + Flight update(Flight flight); } diff --git a/samples/airline/src/main/java/org/springframework/ws/samples/airline/dao/FrequentFlyerDao.java b/samples/airline/src/main/java/org/springframework/ws/samples/airline/dao/FrequentFlyerDao.java index 2a5c8541..e889cc97 100644 --- a/samples/airline/src/main/java/org/springframework/ws/samples/airline/dao/FrequentFlyerDao.java +++ b/samples/airline/src/main/java/org/springframework/ws/samples/airline/dao/FrequentFlyerDao.java @@ -23,6 +23,4 @@ public interface FrequentFlyerDao { FrequentFlyer get(String username) throws DataAccessException; - void update(FrequentFlyer frequentFlyer) throws DataAccessException; - } diff --git a/samples/airline/src/main/java/org/springframework/ws/samples/airline/dao/TicketDao.java b/samples/airline/src/main/java/org/springframework/ws/samples/airline/dao/TicketDao.java index e3be0acd..44833eea 100644 --- a/samples/airline/src/main/java/org/springframework/ws/samples/airline/dao/TicketDao.java +++ b/samples/airline/src/main/java/org/springframework/ws/samples/airline/dao/TicketDao.java @@ -21,6 +21,6 @@ import org.springframework.ws.samples.airline.domain.Ticket; public interface TicketDao { - void save(Ticket ticket) throws DataAccessException; + Ticket save(Ticket ticket) throws DataAccessException; } diff --git a/samples/airline/src/main/java/org/springframework/ws/samples/airline/dao/jpa/JpaFlightDao.java b/samples/airline/src/main/java/org/springframework/ws/samples/airline/dao/jpa/JpaFlightDao.java new file mode 100644 index 00000000..52017077 --- /dev/null +++ b/samples/airline/src/main/java/org/springframework/ws/samples/airline/dao/jpa/JpaFlightDao.java @@ -0,0 +1,68 @@ +/* + * 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.dao.jpa; + +import java.util.List; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; + +import org.joda.time.DateTime; +import org.joda.time.Interval; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Repository; +import org.springframework.ws.samples.airline.dao.FlightDao; +import org.springframework.ws.samples.airline.domain.Flight; +import org.springframework.ws.samples.airline.domain.ServiceClass; + +@Repository +public class JpaFlightDao implements FlightDao { + + @PersistenceContext + private EntityManager entityManager; + + public List findFlights(String fromAirportCode, + String toAirportCode, + Interval interval, + ServiceClass serviceClass) throws DataAccessException { + Query query = entityManager.createQuery("FROM Flight f WHERE f.from.code = :from " + + "AND f.to.code = :to AND f.departureTime >= :start AND f.departureTime <= :end AND " + + "f.serviceClass = :class"); + query.setParameter("from", fromAirportCode); + query.setParameter("to", toAirportCode); + query.setParameter("start", interval.getStart()); + query.setParameter("end", interval.getEnd()); + query.setParameter("class", serviceClass); + return query.getResultList(); + } + + public Flight getFlight(Long id) { + return entityManager.find(Flight.class, id); + } + + public Flight getFlight(String flightNumber, DateTime departureTime) { + Query query = entityManager + .createQuery("FROM Flight f WHERE f.number = :number AND f.departureTime = :departureTime"); + query.setParameter("number", flightNumber); + query.setParameter("departureTime", departureTime); + return (Flight) query.getSingleResult(); + } + + public Flight update(Flight flight) { + return entityManager.merge(flight); + } +} diff --git a/samples/airline/src/main/java/org/springframework/ws/samples/airline/dao/jpa/JpaFrequentFlyerDao.java b/samples/airline/src/main/java/org/springframework/ws/samples/airline/dao/jpa/JpaFrequentFlyerDao.java new file mode 100644 index 00000000..0449c812 --- /dev/null +++ b/samples/airline/src/main/java/org/springframework/ws/samples/airline/dao/jpa/JpaFrequentFlyerDao.java @@ -0,0 +1,40 @@ +/* + * 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.dao.jpa; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; + +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Repository; +import org.springframework.ws.samples.airline.dao.FrequentFlyerDao; +import org.springframework.ws.samples.airline.domain.FrequentFlyer; + +@Repository +public class JpaFrequentFlyerDao implements FrequentFlyerDao { + + @PersistenceContext + private EntityManager entityManager; + + public FrequentFlyer get(String username) throws DataAccessException { + Query query = entityManager.createQuery("FROM FrequentFlyer f WHERE f.username = :username"); + query.setParameter("username", username); + return (FrequentFlyer) query.getSingleResult(); + } + +} diff --git a/samples/airline/src/main/java/org/springframework/ws/samples/airline/dao/jpa/JpaTicketDao.java b/samples/airline/src/main/java/org/springframework/ws/samples/airline/dao/jpa/JpaTicketDao.java new file mode 100644 index 00000000..e4a1517e --- /dev/null +++ b/samples/airline/src/main/java/org/springframework/ws/samples/airline/dao/jpa/JpaTicketDao.java @@ -0,0 +1,36 @@ +/* + * 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.dao.jpa; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Repository; +import org.springframework.ws.samples.airline.dao.TicketDao; +import org.springframework.ws.samples.airline.domain.Ticket; + +@Repository +public class JpaTicketDao implements TicketDao { + + @PersistenceContext + private EntityManager entityManager; + + public Ticket save(Ticket ticket) throws DataAccessException { + return entityManager.merge(ticket); + } +} diff --git a/samples/airline/src/main/java/org/springframework/ws/samples/airline/domain/Airport.java b/samples/airline/src/main/java/org/springframework/ws/samples/airline/domain/Airport.java index 36c43240..d9951a03 100644 --- a/samples/airline/src/main/java/org/springframework/ws/samples/airline/domain/Airport.java +++ b/samples/airline/src/main/java/org/springframework/ws/samples/airline/domain/Airport.java @@ -17,13 +17,23 @@ package org.springframework.ws.samples.airline.domain; import java.io.Serializable; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +@Entity +@Table(name = "AIRPORT") public class Airport implements Serializable { + @Id + @Column(name = "CODE") private String code; + @Column(name = "NAME") private String name; + @Column(name = "CITY") private String city; public Airport() { @@ -39,26 +49,14 @@ public class Airport implements Serializable { return city; } - public void setCity(String city) { - this.city = city; - } - public String getCode() { return code; } - public void setCode(String code) { - this.code = code; - } - public String getName() { return name; } - public void setName(String name) { - this.name = name; - } - public boolean equals(Object other) { if (this == other) { return true; @@ -67,7 +65,7 @@ public class Airport implements Serializable { return false; } final Airport that = (Airport) other; - return this.code.equals(that.code); + return code.equals(that.code); } public int hashCode() { diff --git a/samples/airline/src/main/java/org/springframework/ws/samples/airline/domain/Flight.java b/samples/airline/src/main/java/org/springframework/ws/samples/airline/domain/Flight.java index 316bf2c9..d5248a6a 100644 --- a/samples/airline/src/main/java/org/springframework/ws/samples/airline/domain/Flight.java +++ b/samples/airline/src/main/java/org/springframework/ws/samples/airline/domain/Flight.java @@ -15,26 +15,69 @@ */ package org.springframework.ws.samples.airline.domain; +import java.io.Serializable; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; + +import org.hibernate.annotations.Type; import org.joda.time.DateTime; -public class Flight extends Entity { +@Entity +@Table(name = "FLIGHT") +public class Flight implements Serializable { + @Id + @Column(name = "ID") + @GeneratedValue + private Long id; + + @Column(name = "NUMBER") private String number; + @Column(name = "DEPARTURE_TIME") + @Type(type = "org.springframework.ws.samples.airline.domain.hibernate.DateTimeUserType") private DateTime departureTime; - private DateTime arrivalTime; - - private Airport to; - + @ManyToOne + @JoinColumn(name = "FROM_AIRPORT_CODE", nullable = false) private Airport from; + @Column(name = "ARRIVAL_TIME") + @Type(type = "org.springframework.ws.samples.airline.domain.hibernate.DateTimeUserType") + private DateTime arrivalTime; + + @ManyToOne + @JoinColumn(name = "TO_AIRPORT_CODE", nullable = false) + private Airport to; + + @Column(name = "SERVICE_CLASS") + @Enumerated(EnumType.STRING) private ServiceClass serviceClass; + @Column(name = "SEATS_AVAILABLE") private int seatsAvailable; + @Column(name = "MILES") private int miles; + public Flight() { + } + + public Flight(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + public DateTime getArrivalTime() { return arrivalTime; } @@ -99,6 +142,10 @@ public class Flight extends Entity { this.to = to; } + public void substractSeats(int count) { + seatsAvailable -= count; + } + public boolean equals(Object o) { if (this == o) { return true; @@ -120,8 +167,7 @@ public class Flight extends Entity { } public int hashCode() { - int result; - result = number.hashCode(); + int result = number.hashCode(); result = 29 * result + departureTime.hashCode(); return result; } @@ -130,11 +176,7 @@ public class Flight extends Entity { StringBuffer buffer = new StringBuffer(); buffer.append(getNumber()); buffer.append(' '); - buffer.append(getDepartureTime()); + buffer.append(getDepartureTime().toString()); return buffer.toString(); } - - public void substractSeats(int count) { - this.seatsAvailable -= count; - } } diff --git a/samples/airline/src/main/java/org/springframework/ws/samples/airline/domain/FrequentFlyer.java b/samples/airline/src/main/java/org/springframework/ws/samples/airline/domain/FrequentFlyer.java index 4ac222b8..7e428ea3 100644 --- a/samples/airline/src/main/java/org/springframework/ws/samples/airline/domain/FrequentFlyer.java +++ b/samples/airline/src/main/java/org/springframework/ws/samples/airline/domain/FrequentFlyer.java @@ -16,12 +16,23 @@ package org.springframework.ws.samples.airline.domain; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.PrimaryKeyJoinColumn; +import javax.persistence.Table; + +@Entity +@Table(name = "FREQUENT_FLYER") +@PrimaryKeyJoinColumn(name = "PASSENGER_ID") public class FrequentFlyer extends Passenger { + @Column(name = "USERNAME") private String username; + @Column(name = "PASSWORD") private String password; + @Column(name = "MILES") private int miles; public FrequentFlyer() { @@ -31,7 +42,7 @@ public class FrequentFlyer extends Passenger { this.username = username; } - public FrequentFlyer(String username, String password, String firstName, String lastName) { + public FrequentFlyer(String firstName, String lastName, String username, String password) { super(firstName, lastName); this.username = username; this.password = password; @@ -69,13 +80,17 @@ public class FrequentFlyer extends Passenger { return false; } final FrequentFlyer that = (FrequentFlyer) other; - return this.username.equals(that.username); + return username.equals(that.username); } public int hashCode() { return username.hashCode(); } + public String toString() { + return username; + } + public void addMiles(int miles) { this.miles += miles; } diff --git a/samples/airline/src/main/java/org/springframework/ws/samples/airline/domain/Passenger.java b/samples/airline/src/main/java/org/springframework/ws/samples/airline/domain/Passenger.java index d7af0730..28d75be4 100644 --- a/samples/airline/src/main/java/org/springframework/ws/samples/airline/domain/Passenger.java +++ b/samples/airline/src/main/java/org/springframework/ws/samples/airline/domain/Passenger.java @@ -15,24 +15,61 @@ */ package org.springframework.ws.samples.airline.domain; -import org.springframework.util.Assert; +import java.io.Serializable; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; +import javax.persistence.Table; -public class Passenger extends Entity { +@Entity +@Table(name = "PASSENGER") +@Inheritance(strategy = InheritanceType.JOINED) +public class Passenger implements Serializable { + @Id + @GeneratedValue + @Column(name = "ID") + private Long id; + + @Column(name = "FIRST_NAME") private String firstName; + @Column(name = "LAST_NAME") private String lastName; public Passenger() { } public Passenger(String firstName, String lastName) { - Assert.hasLength(firstName); - Assert.hasLength(lastName); this.firstName = firstName; this.lastName = lastName; } + public Passenger(Long id, String firstName, String lastName) { + this.id = id; + this.firstName = firstName; + this.lastName = lastName; + } + + public String getFirstName() { + return firstName; + } + + public Long getId() { + return id; + } + + public String getLastName() { + return lastName; + } + + public String toString() { + return firstName + " " + lastName; + } + public boolean equals(Object o) { if (this == o) { return true; @@ -58,24 +95,4 @@ public class Passenger extends Entity { result = 29 * result + getLastName().hashCode(); return result; } - - public String getFirstName() { - return firstName; - } - - public void setFirstName(String firstName) { - this.firstName = firstName; - } - - public String getLastName() { - return lastName; - } - - public void setLastName(String lastName) { - this.lastName = lastName; - } - - public String toString() { - return firstName + " " + lastName; - } } diff --git a/samples/airline/src/main/java/org/springframework/ws/samples/airline/domain/ServiceClass.java b/samples/airline/src/main/java/org/springframework/ws/samples/airline/domain/ServiceClass.java index 2e1992ab..2c6dc5d3 100644 --- a/samples/airline/src/main/java/org/springframework/ws/samples/airline/domain/ServiceClass.java +++ b/samples/airline/src/main/java/org/springframework/ws/samples/airline/domain/ServiceClass.java @@ -16,41 +16,11 @@ package org.springframework.ws.samples.airline.domain; -import java.io.Serializable; -import java.util.HashMap; -import java.util.Map; +public enum ServiceClass { -public class ServiceClass implements Serializable { + ECONOMY, - private String name; + BUSINESS, - public static final ServiceClass ECONOMY = new ServiceClass("economy"); - - public static final ServiceClass BUSINESS = new ServiceClass("business"); - - public static final ServiceClass FIRST = new ServiceClass("first"); - - private static final Map INSTANCES = new HashMap(); - - static { - INSTANCES.put(ECONOMY.toString(), ECONOMY); - INSTANCES.put(BUSINESS.toString(), BUSINESS); - INSTANCES.put(FIRST.toString(), FIRST); - } - - private ServiceClass(String name) { - this.name = name; - } - - public String toString() { - return name; - } - - Object readResolve() { - return getInstance(name); - } - - public static ServiceClass getInstance(String name) { - return (ServiceClass) INSTANCES.get(name); - } + FIRST } diff --git a/samples/airline/src/main/java/org/springframework/ws/samples/airline/domain/Ticket.java b/samples/airline/src/main/java/org/springframework/ws/samples/airline/domain/Ticket.java index d86058d7..cc6abc5d 100644 --- a/samples/airline/src/main/java/org/springframework/ws/samples/airline/domain/Ticket.java +++ b/samples/airline/src/main/java/org/springframework/ws/samples/airline/domain/Ticket.java @@ -16,19 +16,56 @@ package org.springframework.ws.samples.airline.domain; +import java.io.Serializable; import java.util.HashSet; import java.util.Set; +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.ManyToMany; +import javax.persistence.ManyToOne; +import javax.persistence.Table; -import org.joda.time.YearMonthDay; +import org.hibernate.annotations.Type; +import org.joda.time.LocalDate; -public class Ticket extends Entity { +@Entity +@Table(name = "TICKET") +public class Ticket implements Serializable { - private YearMonthDay issueDate; + @Id + @GeneratedValue + private Long id; - private Set passengers = new HashSet(); + @Column(name = "ISSUE_DATE") + @Type(type = "org.springframework.ws.samples.airline.domain.hibernate.LocalDateUserType") + private LocalDate issueDate; + @ManyToOne + @JoinColumn(name = "FLIGHT_ID", nullable = false) private Flight flight; + @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}) + @JoinTable(name = "PASSENGER_TICKET", + joinColumns = @JoinColumn(name = "TICKET_ID"), + inverseJoinColumns = @JoinColumn(name = "PASSENGER_ID")) + private Set passengers = new HashSet(); + + public Ticket() { + } + + public Ticket(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + public Flight getFlight() { return flight; } @@ -37,19 +74,19 @@ public class Ticket extends Entity { this.flight = flight; } - public YearMonthDay getIssueDate() { + public LocalDate getIssueDate() { return issueDate; } - public void setIssueDate(YearMonthDay issueDate) { + public void setIssueDate(LocalDate issueDate) { this.issueDate = issueDate; } - public Set getPassengers() { + public Set getPassengers() { return passengers; } - public void setPassengers(Set passengers) { + public void setPassengers(Set passengers) { this.passengers = passengers; } diff --git a/samples/airline/src/main/java/org/springframework/ws/samples/airline/domain/hibernate/DateTimeUserType.java b/samples/airline/src/main/java/org/springframework/ws/samples/airline/domain/hibernate/DateTimeUserType.java new file mode 100644 index 00000000..1f4e320b --- /dev/null +++ b/samples/airline/src/main/java/org/springframework/ws/samples/airline/domain/hibernate/DateTimeUserType.java @@ -0,0 +1,88 @@ +/* + * 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.domain.hibernate; + +import java.io.Serializable; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.sql.Types; + +import org.hibernate.HibernateException; +import org.hibernate.usertype.UserType; +import org.joda.time.DateTime; + +/** @author Arjen Poutsma */ +public class DateTimeUserType implements UserType { + + public int[] sqlTypes() { + return new int[]{Types.TIMESTAMP}; + } + + public Class returnedClass() { + return DateTime.class; + } + + public boolean isMutable() { + return false; + } + + public Object deepCopy(Object value) throws HibernateException { + return value; + } + + public Serializable disassemble(Object value) throws HibernateException { + return (Serializable) value; + } + + public Object assemble(Serializable cached, Object owner) throws HibernateException { + return cached; + } + + public Object replace(Object original, Object target, Object owner) throws HibernateException { + return original; + } + + public boolean equals(Object x, Object y) throws HibernateException { + return x == y || !(x == null || y == null) && x.equals(y); + } + + public int hashCode(Object x) throws HibernateException { + return x.hashCode(); + } + + public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException { + Timestamp timestamp = rs.getTimestamp(names[0]); + if (rs.wasNull()) { + return null; + } + return new DateTime(timestamp); + } + + public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException { + if (value == null) { + st.setNull(index, Types.TIMESTAMP); + } + else { + DateTime dateTime = (DateTime) value; + Timestamp timestamp = new Timestamp(dateTime.getMillis()); + st.setTimestamp(index, timestamp); + } + } + +} diff --git a/samples/airline/src/main/java/org/springframework/ws/samples/airline/domain/hibernate/LocalDateUserType.java b/samples/airline/src/main/java/org/springframework/ws/samples/airline/domain/hibernate/LocalDateUserType.java new file mode 100644 index 00000000..45d63868 --- /dev/null +++ b/samples/airline/src/main/java/org/springframework/ws/samples/airline/domain/hibernate/LocalDateUserType.java @@ -0,0 +1,93 @@ +/* + * 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.domain.hibernate; + +import java.io.Serializable; +import java.sql.Date; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Types; + +import org.hibernate.HibernateException; +import org.hibernate.dialect.Dialect; +import org.hibernate.type.LiteralType; +import org.hibernate.usertype.UserType; +import org.joda.time.LocalDate; + +public class LocalDateUserType implements UserType, LiteralType { + + public int[] sqlTypes() { + return new int[]{Types.DATE}; + } + + public Class returnedClass() { + return LocalDate.class; + } + + public boolean isMutable() { + return false; + } + + public Object deepCopy(Object value) throws HibernateException { + return value; + } + + public Serializable disassemble(Object value) throws HibernateException { + return (Serializable) value; + } + + public Object assemble(Serializable cached, Object owner) throws HibernateException { + return cached; + } + + public Object replace(Object original, Object target, Object owner) throws HibernateException { + return original; + } + + public boolean equals(Object x, Object y) throws HibernateException { + return x == y || !(x == null || y == null) && x.equals(y); + } + + public int hashCode(Object x) throws HibernateException { + return x.hashCode(); + } + + public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException { + Date sqlDate = rs.getDate(names[0]); + if (rs.wasNull()) { + return null; + } + return new LocalDate(sqlDate.getTime()); + } + + public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException { + if (value == null) { + st.setNull(index, Types.DATE); + } + else { + LocalDate localDate = (LocalDate) value; + Date sqlDate = new Date(localDate.toDateMidnight().getMillis()); + st.setDate(index, sqlDate); + } + } + + public String objectToSQLString(Object value, Dialect dialect) throws Exception { + LocalDate localDate = (LocalDate) value; + return localDate.toString(); + } +} diff --git a/samples/airline/src/main/java/org/springframework/ws/samples/airline/security/AcegiFrequentFlyerSecurityService.java b/samples/airline/src/main/java/org/springframework/ws/samples/airline/security/AcegiFrequentFlyerSecurityService.java index d2abe19c..e1b3cea6 100644 --- a/samples/airline/src/main/java/org/springframework/ws/samples/airline/security/AcegiFrequentFlyerSecurityService.java +++ b/samples/airline/src/main/java/org/springframework/ws/samples/airline/security/AcegiFrequentFlyerSecurityService.java @@ -19,7 +19,11 @@ package org.springframework.ws.samples.airline.security; import org.acegisecurity.Authentication; import org.acegisecurity.context.SecurityContext; import org.acegisecurity.context.SecurityContextHolder; - +import org.acegisecurity.userdetails.UserDetails; +import org.acegisecurity.userdetails.UserDetailsService; +import org.acegisecurity.userdetails.UsernameNotFoundException; +import org.springframework.dao.DataAccessException; +import org.springframework.transaction.annotation.Transactional; import org.springframework.ws.samples.airline.dao.FrequentFlyerDao; import org.springframework.ws.samples.airline.domain.FrequentFlyer; @@ -28,14 +32,15 @@ import org.springframework.ws.samples.airline.domain.FrequentFlyer; * * @author Arjen Poutsma */ -public class AcegiFrequentFlyerSecurityService implements FrequentFlyerSecurityService { +public class AcegiFrequentFlyerSecurityService implements FrequentFlyerSecurityService, UserDetailsService { private FrequentFlyerDao frequentFlyerDao; - public void setFrequentFlyerDao(FrequentFlyerDao frequentFlyerDao) { + public AcegiFrequentFlyerSecurityService(FrequentFlyerDao frequentFlyerDao) { this.frequentFlyerDao = frequentFlyerDao; } + @Transactional public FrequentFlyer getCurrentlyAuthenticatedFrequentFlyer() { SecurityContext context = SecurityContextHolder.getContext(); Authentication authentication = context.getAuthentication(); @@ -53,7 +58,20 @@ public class AcegiFrequentFlyerSecurityService implements FrequentFlyerSecurityS } } + @Transactional public FrequentFlyer getFrequentFlyer(String username) { return frequentFlyerDao.get(username); } + + @Transactional + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { + FrequentFlyer frequentFlyer = frequentFlyerDao.get(username); + if (frequentFlyer != null) { + return new FrequentFlyerDetails(frequentFlyer); + } + else { + throw new UsernameNotFoundException("Frequent flyer '" + username + "' not found"); + } + } + } diff --git a/samples/airline/src/main/java/org/springframework/ws/samples/airline/security/StubFrequentFlyerSecurityService.java b/samples/airline/src/main/java/org/springframework/ws/samples/airline/security/StubFrequentFlyerSecurityService.java index e9c5b029..cb32da1c 100644 --- a/samples/airline/src/main/java/org/springframework/ws/samples/airline/security/StubFrequentFlyerSecurityService.java +++ b/samples/airline/src/main/java/org/springframework/ws/samples/airline/security/StubFrequentFlyerSecurityService.java @@ -30,11 +30,7 @@ public class StubFrequentFlyerSecurityService implements FrequentFlyerSecuritySe private FrequentFlyer john; public StubFrequentFlyerSecurityService() { - john = new FrequentFlyer(); - john.setUsername("john"); - john.setFirstName("John"); - john.setLastName("Doe"); - john.setPassword("changeme"); + john = new FrequentFlyer("John", "Doe", "john", "changeme"); john.setMiles(10); } diff --git a/samples/airline/src/main/java/org/springframework/ws/samples/airline/service/AirlineService.java b/samples/airline/src/main/java/org/springframework/ws/samples/airline/service/AirlineService.java index 5cea9e1b..c997e668 100644 --- a/samples/airline/src/main/java/org/springframework/ws/samples/airline/service/AirlineService.java +++ b/samples/airline/src/main/java/org/springframework/ws/samples/airline/service/AirlineService.java @@ -19,6 +19,9 @@ import java.util.List; import org.joda.time.DateTime; import org.joda.time.LocalDate; +import org.springframework.ws.samples.airline.domain.Flight; +import org.springframework.ws.samples.airline.domain.FrequentFlyer; +import org.springframework.ws.samples.airline.domain.Passenger; import org.springframework.ws.samples.airline.domain.ServiceClass; import org.springframework.ws.samples.airline.domain.Ticket; @@ -29,6 +32,15 @@ import org.springframework.ws.samples.airline.domain.Ticket; */ public interface AirlineService { + /** + * Returns a single Flight with the given id. + * + * @param id the flight identifier + * @return the flight + * @throws NoSuchFlightException if a flight with the specified flight iddoes not exist + */ + Flight getFlight(Long id) throws NoSuchFlightException; + /** * Returns a list of Flight objects that fall within the specified criteria. * @@ -37,25 +49,27 @@ public interface AirlineService { * @param departureDate the date of the flights * @param serviceClass the desired service class level. May be null * @return a list of flights - * @see org.springframework.ws.samples.airline.domain.Flight */ - List getFlights(String fromAirportCode, String toAirportCode, LocalDate departureDate, ServiceClass serviceClass); + List getFlights(String fromAirportCode, + String toAirportCode, + LocalDate departureDate, + ServiceClass serviceClass); /** * Books a single flight for a number of passengers. Passengers can be either specified by name or by frequent flyer - * username. If a FrequentFlyer is specified, the first and last name are looked up in the database. + * username. If a {@link FrequentFlyer} is specified, the first and last name are looked up in the database. * * @param flightNumber the number of the flight to book * @param departureTime the departure time of the flight to book - * @param passengers the list of passengers for the flight to book. Can be either Passengers with a - * first and last name, or FrequentFlyers with a username. + * @param passengers the list of passengers for the flight to book. Can be either {@link Passenger} objects with + * a first and last name, or {@link FrequentFlyer} objects with a username. * @return the created ticket * @throws NoSuchFlightException if a flight with the specified flight number and departure time does not exist * @throws NoSeatAvailableException if not enough seats are available for the flight * @see org.springframework.ws.samples.airline.domain.Passenger * @see org.springframework.ws.samples.airline.domain.FrequentFlyer */ - Ticket bookFlight(String flightNumber, DateTime departureTime, List passengers) + Ticket bookFlight(String flightNumber, DateTime departureTime, List passengers) throws NoSuchFlightException, NoSeatAvailableException; /** diff --git a/samples/airline/src/main/java/org/springframework/ws/samples/airline/service/NoSeatAvailableException.java b/samples/airline/src/main/java/org/springframework/ws/samples/airline/service/NoSeatAvailableException.java index 8ff3f844..d04c62da 100644 --- a/samples/airline/src/main/java/org/springframework/ws/samples/airline/service/NoSeatAvailableException.java +++ b/samples/airline/src/main/java/org/springframework/ws/samples/airline/service/NoSeatAvailableException.java @@ -17,12 +17,15 @@ package org.springframework.ws.samples.airline.service; import org.springframework.ws.samples.airline.domain.Flight; +import org.springframework.ws.soap.server.endpoint.annotation.FaultCode; +import org.springframework.ws.soap.server.endpoint.annotation.SoapFault; /** * Exception thrown when not enough seats are available for a flight. * * @author Arjen Poutsma */ +@SoapFault(faultCode = FaultCode.SERVER) public class NoSeatAvailableException extends Exception { private Flight flight; diff --git a/samples/airline/src/main/java/org/springframework/ws/samples/airline/service/NoSuchFlightException.java b/samples/airline/src/main/java/org/springframework/ws/samples/airline/service/NoSuchFlightException.java index e38c552e..d8ffbc5a 100644 --- a/samples/airline/src/main/java/org/springframework/ws/samples/airline/service/NoSuchFlightException.java +++ b/samples/airline/src/main/java/org/springframework/ws/samples/airline/service/NoSuchFlightException.java @@ -35,6 +35,10 @@ public class NoSuchFlightException extends Exception { this.departureTime = departureTime; } + public NoSuchFlightException(Long id) { + super("No flight with id [" + id + "]"); + } + public String getFlightNumber() { return flightNumber; } diff --git a/samples/airline/src/main/java/org/springframework/ws/samples/airline/service/impl/AirlineServiceImpl.java b/samples/airline/src/main/java/org/springframework/ws/samples/airline/service/impl/AirlineServiceImpl.java index bdbc8f03..d9710f42 100644 --- a/samples/airline/src/main/java/org/springframework/ws/samples/airline/service/impl/AirlineServiceImpl.java +++ b/samples/airline/src/main/java/org/springframework/ws/samples/airline/service/impl/AirlineServiceImpl.java @@ -15,14 +15,14 @@ */ package org.springframework.ws.samples.airline.service.impl; -import java.util.Iterator; 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.joda.time.YearMonthDay; +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; @@ -52,24 +52,21 @@ public class AirlineServiceImpl implements AirlineService { private FrequentFlyerSecurityService frequentFlyerSecurityService = new StubFrequentFlyerSecurityService(); - public void setFlightDao(FlightDao flightDao) { + public AirlineServiceImpl(FlightDao flightDao, TicketDao ticketDao) { this.flightDao = flightDao; + this.ticketDao = ticketDao; } public void setFrequentFlyerSecurityService(FrequentFlyerSecurityService frequentFlyerSecurityService) { this.frequentFlyerSecurityService = frequentFlyerSecurityService; } - public void setTicketDao(TicketDao ticketDao) { - this.ticketDao = ticketDao; - } - - public Ticket bookFlight(String flightNumber, DateTime departureTime, List passengers) + @Transactional(rollbackFor = {NoSuchFlightException.class, NoSeatAvailableException.class}) + public Ticket bookFlight(String flightNumber, DateTime departureTime, List passengers) throws NoSuchFlightException, NoSeatAvailableException { Assert.notEmpty(passengers, "No passengers given"); if (logger.isDebugEnabled()) { - logger.debug("Booking flight '" + flightNumber + "' on '" + departureTime + "' for " + passengers.size() + - " passengers"); + logger.debug("Booking flight '" + flightNumber + "' on '" + departureTime + "' for " + passengers); } Flight flight = flightDao.getFlight(flightNumber, departureTime); if (flight == null) { @@ -79,10 +76,9 @@ public class AirlineServiceImpl implements AirlineService { throw new NoSeatAvailableException(flight); } Ticket ticket = new Ticket(); - ticket.setIssueDate(new YearMonthDay()); + ticket.setIssueDate(new LocalDate()); ticket.setFlight(flight); - for (Iterator iterator = passengers.iterator(); iterator.hasNext();) { - Passenger passenger = (Passenger) iterator.next(); + for (Passenger passenger : passengers) { // frequent flyer service is not required if (passenger instanceof FrequentFlyer && frequentFlyerSecurityService != null) { String username = ((FrequentFlyer) passenger).getUsername(); @@ -97,19 +93,25 @@ public class AirlineServiceImpl implements AirlineService { } flight.substractSeats(passengers.size()); flightDao.update(flight); - ticketDao.save(ticket); - return ticket; + return ticketDao.save(ticket); } - public int getFrequentFlyerMileage() { - FrequentFlyer frequentFlyer = frequentFlyerSecurityService.getCurrentlyAuthenticatedFrequentFlyer(); - return frequentFlyer.getMiles(); + @Transactional(readOnly = true) + public Flight getFlight(Long id) throws NoSuchFlightException { + Flight flight = flightDao.getFlight(id); + if (flight != null) { + return flight; + } + else { + throw new NoSuchFlightException(id); + } } - public List getFlights(String fromAirportCode, - String toAirportCode, - LocalDate departureDate, - ServiceClass serviceClass) { + @Transactional(readOnly = true) + public List getFlights(String fromAirportCode, + String toAirportCode, + LocalDate departureDate, + ServiceClass serviceClass) { if (serviceClass == null) { serviceClass = ServiceClass.ECONOMY; } @@ -117,6 +119,18 @@ public class AirlineServiceImpl implements AirlineService { logger.debug( "Getting flights from '" + fromAirportCode + "' to '" + toAirportCode + "' on " + departureDate); } - return flightDao.findFlights(fromAirportCode, toAirportCode, departureDate.toInterval(), serviceClass); + List flights = + flightDao.findFlights(fromAirportCode, toAirportCode, departureDate.toInterval(), serviceClass); + if (logger.isDebugEnabled()) { + logger.debug("Returning " + flights.size() + " flights"); + } + return flights; + } + + @Transactional(readOnly = true) + @Secured({"ROLE_FREQUENT_FLYER"}) + public int getFrequentFlyerMileage() { + FrequentFlyer frequentFlyer = frequentFlyerSecurityService.getCurrentlyAuthenticatedFrequentFlyer(); + return frequentFlyer != null ? frequentFlyer.getMiles() : 0; } } diff --git a/samples/airline/src/main/java/org/springframework/ws/samples/airline/web/FlightsController.java b/samples/airline/src/main/java/org/springframework/ws/samples/airline/web/FlightsController.java new file mode 100644 index 00000000..c76e5146 --- /dev/null +++ b/samples/airline/src/main/java/org/springframework/ws/samples/airline/web/FlightsController.java @@ -0,0 +1,72 @@ +/* + * 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.web; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.joda.time.LocalDate; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.ServletRequestUtils; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.multiaction.MultiActionController; +import org.springframework.ws.samples.airline.domain.Flight; +import org.springframework.ws.samples.airline.domain.ServiceClass; +import org.springframework.ws.samples.airline.service.AirlineService; + +/** @author Arjen Poutsma */ +public class FlightsController extends MultiActionController { + + private AirlineService airlineService; + + public FlightsController(AirlineService airlineService) { + Assert.notNull(airlineService, "'airlineService' must not be null"); + this.airlineService = airlineService; + } + + public ModelAndView flightList(HttpServletRequest request, HttpServletResponse response) throws Exception { + String fromAirportCode = ServletRequestUtils.getStringParameter(request, "from"); + String toAirportCode = ServletRequestUtils.getStringParameter(request, "to"); + String departureDateString = + ServletRequestUtils.getStringParameter(request, "departureDate", new LocalDate().toString()); + String serviceClassString = ServletRequestUtils.getStringParameter(request, "serviceClass", "ECONOMY"); + + ServiceClass serviceClass = ServiceClass.valueOf(serviceClassString); + LocalDate departureDate = new LocalDate(departureDateString); + + ModelAndView mav = new ModelAndView("flights"); + if (StringUtils.hasLength(fromAirportCode) && StringUtils.hasLength(toAirportCode)) { + mav.addObject("from", fromAirportCode); + mav.addObject("to", toAirportCode); + mav.addObject("departureDate", departureDateString); + mav.addObject("serviceClass", serviceClassString); + mav.addObject("flights", + airlineService.getFlights(fromAirportCode, toAirportCode, departureDate, serviceClass)); + } + return mav; + } + + public ModelAndView singleFlight(HttpServletRequest request, HttpServletResponse response) throws Exception { + String uri = request.getRequestURI(); + int pos = uri.lastIndexOf('/') + 1; + long id = Long.parseLong(uri.substring(pos)); + Flight flight = airlineService.getFlight(id); + return new ModelAndView("flight", "flight", flight); + } + +} diff --git a/samples/airline/src/main/java/org/springframework/ws/samples/airline/ws/AirlineWebServiceConstants.java b/samples/airline/src/main/java/org/springframework/ws/samples/airline/ws/AirlineWebServiceConstants.java new file mode 100644 index 00000000..fe77510f --- /dev/null +++ b/samples/airline/src/main/java/org/springframework/ws/samples/airline/ws/AirlineWebServiceConstants.java @@ -0,0 +1,23 @@ +/* + * 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; + +/** @author Arjen Poutsma */ +public interface AirlineWebServiceConstants { + + String NAMESPACE = "http://www.springframework.org/spring-ws/samples/airline/schemas"; +} diff --git a/samples/airline/src/main/java/org/springframework/ws/samples/airline/ws/BookFlightEndpoint.java b/samples/airline/src/main/java/org/springframework/ws/samples/airline/ws/BookFlightEndpoint.java deleted file mode 100644 index d91a4685..00000000 --- a/samples/airline/src/main/java/org/springframework/ws/samples/airline/ws/BookFlightEndpoint.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * 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 java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -import org.jdom.Element; -import org.jdom.Namespace; -import org.jdom.xpath.XPath; -import org.joda.time.DateTime; -import org.joda.time.DateTimeZone; -import org.joda.time.YearMonthDay; -import org.joda.time.format.DateTimeFormatter; -import org.joda.time.format.ISODateTimeFormat; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.ws.samples.airline.domain.Airport; -import org.springframework.ws.samples.airline.domain.Flight; -import org.springframework.ws.samples.airline.domain.FrequentFlyer; -import org.springframework.ws.samples.airline.domain.Passenger; -import org.springframework.ws.samples.airline.domain.ServiceClass; -import org.springframework.ws.samples.airline.domain.Ticket; -import org.springframework.ws.samples.airline.service.AirlineService; -import org.springframework.ws.server.endpoint.AbstractJDomPayloadEndpoint; - -public class BookFlightEndpoint extends AbstractJDomPayloadEndpoint implements InitializingBean { - - private AirlineService airlineService; - - private XPath flightNumberXPath; - - private XPath departureTimeXPath; - - private Namespace namespace; - - private DateTimeFormatter dateFormatter; - - private DateTimeFormatter dateTimeFormatter; - - private DateTimeFormatter parser; - - private XPath passengersXPath; - - public void setAirlineService(AirlineService airlineService) { - this.airlineService = airlineService; - } - - protected Element invokeInternal(Element requestElement) throws Exception { - String flightNumber = flightNumberXPath.valueOf(requestElement); - String departureTimeString = departureTimeXPath.valueOf(requestElement); - DateTime departureTime = parser.parseDateTime(departureTimeString); - if (logger.isDebugEnabled()) { - logger.debug("BookFlight request for flight number [" + flightNumber + "] at [" + departureTime + "]"); - } - List passengerElements = passengersXPath.selectNodes(requestElement); - List passengers = new ArrayList(); - for (Iterator iterator = passengerElements.iterator(); iterator.hasNext();) { - Element passengerElement = (Element) iterator.next(); - if ("passenger".equals(passengerElement.getName()) && namespace.equals(passengerElement.getNamespace())) { - Passenger passenger = new Passenger(passengerElement.getChildTextNormalize("first", namespace), - passengerElement.getChildTextNormalize("last", namespace)); - passengers.add(passenger); - } - else - if ("username".equals(passengerElement.getName()) && namespace.equals(passengerElement.getNamespace())) { - FrequentFlyer frequentFlyer = new FrequentFlyer(passengerElement.getTextNormalize()); - passengers.add(frequentFlyer); - } - } - Ticket ticket = airlineService.bookFlight(flightNumber, departureTime, passengers); - return createResponse(ticket); - } - - private Element createResponse(Ticket ticket) { - Element responseElement = new Element("BookFlightResponse", namespace); - responseElement.addContent(new Element("id", namespace).setText(ticket.getId().toString())); - responseElement.addContent(createIssueDateElement(ticket.getIssueDate())); - responseElement.addContent(createPassengersElement(ticket.getPassengers())); - responseElement.addContent(createFlightElement(ticket.getFlight())); - return responseElement; - } - - protected Element createIssueDateElement(YearMonthDay issueDate) { - Element issueDateElement = new Element("issueDate", namespace); - issueDateElement.setText(dateFormatter.print(issueDate)); - return issueDateElement; - } - - protected Element createPassengersElement(Set passengers) { - Element passengersElement = new Element("passengers", namespace); - for (Iterator iterator = passengers.iterator(); iterator.hasNext();) { - Passenger passenger = (Passenger) iterator.next(); - Element passengerElement = new Element("passenger", namespace); - passengersElement.addContent(passengerElement); - passengerElement.addContent(new Element("first", namespace).setText(passenger.getFirstName())); - passengerElement.addContent(new Element("last", namespace).setText(passenger.getLastName())); - } - return passengersElement; - } - - protected Element createFlightElement(Flight flight) { - Element flightElement = new Element("flight", namespace); - flightElement.addContent(new Element("number", namespace).setText(flight.getNumber())); - flightElement.addContent( - new Element("departureTime", namespace).setText(dateTimeFormatter.print(flight.getDepartureTime()))); - flightElement.addContent(createAirportElement("from", flight.getFrom())); - flightElement - .addContent(new Element("arrivalTime", namespace).setText( - dateTimeFormatter.print(flight.getArrivalTime()))); - flightElement.addContent(createAirportElement("to", flight.getTo())); - flightElement.addContent(createServiceClassElement(flight.getServiceClass())); - return flightElement; - } - - protected Element createAirportElement(String localName, Airport airport) { - Element airportElement = new Element(localName, namespace); - airportElement.addContent(new Element("code", namespace).setText(airport.getCode())); - airportElement.addContent(new Element("name", namespace).setText(airport.getName())); - airportElement.addContent(new Element("city", namespace).setText(airport.getCity())); - return airportElement; - } - - protected Element createServiceClassElement(ServiceClass serviceClass) { - Element serviceClassElement = new Element("serviceClass", namespace); - if (ServiceClass.BUSINESS.equals(serviceClass)) { - serviceClassElement.setText("business"); - } - else if (ServiceClass.ECONOMY.equals(serviceClass)) { - serviceClassElement.setText("economy"); - } - else if (ServiceClass.FIRST.equals(serviceClass)) { - serviceClassElement.setText("first"); - } - return serviceClassElement; - } - - public void afterPropertiesSet() throws Exception { - namespace = Namespace.getNamespace("tns", "http://www.springframework.org/spring-ws/samples/airline/schemas"); - flightNumberXPath = XPath.newInstance("/tns:BookFlightRequest/tns:flightNumber/text()"); - flightNumberXPath.addNamespace(namespace); - departureTimeXPath = XPath.newInstance("/tns:BookFlightRequest/tns:departureTime/text()"); - departureTimeXPath.addNamespace(namespace); - passengersXPath = XPath.newInstance("/tns:BookFlightRequest/tns:passengers/*"); - passengersXPath.addNamespace(namespace); - parser = ISODateTimeFormat.dateTimeParser().withZone(DateTimeZone.UTC); - dateTimeFormatter = ISODateTimeFormat.dateTimeNoMillis(); - dateFormatter = ISODateTimeFormat.date(); - } - - -} diff --git a/samples/airline/src/main/java/org/springframework/ws/samples/airline/ws/GetFlightsEndpoint.java b/samples/airline/src/main/java/org/springframework/ws/samples/airline/ws/GetFlightsEndpoint.java deleted file mode 100644 index 0f657c66..00000000 --- a/samples/airline/src/main/java/org/springframework/ws/samples/airline/ws/GetFlightsEndpoint.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * 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 java.util.Iterator; -import java.util.List; - -import org.joda.time.Chronology; -import org.joda.time.DateTimeZone; -import org.joda.time.LocalDate; -import org.joda.time.chrono.ISOChronology; -import org.springframework.ws.samples.airline.schema.Airport; -import org.springframework.ws.samples.airline.schema.Flight; -import org.springframework.ws.samples.airline.schema.GetFlightsRequest; -import org.springframework.ws.samples.airline.schema.GetFlightsResponse; -import org.springframework.ws.samples.airline.schema.ServiceClass; -import org.springframework.ws.samples.airline.schema.impl.AirportImpl; -import org.springframework.ws.samples.airline.schema.impl.FlightImpl; -import org.springframework.ws.samples.airline.schema.impl.GetFlightsResponseImpl; -import org.springframework.ws.samples.airline.service.AirlineService; -import org.springframework.ws.server.endpoint.AbstractMarshallingPayloadEndpoint; - -/** - * Endpoint that returns a list of flights with a given number, and that lie between a given start and end date. It uses - * JAXB-based marshalling for both request and response objects. Because we use separate POJOs for our schema and our - * domain objects, we need to convert the response domain objects to schema-based objects. - * - * @author Arjen Poutsma - */ -public class GetFlightsEndpoint extends AbstractMarshallingPayloadEndpoint { - - private AirlineService airlineService; - - public void setAirlineService(AirlineService airlineService) { - this.airlineService = airlineService; - } - - protected Object invokeInternal(Object requestObject) throws Exception { - GetFlightsRequest request = (GetFlightsRequest) requestObject; - - DateTimeZone dateTimeZone = DateTimeZone.forTimeZone(request.getDepartureDate().getTimeZone()); - Chronology chronology = ISOChronology.getInstance(dateTimeZone); - LocalDate departureDate = new LocalDate(request.getDepartureDate(), chronology); - if (logger.isDebugEnabled()) { - logger.debug("Request for flights from '" + request.getFrom() + "' to '" + request.getTo() + "' on " + - departureDate); - } - List flights = airlineService.getFlights(request.getFrom(), request.getTo(), departureDate, - convertToDomainType(request.getServiceClass())); - if (logger.isDebugEnabled()) { - logger.debug("Marshalling " + flights.size() + " flight results"); - } - GetFlightsResponse response = new GetFlightsResponseImpl(); - for (Iterator iter = flights.iterator(); iter.hasNext();) { - org.springframework.ws.samples.airline.domain.Flight domainFlight = - (org.springframework.ws.samples.airline.domain.Flight) iter.next(); - Flight schemaFlight = convertToSchemaType(domainFlight); - response.getFlight().add(schemaFlight); - } - return response; - } - - private Flight convertToSchemaType(org.springframework.ws.samples.airline.domain.Flight domainFlight) { - Flight schemaFlight = new FlightImpl(); - schemaFlight.setNumber(domainFlight.getNumber()); - schemaFlight.setDepartureTime(domainFlight.getDepartureTime().toGregorianCalendar()); - schemaFlight.setFrom(convertToSchemaType(domainFlight.getFrom())); - schemaFlight.setArrivalTime(domainFlight.getArrivalTime().toGregorianCalendar()); - schemaFlight.setTo(convertToSchemaType(domainFlight.getTo())); - schemaFlight.setServiceClass(convertToSchemaType(domainFlight.getServiceClass())); - return schemaFlight; - } - - private Airport convertToSchemaType(org.springframework.ws.samples.airline.domain.Airport domainAirport) { - if (domainAirport == null) { - return null; - } - Airport schemaAirport = new AirportImpl(); - schemaAirport.setCode(domainAirport.getCode()); - schemaAirport.setName(domainAirport.getName()); - schemaAirport.setCity(domainAirport.getCity()); - return schemaAirport; - } - - private ServiceClass convertToSchemaType(org.springframework.ws.samples.airline.domain.ServiceClass domainServiceClass) { - if (domainServiceClass == null) { - return null; - } - else if (domainServiceClass.equals(org.springframework.ws.samples.airline.domain.ServiceClass.BUSINESS)) { - return ServiceClass.BUSINESS; - } - else if (domainServiceClass.equals(org.springframework.ws.samples.airline.domain.ServiceClass.ECONOMY)) { - return ServiceClass.ECONOMY; - } - else if (domainServiceClass.equals(org.springframework.ws.samples.airline.domain.ServiceClass.FIRST)) { - return ServiceClass.FIRST; - } - else { - throw new IllegalArgumentException("Invalid domain service class: [" + domainServiceClass + "]"); - } - } - - private org.springframework.ws.samples.airline.domain.ServiceClass convertToDomainType(ServiceClass schemaServiceClass) { - if (schemaServiceClass == null) { - return null; - } - else if (schemaServiceClass.equals(ServiceClass.BUSINESS)) { - return org.springframework.ws.samples.airline.domain.ServiceClass.BUSINESS; - } - else if (schemaServiceClass.equals(ServiceClass.ECONOMY)) { - return org.springframework.ws.samples.airline.domain.ServiceClass.ECONOMY; - } - else if (schemaServiceClass.equals(ServiceClass.FIRST)) { - return org.springframework.ws.samples.airline.domain.ServiceClass.FIRST; - } - else { - throw new IllegalArgumentException("Invalid schema service class: [" + schemaServiceClass + "]"); - } - - } - -} diff --git a/samples/airline/src/main/java/org/springframework/ws/samples/airline/ws/MarshallingAirlineEndpoint.java b/samples/airline/src/main/java/org/springframework/ws/samples/airline/ws/MarshallingAirlineEndpoint.java new file mode 100644 index 00000000..0a88f70b --- /dev/null +++ b/samples/airline/src/main/java/org/springframework/ws/samples/airline/ws/MarshallingAirlineEndpoint.java @@ -0,0 +1,160 @@ +/* + * 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 java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import javax.xml.bind.JAXBElement; +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.XMLGregorianCalendar; + +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.util.Assert; +import org.springframework.ws.samples.airline.domain.FrequentFlyer; +import org.springframework.ws.samples.airline.domain.Passenger; +import org.springframework.ws.samples.airline.schema.BookFlightRequest; +import org.springframework.ws.samples.airline.schema.Flight; +import org.springframework.ws.samples.airline.schema.GetFlightsRequest; +import org.springframework.ws.samples.airline.schema.GetFlightsResponse; +import org.springframework.ws.samples.airline.schema.Name; +import org.springframework.ws.samples.airline.schema.ObjectFactory; +import org.springframework.ws.samples.airline.schema.ServiceClass; +import org.springframework.ws.samples.airline.schema.Ticket; +import org.springframework.ws.samples.airline.schema.support.SchemaConversionUtils; +import org.springframework.ws.samples.airline.service.AirlineService; +import org.springframework.ws.samples.airline.service.NoSeatAvailableException; +import org.springframework.ws.samples.airline.service.NoSuchFlightException; +import org.springframework.ws.server.endpoint.annotation.Endpoint; +import org.springframework.ws.server.endpoint.annotation.PayloadRoot; + +/** + * Endpoint that handles the Airline Web Service messages using JAXB2 marshalling. + *

+ * This endpoint contains exactly the same logic as the {@link XPathAirlineEndpoint}, and is only provided as an + * example. Typically, you will not have two endpoints with the same logic. + * + * @author Arjen Poutsma + */ +@Endpoint +public class MarshallingAirlineEndpoint implements AirlineWebServiceConstants { + + private static final Log logger = LogFactory.getLog(MarshallingAirlineEndpoint.class); + + private AirlineService airlineService; + + private ObjectFactory objectFactory = new ObjectFactory(); + + public MarshallingAirlineEndpoint(AirlineService airlineService) { + Assert.notNull(airlineService, "airlineService must not be null"); + this.airlineService = airlineService; + } + + /** + * This endpoint method uses marshalling to handle message with a <GetFlightsRequest> payload. + * + * @param request the JAXB2 representation of a <GetFlightsRequest> + */ + @PayloadRoot(localPart = "GetFlightsRequest", namespace = NAMESPACE) + public GetFlightsResponse getFlights(GetFlightsRequest request) throws DatatypeConfigurationException { + if (logger.isDebugEnabled()) { + logger.debug("Received GetFlightsRequest '" + request.getFrom() + "' to '" + request.getTo() + "' on " + + request.getDepartureDate()); + } + List flights = getSchemaFlights(request.getFrom(), request.getTo(), request.getDepartureDate(), + request.getServiceClass()); + GetFlightsResponse response = new GetFlightsResponse(); + for (Flight flight : flights) { + response.getFlight().add(flight); + } + return response; + } + + /** Converts between the domain and schema types. */ + private List getSchemaFlights(String from, + String to, + XMLGregorianCalendar xmlDepartureDate, + ServiceClass xmlServiceClass) throws DatatypeConfigurationException { + LocalDate domainDepartureDate = SchemaConversionUtils.toLocalDate(xmlDepartureDate); + org.springframework.ws.samples.airline.domain.ServiceClass domainServiceClass = + SchemaConversionUtils.toDomainType(xmlServiceClass); + List domainFlights = + airlineService.getFlights(from, to, domainDepartureDate, domainServiceClass); + return SchemaConversionUtils.toSchemaType(domainFlights); + } + + /** + * This endpoint method uses marshalling to handle message with a <BookFlightRequest> payload. + * + * @param request the JAXB2 representation of a <BookFlightRequest> + * @return the JAXB2 representation of a <BookFlightResponse> + */ + @PayloadRoot(localPart = "BookFlightRequest", namespace = NAMESPACE) + public JAXBElement bookFlight(BookFlightRequest request) + throws NoSeatAvailableException, DatatypeConfigurationException, NoSuchFlightException { + if (logger.isDebugEnabled()) { + logger.debug("Received BookingFlightRequest '" + request.getFlightNumber() + "' on '" + + request.getDepartureTime() + "' for " + request.getPassengers().getPassengerOrUsername()); + } + Ticket ticket = bookSchemaFlight(request.getFlightNumber(), request.getDepartureTime(), + request.getPassengers().getPassengerOrUsername()); + return objectFactory.createBookFlightResponse(ticket); + } + + /** Converts between the domain and schema types. */ + private Ticket bookSchemaFlight(String flightNumber, + XMLGregorianCalendar xmlDepartureTime, + List passengerOrUsernameList) + throws NoSeatAvailableException, NoSuchFlightException, DatatypeConfigurationException { + DateTime departureTime = SchemaConversionUtils.toDateTime(xmlDepartureTime); + List passengers = new ArrayList(passengerOrUsernameList.size()); + for (Iterator iterator = passengerOrUsernameList.iterator(); iterator.hasNext();) { + Object passengerOrUsername = iterator.next(); + if (passengerOrUsername instanceof Name) { + Name passengerName = (Name) passengerOrUsername; + Passenger passenger = new Passenger(passengerName.getFirst(), passengerName.getLast()); + passengers.add(passenger); + } + else if (passengerOrUsername instanceof String) { + String frequentFlyerUsername = (String) passengerOrUsername; + FrequentFlyer frequentFlyer = new FrequentFlyer(frequentFlyerUsername); + passengers.add(frequentFlyer); + } + } + org.springframework.ws.samples.airline.domain.Ticket domainTicket = + airlineService.bookFlight(flightNumber, departureTime, passengers); + return SchemaConversionUtils.toSchemaType(domainTicket); + } + + /** + * This endpoint method uses marshalling to handle message with a <GetFrequentFlyerMileageRequest> + * payload. + * + * @param ignored is ignored + * @return the JAXB2 representation of a <GetFrequentFlyerMileageResponse> + */ + @PayloadRoot(localPart = "GetFrequentFlyerMileageRequest", namespace = NAMESPACE) + public JAXBElement getFrequentFlyerMileage(JAXBElement ignored) { + logger.debug("Received GetFrequentFlyerMileageRequest request"); + int result = airlineService.getFrequentFlyerMileage(); + return objectFactory.createGetFrequentFlyerMileageResponse(result); + } + +} \ No newline at end of file diff --git a/samples/airline/src/main/java/org/springframework/ws/samples/airline/ws/XPathAirlineEndpoint.java b/samples/airline/src/main/java/org/springframework/ws/samples/airline/ws/XPathAirlineEndpoint.java new file mode 100644 index 00000000..85c70c9e --- /dev/null +++ b/samples/airline/src/main/java/org/springframework/ws/samples/airline/ws/XPathAirlineEndpoint.java @@ -0,0 +1,177 @@ +/* + * 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 java.util.ArrayList; +import java.util.List; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.transform.Source; + +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.oxm.Marshaller; +import org.springframework.oxm.support.MarshallingSource; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; +import org.springframework.ws.samples.airline.domain.Flight; +import org.springframework.ws.samples.airline.domain.FrequentFlyer; +import org.springframework.ws.samples.airline.domain.Passenger; +import org.springframework.ws.samples.airline.domain.ServiceClass; +import org.springframework.ws.samples.airline.domain.Ticket; +import org.springframework.ws.samples.airline.schema.GetFlightsResponse; +import org.springframework.ws.samples.airline.schema.ObjectFactory; +import org.springframework.ws.samples.airline.schema.support.SchemaConversionUtils; +import org.springframework.ws.samples.airline.service.AirlineService; +import org.springframework.ws.samples.airline.service.NoSeatAvailableException; +import org.springframework.ws.samples.airline.service.NoSuchFlightException; +import org.springframework.ws.server.endpoint.annotation.Endpoint; +import org.springframework.ws.server.endpoint.annotation.PayloadRoot; +import org.springframework.ws.server.endpoint.annotation.XPathParam; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * Endpoint that handles the Airline Web Service request messages using XPath expressions, and creates response messages + * using JAXB2. + *

+ * This endpoint contains exactly the same logic as the {@link MarshallingAirlineEndpoint}, and is only provided as an + * example. Typically, you will not have two endpoints with the same logic. + * + * @author Arjen Poutsma + */ +@Endpoint +public class XPathAirlineEndpoint implements AirlineWebServiceConstants { + + private static final Log logger = LogFactory.getLog(XPathAirlineEndpoint.class); + + private AirlineService airlineService; + + private ObjectFactory objectFactory = new ObjectFactory(); + + private Marshaller marshaller; + + public XPathAirlineEndpoint(AirlineService airlineService, Marshaller marshaller) { + Assert.notNull(airlineService, "airlineService must not be null"); + Assert.notNull(marshaller, "'marshaller' must not be null"); + this.airlineService = airlineService; + this.marshaller = marshaller; + } + + /** + * This endpoint method uses XPath to handle message with a <GetFlightsRequest> payload. + * + * @param from the from airport + * @param to the to airport + * @param departureDateString the string representation of the departure date + * @param serviceClassString the string representation of the service class + */ + @PayloadRoot(localPart = "GetFlightsRequest", namespace = NAMESPACE) + public Source getFlights(@XPathParam("//tns:from")String from, + @XPathParam("//tns:to")String to, + @XPathParam("//tns:departureDate")String departureDateString, + @XPathParam("//tns:serviceClass")String serviceClassString) + throws DatatypeConfigurationException { + if (logger.isDebugEnabled()) { + logger.debug("Received GetFlightsRequest '" + from + "' to '" + to + "' on " + departureDateString); + } + LocalDate departureDate = new LocalDate(departureDateString); + ServiceClass serviceClass = null; + if (StringUtils.hasLength(serviceClassString)) { + serviceClass = ServiceClass.valueOf(serviceClassString); + } + List flights = airlineService.getFlights(from, to, departureDate, serviceClass); + + GetFlightsResponse response = objectFactory.createGetFlightsResponse(); + for (Flight domainFlight : flights) { + response.getFlight().add(SchemaConversionUtils.toSchemaType(domainFlight)); + } + return new MarshallingSource(marshaller, response); + } + + /** + * This endpoint method uses XPath to handle message with a <BookFlightRequest> payload. + * + * @param flightNumber the flight number + * @param departureTimeString the string representation of the departure time + * @param passengerNodes the passenger nodes + * @param frequentFlyerNodes the frequent flyer nodes + */ + @PayloadRoot(localPart = "BookFlightRequest", namespace = NAMESPACE) + public Source bookFlight(@XPathParam("//tns:flightNumber")String flightNumber, + @XPathParam("//tns:departureTime")String departureTimeString, + @XPathParam("//tns:passengers/tns:passenger")NodeList passengerNodes, + @XPathParam("//tns:passengers/tns:username")NodeList frequentFlyerNodes) + throws NoSeatAvailableException, NoSuchFlightException, DatatypeConfigurationException, JAXBException { + if (logger.isDebugEnabled()) { + logger.debug("Received BookingFlightRequest '" + flightNumber + "' on '" + departureTimeString + "' for " + + passengerNodes.getLength() + " passengers and " + frequentFlyerNodes.getLength() + + " frequent flyers"); + } + DateTime departureTime = new DateTime(departureTimeString); + List passengers = new ArrayList(); + parsePassengers(passengerNodes, passengers); + parseFrequentFlyers(frequentFlyerNodes, passengers); + Ticket domainTicket = airlineService.bookFlight(flightNumber, departureTime, passengers); + + JAXBElement response = + objectFactory.createBookFlightResponse(SchemaConversionUtils.toSchemaType(domainTicket)); + return new MarshallingSource(marshaller, response); + } + + private void parsePassengers(NodeList passengerNodes, List passengers) { + for (int i = 0; i < passengerNodes.getLength(); i++) { + if (passengerNodes.item(i).getNodeType() != Node.ELEMENT_NODE) { + continue; + } + Element passengerElement = (Element) passengerNodes.item(i); + Element firstNameElement = (Element) passengerElement.getElementsByTagNameNS(NAMESPACE, "first").item(0); + Element lastNameElement = (Element) passengerElement.getElementsByTagNameNS(NAMESPACE, "last").item(0); + Passenger passenger = new Passenger(firstNameElement.getTextContent(), lastNameElement.getTextContent()); + passengers.add(passenger); + } + } + + private void parseFrequentFlyers(NodeList frequentFlyerNodes, List passengers) { + for (int i = 0; i < frequentFlyerNodes.getLength(); i++) { + if (frequentFlyerNodes.item(i).getNodeType() != Node.ELEMENT_NODE) { + continue; + } + Element frequentFlyerElement = (Element) frequentFlyerNodes.item(i); + FrequentFlyer frequentFlyer = new FrequentFlyer(frequentFlyerElement.getTextContent()); + passengers.add(frequentFlyer); + } + } + + /** + * This endpoint method uses XPath to handle message with a <GetFrequentFlyerMileageRequest> + * payload. + */ + @PayloadRoot(localPart = "GetFrequentFlyerMileageRequest", namespace = NAMESPACE) + public Source getFrequentFlyerMileage() { + logger.debug("Received GetFrequentFlyerMileageRequest request"); + int result = airlineService.getFrequentFlyerMileage(); + JAXBElement response = objectFactory.createGetFrequentFlyerMileageResponse(result); + return new MarshallingSource(marshaller, response); + } + + +} diff --git a/samples/airline/src/main/resources/META-INF/persistence.xml b/samples/airline/src/main/resources/META-INF/persistence.xml new file mode 100644 index 00000000..6ad8d053 --- /dev/null +++ b/samples/airline/src/main/resources/META-INF/persistence.xml @@ -0,0 +1,14 @@ + + + + org.springframework.ws.samples.airline.domain.Airport + org.springframework.ws.samples.airline.domain.Flight + org.springframework.ws.samples.airline.domain.FrequentFlyer + org.springframework.ws.samples.airline.domain.Passenger + org.springframework.ws.samples.airline.domain.Ticket + + + diff --git a/samples/airline/src/main/resources/org/springframework/ws/samples/airline/dao/jpa/applicationContext-jpa.xml b/samples/airline/src/main/resources/org/springframework/ws/samples/airline/dao/jpa/applicationContext-jpa.xml new file mode 100644 index 00000000..f61f2f49 --- /dev/null +++ b/samples/airline/src/main/resources/org/springframework/ws/samples/airline/dao/jpa/applicationContext-jpa.xml @@ -0,0 +1,68 @@ + + + + + + + A DAO for Flights. + + + + + + A DAO for Tickets. + + + + + + + A DAO for FrequentFlyers. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Handles the @Repository annotation used on the JPA Dao's, and translates from the JPA + exceptions to Spring's richer DataAccessException hierarchy. + + + + + + Injects the JPA PersistenceContext into the JPA Dao's. + + + + + diff --git a/samples/airline/src/main/resources/org/springframework/ws/samples/airline/dao/jpa/hibernate.properties b/samples/airline/src/main/resources/org/springframework/ws/samples/airline/dao/jpa/hibernate.properties new file mode 100644 index 00000000..4e8d346e --- /dev/null +++ b/samples/airline/src/main/resources/org/springframework/ws/samples/airline/dao/jpa/hibernate.properties @@ -0,0 +1,21 @@ +# +# 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. +# + +# Properties file with hibernate-related settings. + +hibernate.dialect=${hibernate.dialect} +hibernate.hbm2ddl.auto=${hibernate.hbm2ddl.auto} +hibernate.cache.provider_class=org.hibernate.cache.NoCacheProvider \ No newline at end of file diff --git a/samples/airline/src/main/resources/org/springframework/ws/samples/airline/security/applicationContext-security.xml b/samples/airline/src/main/resources/org/springframework/ws/samples/airline/security/applicationContext-security.xml index b84c26c2..fa31b9a3 100644 --- a/samples/airline/src/main/resources/org/springframework/ws/samples/airline/security/applicationContext-security.xml +++ b/samples/airline/src/main/resources/org/springframework/ws/samples/airline/security/applicationContext-security.xml @@ -1,26 +1,18 @@ - This application context contains the WS-Security and Acegi beans. - + A transactional security service used to obtain Frequent Flyer information. - - - - - - - - - PROPAGATION_REQUIRED - - + @@ -56,19 +48,11 @@ value="classpath:org/springframework/ws/samples/airline/security/securityPolicy.xml"/> - + - - - This endpoint handles get frequent flier mileage requests. - - - - @@ -77,15 +61,11 @@ - + - - - - @@ -103,9 +83,11 @@ - - org.springframework.ws.samples.airline.service.AirlineService.getFrequentFlyerMileage=ROLE_FREQUENT_FLYER - + + + + + diff --git a/samples/airline/src/main/resources/org/springframework/ws/samples/airline/service/applicationContext.xml b/samples/airline/src/main/resources/org/springframework/ws/samples/airline/service/applicationContext.xml index 4849e80d..9d4b7bb7 100644 --- a/samples/airline/src/main/resources/org/springframework/ws/samples/airline/service/applicationContext.xml +++ b/samples/airline/src/main/resources/org/springframework/ws/samples/airline/service/applicationContext.xml @@ -1,25 +1,53 @@ - + + + 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"> - - - - - + + + + + - - - - - - PROPAGATION_REQUIRED,readOnly - PROPAGATION_REQUIRED - - - - + + + The MessageFactory is used to create new SOAP messages from incoming requests. It is referenced to in + airline-servlet.xml. + + + + + \ No newline at end of file diff --git a/samples/airline/src/main/resources/org/springframework/ws/samples/airline/ws/applicationContext-ws.xml b/samples/airline/src/main/resources/org/springframework/ws/samples/airline/ws/applicationContext-ws.xml deleted file mode 100644 index eb750f40..00000000 --- a/samples/airline/src/main/resources/org/springframework/ws/samples/airline/ws/applicationContext-ws.xml +++ /dev/null @@ -1,153 +0,0 @@ - - - - This application context contains the Spring-WS beans. - - - - - The MessageFactory is used to create new SOAP messages from incoming requests. It is referenced in - airline-servlet.xml and applicationContext-ws-jms.xml. - - - - - - The MessageDispatcher is responsible for routing messages to endpoints. It uses three endpoint mappings to - determine the endpoint suitable for handling a particular incoming request. Having three mappings is not a - recommended approach, it's done here only for illustration purposes. - - - - - - - - - - - - - - - - - - - This bean definition represents the airline.wsdl file found in the root of the web application. It is used - by the WsdlDefinitionHandlerAdapter in airline-servlet.xml. - - - - - - - This endpoint mapping uses the qualified name of the payload (body contents) to determine the endpoint for - an incoming message. The name GetFlightsRequest with namespace - http://www.springframework.org/spring-ws/samples/airline/schemas is mapped to the getFlightsEndpoint. - Additionally, messages are logged using the logging interceptor. - - - - - getFlightsEndpoint - - - - - - - - - - - This endpoint mapping uses SOAP Actions to determine the endpoint for an incoming message. The key - http://www.springframework.org/spring-ws/samples/airline/BookFlight is mapped to the bookFlightEndpoint. - Additionally, message are logged and validated. - - - - - bookFlightEndpoint - - - - - - - - - - - - - - This interceptor validates both incoming and outgoing message contents according to the 'airline.xsd' XML - Schema file. - - - - - - - - - This interceptor logs the message payload. - - - - - - This endpoint handles book flight request. - - - - - - - This endpoint handles get flights request. - - - - - - - - - The validating JAXB Marshaller is used by the getFlightsEndpoint to unmarshal XML to objects and - vice-versa. - - - - - - - - This exception resolver maps exceptions to SOAP Faults. The business logic exceptions - NoSeatAvailableException and NoSuchFlightException are mapped to custom SOAP Fault. Both - UnmarshallingException andValidationFailureException are mapped to a SOAP Fault with a "Sender" fault code. - All other exceptions are mapped to a "Receiver" error code, the default. - - - RECEIVER,Server error - - - - - {http://www.springframework.org/spring-ws/samples/airline}airline:NoMoreSeats, No more seats - available - - - {http://www.springframework.org/spring-ws/samples/airline}airline:NoSuchFlight, No such flight - exists - - SENDER,Invalid request - SENDER,Invalid request - - - - - \ No newline at end of file diff --git a/samples/airline/src/main/sql/airline-dataload.sql b/samples/airline/src/main/sql/airline-dataload.sql index 22778cae..d898b23c 100644 --- a/samples/airline/src/main/sql/airline-dataload.sql +++ b/samples/airline/src/main/sql/airline-dataload.sql @@ -1,8 +1,9 @@ INSERT INTO AIRPORT(CODE, NAME, CITY) VALUES('AMS', 'Schiphol Airport', 'Amsterdam'); INSERT INTO AIRPORT(CODE, NAME, CITY) VALUES('VCE', 'Marco Polo Airport', 'Venice'); -INSERT INTO FLIGHT(ID, NUMBER, DEPARTURE_TIME, FROM_AIRPORT_CODE, ARRIVAL_TIME, TO_AIRPORT_CODE, SERVICE_CLASS, SEATS_AVAILABLE, MILES) VALUES (1,'KL1653','2006-01-31 10:05:00', 'AMS', '2006-01-31 12:25:00', 'VCE', 'economy', 5, 200); -INSERT INTO FLIGHT(ID, NUMBER, DEPARTURE_TIME, FROM_AIRPORT_CODE, ARRIVAL_TIME, TO_AIRPORT_CODE, SERVICE_CLASS, SEATS_AVAILABLE, MILES) VALUES (2,'KL1654','2006-02-05 12:40:00', 'VCE', '2006-02-05 14:15:00', 'AMS', 'economy', 5, 200); +INSERT INTO FLIGHT(ID, NUMBER, DEPARTURE_TIME, FROM_AIRPORT_CODE, ARRIVAL_TIME, TO_AIRPORT_CODE, SERVICE_CLASS, SEATS_AVAILABLE, MILES) VALUES (1,'KL1653','2006-01-31 10:05:00', 'AMS', '2006-01-31 12:25:00', 'VCE', 'ECONOMY', 5, 200); + +INSERT INTO FLIGHT(ID, NUMBER, DEPARTURE_TIME, FROM_AIRPORT_CODE, ARRIVAL_TIME, TO_AIRPORT_CODE, SERVICE_CLASS, SEATS_AVAILABLE, MILES) VALUES (2,'KL1654','2006-02-05 12:40:00', 'VCE', '2006-02-05 14:15:00', 'AMS', 'ECONOMY', 5, 200); INSERT INTO PASSENGER(ID, FIRST_NAME, LAST_NAME) VALUES (1, 'John', 'Doe'); INSERT INTO FREQUENT_FLYER(PASSENGER_ID, USERNAME, PASSWORD, MILES) VALUES (1, 'john', 'changeme', 10); \ No newline at end of file diff --git a/samples/airline/src/main/webapp/WEB-INF/jsp/error.jsp b/samples/airline/src/main/webapp/WEB-INF/jsp/error.jsp new file mode 100644 index 00000000..d7654d9a --- /dev/null +++ b/samples/airline/src/main/webapp/WEB-INF/jsp/error.jsp @@ -0,0 +1,13 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + +<% + Exception ex = (Exception) request.getAttribute("exception"); +%> +<%= ex.getMessage() %> + + +

<%= ex.getMessage() %> +

+Flights + + \ No newline at end of file diff --git a/samples/airline/src/main/webapp/WEB-INF/jsp/flight.jsp b/samples/airline/src/main/webapp/WEB-INF/jsp/flight.jsp new file mode 100644 index 00000000..a0244a0e --- /dev/null +++ b/samples/airline/src/main/webapp/WEB-INF/jsp/flight.jsp @@ -0,0 +1,47 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="joda" uri="http://www.joda.org/joda/time/tags" %> + +Flights + + + + + + + + + + + + + + + + + + + + + + +
Number: + +
From: + + ( + + ) +
Departure: + +
To: + + ( + + ) +
Departure: + +
+Flights + + \ No newline at end of file diff --git a/samples/airline/src/main/webapp/WEB-INF/jsp/flights.jsp b/samples/airline/src/main/webapp/WEB-INF/jsp/flights.jsp new file mode 100644 index 00000000..9e9f6675 --- /dev/null +++ b/samples/airline/src/main/webapp/WEB-INF/jsp/flights.jsp @@ -0,0 +1,71 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="joda" uri="http://www.joda.org/joda/time/tags" %> + +Flights + +
+ + + + + + + + + + + + + + + + + + + + +
From:
To:"/>
Departure Date:"/>
Service Class: + +
+ +
+ + + + + + + + + + + + + + +
NumberDepartsArrives
+ + + + + + ( + + ) + + + + ( + + ) + +
+
+
+ + \ No newline at end of file diff --git a/samples/airline/src/main/webapp/WEB-INF/jsp/noSuchFlight.jsp b/samples/airline/src/main/webapp/WEB-INF/jsp/noSuchFlight.jsp new file mode 100644 index 00000000..161120ff --- /dev/null +++ b/samples/airline/src/main/webapp/WEB-INF/jsp/noSuchFlight.jsp @@ -0,0 +1,13 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + +No Such Flight + +<% + Exception ex = (Exception) request.getAttribute("exception"); +%> +

No such flight: <%= ex.getMessage() %> +

+Flights + + + \ No newline at end of file diff --git a/samples/airline/src/main/webapp/WEB-INF/mvc-servlet.xml b/samples/airline/src/main/webapp/WEB-INF/mvc-servlet.xml new file mode 100644 index 00000000..5d94a74e --- /dev/null +++ b/samples/airline/src/main/webapp/WEB-INF/mvc-servlet.xml @@ -0,0 +1,54 @@ + + + + + This web application context contains a simple Spring Web MVC web application that shows flights + + + + + + + + flightController + flightController + + + + + + + + + + + + + + flightList + singleFlight + + + + + + + + + + + + + + + + + noSuchFlight + + + + + + \ No newline at end of file diff --git a/samples/airline/src/main/webapp/WEB-INF/web.xml b/samples/airline/src/main/webapp/WEB-INF/web.xml index e1cbd992..1aada590 100644 --- a/samples/airline/src/main/webapp/WEB-INF/web.xml +++ b/samples/airline/src/main/webapp/WEB-INF/web.xml @@ -1,36 +1,48 @@ - Spring-WS Airline Sample contextConfigLocation - classpath:org/springframework/ws/samples/airline/dao/hibernate/applicationContext-hibernate.xml + 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 + + org.springframework.web.context.ContextLoaderListener - airline + ws + org.springframework.ws.transport.http.MessageDispatcherServlet + + + ws + /services + + + ws + *.wsdl + + + mvc org.springframework.web.servlet.DispatcherServlet - airline - /Airline - - - airline - *.wsdl + mvc + / xsd text/xml + + index.html + \ No newline at end of file diff --git a/samples/airline/src/main/webapp/WEB-INF/ws-servlet.xml b/samples/airline/src/main/webapp/WEB-INF/ws-servlet.xml new file mode 100644 index 00000000..0e6049f1 --- /dev/null +++ b/samples/airline/src/main/webapp/WEB-INF/ws-servlet.xml @@ -0,0 +1,119 @@ + + + + + + + + + + This endpoint handles the Airline Web Service messages using XPath expressions and JAXB2 marshalling. + + + + + + + + + The JAXB 2 Marshaller is used by the endpoints. + + + + + + + + + + + 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. + + + + + + + + + + + + + + + + + + This adapter allows for methods that need and returns marshalled objects. The MarshallingEndpoint + uses JAXB2 objects. + + + + + + + This adapter allows for methods that use @XPathParam annotations. The XPathAirlineEndpoint uses JAXB2 these. + + + + http://www.springframework.org/spring-ws/samples/airline/schemas + + + + + + + + + + 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. + All other exceptions are mapped to a "Server" error code, the default. + + + + + CLIENT + SERVER + CLIENT,Invalid request + CLIENT,Invalid request + + + + + + + + + Dynamically builds a WSDL from the airline.xsd.This bean definition represents the airline.wsdl file found + in the root of the web application. It is used + by the WsdlDefinitionHandlerAdapter in airline-servlet.xml. + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/airline/src/main/webapp/WEB-INF/xsd/airline.xsd b/samples/airline/src/main/webapp/WEB-INF/xsd/airline.xsd new file mode 100644 index 00000000..5f27b82d --- /dev/null +++ b/samples/airline/src/main/webapp/WEB-INF/xsd/airline.xsd @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/airline/src/test/java/org/springframework/ws/samples/airline/dao/jpa/JpaFlightDaoTest.java b/samples/airline/src/test/java/org/springframework/ws/samples/airline/dao/jpa/JpaFlightDaoTest.java new file mode 100644 index 00000000..52179d38 --- /dev/null +++ b/samples/airline/src/test/java/org/springframework/ws/samples/airline/dao/jpa/JpaFlightDaoTest.java @@ -0,0 +1,114 @@ +/* + * 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.dao.jpa; + +import java.util.List; + +import org.joda.time.DateTime; +import org.joda.time.Interval; +import org.springframework.test.jpa.AbstractJpaTests; +import org.springframework.ws.samples.airline.dao.FlightDao; +import org.springframework.ws.samples.airline.domain.Airport; +import org.springframework.ws.samples.airline.domain.Flight; +import org.springframework.ws.samples.airline.domain.ServiceClass; + +public class JpaFlightDaoTest extends AbstractJpaTests { + + private FlightDao flightDao; + + private DateTime departureTime; + + private DateTime arrivalTime; + + private Interval interval; + + private Airport fromAirport; + + private Airport toAirport; + + public void setFlightDao(FlightDao flightDao) { + this.flightDao = flightDao; + } + + @Override + protected String[] getConfigPaths() { + return new String[]{"applicationContext-jpa.xml"}; + } + + @Override + protected void onSetUpBeforeTransaction() throws Exception { + departureTime = new DateTime(2006, 1, 31, 10, 5, 0, 0); + arrivalTime = new DateTime(2006, 1, 31, 12, 25, 0, 0); + interval = departureTime.toLocalDate().toInterval(); + fromAirport = new Airport("RTM", "Rotterdam Airport", "Rotterdam"); + toAirport = new Airport("OSL", "Gardermoen", "Oslo"); + } + + @Override + protected void onSetUpInTransaction() throws Exception { + jdbcTemplate.update("INSERT INTO AIRPORT(CODE, NAME, CITY) VALUES('RTM', 'Rotterdam Airport', 'Rotterdam')"); + jdbcTemplate.update("INSERT INTO AIRPORT(CODE, NAME, CITY) VALUES('OSL', 'Gardermoen', 'Oslo')"); + } + + public void testGetFlightsInPeriod() throws Exception { + jdbcTemplate + .update("INSERT INTO FLIGHT(NUMBER, DEPARTURE_TIME, FROM_AIRPORT_CODE, ARRIVAL_TIME, TO_AIRPORT_CODE, SERVICE_CLASS, SEATS_AVAILABLE, MILES) " + + "VALUES ('KL020','2006-01-31 10:05:00', 'RTM', '2006-01-31 12:25:00', 'OSL', 'BUSINESS', 90, 10)"); + List flights = flightDao.findFlights("RTM", "OSL", interval, ServiceClass.BUSINESS); + assertNotNull("Invalid result", flights); + assertEquals("Invalid amount of flights", 1, flights.size()); + } + + public void testGetFlightsOutOfPeriod() throws Exception { + jdbcTemplate + .update("INSERT INTO FLIGHT(NUMBER, DEPARTURE_TIME, FROM_AIRPORT_CODE, ARRIVAL_TIME, TO_AIRPORT_CODE, SERVICE_CLASS, SEATS_AVAILABLE, MILES) " + + "VALUES ('KL020','2006-01-31 10:05:00', 'RTM', '2006-01-31 12:25:00', 'OSL', 'BUSINESS', 90, 10)"); + DateTime dateTime = new DateTime(2006, 6, 1, 0, 0, 0, 0); + List flights = flightDao.findFlights("RTM", "OSL", new Interval(dateTime, dateTime), ServiceClass.BUSINESS); + assertNotNull("Invalid result", flights); + assertEquals("Invalid amount of flights", 0, flights.size()); + } + + public void testGetFlightByNumberDepartureTime() throws Exception { + jdbcTemplate + .update("INSERT INTO FLIGHT(NUMBER, DEPARTURE_TIME, FROM_AIRPORT_CODE, ARRIVAL_TIME, TO_AIRPORT_CODE, SERVICE_CLASS, SEATS_AVAILABLE, MILES) " + + "VALUES ('KL020','2006-01-31 10:05:00', 'RTM', '2006-01-31 12:25:00', 'OSL', 'BUSINESS', 90, 10)"); + Flight flight = flightDao.getFlight("KL020", departureTime); + assertNotNull("No flight returned", flight); + assertNotNull("Invalid flight id", flight.getId()); + assertEquals("Invalid flight number", "KL020", flight.getNumber()); + assertEquals("Invalid flight departure time", departureTime, flight.getDepartureTime()); + assertEquals("Invalid flight arrival time", arrivalTime, flight.getArrivalTime()); + assertEquals("Invalid flight from airport", fromAirport, flight.getFrom()); + assertEquals("Invalid flight to airport", toAirport, flight.getTo()); + assertEquals("Invalid flight service class", ServiceClass.BUSINESS, flight.getServiceClass()); + } + + public void testUpdate() throws Exception { + jdbcTemplate + .update("INSERT INTO FLIGHT(NUMBER, DEPARTURE_TIME, FROM_AIRPORT_CODE, ARRIVAL_TIME, TO_AIRPORT_CODE, SERVICE_CLASS, SEATS_AVAILABLE, MILES) " + + "VALUES ('KL020','2006-01-31 10:05:00', 'RTM', '2006-01-31 12:25:00', 'OSL', 'BUSINESS', 90, 10)"); + Flight flight = flightDao.getFlight("KL020", departureTime); + flight.setSeatsAvailable(0); + flightDao.update(flight); + sharedEntityManager.flush(); + int count = jdbcTemplate + .queryForInt("SELECT SEATS_AVAILABLE FROM FLIGHT WHERE ID = ?", new Object[]{flight.getId()}); + assertEquals("Flight not updated", 0, count); + } + +} \ No newline at end of file diff --git a/samples/airline/src/test/java/org/springframework/ws/samples/airline/dao/jpa/JpaFrequentFlyerDaoTest.java b/samples/airline/src/test/java/org/springframework/ws/samples/airline/dao/jpa/JpaFrequentFlyerDaoTest.java new file mode 100644 index 00000000..45f0eaa1 --- /dev/null +++ b/samples/airline/src/test/java/org/springframework/ws/samples/airline/dao/jpa/JpaFrequentFlyerDaoTest.java @@ -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.dao.jpa; + +import org.springframework.test.jpa.AbstractJpaTests; +import org.springframework.ws.samples.airline.dao.FrequentFlyerDao; +import org.springframework.ws.samples.airline.domain.FrequentFlyer; + +public class JpaFrequentFlyerDaoTest extends AbstractJpaTests { + + private FrequentFlyerDao frequentFlyerDao; + + public void setFrequentFlyerDao(FrequentFlyerDao frequentFlyerDao) { + this.frequentFlyerDao = frequentFlyerDao; + } + + @Override + protected String[] getConfigPaths() { + return new String[]{"applicationContext-jpa.xml"}; + } + + @Override + protected void onSetUpInTransaction() throws Exception { + jdbcTemplate + .update("INSERT INTO PASSENGER(ID, FIRST_NAME, LAST_NAME) " + "VALUES (42, 'Arjen', 'Poutsma')"); + jdbcTemplate + .update("INSERT INTO FREQUENT_FLYER(PASSENGER_ID, USERNAME, PASSWORD, MILES) " + + "VALUES (42, 'arjen', 'changeme', 0)"); + } + + public void testGetByUsername() throws Exception { + FrequentFlyer flyer = frequentFlyerDao.get("arjen"); + assertNotNull("No frequent flyer returned", flyer); + assertEquals("Invalid username", "arjen", flyer.getUsername()); + assertEquals("Invalid password", "changeme", flyer.getPassword()); + assertEquals("Invalid first name", "Arjen", flyer.getFirstName()); + assertEquals("Invalid last name", "Poutsma", flyer.getLastName()); + } + + +} \ No newline at end of file diff --git a/samples/airline/src/test/java/org/springframework/ws/samples/airline/dao/jpa/JpaTicketDaoTest.java b/samples/airline/src/test/java/org/springframework/ws/samples/airline/dao/jpa/JpaTicketDaoTest.java new file mode 100644 index 00000000..87aa1eb4 --- /dev/null +++ b/samples/airline/src/test/java/org/springframework/ws/samples/airline/dao/jpa/JpaTicketDaoTest.java @@ -0,0 +1,93 @@ +/* + * 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.dao.jpa; + +import org.joda.time.DateTime; +import org.joda.time.DateTimeZone; +import org.joda.time.LocalDate; +import org.springframework.test.jpa.AbstractJpaTests; +import org.springframework.ws.samples.airline.dao.TicketDao; +import org.springframework.ws.samples.airline.domain.Airport; +import org.springframework.ws.samples.airline.domain.Flight; +import org.springframework.ws.samples.airline.domain.Passenger; +import org.springframework.ws.samples.airline.domain.ServiceClass; +import org.springframework.ws.samples.airline.domain.Ticket; + +public class JpaTicketDaoTest extends AbstractJpaTests { + + private TicketDao ticketDao; + + private DateTime departureTime; + + private DateTime arrivalTime; + + private Flight flight; + + private Passenger passenger; + + public void setTicketDao(TicketDao ticketDao) { + this.ticketDao = ticketDao; + } + + @Override + protected String[] getConfigPaths() { + return new String[]{"applicationContext-jpa.xml"}; + } + + @Override + protected void onSetUpBeforeTransaction() throws Exception { + departureTime = new DateTime(2006, 1, 31, 10, 5, 0, 0, DateTimeZone.UTC); + arrivalTime = new DateTime(2006, 1, 31, 12, 25, 0, 0, DateTimeZone.UTC); + Airport fromAirport = new Airport("RTM", "Rotterdam Airport", "Rotterdam"); + Airport toAirport = new Airport("OSL", "Gardermoen", "Oslo"); + flight = new Flight(42L); + flight.setNumber("KL1653"); + flight.setDepartureTime(departureTime); + flight.setFrom(fromAirport); + flight.setArrivalTime(arrivalTime); + flight.setTo(toAirport); + flight.setServiceClass(ServiceClass.BUSINESS); + flight.setSeatsAvailable(90); + passenger = new Passenger(42L, "Arjen", "Poutsma"); + } + + @Override + protected void onSetUpInTransaction() throws Exception { + jdbcTemplate.update("INSERT INTO AIRPORT(CODE, NAME, CITY) VALUES('RTM', 'Rotterdam Airport', 'Rotterdam')"); + jdbcTemplate.update("INSERT INTO AIRPORT(CODE, NAME, CITY) VALUES('OSL', 'Gardermoen', 'Oslo')"); + jdbcTemplate + .update("INSERT INTO FLIGHT(ID, NUMBER, DEPARTURE_TIME, FROM_AIRPORT_CODE, ARRIVAL_TIME, TO_AIRPORT_CODE, SERVICE_CLASS, SEATS_AVAILABLE, MILES) " + + "VALUES (42, 'KL020','2006-01-31 10:05:00', 'RTM', '2006-01-31 12:25:00', 'OSL', 'BUSINESS', 90, 10)"); + } + + public void testSave() throws Exception { + Ticket ticket = new Ticket(); + ticket.addPassenger(passenger); + ticket.setFlight(flight); + ticket.setIssueDate(new LocalDate()); + int startTicketCount = jdbcTemplate.queryForInt("SELECT COUNT(0) FROM TICKET"); + int startPassengerCount = jdbcTemplate.queryForInt("SELECT COUNT(0) FROM PASSENGER"); + ticket = ticketDao.save(ticket); + sharedEntityManager.flush(); + assertNotNull("No Id generated", ticket.getId()); + int endTicketCount = jdbcTemplate.queryForInt("SELECT COUNT(0) FROM TICKET"); + int endPassengerCount = jdbcTemplate.queryForInt("SELECT COUNT(0) FROM PASSENGER"); + assertEquals("Flight not inserted", 1, endTicketCount - startTicketCount); + assertEquals("Passenger not inserted", 1, endPassengerCount - startPassengerCount); + } + +} \ No newline at end of file diff --git a/samples/airline/src/test/java/org/springframework/ws/samples/airline/security/AcegiFrequentFlyerSecurityServiceTest.java b/samples/airline/src/test/java/org/springframework/ws/samples/airline/security/AcegiFrequentFlyerSecurityServiceTest.java index 080bf71c..014eec11 100644 --- a/samples/airline/src/test/java/org/springframework/ws/samples/airline/security/AcegiFrequentFlyerSecurityServiceTest.java +++ b/samples/airline/src/test/java/org/springframework/ws/samples/airline/security/AcegiFrequentFlyerSecurityServiceTest.java @@ -21,8 +21,7 @@ import org.acegisecurity.context.SecurityContext; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.context.SecurityContextImpl; import org.acegisecurity.providers.TestingAuthenticationToken; -import org.easymock.MockControl; - +import static org.easymock.EasyMock.*; import org.springframework.ws.samples.airline.dao.FrequentFlyerDao; import org.springframework.ws.samples.airline.domain.FrequentFlyer; @@ -30,15 +29,11 @@ public class AcegiFrequentFlyerSecurityServiceTest extends TestCase { private AcegiFrequentFlyerSecurityService securityService; - private MockControl control; - - private FrequentFlyerDao mock; + private FrequentFlyerDao flyerDaoMock; protected void setUp() throws Exception { - securityService = new AcegiFrequentFlyerSecurityService(); - control = MockControl.createControl(FrequentFlyerDao.class); - mock = (FrequentFlyerDao) control.getMock(); - securityService.setFrequentFlyerDao(mock); + flyerDaoMock = createMock(FrequentFlyerDao.class); + securityService = new AcegiFrequentFlyerSecurityService(flyerDaoMock); } public void testGetCurrentlyAuthenticatedFrequentFlyer() throws Exception { @@ -48,18 +43,18 @@ public class AcegiFrequentFlyerSecurityServiceTest extends TestCase { SecurityContext context = new SecurityContextImpl(); context.setAuthentication(token); SecurityContextHolder.setContext(context); - control.replay(); + replay(flyerDaoMock); FrequentFlyer result = securityService.getCurrentlyAuthenticatedFrequentFlyer(); assertEquals("Invalid result", frequentFlyer, result); - control.verify(); + verify(flyerDaoMock); } public void testGetFrequentFlyer() throws Exception { FrequentFlyer frequentFlyer = new FrequentFlyer("john"); - control.expectAndReturn(mock.get("john"), frequentFlyer); - control.replay(); + expect(flyerDaoMock.get("john")).andReturn(frequentFlyer); + replay(flyerDaoMock); FrequentFlyer result = securityService.getFrequentFlyer("john"); assertEquals("Invalid result", frequentFlyer, result); - control.verify(); + verify(flyerDaoMock); } } \ No newline at end of file diff --git a/samples/airline/src/test/java/org/springframework/ws/samples/airline/service/impl/AirlineServiceImplTest.java b/samples/airline/src/test/java/org/springframework/ws/samples/airline/service/impl/AirlineServiceImplTest.java index 9ff9d25a..b3773e2f 100644 --- a/samples/airline/src/test/java/org/springframework/ws/samples/airline/service/impl/AirlineServiceImplTest.java +++ b/samples/airline/src/test/java/org/springframework/ws/samples/airline/service/impl/AirlineServiceImplTest.java @@ -20,7 +20,8 @@ import java.util.Collections; import java.util.List; import junit.framework.TestCase; -import org.easymock.MockControl; +import static org.easymock.EasyMock.*; +import org.easymock.IAnswer; import org.joda.time.DateTime; import org.joda.time.LocalDate; import org.springframework.ws.samples.airline.dao.FlightDao; @@ -38,148 +39,153 @@ public class AirlineServiceImplTest extends TestCase { private AirlineServiceImpl airlineService; - private MockControl flightDaoControl; - private FlightDao flightDaoMock; - private MockControl ticketDaoControl; - private TicketDao ticketDaoMock; - private MockControl securityServiceControl; - private FrequentFlyerSecurityService securityServiceMock; - protected void setUp() throws Exception { - airlineService = new AirlineServiceImpl(); - flightDaoControl = MockControl.createControl(FlightDao.class); - flightDaoMock = (FlightDao) flightDaoControl.getMock(); - airlineService.setFlightDao(flightDaoMock); - ticketDaoControl = MockControl.createControl(TicketDao.class); - ticketDaoMock = (TicketDao) ticketDaoControl.getMock(); - airlineService.setTicketDao(ticketDaoMock); - securityServiceControl = MockControl.createControl(FrequentFlyerSecurityService.class); - securityServiceMock = (FrequentFlyerSecurityService) securityServiceControl.getMock(); - airlineService.setFrequentFlyerSecurityService(securityServiceMock); - } + private String flightNumber; - protected void tearDown() throws Exception { - flightDaoControl.verify(); - ticketDaoControl.verify(); - securityServiceControl.verify(); + protected void setUp() throws Exception { + flightDaoMock = createMock(FlightDao.class); + ticketDaoMock = createMock(TicketDao.class); + airlineService = new AirlineServiceImpl(flightDaoMock, ticketDaoMock); + securityServiceMock = createMock(FrequentFlyerSecurityService.class); + airlineService.setFrequentFlyerSecurityService(securityServiceMock); + flightNumber = "AB1234"; } public void testBookFlight() throws Exception { - String flightNumber = "AB1234"; DateTime departureTime = new DateTime(); Passenger passenger = new Passenger("John", "Doe"); - List passengers = new ArrayList(); + List passengers = new ArrayList(); passengers.add(passenger); Flight flight = new Flight(); flight.setNumber(flightNumber); flight.setSeatsAvailable(10); - flightDaoControl.expectAndReturn(flightDaoMock.getFlight(flightNumber, departureTime), flight); - flightDaoMock.update(flight); - ticketDaoMock.save(null); - ticketDaoControl.setMatcher(MockControl.ALWAYS_MATCHER); - flightDaoControl.replay(); - ticketDaoControl.replay(); - securityServiceControl.replay(); - Ticket ticket = airlineService.bookFlight(flightNumber, departureTime, passengers); + expect(flightDaoMock.getFlight(flightNumber, departureTime)).andReturn(flight); + expect(flightDaoMock.update(flight)).andReturn(flight); + Ticket ticket = new Ticket(); + ticket.setFlight(flight); + expect(ticketDaoMock.save(isA(Ticket.class))).andAnswer(new IAnswer() { + public Ticket answer() throws Throwable { + return (Ticket) getCurrentArguments()[0]; + } + }); + + replay(flightDaoMock, ticketDaoMock, securityServiceMock); + + ticket = airlineService.bookFlight(flightNumber, departureTime, passengers); assertNotNull("Invalid ticket", ticket); assertEquals("Invalid flight", flight, ticket.getFlight()); assertEquals("Invalid seats available", 9, flight.getSeatsAvailable()); assertEquals("Invalid passengers count", 1, ticket.getPassengers().size()); + + verify(flightDaoMock, ticketDaoMock, securityServiceMock); } public void testBookFlightFrequentFlyer() throws Exception { - String flightNumber = "AB1234"; DateTime departureTime = new DateTime(); - FrequentFlyer frequentFlyer = new FrequentFlyer("john", "changeme", "John", "Doe"); - List passengers = new ArrayList(); + FrequentFlyer frequentFlyer = new FrequentFlyer("John", "Doe", "john", "changeme"); + List passengers = new ArrayList(); passengers.add(frequentFlyer); Flight flight = new Flight(); flight.setNumber(flightNumber); flight.setSeatsAvailable(1); flight.setMiles(10); - securityServiceControl.expectAndReturn(securityServiceMock.getFrequentFlyer("john"), frequentFlyer); - flightDaoControl.expectAndReturn(flightDaoMock.getFlight(flightNumber, departureTime), flight); - flightDaoMock.update(flight); - ticketDaoMock.save(null); - ticketDaoControl.setMatcher(MockControl.ALWAYS_MATCHER); - flightDaoControl.replay(); - ticketDaoControl.replay(); - securityServiceControl.replay(); + expect(securityServiceMock.getFrequentFlyer("john")).andReturn(frequentFlyer); + expect(flightDaoMock.getFlight(flightNumber, departureTime)).andReturn(flight); + expect(flightDaoMock.update(flight)).andReturn(flight); + expect(ticketDaoMock.save(isA(Ticket.class))).andAnswer(new IAnswer() { + public Ticket answer() throws Throwable { + return (Ticket) getCurrentArguments()[0]; + } + }); + + replay(flightDaoMock, ticketDaoMock, securityServiceMock); + Ticket ticket = airlineService.bookFlight(flightNumber, departureTime, passengers); assertNotNull("Invalid ticket", ticket); assertEquals("Invalid flight", flight, ticket.getFlight()); assertEquals("Invalid amount of miles", 10, frequentFlyer.getMiles()); + + verify(flightDaoMock, ticketDaoMock, securityServiceMock); } public void testBookFlightNoSeatAvailable() throws Exception { - String flightNumber = "AB1234"; DateTime departureTime = new DateTime(); - List passengers = Collections.singletonList(new Passenger()); + List passengers = Collections.singletonList(new Passenger()); Flight flight = new Flight(); - flightDaoControl.expectAndReturn(flightDaoMock.getFlight(flightNumber, departureTime), flight); - flightDaoControl.replay(); - ticketDaoControl.replay(); - securityServiceControl.replay(); + flight.setNumber("AB1234"); + flight.setDepartureTime(new DateTime()); + expect(flightDaoMock.getFlight(flightNumber, departureTime)).andReturn(flight); + + replay(flightDaoMock, ticketDaoMock, securityServiceMock); + try { airlineService.bookFlight(flightNumber, departureTime, passengers); fail("Should have thrown an NoSeatAvailableException"); } catch (NoSeatAvailableException ex) { } + + verify(flightDaoMock, ticketDaoMock, securityServiceMock); } public void testBookFlightNoSuchFlight() throws Exception { String flightNumber = "AB1234"; DateTime departureTime = new DateTime(); - List passengers = Collections.singletonList(new Passenger()); - flightDaoControl.expectAndReturn(flightDaoMock.getFlight(flightNumber, departureTime), null); - flightDaoControl.replay(); - ticketDaoControl.replay(); - securityServiceControl.replay(); + List passengers = Collections.singletonList(new Passenger()); + expect(flightDaoMock.getFlight(flightNumber, departureTime)).andReturn(null); + + replay(flightDaoMock, ticketDaoMock, securityServiceMock); try { airlineService.bookFlight(flightNumber, departureTime, passengers); fail("Should have thrown an NoSuchFlightException"); } catch (NoSuchFlightException ex) { } + + verify(flightDaoMock, ticketDaoMock, securityServiceMock); } public void testGetFlights() throws Exception { - String toCode = "to"; - String fromCode = "from"; LocalDate departureDate = new LocalDate(2006, 1, 31); Flight flight = new Flight(); - List flights = new ArrayList(); + List flights = new ArrayList(); flights.add(flight); - flightDaoControl.expectAndReturn( - flightDaoMock.findFlights(fromCode, toCode, departureDate.toInterval(), ServiceClass.ECONOMY), flights); - flightDaoControl.replay(); - ticketDaoControl.replay(); - securityServiceControl.replay(); + String toCode = "to"; + String fromCode = "from"; - List result = airlineService.getFlights(fromCode, toCode, departureDate, ServiceClass.ECONOMY); + expect(flightDaoMock.findFlights(fromCode, toCode, departureDate.toInterval(), ServiceClass.ECONOMY)) + .andReturn(flights); + + replay(flightDaoMock, ticketDaoMock, securityServiceMock); + + List result = airlineService.getFlights(fromCode, toCode, departureDate, ServiceClass.ECONOMY); assertEquals("Invalid result", flights, result); + + verify(flightDaoMock, ticketDaoMock, securityServiceMock); } public void testGetFlightsDefaultServiceClass() throws Exception { - String toCode = "to"; - String fromCode = "from"; LocalDate departureDate = new LocalDate(2006, 1, 31); Flight flight = new Flight(); - List flights = new ArrayList(); + List flights = new ArrayList(); flights.add(flight); - flightDaoControl.expectAndReturn( - flightDaoMock.findFlights(fromCode, toCode, departureDate.toInterval(), ServiceClass.ECONOMY), flights); - flightDaoControl.replay(); - ticketDaoControl.replay(); - securityServiceControl.replay(); + String toCode = "to"; + String fromCode = "from"; - List result = airlineService.getFlights(fromCode, toCode, departureDate, null); + expect(flightDaoMock.findFlights(fromCode, toCode, departureDate.toInterval(), ServiceClass.ECONOMY)) + .andReturn(flights); + + replay(flightDaoMock, ticketDaoMock, securityServiceMock); + + List result = airlineService.getFlights(fromCode, toCode, departureDate, null); assertEquals("Invalid result", flights, result); + + verify(flightDaoMock, ticketDaoMock, securityServiceMock); + } } diff --git a/samples/airline/src/test/java/org/springframework/ws/samples/airline/web/FlightsControllerTest.java b/samples/airline/src/test/java/org/springframework/ws/samples/airline/web/FlightsControllerTest.java new file mode 100644 index 00000000..cab51895 --- /dev/null +++ b/samples/airline/src/test/java/org/springframework/ws/samples/airline/web/FlightsControllerTest.java @@ -0,0 +1,66 @@ +/* + * 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.web; + +import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; +import static org.easymock.EasyMock.*; +import org.joda.time.LocalDate; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.ws.samples.airline.domain.Flight; +import org.springframework.ws.samples.airline.domain.ServiceClass; +import org.springframework.ws.samples.airline.service.AirlineService; + +public class FlightsControllerTest extends TestCase { + + private FlightsController flightsController; + + private AirlineService airlineServiceMock; + + protected void setUp() throws Exception { + airlineServiceMock = createMock(AirlineService.class); + flightsController = new FlightsController(airlineServiceMock); + } + + public void testFlightList() throws Exception { + MockHttpServletRequest request = new MockHttpServletRequest(); + String from = "AMS"; + request.setParameter("from", from); + String to = "VCE"; + request.setParameter("to", to); + LocalDate departureDate = new LocalDate(); + request.setParameter("departureDate", departureDate.toString()); + ServiceClass serviceClass = ServiceClass.FIRST; + request.setParameter("serviceClass", serviceClass.toString()); + MockHttpServletResponse response = new MockHttpServletResponse(); + List flights = new ArrayList(); + flights.add(new Flight()); + expect(airlineServiceMock.getFlights(from, to, departureDate, serviceClass)).andReturn(flights); + + replay(airlineServiceMock); + + ModelAndView mav = flightsController.flightList(request, response); + assertNotNull("No ModelAndView returned", mav); + assertEquals("Invalid view name", "flights", mav.getViewName()); + assertTrue("No flights in ModelAndView", mav.getModel().containsKey("flights")); + verify(airlineServiceMock); + } +} \ No newline at end of file diff --git a/samples/airline/src/test/java/org/springframework/ws/samples/airline/ws/BookFlightEndpointTest.java b/samples/airline/src/test/java/org/springframework/ws/samples/airline/ws/BookFlightEndpointTest.java deleted file mode 100644 index a2a433c0..00000000 --- a/samples/airline/src/test/java/org/springframework/ws/samples/airline/ws/BookFlightEndpointTest.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * 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 java.util.Collections; -import java.util.List; - -import org.custommonkey.xmlunit.XMLTestCase; -import org.custommonkey.xmlunit.XMLUnit; -import org.easymock.MockControl; -import org.jdom.Document; -import org.jdom.Element; -import org.jdom.input.SAXBuilder; -import org.jdom.output.XMLOutputter; -import org.joda.time.DateTime; -import org.joda.time.DateTimeZone; -import org.joda.time.YearMonthDay; -import org.springframework.ws.samples.airline.domain.Airport; -import org.springframework.ws.samples.airline.domain.Flight; -import org.springframework.ws.samples.airline.domain.FrequentFlyer; -import org.springframework.ws.samples.airline.domain.Passenger; -import org.springframework.ws.samples.airline.domain.ServiceClass; -import org.springframework.ws.samples.airline.domain.Ticket; -import org.springframework.ws.samples.airline.service.AirlineService; - -public class BookFlightEndpointTest extends XMLTestCase { - - private BookFlightEndpoint endpoint; - - private MockControl serviceControl; - - private AirlineService serviceMock; - - private DateTime departure; - - private Ticket ticket; - - private Document responseDocument; - - private SAXBuilder saxBuilder; - - protected void setUp() throws Exception { - XMLUnit.setIgnoreWhitespace(true); - endpoint = new BookFlightEndpoint(); - serviceControl = MockControl.createControl(AirlineService.class); - serviceMock = (AirlineService) serviceControl.getMock(); - endpoint.setAirlineService(serviceMock); - endpoint.afterPropertiesSet(); - saxBuilder = new SAXBuilder(); - responseDocument = saxBuilder.build(getClass().getResourceAsStream("bookFlightResponse.xml")); - departure = new DateTime(2006, 1, 1, 0, 0, 0, 0, DateTimeZone.UTC); - DateTime arrival = new DateTime(2006, 2, 2, 0, 0, 0, 0, DateTimeZone.UTC); - Flight flight = new Flight(); - flight.setNumber("EF1234"); - flight.setDepartureTime(departure); - flight.setArrivalTime(arrival); - Airport from = new Airport("ABC", "Airport", "City"); - Airport to = new Airport("DEF", "Airport", "City"); - flight.setFrom(from); - flight.setTo(to); - flight.setServiceClass(ServiceClass.ECONOMY); - ticket = new Ticket(); - ticket.setId(new Long(42)); - ticket.setFlight(flight); - ticket.setIssueDate(new YearMonthDay(2006, 1, 1)); - } - - public void testInvoke() throws Exception { - Passenger passenger = new Passenger("John", "Doe"); - List passengers = Collections.singletonList(passenger); - ticket.addPassenger(passenger); - serviceControl.expectAndReturn(serviceMock.bookFlight("EF1234", departure, passengers), ticket); - serviceControl.replay(); - Document requestDocument = saxBuilder.build(getClass().getResourceAsStream("bookFlightRequest.xml")); - Element result = endpoint.invokeInternal(requestDocument.getRootElement()); - assertNotNull("Invalid result", result); - Document resultDocument = new Document(); - resultDocument.setRootElement(result); - XMLOutputter outputter = new XMLOutputter(); - assertXMLEqual(outputter.outputString(responseDocument), outputter.outputString(resultDocument)); - serviceControl.verify(); - } - - public void testInvokeFrequentFlyer() throws Exception { - FrequentFlyer frequentFlyer = new FrequentFlyer("john", "changeme", "John", "Doe"); - List passengers = Collections.singletonList(frequentFlyer); - ticket.addPassenger(frequentFlyer); - serviceControl.expectAndReturn(serviceMock.bookFlight("EF1234", departure, passengers), ticket); - serviceControl.replay(); - Document requestDocument = - saxBuilder.build(getClass().getResourceAsStream("bookFlightRequestFrequentFlyer.xml")); - Element result = endpoint.invokeInternal(requestDocument.getRootElement()); - assertNotNull("Invalid result", result); - Document resultDocument = new Document(); - resultDocument.setRootElement(result); - XMLOutputter outputter = new XMLOutputter(); - assertXMLEqual(outputter.outputString(responseDocument), outputter.outputString(resultDocument)); - serviceControl.verify(); - } - - -} \ No newline at end of file diff --git a/samples/airline/src/test/java/org/springframework/ws/samples/airline/ws/GetFlightsEndpointTest.java b/samples/airline/src/test/java/org/springframework/ws/samples/airline/ws/GetFlightsEndpointTest.java deleted file mode 100644 index e42f82c4..00000000 --- a/samples/airline/src/test/java/org/springframework/ws/samples/airline/ws/GetFlightsEndpointTest.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * 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 java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import junit.framework.TestCase; -import org.easymock.MockControl; -import org.joda.time.DateTime; -import org.joda.time.LocalDate; -import org.springframework.oxm.jaxb.Jaxb1Marshaller; -import org.springframework.ws.WebServiceMessage; -import org.springframework.ws.context.MessageContext; -import org.springframework.ws.samples.airline.domain.Flight; -import org.springframework.ws.samples.airline.schema.GetFlightsRequest; -import org.springframework.ws.samples.airline.schema.GetFlightsResponse; -import org.springframework.ws.samples.airline.schema.ServiceClass; -import org.springframework.ws.samples.airline.schema.impl.GetFlightsRequestImpl; -import org.springframework.ws.samples.airline.service.AirlineService; -import org.springframework.xml.transform.StringResult; -import org.springframework.xml.transform.StringSource; - -public class GetFlightsEndpointTest extends TestCase { - - private GetFlightsEndpoint endpoint; - - private MockControl serviceControl; - - private AirlineService serviceMock; - - protected void setUp() throws Exception { - endpoint = new GetFlightsEndpoint(); - serviceControl = MockControl.createControl(AirlineService.class); - serviceMock = (AirlineService) serviceControl.getMock(); - endpoint.setAirlineService(serviceMock); - } - - public void testInvoke() throws Exception { - String fromAirportCode = "ABC"; - String toAirportCode = "DEF"; - LocalDate departureDate = new LocalDate(); - GetFlightsRequest request = new GetFlightsRequestImpl(); - request.setFrom(fromAirportCode); - request.setTo(toAirportCode); - request.setDepartureDate(departureDate.toDateTimeAtMidnight().toGregorianCalendar()); - request.setServiceClass(ServiceClass.FIRST); - List flights = new ArrayList(); - Flight flight = new Flight(); - flight.setNumber("1"); - flight.setDepartureTime(new DateTime()); - flight.setArrivalTime(new DateTime()); - flights.add(flight); - serviceControl.expectAndReturn(serviceMock.getFlights(fromAirportCode, toAirportCode, departureDate, - org.springframework.ws.samples.airline.domain.ServiceClass.FIRST), flights); - serviceControl.replay(); - GetFlightsResponse response = (GetFlightsResponse) endpoint.invokeInternal(request); - serviceControl.verify(); - assertNotNull("Response is null", response); - assertEquals("Invalid amount of flights in response", 1, response.getFlight().size()); - org.springframework.ws.samples.airline.schema.Flight responseFlight = - (org.springframework.ws.samples.airline.schema.Flight) response.getFlight().get(0); - assertEquals("Invalid flight number on flight", "1", responseFlight.getNumber()); - } - - public void testMarshalling() throws Exception { - Jaxb1Marshaller marshaller = new Jaxb1Marshaller(); - marshaller.setContextPath("org.springframework.ws.samples.airline.schema"); - marshaller.setValidating(true); - marshaller.afterPropertiesSet(); - endpoint.setMarshaller(marshaller); - endpoint.setUnmarshaller(marshaller); - - MockControl contextControl = MockControl.createControl(MessageContext.class); - MessageContext contextMock = (MessageContext) contextControl.getMock(); - MockControl messageControl = MockControl.createControl(WebServiceMessage.class); - WebServiceMessage requestMock = (WebServiceMessage) messageControl.getMock(); - WebServiceMessage responseMock = (WebServiceMessage) messageControl.getMock(); - - contextControl.expectAndReturn(contextMock.getRequest(), requestMock); - StringSource source = new StringSource( - "AMSVCE2006-01-31Z"); - messageControl.expectAndReturn(requestMock.getPayloadSource(), source); - String fromAirportCode = "AMS"; - String toAirportCode = "VCE"; - LocalDate departureDate = new LocalDate(2006, 1, 31); - serviceControl.expectAndReturn(serviceMock.getFlights(fromAirportCode, toAirportCode, departureDate, null), - Collections.EMPTY_LIST); - contextControl.expectAndReturn(contextMock.getResponse(), responseMock); - StringResult result = new StringResult(); - messageControl.expectAndReturn(responseMock.getPayloadResult(), result); - - contextControl.replay(); - messageControl.replay(); - serviceControl.replay(); - - endpoint.invoke(contextMock); - - contextControl.verify(); - messageControl.verify(); - serviceControl.verify(); - } - -} diff --git a/samples/airline/src/test/java/org/springframework/ws/samples/airline/ws/MarshallingAirlineEndpointTest.java b/samples/airline/src/test/java/org/springframework/ws/samples/airline/ws/MarshallingAirlineEndpointTest.java new file mode 100644 index 00000000..0cf8eda7 --- /dev/null +++ b/samples/airline/src/test/java/org/springframework/ws/samples/airline/ws/MarshallingAirlineEndpointTest.java @@ -0,0 +1,204 @@ +/* + * 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 java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import javax.xml.bind.JAXBElement; +import javax.xml.datatype.DatatypeConstants; +import javax.xml.datatype.DatatypeFactory; + +import junit.framework.TestCase; +import static org.easymock.EasyMock.*; +import org.joda.time.DateTime; +import org.joda.time.DateTimeZone; +import org.joda.time.LocalDate; +import org.springframework.ws.samples.airline.domain.Airport; +import org.springframework.ws.samples.airline.domain.FrequentFlyer; +import org.springframework.ws.samples.airline.domain.Passenger; +import org.springframework.ws.samples.airline.schema.BookFlightRequest; +import org.springframework.ws.samples.airline.schema.Flight; +import org.springframework.ws.samples.airline.schema.GetFlightsRequest; +import org.springframework.ws.samples.airline.schema.GetFlightsResponse; +import org.springframework.ws.samples.airline.schema.Name; +import org.springframework.ws.samples.airline.schema.ObjectFactory; +import org.springframework.ws.samples.airline.schema.ServiceClass; +import org.springframework.ws.samples.airline.schema.Ticket; +import org.springframework.ws.samples.airline.service.AirlineService; + +public class MarshallingAirlineEndpointTest extends TestCase { + + private MarshallingAirlineEndpoint endpoint; + + private AirlineService airlineServiceMock; + + private DatatypeFactory datatypeFactory; + + private ObjectFactory objectFactory; + + protected void setUp() throws Exception { + airlineServiceMock = createMock(AirlineService.class); + endpoint = new MarshallingAirlineEndpoint(airlineServiceMock); + datatypeFactory = DatatypeFactory.newInstance(); + objectFactory = new ObjectFactory(); + } + + public void testGetFlights() throws Exception { + GetFlightsRequest request = objectFactory.createGetFlightsRequest(); + request.setDepartureDate( + datatypeFactory.newXMLGregorianCalendarDate(2007, 6, 13, DatatypeConstants.FIELD_UNDEFINED)); + request.setFrom("ABC"); + request.setTo("DEF"); + request.setServiceClass(ServiceClass.FIRST); + + org.springframework.ws.samples.airline.domain.Flight domainFlight = createDomainFlight(); + + expect(airlineServiceMock.getFlights("ABC", "DEF", new LocalDate(2007, 6, 13), + org.springframework.ws.samples.airline.domain.ServiceClass.FIRST)) + .andReturn(Collections.singletonList(domainFlight)); + + replay(airlineServiceMock); + + GetFlightsResponse response = endpoint.getFlights(request); + assertEquals("Invalid amount of flights received", 1, response.getFlight().size()); + Flight schemaFlight = response.getFlight().get(0); + verifySchemaFlight(schemaFlight); + + verify(airlineServiceMock); + } + + private void verifySchemaFlight(Flight schemaFlight) { + assertEquals("Invalid number", "ABC1234", schemaFlight.getNumber()); + assertEquals("Invalid departure time", datatypeFactory.newXMLGregorianCalendar(2007, 6, 13, 12, 0, 0, 0, 0), + schemaFlight.getDepartureTime()); + assertEquals("Invalid from code", "ABC", schemaFlight.getFrom().getCode()); + assertEquals("Invalid from name", "ABC Airport", schemaFlight.getFrom().getName()); + assertEquals("Invalid from city", "ABC City", schemaFlight.getFrom().getCity()); + assertEquals("Invalid arrival time", datatypeFactory.newXMLGregorianCalendar(2007, 6, 13, 14, 0, 0, 0, 0), + schemaFlight.getArrivalTime()); + assertEquals("Invalid to code", "DEF", schemaFlight.getTo().getCode()); + assertEquals("Invalid to name", "DEF Airport", schemaFlight.getTo().getName()); + assertEquals("Invalid to city", "DEF City", schemaFlight.getTo().getCity()); + assertEquals("Invalid service class", ServiceClass.FIRST, schemaFlight.getServiceClass()); + } + + private org.springframework.ws.samples.airline.domain.Flight createDomainFlight() { + org.springframework.ws.samples.airline.domain.Flight domainFlight = + new org.springframework.ws.samples.airline.domain.Flight(); + domainFlight.setNumber("ABC1234"); + domainFlight.setDepartureTime(new DateTime(2007, 6, 13, 12, 0, 0, 0, DateTimeZone.UTC)); + domainFlight.setFrom(new Airport("ABC", "ABC Airport", "ABC City")); + domainFlight.setArrivalTime(new DateTime(2007, 6, 13, 14, 0, 0, 0, DateTimeZone.UTC)); + domainFlight.setTo(new Airport("DEF", "DEF Airport", "DEF City")); + domainFlight.setServiceClass(org.springframework.ws.samples.airline.domain.ServiceClass.FIRST); + return domainFlight; + } + + public void testBookFlightPassenger() throws Exception { + BookFlightRequest request = objectFactory.createBookFlightRequest(); + request.setDepartureTime(datatypeFactory.newXMLGregorianCalendar(2007, 6, 13, 12, 0, 0, 0, 0)); + request.setFlightNumber("ABC1234"); + Name passengerName = new Name(); + passengerName.setFirst("John"); + passengerName.setLast("Doe"); + BookFlightRequest.Passengers passengers = new BookFlightRequest.Passengers(); + passengers.getPassengerOrUsername().add(passengerName); + request.setPassengers(passengers); + + Passenger domainPassenger = new Passenger("John", "Doe"); + + org.springframework.ws.samples.airline.domain.Ticket domainTicket = + new org.springframework.ws.samples.airline.domain.Ticket(42L); + domainTicket.setFlight(createDomainFlight()); + domainTicket.setIssueDate(new LocalDate(2007, 6, 13)); + domainTicket.setPassengers(Collections.singleton(domainPassenger)); + + expect(airlineServiceMock.bookFlight("ABC1234", new DateTime(2007, 6, 13, 12, 0, 0, 0, DateTimeZone.UTC), + Collections.singletonList(domainPassenger))).andReturn(domainTicket); + + replay(airlineServiceMock); + + JAXBElement response = endpoint.bookFlight(request); + Ticket schemaTicket = response.getValue(); + assertEquals("Invalid id", 42L, schemaTicket.getId()); + assertEquals("Invalid issue date", + datatypeFactory.newXMLGregorianCalendarDate(2007, 6, 13, DatatypeConstants.FIELD_UNDEFINED), + schemaTicket.getIssueDate()); + assertEquals("Invalid amount of passengers", 1, schemaTicket.getPassengers().getPassenger().size()); + Name schemaPassenger = schemaTicket.getPassengers().getPassenger().get(0); + assertEquals("Invalid passenger first name", "John", schemaPassenger.getFirst()); + assertEquals("Invalid passenger first name", "Doe", schemaPassenger.getLast()); + verifySchemaFlight(schemaTicket.getFlight()); + + verify(airlineServiceMock); + } + + public void testBookFlightFrequentFlyer() throws Exception { + BookFlightRequest request = objectFactory.createBookFlightRequest(); + request.setDepartureTime(datatypeFactory.newXMLGregorianCalendar(2007, 6, 13, 12, 0, 0, 0, 0)); + request.setFlightNumber("ABC1234"); + BookFlightRequest.Passengers passengers = new BookFlightRequest.Passengers(); + passengers.getPassengerOrUsername().add("john"); + request.setPassengers(passengers); + + FrequentFlyer domainFrequentFlyer = new FrequentFlyer("John", "Doe", "john", "changeme"); + Set domainPassengers = new HashSet(); + domainPassengers.add(domainFrequentFlyer); + + org.springframework.ws.samples.airline.domain.Ticket domainTicket = + new org.springframework.ws.samples.airline.domain.Ticket(42L); + domainTicket.setFlight(createDomainFlight()); + domainTicket.setIssueDate(new LocalDate(2007, 6, 13)); + domainTicket.setPassengers(domainPassengers); + + List domainPassengerList = new ArrayList(domainPassengers); + expect(airlineServiceMock.bookFlight("ABC1234", new DateTime(2007, 6, 13, 12, 0, 0, 0, DateTimeZone.UTC), + domainPassengerList)).andReturn(domainTicket); + + replay(airlineServiceMock); + + JAXBElement response = endpoint.bookFlight(request); + Ticket schemaTicket = response.getValue(); + assertEquals("Invalid id", 42L, schemaTicket.getId()); + assertEquals("Invalid issue date", + datatypeFactory.newXMLGregorianCalendarDate(2007, 6, 13, DatatypeConstants.FIELD_UNDEFINED), + schemaTicket.getIssueDate()); + assertEquals("Invalid amount of passengers", 1, schemaTicket.getPassengers().getPassenger().size()); + Name schemaPassenger = schemaTicket.getPassengers().getPassenger().get(0); + assertEquals("Invalid passenger first name", "John", schemaPassenger.getFirst()); + assertEquals("Invalid passenger first name", "Doe", schemaPassenger.getLast()); + verifySchemaFlight(schemaTicket.getFlight()); + + verify(airlineServiceMock); + } + + public void testGetFrequentFlyerMileage() throws Exception { + JAXBElement request = objectFactory.createGetFrequentFlyerMileageRequest(null); + + expect(airlineServiceMock.getFrequentFlyerMileage()).andReturn(42); + + replay(airlineServiceMock); + + JAXBElement response = endpoint.getFrequentFlyerMileage(request); + assertEquals("Invalid amount of miles received", 42, response.getValue().intValue()); + + verify(airlineServiceMock); + } +} \ No newline at end of file diff --git a/samples/airline/src/test/java/org/springframework/ws/samples/airline/ws/XPathAirlineEndpointTest.java b/samples/airline/src/test/java/org/springframework/ws/samples/airline/ws/XPathAirlineEndpointTest.java new file mode 100644 index 00000000..5a5c9ed2 --- /dev/null +++ b/samples/airline/src/test/java/org/springframework/ws/samples/airline/ws/XPathAirlineEndpointTest.java @@ -0,0 +1,41 @@ +/* + * 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 junit.framework.TestCase; +import static org.easymock.EasyMock.createMock; +import org.springframework.oxm.Marshaller; +import org.springframework.ws.samples.airline.service.AirlineService; + +public class XPathAirlineEndpointTest extends TestCase { + + private XPathAirlineEndpoint endpoint; + + private AirlineService airlineServiceMock; + + private Marshaller marshallerMock; + + protected void setUp() throws Exception { + airlineServiceMock = createMock(AirlineService.class); + marshallerMock = createMock(Marshaller.class); + endpoint = new XPathAirlineEndpoint(airlineServiceMock, marshallerMock); + } + + public void testGetFlights() throws Exception { + endpoint.getFlights("ABC", "DEF", "2006-01-31Z", ""); + } +} \ No newline at end of file diff --git a/samples/airline/src/test/resources/org/springframework/ws/samples/airline/ws/bookFlightRequest.xml b/samples/airline/src/test/resources/org/springframework/ws/samples/airline/ws/bookFlightRequest.xml deleted file mode 100644 index cea57ce0..00000000 --- a/samples/airline/src/test/resources/org/springframework/ws/samples/airline/ws/bookFlightRequest.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - EF1234 - 2006-01-01T00:00:00.000Z - - - John - Doe - - - diff --git a/samples/airline/src/test/resources/org/springframework/ws/samples/airline/ws/bookFlightRequestFrequentFlyer.xml b/samples/airline/src/test/resources/org/springframework/ws/samples/airline/ws/bookFlightRequestFrequentFlyer.xml deleted file mode 100644 index 64bc5237..00000000 --- a/samples/airline/src/test/resources/org/springframework/ws/samples/airline/ws/bookFlightRequestFrequentFlyer.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - EF1234 - 2006-01-01T00:00:00.000Z - - john - - diff --git a/samples/airline/src/test/resources/org/springframework/ws/samples/airline/ws/bookFlightResponse.xml b/samples/airline/src/test/resources/org/springframework/ws/samples/airline/ws/bookFlightResponse.xml deleted file mode 100644 index f0184e5d..00000000 --- a/samples/airline/src/test/resources/org/springframework/ws/samples/airline/ws/bookFlightResponse.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - 42 - 2006-01-01 - - - John - Doe - - - - EF1234 - 2006-01-01T00:00:00Z - - ABC - Airport - City - - 2006-02-02T00:00:00Z - - DEF - Airport - City - - economy - - \ No newline at end of file