Address Types
Three types of addresses are defined in the system:
- agent addresses,
- component addresses,
- node addresses.
Agent Addresses and Component Addresses
Both AgentAddress
and ComponentAddress
interfaces consist of an unique identifier, an optional friendly name and the address of the node they were created on.
Address identity is based on the identifier, but only within a given implementing class. This means that different address implementation with same identifiers will not be equal. This identity is preserved across serialization, so instances can be send over a network.
The user friendly name does not need to be unique, and is optional - the default user friendly name is the identifier itself.
Addresses can be converted into string in two ways: the standard toString
method will represent the address using its userFriendly name, and thus is not guaranteed to be unique. The specialized toQualifiedString
will instead use the identifier and produce an unique string.
Node Addresses
The NodeAddress
interface consist only in an unique identifier. Instances are comparable, in order to resolve ordering and priority policies in distributed environments.
As the interface itself is made comparable, in order to introduce a correct ordering, implementations should only rely on the identifier to compare node addresses. That is precisely what the AbstractNodeAddress
class does, and its reuse is highly recommended.
The default NodeAddress
implementation creates an identifier on the base of the JVM process ID and the hostname it is running on.
All addresses are immutable through the entire lifetime of the system.
Address Suppliers
Address instances can be created manually or mocked, which is useful in tests. However, in actual practical configuration, factories are used. Each of the address types listed above come with a corresponding Supplier
, which is an interface with a single get() method.
An agent needs only to interact with an AgentAddressSupplier
, but this factory implementations will generally depend on a NodeAddressSupplier.
Sample configuration
The code below shows the fragment of the configuration that defines some suppliers. It is recommended to declare the agent address supplier in the workplace manager scope, as this factory is only relevant to agents.
<component name="nodeAddressSupplier" class="org.jage.address.node.DefaultNodeAddressSupplier" /> <component name="workplaceManager" class="org.jage.pico.PicoWorkplaceManager"> <component name="agentAddressSupplier" class="org.jage.address.agent.DefaultAgentAddressSupplier" /> ... </component>
Adressing agents
Your implementation needs to provide an address to the AbstractAgent
super class constructor. The best way to do it is to inject an instance or supplier from the configuration:
public class MyAgent extends AbstractAgent { public MyAgent(AgentAddress address) { super(address); } @Inject public MyAgent(AgentAddressSupplier addressSupplier) { this(addressSupplier.get()); } ... }
Templates for user friendly agent names
The default implementation of AgentAddressSupplier
is able to generate unique user friendly names, based on a provided template. The template can contain wildcards, which will be replaced by consecutive numbers for each consecutive address:
<component class="org.jage.address.agent.DefaultAgentAddressSupplier" /> <constructor-arg name="nameTemplate" value="TheXFiles"/> </component>
You can then take advantage of component shadowing and provide a different template to different agents:
<component name="defaultAddressSupplier" class="org.jage.address.agent.DefaultAgentAddressSupplier" /> <constructor-arg name="nameTemplate" value="conscript*"/> </component> <agent name="conscript" class="com.myapp.MyAgent /> <agent name="warrior" class="com.myapp.MyAgent> <component class="org.jage.address.agent.DefaultAgentAddressSupplier" /> <constructor-arg name="nameTemplate" value="warrior*"/> </component> </agent> <agent name="archer" class="com.myapp.MyAgent> <component class="org.jage.address.agent.DefaultAgentAddressSupplier" /> <constructor-arg name="nameTemplate" value="archer*"/> </component> </agent>