You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2015/07/04 13:56:27 UTC

[1/2] isis-site git commit: ISIS-1166: enhancements to docs on fake server endpoints

Repository: isis-site
Updated Branches:
  refs/heads/asf-site e3363caa5 -> 0a6fe28fa


ISIS-1166: enhancements to docs on fake server endpoints


Project: http://git-wip-us.apache.org/repos/asf/isis-site/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis-site/commit/575582fb
Tree: http://git-wip-us.apache.org/repos/asf/isis-site/tree/575582fb
Diff: http://git-wip-us.apache.org/repos/asf/isis-site/diff/575582fb

Branch: refs/heads/asf-site
Commit: 575582fbd068c94db9a3ba2a1314e6c82fe3ce2d
Parents: e3363ca
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Sat Jul 4 08:06:21 2015 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Sat Jul 4 08:06:21 2015 +0100

----------------------------------------------------------------------
 content/guides/ug.html | 119 +++++++++++++++++++++++++-------------------
 1 file changed, 69 insertions(+), 50 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis-site/blob/575582fb/content/guides/ug.html
----------------------------------------------------------------------
diff --git a/content/guides/ug.html b/content/guides/ug.html
index 8bb1afe..a9e79fa 100644
--- a/content/guides/ug.html
+++ b/content/guides/ug.html
@@ -14197,7 +14197,7 @@ CustomerRepository customers;</code></pre>
 </div>
 </div>
 <div class="sect3">
-<h4 id="_ug_testing_unit-test-support_soap-fake-server-junit-rule">12.2.3. SOAP Fake Servers</h4>
+<h4 id="_ug_testing_unit-test-support_soap-fake-server-junit-rule">12.2.3. SOAP Fake Endpoints</h4>
 <div class="paragraph">
 <p>No man is an island, and neither are most applications.  Chances are that at some point you may need to integrate your Apache Isis application to other external systems, possibly using old-style SOAP web services.  The SOAP client in this case could be a domain service within your app, or it might be externalized, eg invoked through a scheduler or using <a href="http://camel.apache.org">Apache Camel</a>.</p>
 </div>
@@ -14224,34 +14224,28 @@ CustomerRepository customers;</code></pre>
 <div class="sect4">
 <h5 id="__code_soapendpointpublishingrule_code"><code>SoapEndpointPublishingRule</code></h5>
 <div class="paragraph">
-<p>The idea behing this rule is that you write a fake server that implements the same WSDL contract as the "real" external system does, but which also exposes additional API to specify responses (or throw exceptions) from SOAP calls.  It also typically records the requests and allows these to be queried.</p>
+<p>The idea behind this rule is that you write a fake server endpoint that implements the same WSDL contract as the "real" external system does, but which also exposes additional API to specify responses (or throw exceptions) from SOAP calls.  It also typically records the requests and allows these to be queried.</p>
 </div>
 <div class="paragraph">
-<p>In its setup your unit test instantiates the fake server, and gets the rule to host that fake server on an SOAP endpoint.  It also instantiates the SOAP client, pointing it at the endpoint address (that is, a URL) that the fake server is runnig on.</p>
+<p>In its setup your unit test and gets the rule to instantiate and publish that fake server endpoint, and then obtains a reference to that server endpoint.  It also instantiates the SOAP client, pointing it at the address (that is, a URL) that the fake server endpoint is running on.  This way the unit test has control of both the SOAP client and server: the software under test and its collaborator.</p>
 </div>
 <div class="paragraph">
 <p>In the test methods your unit test sets up expectations on your fake server, and then exercises the SOAP client.  The SOAP client calls the fake server, which then responds accordingly.  The test can then assert that all expected interactions have occurred.</p>
 </div>
 <div class="paragraph">
-<p>So that tests don&#8217;t take too long to run, the rule puts the server onto a thread-local.  Therefore the unit tests should clear up any state on the fake server.</p>
+<p>So that tests don&#8217;t take too long to run, the rule puts the fake server endpoints onto a thread-local.  Therefore the unit tests should clear up any state on the fake server endpoints.</p>
 </div>
 <div class="paragraph">
