The Metadata Server is a Resource Oriented Platform for hosting resources and RESTful services. It differs from other Resource Oriented Frameworks because it allows resources to be dynamic and change over time. In AliBaba, resources are objects and are instances of classes. Every resource in the system has properties and methods, just like objects. These properties and methods are defined within a class that has resource instances. What makes resources different from objects is that they can also be Web resources (documents or files).
Resources are identified by URLs that dereference to an AliBaba metadata server. Properties and method results are accessible through the notation: http://server/path?operation, where "http://server/path" is the resource URL and "operation" is the operation name of the property or method. Methods may have named parameters, which can be passed as URL query parameters, or a body parameters, which is passed in the request body. AliBaba uses a built in cache control to serve repeated safe dynamic requests as fast as it would static Web resources.
The Metadata Server includes two types of persistence stores: Web resources (or blobs) are stored using the local file system and accessed over HTTP and metadata about resources is stored in an RDF store, which is available as Linked Data (or through another server extension).
To start the metadata server run the provided bin/metadata-server.sh (or .bat) file with the main class org.openrdf.server.metadata.Server. The server has optional command line options to assign the repository, data directory, and web directory. For details run the server with the '-h' option.
Once the server is started, it can be accessed from the assigned port (8080 by default). Information can be added to the server via the HTTP PUT method from any supporting HTTP client. Here is an example using the curl client.
curl -X PUT -H "Content-Type: text/html" --data-binary @welcome.html \ http://localhost:8080/welcome.html
Once the above command is run successfully, the server will return a copy of the welcome.html file when accessing the http://localhost:8080/welcome.html URL. The server's copy of a file can be removed using the HTTP DELETE method.
The server has built in support for content negotiation. When a request for a resource is received with an Accept header that cannot be satisfied by its primary representation (if it has one at all) the server will search for properties and methods of the resource that have a @rel annotation of "alternate" and @type annotation that is acceptable by the request to redirect (302) the client to. Otherwise the server will search for @rel("describedby") to redirect (303) the client to.
When an RDF file is PUT onto the server, the contents of the file are indexed in the RDF store using the target URL as the named graph. If a client asks for the contents of the graph in a different RDF format, the server will redirect the client and return the indexed graph in the requested format, as shown here.
curl -X PUT -H "Content-Type: application/x-turtle" --data-binary @my-graph.ttl \ http://localhost:8080/my-graph curl -X GET --compressed -L -H "Accept: application/rdf+xml" \ http://localhost:8080/my-graph
If the client requests a URL as RDF and no RDF graph has been uploaded, the server will redirect the client to DESCRIBE the RDF resource in the format requested. This allows the metadata server to participate as a Linked Data node, by returning something useful for any resource request.
The metadata server is easily extended to support other operations or methods. Server extensions can be uploaded to the server as OWL ontologies or appended to the command line as ontologies or Java JAR files.
By uploading the graph in Figure 1, any HTML resource with the dc:creator property can be followed using the suffix ?creator.
Figure 1. creator-operation.ttl
@prefix dc:<http://purl.org/dc/elements/1.1/>. @prefix meta:<http://www.openrdf.org/rdf/2009/metadata#>. @prefix owl:<http://www.w3.org/2002/07/owl#>. @prefix rdfs:<http://www.w3.org/2000/01/rdf-schema#>. @prefix rdf:<http://www.w3.org/1999/02/22-rdf-syntax-ns#>. dc:creator a rdf:Property; meta:operation "creator"; rdfs:domain <urn:mimetype:text/html>.
For example, if the graph in Figure 2 is also uploaded to the server, the request for http://localhost:8080/welcome.html?creator will be redirected to http://localhost:8080/somebody.
Figure 2. creator-graph.ttl
@prefix dc:<http://purl.org/dc/elements/1.1/>. <http://localhost:8080/welcome.html> dc:creator <http://localhost:8080/somebody>.
The dc:creator property can also be changed by issuing the following PUT request.
curl -X PUT -H "Content-Location: me" \ http://localhost:8080/welcome.html?creator
Furthermore if the ontology in Figure 3 is uploaded, the result of the query can be accessed using any HTTP client as shown below using curl.
Figure 3. text-html.ttl
@prefix rdfs:<http://www.w3.org/2000/01/rdf-schema#>.
@prefix owl:<http://www.w3.org/2002/07/owl#>.
@prefix obj:<http://www.openrdf.org/rdf/2009/object#>.
@prefix meta:<http://www.openrdf.org/rdf/2009/metadata#>.
<#text-html> rdfs:subClassOf obj:Message;
meta:method "GET";
meta:cache-control "must-reevaluate";
rdfs:subClassOf [owl:onProperty obj:target;
owl:allValuesFrom [obj:matches "/text-html"]];
rdfs:subClassOf [owl:onProperty obj:functionalObjectResponse;
owl:allValuesFrom obj:TupleResult];
obj:sparql """
SELECT ?html WHERE { ?html a <urn:mimetype:text/html> }
""".
curl -X GET --compressed -H "Accept: application/sparql-results+json" \ http://localhost:8080/text-html
The annotation meta:cache-control (or in Java @cacheControl) assigns a cache directive that must be followed by AliBaba's caching mechanism. The value "no-store" directs the server to never cache the result, causing the request to be reprocessed every time. The cache extension "must-reevaluate" directs the server to re-evaluate the result every time the cache expires. Otherwise the request will only be reprocessed when the resources has changed (web resource data or RDF resource metadata) either directly (via HTTP) or indirectly through a change in the RDF store.
The server can also be extended through Java classes. If the file in Figure 4 is compiled and included in a JAR or directory (ending in '/') as a relative file URL on the command line, the server will execute the method for all POST requests to the path "/echo".
Figure 4. Echo.java
// Echo.java
import org.openrdf.repository.object.*;
import org.openrdf.repository.object.annotations.*;
import org.openrdf.server.metadata.annotations.*;
import java.util.Map;
@matches("/echo")
public abstract class Echo implements RDFObject {
@method("POST")
@type("text/plain")
public String echo(Map<String, String[]> param) throws Exception {
StringBuilder out = new StringBuilder();
out.append("Request URL:\n");
out.append(getResource().stringValue());
out.append("\n\n");
out.append("Post Parameters:\n");
for (String name : param.keySet()) {
String values[] = param.get(name);
if (values != null) {
for (int i = 0; i < values.length; i++) {
out.append(name).append(": ");
out.append(values[i]).append("\n");
}
}
}
return out.toString();
}
}
As shown below using curl.
curl --compressed -X POST -d "hello=world" \ http://localhost:8080/echo
Methods can return any registered concept, a concept Set, Model, GraphQueryResult, TupleQueryResult, InputStream, Readable, ReadableByteChannel, String, or URL (307 redirect). They can include a body parameter of any of the for listed types and other parameters with the @parameter annotation with a query parameter name. Query parameters can be any datatype or concept type. A @parameter("*") can be used with a MapString, String[] for a complete set of query parameters. The method RDFObject#getResource().stringValue() returns the URI of the resource (without any query parameters). The annotation @type restricts the possible media types a method can produce.
The metadata server is immediately useful as an RDF web server by exposing the contents of an RDF repository over HTTP requests via Linked Data. Because the metadata server is easily extended, it can scale from a simple static file server to an application controller that facilitates structuring applications around the resources they serve.