Wiki

Clone wiki

javarosa / TransportAPI

'''This is a work in progress and the API is not complete'''

New Transport API

The Transport API is concerned with handling the movement of data from a server to the client or from a client to a server.BR It handles the downloading of entities from the server and the upload of entities to the server in a generic way that can be easily changed.

Plus the API intends to provide a way of automatically adding HTTP Parameters and other Transport Level specifics with ease.

Problems with the existing Transport utility

  • We always want to download data from the server. The current transport utility does not have a modular generic way to doing this. Every developer had to implement a way of getting data from the server.
  • The handling of data in the current Transport utility was not far reaching. It did not cater for all use case scenarios and was prone to break if the expected data is not the one received.
  • The current Transport Utility does not cater for downloading other entities from the server like users, surveys etc.
  • The current Transport Utility also required a hard coded URL that points to the server. This is not generic enough.
  • Reusing of the code in the current Transport utility was always hard and prone to generating bugs.
  • Xforms had to be built with application. It required to recompile the application if you want to add new forms

A vision for the new Transport API

  • Provision of a downloading entities from the server.
  • Ability to download other entities other than forms from the server.
  • Eliminate the idea of adding forms to the application through recompiling the whole application.
  • Provision of adding HTTP Parameters to the message being sent.
  • Have a generic straight forward method handling transport messages.
  • Developing a reusable API.

Details of the Transport API

The API is very extensible. The capabilities are extended by implementing interfaces that will enable you define new types of Transporters e.g. SMS, Http and Blue tooth.

'''Interface - TransportMessage'''

This is one of the interfaces that you need to implement in order to extend the Transport Layer.

Each instance of TransportMessage has the ability to create a Transporter capable of sending itself.

  • Transporter createTransporter() -- This method creates a Transport capable of sending itself.
 public Transporter createTransporter(){
  return new SimpleHttpTransporter(this);
 }
  • boolean isCacheable() -- Some transport types can sensibly make use of the TransportService's persistent store (e.g. http), some others not (e.g. sms) so that when transport fails, messages are cached to be retried later. isCacheable() returns true if this kind of Message is cacheable
  • Object getContent() -- Return what is being transmitted
  • InputStream getContentStream() -- Retrieve the underlying contents in the input stream.
  • boolean isSuccess() -- Indicates if sending was successful or not
  • int getStatus() -- An integer representing the status of the message (Sent, cached or queued)
  • void setStatus(int status) -- Sets the status of the message in relation to the above.
  • String getFailureReason() -- Retrieves the reason detailing why the transport message failed to be transmitted.
  • void setFailureReason(String reason) -- Sets the reason why transmitting failed.
  • int getFailureCount -- The number of times unsuccessful attempts have been made to send.
  • String getCacheIdentifier() -- Every message is persisted in the transport cache before any attempt is made to send it When persisted in the transport cache, it is given a unique id. getCacheIdentifies() returns the cache-unique identifier assigned to the message
  • void setCacheIdentifier(String id) -- sets the message cache identifier. See above.
  • void setSendingThreadDeadline(long time) -- The TransportService first tries to send a message in a SenderThread. This poses an issue: if the SenderThread is interrupted unexpectedly, a TransportMessage could be stuck with a CACHED status and never get onto the CACHED list to be sent via the "sendCached" method. To prevent Messages being stuck with a QUEUED status, a time-limit is set, after which they are considered to be CACHED.
  • long getQueuingDeadline() -- Retrieve the time at which the TransportService concludes that the message is no lonfer within its initial queuingThread.
  • Date getCreated() -- Date the message was created.
  • Date getSent() -- Date the message was sent.

'''Interface -- Transporter'''

This is the other interface that the developer extends inorder to add more capabilities to the Transport Layer.

A Transporter is given a TransportMessage in its constructor and has the ability to send it via the send method.

Example usage:

public SimpleHttpTransporter(SimpleHttpTransportMessage message) {
	this.message = message;
 }

The TransportService spawns a thread which calls the send method. So exceptions are caught and are recorded via message object methods:

  • setFailureReason() to set the reason the transmitting failed.
  • setStatus() -- to set the current status of the message.

'''Members'''

  • TransportMessage send() -- (Attempt to) send the message given to the Transporter in its constructor. It returns the message being sent.
  • TransportMessage getMessage() -- Gets the currently transmitting TransportMessage
  • void setMessage (TransportMessage message) -- Sets the Transport Message to send.

'''Interface - TransportCache'''

The TransportService needs persistent storage. The TransportCache interface define the persistent storage in terms of a message cache.

'''Members'''

  • String cache(TransportMessage message) throws TransportException -- Put a message in storage by caching. Returns the cached message
  • void decache(TransportMessage message) throws TransportException -- Remove a message from permanent cache.
  • void updateMessage(TransportMessage message) throws TransportException - Updates a message in the store.
  • TransportMessage findMessage(String id) -- Retrieves a message from the store given a valid id.
  • int getCachedMessagesCount() -- returns the number of records in the cache store.
  • Vector getCachedMessages() -- Retrieves all the cached messages in the store.
  • clearCache() -- Clear the cache store. Removes all the messages.

'''Note'''

In future, we should probably use the new storage API for this other than defining our own Transport utility store.

'''Interface -- TransportListener'''

The TransportListener listens for changes on the Transport Layer messages

'''Members'''

  • void onChange(TransportMessage message,String remark) -- fired when the message changes.
  • void onStatusChange(TransportMessage message) -- Fired when the status of a transmitting message changes.

'''Interface -- TransportException'''

TransportExceptions are used to wrap other exceptions to provide applications which make use of the TransportService a clear indication of the provenance of the exceptions.

'''Members'''

  • String getMessage() - Returns the message of the the underlying exception which is an instance of java.lang.Throwable.

'''Class -- TransportService'''

The TransportService is generic. Its capabilities are extended by defining new kinds of Transport.

The idea of a TransportService is to create an intuitive programmer interface which involves very few steps required to perform an action.

  • create a Message
  • Ask the TransportService to send the Message
TransportMessage m = new SomeTransportMessage() 
TransportService.send(m);

Implementing a Transport Method Using the API

Using the API, the expectation is that different Transport Methods (SMS, HTTP, etc) are implemented using the '''TransportMessage''' as the entry point for developers, specifically through the '''createTransporter()''' method and the '''Transporter''' which it returns.

Although many complex parameters are available for customizing the details of how a message is carried through the transport service, most asynchronous messages can be implemented by subclassing the '''BasicTransportMessage''' class, which handles many of the aspects with reasonable default behavior.

Since using the transport layer might involve utilizing information specific to what the application wants to do at the time (URL for sending data, authorization credentials for connecting, or even synchronous communication), the '''TransportMessage''' is expected to be created and used in a way which provides this information at the time of use and then handed to the Transport Service. When implementing a new transport method, developers should expose access to this data when the message is created. Preferably through the constructor.

For example, the '''SimpleHttpTransportMessage''' requires a payload and a destination URL to be sent, which it takes in through its constructors.

Once a message is created, it must be able to create an appropriate transporter to transport it. In this example, the SimpleHttpTransporter which uses TCP/IP to connect to a URL and transport a message. The SimpleHttpTransporter implements the majority of the business logic for negotiating the connection and streaming content, also relying on the message to deliver method-specific details like message headers.

This Simple Transporter is spawned per message, although the nature of the interface also allows for a reference to an existing Transporter to be returned, to allow for more complex sending logic to be used.

Updated