The figure below outlines the high level components that make up a Talon application. 

 

 

Development Artifacts

From an application developer's perspective, authoring an X application involves:

The Application Data Modeler (ADM)

The application data modeler provides an XML based modeling language that generates messages and state as plain old java objects. ADM modeled objects are highly optimized and shield application developers from concerns around serialization, transport and persistence of these objects. 

<?xml version="1.0"?>
<model xmlns="http://www.neeveresearch.com/schema/x-adml" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       namespace="com.example.helloapp"
       defaultFactoryId="1">
    <factories>
      <factory name="HelloDataFactory" id="1"/>
    </factories>
    <messages>
        <message name="HelloRequest" id="1">
            <field name="fromName" type="String" id = "1"/>
        </message>
        <message name="HelloReply" id="2">
            <field name="text" type="String" id = "1"/>
            <field name="count" type="Long" id = "2"/>
        </message>
    </messages>
    
    <entities>
      <entity name="MyState" id="100">
        <field name="counter" type="Long" id = "1"/>
      </entity>
    </entities>
</model>

See Modeling Message and State for more information on modeling messages and state.

Application Event Handlers

From an application developer perspective, a Talon application is essentially a set of event handlers via @EventHandler annotated methods that are bound together by an application entry point class. The application's event handlers are invoked in response to messages or notification events dispatched by the Talon runtime. Event Handlers are single threaded and generally must be non-blocking. A typical message handler will consume a message, perform business logic, may update state, and/or send outbound messages. The Talon runtime handles the underlying plumbing to ensure that the operations of receipt, state updates and outbound sends are atomic and reliable. 

The following shows a minimal Talon application

@AppHAPolicy(value = StateReplication)
public class HelloApp {
    private AepMessageSender sender;

    /**
     * Injected by Talon at creation time. 
     */
    @AppInjectionPoint
    public void setMessageSender(AepMessageSender messageSender) {
        this.messageSender = messageSender;
    }
 
    /**
     * Called by Talon on receipt of a HelloRequest message. 
     */
    @EventHandler
    public void onMessage(HelloRequest helloRequest, MyState state) {
        // update state
        state.setCounter(state.getCounter() + 1);
        // send hello reply
        HelloReply helloReply = HelloReply.create();
        helloReply.setText("Hi There");
        messageSender.sendMessage("hello-replies", helloReply);
    }
 
    /**
     * Invoked by Talon the very first time a message is received
     * by the application to create clean state. From that point forward
     * Talon will ensure that changes to state aren't lost in the event
     * of failover of restart. 
     */
    @AppStateFactoryAccessor
    public IAepApplicationStateFactory getStateFactory() {
        return new IAepApplicationStateFactory() {
            @Override
            final public MyState createState(MessageView view) {
                return MyState.create();
            }
        };
    }
}

See Talon Programming for more information on writing event handlers.

Configuration

X Application code doesn't work directly with the underlying infrastructure components. For example, binding of an application to a particular message bus implementation is a configuration concern. The platform's Domain Descriptor Language (DDL) is the platform's configuration schema. It allows developers to configure a group of related applications in a singe xml-based configuration artifact. Deployment tools such as Robin use this configuration to seed the the platform's configuration repository, where it is then used by Talon VMs when they are launched. 

<model>
    <buses>
        <bus name="hello-bus">
			<provider>solace</provider>
            <host>192.168.1.100</host>
            <port>55555</port>
            <channels>
                <channel name="hello-requests">
                   <key>hello/requests</key>
                   <qos>BestEffort</key>
                </channel>
			    <channel name="hello-replies">
                   <key>hello/replies</key>
                   <qos>BestEffort</key>
                </channel>
            </channels>
        </bus>
    </buses>

	<apps>
		<app name="hello-app" mainClass="com.example.HelloApp">
			<messaging>
                <factories>
                  <factory name="com.example.messages.HelloMessageFactory"
                </factories>
				<buses>
					<bus name="hello-bus">
            		<channels>
            	  	  <channel name="hello-requests" join="true">
            	  	  <channel name="hello-replies" join="false">
               	    </channels>
				</buses>
			</messaging>
		</app>
	</env>
 
    <servers>
	    <server name="hello-vm">
            <apps>
                <app name="hello-app" autoStart="true" />
            </apps>
        </server>
    </servers>
