JActor Factories

The JAFactory actor binds actor type names to actor factories, allowing type names to be used in place of class names for serialization/deserialization. There are 3 reasons for this:

Security--When deserializing, only those actor factories bound by an ancestor actor can be used.

Flexibility--A level of indirectness allows the use of different factories in different subsystems over time. And

Configurability--Different type names can be bound to the same actor class with different configurations by passing configuration data (meta data) in the factory's constructor or by using different factories. And this meta data need not be serialized.

The JLPCActor.initialize(Mailbox mailbox, Actor parent, ActorFactory factory) method is used by JAFactory to initialize the actors it creates. And the JLPCActor.getActorType() method returns either the name of the actor type or null if the actor has not been assigned an actor factory.

All actor factory classes, which are used to create, configure and initialize one type of actor, must extend the ActorFactory class:

package org.agilewiki.jactor.factory;

import org.agilewiki.jactor.Actor;

import org.agilewiki.jactor.Mailbox;

import org.agilewiki.jactor.lpc.JLPCActor;

abstract public class ActorFactory {

public final String actorType;

public ActorFactory(String actorType) {

this.actorType = actorType;

}

abstract protected JLPCActor instantiateActor()

throws Exception;

public JLPCActor newActor(Mailbox mailbox, Actor parent)

throws Exception {

JLPCActor a = instantiateActor();

a.initialize(mailbox, parent, this);

return a;

}

}

When binding an actor type to an actor class, JAFactory uses a default actor factory:

package org.agilewiki.jactor.factory;

import org.agilewiki.jactor.lpc.JLPCActor;

import java.lang.reflect.Constructor;

final public class _ActorFactory extends ActorFactory {

private Constructor constructor;

public _ActorFactory(String actorType, Constructor constructor) {

super(actorType);

this.constructor = constructor;

}

protected JLPCActor instantiateActor()

throws Exception {

return (JLPCActor) constructor.newInstance();

}

}

All of JAFactory's methods are thread-safe. This is because JAFactory uses a ConcurrentSkipListMap<String, ActorFactory> to bind type names to actor factories. And there are no Request classes defined to call methods of JAFactory, so you must call the methods directly or via one of the static methods that have been provided.

To define an actor type without an actor factory class, use the method defineActorType(String actorType, Class clazz). Alternatively, the method registerActorFactory(ActorFactory actorFactory) can be used when there is an actor factory class.

The static method JAFactory.getActorFactory(Actor actor, String actorType) returns an ActorFactory, where actor is either a JAFactory or has a JAFactory ancestor. But if no actor factory is found for the given actor type, then an IllegalArgumentException is thrown.

A number of static convenience methods are provided which return a new Actor: