Table of Contents

Getting Started With Coadunation 4

Installation 5

Running Coadunation 5

Web 5

Tomcat 5

Coadunation Administration 5

Deployment 6

Daemon Jar 6

Web Application War 6

Deployment Processes 6

Web Applications 7

JNDI 7

Data Sources 7

User Transaction Manager 7

Coadunation Daemon 7

Configuration 7

Security 7

Documentation 8

Daemons 9

Jar File Layout 9

coadunation.xml 9

Daemon Naming 11

Ranges 11

A very basic Coadunation Daemon 12

Libraries and Dependencies 13

Creating an RMI connection to Coadunation 14

Security Manager 14

JacORB 14

Bean Factory Objects 16

Entity Object 16

Factory Manager pattern method naming and standards 16

Factory Object implementation 16

coadunation.xml 16

Time Object 16

coadunation.xml 17

Web Services 18

coadunation.xml 18

WSDL 18

Web Service Interface 18

Web Service Implementation 19

Threading 20

Implementing Threads 20

Daemon Interfaces 20

Standalone Threads 20

coadunation.xml 21

Starting threads on demand 21

CoadunationThread 21

Security 22

Thread Management Pattern 22

Security 22

JNDI 23

java:comp 23

java:network 23

Using the Timer Daemon 24

Registering an Event 24

Handling an Event 24

API 24

Using the Command Line Tool 24

Registering an Event 24

List Events 25

Delete Event 25

Using the Service Broker Daemon 26

Registering a Service 26

Retrieving a Service 26

Retrieving multiple Services 26

Removing a Service 26

API 26

Using the Command Line Tool 27

Registering a Service 27

Retrieve Service 27

Deleting a Service 27

Using the Jython Daemon 28

Running a script 28

Registering a script 28

Using the Command Line Tool 28

Registering Scripts 28

Running Scripts 29

Using the Deployment Daemon 30

Deploying a Daemon 30

Uploading a File 30

Using the Command Line Tool 30

Uploading a Daemon 30

Uploading a file 30

Using the Message Service 31

Asynchronous RPC Messages 31

Server side implementation 31

Client side implementation 31

Text Message 32

Server side implementation 32

Client side implementation 33

Using the Command Line Tool 34

Listing Named Queues 34

List messages with a named queue 34

Purge a named queue of all its message 35

Building the source 36

Configuration 37

XML Configuration 37

Object 37

Entry 38

Data-source Support 38

XML Configuration 38

DB Source Manager 38

Hibernate Configuration 39

XML Configuration 39

Use 39

Adding Distributed Environment Configurations 39

Name Service Store 40

Getting Started With Coadunation


Contained within this document are some basic tutorials which should allow you to get Coadunation up and running quickly and easily.


Installation

Requires Java JDK 1.5.

Follow these steps to install a primary Coadunation instance:

Running Coadunation

To run Coadunation on Windows or any Unix based OS simply navigate to the bin folder within your installation using the command prompt and run either the run.bat or run.sh file based on OS. Note: run.bat is for Windows and run.sh is for any Unix based OS.



Web

Once a Coadunation instance has been started it is possible to access the embedded Tomcat Daemon. This daemon is normally bound to port 8080. Simply open a browser and point it at http://[host name]:8080. Doing this brings up the home page for Coadunation, which offers links to the Tomcat administration, the Coadunation Administration console and documentation.

Tomcat

  1. Go to the URL http://[host name]:8080.

  2. Click on the tomcat link.

  3. Enter a user name and password that has been configured to access the management frontend. The default of admin and 112233 will work on a stock system. To change this look at the user configuration section.

  4. Once the correct user name and password has been entered the Tomcat management page will appear.

Note: It is possible to deploy a war file using the tomcat management frontend, but once the Coadunation instance is restarted these applications will be lost. Instead use the standard deployment process of copying the war file to the Coadunation deploy directory. Coadunation will take care of the rest.

Coadunation Administration

The console supplies the ability to look at interact with all the deployed MX Beans, Daemons and Web Services.

  1. Go to the URL http://[host name]:8080.

  2. Click on the “Coadunation Admin” link.

  3. Enter a user name and password that has been configured to access the management frontend. The default of admin and 112233 will work on a stock system. To change this look at the user configuration section.

  4. Once the correct user name and password has been entered the Coadunation Admin console will appear.



Deployment

Coadunation provides auto deployment for daemons and web applications. It expects all daemons and web applications to be self contained in a jar or war file. This means that if the code replies on another library that is not provided by Coadunation, that it must be included in the war or jar file.

Daemon Jar

The daemon jar file must contain all the compiled classes for the daemon plus all the libraries that are not provided by Coadunation. The libraries must be included in the base of the jar and not in any sub directory. For an example look at the sample projects provided with the Coadunation distribution.

Web Application War

Web applications must be deployed in war files. These war files do not differ in any way from traditional Application server war files, as Tomcat is used to run the Web Applications.

Deployment Processes

Deployment:

To deploy a daemon or web application copy the daemon jar or web war to the Coadunation deploy directory. This can be done before starting Coadunation or while it is running.

Un-deployment:

To un-deploy a daemon or web application simply remove the jar or war from the Coadunation deploy directory. This can be done while Coadunation is running or after it is stopped.

Re-deployment:

To re-deploy a daemon or web application simply replace the jar or war file in the deploy directory. If Coadunation is running the existing instance will be stopped and the new instance started.



