diff --git a/samples/tutorial/pom.xml b/samples/tutorial/pom.xml
new file mode 100644
index 00000000..76334b4d
--- /dev/null
+++ b/samples/tutorial/pom.xml
@@ -0,0 +1,78 @@
+
+
+
+
+
+ spring-ws-samples
+ org.springframework.ws
+ 1.0-rc1-SNAPSHOT
+
+ 4.0.0
+ tutorial
+ war
+ Spring WS Holdiday Service Tutorial
+ This sample contains the code for the tutorial in the reference documentation.
+
+
+
+ org.springframework.ws
+ spring-ws-core
+
+
+ jdom
+ jdom
+
+
+ jaxen
+ jaxen
+
+
+ dom4j
+ dom4j
+
+
+ jdom
+ jdom
+
+
+ xom
+ xom
+
+
+ xerces
+ xmlParserAPIs
+
+
+ xerces
+ xercesImpl
+
+
+
+
+
+ org.springframework
+ spring-mock
+
+
+ easymock
+ easymock
+ 1.2_Java1.3
+ test
+
+
+
diff --git a/samples/tutorial/src/main/java/com/mycompany/hr/service/HumanResourceService.java b/samples/tutorial/src/main/java/com/mycompany/hr/service/HumanResourceService.java
new file mode 100644
index 00000000..ebc47d85
--- /dev/null
+++ b/samples/tutorial/src/main/java/com/mycompany/hr/service/HumanResourceService.java
@@ -0,0 +1,38 @@
+/*
+ * 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 com.mycompany.hr.service;
+
+import java.util.Date;
+
+/**
+ * This interface defined the contract for a HR business service. It is used by the {@link
+ * com.mycompany.hr.ws.HolidayEndpoint}.
+ *
+ * @author Arjen Poutsma
+ */
+public interface HumanResourceService {
+
+ /**
+ * Books a holiday.
+ *
+ * @param startDate the start date of the holiday
+ * @param endDate the end date of the holiday
+ * @param name the name of the person taking the holiday
+ */
+ void bookHoliday(Date startDate, Date endDate, String name);
+
+}
diff --git a/samples/tutorial/src/main/java/com/mycompany/hr/service/StubHumanResourceService.java b/samples/tutorial/src/main/java/com/mycompany/hr/service/StubHumanResourceService.java
new file mode 100644
index 00000000..65fe8ab3
--- /dev/null
+++ b/samples/tutorial/src/main/java/com/mycompany/hr/service/StubHumanResourceService.java
@@ -0,0 +1,37 @@
+/*
+ * 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 com.mycompany.hr.service;
+
+import java.util.Date;
+import java.util.logging.Logger;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Simple stub implementation of {@link HumanResourceService}, which does nothing but logging.
+ *
+ * @author Arjen Poutsma
+ */
+public class StubHumanResourceService implements HumanResourceService {
+
+ private static final Log logger = LogFactory.getLog(StubHumanResourceService.class);
+
+ public void bookHoliday(Date startDate, Date endDate, String name) {
+ logger.info("Booking holiday for [" + startDate + "-" + endDate + "] for [" + name + "] ");
+ }
+}
diff --git a/samples/tutorial/src/main/java/com/mycompany/hr/ws/HolidayEndpoint.java b/samples/tutorial/src/main/java/com/mycompany/hr/ws/HolidayEndpoint.java
new file mode 100644
index 00000000..091659f8
--- /dev/null
+++ b/samples/tutorial/src/main/java/com/mycompany/hr/ws/HolidayEndpoint.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 com.mycompany.hr.ws;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import com.mycompany.hr.service.HumanResourceService;
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.jdom.Namespace;
+import org.jdom.xpath.XPath;
+import org.springframework.ws.server.endpoint.AbstractJDomPayloadEndpoint;
+
+/**
+ * This endpoint handles holiday requests. It uses a combination of JDOM and XPath to extract interesting pieces of XML
+ * from the incoming message, and invoked the injected {@link HumanResourceService} with those.
+ *
+ * @author Arjen Poutsma
+ */
+public class HolidayEndpoint extends AbstractJDomPayloadEndpoint {
+
+ private XPath startDateExpression;
+
+ private XPath endDateExpression;
+
+ private XPath nameExpression;
+
+ private HumanResourceService humanResourceService;
+
+ public HolidayEndpoint(HumanResourceService humanResourceService) throws JDOMException {
+ this.humanResourceService = humanResourceService;
+ Namespace namespace = Namespace.getNamespace("hr", "http://mycompany.com/hr/schemas");
+ startDateExpression = XPath.newInstance("//hr:StartDate");
+ startDateExpression.addNamespace(namespace);
+ endDateExpression = XPath.newInstance("//hr:EndDate");
+ endDateExpression.addNamespace(namespace);
+ nameExpression = XPath.newInstance("concat(//hr:FirstName,' ',//hr:LastName)");
+ nameExpression.addNamespace(namespace);
+ }
+
+ protected Element invokeInternal(Element holidayRequest) throws Exception {
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+ Date startDate = dateFormat.parse(startDateExpression.valueOf(holidayRequest));
+ Date endDate = dateFormat.parse(endDateExpression.valueOf(holidayRequest));
+ String name = nameExpression.valueOf(holidayRequest);
+
+ humanResourceService.bookHoliday(startDate, endDate, name);
+ return null;
+ }
+
+}
diff --git a/samples/tutorial/src/main/resources/log4j.properties b/samples/tutorial/src/main/resources/log4j.properties
new file mode 100644
index 00000000..16826636
--- /dev/null
+++ b/samples/tutorial/src/main/resources/log4j.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+log4j.rootLogger=WARN, stdout
+log4j.logger.org.springframework.ws=DEBUG
+log4j.logger.org.springframework.xml=DEBUG
+log4j.logger.com.mycompany.hr=DEBUG
+
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
\ No newline at end of file
diff --git a/samples/tutorial/src/main/webapp/WEB-INF/hr.wsdl b/samples/tutorial/src/main/webapp/WEB-INF/hr.wsdl
new file mode 100644
index 00000000..e21e5221
--- /dev/null
+++ b/samples/tutorial/src/main/webapp/WEB-INF/hr.wsdl
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/tutorial/src/main/webapp/WEB-INF/hr.xsd b/samples/tutorial/src/main/webapp/WEB-INF/hr.xsd
new file mode 100644
index 00000000..3cd5b870
--- /dev/null
+++ b/samples/tutorial/src/main/webapp/WEB-INF/hr.xsd
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/tutorial/src/main/webapp/WEB-INF/spring-ws-servlet.xml b/samples/tutorial/src/main/webapp/WEB-INF/spring-ws-servlet.xml
new file mode 100644
index 00000000..e7b241ae
--- /dev/null
+++ b/samples/tutorial/src/main/webapp/WEB-INF/spring-ws-servlet.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ holidayEndpoint
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/tutorial/src/main/webapp/WEB-INF/web.xml b/samples/tutorial/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 00000000..68288e8a
--- /dev/null
+++ b/samples/tutorial/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+ MyCompany HR Holiday Service
+
+
+ spring-ws
+ org.springframework.ws.transport.http.MessageDispatcherServlet
+
+
+
+ spring-ws
+ /*
+
+
+
diff --git a/samples/tutorial/src/test/java/com/mycompany/hr/ws/HolidayEndpointTest.java b/samples/tutorial/src/test/java/com/mycompany/hr/ws/HolidayEndpointTest.java
new file mode 100644
index 00000000..09fa2245
--- /dev/null
+++ b/samples/tutorial/src/test/java/com/mycompany/hr/ws/HolidayEndpointTest.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 com.mycompany.hr.ws;
+
+import java.io.InputStream;
+import java.util.Calendar;
+
+import com.mycompany.hr.service.HumanResourceService;
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.input.SAXBuilder;
+
+public class HolidayEndpointTest extends TestCase {
+
+ private Document holidayRequest;
+
+ private HolidayEndpoint endpoint;
+
+ private MockControl mockControl;
+
+ private HumanResourceService serviceMock;
+
+ private Calendar startCalendar;
+
+ private Calendar endCalendar;
+
+ protected void setUp() throws Exception {
+ mockControl = MockControl.createControl(HumanResourceService.class);
+ serviceMock = (HumanResourceService) mockControl.getMock();
+ SAXBuilder builder = new SAXBuilder();
+ InputStream is = getClass().getResourceAsStream("holidayRequest.xml");
+ try {
+ holidayRequest = builder.build(is);
+ }
+ finally {
+ is.close();
+ }
+ endpoint = new HolidayEndpoint(serviceMock);
+ startCalendar = Calendar.getInstance();
+ startCalendar.clear();
+ startCalendar.set(2006, Calendar.JULY, 3);
+ endCalendar = Calendar.getInstance();
+ endCalendar.clear();
+ endCalendar.set(2006, Calendar.JULY, 7);
+ }
+
+ public void testInvokeInternal() throws Exception {
+ serviceMock.bookHoliday(startCalendar.getTime(), endCalendar.getTime(), "John Doe");
+ mockControl.replay();
+ Element result = endpoint.invokeInternal(holidayRequest.getRootElement());
+ assertNull("No result expected", result);
+ mockControl.verify();
+ }
+
+
+}
diff --git a/samples/tutorial/src/test/java/com/mycompany/hr/ws/holidayRequest.xml b/samples/tutorial/src/test/java/com/mycompany/hr/ws/holidayRequest.xml
new file mode 100644
index 00000000..bfa7e796
--- /dev/null
+++ b/samples/tutorial/src/test/java/com/mycompany/hr/ws/holidayRequest.xml
@@ -0,0 +1,27 @@
+
+
+
+
+ 2006-07-03
+ 2006-07-07
+
+
+ 42
+ John
+ Doe
+
+
\ No newline at end of file