CEnvelope

The envelope is a part of every message. It contains all data necessary to deliver this message to a target in nyssr.net .

There are a few methods for creating envelopes.

Send to a microservice

The following method can be used to send a message to a microservice. The system looks for a microservice with just this ID and then enters the fully qualified target address.

@NotNull
public static CEnvelope forMicroService(@NotNull final IId aMicroServiceId);

Send to a nano service in the same node

To send a message to a nano service in the same node, the following method can be used. The namespace in which this nano service was registered is required:

@NotNull
public static CEnvelope forLocalNanoService(@NotNull final IId aNID);

The generated record class can also be used. But the record must be a nano service and must contain the namespace where the nano service was registered.

@NotNull
public static CEnvelope forLocalNanoService(@NotNull final Class aClass) throws CException;

Send to a nano service on another node

These methods are used to create an envelope for a message to another node.

@NotNull
public static CEnvelope forRemoteNanoService(@NotNull final IId aNID,
                                             @NotNull final CNodeId aNodeId);
@NotNull
public static CEnvelope forRemoteNanoService(@NotNull final IId aNID,
                                             @NotNull final CNodeAddress aNodeAddress);
@NotNull
public static CEnvelope forRemoteNanoService(@NotNull final Class aClass,
                                             @NotNull final CNodeAddress aNodeAddress) throws CException;

Send directly to a target

If the address of a target is known, you can also use these methods:

@NotNull
public static CEnvelope forSingleTarget(@Nullable final IId aTID,
                                        @Nullable final IId aNID,
                                        @Nullable final CNodeId aNodeId);
@NotNull
public static CEnvelope forSingleTarget(@Nullable final IId aTID,
                                        @Nullable final IId aNID,
                                        @Nullable final CNodeAddress aNodeAddress);
@NotNull
public static CEnvelope forSingleTarget(final CTargetAddress aReceiver);

Copy

There is also a static copy method:

@NotNull
public static CEnvelope copy(@NotNull final CEnvelope aEnvelope);

Stream

Messages can of course also be read from a DataInput stream and written to a DataOutput stream:

@NotNull
public static CEnvelope fromStream(@NotNull final DataInput aStream) throws IOException;
public void toStream(@NotNull final DataOutput aStream) throws IOException;

Default constructor

public CEnvelope(){}

Sender

An envelope contains exactly one sender. Normally it is set by CTarget when sending the message. But it can also be set manually.

public void setSender(final CTargetAddress aSender);

The getter always returns an address, but it can be invalid (INVALID), if it has not been set before.

@NotNull
public CTargetAddress getSender();

Receiver

Normally, an envelope contains exactly one recipient address. This is sufficient to deliver a message nyssr.net-wide.

public void setReceiver(@Nullable final CTargetAddress aReceiver);
@NotNull
public CTargetAddress getReceiver();

In contrast to the sender, however, receivers are stored in a stack list, which means that several receivers can exist. However, it is not the case that this message is delivered to multiple receivers. Rather, this list is used to forward messages to additional receivers, after it has reached the first receiver.

If the envelope already has a valid receiver address, and another valid address is passed to setReceiver(), then a push() is performed. The new address is then the valid address. If zero is passed, a pop() is executed and the first address is discarded.

Accordingly, there is a method to fetch all the recipients.

@NotNull
public Stack<CTargetAddress> getReceivers();

Result

The envelope of a response always carries a result code and sometimes a result text. If the message has not been processed by the receiver, the reply carries the result code CResultCode.NOT_HANDLED. In case of technical errors in the delivery of the message (e.g. receiver unknown), the system enters a corresponding ResultCode. The user is required to provide messages that have been processed by him with a result code.

CResult is a small auxiliary class that contains code and text. There are many predefined codes in CResultCode.

public void setResult(final int aCode,
                      final String aText);
public void setResultSuccess();
public int getResultCode();
public String getResultText();
public CResult getResult();

Reply

Each envelope contains a Boolean in which it is noted whether a reply is desired. In this case the message is sent back to the sender by the system itself. This happens after leaving the handler. In case of errors during the delivery of the message, it will be sent back regardless of the user's request.

public void setIsAnswer(final boolean aIsAnswer);
public boolean isAnswer();
public void setWantAnswer(final boolean aWantAnswer);
public boolean wantAnswer();

The automatic handling of responses is an essential feature of nyssr.net . Whereas e.g. JMS focuses on saving messages until they are processed, nyssr.net uses the handshake for fast processing. Data is only considered to be reliably transferred when a positive response is received. Until the response arrives, the sender is always responsible for securing data. In return, however, he gets control over the process. He can thus send data to another destination, for example, or handle it alternatively.