Web Applications

Coadunation supports standard web applications through the use of Tomcat. This means that it is possible to write a web based application that interacts seamlessly with any Coadunation deployed daemon. This is because any deployed application has access to Coadunations JNDI and any exposed Coadunation resources; making it possible to resolve any daemon or any JNDI bound resource, and providing central configuration, security, transactions and more.

Anything accessible to a daemon is accessible to a Web Application.

JNDI

Coadunation exposes its own JNDI context to any servlets or JSP pages. This makes it possible to resolve data sources, the user transaction manager and Coadunation daemons from an Web Application. There is no need setup a context to do it on deployment of an application, as is the traditional mechanism with Tomcat.

Data Sources

The following example gets a reference to the standard HsqlDB data source that comes with every Coadunation instance.

// intanciate a context

Context context = new InitialContext();

java.sql.DataSource ds = (java.sql.DataSource)context.lookup(“java:comp/env/jdbc/hsqldb”);


User Transaction Manager

If a web application wishes to manage a transaction than it can get a reference to the transaction manager in Coadunation as follows.

// Instanciate a context

Context context = new IntialContext();

UserTransaction ut = (UserTransaction)context.lookup(“java:comp/UserTransaction”);



Coadunation Daemon

It is possible to get a connection to any Coadunation daemon using JNDI. The process is the same as a data source lookup except it returns an RMI reference that can than be narrowed and than called appropriately. The code below uses the MessageService as an example.

// Instanciate a context

Context context = new IntialContext();

Object ref = context.lookup(“message/MessageService”);

MessageService messageService = (MessageService)PortableRemoteObject.narrow(ref,

MessageService.class);

Configuration

Coadunation implements centralized configuration, and makes this available to any Web Applications. This means that when implementing a web application, there is now the possibility of storing configuration information in the web war and instance configuration in Coadunations configuration.

For more information on using the Configuration objects look at the section titled Configuration.

Security

Coadunation implements container based security. That means that a user accessing a container must have the appropriate rights in order to perform an action. This same security is carried over into the Tomcat Daemon. What this means is that for a web application to access a Coadunation daemon, it must first authenticate the user. Once a user has an authenticated session that user will than be able to access daemons and makes call onto them. This means that Coadunation implements Single Sign On (SSO). This also means that an application will not have to implement its own security module as it will be provided for by Coadunation.

Coadunation currently supports the following types of authentication (More options will be available in time):

  1. Form Based Authentication

    Form based authentication relies on a form requesting authentication information from the user. In Coadunation this is currently limited to Username and Password.
    http://java.sun.com/j2ee/1.4/docs/tutorial/doc/Security5.html

  2. Basic Authentication
    Like Form based authentication basic authentication requires the user to supply identification information, but unlike form based authentication this information is gathered by the users browser and posted when required.

Note: For more information on setting up security in a J2EE web based application look at the following tutorial

http://java.sun.com/j2ee/1.4/docs/tutorial/doc/Security5.html.

Documentation

The Coadunation distribution comes with a example web application. This can be found in the samples directory of the distribution. This sample is there to give people an under standing of how to interact with Coadunation using a web application, it is not there to train users on JSP, and Servlets. More on that can be found online at: http://java.sun.com/j2ee/1.4/docs/tutorial/doc/.

Note: Coadunation does not implement EJB's. This means that traditional Enterprise beans are not available but the same functionality and more, is available via the daemon container framework implemented by Coadunation.

Daemons

A Coadunation daemon is deployed in a self contained jar file. This means that if there are any libraries that the daemon is dependant on, that are not provided by Coadunation, they must be included in the deployment jar.

This jar file also contains the deployment information for the daemons it contains. This information is stored in a coadunation.xml file within the /META-INF directory of the jar.

Jar File Layout

The jar file must be laid out in the following manor:

/

/META-INF

/META-INF/coadunation.xml

/Example.jar

/com/rift/example.class



In the above example the jar consisted of a META-INF directory that contained the “coadunation.xml”, an “Example.jar” or library and a compiled class. This is the standard layout for Coadunation daemon files

coadunation.xml

This file defines the deployment information for a daemon. It describes the interfaces that must be exposed by RMI, and Locally, JNDI bindings, the web services, transaction information, caching information, user information, security information, threading etc.

The file contents are broken down as follows:

<!-- The base element for the file-->

<coadunation version=”1” name=”This is the name of the daemon”>

<description>The description of the daemon</description>

<!-- The basic daemons that will be started and bound to JNDI -->

<beans>

<!-- a bean definition -->

<bean>

<interface>The interface that will be exposed for this bean</interface>

<class>The class that implements the interface</class>

<bindName>The jndi name to use “example/test1”</bindName>

<role>The role that a user must be able to access in order to access the container</role>

<username>The name of the user that this daemon will run as. This is optional and only required

if the class implements the BeanRunnable interface.</username>

<classes>The classes such as factory objects that must get containers</classes>

<cache_by_key>true or false, set if factory objects are going to be used with unique key

identifiers</cache_by_key>

<cache_timeout>The number of milliseconds to cache an entry</cache_timeout>

<transaction>True if container based transaction are going to be used.</transaction>

<!-- If this bean is going to have other threads they are configured here -->

<thread>

<class>The name of the class implementing the basic thread </class>

<username>The name of the user this thread will run as</username>

<number>The size of the thread pool for this thread</number>

