From 3de06c8636992c68ae05f90d369222a884ec91af Mon Sep 17 00:00:00 2001
From: Arjen Poutsma
Date: Wed, 4 Apr 2007 15:52:02 +0000
Subject: [PATCH] Added Why contract-first? page
---
src/site/apt/why-contract-first.apt | 183 ++++++++++++++++++++++++++++
src/site/fml/faq.fml | 65 +++++++---
src/site/site.xml | 1 +
3 files changed, 229 insertions(+), 20 deletions(-)
create mode 100644 src/site/apt/why-contract-first.apt
diff --git a/src/site/apt/why-contract-first.apt b/src/site/apt/why-contract-first.apt
new file mode 100644
index 00000000..bf144bf3
--- /dev/null
+++ b/src/site/apt/why-contract-first.apt
@@ -0,0 +1,183 @@
+ -------------------
+ 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/fml/faq.fml b/src/site/fml/faq.fml
index 22825f09..3ec4f2fa 100644
--- a/src/site/fml/faq.fml
+++ b/src/site/fml/faq.fml
@@ -36,8 +36,7 @@
/System/Library/Frameworks/JavaVM.framework/Versions/1.5.0/Classes/.compatibility/14compatibility.jar
- .
- You can safely remove or rename it, and the tests will run again.
+ . You can safely remove or rename it, and the tests will run again.
@@ -47,14 +46,23 @@
What is SAAJ?
- SAAJ is the SOAP with Attachments API for Java. Previously, it has been part of JAXM, but it has been
- released as a seperate API as part of the
- Java Web Service
- Developer Pack
-
- , and also as part of J2EE 1.4. SAAJ is generally known as the package
- javax.xml.soap
- .
+
+ SAAJ is the SOAP with Attachments API for Java. Previously, it has been part of JAXM, but it has
+ been
+ released as a seperate API as part of the
+ Java Web Service
+ Developer Pack
+
+ , and also as part of J2EE 1.4. SAAJ is generally known as the package
+ javax.xml.soap
+ .
+
+
+ Spring-WS uses this standard SAAJ library to create representations of SOAP messages. Alternatively,
+ it can use
+ Apache AXIOM
+ .
+
@@ -94,16 +102,17 @@
If you get the following stack trace:
-
-org.springframework.beans.factory.BeanCreationException:
- Error creating bean with name 'org.springframework.ws.soap.saaj.SaajSoapMessageContextFactory'
- defined in ServletContext resource [/WEB-INF/springws-servlet.xml]:
- Invocation of init method failed;
-nested exception is java.lang.NoSuchMethodError:
- javax.xml.soap.MessageFactory.newInstance(Ljava/lang/String;)Ljavax/xml/soap/MessageFactory;
-Caused by:
- java.lang.NoSuchMethodError: javax.xml.soap.MessageFactory.newInstance(Ljava/lang/String;)Ljavax/xml/soap/MessageFactory;
-
+
+ org.springframework.beans.factory.BeanCreationException:
+ Error creating bean with name 'org.springframework.ws.soap.saaj.SaajSoapMessageContextFactory'
+ defined in ServletContext resource [/WEB-INF/springws-servlet.xml]:
+ Invocation of init method failed;
+ nested exception is java.lang.NoSuchMethodError:
+ javax.xml.soap.MessageFactory.newInstance(Ljava/lang/String;)Ljavax/xml/soap/MessageFactory;
+ Caused by:
+ java.lang.NoSuchMethodError:
+ javax.xml.soap.MessageFactory.newInstance(Ljava/lang/String;)Ljavax/xml/soap/MessageFactory;
+
Like most J2EE libraries, SAAJ consists of two parts: the API that consists of interfaces (
saaj-api.jar
@@ -124,6 +133,22 @@ Caused by:
WSDL
+
+ Why does Spring-WS only support contract-first?
+
+
+ You can find the answer to this question on
+ a separate page
+
+ .
+
+
+ Note that Spring-WS only requires you to write the XSD; the WSDL can be generated from that.
+ The tutorial
+ illustrates how.
+
+
+
How do I retrieve the WSDL from a Service? The &WSDL query parameter does not work.
diff --git a/src/site/site.xml b/src/site/site.xml
index d4f5a2fc..e2084400 100644
--- a/src/site/site.xml
+++ b/src/site/site.xml
@@ -28,6 +28,7 @@
+