# Class RestStateRelay

java.lang.Object
com.codename1.continuity.RestStateRelay

All Implemented Interfaces:
  `StateRelay`

public class RestStateRelay extends Object implements StateRelay

A `StateRelay` over your own HTTPS endpoint, which is all most applications need.

    Continuity.setRelay(new RestStateRelay("https://api.example.com/continuity") {
        protected String getToken() {
            return session.getAccessToken();
        }
     });

##### The contract

Two requests against the one URL you supply:

- `POST` with the state as a JSON body and `Content-Type: application/json`. Store it against the signed-in user, replacing whatever you held for them. Any 2xx means stored.
- `GET`, answering with the newest state you hold for that user as the same JSON, or an empty body when you hold none. A 404 also means none.

The JSON is exactly what `StateCodec.toJson(AppState)` produces, and it is a closed shape: your endpoint stores and returns the document, and never needs to look inside it.

##### Identity is yours

Which states belong to the same person is the one question the framework cannot answer, which is why the token comes from `getToken()` rather than from a constructor: it is read at each request, so a session that refreshes its token is followed automatically. Return null for an endpoint that identifies the user some other way -- a cookie, mutual TLS -- and the header is simply omitted.

##### Threading

Both methods are called from a background thread and block, which is what the framework expects of a relay. `getToken()` is called on that same thread, so it must not wait on the event dispatch thread.

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `RestStateRelay(String url)`
  Creates a relay against an HTTPS endpoint.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `AppState`
  `fetch()`
  Asks for the newest state this user has on any device.
  `protected String`
  `getToken()`
  The bearer token to present, read once per request.
  `String`
  `getUrl()`
  The endpoint this relay talks to.
  `void`
  `publish(AppState state)`
  Sends a state.

  ### Methods inherited from class Object

  `clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Constructor Details

  - ### RestStateRelay

    public RestStateRelay(String url)

    Creates a relay against an HTTPS endpoint.

    ###### Parameters

    - `url`: the endpoint, which must be HTTPS

    ###### Throws

    - `IllegalArgumentException`: when the URL is null, empty or not HTTPS

- ## Method Details

  - ### getUrl

    public String getUrl()

    The endpoint this relay talks to.

    ###### Returns

    the URL

  - ### getToken

    protected String getToken()

    The bearer token to present, read once per request. The default returns null, which sends no `Authorization` header.

    ###### Returns

    the token, or null for none

    ###### Changing accounts

    Install a NEW relay for the new account -- `Continuity.setRelay(StateRelay)` -- rather than returning a different account's token from the same object. A publish that was authorised for the previous account can still be between the framework's last check and this read when the switch happens, and the framework cannot bind a token it is not allowed to read. What it can recognise is an object that is no longer installed, which it then refuses; an object that quietly starts answering for someone else looks identical to one that refreshed its own session.

  - ### publish

    public void publish(AppState state) throws IOException
    Description copied from interface: `StateRelay`

    Sends a state. Called after each checkpoint, so implementations that talk to a slow endpoint should coalesce rather than send every one.

    ###### Parameters

    - `state`: the state to send

    ###### Throws

    - `java.io.IOException`: when the send failed. The framework logs it and keeps the state, which the next checkpoint's publisher sends -- unless a newer state has superseded it by then, or the user signed out in between. It is not retried on a timer: one attempt per change beats spinning against an endpoint that is down.
    Specified by:
      `publish` in interface `StateRelay`
    Throws:
      `IOException`

  - ### fetch

    public AppState fetch() throws IOException
    Description copied from interface: `StateRelay`

    Asks for the newest state this user has on any device. Returning this device's own most recent state is fine and expected -- the framework recognizes its own echo by device id and sequence, and ignores it.

    ###### Returns

    the state, or null when the endpoint has nothing

    ###### Throws

    - `java.io.IOException`: when the fetch failed
    Specified by:
      `fetch` in interface `StateRelay`
    Throws:
      `IOException`