A number of tools are provided that generate the special interface or class files that are required by the Bojangles environment from hand written files provided by a programmer.
Bojangles requires a number of class and interface definitions for each business object. The tools described below can generate most of these files so that the actual burden on the programmer is very small. In order to reduce complexity a set of naming conventions are followed for these files. Briefly the files and their naming convention are (assuming that the base name of the business object is XXX and it is to be managed by the YY base collection):
The following tools are provided. Note: all tools take as input the compiled version of the file not the source version. Thus to run the tool you must be able to compile its input file. This is the main reason for hand writting the interface files.
Assume that XXX is the name of the application object's interface and that YY is the name of the base collection that the object will be used with. Only the XXXBase file is produced by hand, all the other files are completely generated. (You may also choose to hand-write the XXX file.)
XXXBase--+------------>XXX--+-------------->XXXStub | | | | | +-------------->XXXSkeleton | +------------>XXXImpl------------->XXXYYMO
In the above, Java source files are produced and compiled java files (class files) are used to produce the next step. For example, XXXBase.java is compiled to produce XXXBase.class which is then used to generate XXX.java, which is then compiled to produce XXX.class which is used produce XXXStub.
For some CORBA and BaseCollection features more information is needed to drive the emitting process than can be extracted from the Java class files as they are produced by the compiler. For example, CORBA supports one-way methods, but there is no way to indicate this in Java source. However, Java class files have an architected extension mechanism that allows additional information to be added to the class file that will not effect its use by interpreters. Therefore, we have developed a utility that takes a file (XXXBase.attributes) with attribute name/value pairs in it and adds the information to the class file. Currently we do not support any features that require this extra information, but we will soon. When we begin to use attribute files the data flow will become:
XXXBase.attributes XXXBase.java | | +-------+-------+ | v XXXBase.class | +------------+---+-----------+------------------+ | | | | v v v v XXX.attributes XXX.java XXXImpl.attributes XXXImpl.java | | | | +------+-----+ +----------+-------+ | | v v XXX.class XXXImpl.class | | +-------+-------+ | | | | v v v XXXStub.java XXXSkeleton.java XXXYYMO.java
Only the XXXBase.attributes and
XXXBase.java files need to be
handwritten. Although, it is frequently best to also handwrite the
XXX file.
These two programs (called the base emitters) are convenience tools
provided to help in generating and maintaining application
objects. They can save a lot of effort during the development of an
application object.
Basicially, these tools allow you to maintain one simple Java
source file and generate the Java interface and implementation files
required for the Bojangles environment. You don't have to use these tools,
it is quite reasonable to produce your interface and implementation
files manually.
The concept behind these tools is to maintain one class file that
contains a field definition for each of your attributes and provides
an implementation for each of the methods you need to implement your
object's interface. If you are developing an application object whose
interface is to be called XXX, then the file that you hand write should
be called XXXBase.java. From this file, RunInterfaceEmitter will generate an
interface file, XXX.java. RunImplEmitter will generate an implementation
class file, XXXImpl.java, that "implements" XXX and "extends" XXXBase.
Whenever you change XXXBase.java in a way that affects its interface
you must regenerate both XXX.java and XXXImpl.java.
The XXX.java file will extend COM.ibm.jaws.mofw.Manageable. The
XXXImpl.java file will provide implementations for any of the methods
required by Manageable that you don't provide in your base file. In
addition the base emitters will provide interfaces and implementations
for each of your object's "attributes".
Follow these steps in your base file implementation
Usually, application objects have a number of get/set method
pairs that are referred to as attributes. Usually each get method
returns the value of a field in the object and each set method
sets the value of the same field.
For each read/write attribute you want to have, define a field in
your base file with the "protected" access attribute. For example:
If you define a field that is final, then only a get method
will be generated for it.
If you have a more complicated requirement for some of your
attributes then declare their associated fields as private and
define your own get/set methods.
Make all fields that you don't want to become attributes
"private".
Access fields in your object directly not by their get/set
methods. (This is more efficient.)
Issue: The Impl emitter cannot generate externalizeToStream and
internalizeFromStream support for private fields, therefore all
persistent fields need to be protected (or public). This will
result in the generation of get/set methods for these fields. It
should be possible to indicate that a protected field is NOT an
attribute and prevent the generation of get/set methods. This will
be added in the next release of these tools. In the meantime you
can use the emitters to generate externalizeToStream and
internalizeFromStream methods and then copy the methods back to
your base file and edit their content. You will have to maintain
these two methods after this as their presence in your base file
will prevent their generation into the impl file.
Issue: Bojangles does not support direct externalization of
Java objects that do not support the interface
COM.ibm.jaws.mofw.Manageable, except for
java.lang.String. Therefore you cannot have attributes (fields
with get/set methods) or persistent fields that are other types of
Java object (such as arrays, Vectors, URLs, etc.). If the objects
you want to use are subclassable then you can subclass them an
make them Manageable (write internalize/externalize methods for
them). If they are not subclassable or you don't want to make them
manageable then you cannot make them attributes and if you want to
make them persistent will will have to write your own
internalize/externalize methods as described above. When Java
serialization support becomes widely deployed we will remove this
restriction.
For each method that you want to be in your object's interface
define a method in your base file with the "public" access
attribute. For example:
Make all methods that you don't want in your interface either
private or protected. (Static methods will also not become a part
of your interface.)
The base implementation emitter will generate
externalizeToStream and internalizeFromStream methods for you
based on your object's fields. Each "public" or "protected",
non-"transient", non-"static", field will be written out and read in.
To enhance the value of generated externalizeToStream and
internalizeFromStream methods an interface,
COM.ibm.jaws.motk.Activation, is provided. The generated
externalizeToStream will call the prepareForExternalization method
from this interface before begining externalization. This allows
you to update any of your persistent fields from transient data if
necessary. The generated internalizeFromStream will call activate
from this interface after internalization is complete. This allows
you to update any transient state after internalization. You may
also find it convient to use activate after object
construction. For example, you might new-up an instance of one of
your objects. Call a series of set methods to initialize its state
and then call activate to finish its initialization. You might also
call activate from any constructors that fully initialize the
object.
If this is not correct or you need to do more then you must
define these methods yourself. You can use the emitters to
generate externalizeToStream and internalizeFromStream methods and
then copy the methods back to your base file and edit their
content. You will have to maintain these two methods after this as
their presence in your base file will prevent their generation
into the impl file.
If you don't provide implementations of these methods then the
base implementation emitter will generate default implementations of
them that do nothing.
The base emitters are run from a command line with the compiled
version of your base file as input. The syntax of the commands are:
Where:
For example:
Where:
Note:A restriction in the current Bojangles distribution support
requires that you generate stub and skeletons with the same package as
their interface class. This restriction will be removed shortly.
Where:
Note:A restriction in the current Bojangles distribution support
requires that you generate stub and skeletons with the same package as
their interface class. This restriction will be removed shortly.
To run RunFlexMOEmitter to generate a managed object file from an impl
file, type the following command. Your impl file must support the
interface COM.ibm.jaws.mofw.Managable. This emitter will add the
methods and fields required by the FlexBC base collection for objects
it will manage. If you object is a key-in-data type of object then
your impl file must also support a method, getKey,
which returns your object's key. Future versions of FlexBC will allow
other ways to specify how to derive a key from the object's data. If
you will be suppling the key in the create calls for you object then
you don't have to implement getKey.
In addition to producing an Managed object for FlexBC to use, you
need to register this in the context.cfg file for your application.
(See the
documentation for SimpleRootBC for how to do this.)
Where:
In addition to producing an Managed object for SimpleRootBC to use, you
need to register this in the context.cfg file for your application.
(See the
documentation for SimpleRootBC for how to do this.)
Where:
The SOM Emitter Framework is documented in a separate
document. This
is a Java package for developing emitter tools such as the ones
described above in this document.
User's Guides
RunInterfaceEmitter and RunImplEmitter
Base File Cookbook
protected int x;
protected String y;
Each such field will result in a get/set method pair being defined in
the generated interface file and corresponding method implementations
in the generated implementation file. For example:
public interface XXX {
// ...
public int x();
public void x(int value);
public String y();
public void y(String value);
// ...
}
and
public class XXXImpl extends XXXBase implements XXX {
// ...
public int x() { return x; }
public void x(int value) { x = value; }
public String y() { return y; }
public void y(String value) { y = value; }
// ...
}
public int computeValue() { /* ... */ }
This will produce a declaration in the generated interface
file. It will not produce anything in the generated implementation
file.
Running the Base Emitters
java COM.ibm.jaws.tools.emit.RunInterfaceEmitter
baseClass [ targetPackage ]
java COM.ibm.jaws.tools.emit.RunImplEmitter
baseClass [ targetPackage ]
java COM.ibm.jaws.tools.emit.RunInterfaceEmitter
COM.ibm.jaws.models.trs.UserBase COM.ibm.jaws.models.trs
java COM.ibm.jaws.tools.emit.RunImplEmitter
COM.ibm.jaws.models.trs.UserBase COM.ibm.jaws.models.trs
Each of these commands will produce files in the directory in which
the program is run with appropriate names (e.g., User.java and
UserImpl.java).
RunStubEmitter
To run RunStubEmitter to generate a stub file from an interface file, type
the following command.
java COM.ibm.jaws.tools.emit.RunStubEmitter
interface [ targetPackage ]
COM.ibm.jaws.models.trs.User
.
RunSkeletonEmitter
To run RunSkeletonEmitter to generate a skeleton file from an interface file, type
the following command.
java COM.ibm.jaws.tools.emit.RunSkeletonEmitter
interface [ targetPackage ]
COM.ibm.jaws.models.trs.User
.
RunFlexMOEmitter
java COM.ibm.jaws.tools.emit.RunFlexMOEmitter
impl [ targetPackage ]
COM.ibm.jaws.models.trs.UserImpl
.
RunSRootMOEmitter
To run RunSRootMOEmitter to generate a managed object file from an
impl file, type the following command. Your impl file must support the
interface COM.ibm.jaws.mofw.Managable. This emitter will add the
methods and fields required by the SRootBC base collection for objects
it will manage.
java COM.ibm.jaws.tools.emit.RunSRootMOEmitter
impl [ targetPackage ]
COM.ibm.jaws.models.trs.UserImpl
.
Tools for Service Providers