<?xml version="1.0" encoding="utf-8"?>
<feed version="0.3" xmlns="http://purl.org/atom/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="en">
<title>Ryan Heaton&apos;s Blog</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/stoicflame/" />
<modified>2008-05-16T17:50:19Z</modified>
<tagline></tagline>
<id>tag:weblogs.java.net,2008:/blog/stoicflame/400</id>
<generator url="http://www.movabletype.org/" version="3.01D">Movable Type</generator>
<copyright>Copyright (c) 2008, stoicflame</copyright>
<entry>
<title>OAuth is Handy</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/stoicflame/archive/2008/05/oauth.html" />
<modified>2008-05-16T17:50:19Z</modified>
<issued>2008-05-16T17:50:00Z</issued>
<id>tag:weblogs.java.net,2008:/blog/stoicflame/400.9815</id>
<created>2008-05-16T17:50:00Z</created>
<summary type="text/plain">OAuth for Spring Security was just released this week, and I thought I&apos;d take a stab at why you might be interested.</summary>
<author>
<name>stoicflame</name>

<email>ryan@webcohesion.com</email>
</author>

<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/stoicflame/">
<![CDATA[  <p><a href="http://spring-security-oauth.codehaus.org">OAuth for Spring Security</a> was released this week, and I thought
  I'd take a stab at why you might be interested.</p>

  <p><u><b>What is OAuth?</b></u></p>

  <p>I like to explain <a href="http://oauth.net">OAuth</a> by describing the problem it is trying to solve. So here goes.</p>

  <p>Let's say you're <a href="http://www.linkedin.com/">a sizeable social networking site</a> and you'd like to offer a feature to your users to allow them
  to <a href="http://www.linkedin.com/findContacts">search their webmail contacts</a> for import into their social network. The problem is, you (the "consumer")
  need access to a resource that is protected by a another site (a.k.a. "service provider"). How do you go about doing that?</p>

  <p>Option 1: Just ask the user for his/her credentials and <a href="http://www.linkedin.com/static?key=privacy_policy&trk=hb_ft_priv">promise that you won't store
  them or do anything bad with them</a>. Well, it works, I suppose, but this isn't a great general-purpose practice for online applications. And it's not hard
  to see why.  Sure, <i>you</i> might be trustworthy, but there are plenty of other sites who are not. And what about the service provider? How would <i>you</i>
  feel about your users giving out their credentials to other sites that want access to the resources you protect?</p>

  <p>Option 2: Use OAuth. OAuth is a protocol that was defined to address this problem.  Continuing the above example, let's say that you've established a trust
  with the webmail service providers.  You share a "secret" (which in practical terms is a passphrase or a public key or something) that you can use to gain
  access to the webmail contacts&mdash;provided, of course, that the user approves it.  In order to gain this approval, all you have to do is redirect the user
  to the login page of the webmail service provider and have the user tell the service provider that it's okay that you access his/her contacts.</p>

  <p>OAuth is a protocol standard that can be used to enable this mechanism.</p>

  <p><u><b>How do I try it out?</b></u></p>

  <p><a href="http://spring-security-oauth.codehaus.org">OAuth for Spring Security</a> has a <a href="http://spring-security-oauth.codehaus.org/tutorial.html">really
    nice tutorial</a> that walks you through setting up both a service provider and a consumer on your local box.  Once those are set up, you can see OAuth in
    action by walking through the user flow.</p>

  <p><u><b>How do learn more?</b></u></p>

  <ul>
    <li><a href="http://oauth.net">OAuth</a></li>
    <li><a href="http://oauth.net/core/1.0/">Spec</a></li>
    <li><a href="http://oauth.net/documentation/faq">FAQ</a></li>
    <li><a href="http://oauth.net/documentation/getting-started">Getting Started</a></li>
    <li><a href="http://www.hueniverse.com/hueniverse/2007/10/beginners-gui-1.html">Illustration</a> (Eran Hammer-Lahav)</li>
    <li><a href="http://www.slideshare.net/leahculver/oauth-open-api-authentication">Presentation</a> (Leah Culver)</li>
  </ul>]]>

</content>
</entry>
<entry>
<title>Enunciate 1.7: Security and Custom Content Types</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/stoicflame/archive/2008/05/enunciate_17_se.html" />
<modified>2008-05-06T23:22:28Z</modified>
<issued>2008-05-06T23:22:22Z</issued>
<id>tag:weblogs.java.net,2008:/blog/stoicflame/400.9713</id>
<created>2008-05-06T23:22:22Z</created>
<summary type="text/plain">Enunciate 1.7 includes support for securing your Web service endpoints via Spring Security; support for OAuth is an added bonus.  Also, support for custom content types (in addition to XML and JSON) for your REST endpoints.</summary>
<author>
<name>stoicflame</name>

<email>ryan@webcohesion.com</email>
</author>

