[go: up one dir, main page]

home

There is a newer version of this page. You can find it here.

SWire documentation

About SWire

SWire stands for Stata-Wire. SWire is a software interface, enabling us to query Stata for the executing of basic operations, such as reading or writing data. Its core is a Stata-Java plugin which functions as a server; it can be queried by using the HTTP protocol. Clients, such as a desktop software application or a web page, can be developed for interacting with SWire, thus allowing the integration between Stata and other software.

SWire is in essence a wrapper around the Stata-Java API: all the functions relating to this API can, therefore, be externally called by clients. SWire exposes the Stata-Java API, together with other SWire special methods. Special methods are functions facilitating the interaction between Stata and external clients; they provide additional functionalities than those provided by the Stata-Java API.

SWire can be interrogated on a local network and it accepts AJAX queries. This allows for the development of web applications to provide the user with graphical user interfaces. For example, a web application running on a browser can interact with Stata on a local network; this application could be a data entry form or an automatic report.

By providing a communication protocol, SWire makes it possible to connect Stata with many other applications for data exchange and basic interaction, thereby extending the capabilities of Stata. SWire requires Stata >=13.

The SWire protocol is based on HTTP. In this protocol, the body of the HTTP request/response is a SWire request/response. The HTTP body is a base64 encoding of a MessagePack serialization of a JSON request/response. The SWire request/response syntax can be described by JSON strings.

Installation

SWire must be installed in a valid Stata ado-directory. Here will be discussed how to install SWire in your personal ado-directory. You can find out your personal ado-directory by using the personal command in Stata. To do that, type this in Stata:

personal

Then, follow these instructions:

  1. if your personal ado-directory does not exist, then create it;
  2. copy swire.ado and swire.sthlp in your personal ado-directory;
  3. copy the contents of the jar folder in the "jar" folder under you personal ado-directory. If the "jar" folder does not exist under you personal ado-directory, then create it first.

At the end of this process this will be the structure of your personal ado-directory (let suppose the your personal ado-directory is "/home/john/ado/personal/"):

/home/john/ado/personal/swire.ado
/home/john/ado/personal/swire.sthlp
/home/john/ado/personal/jar/swire.jar
/home/john/ado/personal/jar/lib/javassist-3.20.0-GA.jar
/home/john/ado/personal/jar/lib/msgpack-0.6.12.jar

Try this command in Stata:

swire version

The previous command will display the SWire version number if the installation was successful.

Troubleshooting

If the communication between SWire and the client application does not function, please ensure that:

  • the network port which is used by SWire is unused by other applications;
  • the network port which is used by SWire is the same which is used by the client application;
  • no firewall is blocking network traffic on the port which is used by SWire.

The swire Stata command

The swire Stata command is a wrapper aroud the SWire plugin. It is indeed a collection of Stata commands:

  • swire
  • swire start
  • swire stop
  • swire status
  • swire methods

swire

Syntax

swire

Description

swire displays the list if the SWire commands, namely: swire start, swire stop, swire status, swire methods and swire version.

swire start

Syntax

swire start [, port(port_number)]

Description

swire start is the command for starting the SWire server. It accepts the optional argument port() for specifying the network port number on which the SWire server will listen. If port() is not specified, port 50000 will be used by default. A valid port number between 1024 and 65535 must be specified. The port must be not used by other applications and no firewall must block network traffic on that port. Other applications can interact with SWire only if the SWire server is listening.

swire stop

Syntax

swire stop

Description

swire stop is the command for stopping the SWire server.

swire status

Syntax

swire status

Description

swire status reports the status of the SWire server. The SWire server can listen or not listen on a network port.

Stored results

Macros
r(status)
The SWire server status

Scalars
r(port)
The network port number used by the SWire server (a missing value is returned if the SWire server is not listening)

swire methods

Syntax

swire methods

Description

swire methods displays the Stata-Java API methods and the SWire special methods that are exposed by SWire. A corresponding availability status is also reported for each Stata-Java API method. A Stata-Java API method is unavailable if the method is not available in the Stata-Java API, which is used by your Stata release.

swire version

Syntax

swire version

Description

swire version displays the SWire version number.

Stored results

Scalars
r(version)
The SWire version number.

The SWire protocol

The SWire protocol is based on HTTP and is the protocol to use for communicating with the SWire server. There are two types of messages in the SWire protocol: the SWire request, which is sent to the SWire server by a client, and the SWire response, which is sent back to the client by the SWire server.

The HTTP body of a SWire message is a base64 encoding of a MessagePack serialization of a JSON request/response. Thus, the SWire protocol can be described by the syntaxes of JSON requests/responses. This documentation will describe the SWire protocol in terms of syntax of JSON strings, althought what is indeed sent/received is a base64 encoding of a MessagePack serialization of those strings.

