Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Table of Contents

Getting the Spin source, including examples

The Spin source is available from a public Subversion server.  Instructions for accessing the source are here.

Building Spin

Spin is written primarily in Java and uses the Apache Maven build tool.  (See the installation guide for more information on prerequisites.)  You should be able to check out the Spin trunk, or a release, and build it with

Code Block
 $ mvn install

Spin source organization

The Spin source is divided into a number of Maven modules, some of which have sub-modules of their own.  (See the Maven reference for more information on what a module means in the Maven context.)  In particular, the examples/ module contains small example applications built with Spin, written in Java and Scala.  Example configuration files are also provided.  The code samples used here all come from the examples module.  Later, this document will refer to an example web application that allows testing Spin in a servlet container.  This web application is built by the examples/war/ module.

Module descriptions

  • tools
    • Miscellaneous utility classes used throughout Spin.  These handle things like configuration, cryptography, and message serialization
  • node
    • The server-side implementation of a Spin node, QueryActions, and interfaces used by client code to query local and remote Spin nodes.
  • query-interface
    • Client-side classes for querying Spin networks
  • etl
    • An Extract, Transform, Load framework used by some Spin extensions.  (This may go away or move to extension-support in future versions.)
  • examples
    • Example Spin applications and configuration files, including a deployable example web application.
  • identity-service
    • A pluggable framework for creating federated authentication and authorization services suitable to Spin.
  • integration
    • Integration/functional tests that require deployed Spin nodes, or test the interaction between code from two or more modules.
  • extension-support
    • A parking spot for classes used by Spin extensions, but not referenced anywhere in Spin the framework.
    • Classes in extension-support should not be relied upon and may be removed with little notice in future versions.  If this happens, relevant classes should be moved to the Spin extensions that need them.

Writing a Spin Query

A Spin network is a collection of nodes, which are objects that can perform queries. These nodes join together to form a network that allow queries to be broadcast from node to node and then aggregate results in reverse order. 

...

This section explains how to write the Spin plug-in used to implement a query and provides client code that can be used to perform this query remotely.

Resources

System Requirements

  • Sun/Oracle Java Development Kit (JDK) 1.6.0_04 or later.  Other JDKs, including OpenJDK, are not supported but will likely work.
  • Apache Maven 2.2.1. Maven 3.x is not supported, but will likely work. (Required to build SPIIN and the example module)

Hello, Spin

The queries that SPIN nodes perform are implemented as instances of the QueryAction interface.

...

QueryAction takes a serialized input criteria and returns serialized results.  It is up to the implementer to choose a serialization format, if any. Queries are submitted to a SPIN network using either the Agent, Querier, or SpinClient classes.  These are presented in order from lowest- to hight-level.  The highest-level client API, SpinClient, is used in this document and the examples module.

Implement QueryAction

A simple QueryAction is one that echoes its input.  Here's how it would look in Scala:

...

Code Block
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<ns2:AddInput xmlns:ns2="http://spin.org/xml/res/">

    <number xsi:type="xs:int" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">1</number>

    <number xsi:type="xs:int" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">2</number>

    <number xsi:type="xs:int" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">3</number>

</ns2:AddInput>

which gets unmarshalled into a class like

@XmlAccessorType(XmlAccessType.FIELD)

@XmlType(name = "AddInput", namespace = "http://spin.org/xml/res/")

@XmlRootElement(name = "AddInput", namespace = "http://spin.org/xml/res/")

//The only field is a Java List, which works with JAXB

final case class AddInput(private val number: JList[Int])
{ &nbsp;&nbsp;&nbsp; //JAXB requires a no-arg constructor; can be private &nbsp;&nbsp;&nbsp; *def* *this*() = *this*(*new* JArrayList\[Int\]) &nbsp;&nbsp;&nbsp; //For nicer Scala interop &nbsp;&nbsp;&nbsp; *def* *this*(toAdd: Seq\[Int\]) = *this*(*new* JArrayList(asJavaList(toAdd))) &nbsp;&nbsp;&nbsp; *def* toAdd: Seq\[Int\] = number.toSeq }

Returning Results

QueryActions return results as serialized Strings.  Spin is agnostic about the contents of the returned String and, as with input, the serialization format used.  In this case, if you define a class that's serializable by JAXB, like:

...

Code Block
final class AddQueryAction extends JAXBQueryAction(classOf[AddInput]) {

    //Take an AddInput, and return an XML-serialized AddResult

    override def perform(context: QueryContext, input: AddInput): String = {

        val result = new AddResult(input.toAdd.sum)



        JAXBUtils.marshalToString(result)

    }

}

Make a node that loads your query

A SPIN node is an instance of the SpinNodeImpl class, which implements the SpinNode interface accessed directly in the same JVM, or remotely via HTTP.  This example uses the JVM method, because it's the simplest.  Deploying a SPIN node in a servlet container is covered later.

Nodes assign each type of query a unique string identifier, called a QueryType, which is used to look up the QueryAction instance that implements the query.  By convention, QueryTypes are human-readable.  This mapping can be set up one of two ways:

 Specify QueryAction class directly

 Create a NodeConfig object with the mapping like:

...

It is also possible to set up this mapping in a node.xml file, which is an XML-serialized NodeConfig.  Setting up this mapping is covered later in this document.

Use a QueryActionMap

Specifying QueryType-to-QueryAction-class mappings directly is straightforward, but has some drawbacks: 

...

Alternatively, you can supply an instance of the QueryActionMap interface.  This interface describes a factory for QueryActions that the node uses to obtain them.  A QueryActionMap may be lazy, cache QueryActions or not, or use a DI framework like Guice or Spring, among other possibilities.  Defining a QueryActionMap, while straightforward, is more verbose than the direct-mapping approach so it is not used in this guide.

Make a client

Spin's client-side classes are fairly low-level.  First, you need a place to hold some constants and perform administrative tasks:

...

A SpinClient with the default configuration will attempt to sign all outgoing queries, which means that a certificate with a private key part must be available.  (TODO: Spin certificate management)

Testing in a Servlet Container

The easiest way to get started is to build the Spin examples module.  

1) Obtain the Spin node WAR file

The examples.war file built by the examples-war module exists in source control at http://scm.chip.org/svn/repos/spin/base/trunk/examples and is also available from the Open.Med Maven repository at (TODO: Nexus URL).  examples.war contains a SPIN node, plus example QueryActions defined in the examples/* modules.

2) Install and configure Spin

  1. Determine the Java servlet container's home directory, which is typically dictated by the host operating system. For example, it may be the Tomcat user's home directory, ~tomcat, which would look like: $TOMCAT_HOME/webapps directory.
  2. Determine the servelet container user. If you're running Tomcat on Debian and Red Hat, and if Tomcat was installed with the package manager, the user is tomcat. If you're starting your servlet container manually, the user is probably the username you logged in as.
  3. Create $SPIN_HOME:
    On Unix-like systems $SPIN_HOME is ~/.spin/conf/, where ~ is the home directory of the Tomcat user.
    If the operating system is Windows, $SPIN_HOME is ~/spin.  If the operating system is Windows, replace '.spin' with 'spin'.
  4. Copy the files node.xml and routingtable.xml from the conf/ directory of the examples-war module ( http://scm.chip.org/svn/repos/spin/base/trunk/examples/war/conf) to $SPIN_HOME/conf
  5. Start the servlet container.

These instructions are specific to building the examples module, refer to the Spin Installation Guide for more detailed installation, configuration and testing instructions. 

3) Test the installation

You can use WSDL to test the installation.

...