<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/stoicflame/">
<![CDATA[<h2>Enunciate 1.7 has been released!</h2>

<p>The primary feature of Enunciate 1.7 is support for securing your Web service endpoints using <a href="http://static.springframework.org/spring-security/site/">Spring Security</a>.  There is additional support for <a href="http://oauth.net">OAuth</a>, with OpenID and WS-Security planned for 1.8.</p>

<p>In addition, Enunciate 1.7 introduces the concept of custom REST content types, which you can use to support custom serialization formats for REST responses (beyond the default XML and JSON endpoints).</p>

<p>Enjoy!</p>

<p><a href="http://enunciate.codehaus.org">http://enunciate.codehaus.org</a></p>]]>

</content>
</entry>
<entry>
<title>Web Service Programming for the Masses, Part II: Developing the RIA</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/stoicflame/archive/2008/01/web_service_pro.html" />
<modified>2008-01-09T19:41:31Z</modified>
<issued>2008-01-09T19:41:10Z</issued>
<id>tag:weblogs.java.net,2008:/blog/stoicflame/400.8928</id>
<created>2008-01-09T19:41:10Z</created>
<summary type="text/plain">This is the second of a two-part tutorial that will walk you through the development of a Rich Internet Application that will consume the Web service API we developed in Part I. We&apos;ll be writing an AJAX app with an embedded Flash component. Bring your favorite IDE and join the fun!</summary>
<author>
<name>stoicflame</name>

<email>ryan@webcohesion.com</email>
</author>

<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/stoicflame/">
<![CDATA[<p><a href="http://weblogs.java.net/blog/stoicflame/archive/2008/01/web_service_pro_1.html">The first part of this tutorial</a> walked through the development of a Web service API that exposes its endpoints via SOAP, REST/XML, JSON, GWT-RPC, and AMF.  In this second part of the tutorial, we intend to prove out this API.  We will walk through building a rich AJAX application with an embedded Flash component. The AJAX application will use
  <a href="http://code.google.com/webtoolkit/documentation/com.google.gwt.doc.DeveloperGuide.RemoteProcedureCalls.html">GWT-RPC</a> to access the API while the Flash movie will use
  <a href="http://en.wikipedia.org/wiki/Action_Message_Format">AMF</a>.</p>

<p>For those of you who would like to see the example code on your local filesystem, you can check it out of SVN at <a href="http://svn.codehaus.org/enunciate/trunk/enunciate/src/samples/addressbook/">http://svn.codehaus.org/enunciate/trunk/enunciate/src/samples/addressbook/</a>.</p>

<h2>Step 1: Set up the GWT application.</h2>

<p>We first have to create our GWT application. We will use the name “net.java.apps.addressbook.AddressBookApp” to identify our application to Enunciate and
  GWT.</p>

<p>Before we continue, we have to add a project dependency on the main GWT client-side library. The added dependency declaration will go in the “dependencies”
  section of our pom.xml file:</p>

<pre><code>
&lt;dependency&gt;
  &lt;groupId&gt;com.google.gwt&lt;/groupId&gt;
  &lt;artifactId&gt;gwt-user&lt;/artifactId&gt;
  &lt;version&gt;1.4.60&lt;/version&gt;
&lt;/dependency&gt;
</code></pre>

<p>Then, we create our main GWT application structure. For more information, see the <a href="http://code.google.com/webtoolkit/">GWT documentation</a>:</p>

<code><u>addressbook/src/main/gwt/net/java/apps/addressbook/AddressBookApp.gwt.xml:</u></code>

<pre><code>
&lt;module&gt;

  &lt;!--inherit from the main GWT client-side library.--&gt;
  &lt;inherits name='com.google.gwt.user.User'/&gt;

  &lt;!--inherit from our Enunciate-generated GWT-RPC client-side code.--&gt;
  &lt;inherits name='net.java.ws.addressbook.AddressBookGWT'/&gt;

  &lt;!--define the entry point for the address book app.--&gt;
  &lt;entry-point class='net.java.apps.addressbook.client.AddressBookApp'/&gt;

&lt;/module&gt;
</code></pre>

<code><u>addressbook/src/main/gwt/net/java/apps/addressbook/public/addressbook.html:</u></code>

<pre><code>
&lt;html&gt;
&lt;head&gt;
  &lt;title&gt;AddressBook Application&lt;/title&gt;
  &lt;meta name='gwt:module' content='net.java.apps.addressbook.AddressBookApp'&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;script language="javascript" src="gwt.js"&gt;&lt;/script&gt;
  &lt;iframe id="__gwt_historyFrame" style="width:0;height:0;border:0"&gt;&lt;/iframe&gt;
  &lt;h1&gt;AddressBook Application&lt;/h1&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>

<code><u>addressbook/src/main/gwt/net/java/apps/addressbook/client/AddressBookApp.java:</u></code>

<pre><code>
package net.java.apps.addressbook.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.*;

/**
 * Basic entry point for the GWT address book application.
 *
 * @author Ryan Heaton
 */
public class AddressBookApp implements EntryPoint {
  public void onModuleLoad() {
  }
}
</code></pre>

<p>Finally, we edit the Enunciate configuration file to point to our application so it will be compiled during the normal compile process.</p>

<code><u>addressbook/enunciate.xml:</u></code>

<pre><code>
&lt;enunciate&gt;
  &lt;modules&gt;
    &lt;gwt disabled="false" gwtHome="/path/to/gwt/home" rpcModuleName="net.java.ws.addressbook.AddressBookGWT"&gt;
      &lt;app srcDir="src/main/gwt"&gt;
        &lt;module name="net.java.apps.addressbook.AddressBookApp"/&gt;
      &lt;/app&gt;
    &lt;/gwt&gt;
    &lt;amf disabled="false" flexHome="/path/to/flex/sdk/home"/&gt;
  &lt;/modules&gt;
&lt;/enunciate&gt;
</code></pre>

<h2>Step 2: Set up the Flex Application</h2>

<p>Having created the skeleton for our AJAX application using GWT, we can now set up the skeleton for developing our Flex application. This takes only a single
  <a href="http://en.wikipedia.org/wiki/MXML">MXML file</a> and editing the Enunciate configuration file to point to our Flex source directory. For more information, see Adobe's documentation on developing a
  Flex application.</p>

<code><u>addressbook/src/main/flex/net/java/apps/addressbook/bytype.mxml:</u></code>

<pre><code>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" backgroundColor="#FFFFFF"&gt;
&lt;/mx:Application&gt;
</code></pre>

<code><u>addressbook/enunciate.xml:</u></code>

<pre><code>
&lt;enunciate&gt;
  &lt;modules&gt;
    &lt;gwt disabled="false" gwtHome="/path/to/gwt/home" rpcModuleName="net.java.ws.addressbook.AddressBookGWT"&gt;
      &lt;app srcDir="src/main/gwt"&gt;
        &lt;module name="net.java.apps.addressbook.AddressBookApp"/&gt;
      &lt;/app&gt;
    &lt;/gwt&gt;
    &lt;amf disabled="false" flexHome="/path/to/flex/sdk/home"&gt;
      &lt;app srcDir="src/main/flex" name="bytype" mainMxmlFile="src/main/flex/net/java/apps/addressbook/bytype.mxml"/&gt;
    &lt;/amf&gt;
  &lt;/modules&gt;
&lt;/enunciate&gt;
</code></pre>

<p>*At this point, it might be convenient to rebuild our project file using Maven. The new project will contain references to the new generated code and to our
  GWT application.</p>

<h2>Step 3: Write the Flex Application</h2>

<p>We can now write our Flash component that will lookup contacts by type. Our application has only three components: a <a
  href="http://livedocs.adobe.com/flex/201/langref/mx/controls/DataGrid.html">DataGrid</a> to display the information, a
  <a href="http://livedocs.adobe.com/flex/201/langref/mx/controls/ComboBox.html">ComboBox</a> used to select the contact type, and a <a href="http://livedocs.adobe.com/flex/201/langref/mx/controls/Button.html">Button</a> that will invoke the find and populate the DataGrid with the data. The
  <code>Script</code> tag is where we put our
  logic to invoke the AMF Web service method:</p>

<code><u>addressbook/src/main/flex/net/java/apps/addressbook/bytype.mxml:</u></code>

<pre><code>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" backgroundColor="#FFFFFF" creationComplete="initApp()"&gt;
  &lt;mx:Script&gt;&lt;![CDATA[
     import mx.controls.Alert;
     import mx.rpc.events.FaultEvent;
     import mx.rpc.events.ResultEvent;
     import mx.rpc.remoting.RemoteObject;
     import net.java.ws.addressbook.services.AddressBook;
     import net.java.ws.addressbook.services.AddressBook.FindContactsByTypeResultEvent;
     import net.java.ws.addressbook.domain.ContactType;
     import net.java.ws.addressbook.domain.ContactList;
     import net.java.ws.addressbook.domain.Contact;

     //instantiate our address book service.
     var book:AddressBook = new AddressBook();

     //array of contact types; used to popluate the combo box.
     [Bindable]
     public var contactTypes: Array = [ ContactType.friend, ContactType.family, ContactType.professional ];

     private function initApp():void {
       //initialize our address book with our event listeners.
        book.addEventListener("fault", myFaultHandler);
        book.addEventListener("findContactsByType", myEventHandler);
     }

     private function myFaultHandler(event:FaultEvent):void {
       //if a fault occurs, display a fault message.
       Alert.show(event.fault.message);
     }

     private function myEventHandler(event:FindContactsByTypeResultEvent):void {
       //the event listener is a strongly-typed listener for the findContactsByType method.
       dg.dataProvider = event.result.contacts;
     }

  ]]&gt;&lt;/mx:Script&gt;

  &lt;mx:DataGrid id="dg" width="100%" height="100%"/&gt;

  &lt;mx:ComboBox id="ct" dataProvider="{contactTypes}"/&gt;

  &lt;mx:Button label="Find By Type" click="book.findContactsByType(ct.selectedItem as String)"/&gt;

&lt;/mx:Application&gt;
</code></pre>

<p>You'll notice that the remote interface that we're working with in our Flex application is strongly typed (inasmuch as Flex allows it). This is because
  Enunciate generates the client-side ActionScript classes that are used to access the AMF endpoints (these can be found in
  <code>addressbook/target/enunciate-generate/amf/client</code>). This is a big advantage over using an ActionScript <a
  href="http://livedocs.adobe.com/flex/201/langref/mx/rpc/remoting/mxml/RemoteObject.html">RemoteObject</a> directly since you get compile-time type
  safety.</p>

<h2>Step 4: Write the GWT Application</h2>

<p>Our GWT Application will be a tab-based UI, with two tabs. The first tab will be a lookup of contacts by name via suggestion box. The second tab will display
  our Flash component that looks up contacts by type. Because we are using GWT, we have the advantage of writing the AJAX UI in Java. We'll let Enunciate handle
  the process of invoking GWT to compile our Java source code into JavaScript. Since this isn't a tutorial on GWT, we'll let the code do the talking.</p>

<code><u>addressbook/src/main/gwt/net/java/apps/addressbook/client/AddressBookApp.java:</u></code>

<pre><code>
package net.java.apps.addressbook.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.*;
import net.java.ws.addressbook.client.services.AddressBook;
import net.java.ws.addressbook.client.domain.ContactList;
import net.java.ws.addressbook.client.domain.Contact;

import java.util.Iterator;
import java.util.Collection;
import java.util.ArrayList;

/**
 * Basic entry point for the GWT address book application.
 *
 * @author Ryan Heaton
 */
public class AddressBookApp implements EntryPoint {
  public void onModuleLoad() {
    //the panel that will hold the widgets that will look up by name.
    VerticalPanel byNamePanel = new VerticalPanel();

    //the Enunciate-generated client-side GWT address book service
    final AddressBook book = new AddressBook();

    //the grid we will use to display the contacts that are found.
    final Grid contactGrid = new Grid();

    //the oracle that will make a remote call to populate the suggest box.
    SuggestOracle oracle = new SuggestOracle() {
      public void requestSuggestions(final Request request, final Callback callback) {
        String query = request.getQuery();

        //call the method to find contacts by name.
        book.findContactsByName(query, new AddressBook.FindContactsByNameResponseCallback() {
          public void onResponse(ContactList response) {
            Iterator contactIt = response.getContacts().iterator();
            Collection suggestions = new ArrayList();
            while (contactIt.hasNext()) {
              final Contact contact = (Contact) contactIt.next();

              //add the suggestion.
              suggestions.add(new Suggestion() {
                public String getDisplayString() {
                  return contact.getName();
                }

                public String getReplacementString() {
                  return contact.getName();
                }
              });
            }

            contactGrid.clear(); //clear the grid.
            callback.onSuggestionsReady(request, new Response(suggestions));
          }

          public void onError(Throwable throwable) {
            //do nothing if an error occurs while asking for suggestions
          }
        });
      }
    };

    //the suggest box (instantiated with our oracle).
    final SuggestBox suggestBox = new SuggestBox(oracle);

    //The panel that will hold the suggest box and the "find" button.
    HorizontalPanel findForm = new HorizontalPanel();
    findForm.add(suggestBox);

    //the "find" button.
    Button findButton = new Button("find");
    findButton.addClickListener(new ClickListener() {
      public void onClick(Widget widget) {
        //when "find" is clicked, make the query and populate the grid.
        String text = suggestBox.getText();
        book.findContactsByName(text, new AddressBook.FindContactsByNameResponseCallback() {
          public void onResponse(ContactList response) {
            contactGrid.resize(6 * response.getContacts().size(), 2);
            Iterator contactIt = response.getContacts().iterator();
            int i = 0;
            while (contactIt.hasNext()) {
              Contact contact = (Contact) contactIt.next();
              contactGrid.setWidget(++i, 0, new Label("Name:"));
              contactGrid.setWidget(i, 1, new Label(contact.getName()));
              contactGrid.setWidget(++i, 0, new Label("Phone:"));
              contactGrid.setWidget(i, 1, new Label(contact.getPhone()));
              contactGrid.setWidget(++i, 0, new Label("Address:"));
              contactGrid.setWidget(i, 1, new Label(contact.getAddress1()));
              contactGrid.setWidget(++i, 0, new Label("City:"));
              contactGrid.setWidget(i, 1, new Label(contact.getCity()));
              contactGrid.setWidget(++i, 0, new Label("Type:"));
              contactGrid.setWidget(i, 1, new Label(contact.getContactType()));
              contactGrid.setWidget(++i, 0, new HTML("&lt;hr/&gt;"));
              contactGrid.setWidget(i, 1, new HTML("&lt;hr/&gt;"));
            }
          }

          public void onError(Throwable throwable) {
            //if an error while doing a "find," display it in the grid.
            contactGrid.resize(1, 1);
            contactGrid.setWidget(0, 0, new Label("ERROR: " + throwable.getMessage()));
          }
        });
      }
    });

    //add the find button.
    findForm.add(findButton);

    //add the find form to the panel.
    byNamePanel.add(findForm);

    //add the display grid to the panel.
    byNamePanel.add(contactGrid);

    //create the tab panel.
    TabPanel panel = new TabPanel();

    //add the find by name panel to the tab panel.
    panel.add(byNamePanel, "&amp;nbsp;&lt;a href=\"#byname\"&gt;by name&lt;/a&gt;&amp;nbsp;", true);

    //create some HTML that will embed our flash component.
    HTML flashHTML = new HTML("&lt;object width=\"550\" height=\"400\"&gt;\n" +
              "&lt;param name=\"movie\" value=\"bytype.swf\"&gt;\n" +
              "&lt;embed src=\"bytype.swf\" width=\"550\" height=\"400\"&gt;\n" +
              "&lt;/embed&gt;\n" +
              "&lt;/object&gt;");

    //add the flash component to the other tab in the tab panel.
    panel.add(flashHTML, "&amp;nbsp;&lt;a href=\"#bytype\"&gt;by type&lt;/a&gt;&amp;nbsp;", true);

    //add the tab panel to the root HTML.
    RootPanel.get().add(panel);
  }
}
</code></pre>

<p>You'll notice that Enunciate has also generated client-side code for accessing our Web service API via GWT. Again, this adds significant benefits in terms of
  type safety and simplifies the creation of the initial environment.</p>

<h2>Step 5: Build, Package, and Run the Application</h2>

<p>Once again, we run</p>

<code>mvn jetty:run-war</code>

<p>Assuming everything builds correctly, we can navigate to
  <a href="http://localhost:8080/addressbook/addressbook.html">http://localhost:8080/addressbook/addressbook.html</a> and see our Rich AJAX Application with an
  embedded Flash component, both of which make dynamic calls to our Web service API.</p>]]>

</content>
</entry>
<entry>
<title>Web Service Programming for the Masses, Part I: Developing the Web Service API</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/stoicflame/archive/2008/01/web_service_pro_1.html" />
<modified>2008-01-09T19:33:46Z</modified>
<issued>2008-01-09T19:33:29Z</issued>
<id>tag:weblogs.java.net,2008:/blog/stoicflame/400.8915</id>
<created>2008-01-09T19:33:29Z</created>
<summary type="text/plain">This is the first of a two-part tutorial that will walk you through the development of a Web service API that bundles a bouquet of remoting technologies: SOAP, REST/XML, JSON, GWT-RPC and even AMF (for all you Flex developers). Bring your favorite IDE and join the fun!</summary>
<author>
<name>stoicflame</name>

<email>ryan@webcohesion.com</email>
</author>
<dc:subject>Web Services and XML</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/stoicflame/">
<![CDATA[<p>So you've got a web application that needs to expose a Web service API. Maybe you're going to be writing a <a
  href="http://en.wikipedia.org/wiki/Rich_Internet_application">Rich Internet Application</a> (RIA) using <a
  href="http://en.wikipedia.org/wiki/Adobe_Flex">Flex</a> or some
  <a href="http://en.wikipedia.org/wiki/Ajax_framework">AJAX Framework</a>. Or maybe you'll be developing a desktop application that needs to interface with your online data. Or perhaps you've got a few business
  partners that want to integrate with your application.</p>

<p>Whatever the reason, you need a solution that not only fits your client-side requirements, but one that is also easy to develop, easy to debug, easy to
  maintain, and easy to enhance. Don't be too hasty with your choice of a Web service implementation technology. <a
  href="http://weblogs.java.net/blog/stoicflame/archive/2007/10/why_roi_vs_soi_1.html">REST is not always the best answer.</a> It might
  be, but not always. Take some time to research your needs, gather your requirements, and look at other remoting technologies that are available. Then decide
  what you need.</p>

<p>This is the first part of a tutorial will walk you through developing a Web service API that could meet the requirements of all of the above-mentioned use cases. For the sake of
  clarity and brevity, we'll keep the operations simple, but by the time we're done, we'll have a fully-functional Web service API that exposes a bouquet of
  endpoints: <a href="http://en.wikipedia.org/wiki/SOAP">SOAP</a>, <a href="http://en.wikipedia.org/wiki/REST">REST</a>/XML, <a
  href="http://www.json.org/">JSON</a>, <a href="http://code.google.com/webtoolkit/">GWT</a>-RPC, and even <a
  href="http://en.wikipedia.org/wiki/Action_Message_Format">AMF</a> (for all you Flex developers). In Part II of this tutorial, we'll prove out the Web service API by building a rich AJAX
  application with an embedded Flash component that accesses it.</p>

<p>By the end of this two-part tutorial, we'll have established a good custom-fit Web service development
  process for maintaining your Web service API in your favorite development environment.</p>

<p>For those of you who would like to see the example code on your local filesystem, you can check it out of SVN at <a href="http://svn.codehaus.org/enunciate/trunk/enunciate/src/samples/addressbook/">http://svn.codehaus.org/enunciate/trunk/enunciate/src/samples/addressbook/</a>.</p>

<h2>Step 1: Create Your Project</h2>

<p>We will be exposing a Web service API for an address book application. We will be using <a href="http://maven.apache.org/">Maven 2</a> and <a
  href="http://enunciate.codehaus.org">Enunciate 1.6</a> to build and package our
  application. (Note that we could also use <a href="http://ant.apache.org">Ant</a> to build the application, but Maven will get us started more quickly.)</p>

<p>We'll label our application “addressbook” and assign it a group id “net.java.ws.addressbook”. Assuming Maven is already installed, we can use its <a
  href="http://maven.apache.org/plugins/maven-archetype-plugin/">archetype
  plugin</a> to bootstrap the project from the command line:</p>

<code>mvn archetype:create -DgroupId=net.java.ws.addressbook -DartifactId=addressbook</code>

<p>This will create a simple project for us with an empty Java source file and an associated test. You can open up the project in your favorite IDE;
  Maven has plugins available that will create project files for whichever one you like to work with.</p>

<p>Before our project is fully usable, we need to tweak it to declare our dependencies, configure the compile settings, and add any additional build tools. As
  for our dependencies, we need only one additional dependency on Enunciate's runtime libraries (groupId: org.codehaus.enunciate, artifactId:enunciate-rt). We
  also need to declare a Maven plugin for Enunciate to build the Web service application (with the “assemble” goal). For deployment, we
  can use the <a href="http://docs.codehaus.org/display/JETTY/Maven+Jetty+Plugin">Maven Jetty plugin</a> to deploy and run the application. Finally, we need to configure
  <a href="http://maven.apache.org/plugins/maven-compiler-plugin/">Maven's compiler plugin</a> to compile for JDK 1.5 compatability
  and make sure we're using “war” packaging since we're building a web application. In the end, our project descriptor looks like this:</p>

<code><u>addressbook/pom.xml:</u></code>

<pre><code>
&lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"&gt;
  &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
  &lt;groupId&gt;net.java.ws.addressbook&lt;/groupId&gt;
  &lt;artifactId&gt;addressbook&lt;/artifactId&gt;
  &lt;packaging&gt;war&lt;/packaging&gt;
  &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
  &lt;name&gt;addressbook&lt;/name&gt;
  &lt;build&gt;
    &lt;plugins&gt;
      &lt;plugin&gt;
        &lt;groupId&gt;org.codehaus.enunciate&lt;/groupId&gt;
        &lt;artifactId&gt;maven-enunciate-plugin&lt;/artifactId&gt;
        &lt;version&gt;1.6&lt;/version&gt;
        &lt;executions&gt;
          &lt;execution&gt;
            &lt;goals&gt;
              &lt;goal&gt;assemble&lt;/goal&gt;
            &lt;/goals&gt;
          &lt;/execution&gt;
        &lt;/executions&gt;
      &lt;/plugin&gt;

      &lt;plugin&gt;
        &lt;groupId&gt;org.mortbay.jetty&lt;/groupId&gt;
        &lt;artifactId&gt;maven-jetty-plugin&lt;/artifactId&gt;
      &lt;/plugin&gt;

      &lt;plugin&gt;
        &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
        &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
        &lt;configuration&gt;
          &lt;source&gt;1.5&lt;/source&gt;
          &lt;target&gt;1.5&lt;/target&gt;
        &lt;/configuration&gt;
      &lt;/plugin&gt;
    &lt;/plugins&gt;
  &lt;/build&gt;
  &lt;dependencies&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;org.codehaus.enunciate&lt;/groupId&gt;
      &lt;artifactId&gt;enunciate-rt&lt;/artifactId&gt;
      &lt;version&gt;1.6&lt;/version&gt;
    &lt;/dependency&gt;

    &lt;dependency&gt;
      &lt;groupId&gt;junit&lt;/groupId&gt;
      &lt;artifactId&gt;junit&lt;/artifactId&gt;
      &lt;version&gt;3.8.1&lt;/version&gt;
      &lt;scope&gt;test&lt;/scope&gt;
    &lt;/dependency&gt;
  &lt;/dependencies&gt;
&lt;/project&gt;
</code></pre>

<h2>Step 2: Create Your Domain</h2>

<p>The domain of an address book application is very simple. It consists of a basic Contact object. The Contact has fields for an id, name, phone number, two
  address fields, and city. We'll also add a contact type enumeration object ("friend", "family", or "professional") and create an object representing a contact list
  for use when we want to retrieve multiple contacts from a Web service request. You'll also note that we've annotated Contact and ContactList with a
  <a href="https://jaxb.dev.java.net/">JAXB</a>
  annotation, <code>@javax.xml.bind.annotation.XmlRootElement</code>, which will allow us to return these types as XML elements from a REST request (see below).</p>

<code><u>addressbook/src/main/java/net/java/ws/addressbook/domain/Contact.java:</u></code>

<pre><code>
package net.java.ws.addressbook.domain;

import javax.xml.bind.annotation.XmlRootElement;

/**
 * A contact in the address book.
 *
 * @author Ryan Heaton
 */
@XmlRootElement
public class Contact {

  private int id;
  private String name;
  private String phone;
  private String address1;
  private String address2;
  private String city;
  private ContactType contactType;

  /**
   * The id of the contact.
   *
   * @return The id of the contact.
   */
  public int getId() {
    return id;
  }

  /**
   * The id of the contact.
   *
   * @param id The id of the contact.
   */
  public void setId(int id) {
    this.id = id;
  }

  /**
   * The name of the contact.
   *
   * @return The name of the contact.
   */
  public String getName() {
    return name;
  }

  /**
   * The name of the contact.
   *
   * @param name The name of the contact.
   */
  public void setName(String name) {
    this.name = name;
  }

  /**
   * The phone of the contact.
   *
   * @return The phone of the contact.
   */
  public String getPhone() {
    return phone;
  }

  /**
   * TThe phone of the contact.
   *
   * @param phone The phone of the contact.
   */
  public void setPhone(String phone) {
    this.phone = phone;
  }

  /**
   * The first address field of the contact.
   *
   * @return The first address field of the contact.
   */
  public String getAddress1() {
    return address1;
  }

  /**
   * The first address field of the contact.
   *
   * @param address1 The first address field of the contact.
   */
  public void setAddress1(String address1) {
    this.address1 = address1;
  }

  /**
   * The second address field of the contact.
   *
   * @return The second address field of the contact.
   */
  public String getAddress2() {
    return address2;
  }

  /**
   * The second address field of the contact.
   *
   * @param address2 The second address field of the contact.
   */
  public void setAddress2(String address2) {
    this.address2 = address2;
  }

  /**
   * The city of the contact.
   *
   * @return The city of the contact.
   */
  public String getCity() {
    return city;
  }

  /**
   * The city of the contact.
   *
   * @param city The city of the contact.
   */
  public void setCity(String city) {
    this.city = city;
  }

  /**
   * The contact type.
   *
   * @return The contact type.
   */
  public ContactType getContactType() {
    return contactType;
  }

  /**
   * The contact type.
   *
   * @param contactType The contact type.
   */
  public void setContactType(ContactType contactType) {
    this.contactType = contactType;
  }
}
</code></pre>

<code><u>addressbook/src/main/java/net/java/ws/addressbook/domain/ContactType.java:</u></code>

<pre><code>
package net.java.ws.addressbook.domain;

/**
 * A contact type.
 *
 * @author Ryan Heaton
 */
public enum ContactType {

  friend,

  family,

  professional

}
</code></pre>

<code><u>addressbook/src/main/java/net/java/ws/addressbook/domain/ContactList.java:</u></code>

<pre><code>
package net.java.ws.addressbook.domain;

import javax.xml.bind.annotation.XmlRootElement;
import java.util.Collection;

/**
 * A list of contacts.
 *
 * @author Ryan Heaton
 */
@XmlRootElement
public class ContactList {

  private Collection<Contact> contacts;

  /**
   * The contact list.
   *
   * @return The contact list.
   */
  public Collection<Contact> getContacts() {
    return contacts;
  }

  /**
   * The contact list.
   *
   * @param contacts The contact list.
   */
  public void setContacts(Collection<Contact> contacts) {
    this.contacts = contacts;
  }
}
</code></pre>

<h2>Step 3: Create Your Services</h2>

<p>The next step involves creating the services that will comprise our Web service API. We'll create an AddressBook interface that defines three operations:
  <code>getContact</code>, <code>findContactsByName</code>, and <code>findContactsByType</code>, each of them throwing an <code>AddressBookException</code> in case something goes wrong.</p>

<p>Furthermore, we have to identify our interface as a Web service. We do this by applying the <a href="https://jax-ws.dev.java.net/">JAX-WS</a> annotation <code>@javax.jws.WebService</code> to the interface. As it
  turns out, this service interface also lends itself nicely to a mapping to a REST endpoint. We can decide, for example, to map the <code>getContact</code> method to an HTTP
  GET that will take the id parameter from the URL in the form of a context parameter. To perform the mapping to a <a
  href="http://weblogs.java.net/blog/stoicflame/archive/2007/10/why_roi_vs_soi_1.html">resource-oriented interface</a>, we use
  Enunciate's proprietary REST annotations (<code>@RESTEndpoint</code>, <code>@Noun</code>, <code>@Verb</code>, <code>@ProperNoun</code>, etc.)</p>

<code><u>addressbook/src/main/java/net/java/ws/addressbook/services/AddressBook.java:</u></code>

<pre><code>
package net.java.ws.addressbook.services;

import net.java.ws.addressbook.domain.ContactList;
import net.java.ws.addressbook.domain.Contact;
import net.java.ws.addressbook.domain.ContactType;

import javax.jws.WebService;

import org.codehaus.enunciate.rest.annotations.*;

/**
 * An address book that provides access to a set of contacts.
 *
 * @author Ryan Heaton
 */
@WebService
@RESTEndpoint
public interface AddressBook {

  /**
   * Get a contact by id.
   *
   * @param id The id of the contact.
   * @return The contact.
   * @throws AddressBookException If the contact wasn't found.
   */
  @Noun (
    "contact"
  )
  @Verb (
    VerbType.read
  )
  Contact getContact(@ProperNoun Integer id) throws AddressBookException;

  /**
   * Find contacts by name.
   *
   * @param name The name to search for.
   * @return The contacts that were found.
   */
  ContactList findContactsByName(String name) throws AddressBookException;

  /**
   * Find contats by type.
   *
   * @param type The type of contact.
   * @return The contacts.
   */
  ContactList findContactsByType(ContactType type) throws AddressBookException;
}
</code></pre>

<code><u>addressbook/src/main/java/net/java/ws/addressbook/services/AddressBookException.java:</u></code>

<pre><code>
package net.java.ws.addressbook.services;

/**
 * @author Ryan Heaton
 */
public class AddressBookException extends Exception {

  public AddressBookException(String message) {
    super(message);
  }
}
</code></pre>

<p>Of course, we have to create an implementation of the AddressBook. This is what will query our database and perform the business logic of our application.
  For the purposes of this tutorial, we'll just create a simple in-memory store of contacts.</p>

<p>Our implementation must also reference its Web service interface in order to be identified as the implementation for the Web service. We again use the
  JAX-WS-specified <code>@javax.jws.WebService</code> and the Enunciate-specific <code>@RESTEndpoint</code> annotation to accomplish this.</p>

<code><u>addressbook/src/main/java/net/java/ws/addressbook/impl/AddressBookImpl.java:</u></code>

<pre><code>
package net.java.ws.addressbook.impl;

import net.java.ws.addressbook.services.AddressBook;
import net.java.ws.addressbook.services.AddressBookException;
import net.java.ws.addressbook.domain.Contact;
import net.java.ws.addressbook.domain.ContactList;
import net.java.ws.addressbook.domain.ContactType;

import java.util.*;

import org.codehaus.enunciate.rest.annotations.RESTEndpoint;

import javax.jws.WebService;

/**
 * @author Ryan Heaton
 */
@WebService (
  endpointInterface = "net.java.ws.addressbook.services.AddressBook"
)
@RESTEndpoint
public class AddressBookImpl implements AddressBook {

  private static final Map<Integer, Contact> STORE = loadContacts();

  public Contact getContact(Integer id) throws AddressBookException {
    Contact contact = STORE.get(id);
    if (contact == null) {
      throw new AddressBookException("contact not found: " + id);
    }
    return contact;
  }

  public ContactList findContactsByName(String name) throws AddressBookException {
    ArrayList<Contact> contacts = new ArrayList<Contact>();
    if (name != null) {
      for (Contact contact : STORE.values()) {
        if (contact.getName().toLowerCase().contains(name.toLowerCase())) {
          contacts.add(contact);
        }
      }
    }
    ContactList list = new ContactList();
    list.setContacts(contacts);
    return list;
  }

  public ContactList findContactsByType(ContactType type) throws AddressBookException {
    ArrayList<Contact> contacts = new ArrayList<Contact>();
    for (Contact contact : STORE.values()) {
      if (contact.getContactType().equals(type)) {
        contacts.add(contact);
      }
    }
    ContactList list = new ContactList();
    list.setContacts(contacts);
    return list;
  }

  private static Map<Integer, Contact> loadContacts() {
    final int size = 20;
    Random random = new Random();
    String[] firstNames = new String[]{"Sally", "George", "Harold", "Tammy", "Robert", "Daniel", "Jane", "Mike", "David", "John"};
    String[] lastNames = new String[]{"Beach", "Jobs", "Gates", "Bush", "Clinton", "Gore", "Moore", "Jones", "Adams", "Washington", "Smith"};
    String[] addresses = new String[]{"1 First Street", "2 Second Street", "3 Third Street"};
    String[] cities = new String[]{"Long Beach, CA", "New York, NY", "Orlando, FL", "Honolulu, HI", "Oklahoma City, OK"};
    String[] phoneNumbers = new String[]{"111-1111", "222-2222", "333-3333", "444-4444", "555-5555", "666-6666", "777-7777"};

    HashMap<Integer, Contact> contacts = new HashMap<Integer, Contact>();
    for (int i = 0; i < size; i++) {
      Contact contact = new Contact();
      contact.setId(i);
      contact.setName(firstNames[random.nextInt(firstNames.length)] + " " + lastNames[random.nextInt(lastNames.length)]);
      contact.setAddress1(addresses[random.nextInt(addresses.length)]);
      contact.setCity(cities[random.nextInt(cities.length)]);
      contact.setPhone(phoneNumbers[random.nextInt(phoneNumbers.length)]);
      contact.setContactType(ContactType.values()[random.nextInt(ContactType.values().length)]);
      contacts.put(i, contact);
    }

    return Collections.unmodifiableMap(contacts);
  }
}
</code></pre>

<h2>Step 4: Enable and Configure GWT and AMF (Flex Data Services) Endpoints.</h2>

<p>Enunciate will publish your Web service API as <a
  href="http://code.google.com/webtoolkit/documentation/com.google.gwt.doc.DeveloperGuide.RemoteProcedureCalls.html">GWT-RPC</a> endpoints and AMF (<a
  href="http://www.adobe.com/products/flex/dataservices/">Flex Data Services</a>) endpoints if you enable this option in the Enunciate
  configuration file. The configuration for the GWT module requires a path to the installed Google Web Toolkit and a name for the client module that will be
  generated (see the GWT documentation for details). The configuration for the AMF module requires a path to the installed Flex SDK.</p>

<code><u>addressbook/enunciate.xml:</u></code>

<pre><code>
&lt;enunciate&gt;
  &lt;modules&gt;
    &lt;gwt disabled="false" gwtHome="/path/to/gwt/home" rpcModuleName="net.java.ws.addressbook.AddressBookGWT"/&gt;
    &lt;amf disabled="false" flexHome="/path/to/flex/sdk/home"/&gt;
  &lt;/modules&gt;
&lt;/enunciate&gt;
</code></pre>

<h2>Step 5: Build, Package, and Run the Application</h2>

<p>Since we've got everything set up and all our endpoints configured, we can now use Maven to invoke Enunciate, build, package, and even deploy our application
  to Jetty by running the command:</p>

<code>mvn jetty:run-war</code>

<p>Assuming everything builds as expected, Jetty should be running your Web service API. Things to note:</p>

  <ol>
    <li>You can see the documentation for your Web service API by browsing to <a href="http://localhost:8080/addressbook/index.html">http://localhost:8080/addressbook/index.html</a>. You'll notice that Enunciate
      generated full documentation for your Web service API scraped from your JavaDocs. You've got your SOAP endpoints and REST endpoints documented along with
      the documentation for the data types.
    </li>
    <li>Each of the endpoints are up and running and servicing requests. Your browser doesn't know how to format requests for the SOAP endpoints, GWT endpoints,
      or the AMF endpoints, but you can see that the endpoints are at least responding to invalid requests by browsing to
      <a href="http://localhost:8080/addressbook/index.html">http://localhost:8080/addressbook/soap/AddressBookService</a>, <a href="http://localhost:8080/addressbook/gwt/AddressBookService">http://localhost:8080/addressbook/gwt/AddressBookService</a>, and
      <a href="http://localhost:8080/addressbook/amf/AddressBookService">http://localhost:8080/addressbook/amf/AddressBookService</a>.
    </li>
    <li>Your browser does, however, know how to format a REST request. You can see the XML for a contact by making a request to
      <a href="http://localhost:8080/addressbook/rest/contact/4">http://localhost:8080/addressbook/rest/contact/4</a>, for example. Or, to see the same contact in JSON format, browse to
      <a href="http://localhost:8080/addressbook/json/contact/4">http://localhost:8080/addressbook/json/contact/4</a>.
    </li>
    <li>Enunciate automatically generates client-side code that can be used to access your SOAP endpoints, GWT endpoints, and AMF endpoints (ActionScript
      classes). By default, the client-side libraries that can access your SOAP endpoints are provided as downloads from your Web service API. To see these
      downloads, navigate to <a href="http://localhost:8080/addressbook/downloads.html">http://localhost:8080/addressbook/downloads.html</a>. You can also configure Enunciate to make the client-side GWT code and
      ActionScript classes available for download from the download page. They are not available as a download by default because they are subject to cross-site
      scripting restrictions and are usually for internal consumption (see Part II).
    </li>
  </ol>]]>

</content>
</entry>
<entry>
<title>Enunciate 1.6: AMF Endpoints for Flex Developers</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/stoicflame/archive/2008/01/enunciate_16_am_1.html" />
<modified>2008-01-09T19:13:08Z</modified>
<issued>2008-01-09T19:13:03Z</issued>
<id>tag:weblogs.java.net,2008:/blog/stoicflame/400.8958</id>
<created>2008-01-09T19:13:03Z</created>
<summary type="text/plain">Enunciate 1.6 will publish your service endpoints via SOAP, REST/XML, JSON, GWT, and now AMF.  Furthermore, it&apos;ll generate the client-side code to access those endpoints (including the ActionScript classes for Flex developers).  And, as Enunciate has always done, it will generate your WSDLs, schemas, and full user-level documentation.</summary>
<author>
<name>stoicflame</name>

<email>ryan@webcohesion.com</email>
</author>

<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/stoicflame/">
<![CDATA[<p>If you haven't checked out the <a href="http://enunciate.codehaus.org">Enunciate</a> project recently, you may want to give it another look to see how it can improve the development, deployment, and consumption of your Web service API.</p>

<p>Enunciate 1.6 was just released with support for mounting your JAX-WS endpoint classes via AMF (thanks to Adobe's release of <a href="http://labs.adobe.com/technologies/blazeds/">BlazeDS</a>). This should be really interesting to Flex developers.  Not only will you be able to make Web service calls via AMF, but Enunciate will also generate type-safe client-side ActionScript classes that will access those endpoints.</p>

<p>Enunciate will also publish your endpoints via SOAP, REST/XML, JSON, and GWT. You'll also get your WSDLs, schemas, and full user-level documentation of your Web service API.</p>

<p>I'll be shortly posting a two-part tutorial on how to publish this kind of a rich API with your service endpoints and how to write an AJAX app with an embedded Flash component that consumes it.</p>]]>

</content>
</entry>
<entry>
<title>Enunciate 1.5 Released</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/stoicflame/archive/2007/10/enunciate_15_re_1.html" />
<modified>2007-10-22T13:56:58Z</modified>
<issued>2007-10-22T13:56:54Z</issued>
<id>tag:weblogs.java.net,2007:/blog/stoicflame/400.8468</id>
<created>2007-10-22T13:56:54Z</created>
<summary type="text/plain">Enunciate 1.5 makes some dramatic improvements in the GWT application development experience.  Included in the distribution bundle is a new pet clinic sample application that will demonstrate how to publish the pet clinic Web service API and how to develop a nice AJAX app for the pet clinic using GWT.</summary>
<author>
<name>stoicflame</name>

<email>ryan@webcohesion.com</email>
</author>

<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/stoicflame/">
<![CDATA[<p>Enunciate 1.5 makes some dramatic improvements in the GWT application development experience.  Included in the distribution bundle is a new pet clinic sample application that will demonstrate how to publish the pet clinic Web service API and how to develop a nice AJAX app for the pet clinic using GWT.</p>

<p><a href="http://enunciate.codehaus.org">http://enunciate.codehaus.org</a></p>]]>

</content>
</entry>
<entry>
<title>Why ROI vs. SOI (read &quot;REST vs. SOAP&quot;) Still Matters</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/stoicflame/archive/2007/10/why_roi_vs_soi_1.html" />
<modified>2007-10-10T00:31:40Z</modified>
<issued>2007-10-10T00:31:34Z</issued>
<id>tag:weblogs.java.net,2007:/blog/stoicflame/400.8402</id>
<created>2007-10-10T00:31:34Z</created>
<summary type="text/plain">Much to the chagrin of Web service engineers, the REST vs. SOAP debate still lives, and the discussion is not going to die anytime soon. The fundamentals of the debate go beyond superficial rivalry--they are architectural in nature. In order to design a sound Web service API, these principles must be confronted.</summary>
<author>
<name>stoicflame</name>

<email>ryan@webcohesion.com</email>
</author>

<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/stoicflame/">
<![CDATA[<p>The honeymoon with RESTful Web services is over. Now that we've had some time to get over the infatuation, let's take a fresh look at the principles of sound Web service API design.  Despite how rocky our relationship with SOAP has been, it's time to confront our prejudices and accept both technologies for their virtues and vices.</p>

<p>In fact, I propose we give this discussion a new identity in order to help us put the painful memories, bitter tears, and long, sleepless nights behind us. Because it's not really about REST vs. SOAP anymore, is it? A well-designed Web service API is so much more important than the technology we use to implement it. So after we get past the name-calling and mud slinging, what we're left with is a set of fundamental architectural principles for Web service API design.</p>

<p>On the REST side of the playing field we have engineers who have a set of well-defined resources that they want to make available by defining a constrained set of basic operations that can be applied. On the other side, we have engineers whose operations are much more complex, maybe contextual, and perhaps interdependent.  These engineers may or may not have a well-defined set of resources to which these operations apply. Rather than making a set of <i>resources</i> available, these engineers have a set of <i>services</i> they want to make available.</p>

<p>So on one end of the spectrum we have the need to design a Resource-Oriented Interface (ROI).  On the other end, we have the need to design a Service-Oriented Interface (SOI).</p>

<p>Determining what kind of an API is to be published should be the <u>first step</u> in designing a good Web service API. And, trust me, it's not always easy to determine where your API fits.  You may, for example, have a well-defined set of Gismo objects to which you can limit your operations to be create, read, update, and delete.  But what if you want to provide a search operation for Gismos?  In this case, the boundaries of the resource and the operation are less clear.</p>

<p>In any case, you will be able to make a much better choice of a development technology if you can first define whether your API is more Resource-Oriented or Service-Oriented. (By the way, it'll probably fit somewhere in between.) <i>Choosing the development technology first is letting the tail wag the dog</i>.</p>

<p>Still unconvinced?  May I suggest that you subscribe to one or more of the common misconceptions about the current state of Web service development?  Let's debunk those right now, shall we?</p>

<ol>
  <li><b>It is <i>not</i> easier to design a good Resource-Oriented Interface (think "REST") than it is to design a good Service-Oriented Interface.</b>  Actually, I'd suggest that for most engineers, an SOI is more intuitive than a ROI.</li>
  <li><b>It is <i>not</i> easier to implement an ROI than it is to implement an SOI.</b> In fact, the tools these days are much more mature for SOI. I've found that ROI developers often have to work directly with low-level protocol APIs, although that's changing fast.</li>
  <li><b>It is <i>not</i> easier to consume an ROI than it is to consume an SOI.</b> Which type of interface is easier to consume always depends on the platform of the consumers.  Are they using a high-level, compiled programming language or are they in looser, more interpreted environment?</li>
  <li><b>An SOI is <i>not</i> any less interoperable than an ROI.</b> I'm going to assert that we've pretty much solved the issue of interoperability. I'm sure there are many of you who might disagree.  Bring it on.</li>
  <li><b>SOAP is <i>not</i> the only technology for implementing an SOI.</b> Really. Just because you have a more service-oriented API doesn't mean you have to use SOAP. (Really? Whew!)</li>
  <li><b>ROI is <i>not</i> always the best choice for supporting RIAs.</b> Many AJAX frameworks (e.g. <a href="http://code.google.com/webtoolkit/documentation/com.google.gwt.doc.DeveloperGuide.RemoteProcedureCalls.html">GWT</a>) have their own RPC mechanisms that are much more SOI than they are ROI. Another example for Flash is <a href="http://en.wikipedia.org/wiki/Action_Message_Format">AMF</a>.</li>
</ol>

<p>So what do you think?  I say let's adopt a rational, reasonable approach to Web service API design and stop letting the tail wag the dog.</p>]]>

</content>
</entry>
<entry>
<title>Enunciate 1.4: Your JAX-WS endpoint published as a GWT-RPC endpoint</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/stoicflame/archive/2007/09/enunciate_14_yo_1.html" />
<modified>2007-09-19T16:56:16Z</modified>
<issued>2007-09-19T16:56:12Z</issued>
<id>tag:weblogs.java.net,2007:/blog/stoicflame/400.8259</id>
<created>2007-09-19T16:56:12Z</created>
<summary type="text/plain">...not to mentioned that it will be published via SOAP, REST/XML and JSON.  The GWT client-side Java code is generated and packaged for use with GWT to support your AJAX app.</summary>
<author>
<name>stoicflame</name>

<email>ryan@webcohesion.com</email>
</author>
<dc:subject>Web Services and XML</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/stoicflame/">
<![CDATA[<p>When you use Enunciate 1.4 to publish your Web service API, Enunciate will build you a war that you can drop into your favorite webapp container.  The war will supply any or all of the following, depending on your configuration:</p>

<ul>
<li>Full documentation (scraped from the JavaDocs)</li>
<li>Your service beans mounted via SOAP, along with the formal contract (WSDL, schemas, etc.)</li>
<li>Those same service beans mounted via REST/XML.</li>
<li>Those same service beans mounted via JSON.</li>
<li>Those same service beans mounted as GWT-RPC endpoints.</li>
<li>Client-side libraries for download (used for invoking your API programatically via SOAP).</li>
<li>Client-side GWT Java libraries that can be used with GWT to support an AJAX app.</li>
<li>Etc.</li>
</ul>

<p>If you want to know more, I suggest a quick walk through the <a href="http://enunciate.codehaus.org/getting_started.html">getting started guide</a>.</p>

<p><a href="http://enunciate.codehaus.org/">http://enunciate.codehaus.org/</a></p>]]>

</content>
</entry>
<entry>
<title>Enunciate 1.3 Released</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/stoicflame/archive/2007/08/enunciate_13_re.html" />
<modified>2007-08-23T18:50:23Z</modified>
<issued>2007-08-23T18:50:16Z</issued>
<id>tag:weblogs.java.net,2007:/blog/stoicflame/400.8095</id>
<created>2007-08-23T18:50:16Z</created>
<summary type="text/plain">Enunciate 1.3 includes support for applying aspects to service beans,
customization of endpoint URLs, and many bug fixes and minor
enhancements.</summary>
<author>
<name>stoicflame</name>

<email>ryan@webcohesion.com</email>
</author>
<dc:subject>Web Services and XML</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/stoicflame/">
<![CDATA[<a href="http://enunciate.codehaus.org/">Enunciate 1.3</a> includes support for applying aspects to service beans,
customization of endpoint URLs, and many bug fixes and minor
enhancements. See the <a href="http://enunciate.codehaus.org/release-notes-1.3.txt">release notes</a> for details.]]>

</content>
</entry>
<entry>
<title>Enunciate 1.2 Released</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/stoicflame/archive/2007/05/enunciate_12_re_1.html" />
<modified>2007-05-31T17:48:53Z</modified>
<issued>2007-05-31T00:10:42Z</issued>
<id>tag:weblogs.java.net,2007:/blog/stoicflame/400.7524</id>
<created>2007-05-31T00:10:42Z</created>
<summary type="text/plain">Enunciate 1.2 was just released with support for maps and JAXB 2.0 type adapters.</summary>
<author>
<name>stoicflame</name>

<email>ryan@webcohesion.com</email>
</author>
<dc:subject>Web Services and XML</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/stoicflame/">
<![CDATA[<p>Maps and support for type adapters were the two features most requested from those using Enunciate (and the two features that most often precluded more use from those <em>wanting</em> to use Enunciate).</p>

<p>Of course, the release includes numerous bug fixes and some user experience enhancements.</p>

<p><a href="http://enunciate.codehaus.org">http://enunciate.codehaus.org</a></p>]]>

</content>
</entry>
<entry>
<title>Enunciate 1.1 Released</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/stoicflame/archive/2007/04/enunciate_11_re.html" />
<modified>2007-04-18T18:49:47Z</modified>
<issued>2007-04-18T18:49:43Z</issued>
<id>tag:weblogs.java.net,2007:/blog/stoicflame/400.7082</id>
<created>2007-04-18T18:49:43Z</created>
<summary type="text/plain">Enunciate 1.1 was released yesterday, adding support for Maven 2.</summary>
<author>
<name>stoicflame</name>

<email>ryan@webcohesion.com</email>
</author>

<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/stoicflame/">
<![CDATA[<p><a href="http://enunciate.codehaus.org/">Enunciate 1.1</a> was released yesterday, adding support for Maven 2.  There were also some bug fixes and usability enhancements that were added, thanks to user feedback.</p>

<p>Enunciate is a Web service development platform.  Starting from the source code of your Web service API, Enunciate will produce a fully-functional webapp runnable from your favorite J2EE container that supports SOAP, REST/XML, and REST/JSON endpoints.  Enunciate will also publish user-level HTML documentation for your API and make fully-compatible client libraries available for download from the deployed application.</p>]]>

</content>
</entry>
<entry>
<title>My Two-Edged Arsenal</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/stoicflame/archive/2007/04/my_twoedged_ars.html" />
<modified>2007-04-18T18:38:22Z</modified>
<issued>2007-04-18T18:38:15Z</issued>
<id>tag:weblogs.java.net,2007:/blog/stoicflame/400.7081</id>
<created>2007-04-18T18:38:15Z</created>
<summary type="text/plain">Who&apos;s Ryan Heaton, and who let him in here packing that kind of heat?</summary>
<author>
<name>stoicflame</name>

<email>ryan@webcohesion.com</email>
</author>
<dc:subject>Community: Java Web Services and XML</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/stoicflame/">
<![CDATA[<p>I'm Ryan Heaton, and I'm delighted to be given blog space at Java.net.  I hope my contributions will add something of value to this terrific community. </p>

<p>My expertise pivots around Web service design and development, so I often find myself wielding some pretty sharp two-edged tools: WSDL, XML Schema, <a href="http://java.sun.com/webservices/jaxws/">JAX-WS</a>, <a href="https://jaxb.dev.java.net/">JAXB 2.0</a>, SOAP, REST, etc.  Believe me, I've got plenty of experience nursing the wounds that come from using such dangerous gear.  But by now, I'm pretty good at avoiding these kinds of injuries, and I strongly believe there are no better tools for the job.</p>

<p>And I want to help make life less hazardous for other Web service developers.  To this end, I authored <a href="http://www.webcohesion.com/compiled_contract.html">the compiled contract model</a> for Web service development and an associated Web service development framework called <a href="http://enunciate.codehaus.org/">Enunciate</a>.  They also let me on the expert group for <a href="https://jsr311.dev.java.net/">JSR 311</a>.</p>

<p>I consider myself both a SOAP advocate and a REST advocate, depending on the problem at hand.  I also strongly believe that contract-first Web service development should only be used as a last resort.</p>

<p>I'm currently employed as the lead engineer of the Web service API for <a href="http://www.familysearch.org/">FamilySearch.org</a>.  We're developing an online web application designed to be a free and open database for genealogical information.  The goal is to become a common repository of family history records and information for the entire world in an effort to reduce duplication and consolidate effort in genealogical research.</p>

<p>I'm a graduate of <a href="http://www.byu.edu">Brigham Young University</a>.  I currently reside in Salt Lake City, and I'm the father of four boys.</p>

<p>I love life.</p>]]>

</content>
</entry>

</feed>