</thread>

</bean>

</beans>

<!-- The jmx daemons that will be bound to the JMX manager and JNDI -->

<jmxbeans>

<!-- a bean definition -->

<bean>

<interface>The interface that will be exposed for this bean</interface>

<class>The class that implements the interface</class>

<bindName>The jndi name to use “example/test1”</bindName>

<objectName>The name to bind the object to the JMX manager with

com.test:type=JMXBean1”</objectName>

<role>The role that a user must be able to access in order to access the container</role>

<username>The name of the user that this daemon will run as. This is optional and only required

if the class implements the BeanRunnable interface.</username>

<classes>The classes such as factory objects that must get containers</classes>

<cache_by_key>true or false, set if factory objects are going to be used with unique key

identifiers</cache_by_key>

<cache_timeout>The number of milliseconds to cache an entry</cache_timeout>

<transaction>True if container based transaction are going to be used.</transaction>

<!-- If this bean is going to have other threads they are configured here -->

<thread>

<class>The name of the class implementing the basic thread </class>

<username>The name of the user this thread will run as</username>

<number>The size of the thread pool for this thread</number>

</thread>

</bean>

</jmxbeans>

<!-- The web services to expose -->

<webservices>

<webservice>

<path>The path that the web service will be bound to</path>

<class>The class implementing the web service call</class>

<wsdl>The path to the wsdl file resource within the deployed jar.</wsdl>

<role>The role that the caller must have access to</role>

<transaction>True if container based transactions are going to be used.</transaction>

</webservice>

</webservices>

</coadunation>

Daemon Naming

Coadunation auto deploys everything it finds in its deploy directory. This means that deploying something new is simply a matter of copying the jar, containing the new daemon, into the deploy directory and waiting. Coadunation deploys files in order based on the name of the file, they will be un-deployed on shutdown in reverse order. This means that if one daemon must start before another its name should order it before the other.

To make sure daemons load in the appropriate order all jars must be prefixed with a four digit number and a dash. Example:

0010-{Name}

This is very similar to the process ordering found on a Unix box.

Ranges

0000 – 0100 Critical processes such as databases, timers, message services and service brokers.

0100 – 1000 Business Logic related daemons.

1000 - & Anything.

A very basic Coadunation Daemon

To write a Daemon, requires the writing of a Coadunation Bean. This bean will get bound to JNDI and supply access to the daemon. The following tutorial will cover all the steps required to create an absolute bare bones instance, any further expansion is very easy.


Start by creating an empty project in your favorite IDE. In the source root directory create a “META-INF” folder, this is where we will be putting the “coadunation.xml” file that will define the bean.


The basic layout of the “coadunation.xml” file is as follows:


<?xml version="1.0" encoding="UTF-8"?>


<coadunation version="1" name="CoadunationTest">

<beans>

<bean>

<bindName><!-- Bean name --></bindName>

<role><!-- role --></role>

<username><!-- username --></username>

</bean>

</beans>

</coadunation>


There are an additional 2 parameters required to create the most basic Coadunation bean possible, these parameters are <interface><!-- bean interface --></interface> and <class><!-- interface implementation --></class>. You will need to create a package within your source root folder in which the bean interface and interface implementation will be created. Your “coadunation.xml” file will then look something like this:


<?xml version="1.0" encoding="UTF-8"?>


<coadunation version="1" name="CoadunationTest">

<beans>

<bean>

<bindName><!-- Bean name --></bindName>

<role><!-- role --></role>

<username><!-- username --></username>

<interface><!-- bean interface --></interface>

<class><!-- interface implementation --></class>

</bean>

</beans>

</coadunation>


If you wish the bean to be globally available than it must implement java.rmi.Remote and throw java.rmi.RemoteException from all of its interface methods. If you want it to be a local interface than this is not a requirement.:


Example:


package com.test;


import java.rmi.Remote;

import java.rmi.RemoteException;


public interface BeanInterface extends Remote {

public void exampleMethod() throws RemoteException;

}


The interface implementation is where the logic of the bean is located. An example of this follows:


Example:


package com.test;


import java.rmi.RemoteException;


public class BeanImpl implements BeanInterface {


public BeanImpl() {

}


public void exampleMethod() throws RemoteException {

/** Do something. */

}

}


Once you have created both of these files and put them into their respective folders one simply has to build the project and copy the generated .jar file into the Coadunation deploy folder and Coadunation will take care of the rest. A sample daemon can be found within the Coadunation installation under samples. Note: This is a Netbeans project.


Libraries and Dependencies

For a project that is dependent on other libraries such as database, daemons, or utils, one simply has to include these jars in the final deployment jar. This results in a single deployment archive reducing the complexity of the deployment and means that no extra modifications need to be made to a Coadunation instance in order to run another daemon.

Note: The jars that must not be included in the deployment archive are those that get stored in Coadunation's own lib directory.

Creating an RMI connection to Coadunation

The Coadunation RMI connection supports both local and remote connections and is easy to implement.


You will need to include the CoadunationClient.jar file within your class path.


The required Java imports are:


import java.util.Hashtablel

import javax.naming.Context;

import javax.naming.InitialContext;

import javax.rmi.PortableRemoteObject;


The code to create the connection is as follows:


Hashtable env = new Hashtable();

env.put(Context.INITIAL_CONTEXT_FACTORY,

"com.rift.coad.client.naming.CoadunationInitialContextFactory");

