It is frequently necessary to take a break, stand still (very important and not only for my three year old son) and look back from where you came. If you don't do this, assumptions you make will soon no longer be valid.
Don't do this when you've got a hungry tiger or bear chasing you. Erring on the side of caution is perfectly acceptable and can safe your life.
Recently I've been trying to teach myself at least one of the Functional Programming languages. Almost every book assumes - without explicitly saying so - that you like the language before you read the book. No, I don't. Almost every book on the subject assumes - without explicitly saying so - that you just see how much simpler functional code is as opposed to the equivalent in imperative code. No, I don't.
I said almost every book because I think I found one that doesn't make those assumptions and is willing to take my hand and show me. I'm working through it at the moment, I'll definitely let you know when I'm done.
By now you should be thinking : this is a clear case of the pot calling the kettle black. And in case you were not, I was myself. So starting today I'm going to go through a couple of the basics of NetKernel again. I will also try make any assumption explicit. Are you ready (forgive me the long introduction) ? Today we're revisiting Hello World.
- You want to take a look at NetKernel.
- You have succeeded in installing NetKernel in a directory that I'll from here on describe as [installationdirectory].
- You have an instance of NetKernel running and when you point your browser to http://localhost:1060, it shows the NetKernel Backend Fulcrum.
- You are able to extract a directory from a zip archive.
In NetKernel there is a concept of a module, which you can describe as the unit of deployment or (with less pomp) as an application. The source of the application that we are going to discuss can be found here on Github. It's the urn.org.elbeesee.experiment.introduction directory (with content) that we are going to need on the system where you've got NetKernel running.
Again a lot of assumptions. If you're not familiar with git and Github, this link should get you a zip archive that contains the directory we need.
Deploying the module
If you already have some experience with creating your own modules, you probably have a location on the filesystem where you like those modules to reside. Otherwise :
- Create a subdirectory project-modules underneath [installationdirectory].
- Put the directory urn.org.elbeesee.experiment.introduction (with content) in the project-modules subdirectory.
- If it doesn't exist yet, create a subdirectory modules.d underneath [installationdirectory]/etc.
- Create a file elbeesee-experiment.xml in the modules.d directory with the following content :
Exploring the module
For this we are going to use the Request Resolution Trace Tool. Set it up (select the module and the space) as shown below.
What we're going to do is run through a couple of Identifiers and then Resolve, Inject and Display Representation for those. Every time we do that, we're going to explore our module's source to see if we can find why we got the result that we did. Let us start with Identifier res:/introduction/helloworld-file. A Resolve will look like this
This is the time to also start following along in the module source. Fire up your favorite plain text editor (anything but Notepad will do fine, I use both Eclipse and Sublime Text) and open up the module.xml file in the urn.org.elbeesee.experiment.introduction directory.
I am assuming a bit of familiarity with XML here.
In NetKernel, everything is a resource. You can think of a resource as an addressable bit of information. Resources live in spaces. You can think of a space as a mathematical set or a scope or a context. A resource can be requested with its space as the context. And that's it, there's no more. A module is no more than a carrier/container for a couple of (root)spaces that belong together but has no further meaning within NetKernel.
In the Request Resolution Trace Tool, we selected a space. You can find this same space in the module.xml file. Right at the top of that space you find this snippet of XML :
Can you see the Identifier we used in the Request Resolution Trace Tool ? Can you deduct what this snippet is going to do ? Note that fileset endpoint (specific type of resource) assumes the files to be relative to the module.
The Resolve just checked if the Identifier was available in the space, lets try to Inject next.
Your output will very likely differ from mine in that the location of the module will differ (and you might be using a Linux OS ... und so weiter). The Inject actually requested the resource.
Now, when you request a resource, you never get the resource as a result. I'll leave philosophical debates about whether or not there actually is anything at all to (meta) physicists (they can't show you an electron any more or less than they can show you love or an idea or ...), the fact is that what you get from a request is a representation of a resource.
This is not bullshit. If you accept that when you browse to http://google.com, what you get is not the http://google.com, but a representation of it and that at that same instant thousands of other people also get a representation of http://google.com ... you've understood the concept.
So, what the Request Resolution Trace Tool is telling us, is that the representation we got back from our resource request has type readable binary stream. Which is the standard representation type for a file.
But what does the readable binary stream contain ? Well, with Display Representation we can try to visualize it.
This must have felt like a huge roundabout way to show you the contents of the helloworld.txt file, but we've actually covered most of what Resource Oriented Computing is about while doing so !
Let us move on to Identifier res:/introduction/helloworld-literal. The Resolve will look like this
Interesting. Note how the fileset endpoint is checked first. Within a space, resolution is top down. The hit this time fell on this snippet of XML
<literal type="string" uri="res:/introduction/helloworld-literal">Hello World</literal>
This is the NetKernel entry (hasn't been added yet) for the list of Hello World programs. Defining a resource doesn't get any easier than that.
When we Inject the request, the result looks like this
You are correct to say there's a fundamental difference here. We can already see the result ! The reason is that our representation is a java.lang.String. The toString() function applied to a String shows ... you guessed it ... the String, whereas the same function applied to a Readable Binary Stream does not show the contents of the Stream.
There ... I'm leaving the the final Identifier res:/introduction/helloworld-accessor as an exercise for you. It may look harder than the two others, but it is exactly the same. An accessor is a code based (in this case Java) resource request.
Also try a couple of Identifiers that can not be resolved, like res:/introduction/helloworld-yourown for example.
That's it for this episode. Next time I'm going to show how you can make these resources directly accessible from your browser so you don't have to constantly use the Request Resolution Trace Tool.