Gozirra

0.4.1 (75)

Gozirra is a lightweight implementation of the Stomp specification. As of the first release it includes both client and server implementations for Java. The name stinks, and may change.

Stomp (previously TTMP) is a simple publish/subscribe messaging protocol. Its main attraction, to me at least, is its simplicity and focus. A Ruby client comes out to 107 lines of code. The Java server and client of this project fit in a jarball about 14KB large. You can easily communicate with a Stomp server via telnet, and it provides publish, subscribe, receipts, and transactions. It is everything you need for a lightweight communication protocol.

Gozirra is not intended to be a scalable standalone MOM solution. While it can be run in standalone mode, it is really targetted at being a library for providing embedded messaging to other applications. If you want a more feature full messaging provider, check out ActiveMQ, the reference platform for Stomp.


Getting

Sources and binaries can be downloaded from the following links:


Building

Requires Jakarta Ant. You build one of: all-jar, server-only-jar, or client-only-jar depending on what you're using it for.


Usage

The entry points are the Client and Server classes. For intra-VM communications, only the Server class is needed, and is used to return a Stomp client. The Client class is used to connect to servers over the network. The other class you may use is the Listener interface, which is how clients get Stomp messages delivered. You shouldn't need to directly access any of the other classes in the package.

I've purposely kept the API minimal.

Running a server

  Server s = new Server( 61626 );   // To start it.
  s.stop();                         // To stop it.  That's it.
    

Intra-VM messaging

To deliver messages on the server, get an internal client:

  Stomp local_client = s.getClient();
  // Deliver some messages:
  local_client.send( "/log/foo", "Message number one" );
  // Listen for commands from clients
  local_client.subscribe( "/command/info", new Listener() {
    public void message( Map header, String body ) {
      if (body.equals( "get-info" )) {
        // Send some message to the clients with info about the server
      }
      // ...
    }
  } );
    

Network clients

To connect to a network server from a client:

  Client c = new Client( "localhost", 61626, "ser", "ser" );
  c.subscribe( "foo-channel", my_listener );
  c.subscribe( "foo-channel", other_listener );
  c.unsubscribe( "foo-channel", other_listener );  // Unsubscribe only one listener
  c.unsubscribe( "foo-channel" );   // Unsubscribe all listeners
  c.disconnect();
    

Errors

Server errors are delivered as messages to special listeners. These are attached to the Stomp client with addErrorListene().

  c.addErrorListener( new Listener() {
    public void message( Map header, String message ) {
      // ...
    }
  });
    

Receipts

Receipts can be added to any message by passing in a header Map containing a receipt header.

  HashMap headers = new HashMap();
  headers.put( "receipt", "my-receipt-123" );
  client.send( "channela", "Hello World", headers );
    

There are two ways of testing for receipts:

hasReceipt()

hasReceipt() returns true if the client has already received a receipt from the server:

  boolean receipt = client.hasReceipt( "my-receipt-123" )
    

waitOnReceipt()

There are two blocking methods for waiting for a receipt to come in. The first takes one argument -- the receipt id -- and returns only when it finds a receipt. This method has no return value. The second takes two arguments -- the receipt id and a long timeout -- and waits for that many milliseconds. This method returns true if and only if it received the receipt within the timeout period.

  // Wait two seconds for the receipt
  boolean receipt = client.waitOnReceipt( "my-receipt-123", 2000 );
    

Receipts can be cleared with the Stomp.clearReceipts() method. Individual receipts can be cleared with the Stomp.clearReceipt() method.

  client.clearReceipt( "my-receipt-123" );  // Clear just one
  client.clearReceipts();                   // Clear all receipts
    

Synchronous communication

Stomp is inherantly asynchronous. Synchronous communication can be implemented using receipts, and Gozirra provides convenience methods for this. The synchronous methods are all suffixed with a W, for wait, and they do not return until the server has acknowledged the receipt of the message. Messages sent to the server via these methods either (a) do not return, (b) throw an InterruptedException, or (c) guarantee delivery. The first case occurs if the server never sends a receipt, the second occurs if the client is interrupted while waiting for a receipt, and the third occurs when the client receives delivery confirmation from the server.

Four methods have synchronous versions: send, subscribe, unsubscribe, and commit.

  c.sendW( "/destination", "some method" );
    

There is no synchronous version of unsubcribe( String, Listener ), since this usually occurs on the client side.

Transactions

Gozirra implements server-side transactions. A transaction is a sequence of messages that are cached on a server, and then are either aborted or delivered. Gozirra transactions are not atomic; that is, the only guarantee is that all of the messages will be on the server and pending delivery until the commit or the abort. There is no guarantee that all subscribers will receive only either all or none of the messages.

  client.begin();   // Begin the transaction
  client.send( "c1", "Mess1" );
  client.send( "c1", "Mess2" );
  client.send( "c1", "Mess3" );
  client.send( "c1", "Mess4" );
  client.commit();  // Now the server delivers the four messages to the clients
    
  client.begin();   // Begin the transaction
  client.send( "c1", "Mess1" );
  client.send( "c1", "Mess2" );
  client.send( "c1", "Mess3" );
  client.send( "c1", "Mess4" );
  client.abort();  // None of the messages are delivered to any clients
    

Authentication

The server can be provided with an authenticating instance that will validate connections, sends, and subscriptions.

  public class AllowAllAuthenticator implements Authenticator {
    public Object connect( String user, String pass ) throws LoginException {
      // Send back some token here if the user and pass are Ok; otherwise,
      // throw an exception.
    }
    public boolean authorizeSend( Object token, String channel ) {
      // If token is allowed to send to channel, return true.
      // Otherwise, return false.
    }

    public boolean authorizeSubscribe( Object token, String channel ) {
      // If token is allowed to subscribe to channel, return true.
      // Otherwise, return false.
    }
  }

  Server s = new Server( port, new AllowAllAuthenticator() );
    

See the API docs and unit tests for usage information and examples.


To do


0.3.2 -> 0.4.0

The only significant API change that require changes to code using this library is that the Client constructor can now throw a javax.security.auth.login.LoginException in addition to an IOException, and this must be caught.

0.3.1 -> 0.3.2

0.3.0 -> 0.3.1


0.3.2 (Beta) Notes:


This page produced with VIM