env.put(Context.PROVIDER_URL,/** localhost:2000 String */);

env.put("com.rift.coad.username",/** Username String */);

env.put("com.rift.coad.password",/** Password String */);

Context ctx = new InitialContext(env);


Object obj = ctx.lookup("java:network/env//** Coadunation server ID *///** Bean name */");

/** Bean Interface e.g. com.rift.coad.BeanInterface */ beanInterface =

(/** Bean Interface */)

PortableRemoteObject.narrow(obj,

/** Bean Interface.class */);


Once you have inserted the code and made the appropriate changes, by replacing the comments with the necessary details, you will have your first Coadunation RMI connection.


Security Manager


This functionality relies on the ability to dynamically download the generated stub code. To do this the security manager must be enabled. If the code is running in a standalone environment, and this does not work, there is a good chance the security manager is not enable.


To enable the security manager add the following to the command line of the java environment.


Windows


set JAVA_OPTS=%JAVA_OPTS% -Djava.security.policy==C:\server\policy\file

set JAVA_OPTS=%JAVA_OPTS% -Djava.security.manager


Unix


JAVA_OPTS=$JAVA_OPTS -Djava.security.policy==/server/policy/file

JAVA_OPTS=$JAVA_OPTS -Djava.security.manager


The server policy file contains the policies used by the java environment to see if objects have the rights to access one another. Use the following if you are not concerned about this and just want to get it running.

grant {

permission java.security.AllPermission;

};


For more information on the JDK security manager visit: http://java.sun.com/j2se/1.4.2/docs/guide/security/.


JacORB

Because Coadunation implements RMI/IIOP using JacORB, all clients making an RMI connection to it, will have to use it as well. This simply means linking with the libraries, the CoadunationClient library will take care of the rest.

JacORB and its library dependancies are provided as part of the clientlib directory. They are as follows:

Bean Factory Objects

Coadunation supports two types of factory objects. Unique key based factory objects and time based factory objects. Key based factory objects work by caching an object identified by a unique key, for a set period of time. Time based factory objects cache an object purely on time.

A key based factory object would be used to manipulate an identifiable unit such as a mailbox, account or file; while a time based factory object could be used as a session based connection such as a database connection.

The cache period time in both cases is the period of time without any activity that the object must be cached for before being removed. Activity on the object will length the time the object are in memory.

A basic sample of a bean factory can be found within the Coadunation installation under samples. Note: This is a Netbeans project.

Entity Object

To implement an entity object factory pattern there must some unique identifying information for the object. If this is not a single value than a composite key object needs to be constructed. This object must be serializable and implement the equals and hashId methods.

Factory Manager pattern method naming and standards

The management interface must follow the following rules in order to act as a factory object.

Factory Object implementation

The factory object must be implemented as follows.

coadunation.xml

The coadunation file in the META-INF directory needs to be modified to support the factory interface. The following parameters must be added to the bean implementing the the factory methods.

<cache_by_key>true</cache_by_key>

<cache_timeout><!-- a cache time in milli seconds.--></cache_timeout>

<!-- List the classes that get returned as factory objects -->

<classes><!--a name of a class that will get return as a factory object --></classes>

<classes><!--a name of a class that will get return as a factory object --></classes>


If the cache_timeout is set to zero it will remain in memory until the daemon is un-deployed or until the instance is stopped.

Time Object

The time object is very simple to implement. The factory management interface must simply return a reference to the object that must be timed. This will generally be a new object each time. The container will than wait until the object has not been modified or touched for a given period of time before removing it.

The management method names should not use, add, create, get, find, remove or delete to reference the object, use connect instead.

coadunation.xml

The coadunation file in the META-INF directory needs to be modified to support the factory interface. The following parameters must be added to the bean implementing the the factory methods.

<cache_timeout><!-- a cache time in milli seconds.--></cache_timeout>

<!-- List the classes that get returned as factory objects -->

<classes><!--a name of a class that will get return as a factory object --></classes>

<classes><!--a name of a class that will get return as a factory object --></classes>


If the cache_timeout is set to zero it will remain in memory until the daemon is un-deployed or until the instance is stopped.

Web Services

Coadunation supports web services as a means to communicate with a daemon. These web services are exposed via a web server which by default runs on port 8085(This is configurable). To implement a web service follow the following rules:

coadunation.xml

To add a web service to the coadunation.xml file add the following section:

<webservices>

<webservice>

<path><!-- path on web server, the end point it will end up being http://server/path--></path>

<class><!-- the class implementing the WSDL interface --></class>

<wsdl><!-- the path to the WSDL file --></wsdl>

<role><!-- the role that is required to access this web service --></role>

</webservice>

</webservices>



WSDL

Here follows a WSDL example, please note, that the end point address is over ridden when loaded in to a Coadunation instance.

<?xml version="1.0" encoding="UTF-8"?>


<definitions name="WebService" targetNamespace="urn:WebService/wsdl" xmlns:tns="urn:WebService/wsdl" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">

<types/>

<message name="WebServiceSEI_helloWorld">

<part name="String_1" type="xsd:string"/></message>

<message name="WebServiceSEI_helloWorldResponse">

<part name="result" type="xsd:string"/></message>

<portType name="WebServicePortType">

<operation name="helloWorld" parameterOrder="String_1">

<input message="tns:WebServiceSEI_helloWorld"/>

<output message="tns:WebServiceSEI_helloWorldResponse"/></operation></portType>

