ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Developing Highly Distributed Applications with Jtrix

by Nik Silver
05/08/2002

Jtrix is an open source Java platform for creating highly scalable, distributed, and efficient Web services. This article describes Jtrix, compares it to other Java technologies, and illustrates how to write a Jtrix application -- both a client, and the service it uses. You can download Jtrix from the Jtrix.org Web site or look it up on Sourceforge.

What is Jtrix?

How can you write an application that is economical to run? To answer this question, you need several things. You cannot create everything yourself, so you'll need to outsource some services: database, server farms, DNS server, credit card authorization, etc. And of course, you should expect to pay for these services, so you and your service providers need to measure usage accurately. If your application is successful, you'll need to allocate more processing power and more server space in various parts of the world. And you shouldn't have to rewrite your application to cope with that.

Jtrix addresses these issues. It's about creating and using Web services of any kind, and making applications distributed for reliability and mobile so they can move to new locations. Those roaming Jtrix programs are called netlets, and many netlets will work together to provide a highly scaled, distributed service or application. Each netlet will run on a node -- a Jtrix runtime environment.

But Jtrix is also about making applications sensitive to resource usage and need. Applications should be able to grow and shrink as needed, so they don't cost a fortune to run before demand increases, or when it shrinks. In the Jtrix world, the same application will cost 1,000 times less to run when there are 1,000 times fewer users. If you ran a dot-com a few years ago, you'll appreciate the business need for such an architecture.

How Does Jtrix Compare to ...

Jtrix has been inspired by many technologies, most of them Java-based. As befits a highly distributed system, Jtrix is very peer to peer. But whereas JXTA is a P2P communications system, Jtrix doesn't care how its communication works. A Jtrix application can use JXTA if it likes, or it can use something else. We're actually considering using JXTA in a couple of places; if it had been released five months earlier, we might be using it already.


O'Reilly Emerging Technologies Conference

The 2002 O'Reilly Emerging Technologies Conference explored how P2P and Web services are coming together in a new Internet operating system.


Another P2P touchstone is Gnutella. In fact, Gnutella would be a good application for Jtrix, but this is only one possibility; Jtrix is far more general and is intended for all kinds of Web services.

Jtrix's concept of accessing services is very close to Jini, because when one netlet uses a service, it's provided by a second, downloaded, netlet. That second netlet may be a simple proxy or carry a lot of intelligence. But Jtrix is very strong on security, so neither netlet can trust the other enough to let it run in its own class space. The node ensures the two are separated from each other and itself. So Jini is suited to a trusted Intranet environment, while Jtrix is designed for the hostile world of the Internet.

Enterprise Java Beans are all about distributed systems, too. The EJB concept of an application is very much the client/server, three-tier architecture, whereas Jtrix applications are much more P2P and don't enforce any heirarchy among netlets. Also, EJB distributes objects, which again download into the client's class space; Jtrix netlets are separated, as we've already said, and they are more about delivering full services, not just single objects.

Actually, since EJB servers are much higher level than Jtrix, an EJB server would be an excellent application to implement in Jtrix. It would produce a very highly scalable and mobile application server with all the high-level functionality of EJBs.

Jtrix Jargon

We've already met netlet and nodes. A netlet must implement the INetlet interface. It is described by an XML netlet descriptor, which tells the node how to get the netlet's code, load it and initialize it.

We also know that any Jtrix application can provide or use a service. A service connection is a two-way deal, and if your netlet uses a service, then it must offer one in return, even if it has no function. The class NullService provides a do-nothing service for this purpose.

A service is accessed by means of a warrant, which is an XML document. The warrant will have been issued by the service provider, probably to you personally, so that when you use it they recognize you. Then they can give you access to your "account" (your files, in the example of a data storage service), and bill you if needed.

To connect to a service, we say you bind to it. The node handles all connection details. Once you've bound to a service, you can access one of its facets, which is just any Java interface it offers. Getting a facet is also called binding.

Any of these facet interfaces will implement the IRemote interface, in much the same way that RMI has its Remote interface. In Jtrix, all interfaces start with the letter I, just so we know what we're dealing with.

Hello, Jtrix World

Here's a "Hello, World" program in Jtrix. We're first writing a client netlet which uses a Jtrix "Hello, World" service; we'll write the service itself later. The client takes a warrant, asks the node to bind the corresponding service, binds the facet offered by the service (IHelloFacet), and then gets the message contained within. This code and more is discussed in the complete programmer's guide, "How to Write Netlets." All of the Jtrix JARs and tools needed are in the download bundle on the site.

First, here's the definition of the IHelloFacet:


package org.jtrix.project.helloworld;

import org.jtrix.base.*;

public interface IHelloFacet extends IRemote
{
    public String getMessage();
}

Now here's the netlet. Most of it is made up of trivial do-nothing implementations of methods in the INetlet interface. The initialise() method does all of the real work. (Note the British spelling!) It binds to the service, gets the facet, and uses it. It offers the NullService mentioned above as its side of the two-way service connection.


package org.jtrix.project.helloworld;

import org.jtrix.base.*;
import org.jtrix.project.libjtrix.netlet.NullService;

/** Netlet which accesses a hello world service using a warrant
 * read from an incoming parameter.
 */
public class Hello1Client implements INetlet
{
    public byte[] initialise(INode node, Object param, byte[] unsigned)
        throws InitialiseException
    {
        try
        {
            // Get the warrant, use it bind the service, and then get the facet
            Warrant warrant = (Warrant)param;
            IService service = node.bindService(warrant, new NullService());
            String hf_name = IHelloFacet.class.getName();
            IHelloFacet facet = (IHelloFacet) service.bindFacet(hf_name);

            // Use the facet
            System.out.println(facet.getMessage());
            return null;
        }
        catch (Throwable e)
        {
            System.out.println("Sorry, no message available");
            e.printStackTrace();
            throw new InitialiseException(e.toString());
        }
    }

    public void terminate(long date, IShutdownProgress progress)
    {
        // Nothing to clean up when we terminate
    }

    public IService bindService(Warrant warrant, IService consumer)
        throws ServiceBindException
    {
        // This netlet offers no services to other netlets using warrants
        throw new ServiceBindException();
    }

    public String[] getFacets()
    {
        // This netlet offers no facets to the node
        return new String[0];
    }

    public IRemote bindFacet(String facet) throws FacetBindException
    {
        // The node shouldn't try to bind facets from here
        throw new FacetBindException();
    }
} // Hello1Client

To compile this, you need jtrix.jar and libjtrix.jar on your classpath, and you can put both classes into hello1.jar.

However, this client netlet is useless without a "Hello, World" service. So let's write that next.

What is a Jtrix Service?

To recap, a Jtrix service is anything that offers features and functionality to a netlet any time, anywhere. We'll get to the "any time, anywhere" part in a moment, but first, here are some examples of Jtrix services:

  • A "Hello, World" service. Provides a message to a netlet. We'll be writing that here.
  • A hosting service. Provides a runtime environment for netlets and an upload interface for remote access. Also provides them with resources, such as disk space and networking. By accessing several hosting services simultaneously you can ensure your application is distributed and redundant.
  • A servlet engine service. Allows a consumer to upload a WAR file of servlets and JSPs, and processes them as needed, returning HTML pages.
  • A DNS service. Acts as a distributed DNS server and allows a consumer to update their own DNS information, manage subdomains, etc.
  • An HTTP service. Listens for incoming HTTP requests and handles them appropriately. It can use the servlet engine service to outsource JSP requests. And it can use the DNS service, so it can update the location of a site if one server fails and it starts a replacement elsewhere.

In fact, all of these services have already been created, with the servlet service being a Jtrix wrapper around the Tomcat servlet engine. You can download them from the site.

The "any time, anywhere" part of a service is a central principle of Jtrix. Jtrix aims to provide services that are always available to anyone who has the rights to access them. It recognizes the fact that servers are never 100% reliable, so Jtrix services tend to be distributed and redundant.

What Makes Up a Service?

There are really only two necessary parts to a Jtrix service. The first is a warrant -- an XML document that allows the holder access to a service. The client netlet presents the warrant to its node, which then puts it in touch with the service.

When the node is given a warrant it downloads a new netlet, the access point netlet -- the second required part of a Jtrix service. The client netlet talks to the access point netlet, which then fulfills the service, most likely by proxying requests back to a central server.

An access point netlet is a bit like an RMI stub, but there are key differences. For one thing, the access point netlet represents the entire service, not a single object. For another, it never runs in the same class space as the client code, thus ensuring security and version safety.

We might think that a server would be an essential part of a Jtrix service, but this is not so. An access point netlet doesn't have to proxy requests back to a server; it could deal with them itself.

Pages: 1, 2

Next Pagearrow