-<p>The easiest way to use the rule is to subclass it for your particular fake server, eg:</p>
+<p>The easiest way to use the rule is to subclass it, eg:</p>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">ExternalSystemFakeServerRule</span>
-        <span class="directive">extends</span> SoapEndpointPublishingRule&lt;ExternalSystemFakeServer&gt; {  <i class="conum" data-value="1"></i><b>(1)</b>
-    <span class="directive">public</span> ExternalSystemFakeServerRule() {
-        <span class="local-variable">this</span>(<span class="integer">54345</span>);                                                    <i class="conum" data-value="2"></i><b>(2)</b>
-    }
-    <span class="directive">public</span> ExternalSystemFakeServerRule(<span class="directive">final</span> <span class="type">int</span> port) {
+<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">FakeExternalSystemEndpointRule</span> <span class="directive">extends</span> SoapEndpointPublishingRule {
+    <span class="directive">public</span> FakeExternalSystemEndpointRule() {
         <span class="local-variable">super</span>(
-            buildAddress(port),                                         <i class="conum" data-value="3"></i><b>(3)</b>
-            () -&gt; <span class="keyword">new</span> ExternalSystemFakeServer());                      <i class="conum" data-value="4"></i><b>(4)</b>
-    }
-    <span class="directive">protected</span> <span class="directive">static</span> <span class="predefined-type">String</span> buildAddress(<span class="directive">final</span> <span class="type">int</span> port) {
-        <span class="keyword">return</span> <span class="predefined-type">String</span>.format(<span class="string"><span class="delimiter">&quot;</span><span class="content">http://localhost:%d/any/old/string/will/work</span><span class="delimiter">&quot;</span></span>, port);
+            FakeExternalSystemEndpoint.class,                   <i class="conum" data-value="1"></i><b>(1)</b>
+            <span class="string"><span class="delimiter">&quot;</span><span class="content">http://localhost:54345/any/old/string/will/work</span><span class="delimiter">&quot;</span></span>,  <i class="conum" data-value="2"></i><b>(2)</b>
+            );
     }
 }</code></pre>
 </div>
@@ -14260,19 +14254,11 @@ CustomerRepository customers;</code></pre>
 <table>
 <tr>
 <td><i class="conum" data-value="1"></i><b>1</b></td>
-<td>generic type specifies the class that implements the endpoint</td>
+<td>specify the class that implements the endpoint (must have a no-arg constructor)</td>
 </tr>
 <tr>
 <td><i class="conum" data-value="2"></i><b>2</b></td>
-<td>hardcoded port (or could choose one at random from within a range)</td>
-</tr>
-<tr>
-<td><i class="conum" data-value="3"></i><b>3</b></td>
-<td>build an address based on the port</td>
-</tr>
-<tr>
-<td><i class="conum" data-value="4"></i><b>4</b></td>
-<td>provide a <code>Supplier</code> that will instantiate the fake server</td>
+<td>provide an address to host the endpoint.  The port can be hard-coded, as shown, or (probably better) could choose one at random from within a range</td>
 </tr>
 </table>
 </div>
@@ -14281,43 +14267,42 @@ CustomerRepository customers;</code></pre>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">ExternalSystemFakeServerRuleTest</span> {
+<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">FakeExternalSystemEndpointRuleTest</span> {
     <span class="annotation">@Rule</span>
-    <span class="directive">public</span> ExternalSystemFakeServerRule serverRule = <span class="keyword">new</span> ExternalSystemFakeServerRule();
-    <span class="directive">private</span> ExternalSystemFakeServer externalSystemFakeServer;
+    <span class="directive">public</span> FakeExternalSystemEndpointRule serverRule = <span class="keyword">new</span> FakeExternalSystemEndpointRule();
+    <span class="directive">private</span> FakeExternalSystemEndpoint fakeServerEndpoint;
     <span class="directive">private</span> DemoObject externalSystemContract;                                      <i class="conum" data-value="1"></i><b>(1)</b>
     <span class="annotation">@Before</span>
     <span class="directive">public</span> <span class="type">void</span> setUp() <span class="directive">throws</span> <span class="exception">Exception</span> {
-        <span class="directive">final</span> DemoObjectService externalSystemService =                             <i class="conum" data-value="2"></i><b>(2)</b>
-                <span class="keyword">new</span> DemoObjectService(ExternalSystemWsdl.getWsdl());                <i class="conum" data-value="3"></i><b>(3)</b>
+        fakeServerEndpoint =
+            serverRule.getEndpointImplementor(ExternalSystemFakeServer.class);      <i class="conum" data-value="2"></i><b>(2)</b>
+        <span class="directive">final</span> <span class="predefined-type">String</span> endpointAddress =
+            serverRule.getEndpointAddress(ExternalSystemFakeServer.class);          <i class="conum" data-value="3"></i><b>(3)</b>
+        <span class="directive">final</span> DemoObjectService externalSystemService =                             <i class="conum" data-value="4"></i><b>(4)</b>
+                <span class="keyword">new</span> DemoObjectService(ExternalSystemWsdl.getWsdl());                <i class="conum" data-value="5"></i><b>(5)</b>
         externalSystemContract = externalSystemService.getDemoObjectOverSOAP();
         BindingProvider provider = (BindingProvider) externalSystemContract;
         provider.getRequestContext().put(
                 BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
-                serverRule.getEndpointAddress()
+                endpointAddress)
         );
-        externalSystemFakeServer = serverRule.getPublishedEndpoint();               <i class="conum" data-value="4"></i><b>(4)</b>
     }
     <span class="annotation">@Test</span>
     <span class="directive">public</span> <span class="type">void</span> happy_case() <span class="directive">throws</span> <span class="exception">Exception</span> {
         <span class="comment">// given</span>
-        <span class="directive">final</span> Update update = <span class="keyword">new</span> Update();                                         <i class="conum" data-value="5"></i><b>(5)</b>
+        <span class="directive">final</span> Update update = <span class="keyword">new</span> Update();                                         <i class="conum" data-value="6"></i><b>(6)</b>
         ...
-
         <span class="comment">// expect</span>
-        final UpdateResponse response = <span class="keyword">new</span> UpdateResponse();                       <i class="conum" data-value="6"></i><b>(6)</b>
+        final UpdateResponse response = <span class="keyword">new</span> UpdateResponse();                       <i class="conum" data-value="7"></i><b>(7)</b>
         ...
-        externalSystemFakeServer.control().setResponse(updateResponse);
-
+        fakeServerEndpoint.control().setResponse(updateResponse);
         <span class="comment">// when</span>
-        PostResponse response = externalSystemContract.post(update);                <i class="conum" data-value="7"></i><b>(7)</b>
-
+        PostResponse response = externalSystemContract.post(update);                <i class="conum" data-value="8"></i><b>(8)</b>
         <span class="comment">// then</span>
-        <span class="directive">final</span> <span class="predefined-type">List</span>&lt;Update&gt; updates =                                                <i class="conum" data-value="8"></i><b>(8)</b>
-            externalSystemFakeServer.control().getUpdates();
+        <span class="directive">final</span> <span class="predefined-type">List</span>&lt;Update&gt; updates =                                                <i class="conum" data-value="9"></i><b>(9)</b>
+            fakeServerEndpoint.control().getUpdates();
         ...
     }