<binding name="WebServiceSEIBinding" type="tns:WebServicePortType">

<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc"/>

<operation name="helloWorld">

<soap:operation soapAction=""/>

<input>

<soap:body use="literal" namespace="urn:WebService/wsdl"/></input>

<output>

<soap:body use="literal" namespace="urn:WebService/wsdl"/></output></operation></binding>

<service name="WebService">

<port name="WebServiceSEIPort" binding="tns:WebServiceSEIBinding">

<soap:address location="http://localhost:8085/WebServiceTest"/></port></service></definitions>


Note: It is possible and recommended to build the WSDL files from the interface definition rather than hand writing them. This can be done simple by using Ant and Axis 1.4. The example below is an extract from an ant build file..


<target name="-pre-jar">

<path id="wsdl.classpath">

<pathelement location="axis jar location"/>

<pathelement location="axis ant jar location"/>

<pathelement location="apache commons logging jar"/>

<pathelement location="log 4j jar location"/>

<pathelement location="apache commons discovery jar"/>

<pathelement location="axis rpc jar"/>

<pathelement location="axis wsdl jar"/>

<pathelement location="a path to the directory in which the compiled interface can be found"/>

</path>

<taskdef resource="axis-tasks.properties" classpathref="wsdl.classpath"/>

<axis-java2wsdl

classname="com.Example.WebService"

location="http://localhost:8080/Example/WebService"

namespace="com.Example"

output="${build.classes.dir}/com/Example/WebService.wsdl">

</axis-java2wsdl>

</target>


For more information on this visit http://ws.apache.org/axis and for java2wsdl information visit http://ws.apache.org/axis/java/ant/axis-java2wsdl.html.

Web Service Interface

The web service interface must inherit from java.rmi.Remote and implement the methods defined in the WSDL file.

public interface WebServiceSEI extends java.rmi.Remote {

/**

* This method will be called to test the web service end point interface.

*

* @param msg The string containing the message for the server.

* @return The containing the message from the server.

*/

public String helloWorld(String msg);

}


Web Service Implementation

public class WebService implements WebServiceSEI {

/**

* Creates a new instance of WebService

*/

public WebService() {

}

/**

* This method will be called to test the web service end point interface.

*

* @param msg The string containing the message for the server.

* @return The containing the message from the server.

*/

public String helloWorld(String msg) {

System.out.println(msg);

return “Test message”;

}

}


Threading

Coadunation supports the ability to run user bound threads. These are threads that are know to Coadunation and have a user associated with them. If no user is associated with a thread, that thread will not be able to access another container. Note: Threads that are not known to Coadunation will not be notified of a shutdown but simply destroyed leaving no room to clean up. There are ways around this involving thread management patterns that will be described later.

Threads in Coadunation do not process using the standard run method they instead supply a process method that works in conjunction with a terminate method. The process method is called to perform the thread processing, the terminate to notify the thread that it has been requested to stop processing.

Note: If a thread does not respond to the terminate method with in a configured time, the thread stop method is called, resulting in thread death and no time to clean up.

A sample daemon interface based thread can be found within the Coadunation installation under samples. Note: This is a Netbeans project.

Implementing Threads

There are two main ways of implementing threads within a Coadunation daemon. The first is by turning a daemon interface into a thread, the second by implementing a stand alone thread that can be started as a single entity or a pool.

Daemon Interfaces

A daemon interface can be turned into a thread my implementing the BeanRunnable interfaces on the final implementation class. This requires the implementation of the process and terminate methods.

Example:

import com.rift.coad.lib.bean.BeanRunnable;


class DaemonInterfaceImpl implements DaemonInterface, BeanRunnable {


/**

* The process method

*/

public void process() {

/* perform the processing until terminate is called */

}

/**

* The terminate method

*/

public void terminate() {

/* notify thread that it has been terminated and must shut down */

}

};

Standalone Threads

To implement a standalone thread extend the BeanThread and implement the process and terminate methods.

Example:

import com.rift.coad.lib.bean.BeanThread;


class StandaloneThread extends BeanThread {


/**

* Must implement a constructor that throws Exception.

*/

public StandaloneThread() throws Exception {

/* setup the environment */

}

/**

* The process method

*/

public void process() {

/* perform the processing until terminate is called */

}

/**

* The terminate method

*/

public void terminate() {

/* notify thread that it has been terminated and must shut down */

}

};


coadunation.xml

The daemon interface thread and the standalone threads must run as a user, and in the case of the standalone thread the number of threads must be specified. This is done through the coadunation.xml file.

<beans>

<bean>

<interface><!-- path to the interface --></interface>

<class><!-- path to the implementation class --></class>

<classes><!-- Factory object path --></classes>

<cache_by_key><!- if true cache the key defined methods --></cache_by_key>

<cache_timeout><!- The time out in milli seconds --></cache_timeout>

<bindName><!-- Name of bean to be bound to JNDI --></bindName>

<role><!-- The role describing the access permissions --></role>

<username><!-- The user the daemon interface thread will start as--></username>

<thread>

<class><!-- Path to thread implementation thread--></class>

<username><!-- The name of the user--></username>

<number><!-- The number of threads to start--></number>

</thread>

</bean>

</beans>


Starting threads on demand

