Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

REST for Java developers, Part 3: NetKernel

A next-generation environment where SOA meets multicore

  • Print
  • Feedback

Page 5 of 7

With a loosely typed language like BeanShell (or Groovy, also supported by NetKernel), you often do not know or care in what form information is returned. If you know that it came back as some form of XML by default, you might add the line:

resp.setMimeType("text/xml");

Using NetKernel: A short demo

It's time to give NetKernel a try, using a sample application. Download the application source and install it according to the directions in the included README.txt file. There's an XML skew to the configuration files and these examples, but NetKernel has fundamentally nothing to do with XML per se. It would be just as easy to write custom modules to deal with your domain objects if you wanted to.

The sample module is configured via the module.xml file to accept requests that match the following patterns (as well as others):

<export>
    <uri>
      <match>active:fetch-customer.*</match>
      <match>ffcpl:/customer.*</match>
      ...
    </uri>
  </export>

These are exported by the module definition, so any module that imports this one can issue requests for the behavior I describe below. Other modules are configured to convert external requests such as http://someserver/customer into an internal request of: ffcpl:/customer. This is just an internal request that gets remapped to the active:fetch-customers scheme like this:

<rewrite>
    <rule>
      <match>ffcpl:/customer</match>
      <to>active:fetch-customers</to>
    </rule>
  </rewrite>

The question remains, What actually executes the request? What handler do you rewrite the active URI to? Eventually, you imagine you will use a database, Web service, or other RESTful system to pull the information in but, when you get started, you may not know this. For the time being, you will simply dump some XML representations of customers into a directory and serve them up by munging them together. The initial rewrite rule will point to a BeanShell script to take care of this:

<rewrite>
    <match>active:fetch-customers</match>
    <to>active:beanshell+operator@ffcpl:/scripts/defaultcustomers.bsh</to>
  </rewrite>

This tells NetKernel to convert any request for active:fetch-customers into a request to execute the specified BeanShell. Notice how the pattern continues. You are identifying the functionality (active:beanshell, the logical name for interpreting BeanShell scripts) and the state needed to satisfy the request (a BeanShell script found at ffcpl:/scripts/defaultcustomers.bsh). Another module is responsible for handling this request. You can use it from your customer module because the NetKernel script module is included in your module definition:

<import>
    <uri>urn:org:ten60:netkernel:ext:script</uri>
  </import>

You could go look at that module's definition to find out how the script is actually executed, but for now, you do not care. You simply want it to happen. The default customer-handling BeanShell looks like Listing 1:

Listing 1. Default customer-handling script

import org.ten60.netkernel.layer1.nkf.*;
import org.ten60.netkernel.layer1.nkf.impl.*;
import org.ten60.netkernel.xml.representation.*;
import org.ten60.netkernel.xml.xda.*;

import com.ten60.netkernel.urii.aspect.*;

main()
{
  // Fetch the list of XML files in the data directory
  req = context.createSubRequest("active:mls");
  req.addArgument("operator", "ffcpl:/etc/MLS-Config.xml");
  req.setAspectClass(IAspectXDA.class);

  mls = context.issueSubRequestForAspect(req);

  // Iterate over the results
  xdaROItor = mls.getXDA().readOnlyIterator("/mls/dir/res");

  sb = new StringBuffer("<customers>");

  while(xdaROItor.hasNext()) {
    xdaROItor.next();
    current = xdaROItor.getText(".", true);

    // Fetch the content of the appropriate file
    cust = context.sourceAspect("ffcpl:/data/" + current, IAspectString.class);

    // Append to the results
    sb.append(cust.getString());
  }

  sb.append("</customers>");

  response = context.createResponseFrom(new StringAspect(sb.toString()));
  response.setExpired();
  response.setMimeType("text/xml");

  context.setResponse(response);
}

Listing 1 is busy, but reasonably straightforward to follow. First, a call is issued to the active:mls handler, which will fetch all of the files in a module that follow a certain pattern. The etc/MLS-Config.xml file from the module you installed shows that any XML files in the data directory should be returned:

  • Print
  • Feedback

Resources

More from JavaWorld