Simplest Example

This example is the simplest that we can create because this example don't create any component and don't configure anything, just execute Tubo with default configuration.

Default Tubo configuration, Echo Configuration

Tubo by default create a echo service used to ping the instance. To make this appends by default there are some components preconfigured and a echo flow supporting service.

This service is a socket service listen on a port, when a client connect to this a welcome message is sended to client, and each line than is readed from client is sended back to him. If the line "bye" is readed, a goodbye message is sended to client and the connection is closed.

To support this service two components are created:

  • ServerSocketLineReaderConsumer have the responsability of listen on configured ports, create client connection and activate some event or flag to allow the creation of a welcome message, read input line by line and send back response, close connection.
  • EchoComponent this component have the responability of generate the diferent message responses (hello, goodbye, echo) to client.

Echo Consumer

Consume phase strategy is based on a consumer component ServerSocketLineReaderConsumer which use a ServerSocket listen on a port. When a new connection arrives the component generate a event and begin to read the input stream line by line. Each line generate a new event and when the line readed match with the goodbye word then the goodbye event is generated.

Each event is processed by the consumer life cycle activating an executing a determinated Flow. Event consept is used to show a determinated activity or "event" has happened on some component, in this case on Consumer. To share data the event originator or any component can use Item properties.

Don't forget than Tubo is based on Pipeline Arquitecture. On this Arquitecture a set of nodes (aka Components) are conecteds one to anothers making a king of pipeline or node flow. Each conection between nodes is made of data (aka Item), and each node transform this data. Each Node have an Input and a Output (in a traditional point of view).

Events and properties

This component fire tree kinds of events and use two properties, one to send readed input line to flow, and one to write the output message generated on flow.

NEW_CONNECTION_EVENTThis event is fired when a new connection is created, given the posibility of write a welcome message.
Properties:
SSLINEREADER_INPUT: This property is setted null by Consumer before fire the event.
SSLINEREADER_OUTPUT: This property is used by components on flow to store the output message.
READ_LINE_EVENTThis event is fired when a new line is readed.
Properties:
SSLINEREADER_INPUT: This property is setted with the line readed.
SSLINEREADER_OUTPUT: This property is used by components on flow to store the output message.
GOODBYE_EVENTThis event is fired when a goodbye word is readed. After this event is processed the connection will be closed.
Properties:
SSLINEREADER_INPUT: This property is setted with the line readed.
SSLINEREADER_OUTPUT: This property is used by components on flow to store the output message.
Consumer configuration

This consumer create a socket with client, and consume input line by line. Because the socket between client and consumer is a statefull condition, the consumer assigned will be free when the conection is closed (is implemented in this way, not is the only way!) componentClassname="org.tubo.resource.component.transform.SimpleTransformComponent" type="singleton"

Will see than this consumer is listening at port 6666 with a concurrency of 3 (three client connections can be procesed at time), if the three consumers are busy (because are three connections open) then the next clients they will be able to create connections but will be blocked waiting for next free consumer.

The process cut condition is configured on goodbye-words property. In this case, the connection will finish if client send "bye" or "." words.

<consumer id="tubo-echo-consumer"
    consumerClassname="org.tubo.resource.consumer.serversocketlinereader.ServerSocketLineReaderConsumer"
    type="pooled"
    maxCapacity="3"
    >
    <property>
        <prop-name>ports</prop-name>
        <prop-value>6666</prop-value>
    </property>
    <property>
        <prop-name>goodbye-words</prop-name>
        <prop-value>bye,.</prop-value>
    </property>
</consumer>

Echo Component

This component is really simple, have three executional methods than can be mapped to listeners and two properties, one for input and one for output.

Events and properties
sayHeloThis method is used by the listener of the NEW_CONNECTION_EVENT event.
Properties:
ECHO_OUTPUT: In this property put the Hello Message
executeThis is the default executional method for components, when a component don't listen a particular event this method is executed. This echo component use this method for copy input on output.
Properties:
ECHO_INPUT: Input
ECHO_OUTPUT: Output
sayGoodbyeThis event is fired when a goodbye word is readed. After this event is processed the connection will be closed.
Properties:
ECHO_INPUT: Input
ECHO_OUTPUT: Goodbye message.
Echo Code

