In this tutorial we'll create a simple "hello world" service and deploy it in a simple module.
At each step we'll describe what we are doing and why. Where necessary links are given to further reading.
We'll create a service which produces an XML fragment which is bound to a URL path on a HTTP port. The XML fragment is:
<hello>world</hello>
The XML document will be generated by a DPML (Declarative Processing Markup
Language) script.
1) Create a directory structure for a module
All functionality deployed on NetKernel is packaged into modules.
Modules exist on the filesystem of the host as either .jar archive file or expanded into a directory structure. For
development purposes you will always be working with a directory.
Lets create the module directory; there are no limitations on its name or location but for this example lets call it
HelloWorld and place it in the modules directory of your installation. That is
[install]/modules/HelloWorld/ where [install] is the location you installed NetKernel.
2) Create a module definition
The module definition is a file called module.xml which exists in the root directory
of every module. The purpose of the module definition is to define meta data about the module, its
publicly exposed interface, the handling chain for requests on the module, and finally and specialised
components that are hosted by the module. The module definition conforms to the module definition schema.
Here is a minimal module definition for our module:
<module>
<identity>
<uri>urn:hello-world</uri>
<version>0.1.0</version>
</identity>
<info>
<name>Hello World</name>
<description>my first module</description>
<type>application</type>
</info>
<export>
<uri>
<match>ffcpl:/hello/world</match>
</uri>
<class />
</export>
<rewrite>
<rule>
<match>ffcpl:/hello/world</match>
<to>active:dpml+operand@ffcpl:/world.idoc</to>
</rule>
</rewrite>
<mapping>
<this>
<match>ffcpl:/.*</match>
</this>
<import>
<uri>urn:org:ten60:netkernel:ext:dpml</uri>
</import>
</mapping>
</module>
Lets look at what the module definition is specifying skipping over the identity and info
sections (more information.)
The export section declares that this module will accept any request with a URI of
ffcpl:/hello/world. These specifications for URIs may be wildcarded with standard regular expressions.
The ffcpl: URI scheme is an internal NetKernel scheme which is used to map on to the interfaces and internal resources of
modules.
The rewrite section declares that a URI of ffcpl:/hello/world will be rewritten to active:dpml+operand@ffcpl:/world.idoc.
This rewritten URI is matched by the DPML service which is being imported into the internal address space of this module by the
import statement in the mapping section. Above that, the this statement declares
that all URIs starting with ffcpl:/ are matched against static resources in this module.
It is worth spending a moment to look at the unusual URI which is matched by the DPML service. The active: scheme is
another internal NetKernel scheme. By convention it is used to map to services which perform processing. The way to parse it is to split it by
the + character. The first part, active:dpml, is what is matched by the DPML service. The second and subsequent parts,
operand@ffcpl:/world.idoc, are name-value argument pairs separated by the @ character which are passed to the service. The value is always another
nested URI. In this case the operand is the script that the DPML service should execute. More detail about active URIs here.
So in summary this module definition declares a module which will accept a request with URI ffcpl:/hello/world
and execute a DPML script to create a response.
3) Create a DPML script
In the previous section we declared a rewrite rule in the module definition which would execute a DPML script with a
URI of ffcpl:/world.idoc. We also declared that all requests with URI's starting ffcpl:/
would be resolved to resources in this module. Therefore if we create a file in the root directory of this module with a name
world.idoc it will be this that is used. This script has one instruction that copies a
literal XML document to the response:
<idoc> <instr>
<type>copy</type>
<operand>
<hello>world</hello>
</operand>
<target>this:response</target>
</instr>
</idoc>
For more information on the DPML language see here.
4) Register module
When NetKernel starts or restarts it commisions all modules that are registered in
[install]/etc/deployedModules.xml. To register our new module we need to add
the following fragment to root element of deployedModuled.xml:
<module>modules/HelloWorld/</module>
This defines the path to a module to commision. More information on
deployedModules.xml is available
here.
5) Associate module with HTTP server
If we restarted NetKernel now we would have our module deployed; however this module would be orphaned- no
other module is importing it so it is unused. The next step is to import our new module into the "frontend fulcrum". The
frontend fulcrum is the name given to a module that ships with NetKernel Standard Edition which starts a HTTP server on
port 8080 and is in expanded module form for easy editing. You can find the frontend fulcrum module configuration at
[install]/modules/mod-fulcrum-frontend/module.xml. Edit this to add the following fragment
into the mapping section as the next to last element- (the super element should remain at the end):
<import> <uri>urn:hello-world</uri>
</import>
The term "fulcrum" is the name of module pattern which
pivots a transport, which receives external requests (in this case HTTP), with modules that handle those requests (in this case
our hello world module. The fulcrum pattern along with other module patterns are documented
here.
6) Run service
Now we have everything setup we need to restart NetKernel. Go to the Cold Restart Tool
on the control panel, confirm the restart and then wait a few seconds.
Now enter http://localhost:8080/hello/world into your HTTP browser address bar. You should receive the
hello world message:
<hello>world</hello>
If you were to enter a different URI, say http://localhost:8080/hello/mars this URI would not be matched
by any modules in the fulcrum and you would receive a URI Resolution Failure exception. The default configuration
of the HTTP transport maps this into a HTML error page. It is worth noting that you can get more
detail on the error by clicking on the Exception Trace link, this shows a full
request trace hopefully detailing exactly where and why the error occured.
More details on configuring the HTTP transport are available
here.
Wrap up
Thats it! - you have now created your first module and service. Not only do you have a starting point to work from
but you have learned a lot of the basic concepts. You know how to create and deploy modules. You know how to link a
module to a transport and how a service gets invoked. This is, of course, more details behind all of these concepts...
Here are some links to continue your exploration:
- Using the Tools - a quick run through some of the tools on the System Services Fulcrum showing how they relate to the
module and service we have just created.
- Text2Image Service - a more complex example that explores parameter passing, calling sub-services and
exception handling.
- Scripted Services - a set of trailmaps creating services using procedural scripting languages.