Coadunation does support the ability to start threads on demand. This functionality is supplied by the CoadunationThread object. Simply extend it and implement both the process and terminate methods appropriately. Than call start on the the thread when required. The start method supplied by the CoadunationThread takes a user-name. This is the name of the user that the thread must run as. In order to call start on the thread the current thread must be granted the write to that role.

CoadunationThread

// imports

import com.rift.coad.lib.thread.CoadunationThread;


/**

* The implementation of the on demand thread.

*/

public class OnDemandThread extends CoadunationThread {

/**

* The constructor must throw an Exception

*/

public OnDemandThread() throws Exception {

}

/**

* The processing method

*/

public void process() throws Exception {

/* thread processing */

}



/**

* This method will be implemented by child objects to terminate the

* processing of this thread.

*/

public synchronized void terminate() {

/* terminate the thread processing */

}

}


// starting the thread

OnDemandThread thread = new OnDemandThread();

thread.start(/* the name of the user */);


Security

The thread starting the Coadunation thread instance must have the rights to do so. This is controlled by an entry in the configuration file.

<object name="com.rift.coad.lib.thread.ThreadGroupManager">

<entry key="role" type="string">

<!-- the name of the role that the thread starting the on demand thread must have access to -->

</entry>

</object>


Thread Management Pattern

There are various circumstances where using only Coadunation user based threads is not going to work. Such as embedding Jakata or another daemon that has its own threading. Under these circumstances the developer will have to use the thread management pattern.

This pattern works by implementing a single user bound coadunation thread. (This can be anyone of the available Coaduantion threads. ) Its role will be to start the processing of the embedded daemons threads and when required terminate the daemon.

Security

The embedded daemons threads will not be able to access another container, through there are ways around this. Using the interceptor framework supplied by Coadunation will make it possible to assign a none Coadunation based thread an appropriate user. This is normally done by supplying user authentication data to the framework, such as user name and password, thus enabling the framework to assign the current thread an active session id, so that it can be validated against other containers.



JNDI

Coadunation has its own implementation of JNDI. This is broken into two URL patterns java:comp and java:network. The java:comp base falls within the process and the java:network is scoped within the Coadunation cluster. This means anything added to java:comp will only be accessible to things running within that process such as database source, user transaction managers and local interfaces. Where as the java:network base is accessible to to any daemon within a Coadunation cluster.

java:comp

The java:comp environment is divided into a global process environment, this covers data source added in the configuration file and the user transaction manager. There is a second level that is scoped within a daemon. Any entry added here such as a local interface or a data source added by code is only accessible to the code within that daemon.

Example:

// a data source that could be available to that processing environment

DataSource ds = (DataSource)context.lookup("java:comp/env/jdbc/test");


// a local interface only available within a daemon

com.test.BeanInterface beanInterface = (com.test.BeanInterface)

context.lookup("java:comp/env/bean/testbean");


java:network

The java:network environment is defined by the cluster. The basic url is as follows java:network/env/instanceid/interface/name.



Example:

If a entry in a cluster is defined by the name Test than the url to get to a interface named TestingInter would be as follows.

java:network/env/Test/TestingInter


TestingInter obj = (TestingInter)

PortableRemoteObject.narrow(context.lookup("java:network/env/Test/TestingInter"),

TestingInter.class);



Lookups do not have to supply the entire URL when performing a lookup on a network URL, only the relative path is required if the entry is found within the same process. This is supported as local interfaces are not accessible to anything outside of the daemon.

Example:

TestingInter obj = (TestingInter)

PortableRemoteObject.narrow(context.lookup("TestingInter"),TestingInter.class);

Using the Timer Daemon

The timer daemon supplies the ability to register an event for a specific time. When this time is reached the timer daemon will make a call onto the service implementing the timer event handler, identified by the JNDI name for that event. It passes to the event handler the id of the event identified by a serializable object.

Registering an Event

To register an event with the timer first narrow, and than register the event as follows:

com.rift.coad.daemon.timer.Timer timer =

(com.rift.coad.daemon.timer.Timer)

PortableRemoteObject.narrow(obj,

com.rift.coad.daemon.timer.Timer.class);

timer.register(“jndi url of target”,10,12,13

,24,(Serializable)"id for event, eg end of trading",true);


Handling an Event

To handle an event, a daemon must simply implement the event handler interface.

// imports

import com.rift.coad.daemon.timer.TimerEventHandler;

import com.rift.coad.daemon.timer.TimerException;


public class /* daemon name */ implements TimerEventHandler {

/**

* Implementation of the processEvent method.

*

* @param event Identifying object.

*/

public void processEvent(Serializable event) throws RemoteException, TimerException {

.

.

}


}

API

Jdoc for the timer daemon is available on line via the web site and is supplied with Coaduntion install.


Using the Command Line Tool

The command line tool comes with coadunation and both the timer.bat and timer.sh files for running it are found in the bin folder of Coadunation. The Command Line Tool allows a user to register an event, list all the events and delete a specific event via the command line.

Registering an Event

In order to register an event through the command line you need to supply several fields. These required fields are as followed.

-r This is called to register an event.

-m This is to be followed by the month and can be -1 if it is to recur once monthly.

-da This is to be followed by the day of the month and can be -1 if it is to recur on a daily basis.

-ho This is to be followed by the hour and can be -1 if it is to recur on a hourly basis.

-mi This is to be followed by the minute and can be -1 if it is to recur every minute.

-j This is to be followed by the JNDI for the daemon that is to be called.

