Chapter 7 • Software
Components 257
String toString; The return types Constructor, Field, and Method are defined in the package
java.lang.reflect .
7.3.2 Reification
For the meta-level to be able to reflect on several objects, especially if they are instances of different classes, it must be given information regarding the internal structure of objects. This
meta-level object must be able to find out what are the methods implemented by an object, as well as the fields attributes defined by this object. Such base-level representation, that is
available for the meta-level, is called structural meta-information. The representation, in form of objects, of abstract language concepts, such as classes and methods, is called reification.
Base-level behavior, however, cannot be completely modeled by reifying only structural aspects of objects. Interactions between objects must also be materialized as objects, so that meta-level
objects can inspect and possibly alter them. This is achieved by intercepting base-level operations such as method invocations, field value inquiries or assignments, creating operation objects that
represent them, and transferring control to the meta level, as shown in Figure 7-3. In addition to receiving reified base-level operations from the reflective kernel, meta-level objects should also
be able to create operation objects, and this should be reflected in the base level as the execution of such operations.
A reflective kernel is responsible for implementing an interception mechanism. The method invocation is reified as an operation object and passed for the callee’s meta-object to reflect upon
handle. Eventually, the meta-object requests the kernel to deliver the operation to the callee’s replication object, by returning control as in the diagram or performing some special meta-level
action. Finally, the result of the operation is reified and presented to the meta-object.
caller kernel
op : Operation res : Result
handleop : MetaObject
methodarg obj : Object
methodarg
result createobj, method, arg
op
result createop, result
res handleres
Figure 7-3. Reifying an operation. See text for explanation.
Ivan Marsic • Rutgers University
258
Show example of reflection using DISCIPLE Commands in Manifold Reflection enables dynamic run-time evolution of programming systems, transforming
programs statically at compile-time to add and manage such features as concurrency, distribution, persistence, or object systems, or allowing expert systems to reason about and adapt
their own behavior. In a reflective application, the base level implements the main functionality of an application, while the meta level is usually reserved for the implementation of management
requirements, such as persistence [28,34], location transparency [26], replication [8,18], fault tolerance [1,2,9,10] and atomic actions [35,37]. Reflection has also been shown to be useful in the
development of distributed systems [6,20,36,40,41] and for simplifying library protocols [38].
http:www.dcc.unicamp.br~olivaguaranadocsdesign-htmlnode6.htmltransparency A recent small project in Squeak by Henrik Gedenryd to develop a Universal Composition
system for programs. It essentially involves a graph of meta-objects describing source- composition operations which can be eagerly or lazily statically or dynamically driven, resulting
in partial evaluation or forms of dynamic composition such as Aspect-Oriented Programming AOP.
7.3.3 Automatic Component Binding
Components can be seen as pieces of a jigsaw puzzle, like molecular binding—certain molecule can bind only a molecule of a corresponding type.
7.4 State Persistence for Transport
A class is defined by the Java bytecode and this is all that is necessary to create a fresh new instance of the class. As the new instance object interacts with their objects, its state changes.
The variables assume certain values. If we want a new instance resume from this state rather than from the fresh initial state, we need a mechanism to extract the object state. The mechanism is
known as object serialization or in the CORBA jargon it is called object externalization [OMG- CORBA-Services].
Object serialization process transforms the object graph structure into a linear sequence of bytes, essentially a byte array. The array can be stored on a physical support or sent over the network.
The object that can be serialized should implement the interface java.io.Serializable. The object essentially implements the methods writeObject and readObject. These
methods define how to convert the component attributes, which represented by programmer- defined data types, to a one-dimensional bytestream.
When restoring the object, we need to have its class bytecode because class definition is not stored in the serialized state. If the receiving process does not know the objects class, it will
throw the java.io.SerializationError exception. This may be a problem if we are
Chapter 7 • Software
Components 259
sending the object to a server which is running all the time and cannot load new classes, so its class loader cannot know about the newly defined class. The solution is to use the method:
byte[] getBytes;
which is available on every java.lang.Object object, i.e., on every Java object. The method returns a byte array—a primitive data type, which can be used by the server to reconstruct the
object there.
JAR file contains: • Manifest file
• Classes next to the class name, there is a Boolean variable “bean” which can be true or false
• Bean customizers Beans provide for a form of state migration since the bean state can be “canned” serialized and
restored on a remote machine unlike an applet which always starts in an initial state after landing on a remote machine. However, this is not object migration since the execution state program
counters for all threads would need to be suspended and resumed. Persistency is more meant to preserve the state that resulted from external entities interacting with the bean, rather than the
state of the execution, which would be possible to resume on another machine.
7.5 A Component Framework
Here I present a component framework that I designed, which is inspired by several component frameworks existing in research laboratories. Compared to JavaBeans, this framework is more
radical in enforcing the component encapsulation and uniformity of communication with it.
7.5.1 Port Interconnections
Options for component wiring are illustrated in Figure 7-4. The ports of different components can be connected directly, one-on-one. In the simplest case, output port of a component directly
connects to an input port of another component. Another useful analogy is wire, which is a broadcast medium to which multiple ports can be connected. Similar effect could be achieved by
the Publisher-Subscriber pattern see Section 4.1 above, but the Wire abstraction appears to be more elegant in the context of components and ports.
In the spirit of object-oriented encapsulation, components as defined here share nothing—they have no shared state variables. The communication is entirely via messages. Of course,
communication via ports is limited to the inter-component communication. Components contain one or more objects, which mutually communicate via regular method calls. Similarly,
components make calls to the runtime environment and vice versa, via method calls. The only requirement that is enforced is that components communicate with each other via ports only.