This is the code of Echo component.

public class EchoComponent extends BaseComponentImpl {
    public static final String RCS_ID = "$Id: EchoComponent.java 54 2006-11-08 14:02:18Z maldito_orco $";
    private static Log log = LogFactory.getLog(EchoComponent.class);

    public static final String ECHO_INPUT_PROPERTY = "ECHO_INPUT";
    public static final String ECHO_OUTPUT_PROPERTY = "ECHO_OUTPUT";


    public void sayHelo(FlowContext flowContext) throws TuboException {
        flowContext.getItem().setProperty(ECHO_OUTPUT_PROPERTY,"helo");
    }

    public void sayGoodbye(FlowContext flowContext) throws TuboException {
        flowContext.getItem().setProperty(ECHO_OUTPUT_PROPERTY,"goodbye");
    }

    public void execute(FlowContext flowContext) throws TuboException {
        //
        // get item
        Item item = flowContext.getItem();
        //
        // get input
        String input = (String)item.getProperty(ECHO_INPUT_PROPERTY);
        //
        // put input in output
        item.setProperty(ECHO_OUTPUT_PROPERTY,input);
    }
}
Echo Configuration

This is the definition of Echo Component

<component id="tubo-echo-component"
    componentClassname="org.tubo.resource.component.echo.EchoComponent"
    >
</component>

Transformation

Because the Consumer output property name and Echo input property name don't match we need a simple transformation to make input available to Echo and output availavble to Consumer.

Transformation Code

This is the code of Echo component.

public class SimpleTransformComponent extends BaseComponentImpl {
    public static final String RCS_ID = "$Id: SimpleTransformComponent.java 78 2006-12-15 21:37:36Z maldito_orco $";
    private static Log log = LogFactory.getLog(SimpleTransformComponent.class);


    public void execute(FlowContext flowContext) throws TuboException {
        //
        // get item
        Item item = flowContext.getItem();
        //
        //
        int i=0;
        String transform = null;
        do {
            //
            // get i-esima transformation
            String ti = "t"+i;
            transform = (String)item.getProperty(ti);
            //
            // if i-esima transformation is null then is cut condition
            if (transform!=null) {
                //
                // parse transformation
                int inx = transform.indexOf("->");
                String from = transform.substring(0,inx).trim();
                String to = transform.substring(inx+"->".length(),transform.length()).trim();
                //
                // transform
                Object value = item.getProperties().remove(from);
                item.setProperty(to,value);
                //
                // increment i
                i++;
            }
        //
        // check cut condition
        } while (transform!=null);
    }
}
Transformation Configuration

This is the definition of Transformation

<component id="simple-transform"
    componentClassname="org.tubo.resource.component.transform.SimpleTransformComponent"
    type="singleton"
    >
</component>

Echo Flow

A Flow is a pipeline of components with zero, one or more Consumers on beginning and zero, one or more Nodes to execute.

A Node in a flow can be a Component or a Flow.

Flow Configuration
<flow id="tubo-echo-flow">
    <consume>
        <from refId="tubo-echo-consumer" />
    </consume>
    <node-list>
        <!-- transform input ss to input echo-->
        <component-node refId="simple-transform">
            <property>
                <prop-name>t0</prop-name>
                <prop-value>SSLINEREADER_INPUT->ECHO_INPUT</prop-value>
            </property>
        </component-node>
        <!-- execute echo -->
        <component-node refId="tubo-echo-component">
            <listen>
                <event>
                    <action>NEW_CONNECTION_EVENT</action>
                    <execute>sayHelo</execute>
                </event>
                <event>
                    <action>GOODBYE_EVENT</action>
                    <execute>sayGoodbye</execute>
                </event>
                <!-- by default if not defined listens or not matched events, method 'execute' is invoked -->
            </listen>
        </component-node>
        <!-- transform output echo to output ss-->
        <component-node refId="simple-transform">
            <property>
                <prop-name>t0</prop-name>
                <prop-value>ECHO_OUTPUT->SSLINEREADER_OUTPUT</prop-value>
            </property>
        </component-node>
    </node-list>
</flow>