-s This is to be followed by the host name and port e.g. Test:2000.

-u This is to be followed by the JNDI for the Timer Daemon.

List Events

In order to list all stored events supply the following fields:

-l This is called to list all the events.

-j This is to be followed by the JNDI for the daemon that is to be called.

-s This is to be followed by the host name and port e.g. Test:2000.

-u This is to be followed by the JNDI for the Timer Daemon.

Delete Event

In order to delete an event supply the following fields:

-d This is called when you want to delete an event.

-id This is to be followed by the ID of the event that you wish to delete.

-j This is to be followed by the JNDI for the daemon that is to be called.

-s This is to be followed by the host name and port e.g. Test:2000.

-u This is to be followed by the JNDI for the Timer Daemon.

Using the Service Broker Daemon



The Service Broker Daemon stores the JNDI for daemon's and then associates that JNDI with a list of services that the daemon can perform. A single JNDI or multiple JNDI's can then be retrieved from the database using a list of appropriate services.



Registering a Service

To register a service with the Service Broker first narrow, and then register the event as follows:



com.rift.coad.daemon.servicebroker.ServiceBroker beanInterface =

(com.rift.coad.daemon.servicebroker.ServiceBroker)

PortableRemoteObject.narrow(obj,

com.rift.coad.daemon.servicebroker.ServiceBroker.class);


beanInterface.registerService("JNDI",serviceList);

Retrieving a Service

To retrieve a service from the Service Broker first narrow, and then retrieve the service as follows:



com.rift.coad.daemon.servicebroker.ServiceBroker beanInterface =

(com.rift.coad.daemon.servicebroker.ServiceBroker)

PortableRemoteObject.narrow(obj,

com.rift.coad.daemon.servicebroker.ServiceBroker.class);


String JNDI = beanInterface.getServiceProvider(serviceList);

Retrieving multiple Services



To retrieve multiple services from the Service Broker first narrow, and then retrieve the services as follows:



com.rift.coad.daemon.servicebroker.ServiceBroker beanInterface =

(com.rift.coad.daemon.servicebroker.ServiceBroker)

PortableRemoteObject.narrow(obj,

com.rift.coad.daemon.servicebroker.ServiceBroker.class);


List JNDI = beanInterface.getServiceProviders(serviceList);


Removing a Service

To remove a service from the Service Broker first narrow, and then remove the service as follows:



com.rift.coad.daemon.servicebroker.ServiceBroker beanInterface =

(com.rift.coad.daemon.servicebroker.ServiceBroker)

PortableRemoteObject.narrow(obj,

com.rift.coad.daemon.servicebroker.ServiceBroker.class);


beanInterface.removeServiceProviders("JNDI",serviceList);


API

Jdoc's for the Service Broker Daemon are available from the web site and are supplied with the Coaduntion install.

Using the Command Line Tool

The command line tool comes with coadunation and both the servicebroker.bat and servicebroker.sh files for running it are found in the bin folder of Coadunation. The command line tool gives users the ability to register services, retrieve service JNDI's and delete services.

Registering a Service

In order to register a service supply the following fields:

-r This is called when you want to register a new service.

-S This is to be followed by the Service that the Daemon is to perform and there can be multiple in a single statement.

-j This is to be followed by the JNDI of the Daemon that performs the service.

-s This is to be followed by the host name and port e.g. Test:2000.

-u This is to be followed by the JNDI for the Timer Daemon.

Retrieve Service

In order to retrieve a service supply the following fields:

-o This is to be called when you want to retrieve a single JNDI for a service or services.

-m This is to be called when you want to retrieve multiple JNDIs for a service or services.

-S This is to be followed by the Service that the Daemon is to perform and there can be multiple in a single statement.

-s This is to be followed by the host name and port e.g. Test:2000.

-u This is to be followed by the JNDI for the Timer Daemon.

Deleting a Service

In order to delete a service supply the following fields:

-d This is to be called when you want to delete a service.

-S This is to be followed by the Service that the Daemon is to perform and there can be multiple in a single statement.

-j This is to be followed by the JNDI of the Daemon that performs the service.

-s This is to be followed by the host name and port e.g. Test:2000.

-u This is to be followed by the JNDI for the Timer Daemon.

Using the Jython Daemon

The Jython Daemon is an implementation of Jython within Coadunation, this gives users the ability to run Python scripts within Coadunation. The Jython Daemon also includes Jython Timer which is an implementation of a TimerEventHandler which gives the user the ability to run scripts using the Timer Daemon.

Running a script

There are 2 methods that allow you to accomplish this, they are both called “runScript”. The difference however is that the once instance of runScript simply runs the script and returns a value from the script in whichever format suits you. The second instance will do this as well however it will also give you the ability to set values within the script itself. Below are 2 examples of a call to both of the above mentioned methods. Note: As with other Daemons we must first perform a narrow.

Example 1:

com.rift.coad.daemon.jython.JythonDaemon beanInterface =

(com.rift.coad.daemon.jython.JythonDaemon)

PortableRemoteObject.narrow(obj,

com.rift.coad.daemon.jython.JythonDaemon.class);


returnedValue = beanInterface.runScript(“ExampleScript”,”varA”,Class.forName(“java.lang.Integer”));


Example 2:



com.rift.coad.daemon.jython.JythonDaemon beanInterface =

(com.rift.coad.daemon.jython.JythonDaemon)

