Let us first layout the bundles I like to think in bundles because it is nicely concrete and down to earth. We obviously need a web server, which is easy to fulfill with the OSGi Http Service. We then require a bundle to handle the grunts of the remote procedure calling and another bundle to prove that it works.
The webrpc bundle should not indiscriminately export services. There are obviously security issues but also not all services are well suited to be exported. However, we’d like to keep the service as simple as possible. The choice was made to look for the public property on the service registration. This is easy to set with declarative services and it means we can use a POJO as our service; the service itself is not involved with the remote procedure calling. The value of the property is the name under which the service should be known to the outside world.
This request will invoke the newGame method on the service that is registered with the property public set to “sudoku”.
The webrpc bundle depends on the Http Service. When there is an Http Service present, it registers itself under the /rpc alias. The servlet will get called for all requests that start with /rpc. For such a request, the webrpc bundle looks up the service name (in the example sudoku) in the service registry using a simple query string with the OSGi filter language to do this. The next part is calling the right method in this service; this is non-trivial because it is necessary to coerce all the arguments from strings into the method argument types. I wrote a separate Invoker class to handle this coercion. Read it and weep. Most of the work is handling Java’s silly primitives.
The webrpc bundle maps requests that do not look like a method name to a getResource() call on the service object’s class. A service implementer can place all its web resources in the www directory and they are automatically mapped. That is, if someone requests /rpc/sudoku/prototype.js, it will load the resource from aQute/sudoko/www/prototype.js. Assuming the implementation class is in the aQute.sudoku package.
All this effort in the webrpc bundle has makes the sudoku bundle almost trivial. Well, I guess it was trivial in the first place because the server only calculates the board and this is not rocket science. The Soduko service only implements a newGame method. This method returns an array of 81 integers (remember how 9x9 was?). Negative integers mark positions that can be shown from the beginning; positive integers are to be guessed by the player. For the HTML side I decided to make a splash screen in SVG. Hey! We now have those fantastic tools, so let us use them. Though splash screen sounds more dramatic than it turned out, I admit, I am a lousy artist.
Both the webrpc and sudoku bundles used declarative services. The webrpc bundle was hard to test standalone because it relies heavily on the OSGi service registry. The Sudoku service was however a POJO and could therefore easily be tested.
Try it out! If you think it looks too big, just make the window smaller. Notice how nicely it all scales because CSS and SVG are used to adjust all parameters to the window size.
You can download the bundles from the OSGi Bundle Repository (OBR). The JAR’s contain the source code of the bundles in the OPT-INF/src directory. See how extremely little code is required to achieve the goals. Enjoy!