2013/11/08

back to the beginning ... spaces

I got some very nice feedback on my previous post (thank you, you know who you are), so I'm starting this time with the assumption that there is demand for basic information. Today we are taking a closer look at spaces.

You are almost certainly familiar with the concept. If you are into mathematics, you might consider a space as a set. If you are into programming, you might consider a space as a scope. The very fact that you are reading this post, means that you have issued a http:// request into a space that knows how to resolve such requests ... a space better known as the World Wide Web. You may or may not understand in detail how it (the World Wide Web) works but you certainly issued that request with a pretty good idea of what you were going to get.
Let us look at one such request :
  1. http://netkernelbook.org/author.html is requested in the World Wide Web space, you can do that with a - almost - magic tool called browser.
  2. resolution takes place, in the case of the World Wide Web DNS does that job and finds that there is indeed an http:// capable endpoint living at address 94.76.200.117 
  3. the document /author.html is requested of that endpoint 
  4. the document representation is returned to the browser, note that /author.html is just the identifier of the document, how the response is created is unknown (nor should you care, that's the whole point of the World Wide Web)
Spaces in Resource Oriented Computing work in exactly the same way : 
  1. requests are issued into them
  2. resolution takes place to find an endpoint capable of handling the request
  3. the resource is requested of that endpoint
  4. the resource representation is returned
You might think ja, ja you've already said that last time. And we've seen it when using the Request Resolution Trace Tool. Where's the rest of it ? There is no rest. This is it !

There is REST though, but that's a topic for another post.

The main difference with the World Wide Web is that Resource Oriented Computing doesn't stop at just one space. Let us look at my own module template to see what that means :

<module version="2.0">
    <meta>
        <identity>
            <uri>urn:org:elbeesee:experiment:introduction</uri>
            <version>1.0.0</version>
        </identity>
        <info>
            <name>elbeesee / experiment / introduction</name>
            <description>elbeesee / experiment / introduction</description>
        </info>
    </meta>

    <system>
        <dynamic/>
    </system>


    <rootspace
        name="elbeesee experiment introduction"
        public="true"
        uri="urn:org:elbeesee:experiment:introduction">
                       
        <import>
            <uri>urn:org:elbeesee:experiment:introduction:import</uri>
            <private/>
        </import>
    </rootspace>


    <rootspace
        name="elbeesee experiment introduction import"
        public="false"
        uri="urn:org:elbeesee:experiment:introduction:import">
    </rootspace>
</module>


Right, a module with two spaces. Let us start with the generalities (and a couple of best practices) :

  • A space is identified by the uri attribute on the <rootspace> tag. If you do not specify one, one is generated for you. Specify one !
  • The attribute public on the <rootspace> tag specifies whether or not a space can be used (imported) outside of it's module. The default is true, however, specify it !
You may think I have an obsession with being explicit. I don't. I am however much in favour of the KWYAD approach. For the youngsters, that approach predates Xtreme programming, Agile, ... you name it ... and is still as valid today as it was 20 years ago. Know What You Are Doing.

At the bottom there is the urn:org:elbeesee:experiment:introduction:import space. It will contain resources that are only needed in the module itself (public="false"). These will typically be imports from other spaces.

At the top there is the urn:org:elbeesee:experiment:introduction space. It will contain the resources that we want to expose (public="true"). Note that it has the same uri as the module itself. That is a common practice for smaller modules that only expose a single space. That's not mandatory, if you think urn:org:elbeesee:experiment:introduction:public (or whatever) is clearer, by all means go with that.


This sometimes leads to confusion. Remember that modules have no relevance, but spaces do ! You can not import a module. You import a space.

The top space imports the bottom space. And marks the import as private. This means that none of the resources from the bottom space will get exposed. This is KWYAD SOP.

To experiment with this a bit, add an import of urn:org:netkernel:ext:layer1 in the bottom space :
    <rootspace
        name="elbeesee experiment introduction import"
        public="false"
        uri="urn:org:elbeesee:experiment:introduction:import">
       
        <import>
            <!-- data:/ scheme -->
            <uri>urn:org:netkernel:ext:layer1</uri>
        </import>
    </rootspace>


Right, before I can ask you to fire-up the Request Resolution Trace Tool ... I promised not to make - too many - assumptions so a bit of explaining is in order here. You just modified the module.xml file of the module we deployed earlier. NetKernel has picked up those changes. It has. That's what the <dynamic/> tag in module.xml does. While you can debate if that tag should be there in a production system, it is of huge value during development. You make your changes to module.xml and lo and behold, they are deployed.


Another assumption I'm making is that you know what Layer1 is. For now you'll have to settle with the explanation that it is a space with tools that you can freely reuse in your own modules. 


Ok, now set up the Request Resolution Trace Tool as you can see below (note that I selected the bottom space) :

Amongst - a lot of - other things, the Layer1 space contains the data: scheme which we're going to use for our tests. And yes, that is why I specified that as a comment. When I look back to this module in a couple of months, that comment will remind me of why I imported Layer1 (yep, KWYAD again).

The identifier we are doing to use is data:text/plain,Hello World. I bet you can deduce what that is going to do. Anyway, let us Resolve it :


What you see is that we go down into the imported space and get a hit. 

Now, urn:org:elbeesee:experiment:introduction:import is itself imported into urn:org:elbeesee:experiment:introduction. So is our identifier resolvable there ?

No it isn't. At least it isn't in the sense that it does not get exposed. You may already have noticed however that there seems to be a third space you can select in the drop-down. Select it and try to resolve again :

This isn't actually a third space, it is the private part (for internal use only) of the urn:org:elbeesee:experiment:introduction. To prove that the data: scheme is available internally, add the following snippet in there:

        <mapper>
          <config>
              <endpoint>
                  <grammar>res:/introduction/helloworld-data</grammar>
                  <request>
                      <identifier>data:text/plain,Hello World</identifier>
                  </request>
              </endpoint>
          </config>
          <space></space>
        </mapper>
 


Now try to Resolve and Inject identifier res:/introduction/helloworld-data in urn:org:elbeesee:experiment:introduction :

I'll explain the mapper endpoint in detail in a future post, as you can see however, there's quite a couple of Hello World examples possible.

Ok, that's a lot of information to digest. Before I sign off I want to make the point that the examples are far from childish. The whole World Wide Web is contained in one single space. The above explores three spaces that have at least the same potential. Think about it.

Yes, I know I promised to show you how to make your resources available in the browser. That is part of the space-story but although doing it is simple, the explanation is quite long. So I'm moving that bit to next week's post.