PortableRemoteObject.narrow(obj,

com.rift.coad.daemon.jython.JythonDaemon.class);


returnedValue = beanInterface.runScript(name,returnValue,Class.forName(“java.lang.Integer”),

arguments);


Registering a script

There is a method that gives a user the ability to remotely upload scripts to the Coadunation instance, this method is “registerScript”. As with calling other Daemons a narrow must be performed first.



com.rift.coad.daemon.jython.JythonDaemon beanInterface =

(com.rift.coad.daemon.jython.JythonDaemon)

PortableRemoteObject.narrow(obj,

com.rift.coad.daemon.jython.JythonDaemon.class);


beanInterface.registerScript(“String containing the contents of a script file”,”The name that the script is to be called”);

Using the Command Line Tool

The command line tool comes with coadunation and both the jython.bat and jython.sh files for running it are found in the bin folder of Coadunation. The command line tool gives users the ability to register scripts and run them.

Registering Scripts

In order to register a script supply the following fields:

-r This is called when you need to register a script.

-l This is to be followed by the full path of the local script.

-n This is to be followed by the name of the script. Note: in windows this is to include the file extension “.py”

-s This is to be followed by the host name and port e.g. Test:2000.

-u This is to be followed by the JNDI for the Timer Daemon.

-U Followed by the user-name to authenticate the call with.

-P Followed by the password to authenticate this call with.

Running Scripts

In order to run a script supply the following fields:

-e This is called when a user wishes to execute a script, it is followed by the name of the script to execute.

-p This is to be followed by the full path to the properties file which contains properties for the script. This field is optional.

-j This is to be followed by a java class and will determine the type that is passed back by the daemon after running the script. e.g “java.lang.Integer”

-v This is to be followed by the name of the variable who's end value is to be returned by the daemon after running the script.

-s This is to be followed by the host name and port e.g. Test:2000.

-u This is to be followed by the JNDI for the Timer Daemon.

-U Followed by the user-name to authenticate the call with.

-P Followed by the password to authenticate this call with.

Using the Deployment Daemon

The Deployment Daemon gives a user the ability to remotely deploy and upload files to a Coadunation server.

Deploying a Daemon

This is done by call the “daemonDeployer” method, this will then upload a Daemon to the deployment folder within the Coadunation instance. This like all other daemon call first requires that the user perform a narrow.


DeploymentDaemon beanInterface =

(DeploymentDaemon)

PortableRemoteObject.narrow(obj,

com.rift.coad.daemon.deployment.DeploymentDaemon.class);


beanInterface.daemonDeployer(“byte[] containing the contents of a daemon”,

example.jar”);


Uploading a File

This is done by calling the “copyFile” method, this method will copy any file to any folder existing folder on the Coadunation instance. This like all other daemon call first requires that the user perform a narrow.



DeploymentDaemon beanInterface =

(DeploymentDaemon)

PortableRemoteObject.narrow(obj,

com.rift.coad.daemon.deployment.DeploymentDaemon.class);


beanInterface.copyFile(“byte[] containing the contents of a daemon”,”example.txt”,”C:\test\”);

Using the Command Line Tool

The command line tool comes with coadunation and both the deploy.bat and deploy.sh files for running it are found in the bin folder of Coadunation. The command line tool gives users the ability to deploy a daemon and a file.

Uploading a Daemon

In order to deploy a daemon supply the following fields:

-d This is called when you want to deploy a daemon.

-l This is the full location of the local Daemon that is to be deployed.

-n This is the name that the Daemon is to be called. Note on a windows system this is to include the extension “.jar”

-s This is to be followed by the host name and port e.g. Test:2000.

-u This is to be followed by the JNDI for the Timer Daemon.

Uploading a file

In order to upload a file supply the following fields:

-f This is to be called when you want to upload a file to the Coadunation server.

-l This is the full location of the local Daemon that is to be deployed.

-n This is the name that the Daemon is to be called. Note on a windows system this is to include the extension “.jar”

-p This it the full path to which the file is to be copied.

-s This is to be followed by the host name and port e.g. Test:2000.

-u This is to be followed by the JNDI for the Timer Daemon.

Using the Message Service

The Coadunation message service allows for asynchronous distributed processing with guaranteed delivery.

Asynchronous RPC Messages

Server side implementation

In order to use the the message service one simply has to make a standard Coadunation bean on the server side.



Below is an example Coadunation bean interface:

package test.server;


import java.rmi.Remote;

import java.rmi.RemoteException;


public interface RPCServerTest extends Remote {


public int testMethod(String msg) throws RemoteException;


}


Below is an example Implementation of the bean interface:


package test.server;


import java.util.Date;

import java.rmi.Remote;

import java.rmi.RemoteException;


public class RPCServerTestImpl implements RPCServerTest {


public RPCServerTestImpl() {

}


public int testMethod(String msg) throws RemoteException {

return msg.length();

}


}

Client side implementation

However on the client side it is necessary to create an asynchronous interface. This will contain all the methods from the server side bean effectively mirroring it but it must always return a String object. It is also necessary for the client side object to extend “AsyncCallbackHandler” and implement the methods “onSuccess(String messageId, String correllationId, Object result) throws RemoteException” and “onFailure(String messageId, String correllationId, Throwable caught) throws RemoteException”. The client side implementation also requires that both “MessageServiceClient.jar” and “CoadunationUtil.jar” be linked into the project.

Below is an example asynchronous interface for the above bean: