Jump to: navigation, search

SMILA/Project Concepts/ConnectivityMessageInterface

Description

This is an alternative concept for the Connectivity Interface. It does not use a traditional structured API but a message like approach. Attached is a sample implementation that illustrates the usage: [^ConnectivityInterface.zip].

Technical proposal

Interface

The interface has only one method that processes the incoming message and creates a response message.

    public class ConnectivityManager
    {
        Message process(Message msg) throws Exception
    }


Message Objects

A Message can be either a REQUEST to Connectivity or a RESPONSE by Connectivity. This is the Type of the message. It also contains and identifier for an Action that is/was performed. And finaly a message has a MessageItem, the content of the message. Type and Action are Enumerations, that can be extended easily.

public class Message
{
    Type type;
    Action action;
    MessageItem item;
}
 
public enum Type 
{
    REQUEST, RESPONSE
}
 
public enum Action 
{
    DI_INIT, DI_CHECK_FOR_UPDATE, DI_FINISH, DI_DELETE, // delta indexing
    ADD, UPDATE, DELETE,                                // indexing
    CLEAR                                               // management
}


The MessageItem is an abstract base class for concrete MessageItem classes. Each concrete MessageItem has a name and a value. If additional MessageItem classes are needed, they can be introduced easily just by extending the abstract base class MessageItem. In this way, the content of a message can be assembled in any way. How a message has to be assembeled depends on Type and Action.

public abstract class MessageItem
{
    String name;
 
    public MessageItem(String name)
    {
        this.name = name;
    }
}
 
public class MessageItemList extends MessageItem
{
    MessageItem[] value;
 
    MessageItemList(String name, int size)
    {
        super(name);
        value = new MessageItem[size];
    }
}
 
public class RecordItem extends MessageItem
{
    Record value;
 
    public RecordItem(String name, Record record )
    {
        super(name);
        value = record;
    }
}
 
public class IDItem extends MessageItem
{
    ID value;
 
    public IDItem(String name, ID id )
    {
        super(name);
        value = id;
    }
 
}
 
public class StringItem extends MessageItem
{
    String value;
 
    public StringItem(String name, String string )
    {
        super(name);
        value = string;
    }
 
}
 
public class BooleanItem extends MessageItem
{
    boolean value;
    public BooleanItem(String name, boolean bool )
    {
        super(name);
        value = bool;
    }
}
 
public class IntegerItem extends MessageItem
{
    int value;
    public IntegerItem(String name,  int integer )
    {
        super(name);
        value = integer;
    }
}


MessageItem Structure

As said before, the structure of a message item depends on the Type and Action. For each combination of Type/Action a MessageItem structure has to be defined. Here is a table of some simple examples. These are by no means final. If a message needs additional data it can easily be redefined. The data could also be represented in other ways, for example the REQUEST/DI_CHECK_FOR_UPDATE could also use a MessageItemList<MessageItemList<String, String>>. Or the ADD and UPDATE actiuons could only allow one RecordItem instead of a list of RecordItems

REQUEST RESPONSE
DI_INIT StringItem BooleanItem
DI_CHECK_FOR_UPDATE MessageItemList<RecordItem> MessageItemList<BooleanItem>
DI_FINISH StringItem BooleanItem
DI_DELETE StringItem IntegerItem
ADD MessageItemList<RecordItem> IntegerItem
UPDATE MessageItemList<RecordItem> IntegerItem
DELETE MessageItemList<IDTem> MessageItemList<IntegerItem>
CLEAR StringItem BooleanItem

The same applies to names for MessageItems. In some cases there may be no need for explicit names, in other cases the might be helpful to distinguish between different information. Here are two examples for complete Message objects used during delta indexing check for update. The Request contains a list of EILFRecords with delta indexing information (ID and hash). The Response contains a list of boolean. The index of both lists match, so that the result for a record at request\[x\] can be found at response\[x\]. The examples are represented in XML syntax for better readability. Note that the XML representation of the EILFRecord is just a sample.

<?xml version="1.0" encoding="UTF-8"?>
<Message xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Message.xsd">
<Message>
    <Type>REQUEST</Type>
    <Action>CHECK_FOR_UPDATE</Action>
    <MessageItemList name="recordCheckList">
        <RecordItem name="1">
            <EILFRecord>
                <ID>1</ID>
                <Hash>aaa</Hash>
            </EILFRecord>
        </RecordItem>
        <RecordItem name="2">
            <EILFRecord>
                <ID>2</ID>
                <Hash>bbb</Hash>
            </EILFRecord>
        </RecordItem>
        <RecordItem name="3">
            <EILFRecord>
                <ID>3</ID>
                <Hash>ccc</Hash>
            </EILFRecord>
        </RecordItem>
    </MessageItemList>
</Message>
<?xml version="1.0" encoding="UTF-8"?>
<Message xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Message.xsd">
    <Type>RESPONSE</Type>
    <Action>CHECK_FOR_UPDATE</Action>
    <MessageItemList name="recordFeedbackList">
        <BooleanItem name="1">true</BooleanItem>
        <BooleanItem name="2">true</BooleanItem>
        <BooleanItem name="3">false</BooleanItem>
    </MessageItemList>
</Message>


Utilities

To make the usage of the MessageItems easier for developers we could also provide Factory classes for creation of certain messages.

public interface MessageFactory
{
    static Message createAddRequest(EILFRecord[] records)
 
    static Message createAddResponse(int count)
 
    static Message createCheckForUpdateRequest(EILFRecord[] records);
 
    static Message createCheckForUpdateResponse(boolean[] values);
 
    ...
}


Message Objects vs plain XML Messaging

The idea of the Message Objects was to provide a Java API in the first place. By using SCA it is easily possible to also use the interface remote, either via RMI or Webservice interface. However, there are some issues regarding component upgrades. Imagine a setup where components are hosted by different departments and each department has it's own update cycle. This will certainly lead to different software versions of components. So an updated IRM could use a newer Version of the Message Objects (e.g. with additional Actions) than the called ConnectivityModule.

  • plain XML

With a plain XML message concept, using a version flag, it's possible to decide during parsing if Connectivity is capable of processing a given message and a message could be declined (e.g. sending a response or throwing an exception). It's possible to allow downwards compatibility to certain versions.

  • RMI

Objects exchanged over RMI need to be serializable. This implies the usage of a serialVersionUID, by which the JVM can check if a serialized data fits to the current available .class file. If not, a InvalidClassException is thrown. The serialVersionUID usualy changes on any modifications. However, it is also possible to assign the serialVersionUID manually. In this way the serialVersionUID could be maintained on non conflicting changes (e.g. changes that do not affect the serialized data). It's not possible to be downwards compatible, as it is only checked if the serialVersionUID is equal. Adding a new value to an Enum may be seen as a non conflicting change - it is NOT. During de-serialization the JVM throws a java.lang.IllegalArgumentException. So in case of Message Objects the serialVersionUID needs also to be changed if any of the used Enums changes.

  • Webservice

The Tuscany generated Webservice interface doesn't care about the serialVersionUID used in serializable classes. Here we would have to use an own version flag. It is also a little more flexible concerning Enums, as if it does not know about a value it initializes the variable with null (no Exception). It's possible to allow downwards compatibility to certain versions.

The biggest problem is that RMI and Webservices behave differently and the client has to be prepared to handle any exceptions, as the binding is configurable. Also, there may be many dependencies in the serializable Message Objects and deciding if modifications need to change the serialVersionUID may not be obvious.