diff --git a/src/docbkx/tutorial.xml b/src/docbkx/tutorial.xml index 8da5a83f..63721cbc 100644 --- a/src/docbkx/tutorial.xml +++ b/src/docbkx/tutorial.xml @@ -483,7 +483,20 @@ The following command creates a Maven2 web application project for us, using the Spring-WS archetype - (i.e. project template) + (i.e. project template) + + Until version RC1 of Spring-WS is released, the following has to be added to to + ~/.m2/settings.xml in order to find the archetype: + + springframework.org + Springframework Maven SNAPSHOT Repository + http://static.springframework.org/maven2-snapshots/ + + true + +]]> + mvn archetype:create -DarchetypeGroupId=org.springframework.ws \ -DarchetypeArtifactId=spring-ws-archetype \ diff --git a/src/site/apt/tutorial/tutorial1.apt b/src/site/apt/tutorial/tutorial1.apt deleted file mode 100644 index 5879b22a..00000000 --- a/src/site/apt/tutorial/tutorial1.apt +++ /dev/null @@ -1,348 +0,0 @@ - ----------------------------------- - Writing Contract-first Web Services - ----------------------------------- - -Introduction - - This is the first part of an overall tutorial on how to approach Web services development in contract-first style, -i.e. starting with the XML Schema/WSDL contract instead of Java code. Spring Web Services focuses on this -development style, and this tutorial helps you get started. Note that this page contains almost no Spring-WS -specific information: it is mostly about XML, XSD, and WSDL. The {{{tutorial2.html}second page}} focusses on -implementing this contract using Spring-WS. - - In this tutorial, we will define a Web service that can be used for Human Resources. Clients can send -holiday request forms to this service to book a holiday. It is based on a metaphor for Service Oriented Architectures -originally thought of by {{{http://blog.springframework.com/arjen/archives/2006/02/06/what-is-so-hard-about-soa/}Dan -North}}. - - The most important thing when doing contract-first Web service development is to try and think in terms of -XML. This means that Java-language concepts are of lesser importance. It is the XML that is sent across the wire, and -you should focus on that. The fact that Java is used to implement the Web service is an implementation detail. An -important detail, but a detail nonetheless. - -The Messages - - In this section, we will focus on the actual XML messages that are sent to and from the service. We will -start out by determining what these messages look like. - -* Holiday - - In the scenario, we have to deal with holiday request, so it makes sense to determine what a holiday looks like: - -+------------------------------------- - - 2006-07-03 - 2006-07-07 - -+------------------------------------- - - A holiday consists of a start date and an end date. We decided to use the standard -{{{http://www.cl.cam.ac.uk/~mgk25/iso-time.html}ISO 8601}} date format for the dates, because that will save a lot of -parsing hassle. We also added a namespace to the element, to make sure our elements can used within other XML documents. - -* Employee - - There is also the notion of an employee in the scenario. Here's what it looks like: - -+------------------------------------- - - 42 - Arjen - Poutsma - -+------------------------------------- - - - We have used the same namespace as before. If this employee element could be used in other scenarios, it might make -sense to use a different namespace, such as <<<"http://mycompany.com/employees/schemas">>>. - -* HolidayRequest - - Both the holiday and employee element can be put in a <<>>: - -+------------------------------------- - - - 2006-07-03 - 2006-07-07 - - - 42 - Arjen - Poutsma - - -+------------------------------------- - - The order of the two element does not matter: <<>> could have been the first element just as -well. As long as all the data is there; that's what is important. In fact, the data is the only thing that is -important: we are taking a <> approach. - -The Schema - - Now that we have seen some examples of the XML data that we will use, it makes sense to formalize this into -a schema. Basically, there are four different ways of defining a grammar for XML: - - * DTDs - - * {{{http://www.w3.org/XML/Schema}XML Schema (XSD)}} - - * {{{http://www.relaxng.org/}RELAX NG}} - - * {{{http://www.schematron.com/}Schematron}} - - DTDs have limited namespaces support, so they are not suitable for Web services. Relax NG and Schematron are -certainly easier than XSDs. Unfortunately, they are not so widely supported across platforms. We will use XML -Schema. - - By far the easiest way to create a XSD is to infer it from sample documents. Any good XML editor or Java IDE -offers this functionality. Basically, these tools use some sample XML documents, and generate a schema from it -that validates them all. The end result certainly needs to be polished up, but it's a great starting -point. - - Using the sample described above, we end up with the following generated schema: - -+------------------------------------- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+------------------------------------- - - The generated schema can obviously be improved. The first thing to notice is that everything is a root-level -element. This means that the Web service should be able to accept all of these elements as data. This is not desirable: -we only want to accept a <<>>. By removing the wrapping element tags (thus keeping the -types), and inlining the results, we can accomplish this. - -+------------------------------------- - - - - - - - - - - - - - - - - - - - - - - - -+------------------------------------- - - The schema still has one problem: with a schema like this, you can expect the following messages to -validate: - -+------------------------------------- - - - this is not a date - neither is this - - ... - -+------------------------------------- - - Clearly, we must make sure that the start and end date are really dates. XML Schema has an excellent built-in -<<>> type which we can use. We also change the <<>>s to <<>>s. Finally, we change the -<<>> in <<>> to <<>>. This tells the XML parser that the order of <<>> and -<<>> is not significant. Our final XSD looks like this: - -+------------------------------------- - - - - - - - - - - - - - - - - - - - - - - - -+------------------------------------- - - We can store this file with a convenient name such as <<>>. - -The WSDL - - Which leaves the WSDL. Note that in Spring-WS, <>. Based on the XSD and -some conventions, Spring-WS can create the WSDL for you, as explained in the {{{tutorial2.html}next section}} of -this tutorial. The rest of this page will show you how to write your own WSDL, if you choose not to use this -functionality. - - We start our WSDL with the standard preamble, and by importing our existing XSD. To -separate the schema from the definition, we will use a separate namespace for the WSDL definitions: -<<<"http://mycompany.com/hr/definitions">>>. - -+------------------------------------- - - xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" - xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"> - - - - - - -+------------------------------------- - - Next, we define our messages based on the written schema. We only have one message: one with the -<<>> we put in the schema: - -+------------------------------------- - - - - - - - > - - - -+------------------------------------- - - We add the messages to a port type as operations: - -+------------------------------------- - - - - - - - - - - - - - - - -+------------------------------------- - - That finished the abstract part of the WSDL (the interface, as it were), and leaves the concrete part. This -part consists of a <<>>, which tells the client to invoke the operations you've just defined; and a -<<>>, which tells it to invoke it. - - Adding a concrete part is pretty standard: just refer to the abstract part you defined previously, make sure -you use for the <<>> elements (anything else is not interoperable), pick a -<<>> (in this case <<>>, but any URI will do), and determine the -<<>> URL where you want request to come in (in this case <<>>): - -+------------------------------------- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+------------------------------------- - - This is the final WSDL. We will describe how to implement the resulting schema and WSDL in the {{{tutorial2.html}next section}}. \ No newline at end of file diff --git a/src/site/apt/tutorial/tutorial2.apt b/src/site/apt/tutorial/tutorial2.apt deleted file mode 100644 index f9586657..00000000 --- a/src/site/apt/tutorial/tutorial2.apt +++ /dev/null @@ -1,212 +0,0 @@ - ------------------------------------------------------- - Implementing Contract-first Web Services with Spring-WS - ------------------------------------------------------- - - -Introduction - - This is the second part of a tutorial on how to write contract-first Web services. The first part can be found -{{{tutorial1.html}here}}. This second part focusses on implementing the Web service contract using Spring Web Services. - - -Setup - - In this tutorial, we will be using Maven2 to create the initial project structure for us. Doing so is not required, -but greatly reduces the amount of code we have to write to setup our HolidayService. - - The following command creates a Maven2 web application project for us, using the Spring-WS archetype (i.e. project -template): - -+------------------------------------- -> mvn archetype:create -DarchetypeGroupId=org.springframework.ws \ - -DarchetypeArtifactId=spring-ws-archetype \ - -DarchetypeVersion=1.0-rc1-SNAPSHOT \ - -DgroupId=com.mycompany.hr \ - -DartifactId=holidayService -+------------------------------------- - - This command will create a new directory called <<>>. In this project, there is a -<<>> directory, which will contain the root of the WAR file. In this directory, you will find -the standard web application deployment descriptor <<>>, which basically defines a Spring-WS -<<>>, and maps all incoming requests to this servlet: - -+------------------------------------- - - - - MyCompany HR Holiday Service - - - spring-ws - org.springframework.ws.transport.http.MessageDispatcherServlet - - - - spring-ws - /* - - - -+------------------------------------- - - - Next to this file, there is <<>>, which is a Spring application context file that -will contain the Spring-WS bean definitions. - -Implementing the Endpoint - - In Spring-WS, you will implement <> to handle incoming XML messages. There are two flavors of endpoints: -{{{http://static.springframework.org/spring-ws/site/apidocs/org/springframework/ws/server/endpoint/MessageEndpoint.html}<<>>}} and -{{{http://static.springframework.org/spring-ws/site/apidocs/org/springframework/ws/server/endpoint/PayloadEndpoint.html}<<>>}}. -Message endpoint gives access to the entire XML message, including SOAP headers, etc. Typically, however, the -endpoint will only be interested in the <> of the message, i.e. the contents of the SOAP body. In that case, -creating a payload endpoint makes more sense. - -* Handling the XML Message - - In this sample application, we are going to use {{{http://www.jdom.org}JDom}} to handle XML message. We are also -using {{{http://www.w3schools.com/xpath/}XPath}}, because it allows us to select particular parts of the XML JDOM tree, -without requiring strict schema conformance. We extend -our endpoint from -{{{http://static.springframework.org/spring-ws/site/apidocs/org/springframework/ws/server/endpoint/AbstractJDomPayloadEndpoint.html}<<>>}}, -because that will give us a JDOM element to execute the XPath queries on: - -+------------------------------------- -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; - -public class HolidayEndpoint extends AbstractJDomPayloadEndpoint { - - private XPath startDateExpression; - - private XPath endDateExpression; - - private XPath nameExpression; - - private HumanResourceService humanResourceService; - - public HolidayEndpoint(HumanResourceService humanResourceService) { - this.humanResourceService = humanResourceService; - } - - public void init() throws JDOMException { - 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("//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; - } -} -+------------------------------------- - - Let's go over the class one method at a time. The HolidayEndpoint requires the HumanResourceService business service -to operate, so we use the constructor to inject it. Next, we have the initialization method <<>>, which sets up -the XPath expressions using the JDOM API. There are three expressions: <<>> for extracting the -<<<\>>> text value, <<>> for extracting the end date, and <<>> -for extracting the name of the employee. - - The <<>> method is a template method, which gets passed with the <<>> element -from the incoming XML message. Next, we use the XPath expressions to extract the String values from the XML messages, -and convert these values to <<>> using a <<>>. With these values, we invoke a method on the -business service. Typically, this will result in result in a database transaction being started, and some records being -altered in the database. Finally, we return <<>>, which indicates to Spring-WS that we don't want to send a -response message. If we wanted a response message, we could have returned a JDOM Element that represents the payload -of the response message. - - Using JDOM is just one of the options to handle the XML, other options include DOM, dom4j, XOM, SAX, and StAX, but -also marshalling techniques like JAXB, Castor, XMLBeans, JiBX, and XStream. Refer to the airline sample to see how -these are used. - - Here's how we would wire up these classes in our <<>> application context: - -+------------------------------------- - - - - - - - - - - -+------------------------------------- - -* Routing the Message to the Endpoint - - Now that we have written an endpoint that handles the message, we must define how incoming messages are routed to -that endpoint. In Spring-WS, this is the responsibility of an <<>>. In this tutorial, we will route -messages based on their content, by using a <<>>. Here's how we wire it up in -<<>>: - -+------------------------------------- - - - - holidayEndpoint - - - - - - -+------------------------------------- - - This means that whenever a XML message comes in with the namespace <<>> and the -<<>> local name, it will be routed to the holidayEndpoint. It also adds a <<>>, -which dumps incoming and outgoing messages to the log. - -Publishing the WSDL - - Finally, we need to publish the WSDL. As stated on the {{{tutorial1.html}previous page}}, we don't need to write a -WSDL ourselves; Spring-WS can generate one for us based on some conventions. Here's how we define it: - -+------------------------------------- - - - - - - - - - -+------------------------------------- - - The first property we set is the human resource schema we defined on the {{{tutorial1.html}first page}} of this -tutorial, <<>>: we simply placed the schema in the <<>> directory of the application. Next, we define -the WSDL port type to be <<>>. Finally, we set the location where the service can be reached: -<<>>. - - If you deploy the application, and point your browser at -{{{http://localhost:8080/holidayService/holiday.wsdl}<<>>}}, you will -see the generated WSDL. This WSDL is ready to be used by clients, such as {{{http://www.soapui.org/}soapUI}}, or other -SOAP frameworks. - - That concludes this tutorial. The next step would be to look at the echo sample application, that is part of the -distribution. After that, look at the airline sample, which is a bit more complicated, because it uses JAXB, -WS-Security, Hibernate, and a transactional service layer. Finally, refer to the {{{http://static.springframework.org/spring-ws/docs/1.0-m3/reference/html/index.html}reference documentation}}. \ No newline at end of file diff --git a/src/site/apt/why-contract-first.apt b/src/site/apt/why-contract-first.apt deleted file mode 100644 index bf144bf3..00000000 --- a/src/site/apt/why-contract-first.apt +++ /dev/null @@ -1,183 +0,0 @@ - ------------------- - Why Contract-First? - ------------------- - -Why Contract-First? - - When creating Web services, there are two development styles: and . When using a -contract-last approach, you start with the Java code, and let the Web service contract (WSDL, see sidebar) be generated -from that. When using contract-first, you start with the WSDL contract, and use Java to implement said contract. - - Spring-WS only supports the contract-first development style. This page explains why. - -* Object/XML Impedance Mismatch - - Similar to the field of ORM, where we have an -{{{http://en.wikipedia.org/wiki/Object-Relational_impedance_mismatch}Object/Relational impedance mismatch}}, there is a -similar problem when converting Java objects to XML. At first glance, the O/X mapping problem appears simple: create an -XML element for each Java object, converting all Java properties and fields to sub-elements or attributes. However, -things are not so simple as they appear: there is a fundamental difference between hierarchical languages such as XML -(especially XSD) and the graph model of Java. Note that most of the contents in this section was inspired by -{{{http://www.hpl.hp.com/techreports/2005/HPL-2005-83.pdf}Rethinking the Java SOAP Stack}} and -{{{http://safari.awprofessional.com/0321130006}Effective Enterprise Java}}. - -** XSD extensions - - In Java, the only way to change the behavior of a class is to subclass it, adding the new behavior to that subclass. -In XSD, you can extend a data type by restricting it: i.e. constraining the valid values for the elements and -attributes. For instance, consider the following example: - -+-------------------------------------- - - - - - -+-------------------------------------- - - This type restricts a XSD string by ways of a regular expression, allowing only three upper case letters. If this -type is converted to Java, we will end up with an ordinary <<>>; the regular expression is lost in the -conversion process, because Java does not allow for these sorts of extensions. - -** Unportable types - - One of the most important goals of a Web service is to be interoperable: to support multiple platforms such as Java, -.NET, Python, etc. Because all of these languages have different class libraries, you must use some common, interlingual -format to communicate between them. That format is XML, which is supported by all of these languages. - - Because of this conversion, you must make sure that you use portable types in your service implementation. Consider, -for example, a service that returns a <<>>, like so: - -+-------------------------------------- -public Map getFlights() { - // use a tree map, to make sure it's sorted - TreeMap map = new TreeMap(); - map.put("KL1117", "Stockholm"); - ... - return map; -} -+-------------------------------------- - - Undoubtedly, the contents of this map can be converted into some sort of XML, but since there is no way -to describe a map in XML, it will be proprietary. Also, even if it can be converted to XML, many platforms do not have a -data structure similar to the <<>>. So when a .NET client accesses your Web service, it will -probably end up with a <<>>, which has different semantics. - - This problem is also present when working on the client side. Consider the following XSD snippet, which describes a -service contract: - -+-------------------------------------- - - - - - - - - - -+-------------------------------------- - - This contract defines a request that takes an <<>>, which is a XSD datatype representing a year, month, and -day. If we call this service from Java, we will probably use a <<>> or -<<>>. However, both of these classes actually describe times, rather than dates. So, we will -actually send data that represents the fourth of April 2007 at midnight (<<<2007-04-04T00:00:00>>>), which is not -the same as the fourth of April 2007 (<<<2007-04-04>>>). - -** Cyclic graphs - - Imagine we have the following simple class structure: - -+-------------------------------------- -public class Flight { - private String number; - private List passengers; - - // getters and setters omitted -} - -public class Passenger { - private String name; - private Flight flight; - - // getters and setters omitted -} -+-------------------------------------- - - This is a cyclic graph: the <<>> refers to the <<>>, which refers to the <<>> again. -Cyclic graphs like these are quite common in Java. If we took a naive approach to converting this to XML, we will end up -with something like: - -+-------------------------------------- - - - - Arjen Poutsma - - - - Arjen Poutsma - - - - Arjen Poutsma - ... -+-------------------------------------- - - which will take a pretty long time to finish, because there is no stop condition for this loop. - - One way to solve this problem is to use references to objects that were already marshalled, like so: - -+-------------------------------------- - - - - Arjen Poutsma - - - ... - - -+-------------------------------------- - - This solves the recursiveness problem, but introduces new ones. For one, you cannot use an XML validator to validate -this structure. Another issue is that the standard way to use these references in the SOAP (RPC/encoded) has been -deprecated in favor of document/literal. - - These are just a few of the problems when dealing with O/X mapping. It is important to respect these issues when -writing Web services. The best way to respect them is to focus on the XML completely, while using Java as an -implementation language. This is what contract-first is all about. - -* Contract-first versus Contract-last - - Besides the Object/XML Mapping issues mentioned in the previous section, there are other reasons for preferring a -contract-first development style. - -** Fragility - - If you use a contract-last development style, you will have no guarantee that the contract stays constant over time. -Each redeployment of the service can possibly result in a different contract. Additionally, an upgrade of the SOAP stack -used, or a migration to a different SOAP stack can also change said contract. - - In order for a contract to be useful, it must remain constant for as long as possible. If a contract changes, you -will have to contact all of the users of your service, and instruct them to get the new version of the contract. - -** Performance - - When Java is automatically transformed into XML, there is no way to be sure as to what is sent across the wire. -An object might reference another object, which refers to another, etc. In the end, half of your virtual machine -might be converted into XML, which will result in a slow service. - - When using contract-first, you explicitly describe what XML is sent where, thus making sure that it is exactly what -you want. - -** Versioning - - Even though a contract must remain constant for as long as possible, they need to be changed sometimes. -In Java, this typically result in a new Java interface, such as <<>>, and a (new) implementation of -that interface. Of course, the old service must be kept around, because there might be clients who have not migrated -yet. - - If using contract-first, we can have a looser coupling between contract and implementation. Such a looser coupling -allows us to implement both versions of the contract in one class. We could, for instance, use an XSLT to convert any -"old-style" messages to the "new-style" messages. \ No newline at end of file diff --git a/src/site/site.xml b/src/site/site.xml index 140d7287..33c7637f 100644 --- a/src/site/site.xml +++ b/src/site/site.xml @@ -23,9 +23,8 @@ - - +