-    ...
 }</code></pre>
 </div>
 </div>
@@ -14329,34 +14314,68 @@ CustomerRepository customers;</code></pre>
 </tr>
 <tr>
 <td><i class="conum" data-value="2"></i><b>2</b></td>
-<td>also generated by wsdl2java</td>
+<td>get hold of the fake server-side endpoint from the rule&#8230;&#8203;</td>
 </tr>
 <tr>
 <td><i class="conum" data-value="3"></i><b>3</b></td>
-<td><code>getWsdl()</code> is a utility method to return a URL for the WSDL (eg from the classpath)</td>
+<td>&#8230;&#8203; and its endpoint address</td>
 </tr>
 <tr>
 <td><i class="conum" data-value="4"></i><b>4</b></td>
-<td>get hold of the fake server running at the end point</td>
+<td>use factory (also geneated by wsdl2java) to create client-side endpoint</td>
 </tr>
 <tr>
 <td><i class="conum" data-value="5"></i><b>5</b></td>
-<td>create a request (generated from the WSDL and wsdl2java)</td>
+<td><code>getWsdl()</code> is a utility method to return a URL for the WSDL (eg from the classpath)</td>
 </tr>
 <tr>
 <td><i class="conum" data-value="6"></i><b>6</b></td>
-<td>instruct fake server how to respond</td>
+<td>create a request (generated from the WSDL and wsdl2java)</td>
 </tr>
 <tr>
 <td><i class="conum" data-value="7"></i><b>7</b></td>
