Table Of Contents

Quick Start

Specifications

Code Examples

Articles

Common Issues


The Nature of JavaSpaces

Javaspaces have been compared with technologies such as message queues and databases. It is important to understand that whilst JavaSpaces can be used to perform some of the tasks supported by these other technologies, they should be treated very differently.

JavaSpaces are best considered as distributed shared memory with additional features which provide transactional integrity and support for the handling of failure. They are best suited to problems which can be modelled as flows of objects such as:

  • Processing purchase orders - orders go through a series of steps including credit card checks, stock allocation and dispatch.
  • Parallel Computation tasks - compute jobs are passed into the space, removed and computed by workers which then place a result back in the space. The originator then returns to pick up the result.

JavaSpaces provide a simple API for the manipulation of Entry objects:

  1. write - places a new Entry in the space.
  2. read - returns a copy of an Entry matching a particular template.
  3. take - removes an Entry matching a particular template from the space and returns it to the caller.

Entry objects are not serialized in the normal Java fashion. Only the public fields of an Entry object are written to the JavaSpace and each field is serialized separately such that, if two fields reference the same object, when the Entry is recovered from the JavaSpace, each of those fields will contain a separate copy of the original object.

Note also that the objects referenced in an Entry instance are not written separately to the JavaSpace. For example, consider:

public class SimpleEntry implements net.jini.core.entry.Entry {
	public Foo aFoo;
}

public class Foo implements java.io.Serializable {
	private Integer anInteger;
}

An instance of SimpleEntry is created and aFoo is populated with a Foo instance. The SimpleEntry is then written to the space as one object - i.e. the Foo object is not separately written to the space and cannot be matched with a take or read. To summarize, one might expect a JavaSpace to handle object hierarchies in a similar fashion to object-oriented databases but that is not the case. Only the top-level object of the hierarchy is available for matching.

A typical code example looks like this:
// This is a basic Entry implementation - only public fields are stored
//
public class DummyEntry implements Entry {
    public String theName;
    public String theOtherField;

    public DummyEntry() {
    }

    public DummyEntry(String aName) {
        theName = aName;
    }

    public String toString() {
        return theName;
    }

// JavaSpaces doesn't use this method - it's just here for completeness....
    public boolean equals(Object anObject) {
        if ((anObject != null) && (anObject instanceof DummyEntry)) {

            DummyEntry myEntry = (DummyEntry) anObject;

            if (myEntry.theName == null)
                return (myEntry.theName == theName);
            else
                return ((DummyEntry) anObject).theName.equals(theName);
        }

        return false;
    }
}

// Lookup JavaSpace and then......

// "Invent" the value we're looking for - normally, you'd get input from the user
// or whatever....
            Integer myValue =
                new Integer(theRNG.nextInt(thePoolSize));

// Build template
            Entry myTemplate = new DummyEntry(myValue.toString());

// We'll do this transactionally - we want txn to timeout if it takes more than 5 seconds.
            Transaction.Created myTxnC = 
                TransactionFactory.create(theTxnMgr, 5000);

            Transaction myTxn = myTxnC.transaction;

// Ask space to check for match, delete from space and return it to us
// The take actually locks the Entry, deletion won't occur 'til we commit
// If we take too long to execute or we fail, the transaction lease will expire and
// the transaction is automatically aborted, which makes our taken Entry available again
            Entry myResult = theSpace.take(myTemplate, myTxn, aTimeout);

// If we got it.....
            if (myResult != null) {
            	// Make some changes......
            	
            	// Write it back
               theSpace.write(myResult, myTxn, Lease.FOREVER);
            }

// Commit the transaction
            myTxn.commit();

Further Reading