This guide describes all aspects of BambooPipe message queue usage.
In order to utilize BambooPipe effectively, users need to understand two aspects of BambooPipe: programming and administration.
Administration sections include installation, configuration and server startup procedures. Programming sections include an introduction of API and a step by step API example.
Complete reference for programming API can be found in the companion BambooPipe Reference Manual. BambooPipe concepts and features can be found in BambooPipe White Paper.
Content summary:
BambooPipe is downloaded as a zip file. Unzip process creates the top directory BambooPipe. If HTTP server is present, make sure unzip creates top directory BambooPipe under HTTP server's data directory.
Inside BambooPipe directory, there are a HTML file called index.html and four sub-directories: doc, cmd, code and src. Index.html has pointers to all BambooPipe documentation.
doc directory contains BambooPipe documentation.
cmd directory contains scripts to start BambooPipe server. Scripts to run examples are also saved here.
code directory contains Java class files. "bamboo.pipe" package
is the BambooPipe message queue.
Other packages contain examples
and example support classes.
src directory contains Java source files for examples.
Environment variable CLASSPATH must be set to include code directory. For example, if top directory BambooPipe is under c:\ on a Windows NT machine, add "c:\BambooPipe\code" to the end of CLASSPATH.
Since it's a Java RMI server, RMI registry must be started first.
On Windows 95 or Windows NT:
start rmiregistry (Use javaw if start is not available.)
On Solaris:
rmiregistry &
Starting BambooPipe requires two command line parameters: serverName and serverDir. First parameter is serverName. BambooPipe server will register itself in RMI registry with this name. Second parameter, serverDir, is the path name of BambooPipe home directory. This directory should be manually created before startup. BambooPipe server startup searches for a file named as serverName.config in the home directory. If found, the server uses the file as its configuration file. Without a configuration file, BambooPipe server starts with a default queue.
On Windows 95 or Windows NT:
start java bamboo.pipe.BambooPipeImpl
serverName serverDir
On Solaris:
java bamboo.pipe.BambooPipeImpl serverName
serverDir &
By default, a queue has only transient consumers. These consumers receive messages when their logins are alive. A queue does not hold messages for transient consumers. On the other hand, mandatory consumers enjoy guaranteed delivery. If a mandatory consumer has no active login or the login encounters error, the queue holds messages until the consumer opens a valid login to receive again. Mandatory consumers can only be set up by configuration file.
A configuration file is a plain text file with a simple format.
First of all, characters are not case-sensitive in configuration file. For example, "QUEUE" and "queue" are the same.
Configuration file is made up from sections. There are two types of sections, server section and queue section. A file can have only one server section but many queue sections. Server section specifies server wide parameters. Queue section specifies parameters for a queue.
Sections start with a tag like <parameter type=XXXXX name=YYYYY> and ends with a tag like </parameter>. XXXXX must be either system or queue. Name=YYYYY is only used for queue section which specifies name for a queue.
Inside sections, each data line specifies value for one parameter in the format of "parameterName=parameterValue". For example, "interval=4" is a data line for "interval" parameter. Spaces can be added before or after "=" for readability.
An example configuration file:
<parameter type=testServerSection>
queueFail=I
</parameter>
<parameter type=queue name=testQueue1>
</parameter>
<parameter type=queue name=testQueue2>
producerPassword = xxx
retry = 5
interval = 120
mandatory = consumer1
mandatory = consumer2
</parameter>
Valid parameters and their default values are listed in following tables.
Server Section Parameters:
QueueFail | Whether to continue on to other queues when one of the queues failed to recover itself in startup. If continue, failed queue will not exist in the server. |
ErrorLog | File to save error and debug messages. By default, error and debug messages go to stdout. If specified, the file will be created under serverDir. |
Server Section Parameters Values:
Parameter Name | Acceptable Value | Required | System Default |
queueFail | E/I* | N | null |
ErrorLog | String | N | null |
Queue Section Parameters:
producerPassword | Password for a producer to login to the queue. |
consumerPassword | Password for a consumer to login to the queue. |
retry | Numbers of delivery attempts by the queue before invalidating a login. If this is a mandatory consumer's login, the queue will hold messages for the consumer. |
maxRetry | A consumer can specify its own retry limit to overwrite the default value. MaxRetry is the max value that a consumer can specify. |
notifyInterval | Interval between retries in seconds |
maxNotifyInterval | Similarly, a consumer can specify its own interval to overwrite the default value. maxNotifyInterval is the max value that a consumer can specify. |
mandatory | Specify a mandatory consumer. A list of mandatory consumers can be specified by having multiple mandatory parameters. |
checkPointInterval | Interval between database checkpoints. Smaller value speeds up recovery process in startup but use more space on database log file. |
reclaimInterval | Interval that log reclaim thread stays in sleep. If this value is non-zero, reclaim thread will try to reclaim space in database log periodically. Database log essentially becomes a circular file. |
persistent | Whether or not to save messages to database log. When persistent is "No", no mandatory consumer can be specified. |
threshold | max database log size. If specified, the queue will reject messages when log reaches this size. |
Queue Section Parameter Values:
Parameter Name | Acceptable Value | Multiple Allowed 1 | Required | System Default |
producerPassword | String | N | N | null |
consumerPassword | String | N | N | null |
retry | Int(sec)2 | N | N | 3 |
maxRetry | Int(sec)2 | N | N | 6 |
notifyInterval | Int(sec)2 | N | N | 60 |
maxNotifyInterval | Int(sec)2 | N | N | 360000 |
mandatory | String | Y | N | null |
checkPointInterval | Int(sec)2 | N | N | null |
reclaimInterval | Int(sec)2 | N | N | null |
persistent | Y/N | N | N | null |
threshold | Int(MG)3 | N | N | null |
This API consists of a couple of Java RMI interfaces:
bamboo.pipe.BambooPipe
bamboo.pipe.ProducerNotify
bamboo.pipe.Producer
bamboo.pipe.ConsumerNotify
bamboo.pipe.ConsumerConfig
bamboo.pipe.Consumer
In order to use BambooPipe, a client first needs to get a BambooPipe
object. Looking up RMI registry by server name returns this object:
BambooPipe bpObj = (BambooPipe)Naming.lookup("//host/serverName");
A producer opens a login to a BambooPipe queue through the BambooPipe object. A successful login returns a Producer object. Through this object, the producer interacts with the queue. A producer can optionally supply a ProducerNotify object in login. If supplied, the queue will notify the producer of message delivery status.
A consumer opens a login to a BambooPipe queue through the BambooPipe object too. It must pass in a ConsumerNotify object in login. Through this object, the queue notifies the consumer of new messages. A successful login returns a ConsumerConfig object. Through this object, the consumer can config itself but not receive messages.
A new message notification from the queue supplies a Consumer object.
Through this object, the consumer receives messages.
Step 1: Write the client applet.
This applet sends and receives messages on one BambooPipe queue. It
has an internal thread that periodically sends out messages. The inner
class ClientNotifyImpl implements bamboo.pipe.ClientNotify interface for
messages receiving.
package msg.test;
import java.awt.*;
import java.rmi.*;
import java.rmi.server.*;
import bamboo.pipe.*;
public class MsgTest extends java.applet.Applet {
String
message = "";
BambooPipe
bp;
ConsumerConfig bpc;
Producer
bpp;
ClientNotifyImpl ccb;
int
msgCount;
MsgThread
msgThread;
/*
* create the thread which will do the actual work.
*/
public void init() {
msgThread = new MsgThread();
msgThread.start();
}
class MsgThread extends Thread {
public void run() {
int i;
try {
/*
* Create the remote object to handle the consumer notification.
*/
ccb = new ClientNotifyImpl();
/*
* lookup the BambooPipe server through RMI registry. The server
* must be registered as MsgTest.
*/
bp = (BambooPipe)Naming.lookup("//" + getCodeBase().getHost()
+ "/MsgTest");
/*
* login to the queue as producer by a name specified in HTML tag.
*/
System.out.println("queue:"+getParameter("queue")+
" name: "+getParameter("name"));
bpp = bp.producerLogin(getParameter("queue"),
getParameter("name"),
null, null, true);
System.out.println("producer login Ok");
/*
* login to the same queue as a consumer. Pass in the
* ConsumerNotify object.
*/
bpc = bp.consumerLogin(getParameter("queue"),
getParameter("name"),
null, (ConsumerNotify)ccb, true);
bpc.readyReceive();
System.out.println("consumer Login Ok");
/*
* send out 20 messages in a fixed interval.
*/
for (i = 0; i < 20; i++) {
bpp.beginTrans();
bpp.sendObj("Msg #"+i+" from "+getParameter("name"));
bpp.commitTrans();
sleep(5 * 1000);
}
}
catch (Exception
e) {
System.out.println("BambooClient exception: " +
e.getMessage());
e.printStackTrace();
}
} /* run */
} /* class MsgThread */
/*
* The message handler.
*/
public class ClientNotifyImpl extends UnicastRemoteObject
implements ConsumerNotify,
java.io.Serializable
{
public ClientNotifyImpl() throws
RemoteException {
super();
}
public void consumerNotify(Consumer
c) {
Object obj;
try {
c.beginTrans();
while ((obj = c.receiveObj()) != null) {
System.out.println("received msg:"+obj.toString());
}
c.commitTrans();
}
catch (Exception
e) {
System.out.println("BambooClient exception: " +
e.getMessage());
e.printStackTrace();
}
msgCount++;
}
}
}
step 2: Compile the applet
Create a directory MsgTest and save MsgTest.java in the directory.
Compile the class:
javac -d . MsgTest.java
step 3: Generate RMI stubs for ClientNotify remote object
rmic -d . msg.test.MsgTest$ClientNotifyImpl
step 4: create HTML files for two clients
Create a HTML file which can be used for both clients in MsgTest directory.
Make two copies of the
HTML file and save them as tester1.html and tester2.html. Change "name"
parameter in the applet tag in both files to correspond to the file name.
<HTML>
<title>BambooPipe Test</title>
<center> <h1>BambooPipe Test</h1> </center>
<p>
<applet codebase="."
name="tester1"
queue="BPDefault"
code="msg.test.MsgTest"
width=500 height=120>
</applet>
</HTML>
step 5: startup RMI registry and BambooPipe server
Before start, create the server directory "server"
start rmiregistry
start java bamboo.pipe.BambooPipeImpl
MsgTest ./server
step 6: startup appletviewer for both clients
start appletviewer tester1.html
start appletviewer tester2.html
Console windows for both clients will display messages produced by both
clients.
BambooPipe is designed to be light weight and simple to use. This guide demostrate that learning it is easy and fast.