-<td>invoke the service</td>
+<td>instruct fake server how to respond</td>
 </tr>
 <tr>
 <td><i class="conum" data-value="8"></i><b>8</b></td>
+<td>invoke the service</td>
+</tr>
+<tr>
+<td><i class="conum" data-value="9"></i><b>9</b></td>
 <td>check service was correctly invoked etc.</td>
 </tr>
 </table>
 </div>
+<div class="paragraph">
+<p>For "real-world" usage, see the example app of the (non-ASF) <a href="http://github.com/isisaddons/isis-module-publishmq">Isis addons' publishmq</a> module.</p>
+</div>
+<div class="paragraph">
+<p>Alternatively, the rule can host multiple endpoints.  Each of these will be at a separate address.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">ExternalSystemFakeServerRule</span> <span class="directive">extends</span> SoapEndpointPublishingRule {
+    <span class="directive">public</span> ExternalSystemFakeServerRule() {
+        <span class="local-variable">super</span>(
+            <span class="keyword">new</span> SoapEndpointSpec(FakeCustomersEndpoint.class,
+                                 <span class="string"><span class="delimiter">&quot;</span><span class="content">http://localhost:54346/customers</span><span class="delimiter">&quot;</span></span>),
+            <span class="keyword">new</span> SoapEndpointSpec(FakeOrdersEndpoint.class,
+                                 <span class="string"><span class="delimiter">&quot;</span><span class="content">http://localhost:54347/orders</span><span class="delimiter">&quot;</span></span>),
+            <span class="keyword">new</span> SoapEndpointSpec(FakeProductsEndpoint.class,
+                                 <span class="string"><span class="delimiter">&quot;</span><span class="content">http://localhost:54348/products</span><span class="delimiter">&quot;</span></span>))
+    }
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>To lookup a particular endpoint, specify its type, eg:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="java">FakeProductsEndpoint fakeProductsServerEndpoint =
+            serverRule.getPublishedEndpoint(FakeProductsEndpoint.class);</code></pre>
+</div>
+</div>
 </div>
 <div class="sect4">
 <h5 id="_xml_marshalling_support">XML Marshalling Support</h5>
@@ -18016,7 +18035,7 @@ TODO
 </ul>
 </li>
 <li><a href="#_ug_testing_unit-test-support_jmock-extensions">12.2.2. JMock Extensions</a></li>
-<li><a href="#_ug_testing_unit-test-support_soap-fake-server-junit-rule">12.2.3. SOAP Fake Servers</a>
+<li><a href="#_ug_testing_unit-test-support_soap-fake-server-junit-rule">12.2.3. SOAP Fake Endpoints</a>
 <ul class="sectlevel4">
 <li><a href="#__code_soapendpointpublishingrule_code"><code>SoapEndpointPublishingRule</code></a></li>
 <li><a href="#_xml_marshalling_support">XML Marshalling Support</a></li>


[2/2] isis-site git commit: ISIS-1166: enhancements to docs on fake server endpoints

Posted by da...@apache.org.
ISIS-1166: enhancements to docs on fake server endpoints


Project: http://git-wip-us.apache.org/repos/asf/isis-site/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis-site/commit/0a6fe28f
Tree: http://git-wip-us.apache.org/repos/asf/isis-site/tree/0a6fe28f
Diff: http://git-wip-us.apache.org/repos/asf/isis-site/diff/0a6fe28f

Branch: refs/heads/asf-site
Commit: 0a6fe28fa28584c6638433adea253ba11aeb4324
Parents: 575582f
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Sat Jul 4 12:41:08 2015 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Sat Jul 4 12:41:08 2015 +0100

----------------------------------------------------------------------
 content/guides/ug.html | 99 +++++++++++++++++----------------------------
 1 file changed, 36 insertions(+), 63 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis-site/blob/0a6fe28f/content/guides/ug.html
----------------------------------------------------------------------
diff --git a/content/guides/ug.html b/content/guides/ug.html
index a9e79fa..4f2c422 100644
--- a/content/guides/ug.html
+++ b/content/guides/ug.html
@@ -14236,50 +14236,24 @@ CustomerRepository customers;</code></pre>
 <p>So that tests don&#8217;t take too long to run, the rule puts the fake server endpoints onto a thread-local.  Therefore the unit tests should clear up any state on the fake server endpoints.</p>
 </div>
 <div class="paragraph">
-<p>The easiest way to use the rule is to subclass it, eg:</p>
-</div>
-<div class="listingblock">
-<div class="content">
-<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">FakeExternalSystemEndpointRule</span> <span class="directive">extends</span> SoapEndpointPublishingRule {
-    <span class="directive">public</span> FakeExternalSystemEndpointRule() {
-        <span class="local-variable">super</span>(
-            FakeExternalSystemEndpoint.class,                   <i class="conum" data-value="1"></i><b>(1)</b>
-            <span class="string"><span class="delimiter">&quot;</span><span class="content">http://localhost:54345/any/old/string/will/work</span><span class="delimiter">&quot;</span></span>,  <i class="conum" data-value="2"></i><b>(2)</b>
-            );
-    }
-}</code></pre>
-</div>
-</div>
-<div class="colist arabic">
-<table>
-<tr>
-<td><i class="conum" data-value="1"></i><b>1</b></td>
-<td>specify the class that implements the endpoint (must have a no-arg constructor)</td>
-</tr>
-<tr>
-<td><i class="conum" data-value="2"></i><b>2</b></td>
-<td>provide an address to host the endpoint.  The port can be hard-coded, as shown, or (probably better) could choose one at random from within a range</td>
-</tr>
-</table>
-</div>
-<div class="paragraph">
-<p>Your unit test should then look something like:</p>
+<p>Your unit test uses the rule by specifying the endpoint class (must have a no-arg constructor):</p>
 </div>
 <div class="listingblock">
 <div class="content">
 <pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">FakeExternalSystemEndpointRuleTest</span> {
     <span class="annotation">@Rule</span>
-    <span class="directive">public</span> FakeExternalSystemEndpointRule serverRule = <span class="keyword">new</span> FakeExternalSystemEndpointRule();
+    <span class="directive">public</span> SoapEndpointPublishingRule serverRule =
+        <span class="keyword">new</span> SoapEndpointPublishingRule(FakeExternalSystemEndpoint.class);         <i class="conum" data-value="1"></i><b>(1)</b>
     <span class="directive">private</span> FakeExternalSystemEndpoint fakeServerEndpoint;
-    <span class="directive">private</span> DemoObject externalSystemContract;                                      <i class="conum" data-value="1"></i><b>(1)</b>
+    <span class="directive">private</span> DemoObject externalSystemContract;                                    <i class="conum" data-value="2"></i><b>(2)</b>
     <span class="annotation">@Before</span>
     <span class="directive">public</span> <span class="type">void</span> setUp() <span class="directive">throws</span> <span class="exception">Exception</span> {
         fakeServerEndpoint =
-            serverRule.getEndpointImplementor(ExternalSystemFakeServer.class);      <i class="conum" data-value="2"></i><b>(2)</b>
+            serverRule.getEndpointImplementor(FakeExternalSystemEndpoint.class);  <i class="conum" data-value="3"></i><b>(3)</b>
         <span class="directive">final</span> <span class="predefined-type">String</span> endpointAddress =
-            serverRule.getEndpointAddress(ExternalSystemFakeServer.class);          <i class="conum" data-value="3"></i><b>(3)</b>
-        <span class="directive">final</span> DemoObjectService externalSystemService =                             <i class="conum" data-value="4"></i><b>(4)</b>
-                <span class="keyword">new</span> DemoObjectService(ExternalSystemWsdl.getWsdl());                <i class="conum" data-value="5"></i><b>(5)</b>
+            serverRule.getEndpointAddress(FakeExternalSystemEndpoint.class);      <i class="conum" data-value="4"></i><b>(4)</b>
+        <span class="directive">final</span> DemoObjectService externalSystemService =                           <i class="conum" data-value="5"></i><b>(5)</b>
+                <span class="keyword">new</span> DemoObjectService(ExternalSystemWsdl.getWsdl());              <i class="conum" data-value="6"></i><b>(6)</b>
         externalSystemContract = externalSystemService.getDemoObjectOverSOAP();
         BindingProvider provider = (BindingProvider) externalSystemContract;
         provider.getRequestContext().put(
@@ -14290,16 +14264,16 @@ CustomerRepository customers;</code></pre>
     <span class="annotation">@Test</span>
     <span class="directive">public</span> <span class="type">void</span> happy_case() <span class="directive">throws</span> <span class="exception">Exception</span> {
         <span class="comment">// given</span>
-        <span class="directive">final</span> Update update = <span class="keyword">new</span> Update();                                         <i class="conum" data-value="6"></i><b>(6)</b>
+        <span class="directive">final</span> Update update = <span class="keyword">new</span> Update();                              <i class="conum" data-value="7"></i><b>(7)</b>
         ...
         <span class="comment">// expect</span>
-        final UpdateResponse response = <span class="keyword">new</span> UpdateResponse();                       <i class="conum" data-value="7"></i><b>(7)</b>
+        final UpdateResponse response = <span class="keyword">new</span> UpdateResponse();            <i class="conum" data-value="8"></i><b>(8)</b>
         ...
         fakeServerEndpoint.control().setResponse(updateResponse);
         <span class="comment">// when</span>
-        PostResponse response = externalSystemContract.post(update);                <i class="conum" data-value="8"></i><b>(8)</b>
+        PostResponse response = externalSystemContract.post(update);     <i class="conum" data-value="9"></i><b>(9)</b>
         <span class="comment">// then</span>
-        <span class="directive">final</span> <span class="predefined-type">List</span>&lt;Update&gt; updates =                                                <i class="conum" data-value="9"></i><b>(9)</b>
+        <span class="directive">final</span> <span class="predefined-type">List</span>&lt;Update&gt; updates =                                     <i class="conum" data-value="10"></i><b>(10)</b>
             fakeServerEndpoint.control().getUpdates();
         ...
     }
@@ -14310,65 +14284,61 @@ CustomerRepository customers;</code></pre>
 <table>
 <tr>
 <td><i class="conum" data-value="1"></i><b>1</b></td>
-<td>the SOAP contract as defined in WSDL and generated by wsdl2java</td>
+<td>specify the class that implements the endpoint (must have a no-arg constructor)</td>
 </tr>
 <tr>
 <td><i class="conum" data-value="2"></i><b>2</b></td>
-<td>get hold of the fake server-side endpoint from the rule&#8230;&#8203;</td>
+<td>the SOAP contract as defined in WSDL and generated by wsdl2java</td>
 </tr>
 <tr>
 <td><i class="conum" data-value="3"></i><b>3</b></td>
-<td>&#8230;&#8203; and its endpoint address</td>
+<td>get hold of the fake server-side endpoint from the rule&#8230;&#8203;</td>
 </tr>
 <tr>
 <td><i class="conum" data-value="4"></i><b>4</b></td>
-<td>use factory (also geneated by wsdl2java) to create client-side endpoint</td>
+<td>&#8230;&#8203; and its endpoint address</td>
 </tr>
 <tr>
 <td><i class="conum" data-value="5"></i><b>5</b></td>
-<td><code>getWsdl()</code> is a utility method to return a URL for the WSDL (eg from the classpath)</td>
+<td>use factory (also generated by wsdl2java) to create client-side endpoint</td>
 </tr>
 <tr>
 <td><i class="conum" data-value="6"></i><b>6</b></td>
-<td>create a request (generated from the WSDL and wsdl2java)</td>
+<td><code>getWsdl()</code> is a utility method to return a URL for the WSDL (eg from the classpath)</td>
 </tr>
 <tr>
 <td><i class="conum" data-value="7"></i><b>7</b></td>
-<td>instruct fake server how to respond</td>
+<td>create a request object in order to invoke the SOAP web service</td>
 </tr>
 <tr>
 <td><i class="conum" data-value="8"></i><b>8</b></td>
-<td>invoke the service</td>
+<td>instruct the fake server endpoint how to respond</td>
 </tr>
 <tr>
 <td><i class="conum" data-value="9"></i><b>9</b></td>
-<td>check service was correctly invoked etc.</td>
+<td>invoke the web service</td>
+</tr>
+<tr>
+<td><i class="conum" data-value="10"></i><b>10</b></td>
+<td>check the fake server endpoint was correctly invoked etc.</td>
 </tr>
 </table>
 </div>
 <div class="paragraph">
-<p>For "real-world" usage, see the example app of the (non-ASF) <a href="http://github.com/isisaddons/isis-module-publishmq">Isis addons' publishmq</a> module.</p>
-</div>
-<div class="paragraph">
-<p>Alternatively, the rule can host multiple endpoints.  Each of these will be at a separate address.</p>
+<p>The rule can also host multiple endpoints; just provide multiple classes in the constructor:</p>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">ExternalSystemFakeServerRule</span> <span class="directive">extends</span> SoapEndpointPublishingRule {
-    <span class="directive">public</span> ExternalSystemFakeServerRule() {
-        <span class="local-variable">super</span>(
-            <span class="keyword">new</span> SoapEndpointSpec(FakeCustomersEndpoint.class,
-                                 <span class="string"><span class="delimiter">&quot;</span><span class="content">http://localhost:54346/customers</span><span class="delimiter">&quot;</span></span>),
-            <span class="keyword">new</span> SoapEndpointSpec(FakeOrdersEndpoint.class,
-                                 <span class="string"><span class="delimiter">&quot;</span><span class="content">http://localhost:54347/orders</span><span class="delimiter">&quot;</span></span>),
-            <span class="keyword">new</span> SoapEndpointSpec(FakeProductsEndpoint.class,
-                                 <span class="string"><span class="delimiter">&quot;</span><span class="content">http://localhost:54348/products</span><span class="delimiter">&quot;</span></span>))
-    }
-}</code></pre>
+<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@Rule</span>
+<span class="directive">public</span> SoapEndpointPublishingRule serverRule =
+                <span class="keyword">new</span> SoapEndpointPublishingRule(
+                    FakeCustomersEndpoint.class,
+                    FakeOrdersEndpoint.class,
+                    FakeProductsEndpoint.class);</code></pre>
 </div>
 </div>
 <div class="paragraph">
-<p>To lookup a particular endpoint, specify its type, eg:</p>
+<p>To lookup a particular endpoint, specify its type:</p>
 </div>
 <div class="listingblock">
 <div class="content">
@@ -14376,6 +14346,9 @@ CustomerRepository customers;</code></pre>
             serverRule.getPublishedEndpoint(FakeProductsEndpoint.class);</code></pre>
 </div>
 </div>
+<div class="paragraph">
+<p>The endpoint addresses that the server endpoints run on are determined automatically.  If you want more control, then you can call one of <code>SoapEndpointPublishingRule</code>'s overloaded constructors, passing in one or more <code>SoapEndpointSpec</code> instances.</p>
+</div>
 </div>
 <div class="sect4">
 <h5 id="_xml_marshalling_support">XML Marshalling Support</h5>