This tutorial builds on what we learned with our Magic 8-ball service. This time, we'll explore how to build a service with multiple features and we'll learn about more capabilities of the Dream framework. The goal of our service will be to provide a tool to visualize Dream messages: the messaging building block of the system.
This tutorial shows:
Ok, let's begin by creating our service skeleton. As before, we'll start by including the MindTouch.Dream namespace and defining a new class derived from DreamService.
using MindTouch.Tasking;
namespace MindTouch.Dream.Samples {
using Yield = System.Collections.Generic.IEnumerator<IYield>;
[DreamService("Dream Tutorial Show Headers", "Copyright (c) 2006, 2007 MindTouch, Inc.",
Info = "http://doc.opengarden.org/Dream_SDK/Tutorials/Show_Headers",
SID = new string[] { "http://services.mindtouch.com/dream/tutorial/2007/03/showheaders" }
)]
public class ShowHeadersService : DreamService {
}
}
A Dream message is composed of three parts:
Our service will allow us to visualize these parts for any message.
In our 8-ball service example, we were introduced to HTTP verbs. We learned that we could associate a feature with a specific verb. However, in our case, we're interested in capturing a request to our feature regardless of its verb. This can easily be accomplished by using the the wildcard symbol "*", which will match any verb.
Let begin by defining a feature to return the headers of our Dream message.
[DreamFeature("*:headers", "Get message headers of request")]
public Yield WildCardHeaders(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
}
This will match any request to our service that invokes the headers feature. So, if our service runs at http://localhost:8081/show-headers then any request to http://localhost:8081/show-headers/headers will invoke the above method.
Now onto the brunt of our service. We want to capture a Dream message and convert its headers to an XML document and return it. Fortunately, there is already a class that takes care of most of this. The XMessage class is derived from XDoc, our handy XML document class. XMessage is responsible for converting any Dream message into a XML document. It's particularly useful when wanting to embed Dream messages into a larger context.
However, in our case, it does too much since we only want the headers. This is where XDoc starts to show its magic. Every XDoc is always a valid XML document. Thus, we can use its indexer property (doc[index]) to select the desired node from XMessage and return it. This is exactly what the following code does:
public Yield WildCardHeaders(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
// convert dream message into an XML document
XDoc xmessage = new XMessage(request);
// select <headers> element
XDoc headers = xmessage["headers"];
// send it back
response.Return(DreamMessage.Ok(headers));
yield break;
}
Without going into further detail, it is worthwhile mentioning that the "headers" string used in the indexer property of XMessage (which is really just a specialized XDoc) is actually an XPath expression. It is thus possibly to create very sophisticated expressions to select a desired node or set of nodes. Learn more about XDoc here.
Let's add two more features: one for returning just the body and another for returning the complete message.
[DreamFeature("*:body", "Get message body of request")]
public Yield WildCardBody(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
// convert dream message into an XML document
XDoc xmessage = new XMessage(request);
// select first child of <body> element
XDoc body = xmessage["body"];
// respond by sending only the body back
response.Return(DreamMessage.Ok(body));
yield break;
}
[DreamFeature("*:message", "Get entire request message")]
public Yield WildCardMessage(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
// convert dream message into an XML document
XDoc xmessage = new XMessage(request);
// respond by sending the message back
response.Return(DreamMessage.Ok(xmessage));
yield break;
}
Now we only need to write our launch script and we're ready to roll. Let's save it as show-headers.startup.xml.
<script>
<!-- register the blueprint for our show-headers service -->
<action verb="POST" path="/host/load?name=dream.sample.show-headers" />
<!-- instantiate it -->
<action verb="POST" path="/host/services">
<config>
<path>show-headers</path>
<sid>http://services.mindtouch.com/dream/tutorial/2007/03/showheaders</sid>
</config>
</action>
</script>
Compile the service into an assembly file and copy into your bin folder where the other dream binaries are. (Note: this is automatically done by the Visual Studio.Net samples solution file and the makefile.)
Let's start the MindTouch Dream host application with our service configuration file:
mindtouch.host.exe script show-headers.startup.xml
Now, let's try it out by using our browser to go to http://localhost:8081/show-headers/message . If everything worked as planned, you should see something like the following output in your browser:
<message> <status>200</status> <headers> <Connection>keep-alive</Connection> <Keep-Alive>300</Keep-Alive> <Accept>text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5</Accept> <Accept-Charset>ISO-8859-1,utf-8;q=0.7,*;q=0.7</Accept-Charset> <Accept-Encoding>gzip,deflate</Accept-Encoding> <Accept-Language>en-us,en;q=0.5</Accept-Language> <Host>localhost:8081</Host> <Content-Length>0</Content-Length> <Content-Type>text/plain</Content-Type> <Content-Encoding>Windows-1252</Content-Encoding> </headers> <body format="text"/> </message>
The <status> element holds the status code of the message. Since this message was a request, it's status is 200. The <headers> element contains the list of HTTP headers sent by the browser. Finally, there is the <body> element, which is an empty text string since this was a GET message.
| File | Size | Date | Attached by | |||
|---|---|---|---|---|---|---|
| show-headers.startup.xml Show-Headers service startup XML | 396 bytes | 21:04, 23 Mar 2007 | SteveB | Actions | ||
| ShowHeaders.cs Show-Headers service sample | 2.97 kB | 15:14, 14 Oct 2007 | SteveB | Actions | ||