There’s been a lot of development on Construct over the last few months which will result in a couple of releases before the end of the year. The most recent update, (v0.8a) saw a restructuring of the data store around named graphs, and major improvements to performance (both in speed and memory consumption) throughout the framework. We are aiming for a final release of version 0.8 in late October, with remaining work focused on improving the installation procedure. Once complete, the next release (v0.9) will see the codebase becoming fully OSGi compliant in addition to improving support for cross-subnet communication.
Author Archive for graeme
The alpha release of version 0.8 of Construct is now available from the download page. This distribution includes a DataGrabber component for loading RDF/XML files on startup, improved I/O performance, a reworked gossiping layer (not compatible with previous versions of Construct), and experimental support for Pellet. The full release for 0.8 is due in Q4 2008. See the CHANGELOG.txt enclosed in the distribution for full details.
All messages that are exchanged between Construct services and applications take the following format: [3 bytes][10 bytes][payload]
- The first 3 bytes correspond to the message type identifier (see below).
The next 10 bytes correspond to the length of the message payload in bytes. For example, a message with a 64 byte payload would be written as 0000000064.
- Finally, the message payload consists of a number of bytes indicated by the previous part of the message. The contents of the payload are protocol specific.
The message identifier codes used are as follows:
| The protocol identifier for querying | QUERY | 200 |
| The protocol identifier used for responding to queries | QUERY_RESPONSE | 210 |
| The protocol identifier used for sending rdf statements to the data port | RDF_ADD | 100 |
| The protocol identifier used for responding to an add rdf statements request | RDF_ADD_RESPONSE | 110 |
| The protocol identifier used for sending a service descriptor | SERVICE_DESCRIPTOR_RESPONSE | 310 |
When most service send a response to the client, the payload also takes the form of a code:
| The operation succeeded | OK | 600 |
| An error occured during the operation | ERROR | 610 |
| The service code was unrecognised | UNKNOWN | 650 |
Working with the discovery service
Open a connection to the host/port given in the bonjour resolution (there is no need to send any data). You will be sent an XML descriptor file of the form -
-
<services>
-
<servicecomponentdescriptor>
-
<name>Construct DataPort</name>
-
<description>Raw data port: Connect via a socket and send N-TRIPLE RDF strings. Response string will be ok or error if it fails.</description>
-
<host>erdinger</host>
-
<port>3528</port>
-
<misc>See example applications.</misc>
-
</servicecomponentdescriptor>
-
<servicecomponentdescriptor>
-
<name>Construct QueryService</name>
-
<description>The query service: Connect via a socket and send SPARQL queries. Response string will be a SPARQL result set in RDF.</description>
-
<host>erdinger</host>
-
<port>3531</port>
-
<misc>See example applications.</misc>
-
</servicecomponentdescriptor>
-
</services>
This provides you with all the information required to open a connection to the data port or query service directly.
Working with the data port
Use the protocol described above. This is an example of adding a single line:
-
1000000000043<http://hello> <http://construct> "world" .
NOTE: The data RDF Triple must have the trailing full stop . Example responses might be:
-
1100000000003600(OK) -
1100000000003610(ERROR) -
1100000000003650(UNKNOWN)
Working with the query service
The point of contact for application developers to Construct is the Query Service. It takes a SPARQL query as an input. This query is run on the data store (a list of RDF triples). If the query is valid and answerable, a string of data will be returned. This section will try to help you write a SPARQL query, and make sense of the returned information.
Writing a SPARQL query
The presence of a query service implies that there must be something to query. The data in Construct is stored in the data store. All the data is represented in RDF triples. Here’s a few examples of these: For readability, we will replace the URIs with the prefixes “sighting:” and “person:”. NOTE: The prefixes in the query(below) is valid SPARQL syntax.
-
PREFIX: sighting:http://srg.ucd.ie/construct/sighting#
-
PREFIX: person:http://www.pervasive-ontologies.org/ontologies/context/person.owl#
-
<sighting:Waldo109> <sighting:person> <person:Waldo>
-
<sighting:Waldo109> <sighing:computer> <http://srg.cs.ucd.ie/construct/computer/waldo.ucd.ie>
-
<sighting:Waldo109> <sighting:time> <2006-10-04T13:17:59Z>
-
<sighitng:Waldo109> <sightingstatus> <Active>
These four statements represent a sighting from a computer activity sensor.
The Query
To retrieve information from construct, a query must be written in the SPARQL format. This has a similar “Select X From Y Where Z” form to an SQL query. Here is an example query which relates to the RDF Triples above. It finds all the times of sightings of Waldo(note the time triple above).
-
String personQuery = “PREFIX sighting:<http://srg.ucd.ie/construct/sighting#> “
-
+ “PREFIX user:<http://www.pervasive-ontologies.org/ontologies/context/person.owl#> “
-
+ “SELECT ?time “
-
+ “WHERE {”
-
+ “?sighting sighting:person user:Waldo . “
-
+ “?sighting sighting:status sighting:Active . “
-
+ “?sighting sighting:time ?time”
-
+ “}”;
For a more comprehensive tutorial on SPARQL, visit the website at: http://www.w3.org/TR/rdf-sparql-query/
In order to send a query to the query service we must use the protocol described above. Below is an example.
-
200[payload length][SPARQL QUERY]
The Response
You will be sent back a string of the form
-
210[payload length][SPARQL result set in RDF form] - OR
2100000000003610(if an error occured)
This String is a SPARQL ResultSet. This is a valid RDF string, represented in N-TRIPLE format. This means that way in which it is processed is dependent on the RDF parsing capabilities of the language used. For example, in java, a new Jena model (or indeed a ResultSet object) can be created from it, and it can be then easily traversed.
Steve, an original member of the Construct Dev team, left the Systems Research Group last week. He’s off to get hitched and travel the world - so we won’t hold it against him!
As part of his leaving presents we made up this rather fetching (even if we do say so ourselves) T-Shirt, so that he can spread the word of Construct to the world.
Good luck Steve - Bon Voyage!
Every time Ubuntu’s Synaptic Package Manager updates the Avahi layer for Bonjour support it stomps on my Apple Bonjour install and breaks my Construct install. My guess is that the update puts Avahi first in the list of Bonjours to run when Construct starts. So I get this error:
*** WARNING *** The programme ‘java’ uses the Apple Bonjour compatiblity layer of Avahi.
*** WARNING *** Please fix your application to use the native API of Avahi!
*** WARNING *** For more information see
*** WARNING *** The programme ‘java’ called ‘DNSServiceQueryRecord()’ which is not supported (or only supported partially) in the Apple Bonjour compatiblity layer of Avahi.
*** WARNING *** Please fix your application to use the native API of Avahi!
*** WARNING *** For more information see
One way to address this is just to turn off the Avahi warning. Set an environmental variable list this export AVAHI_COMPAT_NOWARN=1 This isn’t a fix though it is just hiding the warning.
The best I have figured out so far is just to reinstall Bonjour:
Instructions for Installing Apple’s Bonjour on *nix
- Download the latest version of the Bonjour source code here.
- Decompress the downloaded archive
- cd to the mDNSPosix directory below the mDNSResponder-xxx directory (where xxx is the Bonjour version number).
- Edit
Makefileand change lineJDK = /usr/jdkto make it point at your Java installation (e.g., /usr/lib/jvm/java-6-sun) - Type
sudo make os=linux Java
- Type
sudo make os=linux install— if you have problems with this, see below. Most likely you will need to install a specific version of gcc
- Copy the java specific files to your jre lib’s ext directory (
cp build/prod/* /path/to/jre/lib/ext/) - Open up
/etc/nsswitch.confand ensure that the ‘mdns’ switch appears on the “hosts:” line. My “hosts:” line looks like this:
hosts: files dns mdns
Remember, whenever you use a new jre, make sure to include dns_sd.jar (Bonjour JAR file) in your jre/lib/ext directory
Problems with the install
Problems with stdlib.h
Lorcan had some problems with this install on Ubuntu (Edgy). He says: when running sudo make os=linux Java I got a lot of errors, starting with ../mDNSShared/dnssd_clientlib.c:71:20: error: stdlib.h: No such file or directory.
I installed the libc6-dev package. When I tried again everything worked fine
Problems with __stack_chk_fail_local
I had some major problems with this install on Ubuntu (Edgy), specifically when using gcc4.1 (to find out which version of gcc you are using type gcc --version).
lorcan@comp:~/Desktop/mDNSResponder-107.6/mDNSPosix$ sudo make os=linux install
Stopping Apple Darwin Multicast DNS / DNS Service Discovery daemon: mdnsd.
cp build/prod/mdnsd /usr/sbin/mdnsd
/usr/sbin/mdnsd installed
cp mdnsd.sh /etc/init.d/mdns
chmod ugo+x /etc/init.d/mdns
/etc/init.d/mdns start
Starting Apple Darwin Multicast DNS / DNS Service Discovery daemon: mdnsd.
ln -s -f /etc/init.d/mdns /etc/rc2.d/S52mdns
ln -s -f /etc/init.d/mdns /etc/rc3.d/S52mdns
ln -s -f /etc/init.d/mdns /etc/rc4.d/S52mdns
ln -s -f /etc/init.d/mdns /etc/rc5.d/S52mdns
ln -s -f /etc/init.d/mdns /etc/rc0.d/K16mdns
ln -s -f /etc/init.d/mdns /etc/rc6.d/K16mdns
/etc/init.d/mdns installed
cp build/prod/libdns_sd.so /usr/lib/libdns_sd.so.1
ln -s -f /usr/lib/libdns_sd.so.1 /usr/lib/libdns_sd.so
/usr/lib/libdns_sd.so.1 /usr/include/dns_sd.h installed
/usr/share/man/man8/mdnsd.8 installed
make[1]: Entering directory `/home/lorcan/Desktop/mDNSResponder-107.6/Clients’
mkdir build
cc dns-sd.c -L../mDNSPosix/build/prod/ -ldns_sd -I../mDNSShared -o build/dns-sd
/usr/bin/ld: build/dns-sd: hidden symbol `__stack_chk_fail_local’ in /usr/lib/libc_nonshared.a(stack_chk_fail_local.oS) is referenced by DSO
/usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: ld returned 1 exit status
make[1]: *** [build/dns-sd] Error 1
make[1]: Leaving directory `/home/lorcan/Desktop/mDNSResponder-107.6/Clients’
make: *** [../Clients/build/dns-sd] Error 2
Solution:
If the version of gcc is not 4.0.x Follow these instructions (EXACTLY!!!) to correct the problem:
- Ensure that gcc version 4.0.x is installed. This is a little tricky as the synaptic package manager stopped supporting this version of gcc since edgy. You’ll have to download the following packages: gcc-4.0-base, cpp-4.0 , gcc-4.0
- Open the terminal and cd to where you saved the package.
- Do the following for each of the three packages: dpkg -i PACKAGE.deb Install them in the same order the are above. gcc base first, then cpp, then gcc — This should put gcc-4.0 into your /usr/bin directory.
-
cd /usr/bin -
sudo mv gcc gcc-backup -
sudo ln -s gcc-4.0 gcc
Now completely rerun the instructions above (at the top of this page) to install Bonjour (you must completely rerun them from step 2). When installation is complete continue these instructions.
-
sudo cd /usr/bin -
sudo rm gcc -
sudo mv gcc-backup gcc
Now gcc should point to the original version of gcc (i.e. that version that you were using before you installed Bonjour).
As the name suggests, the construct.properties file defines settings for the Construct platform. The settings cover three things: global properties for Construct, the components to be instantiated at runtime, and the individual properties of each component.
In the current release, all (bar one) of the global properties are related to logging. The other refers to the hostname of the machine running the Construct software:
| Logging level | The level of log messages to be recorded |
|---|---|
| The Logging limit | The maximum number of bytes to write to any one log file |
| The logging file count | The number of log files to rotate |
| The logging file name | The base name to use for log files |
| The logging directory | The directory in which the log files are stored |
| The hostname | The hostname or IP address of the machine running the Construct software |
The components that you wish to instantiate once the Construct framework is started are also contained in the properties file. Some components also contain properties which are specific to those components and must be declared as children of the components in the properties file. The structure of the properties file is explained further on. Below is an example of some Construct components. More thorough explanations can be found elsewhere on the Wiki.
| Data Store Manager | Provides a single point of access to the data store |
|---|---|
| Query Service | Processes application and entity queries made in SPARQL |
| Data Port | Accepts RDF data provided by sensors and adds them to the data store |
| Registry Service | Stores information on registered services |
| Discovery Service | Handles requests from clients for available Construct services |
| Gossiping Components | Allows distribution of data store contents |
| Extension Components | Add-on components such as a Query Viewer |
Once the start button is clicked on the Construct GUI, a Component Loader is created which reads in the contents of the properties file and instantiates any components that are specified. On instantiation, each component fetches it’s properties and caters for them.
Reading and Writing to the construct.properties File
The construct.properties file is and XML encoded file in which all properties and components must be contained within the parent node, construct (i.e. it takes the form … ). Global properties must be contained directly inside the construct tags and they are indicated by a property tag. Thus, all properties take the form,
-
<property name=“[the name here]“ value=“[the value here]“ />
Components must also be defined directly inside the construct tags. The component specific properties must be declared directly inside the opening and closing tags of the component in question. Components are scripted as follows:
-
<component interface=“[the interface to the component here]“ implementation=“[the implementation of the component here]“>
-
<property … />
-
</component>
where the interface specifies the path to the interface for the component and the implementation specifies the path to the concrete implementation of the component.
There is an example properties file contained in the release of Construct. To add new properties follow the structure of the document as explained above. HTML style comments (i.e. <!– [the code to comment here] –>) can be used to prevent a property or component contained in the file from being read in. Ensure to comment the property or component by adding the opening comment (<!–) before the opening tag of the component or property and adding the closing comment (–>) after the closing tag.
In Part 1 of this series of posts, I described how to add data to Construct. This post will teach you how to get data back out again using the Query Service.
The Java libraries bundled with Construct make use Jena, and the SPARQL query language in the process of querying Construct. If you’re already familiar with Jena, then there is only a couple of additional steps to learn.
Working with Jena and SPARQL
To start, we need to open a connection to the Query Service. This is done in the same way as a connection to the Data Port, by creating a new instance of the appropriate class.
-
final QueryServiceProxy qsProxy = new QueryServiceProxy()
The next step is to create the SPARQL query. In this example, we wish to query for the name property of the subject http://example.com/people/bob that we created in Part 1.
-
<http://example.com/people/bob>
-
<http://example.com/terms#name>
-
?name}”;
Then we call the query() method of the proxy object, passing the query as an argument. The return value is a Jena ResultSet object corresponding to the result of the query.
What you do with the result set is obviously dependent on your need for the data. For the purposes of this example, we’ll print the result to the console.
-
if (resultSet.hasNext()) {
-
final QuerySolution solution = resultSet.nextSolution();
-
final Literal name = solution.getLiteral(“name”);
-
}
Finally, we close the connection to the query service.
-
qsProxy.close();
That’s the basics of querying data with Construct.
After you install Construct, the next thing you might want to do is add some data. This post will describe the basics.
The Java libraries bundled with Construct give you a couple of ways to contribute date: You can either pass RDF triples in directly, or work with Jena and submit a model when you’re ready to publish its contents.
Working with Triples
The first step is to create a connection to the DataPort. This is achieved by creating a new instance of the DataPortProxy class.
-
final DataPortProxy proxy = new DataPortProxy();
Next, we call the add() method of the proxy object, passing the RDF triple as an argument. Multiple triples can be added simultaneously by separating them with a period. The return indicates whether the add operation was successful.
-
final boolean response = proxy.add(“<http://example.com/people/bob>
-
<http://example.com/terms#name>
-
\”Bob Smith\”.”);
Finally, we close the connection to the data port.
-
proxy.close();
Working with Jena
When using Jena, the process is very similar. As before you should begin by creating a new instance of the DataPortProxy object. Next, a new model should be created, and populated with data.
-
final Model model = ModelFactory.createDefaultModel();
-
final Resource person = model.createResource(“http://example.com/people/bob”);
-
final Property name = model.createProperty(“http://example.com/terms#name”);
-
person.addProperty(name, “Bob Smith”);
Then, the contents of the Jena model is added to Construct through another of the proxy object’s add() methods. Remember to close the connection as before when you are finished.
-
final boolean response = proxy.add(model);
That’s the basics of adding data to Construct. The next post in this series will describe how to get data from Construct using the Query Service.
![[del.icio.us]](http://www.construct-infrastructure.org/wp-content/plugins/bookmarkify/delicious.png)
![[Digg]](http://www.construct-infrastructure.org/wp-content/plugins/bookmarkify/digg.png)
![[Google]](http://www.construct-infrastructure.org/wp-content/plugins/bookmarkify/google.png)
![[StumbleUpon]](http://www.construct-infrastructure.org/wp-content/plugins/bookmarkify/stumbleupon.png)
![[Windows Live]](http://www.construct-infrastructure.org/wp-content/plugins/bookmarkify/windowslive.png)
![[Yahoo!]](http://www.construct-infrastructure.org/wp-content/plugins/bookmarkify/yahoo.png)
![[Email]](http://www.construct-infrastructure.org/wp-content/plugins/bookmarkify/email.png)