A message contains a flag that indicates whether this message has been processed by the recipient. It corresponds to the return code of a message handler.

public void setHandled(final boolean aHandled);
public boolean hasBeenHandled();

There are some methods that are called by the system to be able to send a response. For this purpose the addresses must be swapped: the receiver address becomes the sender address and vice versa.

public CResult canSwap();
public CResult swap();

Blocked Messages

Messages cannot always be sent back immediately. Often, for example, the recipient itself must send messages to other destinations in order to process data. The message should not be returned as a response until it has been fully processed.

The recipient must therefore block the message to prevent it from being sent back automatically. Likewise, a method is needed to manually return a postponed message to the sender.

public void setBlocked(final boolean aBlocked);
public boolean isBlocked();

// send back manually
final IMessageSender messageSender = CServiceRegistry.getInstance().
                                                      getService(IMessageSender.class);
// or with a target
final IMessageSender messageSender = target.getMessageSender();

messageSender.sendBack(msg);

Forward messages

A message can be forwarded to another address in a message handler. This interrupts the normal process of sending back a response.

public void forwardMessage(final CTargetAddress aReceiver);
public boolean shallForward();

MicroService ID

We have seen above that envelopes can be created specifically for sending to network microservices. In this case, a microservice ID is passed. There are also methods for accessing this ID.

public void setMicroServiceId(@Nullable final IId aMicroServiceId);
public IId getMicroServiceId();

Nano service flag

When a message is sent from a nano service to Observer, it contains a special flag.

public void setIsNanoServiceMessage(final boolean aIsNanoMessage);
public boolean isNanoServiceMessage();

Transaction ID

Sometimes it is important to store data until a response to a message comes back. This is where a transaction ID comes into play, which is transported in the envelope. This ID is entered manually. In a Hashtable data can be saved so simply to this ID.

public void setTransactionId(@Nullable final UUID aId);
public UUID getTransactionId();

Only local

It can be forbidden that messages leave the own node. This is a security feature.

public void setOnlyLocal(final boolean aOnlyLocal);
public boolean isOnlyLocal();

Priority

Messages can be sent from node to node. At each hop, messages are stored in a queue. Messages with high priority are transported to the next node first.

While log messages or transport of file snippets are given low priority by the system, replies are given the highest priority by the system. The programmer can set a priority for each message himself.

public void setPriority(@NotNull final EPriority aPriority);
public EPriority getPriority();

Packet builder sequence

Messages can be compressed and encrypted by the system. This can be configured globally for nodes or connections, but also for each message directly. Currently, there are only three methods for processing streamed messages. They are identified by a letter. The order is important here:

  • M: stands for the message itself (always present, always at the beginning)
  • Z: stands for ZIP compression
  • A: stands for AES encryption

By default, only one M is entered for the message. Conceivable are also the combinations "MZ" for compressed messages and MZA for first compressed and then encrypted messages. The combination MAZ makes no sense, because encrypted messages are hardly compressible. By the way: Before nodes send encrypted messages to each other, they each create an RSA pair of keys and exchange the public keys with each other. This applies to each individual node pair.

public void setPacketBuilderSequence(final String aSequence);
public String getPacketBuilderSequence();

Another method checks if the message carries only the minimal "M" as PacketBuilderSequence.

public void setRawTransport();
public boolean isRawTransport();

Debug methods

The use of messages can always lead to errors that are strange at first sight. Therefore, there are a number of methods to help the programmer at work.

Messages contain multiple timestamps that are populated by the system.

public Instant getTimeSend();
public Instant getTimeDeliver();
public Instant getTimeSendBack();
public Instant getTimeDeliverAnswer();

public void setTimeSend(@Nullable final Instant aTimeSend);
public void setTimeDeliver(@Nullable final Instant aTimeDeliver);
public void setTimeSendBack(@Nullable final Instant aTimeSendBack);
public void setTimeDeliverAnswer(@Nullable final Instant aTimeDeliverAnswer);

Each envelope has a sequential number, that will NOT be copied or transported.

public void setInstanceId(final int aInstanceId);
public int getInstanceId();

Each envelope has a sequential number, that will be copied and transported. It is suitable for tracking message sequences. To track messages across node boundaries, the transaction ID can be used.

void setEnvId(final short aEnvId);
short getEnvId();

The debug mode can be switched on manually. It provides for the transport of debug data (timestamps) across node boundaries. By default, it is switched off.

public static void setDebug(final boolean aDebug);
public static boolean isDebug();

Message logging can be suppressed for each message.

public void setLogEnabled(final boolean aEnabled);

nyssr.net - Innovative Distributed System