Recommended: Sing it, brah! 5 fabulous songs for developers
JW's Top 5
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
Page 4 of 7
public interface PersistenceLayer {
Customer getCustomer(String id);
List<Customer> getCustomers(String status);
boolean storeCustomer(Customer a);
}
You could then imagine specific implementations for storing to flat files, an RDBMS via JDBC, an RDBMS via Hibernate, a remote fetch via a SOAP service -- anything really.
In NetKernel, you give this concept of a persistence layer a logical name and bind it to a specific instance. Internally, it uses an active URI model to address functionality, so you might call it active:fetch-customers, active:store-customer, and so on. This is how you'd refer to the functionality to fetch and update customer records. The active URI scheme takes
key-value pairs as a series of +key@value arguments.
For reasons that are probably not yet clear, you want the referenced values to be URIs as well if possible. Retrieval of customer
accounts might be active:fetch-customer+id@cust:012345 or something similar. NetKernel would interpret this URI based on a certain module configuration and map the request to the
behavior to perform the request. Just as with a URL and a Web site, you have no idea what kind of technology is used to retrieve
the information. As a client who needs the information, you probably do not care. Documentation will tell you what form it
will come back in. As long as it stays in that form, the module definition can change and your code will not break. This is
the benefit of late-binding, logically connected components to help improve maintainability. You are treating the result of
fetching a customer record as an information resource. Weakly typed and dynamic languages help get you started in this direction;
this approach is just the next step.
NetKernel allows many ways to invoke this kind of behavior. For this article, we'll use BeanShell for basic scripting:
main() {
req = context.createSubRequest("active:fetch-customer");
req.addArgument("id", "cust:012345");
resp = context.issueSubRequest(req);
context.createResponseFrom(resp);
}
Behind the scenes, NetKernel flattens this request to the full active:fetch-customer+id@cust:012345 URI. This represents a stateless, RESTful request; all of the information necessary to satisfy the request is passed in as
part of the request. It identifies both the handler (active:fetch-customer) and the full state (+id@cust:012345). It treats the invocation of this behavior with this parameter as an information resource. This is an example of bringing
REST inside. The behavior is invoked through a logical name, just as you might invoke a REST service at http://someserver/customer/012345.
The request is scheduled asynchronously on one of the microkernel threads. If you are running on a multicore, multi-CPU box, this will automatically scale up to take advantage of those resources without you (or the module implementor) having to think much about it. This is possible because what comes back is an immutable view of the result set, not unlike an HTML page or some JSON that might be returned as the result of issuing an HTTP request.