I was looking into RDF Gateway the other week, and found it to be a very interesting product. It provides an RDF store which can be accessed using SPARQL or T-SQL and persists its data in a SQL Server database. It also allows you to expose your SPARQL queries by creating RDF Server Pages (RSPs). This technology is similar in nature to ASP or JSP in that it mixes markup with SPARQL quires and a JavaScript-like language called RDF Query Language (RQL) similarly to the way ASP embeds JScript/VBScript in markup and JSP intermixes it with Java. RSP documents are interpreted by RDF Gateway, which runs as a Windows NT service. These scripts are requested over HTTP, making them accessible to a wide array of applications and programming environments. After just a cursory investigation, it isn't hard to see how one could use this product to expose an RDF store as a collection of RESTful Web services. In case you're having trouble visualizing this, have a look at the following figure that shows the overall architecture of how this might be done:
In my view, each RESTful service would have one RSP script. The client would indicate which action or operation they wanted to invoke by setting a parameter on the query string. The RSP page would grab this argument, and invoke the corresponding function to fulfill that specific type of request. I realize that this design would make the service an REST-RPC hybrid (using Richardson and Ruby's term which they coined in their book RESTful Web services), but it would avoid the need to use something like Squid simply to do URL rewriting (since RDF Gateway doesn't have such abilities natively).
To show how this would work, I'll describe the idiom used by the different RSP pages above. Because each service would have one RSP page, it would perform the role of "dispatcher." It would grab the action off the query string, switch on it, and call the appropriate function. To demonstrate how this might look, consider the following snippet of RQL code:
<%
import "operations/a1.rql";
import "operations/a2.rql";
import "/common.rql";
%>
<Response>
<%
Response.contentType = "text/xml";
var action = Request["action"]; // Dispatcher
switch (action)
{
case "a1":
a1();
break;
case "a2":
a2();
break;
default:
_Error(); // Imported from common.rql
break;
}
%>
</Response>
This code fragment is the service's entry point, its "main" if you will. To keep the code organized, each of the service's operations is fulfilled by different functions which are factored out into separate RQL script and imported in the main RSP page. Each of the RSP pages for the different services would be almost identical. (I can imagine a little code generator to produce this code and a plug-in for Visual Studio or other editors to call it.)
When the action is fired, it would process the body of the HTTP request, use SPARQL to update or query the RDF store, and return the results in XML or JSON format. (The snippet above precludes the use of JSON, but that could be easily be changed and which format should be returned could be based on the value of a query string argument, e.g., json=1.)
Like the format of the results, the contents of the request would be XML or JSON. In the latter case, I think that RQL's eval statement could be used to turn it into an object that could be processed directly. In the case of XML, a little munging would have to be done, and, I'm not sure what support RDF Gateway has for this. Once converted to objects that could be used in the RQL script, they would be passed to SPARQL to perform the operation-specific processing as shown in the following snippet:
function a1()
{
    var input;   Â
// RQL doesn't have a contentType property on their
// Request object, so we have to see if the input
// is JSON by trying to eval it. I realize that
// this makes the system susceptible to script injection,
// but this is just a POC.
//
// The object returned from eval and MungeXml contains
// two properties, lbound (lower bound) and ubound (upper
// bound).
try {
input = eval(Request.binaryRead());
input.lbound; input.ubound;
}
catch(ex)
{
input = MungeXml();
}
// Use input parameters in a SPARQL expression to update
// or query the datastore.
var rs = (SELECT TOP 5 ?p ?s ?o USING mydata
WHERE {?p ?s ?o} and between(?o, #(input.lbound),
#(input.ubound)));
    Response.Write("<data>");   Â
    for (; rs.EOF; rs.MoveNext())
    {
        Response.Write("<datum><p>");
        Response.Write(rs["p"]);
        Response.Write("</p><s>");
        Response.Write(rs["s"]);
        Response.Write("</s><o>");
        Response.Write(rs["o"]);       Â
        Response.Write("</o></datum>");
    }   Â
    Response.Write("</data>");
}
As I mentioned at the beginning of this post, I've only had time to perform a short investigation into RDF Gateway. So, if there are glaring problems or emissions with the ideas presented here, please let know as a learn more about this exciting product.
If you would like to get started with RDF Gateway, surf over to Intellidimension's Web site and request a 60 day trial license by emailing sales@intellidimension.com.
Check out the SPARQL package for some examples on outputting a resultset as SPARQL Result XML or JSON.
/pkgs/sparql/sparql.rql
writeXMLResults and writeJSONResults functions
Another way to enable restful services on top of RDF Gateway in somewhat of a more powerful way (IMHO) is to use WCF and Basic HTTP Bindings to accept and process incoming requests and then forward the validated/processed request to an generic RSP page that takes some action and returns the results as XML or JSON to the WCF service which then replies to the caller.
It's another layer, but it allows RDFQL to do what it is good at (processing data in Gateway) and it allows WCF to handle what it is great at (processing messages from remote callers via REST/SOAP). It also allows you to lock RDF Gateway endpoint down much more so you don't have to worry so much about script injection and those type of issues.
Eric,
Thanks for the comments. I will check out the SPARQL package.
I agree that the use of WCF in conjunction with RDF Gateway is certainly a viable candidate architecture with many advantages. With that approach though, why send messages to a generic RSP page via HTTP? That has two drawbacks as I see it:
Also, in your proposal, why not use OLEDB to communicate between the WCF service and RDF Gateway? I'm not certain, but I imagine that would be more performant, and it would avoid the need to crete any RSP pages (IINM). Also, why not use the Semantics.SDK in the WCF service implementation to work with the downstream RDF Gateway service?
I think the value I was trying to add with my WCF recomendation is the richness of the WCF/.NET infrastructure as it relates to hosting and managing services. Intellidimension is clearly not in that business and their RSP pages are a means to an end, not a core competancy.
I used OLEDB for the first version of Interactive Media Manager and I felt that it was a real pain in the ass :). There is a lot missing from the OLEDB implementation (eg: datatypes on literal values are not easy to discover). From the discussions I have had with the guys at Intellidimension, I think that their HTTP implementation is actually better/more performant than their OLEDB implementation, it also works on x64 where the OLEDB drivers are x86 only. The RSP implementation is definately the way to go if you want to take advantage of Gateway.
What I typically do with my WCF services is have .NET objects that will serialize to and from the XML format that is being served by the RSP page I have running in Gateway. This way responses from Gateway can be handled using the .NET XML serialization infrastructure and then I can work with strongly typed objects in code or can load those objects right into the Semantics SDK objects.
You point out using the Semantics SDK in WCF and that, in my view, is definately a possibility. I use it in some cases to perform additional inference in memory before sending datasets back over the wire or to easily reformat the data that is being sent from WCF to the caller. The Semantics SDK from Intellidimension is definately one of the most interesting components that they are developing and I am excited about what it will enable in the future and what type of interest solutions people develop with it.
Have you checked out the SemanticServerModel object in the Semantics SDK? In their latest 3.0 version it allows you to execute SPARQL queries directly against the SQL server (bypassing the RDF Gateway service).
I understand what you are saying about the added value of WCF and have no arguments w/ that; however, the price you pay for the use of its features that get layers atop RSP isn't free.
Thanks for the info about their OLEDB provider.
I haven't played with the SemanticServerModel. I will certainly try to find the time to do so. Using it to skip RDF Gateway seems like it would offer a nice performance boost while simultaneously offering a friendly programming model.
I appreciate the tips, Eric.