Developing your System
This section details the elements necessary for developing Tymeac Systems in your
installation.
It's really very simple. It's the first time through here that's a little confusing.
Tymeac development comprises four elements:
- The Processing Application Class that executes the
application code.
- The Queue in which the Processing Application Class
resides.
- The Function in which the Queue resides.
- The Client that calls the Tymeac Server.
... and four related subjects:
- System Wide Variables
- Testing.
- The user exit structure.
- The overall structure.
For an overview of how the Client and Server interact, see
here.

A Tymeac Function is basically a list of Tymeac Queues.

A Tymeac Queue contains a list of waiting requests, called Wait Lists,
the Threads of execution that make Tymeac a multi-threading container and the Processing
Application Class that contains the user code.

A Processing Application Class is the code you write to process the
specifics of the application. A Tymeac Queue Thread uses reflection to invoke the main()
method of your class.
This is the decoupling that is so important in good application design. Multi-threading
is very difficult since not only does the developer have to write the application logic,
the developer also has to write the threading logic (wait(), notify(), synchronize() etc.)
You supply the application logic in a Processing Application Class. Tymeac handles the
threading logic.

Preface
A Client wants to execute a method on the Server and it wants the method to use current
data. Therefore, the Client passes the current data (what we call "input") to
the code. The Client wants two things from the Server:
- A response that says the Server worked perfectly.
- The result of the application method working on the current data, what we call
"returned data".
Let's say the Server calculates Celsius based on Fahrenheit. The Client passes a
Fahrenheit number "input" to the Server and the Server returns a Celsius number
"returned data" to the Client. Additionally, Tymeac includes a String indicating
how the Tymeac Server performed (not the underlying application.)
The Client can wait for the process to complete, a Synchronous Request.
The Client may not wait for the process to complete. This is an Asynchronous Request,
also called autonomous processing. In such a case, how would the Client ever know what
happened and where would the "returned data" go? The Server code could transmit
it to the Client in the network. Unfortunately, this would make the application code very
complex.
Tymeac's answer to overly complex applications is to separate the do-the-work from the
what-now. The application method (do-the-work) calculates the Celsius number, wraps it in
an Object and returns the Object to the Server. The Server returns the Object to the
Client for a Synchronous Request.
For the Asynchronous Request the Server may (this is optional) put the returned Object
in a Queue called the Output Agent Queue. An Output Agent Queue is just like any other
Tymeac Queue. It has Wait Lists, threads and another Processing Application Class that you
write. This is where you may put the what-now code.
For example, when you wish the Client to receive the "returned data" on the
network you would do the following:
First you must write two Processing Application Classes:
- DoTempConv -- Converts Fahrenheit.to Celsius.
- SendToNetwork -- Sends the Converted Object to the user.
Then you define
- a Tymeac Function called "Convert" that contains a normal
Tymeac Queue called "FtoC" (short for Fahrenheit to Celsius) and Output Agent
Queue called "PutOnNet".

- a Tymeac Queue called "FtoC" that uses a Processing
Application Class called "DoTempConv".

- a Tymeac Output Agent Queue called "PutOnNet" that uses a
Processing Application Class called "SendToNetwork".

Now at execution time:
The Client does an Asynchronous Request to the Tymeac Server passing the
Fahrenheit number "input"
The Tymeac Server puts the "input" into Queue
"Convert". A Queue Thread associated with this Queue picks up the
"input" and using Java Reflection invokes the main() method of Class
"DoTempConv".
The "DoTempConv" Class returns an Object "Converted"
to the Queue Thread.
The Queue Thread puts the "Converted" object, which is now a
new "input", into Queue "PutOnNet". An Output Agent Thread associated
with this Queue picks up the new "input" and using Java Reflection invokes the
main() method of Class "SendToNetwork".
The "SendToNetwork" Class passes the "Converted"
object to the network.

Now if that was all there was to Tymeac, then it would be a very nice backend process
manager. But there is more. Tymeac is also a Request Broker. Your Tymeac Functions may
contain multiple Tymeac Queues.
What if your "input" Fahrenheit number also needs converting to a second or
third scale? No problem. You simple write the Processing Application Class to do this
conversion. Define Tymeac Queues as above. Add the new Queues to the Tymeac Function. Now
when you execute this Tymeac Function, you get back all the conversions in one Object
array.
The details begin with the Processing Application Class.
Processing Application Class (or base Class)
If this is your first time through here, we suggest you take a quick tour of this material without all the detail.
Tymeac utilizes two types of applications:
- A normal application
This application receives input from a Client and may return an object.
The returned object may pass back to the calling Client or, when an asynchronous request,
the returned object may be passed on to an Output Agent application.
- An Output Agent application
This optional application receives the returned object(s) from the normal application(s)
for asynchronous requests.
That is just so confusing, but wait, examples are forthcoming.
Your Processing Application Class (base Class) must have a public static main() method
that accepts an Object array.
public static Object main(Object[] args) {}
public static void main(Object[] args) {} (has no returned data)
The Queue Thread uses a java.lang.reflect.Method invoke() for your base Class passing
an Object array (Object args[]) ):
- The first Object (arg[0]) is either
- the optional input data from the Tymeac Client contained in the Tymeac parameter,
Normal Processing ApplicationClass, or
- an Object array when this is an Output Agent Processing Application Class. The
Object array is the array of all the return Objects from the normal Processing Application
Classes. (See here.)
- The second Object (arg[1]) is a reference (TymeacInterface) to the
Tymeac Server. You may use this reference for recursion processing or pass it along to
another Class.
For examples see the Demo Classes we supply in the sample directory. A snippet of the
code is presented in the following documents.
Demo1.java -- is a normal Processing Application Class. It
receives input data from a Tymeac Client.
DemoAgent1.java -- is an Output Agent Processing
Application Class. It receives an Object array of the return Objects of the normal
Processing Application Classes.
DemoRecur.java -- is an example of recursion processing.
It uses the second argument (arg[1]) to call the Tymeac Server.
The main() method Return Type may be an Object, void, another class or
primitive. Tymeac passes the return value back to the Synchronous Request in an Object array or on to the Output Agent in an Object array. Therefore, it is up
to the receiving module to interpret this Object. (For maximum flexibility, we recommend
using a return type of Object and casting any return class to Object, or, wrapping a
primitive in an object and casting it to Object.)
The first object in the returned Object array is the result of Tymeac Processing.
This is always a String.
For a Synchronous Request:
Tymeac SR(0000)
- Tymeac is the prefix.
- SR stands for Synchronous Request.
- (nnnn) Return code, should be 0000. When the number in parentheses
is not zero, then check the return code document for the failure reason.
The other objects in the returned Object array are
the result of YOUR processing. YOUR objects may be any object that implements the interface
serializable.
For an Asynchronous Request there is only one String object in the
returned Object array:
Tymeac AR(0000)[session id, request id]
- Tymeac is the prefix.
- AR stands for Asynchronous Request.
- (nnnn) Return code, should be 0000. When the number in parentheses
is not zero, then check the return code document for the failure reason.
- The data in brackets are:
- Session Id -- The System time in milliseconds since
1970. MilliTime also appears on the start up and shut down messages It is the way to identify this session
of Tymeac. When you wish to inquire about the status of an asynchronous request, this Id
is necessary, see the Request Status Class.
- Request Id -- A unique number assigned to every request starting at one
(1). When you wish to inquire about the status or to cancel an asynchronous request, this
Id is necessary, see the Request Status Class.
For a Shut down Request there is only one String object in the returned Object array:
Tymeac SD(0000)
- Tymeac is the prefix.
- SD stands for Shut Down.
- (nnnn) Return code, should be 0000. When the number in parentheses
is not zero, then check the return code document for the reason.
The public is so that Tymeac may find your base Class. The static is
so that no instance of your base Class is necessary, eliminating constructors (called a
Class Method).
Since this main() is static other method references by code in main() must also
be static. However, there is no restriction on new instances of other Classes
(composition). his means that the main() method can be a base for the rest of your
functionality including loading other Classes, using a transport mechanism (like RMI or
CORBA) or Servlets.
The Queue Thread invokes your base Class with a:
Object return_data = ...invoke()...
The Output Agent Queue Thread invokes your Class with an:
...invoke()... ( no return value specified.)
Additional Subjects:
Canceling a working request
Yes, it is possible, see here.
Access
Tymeac needs access to your Processing Application Class therefore, Tymeac must be able to
load that class into the Java Virtual Machine. Two option are available:
- Using the Java Class Path:
Tymeac uses a custom Class Loader with the method, findSystemClass(), for your base
Class. The base Class is the Class you define in the Tymeac Queue. Therefore,
your base Class must be a local Class (on the CLASSPATH, -cp or codebase).
- Using URL's:
Tymeac uses a URLClassLoader with the list of URL's specified along with the class name.
See the class naming and URL document for details of how to specify a URL list.
Security
Tymeac handles Security Exceptions in that it sets all Queue Threads as unavailable for
requests (status: disabled). Therefore, you must address all security
issues before starting Tymeac Server.
You should catch exceptions.
The Tymeac Queue Thread invokes your base Class in a "try"
block. Exceptions for this reflect.Method are caught, including,
"Throwable". Tymeac processes a caught exception by logging a message, sending a
notification, and disabling the thread. If this is the action you wish to take, then
rethrow the exception. See also the return codes for Queue Threads.
When should you rethrow the exception? Anytime the situation requires manual
intervention, that is, it's broken beyond what error recovery code can handle. An example
is a corrupt file or database, a programming error or any critical resource that is not
available.
Once you rethrow the exception, the thread is marked "disabled". Once all
threads are "disabled" the Queue is no longer functional. The Tymeac Monitor
sends a notification when all threads are disabled.
If the exception was due to a programming error, then you may fix the logic, recompile
the module, use the New Copy to get a new copy of the Class
and enable the Queue Threads with the enable button on the Queue
Threads Display/Alter.
If you can fix the problem without taking down the Server then you may enable the Queue
Threads as above.
Re-loading Classes
During testing it is common that the base Class you develop may need adjusting. It is
not necessary to shut down and restart Tymeac every time a change is necessary. The Tymeac
Class, TyNewCopy, is available to re-load the base class or
load an alternate base Class during execution.
N.B. -- Classes already loaded by the Virtual Machine through a
classpath cannot be unloaded (at this time.) Therefore, if you need changes to the
base class, then you must use a URL to load the class. This also holds true for any
classes your base class loads. See the class naming and URL document.
Long running processes pose a potential problem.
Tymeac is a process NOW system. The structure is to accept a work request, process
that request as quickly as possible and fetch the next request. There is no facility
within Tymeac to process the request at a later time. However, there are numerous
middleware, message-queuing systems on the market. The scope of these systems is that
one sends a message (this could be the parameters for Tymeac) to a message queue with
instructions to deliver the message to another message queue at a later time.
Tymeac keeps track of the time the Queue Thread is executing within the reflection
invoked base class and may flag the Queue Thread as possibly stalled. The result of
this is that the Queue Thread's status becomes 'cancelled' or 'disabled'. When all
Queue Threads within a Queue have either of these status codes, the Queue cannot accept
any more requests (Scheduling failure).
If the processing is just slow, then the potential for a problem is small. However, if
this is truly a long running process then one may use the Queue timeout value to increase
the time Tymeac allows the reflection invoked code to execute before flagging it as
possibly stalled.
This flagging has no affect on the executing Processing Application Class. It simply
changes the Queue Thread's status code. If the Processing Application Class finishes
processing, the Queue Thread resets the status code.
Compiling:
The Tymeac Classes (TymeacInterface, TymeacParm, etc.) are in package com.tymeac.base,
in the directory, <TymeacHome>/Classes. Import the package com.tymeac.base
in the user classes that require access to the Tymeac Classes and include the proper
directory for the compiler.
"Sharing" conflicts:
Since your Processing Application Class runs as a Java Thread, there may be many threads
of execution using this same code. Java provides two ways for preserving integrity on
shared objects. These are:
- the synchronized modifier on the method definition
public synchronized void yourMethod() {}
- and the synchronized statement
synchronized (object) {}
When locking spans multiple methods, then the second way is preferable. However,
confusion sometimes arises over how one may get a reference to a shared object (the
(object) in the synchronized statement.)
The simplest way is to lock on a Class object (e.g. synchronized (MyClass.class) {}).
Another is to use a Singleton Class (i.e. There are numerous examples of this technique
in the Sun archives, developerWorks.com and JavaWorld.com.)
One common way is to use a public Class with static fields. See the User Exit
structure, below.
Not only does "synchronized" lock out other threads, it reads/writes the
thread's variables from/to main memory.
In Java, main memory is where all variables live. (See the Java Memory Model, Chapter
17 of the Java Language Specification) Each thread has a copy of the
variables it uses. When a thread writes a value to a variable, it is the thread's
copy of the variable that gets modified. Eventually, Java writes the value to main memory.
Therefore, if another thread looks at a variable, it may see the value of the main
memory variable before Java updates the main memory.
The solution is to synchronize.
"Java Synchronized" is only one way of working in a multi-threaded
environment. This is the simplest method, often called the "single
threaded" approach -- only one thread may access the resource at a time.
Inter-process communication using:
- shared memory,
- private semaphores,
- locks with a:
- DBMS,
- Queuing Facility, or
- JavaSpaces
- and any propriety software products provide many more.
However, one must remember that Tymeac controls the threads -- instantiation,
termination, wait(), notify(), etc. Although you may pass a thread-object reference
(java.lang.Thread.currentThread() ) to a private product, there is a potential for
conflict if that product uses wait(), notify() or other methods from java.lang.Object or
Thread.
- Tymeac may believe a stall condition is present in the Processing Application Class when
that application waits for an excessive amount of time.
- When using the Queue Thread alteration GUI or the New Copy GUI, one may purge threads
that have a reference stored in a private Vector. Although Tymeac believes the thread
is gone, the thread may resume execution and results are unpredictable.
- Since only Tymeac controls the threads, private techniques for flushing, resetting and
restarting threads in private resources are not available.
RunTime Information
Tymeac maintains information about the currently executing Tymeac Server. This
information is available to any Processing Application Class or User Exit.
The Singleton
Tymeac maintains a user singleton class into which you may put any objects for use by your
runtime classes for sharing between threads.
ShutDown
There are two implementation methods for shut down:
public String shutRequest(); -- This is the old version
and is the same as the second with a boolean false.
public String shutRequest(boolean kill); -- This
version supports forcing termination in the case when there are unresponsive Queue
Threads. For all normal shut down requests, you should set the boolean to false or simply
use version 1. If normal shutdown cannot progress and you need the Server down quickly,
then set the boolean to true.
Queues
A Queue constructs with the Queue Maintenance Class, TyQueMaint.
All three parts of a Queue work together; Threads, Wait Lists, and your Processing
Application Class.
After you write the Processing Application Class, above, you define the
environment in which it is to execute, the Queue.
The client request goes into a Queue's Wait List. A Queue Thread
picks up the request, invokes your Processing Application Class, saves the return
Object from your Class and repeats that cycle until there are no more requests.
For a Synchronous Request, the array of return Objects is passed back to the client.
For an Asynchronous Request, the array of return Objects may go into an Output Agent
Queue's Wait List. An Agent Queue Thread picks up the request, invokes
your Processing Application Class and repeats that cycle until there are no more
requests.
How many threads in the Queue and the number of Wait Lists are determined by processing
requirements. The Queue Maintenance Class, TyQueMaint, discusses these.
Functions
A Function constructs with the Function Maintenance Class, TyFuncMaint.
After you define the Queue, above, the component part of a request, you set up
the way by which Queues tie together, the Function.
The client requests a Function. The Function contains Queues. Each Queue
contains your Processing Application Class.
Each Function has one or more Queues associated with it. For example, refer to the
Tymeac Demonstration System:
Class, Demo1, is a Processing Application Class.
Queue, AAAA, is a Queue that uses Demo1.
Function, Function_2, is a Function that uses Queue AAAA.
Class, Demo2, is a Processing Application Class.
Queue, BBBB, is a Queue that uses Demo2.
Function, Function_3, is a Function that uses Queues AAAA and BBBB.
Tymeac supports two types of requests: Synchronous and Asynchronous.
A Synchronous Request schedules the Queues in the Function, waits
until all Queue's finish processing and returns the "return Objects" of all the
Processing Application Classes to the client in an array.
An Asynchronous Request schedules the Queues in the Function and
returns control to the client.
As part of an Asynchronous Request, it is often useful to do something with the
"return Objects" of all the Processing Application Classes. This is the purpose
of the Output Agent Queue.
As part of the definition of a Function is the option of an Output Agent
Queue. When the last Queue Thread finishes processing the request (the order of which
is irrelevant):
- it builds an array of all the of the "return Objects" of all the Queues in the
Function that is latter passed to the Processing Application Class as the first Object
(arg[0])
- it schedules the Output Agent Queue.
For an overview of Tymeac processing, with drawings, see the Tymeac Overview.
Tymeac Client
The client access to the Tymeac Server is with the parameter the client passes to the
Tymeac Server and the communication code.
The parameter is Class TymeacParm. The
input Object (passed to all Processing Application Classes), is optional.
The communication code is the variable. We supply a framework Class,
TySvrComm. However, you may develop any Class you wish. Processing before and after
this class is purely application oriented.
We supply several demonstration classes that are Tymeac Clients: [prefix
com.tymeac.demo..]
- DemoClientBase -- base from which other classes inherit.
- DemoClient_1 - _8
- TyDemoT1, TyDemoT3
- DemoRecur -- This is the recursion example. It is a Processing Application Class
that also becomes a client.
Identification
There may be times when your Processing Application Class, executing in the Tymeac
Server, needs to know the identification of the Tymeac Client requesting the service Outside
of CallBack.
Although there is an rmi Server method, getClientHost(), this method generally is
unacceptable and Tymeac Server does not use this method.
- The method only returns the TCP EndPoint address of the host on which the client
resides, not the actual client identification and this method is only available to pure
Java (not RMI-IIOP or other plug-in) implementations.
- Using a physical address to identify a client is usually not a good idea. The
network may change, machines come and go. This is "hard wiring". When the
location changes, then an administrator must alter all tables. Using a "soft
wiring" method means the client can take its identification with it when it moves.
Secondly, the RMI Runtime keeps track of the identification of Clients that have
unmarshalled this Server's RemoteObject. (This has to do with the Distributed Garbage
Collector.) However, API access to this data is not available.
Therefore, it is the responsibility of the Client to include a unique identifier for
use by the Processing Application Class within the input Object it passes to the
Tymeac Server. This coding is totally dependent on each application.
Idle Period
There may be times when you would like to know when no Tymeac Clients exist. (See
the SDK documentation /guide/rmi/spec/rmi/ (Garbage Collection of Remote
Objects.) This involves implementing the Unreferenced Interface (one method,
Unreferenced()) in the Tymeac Server.
- The unreferenced() method is only called when ALL clients no longer
hold a reference to the remote object or when the lease time expires
(java.rmi.dgc.leaseValue.)
- The Registries (RMI/JNDI) are clients. When Tymeac Server registers with one of
these, then the unreferenced() method may never be called.
- Since this is the purview of the Distributed Garbage Collector, each operating system
may implement this differently.
We do not implement the Unreferenced Interface.
For the activatable Tymeac Server, we keep track of the idle period, that is - the time
when no Client has called the Server. (see Configuration File Maintenance and User
Variables Class) When this idle period reaches a threshold, the application may take some
action (such as deactivating, etc.) In this way, we are not dependent on any
implementations of DGC and we have much more flexibility.
System Variables
Tymeac reads system variables at start up from the TymeacUserVariables class for stand
alone mode or the Tymeac Configuration File for DBMS start up. This is where you put the
monitor interval, etc.
Testing
Becoming familiar with how Tymeac works is preliminary in any testing
environment. We provide a page on how to alter the Demonstration System Classes and a
page on abnormal conditions that may arise.
The easiest way to test a Class is without the Tymeac threading environment. We supply
a source Class, DemoTesting.java. This Class:
- loads the required Class, Class.forName("name of the Class to load"),
- finds the method signature, "main(Object[])", and
- invokes the found "main" method.
This is similar to the way Tymeac invokes your Processing Application
Class. Therefore, if it runs here, it should run there.
Two directories are necessary to use this Class:
- <home>\com\tymeac\serveruser -- for the Processing Application Class
- <home>\com\tymeac\demo -- for the DemoTesting Class.

Having tested the Class in a stand-alone environment, it is time to test the Class in
the Tymeac threading environment.
Testing a Class usually requires setting up a Queue and a Function just
for testing.
It is easier to test a single Class when there is only one Queue in the Function. It
is easier to isolate threads when there is only one thread in the Queue. Therefore,
define a Queue, TyQueMaint, with one (1) thread and the name of your Processing
Application Class. Define a Function, TyFuncMaint, with the name of this
single Queue.
Write a Tymeac Client Class that passes the input Object to the Tymeac Server as a
Synchronous Request, TymeacParm, with a time out value high
enough to allow stepping through the application.
- Start the RMI Registry.
- Start TymeacServer.
- Set a trap for your application.
- Run the application.
See also the section on naming threads found in the Maintenance Class for Queues and in
the section on Thread Names.
This same process works for the Output Agent Processing Application Class.
Just set up a normal Queue and pass simulated data to this application, with a
Synchronous Request, as it would be if from other applications. When the application
works properly, then set up an Output Agent Queue as part of a Function.
When there is more than one thread in the Queue, knowing which thread is going
to process a request is sometimes possible.
Thread numbering starts at zero (0). Tymeac thread selection always starts at
zero(0). Therefore, if three threads are "waiting for work", TyQueThd, Tymeac selects thread number zero (0), first. If all
threads are "inactive" or "never used", Tymeac activates thread number
zero (0), first.
As mentioned, above, the New Copy Class is available so that you do not have to shut
down and start up Tymeac Server every time you recompile your Class.

Now that all is working well, what happens when this newly developed system is under a
load? That is, many clients requesting service at the same time. Are there any
"sharing" conflicts, resource limitations, etc? We supply an "under
load" system, the T3 series. [You may wish to clone this series, renaming the
classes to your own standards.]
TyDemoT3 is made up of five classes. The only one you must change is
TyDemoT3Thread. The other classes may remain without change. Alter
TyDemoT3Thread Constructor to use your TymeacParm
information. Alter TyDemoT3Thread.run() to perform the sequence of events necessary for
your testing.
Now you may put as heavy a load on your code as necessary.
User Exits
As with other general purpose tools, Tymeac cannot supply all the functionality one may
wish to have. Therefore, Tymeac provides exits or hooks into which you may add your
own functionality. See the section on user exits.
See also the section on start up functions.
These exits are established either in the Tymeac Configuration File or in the
TymeacUserVariables Class.
Overall Structure
- We provide guidance in the form of patterns that appear frequently within Tymeac.
- We provide an exposition on RMI communications for use with Tymeac.
- The computer memory requirements are difficult for any system. We provide a discussion
on how Tymeac uses storage.
- We have a discussion on network load balancing.
|