</model>

Because the platform handles much of the non-functional operational aspects under the covers, many of the knobs it exposes don't have an impact on application code. Therefore, an application developer often won't need to work with much more than the configuration specified above.

See Understanding Configuration for more information about configuration.

Runtime Components

Atomic Event Processor (AEP)

Atomic Event Processing refers to the transactional event processing paradigm in Talon application that an AepEngine implements. An AepEngine sits at the heart of every Talon application. An AepEngine orchestrates the processing of inbound messages, business logic processing, replication and persistence of state changes and outbound messaging. This relieves application event (message) handlers from the non-functional concerns of interfacing with messaging providers, persistence layers and transaction coordination. 

Simple Messaging Abstraction (SMA)

Talon's Simple Messaging Abstraction layer provides a generic messaging API that encapsulates the set of messaging primitives required by the platform. This allows the platform to inter-operate seamlessly with any messaging provider by proving binding implementations that are simple to write. At a high level, SMA exposes the concepts of buses and channels of an application. An application sends and receives messages over bus channels which are mapped via configuration to an underlying messaging provider destination. 

See Working with Messaging

Operational Data Store (ODS)

AEP engines rely on Talon's Operational Data Store. An ODS Store provides HA capabilities for an application via memory-memory multi-peer replication, disk-based persistence, or both. An ODS store provides high performance asynchronous transaction facilities that an AepEngine uses in conjunction with SMA to achieve Atomic Event Processing. 

Important ODS Concepts include:

See Application Storage

XVM

 A Talon XVM serves as a container for Talon micro apps and provides management capabilities for the XVMs that it contains. Key features of the Talon XVM include:

Discovery

The platform's discovery facilities provides plugin mechanisms for ODS store's to discover one another, and for tooling to discovery running instances of applications. Out of the box, the platform supports discovery of multicast and over messaging. 

Application Flow

From an application perspective Talon's application flow is not dissimilar to many other event or message processing architectures: the application exposes message handlers to the platform which in turn passes inbound messages to it for processing. In the act of processing the inbound event, the application will make changes to its state and send some outbound events. The key difference between the Talon architecture and traditional architectures is that application state is stored in memory and resiliency is provided not by synchronous persistence to disk or a data grid, but instead by streaming state changes to a backup's memory in an asynchronous, pipelined fashion. The combination of in memory state and asynchronous 'persistence' allows Talon to operate at extreme performance levels without sacrificing on reliability. 

Key aspects of any streaming application platform that are of critical concern for stream oriented applications are:

In traditional application architectures the problems of state/messaging atomicity and exactly once processing are often solved using distributed transactions. For example, in J2EE state changes would be committed to a databases and messaging sent over JMS with XA transactions used to coordinate commit on both. Such schemes involve a lot of overhead and kill performance. The application flow in Talon provides the same level of reliability without the synchronous overhead of distributed transaction coordination. The following diagram depicts the application flow in a Talon application:

Elaborating on the diagram above, Talon ensures the same level of reliability as traditional architectures as follows:

  1. Talon receives an inbound message
  2. It dispatches the message to the application
  3. Application updates state (monitored by the Talon) 
  4. Application sends Messages (through Talon)
  5. Talon replicates the state changes and outbound messages to one or more hot backup instances via memory to memory replication. 
  6. Once the state and oubound effects (messages) are stabilized on a backup (via an asynchronous stablitity acknowledgement), outbound messages are released. 
  7. Acknowledgement of outbound messages allows cleanup up indoubt state
  8. Acknowledgement of inbound message which has not been fully processed. 

Key Takeaways