See the [ActiveStack SyncEngine API documenation](https://github.com/ActiveStack/syncengine/blob/update_optimizations/API.md) for more details.
## Login
```json
{
"cn": "com.app.mo.Person", // Or whatever the actual class name of the `Person` object is
"userId": "", // The `UserToken`.`User`.`ID` from the `AuthenticationResponse`
}
```
```json
{
"token": "",
"messageId": "",
"refreshToken": "DEV",
"accessToken": "",
"deviceId": "",
"clientType": "",
"userId": "",
"cn": "com.percero.agents.auth.vo.AuthenticateOAuthAccessTokenRequest",
"regAppKey": "",
"clientId": null,
"redirectUri": null,
"authProvider": "GOOGLE"
}
```
```json
{
"token": "",
"code": "",
"clientType": "",
"redirectUri": "http://myapp.com/oauth2callback.html",
"deviceId": "",
"userId": "",
"cn": "com.percero.agents.auth.vo.AuthenticateOAuthCodeRequest",
"regAppKey": "",
"clientId": "",
"messageId": "",
"requestToken": null,
"authProvider": "GOOGLE",
"requestSecret": null
}
```
### Disconnect SyncEngine
When a client disconnects, the ActiveStack SyncEngine expects a [`DisconnectRequest`](https://github.com/ActiveStack/syncengine/blob/master/src/main/java/com/percero/agents/sync/vo/DisconnectRequest.java), which informs the SyncEngine that this client is no longer connected.
```json
{
"cn": "com.percero.agents.sync.vo.DisconnectRequest",
"clientId": "",
"deviceId": "",
"token": "",
"userId": ""
}
```
### Disconnect Auth
When a client disconnects, the ActiveStack SyncEngine expects a [`DisconnectRequest`](https://github.com/ActiveStack/syncengine/blob/master/src/main/java/com/percero/agents/auth/vo/DisconnectRequest.java), which informs the SyncEngine that this client is no longer connected.
```json
{
"cn": "com.percero.agents.auth.vo.DisconnectRequest",
"clientId": "",
"deviceId": "",
"token": "",
"userId": ""
}
```
### Logout
In order to logout, a client must send a [`LogoutRequest`](https://github.com/ActiveStack/syncengine/blob/master/src/main/java/com/percero/agents/sync/vo/LogoutRequest.java) to the ActiveStack SyncEngine.
```json
{
"pleaseDestroyClient": false, // If set to true, destroys all record of this client
"responseChannel": "",
"sendAck": true,
"clientType": "",
"token": "",
"deviceId": "",
"userId": "",
"cn": "com.percero.agents.sync.vo.LogoutRequest",
"regAppKey": "",
"clientId": "",
"messageId": "",
"svcOauthKey": ""
}
```
## Core API
- All `className` references assume that the corresponding class is part of the registered data model, meaning it is included in the `ActiveStack.Domain` module.
### [connect](https://github.com/ActiveStack/syncengine/blob/156ea8927fba9681f8b547662904073a45f990b1/src/main/java/com/percero/amqp/handlers/ConnectHandler.java)
This connect request is NEVER seen by the client, but is handled under the hood by the ActiveStack Gateway. It is included here for the sake of completeness. Note that the `ConnectResponse` IS sent to the client, indicating that the client is now connected to the ActiveStack SyncEngine and can commence sending requests.
NOTE: The `clientId`, `userId`, and `token` in this `ConnectResponse` are to be sent with every subsequent request to the ActiveStack SyncEngine.
Request:
```json
{
"cn": "com.percero.agents.sync.vo.ConnectRequest",
"clientId": "",
"deviceId": "",
"token": "",
"userId": ""
}
```
Response:
```json
{
"cn": "com.percero.agents.sync.vo.ConnectResponse",
"clientId": "",
"timestamp": 1460480647867,
"ids": null,
"data": null,
"type": null,
"correspondingMessageId": null,
"gatewayMessageId": null,
"currentTimestamp": 1460480647867,
"dataID": null
}
```
### [reconnect](https://github.com/ActiveStack/syncengine/blob/156ea8927fba9681f8b547662904073a45f990b1/src/main/java/com/percero/amqp/handlers/ReconnectHandler.java)
When a client loses connection to ActiveStack, it can send a [`ReconnectRequest`](https://github.com/ActiveStack/syncengine/blob/156ea8927fba9681f8b547662904073a45f990b1/src/main/java/com/percero/agents/sync/vo/ReconnectRequest.java) to the SyncEngine. This is to let the SyncEngine know that this client has come back online.
NOTE: The `clientId`, `userId`, and `token` in this `ReconnectResponse` are to be sent with every subsequent request to the ActiveStack SyncEngine. Also, a reconnect always results in a NEW client id being assigned to the client.
Request:
```json
{
"cn": "com.percero.agents.sync.vo.ReconnectRequest",
"existingClientId": "",
"existingClientIds": [
"",
"",
""
],
"clientId": "",
"deviceId": "",
"token": "",
"userId": ""
}
```
Response:
```json
{
"cn": "com.percero.agents.sync.vo.ConnectResponse",
"clientId": "",
"timestamp": 1460480647867,
"ids": null,
"data": null,
"type": null,
"correspondingMessageId": null,
"gatewayMessageId": null,
"currentTimestamp": 1460480647867,
"dataID": null
}
```
### [findById](https://github.com/ActiveStack/syncengine/blob/156ea8927fba9681f8b547662904073a45f990b1/src/main/java/com/percero/amqp/handlers/FindByIdHandler.java)
Request:
```json
{
"token": "",
"messageId": "",
"responseChannel": "",
"sendAck": true,
"clientType": "",
"deviceId": "",
"userId": "",
"cn": "com.percero.agents.sync.vo.FindByIdRequest",
"regAppKey": "",
"clientId": "",
"theClassId": "",
"theClassName": "com.app.mo.MyModelObject",
"svcOauthKey": ""
}
```
### [findByIds](https://github.com/ActiveStack/syncengine/blob/156ea8927fba9681f8b547662904073a45f990b1/src/main/java/com/percero/amqp/handlers/FindByIdsHandler.java)
Request:
```json
{
"token": "",
"messageId": "",
"responseChannel": "",
"sendAck": true,
"clientType": "",
"deviceId": "",
"userId": "",
"cn": "com.percero.agents.sync.vo.FindByIdsRequest",
"regAppKey": "",
"clientId": "",
"theClassIdList": [
{
"className": "com.app.mo.MyModelObject",
"ids": [
"",
"",
"",
...
""
]
}
],
"svcOauthKey": ""
}
```
### [getAllByName](https://github.com/ActiveStack/syncengine/blob/156ea8927fba9681f8b547662904073a45f990b1/src/main/java/com/percero/amqp/handlers/GetAllByNameHandler.java)
Request:
```json
{
"token": "",
"returnTotal": true,
"responseChannel": "",
"sendAck": true,
"theClassName": "com.app.mo.MyModelObject",
"clientType": "",
"pageSize": 25,
"deviceId": "",
"userId": "",
"pageNumber": 0,
"cn": "com.percero.agents.sync.vo.GetAllByNameRequest",
"regAppKey": "",
"clientId": "",
"messageId": "",
"svcOauthKey": ""
}
```
Response:
```json
{
"cn": "com.percero.agents.sync.vo.GetAllByNameResponse",
"clientId": "",
"timestamp": 1460480792894,
"ids": null,
"data": null,
"type": null,
"correspondingMessageId": "",
"gatewayMessageId": null,
"result": [
{
"cn": "com.app.mo.SomeModelObject",
"ID": "",
"someStringField": "..."
},
{
"cn": "com.app.mo.SomeModelObject",
"ID": "",
"someStringField": "..."
}
],
"pageSize": 2,
"pageNumber": 0,
"totalCount": 82
}
```
### [findByExample](https://github.com/ActiveStack/syncengine/blob/156ea8927fba9681f8b547662904073a45f990b1/src/main/java/com/percero/amqp/handlers/FindByExampleHandler.java)
Request:
```json
{
"token": "",
"responseChannel": "",
"sendAck": true,
"clientType": "",
"deviceId": "",
"userId": "",
"cn": "com.percero.agents.sync.vo.FindByExampleRequest",
"regAppKey": "",
"clientId": "",
"messageId": "",
"theObject": {
"cn": "com.app.mo.Person",
"userId": "8ad0360a3a89d53f013b1a99f14d0130"
},
"svcOauthKey": ""
}
```
Response:
```json
{
"cn": "com.percero.agents.sync.vo.FindByExampleResponse",
"clientId": "129d41c01ba2476e01bbb12f0ba50cd5",
"timestamp": 1460480779167,
"ids": null,
"data": null,
"type": null,
"correspondingMessageId": "",
"gatewayMessageId": null,
"result": [
{
"cn": "com.app.mo.MyModelObject",
"ID": "",
"someTimestampField": 1353312000000,
"someStringField": "...",
"someToManyProperty": [
{
"className": "com.app.mo.MyToManyObject",
"ID": ""
},
{
"className": "com.app.mo.MyToManyObjectChildClass",
"ID": ""
}
],
"someToOneProperty": {
"className": "com.app.mo.MyToOneObject",
"ID": ""
}
}
]
}
```
### [putObject](https://github.com/ActiveStack/syncengine/blob/156ea8927fba9681f8b547662904073a45f990b1/src/main/java/com/percero/amqp/handlers/PutObjectHandler.java)
Request:
```json
{
"token": "",
"responseChannel": "",
"sendAck": true,
"clientType": "",
"deviceId": "",
"transId": "",
"userId": "",
"cn": "com.percero.agents.sync.vo.PutRequest",
"regAppKey": "",
"clientId": "",
"messageId": "",
"theObject": {
"someIntegerPropertyName": 12345,
"someToOnePropertyName": {
"className": "com.app.mo.SingleModelObject",
"ID": "",
"properties": {}
},
"someToManyPropertyName": [
{
"className": "com.app.mo.OtherModelObject",
"ID": "",
"properties": {}
},
{
"className": "com.app.mo.OtherModelObject",
"ID": "",
"properties": {}
}
],
"cn": "com.app.mo.MyModelObject",
"someDoublePropertyName": 12.345,
"ID": "",
"someStringPropertyName": "..."
},
"putTimestamp": ,
"svcOauthKey": ""
}
```
Response:
```json
{
"cn": "com.percero.agents.sync.vo.PutResponse",
"clientId": "",
"timestamp": 1460481711169,
"ids": null,
"data": null,
"type": null,
"correspondingMessageId": "",
"gatewayMessageId": null,
"result": true
}
```
### [createObject](https://github.com/ActiveStack/syncengine/blob/156ea8927fba9681f8b547662904073a45f990b1/src/main/java/com/percero/amqp/handlers/CreateObjectHandler.java)
Request:
```json
{
"token": "",
"responseChannel": "",
"sendAck": true,
"clientType": "",
"deviceId": "",
"userId": "",
"cn": "com.percero.agents.sync.vo.CreateRequest",
"regAppKey": "",
"clientId": "",
"messageId": "",
"theObject": {
"someStringProperty": "...",
"someToManyProperty": [],
"ID": "",
"cn": "com.app.mo.MyModelObject",
"someToOneProperty": {
"className": "com.app.mo.SingleModelObject",
"ID": "",
"properties": {}
}
},
"svcOauthKey": ""
}
```
Response:
```json
{
"cn": "com.percero.agents.sync.vo.CreateResponse",
"clientId": "",
"timestamp": 1460481616555,
"ids": null,
"data": null,
"type": null,
"correspondingMessageId": "",
"gatewayMessageId": null,
"theObject": {
"cn": "com.app.mo.MyModelObject",
"ID": "",
"someStringField": "...",
"someToManyProperty": []
},
"result": true
}
```
### [removeObject](https://github.com/ActiveStack/syncengine/blob/156ea8927fba9681f8b547662904073a45f990b1/src/main/java/com/percero/amqp/handlers/RemoveObjectHandler.java)
Request:
```json
{
"token": "",
"responseChannel": "",
"removePair": {
"className": "com.app.mo.MyModelObject",
"ID": "",
"properties": {}
},
"sendAck": true,
"clientType": "",
"deviceId": "",
"userId": "",
"cn": "com.percero.agents.sync.vo.RemoveRequest",
"regAppKey": "",
"clientId": "",
"messageId": "",
"svcOauthKey": ""
}
```
Response:
```json
{
"cn": "com.percero.agents.sync.vo.RemoveResponse",
"clientId": "",
"timestamp": 1460481797411,
"ids": null,
"data": null,
"type": null,
"correspondingMessageId": "",
"gatewayMessageId": null,
"result": true
}
```
### [getChangeWatcher](https://github.com/ActiveStack/syncengine/blob/156ea8927fba9681f8b547662904073a45f990b1/src/main/java/com/percero/amqp/handlers/GetChangeWatcherHandler.java)
Request:
```json
{
"token": "",
"responseChannel": "",
"sendAck": true,
"params": [
""
],
"clientType": "",
"regAppKey": "",
"deviceId": "",
"fieldName": "role",
"userId": "",
"cn": "com.percero.agents.sync.vo.PushCWUpdateRequest",
"classIdPair": {
"className": "com.app.mo.MyModelObject",
"ID": "",
"properties": {}
},
"clientId": "",
"messageId": "",
"svcOauthKey": ""
}
```
Response:
```json
{
"cn": "com.percero.agents.sync.vo.PushCWUpdateResponse",
"clientId": "",
"timestamp": 1460481097749,
"ids": null,
"data": null,
"type": null,
"correspondingMessageId": "",
"gatewayMessageId": null,
"classIdPair": {
"className": "com.app.mo.SomeModelObject",
"ID": ""
},
"fieldName": "role",
"params": [
""
],
"value": {
"className": "com.app.mo.ResultModelObject",
"properties": null,
"ID": ""
}
}
```
### [runServerProcess](https://github.com/ActiveStack/syncengine/blob/156ea8927fba9681f8b547662904073a45f990b1/src/main/java/com/percero/amqp/handlers/RunProcessHandler.java)
- Runs a custom server process. This process can be a custom piece of code, a defined HTTP process, a defined SQL stored procedure, or some other defined Connector.
- Request: [`RunServerProcessRequest`](https://github.com/ActiveStack/syncengine/blob/master/src/main/java/com/percero/agents/sync/vo/RunServerProcessRequest.java)
- Response: [`RunServerProcessResponse`](https://github.com/ActiveStack/syncengine/blob/master/src/main/java/com/percero/agents/sync/vo/RunServerProcessResponse.java)
- Parameters:
- `queryName`: The name of the process. To use a specific Connector (such as 'HTTP' or 'SQL_PROC' for database stored procedures), prefix the operation name of the Connector name and a ":". Example: "HTTP:fetchDataFromHttpEndpoint"
- `queryArguments` (optional): Any required parameters for the server process. Typically, this is passed as some sort of map (parameterName -> parameterValue)
Request:
```json
{
"queryName": "",
"deviceId": "",
"userId": "",
"shardedProcess": false,
"svcOauthKey": "",
"clientId": "",
"responseChannel": "",
"queryArguments": [
"arg1",
12.345,
12345
],
"cn": "com.percero.agents.sync.vo.RunProcessRequest",
"regAppKey": "",
"clientType": "",
"sendAck": true,
"serviceGroupId": null,
"messageId": "",
"processId": null,
"token": ""
}
```
## Client Responses
### Push Updates Received
Whenever the ActiveStack SyncEngine sends out an update, it expects to receive a [`PushUpdatesReceived`]() response from the client. This lets the ActiveStack SyncEngine know that the client has received and processed the update. The SyncEngine will continue to attempt to push the same update out to the client until the client responds with the `PushUpdatesReceived` response.
Request:
```json
{
"token": "",
"responseChannel": "",
"sendAck": true,
"clientType": "",
"deviceId": "",
"userId": "",
"cn": "com.percero.agents.sync.vo.PushUpdatesReceivedRequest",
"regAppKey": "",
"clientId": "",
"messageId": "",
"classIdPairs": [
{
"className": "com.app.mo.MyModelObject",
"ID": "",
"properties": {}
}
],
"svcOauthKey": ""
}
```
Response:
```json
{
"cn": "com.percero.agents.sync.vo.PushUpdatesReceivedResponse",
"clientId": "",
"timestamp": 1460481757415,
"ids": null,
"data": null,
"type": null,
"correspondingMessageId": "",
"gatewayMessageId": null,
"result": true
}
```
### Deletes Received
Whenever the ActiveStack SyncEngine sends out a remove/delete, it expects to receive a [`DeletesReceived`]() response from the client. This lets the ActiveStack SyncEngine know that the client has received and processed the delete. The SyncEngine will continue to attempt to push the same delete out to the client until the client responds with the `DeletesReceived` response.
```json
{
"token": "",
"responseChannel": "",
"sendAck": true,
"clientType": "",
"deviceId": "",
"userId": "",
"cn": "com.percero.agents.sync.vo.PushDeletesReceivedRequest",
"regAppKey": "",
"clientId": "",
"messageId": "",
"classIdPairs": [
{
"className": "com.app.mo.MyModelObject",
"ID": "",
"properties": {}
}
],
"svcOauthKey": ""
}
```
Response:
```json
{
"cn": "com.percero.agents.sync.vo.PushDeletesReceivedResponse",
"clientId": "",
"timestamp": 1460481861735,
"ids": null,
"data": null,
"type": null,
"correspondingMessageId": "",
"gatewayMessageId": null,
"result": true
}
```
## Pushes from SyncEngine
This is really where the real-time aspect of ActiveStack comes into play. The main point here is that clients are notified of updates to objects that they are currently interested in. It is up to the client SDK to respond appropriately to these update notifications.
### PushUpdateResponse
Sent whenever an object has been updated for which a client has registered to receive updates.
Request:
```json
{
"cn": "com.percero.agents.sync.vo.PushUpdateResponse",
"clientId": "",
"timestamp": 1460482040672,
"ids": null,
"data": null,
"type": null,
"correspondingMessageId": null,
"gatewayMessageId": null,
"objectList": [
{
"cn": "com.app.mo.MyModelObject",
"ID": "",
"someStringProperty": "..."
}
],
"updatedFields": []
}
```
### DeleteUpdateResponse
Sent whenever an object has been deleted for which a client has registered to receive updates.
Request:
```json
{
"cn": "com.percero.agents.sync.vo.PushDeleteResponse",
"clientId": "",
"timestamp": 1460481912713,
"ids": null,
"data": null,
"type": null,
"correspondingMessageId": null,
"gatewayMessageId": null,
"objectList": [
{
"className": "com.app.mo.MyModelObject",
"ID": ""
}
]
}
```