Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
public interface QueryAction<Criteria>

 {

    String perform(final QueryContext context, final Criteria criteria) throws QueryException;


    Criteria unmarshal(final String serializedCriteria) throws SerializationException;


    boolean isReady();


    void destroy();

}

http://scm.chip.org/svn/repos/spin/base/trunk/node/api/src/main/java/org/spin/node/actions/QueryAction.java

...

Code Block
final class EchoQueryAction extends QueryAction[String] {

    override def unmarshal(serialized: String) = serialized


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


    override def isReady = true


    override def destroy { }

}

This could be simplified by extending AbstractQueryAction, which provides default implementations for isReady() and destroy() which are suitable for a stateless QueryAction like EchoQueryAction:

Code Block
final class EchoQueryAction extends AbstractQueryAction[String] {

    override def unmarshal(serialized: String) = serialized


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

}

QueryAction's unmarshal method defines how the input criteria is unmarshalled into a Java object.  In this case, we  just echoing our input, so we don't need to deserialize. 

Consider a slightly more complicated QueryAction that receives as input a list of integers and returns the sum.  Here the serialization format is XML, so we can extend JAXBQueryAction, which supplies an implementation of unmarshal() that uses JAXB to turn raw XML into a object in the JVM:

No Formatcode
 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)

    }

}

This class takes input like:

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/XMLSchemaXMLScema" 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

import java.util.{List => JList}
@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*
    def this() = *this*(*new* JArrayList\[Int\]) &nbsp;&nbsp;&nbsp;

    //For nicer Scala interop &nbsp;&nbsp;&nbsp; *def* *this*
    def this(toAdd: Seq\[Int\]) = *this*(*new* JArrayList(asJavaList(toAdd))) &nbsp;&nbsp;&nbsp; *def*

    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:

...