JSON-RPC 2.0 (opens new window) is a simple and light-weight remote procedure call protocol. It is transport agnostic and Manatee has built-in support for three transports; WebSockets, NamedPipes and Netstring/Tcp.
JSON-RPC messages are divided into four types. Each type places specific requirements on content and behavioural semantics, e.g. a Request
should always be followed by a Response
.
# JSON-RPC objects
# Request
The Request
object must contain:
jsonrpc
indicating the version of JSON-RPC supported – always"2.0"
id
is an identifier (string) used to correlate the request with the following responsemethod
is a string identifying which invocation the requests represents
Furthermore it can contain:
params
which is an object with named parameters for the method to be invoked
The following is an example of a Request
object to invoke the Plus
method with two arguments; A
and B
.
{
"jsonrpc": "2.0",
"id": "123",
"method": "Plus",
"params": { "A": 200, "B": 100 },
}
# Response
The Response
object must contain:
jsonrpc
indicating the version of JSON-RPC supported – always"2.0"
id
is the id of theRequest
object that this is a response to
Furthermore it must contain either:
result
to indicate a successful invocation, containing an object with the result, orerror
containing anError
object to indicate a failed invocation.
A Response
for the Plus
invocation above could be:
{
"jsonrpc": "2.0",
"id": "123",
"result": { "A+B": 300 },
}
or in case of failure;
{
"jsonrpc": "2.0",
"id": "123",
"error": { "code": 9000, "message": "A is not a number" },
}
Each request MUST be followed by a response
When receiving a Request
message the client or server must respond with a Response
meessage. Failure to do so will be considered a protocol violation.
# Notification
A Notification
is similar to a Response
except it must not contain an id
.
An example could be;
{
"jsonrpc": "2.0",
"method": "UserLoggedIn",
"params": { "User": "John Doe" }
}
# Error
An Error
object must contain the following properties:
code
an integer denoting the type of the errormessage
a string describing the error
Furthermore the following are optional:
data
an object with further details about the error
An example error could be:
{
"code": -32601, // Method not found
"message": "The method Minus is not found"
}
The following error codes are supported.
Error | Code |
---|---|
ParseError | -32700 |
InvalidRequest | -32600 |
NotFound | -32601 |
InvalidParams | -32602 |
InternalServerError | -32000 |
TimeOut | -32001 |
ProtocolViolation | -32002 |
ParticipantAlreadyJoined | -32100 |
LaunchFailure | -32101 |
InvalidContextCoupon | -32102 |
NotInTransaction | -32103 |
UnknownParticipant | -32104 |
TransactionInProgress | -32105 |
No batch support
We do not support batch operations as defined in the JSON-RPC specs.
# Interfaces
The interfaces available over JSON-RPC are the ContextManager
, ContextData
ContextAction
as defined in the HL7 CCOW specification v1.6.2 (opens new window). Any connecting clients are expected to implement the ContextParticipant
interface (and possibly ParticipantMonitor
as well) to enroll in surveys etc when the common context changes.
WARNING
This section assumes a knowledge of the CCOW standard and the interfaces defined therein.
A common sequence of interactions between a client (in CCOW terms this is called a “participant”) runs as illustrated below.
The overall theme is that a particpant first joins a common context and once joined the partipant may change items in the common context while it must similarly respond to context changes originating with other participants in that same context.
The following describes the methods in each interface which the server (Manatee) exposes and the interfaces that the client is expected to implement.
Conventions and abbreviations used in the following sections
The common context is a map of strings to strings. The keys in the map are called subjects
.
In the coming sections the symbols >>>
means that the following JSON-RPC message is sent from the participant to the context manager while the reverse <<<
means the context manager is sending a message to the participant.
The names of the methods used in the JSON-RPC requests and notifications are of the form <interface-name>.<method-name>
e.g. ContextManager.JoinCommonContext
.
# Abbreviations
- CM = ContextManager
- CP = ContextParticant
- CD = ContextData
- CA = ContextAction
- tx = transaction
# ContextManager
The ContextManager
interface contains methods for creating and controlling context change transactions. Together with the ContextData
interface it provides the complete functionality to change the content of the common context.
The following methods can be found in this interface:
- JoinCommonContext
- LeaveCommonContext
- SuspendParticipation
- ResumeParticipation
- StartContextChanges
- UndoContextChanges
- EndContextChanges
- PublishChangesDecision
- MostRecentContextCoupon
- ImplementationInformation
# JoinCommonContext
This method is used to enroll the CP in the common context. It must precede most of the other invocations - exceptions to this rule includes ContextSession.Create and .Activate.
# Request
The value for method
is "ContextManager.JoinCommonContext"
for JoinCommonContext invocations. This naming rule of interface-name followed by a dot then the method name is consistent in all requests and notifications.
The following arguments are applicable to this invocation:
ApplicationName
[string, required] is used by the CM to determine which parts (which subjects) that the CP is allowed to read/write. The CM must know about the application joining beforehand. This is accomplished via the Cuesta configuration interface (opens new window).ComponentId
[string, optional] determines which session is joined (see Registry). If no value is given then the current active session is joined.SendContextInTxMethods
[bool, optional] iftrue
then the ContextChangesPending request and the ContextChangesAccepted notification includes the current common context to save a the participant the trouble of using the ContextData methods to get this information.
# Response
The response contains the following properties:
ParticipantCoupon
[int] represents the participant in this context. CP should hold on to this to reuse in later interactions with the CM.Tag
[string, optional] is an optional identifier for the context.ComponentId
[string] the id of the context.Color
[string] an hex encoded color for the context. The CP can display this in its UI when joined.
# Example
>>>
{
"jsonrpc": "2.0",
"id": "1",
"method": "ContextManager.JoinCommonContext",
"params": {
"ApplicationName": "Foo",
"ComponentId": "100",
"SendContextInTxMethods": true
}
}
<<<
{
"jsonrpc": "2.0",
"id": "1",
"result": {
"ParticipantCoupon": 1001,
"Tag": "Bar",
"ComponentId": "1234",
"Color": "#000000"
}
}
# LeaveCommonContext
This method is invoked to leave the common context.
# Request
ParticipantCoupon
[long] the identifier for the CP to leave the common context
# Response
The response will always be an empty response in case of success. Otherwise an error will be set.
# Example
>>>
{
"jsonrpc": "2.0",
"id": "2",
"method": "ContextManager.LeaveCommonContext",
"params": { "ParticipantCoupon": 1001 }
}
<<<
{
"jsonrpc": "2.0",
"id": "2",
}
# StartContextChanges
This method is invoked to initiate a context change transaction in which one or more items in the context changes values.
Once the transaction has been started it must be completed (committed or aborted) within a configured deadline (default is 30 seconds). If this is not done, the transaction will be aborted.
# Request
It accepts a single argument:
ParticipantCoupon
[long] which is the value given to the participant when it joined the common context.
# Response
The response will also contain a single value if the invocation was successful.
ContextCoupon
[long] which represent the context change transaction and must be used in e.g. theSetItemValues
method when specifying which parts of the context to change.
# Example
>>>
{
"jsonrpc": "2.0",
"id": "3",
"method": "ContextManager.StartContextChanges",
"params": { "ParticipantCoupon": 1001 }
}
<<<
{
"jsonrpc": "2.0",
"id": "3",
"result": { "ContextCoupon": 2001 }
}
The client can now start changing the desired parts of the context using the context coupon and finally commit the changes.
# UndoContextChanges
Aborts a transaction without notifying other participants.
# Request
Takes a single argument:
ContextCoupon
[long] designating the context change transaction to abort.
# Response
The response will always be an empty response in case of success. Otherwise an error will be set.
# Example
>>>
{
"jsonrpc": "2.0",
"id": "4",
"method": "ContextManager.UndoContextChanges",
"params": { "ContextCoupon": 2001 }
}
<<<
{
"jsonrpc": "2.0",
"id": "4"
}
# EndContextChanges
The EndContextChanges
method is invoked after the desired changes have been made to the common context in a context change transaction. The CM will now query all participants in the same common context to determine whether there are any objections to committing the tx and return the results of this query to the caller.
# Request
Takes a single argument:
ContextCoupon
[long] designating the context change transaction to end.
# Response
The response contains:
NoContinue
[bool] which istrue
if one or more participants rejected the change.Responses
[string[]] a list of human-readable responses from those participants that rejected the change.
# Example
The following is an example where a participant has rejected the change because it needs the user to do a task prior to switching. It is up to each individual participant to determine when a transaction can proceeed according to the their internal business logic.
>>>
{
"jsonrpc": "2.0",
"id": "4",
"method": "ContextManager.EndContextChanges",
"params": { "ContextCoupon": 2001 }
}
<<<
{
"jsonrpc": "2.0",
"id": "4",
"result": {
"NoContinue": true,
"Responses": ["User must save document in NNN prior to change of patient"]
}
}
Following an EndContextChanges
the initiator of the transaction must now decide whether to proceed and commit the transaction or abort.
# PublishChangesDecision
Once EndContextChanges
has been invoked it is up to the tx initiator to decide if the tx should be committed. That is what this method is for.
WARNING
If the result EndContextChanges
has a NoContinue
value of true
the initiator can still decide to commit the transaction. The rejecting participant may be removed from the common context in that case.
# Request
The invocation takes two parameters:
ContextCoupon
[long] to identify the tx to commit/abort.Decision
[string] is the decision to commit when the value"accept"
is given. To abort use"cancel"
.
# Response
The response will always be an empty response in case of success. Otherwise an error will be set.
# Example
>>>
{
"jsonrpc": "2.0",
"id": "5",
"method": "ContextManager.PublishChangesDecision",
"params": {
"ContextCoupon": 2001,
"Decision": "accept"
}
}
<<<
{
"jsonrpc": "2.0",
"id": "5"
}
# SuspendParticipation
Use this to temporarily remove the participant from the common context.
# Request
Takes the participant coupon of the participant to suspend.
ParticipantCoupon
[long] identifies the participant to suspend.
# Response
The response will always be an empty response in case of success. Otherwise an error will be set.
# Example
>>>
{
"jsonrpc": "2.0",
"id": "6",
"method": "ContextManager.SuspendParticipation",
"params": { "ParticipantCoupon": 1001 }
}
<<<
{
"jsonrpc": "2.0",
"id": "6"
}
# ResumeParticipation
Undo a participant suspension.
# Request
Takes the participant coupon of the participant to resume.
ParticipantCoupon
[long] identifies the participant to resume.
# Response
The response will always be an empty response in case of success. Otherwise an error will be set.
# Example
>>>
{
"jsonrpc": "2.0",
"id": "7",
"method": "ContextManager.ResumeParticipation",
"params": { "ParticipantCoupon": 1001 }
}
<<<
{
"jsonrpc": "2.0",
"id": "7"
}
# MostRecentContextCoupon
This method will return the context coupon of the most recent successfull context tx (or the initial coupon generated for the initial context if no transactions have been completed).
Shorthand is -1
Use -1
as ContextCoupon
in the methods which has this argument to automatically use the most recent context coupon. This saves a request/response occasionally.
# Request
Takes no arguments.
# Response
The response will contain the ContextCoupon
.
ContextCoupon
[long] the most recent committed tx.
# Example
>>>
{
"jsonrpc": "2.0",
"id": "8",
"method": "ContextManager.MostRecentContextCoupon"
}
<<<
{
"jsonrpc": "2.0",
"id": "8",
"result": { "MostRecentContextCoupon": 123 }
}
# ImplementationInformation
Extract details about the implementation of the CM.
# Request
Takes no arguments.
# Response
Returns the following information:
ComponentName
[string] the name of the component.Manufacturer
[string] is always “Sirenia”.PartNumber
[string] further details about the CM.RevMajorNum
,RevMinorNum
,RevMaintenanceNum
[string] are the components of the version (of the CM).TargetOS
[string] the os for which the CM was built.TargetOSRev
[string] the OS version compatibility.
# ContextData
The ContextData
interface contains the methods needed to read and write from and to the common context.
The following methods are available here:
# GetItemNames
Get a list of the key/subject of all items in the designated context.
# Request
The request contains an identifier for the context to query for names.
ContextCoupon
[long] the context to return names for.-1
can be used for the latest committed names.
# Response
The response is a string array of all the names/subjects in the context.
Names
[string[]] the names (filtered to match the permissions of the CP) in the context
# Example
>>>
{
"jsonrpc": "2.0",
"id": "9",
"method": "ContextData.GetItemNames",
"params": { "ContextCoupon": 2001 }
}
<<<
{
"jsonrpc": "2.0",
"id": "9",
"result": { "Names": ["foo", "bar"] }
}
# GetItemValues
Use this method to retrieve the values of a selected portion of the context.
# Request
ItemNames
[string[]] the list of names to return values forContextCoupon
[long] the identifier of the context to queryOnlyChanges
[bool, optional] iftrue
and theContextCoupon
denotes an uncompleted transaction then only the values changed will be returned
# Response
ItemValues
[string[]] is a list of the names and values (alternating)
# Example
>>>
{
"jsonrpc": "2.0",
"id": "10",
"method": "ContextData.GetItemValues",
"params": {
"ItemNames": ["foo", "bar"],
"ContextCoupon": 2001
}
}
<<<
{
"jsonrpc": "2.0",
"id": "10",
"result": { "ItemValues": ["foo", 100, "bar", 200] }
}
Note that the returned values contain both the names and the values such that index N
contains the name and N+1
the value where { N | N % 2 == 0 }
.
# SetItemValues
This method can only be called after StartContextChanges
and will set the values to be changed in the transaction to the given values.
# Request
The request contains the names and values to change.
ItemNames
[string[]] the names of the items to change. The index of this property must match up with the value to change in theItemValues
property.ItemValues
[string[]] the values to change matching the names (on index) given inItemNames
.ContextCoupon
[long] the identifier for the context in which the change should take place.ParticipantCoupon
is the identifier for the CP doing the change.
# Response
The response will always be an empty response in case of success. Otherwise an error will be set.
# Example
>>>
{
"jsonrpc": "2.0",
"id": "11",
"method": "ContextData.GetItemValues",
"params": {
"ItemNames": ["foo", "bar"],
"ItemValues": [1000, 2000],
"ContextCoupon": 2001,
"ParticipantCoupon": 1001
}
}
<<<
{
"jsonrpc": "2.0",
"id": "11",
}
# ContextAction
The ContextAction
interface is used to invoke named actions in action agents (which may be other context participants).
Similarly to how information about which parts of the common context is supported by which CP, we use the Registry to store information about which actions are supported by which agents.
# Perform
This is the only method available and it is used to invoke a particular action in a context agent. The agent will (if using this interface) have its ContextAgent.ContextChangesPending method called.
# Request
ActionIdentifier
[string] an identifier for the action to invoke.ParticipantCoupon
[long] the identifier of the caller.InputNames
[string[], optional] a list of names for arguments given inInputValues
InputValues
[string[], optional] a list of arguments matching the names given inInputNames
on index.
# Response
Decision
[string] a string designating wether the CM managed to locate an agent and execute the action.Reason
[string] a human-readable explanation of why the method failed (if it failed, empty otherwise).OutputNames
[string[]] a list of names for return values.OutputValues
[string[]] a list of return values.
# Example
>>>
{
"jsonrpc": "2.0",
"id": "12",
"method": "ContextAction.Perform",
"params": {
"ActionIdentifier": "Plus",
"InputNames": ["A", "B"],
"InputValues": [1, 2],
"ParticipantCoupon": 1001
}
}
<<<
{
"jsonrpc": "2.0",
"id": "12",
"result": {
"OutputNames": ["A+B"],
"OutputValues": [3],
"Decision": "accept"
}
}
# Registry
The Registry
interface exposes an OfType
and ById
methods which can be used to query for various configuration- and instance-level items. It is primarily used to list instances of context managers and the result can be used in the JoinCommonContext
method. However since the argument here is optional and the default behaviour is to join the currently active CM (which is most likely what you want) the methods here are rarely used.
Note that this interface is a poor mans convenience proxy for using the Kwanza registry directly which is a proper context management registry (CMR).
# OfType
# Request
Typename
[string, optional] the type of the item to query, default is"ContextManager"
.
# Response
Identifiers
[string[]] a list of identifiers for items of the given type.
# Example
>>>
{
"jsonrpc": "2.0",
"id": "13",
"method": "Registry.OfType",
"params": { "Typename": "ContextManager" }
}
<<<
{
"jsonrpc": "2.0",
"id": "13",
"result": { "Identifiers": ["foo", "bar", "123"] }
}
# ById
Return a single item given its identifier.
# Request
Typename
[string, optional] the type of the item to query, default is"ContextManager"
.Identifier
[string] the identifier for the item to return.
# Response
The response contains a single item
Item
[object] the item with the given identifier - the structure of the object is dependent of its type. All types of items have the properties;Identifier
[string] the identifier of the item.Typename
[string] the type of the item.
For the "ContextManager"
type additional properties of the item are;
Tag
[string] a human-readable optional tag given to the CM when createdColor
[string] an auto-generated color associated with the CM
# Example
>>>
{
"jsonrpc": "2.0",
"id": "14",
"method": "Registry.ById",
"params": {
"Typename": "ContextManager",
"Identifier": "foo"
}
}
<<<
{
"jsonrpc": "2.0",
"id": "14",
"result": {
"Item": {
"Identifier": "foo",
"Typename": "ContextManager",
"Tag": "bar",
"Color": "#4E4E4E"
}
}
}
# LocalActions
The LocalActions
endpoint returns all available actions from the local CM.
# Request
No arguments needed.
# Response
A list of actions each containing;
Identifier
[string] for the action.Name
[string] a human readable name.Subject
[string] a human readable identifier although no guarantees of uniqueness is offered.ApplicationName
[string] contains the name of the application/agent to which the action is attached.ApplicationDescription
[string] is a human readable description of the application.Groups
[group[]] contains a list of attached groups (can be used to do further filtering filtering) where each group contains the following properties;Identifier
[string] for the group.Name
[string] the name of group.Description
[string] a human readable description of the group.Key
[string] an unspecified configuration property (use at your own discretion when configuring).
# Example
>>>
{
"jsonrpc": "2.0",
"id": "140",
"method": "Registry.LocalActions"
}
<<<
{
"jsonrpc": "2.0",
"id": "140",
"result": {
"Actions": [
{
"Identifier": "1234",
"Name": "Action #1",
"Subject": "[eu.sirenia]Action.One",
"ApplicationName": "App #1",
"ApplicationDescription": "Application One",
"Groups": [
{
"Identifier": "1",
"Name": "Group #1",
"Description": "",
"Key": ""
},
{
"Identifier": "2",
"Name": "Group #2",
"Description": "bar",
"Key": ""
}
]
},
...
]
}
}
# LocalApplications
The LocalApplications
endpoint returns all available applications from the local CM.
# Request
No arguments needed.
# Response
A list of actions each containing;
Identifier
[string] for the action.ApplicationName
[string] same asIdentifier
.FriendlyName
[string] a human readable name.ApplicationType
[string] the type of the application.Version
[string]
# Example
>>>
{
"jsonrpc": "2.0",
"id": "180",
"method": "Registry.LocalApplications"
}
<<<
{
"jsonrpc": "2.0",
"id": "180",
"result": {
"Actions": [
{
"Identifier": "1234",
"ApplicationName": "1234",
"FriendlyName": "Application Foo",
"ApplicationType": "CONTEXTPARTICIPANT",
"Version": "v1.2.3",
},
...
]
}
}
# ContextParticipant
The ContextParticipant
interface is expected to be implemented by the CP joining the common context. It contains methods that will be invoked by the CM on the CP and the flow of requests and responses are therefore inverted with
- requests/notifications/errors coming from the server/CM and targeting the client/CP
- responses generated by the client/CP and returned to the server/CM.
The methods contained in this interfaces:
# ContextChangesPending
This method is invoked by the CM when another CP issues an EndContextChanges
invocation and is the query to this CP to determine whether it can accept a change in the common context.
# Request
The arguments supplied are:
ContextCoupon
[long] the identifier for the context transaction in which the changes occurChanges
[map<string,string>, optional] if theSendContextInTxMethods
argument forJoinCommonContext
istrue
then this argument will contain the changes to the context directly. If not then the participant may query for values using theGetItemValues
method.
# Response
The response should contain:
Decision
[string]"accept"
to accept the change or"cancel"
to not.Reason
[string, optional] should contain a human-readable message as whyDecision
is not"accept"
if that is the case.
# Example
<<<
{
"jsonrpc": "2.0",
"id": "100",
"method": "ContextParticipant.ContextChangesPending",
"params": {
"ContextCoupon": 2003,
"Changes": { "foo": "bar", "qux": "zop" }
}
}
>>>
{
"jsonrpc": "2.0",
"id": "100",
"result": {
"Decision": "cancel",
"Reason": "'zop' is not a valid value for 'qux'"
}
}
# ContextChangesAccepted
This notification is sent when the context change transaction commits.
The CP must update its internal state in response
The CP is required to update its internal state to match that of the common context when it receives a ContextChangesAccepted
notification. If it cannot do this it must leave the common context.
# Request
The arguments are the same as for ContextChangesPending
.
# Response
No response is expected. It is a protocol violation to supply a response.
<<<
{
"jsonrpc": "2.0",
"method": "ContextParticipant.ContextChangesAccepted",
"params": {
"ContextCoupon": 2003,
"Changes": { "foo": "bar", "qux": "zop" }
}
}
# ContextChangesCancelled
This notification is sent when the context change transaction aborts.
# Request
ContextCoupon
[long] the identifier for the transaction rolling back.
# Response
No response is expected. It is a protocol violation to supply a response.
<<<
{
"jsonrpc": "2.0",
"method": "ContextParticipant.ContextChangesCancelled",
"params": {
"ContextCoupon": 2003,
}
}
# CommonContextTerminated
This notification is sent when the context manager terminates.
# Request
Contains no additional arguments.
# Response
No response is expected. It is a protocol violation to supply a response.
# Example
<<<
{
"jsonrpc": "2.0",
"method": "ContextParticipant.CommonContextTerminated"
}
# Ping
The ping
method is invoked periodically to check the liveliness of the CP. If the CP does not respond within a configurable timeout then the CP is ejected from the common context.
# Request
Contains no additional arguments.
# Response
Should contain no additional result.
# Example
<<<
{
"jsonrpc": "2.0",
"id": "101",
"method": "ContextParticipant.Ping"
}
>>>
{
"jsonrpc": "2.0",
"id": "101",
}
# ContextAgent
The ContextAgent
interface is used by the CM to perform actions when its Perform method is invoked. A single application may implement both the ContextParticipant as well as this interface, thus both taking the participant and agent role simultaneuosly.
# ContextAgent.ContextChangesPending
Invoked when this agent must perform an action. The arguments are;
# Request
ActionIdentifier
[string] contains the name/identifier of action to run.Subject
[string] contains the subject of the action if available.ItemNames
[string[]] the names of the input arguments for the action.ItemValues
[string[]] the values of the input arguments corresponding to theItemNames
on index.AgentCoupon
[long] an identifier for this agent.ContextCoupon
[long] an identifier for this “transaction”.Principal
[string] the identifier of the CM asking for the action to be run.
# Response
The response should contain:
Decision
[string]"accept"
if the action was run successfully,"cancel"
otherwise.Reason
[string] a human-readable message if the action failed.ItemNames
[string[]] a list of names for the output generated by the action.ItemValues
[string[]] a list of values for the names inItemNames
.
# Example
<<<
{
"jsonrpc": "2.0",
"id": "102",
"method": "ContextAgent.ContextChangesPending",
"params": {
"ActionIdentifier": "Plus",
"ItemNames": ["A", "B"],
"ItemValues": [100, 200],
"AgentCoupon": 3001,
"ContextCoupon": 2001,
"Principal": "foobar"
}
}
>>>
{
"jsonrpc": "2.0",
"id": "102",
"result": {
"Decision": "Accept",
"ItemNames": ["A+B"],
"ItemValues": [300]
}
}
# ContextSession
The ContextSession
interface contains methods for creating and activating context sessions. Each session is run by its own CM and has the following properties:
color
is a color which participants can use to indicate session participation (in their own UI),tag
is a unique string which can be assigned when the session is created.
The tag
is unique in the sense that if the Create
method is invoked with an already existing tag then the existing session is returned and no new session is created.
The following methods can be found in this interface:
# Create
This method is used to create a new session. If a tag
is given and an existing session exists which has the same tag then the existing session is returned. A newly created session starts by setting itself as the active session.
# Request
The value for method
is "ContextSession.Create"
.
The following arguments are applicable to this invocation:
Tag
[string, optional] is the “unique” tag assigned to the newly created session. If a session with an identical tag already exists then no new session is created and the existing session is returned.Color
[string, optional] which color to apply to the session. You can supply a hex value or a named color. If no color is specified the CM will choose from its own palette.NoFullAuto
[bool, optional] iftrue
then the session will not attach automatically to discovered applications but let the user do this. Default isfalse
.
# Response
The response contains the following properties:
ComponentId
[string] the id of the session/context.
# Example
>>>
{
"jsonrpc": "2.0",
"id": "200",
"method": "ContextSession.Create",
"params": {
"Tag": "Foo",
"Color": "green",
}
}
<<<
{
"jsonrpc": "2.0",
"id": "200",
"result": { "ComponentId": "1234" }
}
# Activate
This method is used to activate a session. There can only be one “active” session at a time. The active session is the session that will automatically attach to new applications if it runs in FullAuto
mode. Non-active sessions will still be synchronising context and for external applications the difference between having joined an active vs inactive session is not noticeable.
# Request
The value for method
is "ContextSession.Activate"
.
The following arguments are applicable to this invocation:
ComponentId
[string, required] is the identifier of the session/context to activate.
# Response
The response contains the following properties:
ComponentId
[string] the id of the session/context.
# Example
>>>
{
"jsonrpc": "2.0",
"id": "201",
"method": "ContextSession.Activate",
"params": { "ComponentId": "1234" }
}
<<<
{
"jsonrpc": "2.0",
"id": "201"
}
# ParticipantMonitor
This interface is not part of the CCOW standard and only contains notifications. It is optional to implement but the intent is to provide the participant with more information about the other participants in the same context.
# ParticipantsChanged
This notification is sent whenever a participant change occurs in the common context. When a new CP joins it will also get a number of these notifications to notify about current members.
# Request
ApplicationName
[string] is the identifier for the CP (not its context coupon)Event
[string] is the event which occurred, can be:"ParticipantJoined"
"ParticipantLeft"
"ParticipantAlreadyHere"
"ParticipantSuspended"
"ParticipantResumed"
# Example
<<<
{
"jsonrpc": "2.0",
"method": "ParticipantMonitor.ParticipantsChanged",
"params": {
"ApplicationName": "Foo",
"Event": "ParticipantJoined"
}
}
# ApplicationLaunched
This notification is sent whenever the CM launches an application as e.g. part of a Perform
invocation.
# Request
ApplicationName
[string] is the identifier for the CP (not its context coupon)Hwnd
[long] is the window handle for the launched applicationPid
[int] is the id of the process launched
# Example
<<<
{
"jsonrpc": "2.0",
"method": "ParticipantMonitor.ApplicationLaunched",
"params": {
"ApplicationName": "Foo",
"Hwnd": 1234,
"Pid": 4321
}
}
# Transport protocols
We support a few different transport protocols for the JSON-RPC message protocol. The following describes how to connect and interact using them.
# NamedPipes
The NamedPipes transport uses two bi-directional pipes.
The first pipe is used for the interfaces in which the client/CP sends requests to the server/CM. Those are
The pipe is named JSON-RPC v1/Context{Manager,Data,Action}/<Username>
and a server endpoint is created by the CM. The <Username>
part should be replaced by the windows username of the current user. The client must connect to it with
PipeDirection = InOut
TransmissionMode = Message
Once the CP issues a JoinCommonContext
and receives a ParticipantCoupon
the CP must now connect to the second pipe in order for the CM to use the ContextParticipant
and ParticipantMonitor
interfaces.
This second pipe must be created as a client pipe with the same properties as the first and the CM will initiate the server end after the JoinCommonContext
invocation successfully completes.
This pipe is named JSON-RPC v1/ContextParticipant/<Username>/<ParticipantCoupon>
.
The reason why two named pipes are needed is such that the strict request/response sequence can be maintained and that the client and server may agree on this sequence based on the which requests/notifications/errors are issued by either.
The encoding for both pipes is UTF-8.
# WebSockets
The WebSockets transport is conceptually simple. Initiating a connection and joining a context is done in one step by connecting to the url:
ws(s)://localhost:<port>/v2/ContextManager/JoinCommonContext
The arguments for JoinCommonContext
should be given as query parameters in the url e.g. ...?ApplicationName=<applicationname>&ComponentId=<componentid
. Furthermore the arguments for ContextSession.Create
can be provided as well. This will correspond to invoking the .Create
method before joining the context and the resulting session (created or matched on tag) will be used. In this case you will not need to provide componentId
.
The port
for the WebSocket server can be read from the registry at HKCU\Software\Sirenia\Manatee\Ports\websocketserver
and HKCU\Software\Sirenia\Manatee\Ports\websocketserversecureselfsigned
depending on wether a secure connection is needed.
Once the connection is established the fully duplexed interaction may begin with all interfaces using the same WebSocket.
# Netstring
The Netstring transport is a raw TCP stream over which JSON-RPC messages are encoded using the Netstring (opens new window) scheme. Netstring is a simple encoding scheme in which the format is:
<byte-count>:<data>,
Where <data>
are the bytes of an UTF-8 encoded string.
So for instance the JSON-RPC request:
{
"jsonrpc": "2.0",
"id": "1",
"method": "ContextManager.JoinCommonContext",
"params": {
"ApplicationName": "Foo",
"ComponentId": "100",
"SendContextInTxMethods": true
}
}
would be encoded as:
156:{"jsonrpc":"2.0","id":"1","method":"ContextManager.JoinCommonContext","params":{"ApplicationName":"Foo","ComponentId":"100","SendContextInTxMethods": true}},
# Connection
The client should connect to the locahost:<port>
where <port>
can be found in the registry at HKCU\Software\Sirenia\Manatee\Ports\netstringtcp
or HKCU\Software\Sirenia\Manatee\Ports\netstringtcpsecure
. The TCP stream is encrypted using SSL for the secure connection and the server certificate is written to disk at %appdata%/Sirenia/Manatee/certs
and the registry at HKCU\Software\Sirenia\Manatee\Certs\netstringtcpsecure
if the client wishes to use it for validation.