A SWire request demands for the execution of a list of atomic jobs. Each atomic job corresponds to a Stata-Java API method or a SWire special method. In the case of a Stata-Java method, the method is referred by its full-qualified name (e.g.: com.stata.sfi.Data.getObsCount rather than getObsCount). Every name of a SWire special method begins with the dollar symbol ($).

Let us start with a JSON representation of SWire request for calling the com.stata.sfi.Data.getObsCount method (this method returns the number of dataset observations):

:::json
{
    "job":[{
        "method": "com.stata.sfi.Data.getObsCount"
    }]
}

The binary MessagePack serialization of the previous JSON string (without line breaks) is:

81 a3 6a 6f 62 91 81 a6 6d 65 74 68 6f 64 be 63 6f 6d 2e 73 74 61 74 61 2e 73 66 69 2e 44 61 74 61 2e 67 65 74 4f 62 73 43 6f 75 6e 74

and its base64 encoding is:

gaNqb2KRgaZtZXRob2S+Y29tLnN0YXRhLnNmaS5EYXRhLmdldE9ic0NvdW50

The final HTTP request is:

POST / HTTP/1.1
Host: 127.0.0.1:50000
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:47.0) Gecko/20100101 Firefox/47.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Length: 60
Origin: null
Connection: keep-alive
Cache-Control: max-age=0

gaNqb2KRgaZtZXRob2S+Y29tLnN0YXRhLnNmaS5EYXRhLmdldE9ic0NvdW50

In the previous SWire request only one method has been called, but generally a list of methods can be called in a single SWire request. Every method call is called atomic job request, thus a SWire request is indeed a list of atomic job requests. After the SWire server executed the request, a response is sent to the client. This response contains the outcome for each atomic request, and each outcome is represented in an atomic job response.

The HTTP response to the previous SWire request is

HTTP/1.1 200 OK
Content-length: 52
Access-control-allow-origin: *
Date: Fri, 04 Nov 2016 16:19:52 GMT

gaNqb2KRgaZtZXRob2S+Y29tLnN0YXRhLnNmaS5EYXRhLmdldE9ic0NvdW50

The HTTP body of the previous HTTP response is:

gaNqb2KRgaZtZXRob2S+Y29tLnN0YXRhLnNmaS5EYXRhLmdldE9ic0NvdW50

This HTTP body is a base64 encoding of a MessagePack serialization of a JSON string. The corresponding JSON string is:

:::json
{
    "status": "ok",
    "output": [
        {
            "status": "ok",
            "output" 74
        }
    ]
}

This JSON response contains the output from the com.stata.sfi.Data.getObsCount Stata-Java method. The first-level status node reports the execution status of the overall request (in the previous example is "ok"). The first-level output node is an array of atomic job responses. As we requested only one atomic job, the output array contains only one element. The atomic job response has a status node and an output node. The latter contains the value 74, namely the number of observations in the current Stata dataset, and it represents the output from the com.stata.sfi.Data.getObsCount Stata-Java method.

The SWire request

Syntax

:::json
{
    "continue": continueFlag,
    "job": jobArray
}

where:

  • continueFlag (type: boolean; required: no) - controls if the execution of the array of atomic jobs must halt when an atomic job reports an error
  • jobArray (type: array; required: yes) - an array of atomic jobs (see atomic jobs)

Examples

A SWire request with the continue flag set to true and two atomic jobs:

