All Packages Class Hierarchy This Package Previous Next Index
In OOD modelling terms, a Manageable object can be thought of as a "dataflow" (in the message model). It's job is to push and pull its essential state (ED) into and out of a "source" (InputEDStream) or "sink" (OutputEDStream).
It is expected that most Manageable objects will need to override the Java Object equals() method in order to make a comparison based on state (as one implementation, the "other" object could be streamed and the contents of the stream read and compared with the essential state of the target object).
Also, due to a limitation of Java, if you provide any constructor
methods at all, then Java will not build a "default" (i.e. parameterless)
constructor for you automatically. Therefore a The OP provides an interface for the application-specific
methods, as well as a class that implements the Manageable
interface. As a convention, the interface name (eg, Employee)
is used for the implementation class with an "Impl" suffix
(eg, EmployeeImpl).
These methods interface defines the methods to allow objects to
control how their state is read or written to streams. Streaming of
objects is used for things like:
A feature of these methods is that they allow a Manageable
object to keep its internal member data definitions independent
from its EssentialDataSchema (EDS), which is a contract with the client of the
Manageable object. This allows an OP to change the member data
definitions of a Manageable object without changing its EDS,
which may be important for class migration without changing
the disk format or the schema mapping of the Manageable objects.
For a Manageable object that does not need
to keep its EDS independent of its internal
member data, tools can generate these methods
from its member data.
See the OutputEDStream, InputEDStream interfaces
for methods with which you read/write internal EssentialData.
The basic model is relatively simple as the
following example of a "Streamable" cotton bale shows:
Assume the bale has internal variables to deal with the net weight,
tare (packing materials) weight, gross weight, the "grade" (grade
would be a Streamable object in its own right), and a reference to the
"gin" that produced the bale from the raw cotton. In this case,
any one of the three weights can be derived from the other two.
Since the "tare" and "net" weights are the smallest two, they will
be the ones stored.
Also, the relationship to a "gin" is assumed to a by reference, so
it is exported as a Managed object. The assumption here is that
the cotton system has only one BaseCollection of gins, so this BC
can be factored out of the identifier written.
Finally, the relationship to a "grade" is assumed to be by value,
so it is exported as an object.
This example does not show how "sequences" of known length are
written to the Stream. One approach is to write the length to the
stream first, then individually stream each element according to the
above rules (possibly recursively). Reading sequences implies the same
thing: read the length, then each individual element. Another approach
is to use a "writeBegin()" and "writeEnd()" calls at the beginning
and end of the sequence (instead of writing the length at the beginning).
Then, during InternalizeFromStream(), a "readBegin()" should take place
first, then an "atEnd()" should be checked prior to each sequence entry,
with a "readEnd()" taking place after the loop is complete.
The reason this was not shown in the above example is that OP's
should avoid using sequences and use collections instead
(BaseCollection, NamedCollection, and/or ReferenceCollection
types). The latter approach was not shown because it is more useful
in "iterator" type behaviors.
One final point to make about Manageable. It is optional, but
highly recommended that your Java class file be usable as an
EssentialDataSchema (EDS) of the expected contents of the Stream
prior to an internalize and/or after and externalize. To this you
must make sure that all of your non-essential fields are marked
transient.
This would look like this for the CottonBale class.
However, this approach has some limitations that need to be addressed,
since the Java language does not capture all of the information necessary for
an EDS.
Name indicates the role that this essential data item plays
in the object.
MOFW indicates the relationship this item maintains with the
Managed Object Framework by either calling out a MOFW Interface (or "Java"
to indicate that it is a Java object or primitive).
Type a string indicating the actual interface or primitive java
type of the essential data item.
Manager indicates whether the object is: a) managing the
identity and activation of the entry itself (via "Self"), b) delegating to the
stream passed in (by using "Stream"), or c) delegating to some other
base collection (through "Base"). The ramification is in how the
externalization is done.
Cardinality indicates the maximum number of values are allowed
and how the actual number will be indicated in the Stream. An actual number
indicates a limit is known prior to runtime (for example, 1), and nothing is
written/read from the stream. A Java type of "boolean", "short", "int" or
"long" indicates that a value of that type will be written/read prior to any
entries to limit the cardinality at runtime. A "*" indicates that the list is
unbounded.
Fixed indicates whether the number of items indicated in the
cardinality are required to be present or not. If "false" (or if the cardinality
is unbounded) then "begin-end" style programming used for variable length
sequences is required.
Readonly is used to indicate that the essential data item is not
updated by any method associated with the Manageable object. This can be
used to increase "store" performance in mapped streams. For example, if all
essential data items are readonly, then the object need not be flushed to
disk at the end of a transaction (nor must it's before image get saved).
A complete EDS for a Cotton Bale might look like this:
public class CottonBale extends Manageable {
public void externalizeToStream(OutputEDStream stream) {
stream.writeShort(netWeight);
stream.writeShort(tareWeight);
stream.writeObject(grade);
stream.writeManaged(ginBC, (Managed)gin);
}
The call to note here is that for calling externalize recursively
on the grade field. This is done because a bale has the grade
"by value" rather than by reference (as is the case for the gin).
public void internalizeFromStream(InputEDStream stream) {
netWeight = stream.readShort();
tareWeight = stream.readShort();
grade = (Grade)stream.readObject("Grade");
gin = (Gin)readManaged(ginBC, "Gin");
}
Note how this code exactly matches the order of the externalization.
The only differences are the read vs. write calls.
public class CottonBaleImp implements CottonBale, Manageable {
protected short netWeight;
protected short tareWeight;
protected GradeImp grade;
protected URLStream ginRef;
transient protected Gin gin;
}
Name MOFW Type Mgr Card Fixed Readonly
---------------------------------------------------------------
netWeight Java short Self 1 true false
tareWeight Java short Self 1 true false
grade Manageable Grade Stream 1 true false
gin Managed Gin Base 1 true false
externalizeToStream(OutputEDStream)
internalizeFromStream(InputEDStream)
externalizeToStream
public abstract void externalizeToStream(OutputEDStream stream) throws EDStreamFormatError
OutputEDStream
in which to
write the object's essential data.
internalizeFromStream
public abstract void internalizeFromStream(InputEDStream stream) throws EDStreamFormatError
InputEDStream
from which to
read the object's essential data.
All Packages Class Hierarchy This Package Previous Next Index