In this section we build a very simple application that uses the coordination contracts API to dynamically reconfigure the interactions between customers and accounts.
The API of a contract consists in a set of methods to create and remove
contract instances, set and get the attributes' values, and to get the participant
objects. Each contract is compiled into a class with the same name in a package cde.contracts.
We now list the available methods, showing the concrete API for the Credit
contract.
The constructor takes as arguments the actual contract participants. The parameters have the same names and are in the same order as the participants that appear in the contract definition.
Credit (Customer customer, Account account)
At the end of the constructor, a parameterless method initialize
is called. By default, CDE generates an empty method that does nothing,
unless you provide your own method in the operations section of
the contract. This method is useful to initialize any contract
attributes.
void initialize ()
The "destructor" removes the contract between the participants,
but, as in all Java programs, it does not actually remove the contract object;
the contract just becomes inactive. This method is always called Delete
and takes no arguments. After this method executes, the contract is
no longer active. No other methods should be called on the contract object
after this one.
void Delete ()
The method getName, without arguments, returns the name of the
contract, i.e., "Credit" for our example.
String getName ()
For each participant there is a getparticipant
method, without arguments, that returns the participant that in the contract
definition has name participant. The return type of this method
is the participant class declared in the contract definition.
Customer getcustomer ()
Account getaccount ()
For each attribute, there is a getattribute method,
without arguments, that returns the attribute with the given name.
The return type of this method is the one declared in the contract definition.
int getlimit ()
For each attribute, there is a setattribute method,
with a single parameter, that sets the attribute with the given name to the
value given as argument.
The type of the parameter is the same as the type of the attribute.
void setlimit (int limit)
The method toString() is overridden to return a string of the
form "ContractName (participant1,
participant2, ...)",
where the contract's name is obtained by calling getName, and participanti
is obtained by calling toString on the respective participant
object.
String toString ()
Notice that the names of attributes and participants are exactly as written in
the contract definition. No changes in capitalization are made by the CDE. This
means, in our example, that the method to get the credit limit is not called
getLimit.
The CDE editor allows you to browse through the generated files. To see the Traditional API, just double-click on the File:Traditional.java node in the project tree (under the Generated Files of the Traditional contract).
The toy application built to illustrate the Credit and Traditional APIs is a single class (to keep things simple) that manages the customers and accounts belonging to a bank agency. The complete application would allow the creation and deletion of customers and accounts, and changes of ownership, but as we are interested only in the operations on contracts, the interaction with the user is limited to setting the credit limit between a given customer and a given account, and to withdrawing and depositing money.
The application is in file Agency.java in the source directory. It is written in a very straightforward, unsophisticated way, to keep it very simple and focus only on the important issues. The noteworthy methods of the class are the following:
Credit getCredit(Customer c, Account a) searches the agency
database (represented as a vector for each type of component or contract)
for a Credit contract with the given participants. It returns the first such
contract it finds, or null if there isn't any. Method getTraditional
is similar for Traditional contracts. These methods illustrate the
participant getter methods of the contract classes, i.e., getcustomer
and getaccount.
void setLimit(Customer c, Account a, double limit) sets the
new credit limit for the given participants. The method raises an exception
if the customer doesn't own the account. Otherwise, it checks which contract
is currently in effect between the participants and what is the new limit.
If the contract is Traditional but the limit is positive, it is replaced by
a Credit contract. If the contract is of Credit type, two cases are
possible: if the new limit is zero, the contract is replaced by a
Traditional one; otherwise only the limit is changed. This method
illustrates how contracts are created and deleted, and how their attributes
are changed.
void listDB() lists the contents of the vectors, showing the full
information for each component and contract. For example, the method lists
the participants and the limit of Credit contracts. This method illustrates
the "getter" and the toString() methods.
To compile and run the application, do as follows:
Open file Agency.java in the src/Bank directory by pressing Ctrl-O or selecting File->Open File... .
Select Project->Compile->Java Compiler.
In Windows, open a Command prompt, go to the application directory (i.e., demos/tour) and execute the command
java -cp "classes;CDE" Bank.Agency
where CDE is the CDE runtime library that you have indicated in
the project options.
The application comes with two pre-defined customers, named Mary and John,
and accounts, numbered 1 and 2. Mary owns both accounts, John only owns account
2. All contracts are of Traditional type, and the accounts have zero balance.
After this initialization, main enters a loop asking the user to
withdraw or deposit money, or to change the credit limit of one customer/account
relation. In both cases, the user has to enter the customer and the account
numbers.
You can now play around with the application, seeing how it keeps the following invariants:
There is at most one contract between each customer/account pair.
The limit of Credit contracts is always positive.
Here is a sample scenario for you to try out. List the database after each operation to see how it changes.
Set the limit of the contract between Mary and account 1 to 200 Euro.
Let John withdraw 100 Euro from account 1.
Let Mary withdraw 100 Euro from account 1.
Let Mary withdraw 100 Euro from account 2.
Let John withdraw 100 Euro from account 2.
Repeat step 3 two more times.
Let John deposit -100 Euro in account 1.
Set the credit between John and account 1 to -50 Euro.
Congratulations! You have completed the Guided Tour, and we hope you feel confident in using contracts and the CDE for your own applications.
Here are some exercises for you to further use the tool and to deepen your understanding of coordination contracts.
Add methods to delete customers and accounts to the application. Deleting a customer or account automatically deletes the contract between them.
Create a LimitedCredit contract and add it, together with the LimitedTraditional contract, to the application. Add another option to allow the user to choose whether withdrawals can be limited or not.