:::json
{
    "continue": true,
    "job": [
    {
        "method": "com.stata.sfi.Scalar.setValue",
        "args": ["myscalar", 21.3] 
    },
    {
        "method": "com.stata.sfi.Data.addVarDouble",
        "args": ["myvar"]
    }
]

The previous request has two atomic jobs: the first is a call to the com.stata.sfi.Scalar.setValue method by passing the string "myscalar" and the value 21.3 as parameters; the secondo is a call to the com.stata.sfi.Data.addVarDouble method by passing the string "myvar" as the only parameter.

The atomic job

Syntax

:::json
{
    "method": method,
    "args": args
}

where:

  • method (type: string; required: yes) - it can be either a Stata-Java Api method (e.g.: “com.stata.sfi.Scalar.setValue”) or a special method (e.g.: “$appendRow”). Note that all special methods begin with “$”.
  • args (type: string; required: depends on method) - it is a parameters array in the case of a Stata-Java Api method and a map in the case of a special method.

Examples

Call to the com.stata.sfi.Scalar.setValue Stata-Java method by passing a numeric value:

:::json
{
    "method": "com.stata.sfi.Scalar.setValue",
    "args": ["myscalar", 21.3]
}

Call to the com.stata.sfi.Data.getVarCount Stata-Java method without any passed parameter (the com.stata.sfi.Data.getVarCount does not require any parameter):

:::json
{
    "method": "com.stata.sfi.Data.getVarCount"
}

Call to the $appendRow SWire special method:

:::json
{
    "method": "$appendRow",
    "args": {
        "data": {
            "myvar1": 8.3,
            "myvar2": 15.7,      
            "myvar3": 9.1,
        }
    }
}

The continue flag

Examples

In the following SWire request, the first atomic job presents an error (the com.stata.sfi.Data.notExistingMethod method does not exists):

:::json
{
    "continue": false,
    "job": [
        {
            "method": "com.stata.sfi.Data.notExistingMethod"
        },
        {
            "method": "com.stata.sfi.Data.getVarCount"
        }         
    ]  
}

As the continue flag has been set to false, the SWire server will execute the first atomic job only. This behaviour is reported in the corresponding SWire response:

:::json
{
    "status": "error_in_job",
    "output": [
        {
            "status": "error",
            "errorType": "STATA_METHOD_NOT_FOUND"
        },
        {
            "status": "not_executed"     
        }         
    ]  
}

In the previous SWire response an error is reported for the first atomic job, while a not_executed status is reported for the second atomic job.
In the following example the continue flag has been set to true:

:::json
{
    "continue": true,
    "job": [
        {
            "method": "com.stata.sfi.Data.notExistingMethod"
        },
        {
            "method": "com.stata.sfi.Data.getVarCount"
        }         
    ]  
}

and this is the corresponding SWire response:

:::json
{
    "status": "error_in_job",
    "output": [
        {
            "status": "error",
            "errorType": "STATA_METHOD_NOT_FOUND"
        },
        {
            "status": "ok",
            "output": 12    
        }         
    ]  
}

The second atomic job has been executed, despite the error which has been reported for the first atomic job, because the continue flag was set to true in the SWire request.

SWire response

Syntax

:::json
{
    "status": status,
    "output": output,
    "errorType": errorType
}

where:

  • status (type: string) - a string that can be ok, error or error_in_job. It is ok when all the atomic jobs have been correctly executed; it is error when there is a syntax error in the request; and it is error_in_job when there is an error in one of the atomic jobs. The status key always appears in the response. From the status value depends the presence of the output and errorType keys (see documentation about output and errorType.
  • output (type: array) - an array of atomic job output for each atomic job request. It appears in the response only if status is ok.
  • errorType (type: string) - a string that describes the error in the global request. It appears in the response only if status is not ok.

Examples

SWire request:

:::json
{
    "job": [
        {
            "method": "com.stata.sfi.Data.getVarCount"
        },
        {
            "method": "com.stata.sfi.SFIToolkit.isValidVariableName",
            "args": ["myvarname"]
        }
    ]
}

and its corresponding SWire response with ok status for each requested atomic job:

:::json
{
    "status": "ok",
    "output": [
        {
            "status": "ok",
            "output": 12
        },
        {
            "status": "ok",
            "output": true
        }
    ]
}

SWire request intentionally wrong (the notExistingKey is a not allowed by the SWire request syntax):

:::json
{
    "notExistingKey": [
        {
            "method": "com.stata.sfi.Data.getVarCount"
        }
    ]
}

and its corresponding SWire response with status = error status and errorType = JOB_NOT_FOUND:

:::json
{
    "status": "error",
    "errorType": "JOB_NOT_FOUND"
}

SWire request with the second job given as intentionally wrong:

:::json
{
    "job": [
        {
            "method": "com.stata.sfi.Data.getVarCount"
        },
        {
            "method": "com.stata.sfi.Data.notExistingMethod"
        }
    ]
}

and its corresponding SWire respone with status = error_in_job:

:::json
{
    "status": "error_in_job",
    "output": [
        {
            "status": "ok",
            "output": 12
        },
        {
            "status": "error",
            "errorType": "STATA_METHOD_NOT_FOUND"
        }
    ]
}

Copyright

SWire is distributed with the following Java libraries:

  • Javassist 3.20.0-GA
  • msgpack-java 0.6.12

Javassist is released under the Mozilla Public License 1.1 (https://www.mozilla.org/en-US/MPL/1.1/).
Msgpack-java is released under the Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0).

Also see

2016 Italian Stata Users Group Meeting, Rome 17-18 November
Abstract and slides that were presented at the Italian Stata Users Group Meeting Meeting 2016

SWire Web Apps Collection
A collection of web apps interacting with Stata through SWire

SWire4js
A JavaScript library for developing SWire web applications

SWire4R
An R package enabling R to interact with Stata for data exchange

Swire4QGIS
A QGIS plugin enabling data exhange with Stata

SQuery
A web application for collectiong questionnaires' responses in Stata