Note: Only the Client/Server version of JBuilder ships with distributed applications features.
This tutorial helps you become acquainted with some of the JBuilder and VisiBroker for Java development tools, and describes how to develop a distributed, object-based application using JBuilder and VisiBroker for Java. A sample application is used to illustrate each step of the process. The Bank application explains how to build a sample client application that can query on the balance in a bank account. Extending the banking application to be an applet explains how to design a graphical user interface (GUI) for the applet, and how to write the necessary code to handle the GUI events.
For more information about Common Object Request Broker Architecture (CORBA), link to
In this tutorial, you will build a sample client application that can query on the balance in a bank account. To build this distributed application in JBuilder, you will need to
The code for this example is provided in the jbuilder\samples\visibroker\samples\bank directory where JBuilder was installed. The following files are provided:
When you develop distributed applications, you must first identify the objects required by the application.
The following figure illustrates the steps needed to develop the sample application.
Developing the sample Bank application.
The Bank.idl file defines the Bank module that contains two interfaces. The Account interface provides a method for obtaining the current balance. The AccountManager interface provides a method that opens an account with a specified name and returns an Account object reference. The Account object reference can then be used to obtain the balance in the account.
To create and enter the code for the IDL file,
module Bank { interface Account { float balance(); }; interface AccountManager { Account open(in string name); }; };
The VisiBroker IDL compiler, named idl2java, generates Java code from a file containing IDL specifications. Since the Bank.idl file requires no special handling, you can compile it by
Since Java allows only one public interface or class per file, compiling the Bank.idl file will generate several Java files. These files are stored in a sub-directory named Bank, which is the module name specified in the IDL file. IDL modules are mapped to Java packages, so all of the files listed below will be part of the Bank package.
For more information about the Helper, Holder, and Operations classes, see the "Generated Classes" chapter in the VisiBroker for Java Reference Manual, at http://www.visigenic.com/techpubs/htmlhelp/vbj30/ref/frames/vbj_4.htm.
To implement the CORBA interface,
AccountImpl.java contains the implementation of the Account object.
package visibroker.samples.bank; public class AccountImpl extends Bank_AccountImplBase { public AccountImpl(float balance) { _balance = balance; } public float balance() { return _balance; } private float _balance; }
AccountManagerImpl.java contains the implementation of the Account Manager object.
package visibroker.samples.bank; import java.util.*; public class AccountManagerImpl extends Bank._AccountManagerImplBase { public AccountManagerImpl(String name) { super(name); } public synchronized Bank.Account open(String name) { // Lookup the account in the account dictionary. Bank.Account account = (Bank.Account) _accounts.get(name); // If there was no account in the dictionary, create one. if(account == null) { // Make up the account's balance, between 0 and 1000 dollars. float balance = Math.abs(_random.nextInt()) % 100000 / 100f; // Create the account implementation, given the balance. account = new AccountImpl(balance); // Make the object available to the ORB. _boa().obj_is_ready(account); // Print out the new account. System.out.println("Created " + name + "'s account: " + account); // Save the account in the account dictionary. _accounts.put(name, account); } // Return the account. return account; } private Dictionary _accounts = new Hashtable(); private Random _random = new Random(); }
Many of the files used in implementing the bank client are contained in the Bank package generated when the IDL file is compiled. However, you need to create the Client.java file.
The client class implements the client application that obtains the current balance of a bank account.
Client.java provides the client side program, written in Java.
// Client.java public class Client { public static void main(String[] args) { // Initialize the ORB. org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null); // Locate an account manager. Bank.AccountManager manager = Bank.AccountManagerHelper.bind(orb,"BankManager"); // use args[0] as the account name, or a default. String name = args.length > 0 ? args[0] : "Jack B. Quick"; // Request the account manager to open a named account. Bank.Account account = manager.open(name); // Get the balance of the account. float balance = account.balance(); // Print out the balance. System.out.println ("The balance in " + name + "'s account is $" + balance); } }
The program performs the following steps:
This file is located in the Bank package. It contains an AccountManagerHelper object and defines several methods for binding to the server that implements this object. The bind method transparently contacts a Smart Agent, described in The Smart Agent (see http://www.visigenic.com/techpubs/htmlhelp/vbj30/pg/frames/vbj_10.htm), to locate the object. Our example application uses the version of the bind method that accepts an object name, but the client may optionally specify a particular host and special bind options.
For information on these additional methods, see the "Specifying Bind Options", at http://www.visigenic.com/techpubs/htmlhelp/vbj30/pg/frames/vbj_4_8.htm. For more information about Helper classes, see the "Generated Classes" chapter in the VisiBroker for Java Reference Manual at http://www.visigenic.com/techpubs/htmlhelp/vbj30/ref/frames/vbj_4.htm.
When your application invokes the bind method, the ORB locates and establishes a connection with an appropriate server and returns a handle to the AccountManager object. If the ORB cannot locate or connect to the Bank.AccountManager server object, the bind method will raise a CORBA system exception.
Several other methods are provided that allow your client application to manipulate an AccountManager object reference. Most of these methods are not used in the example client application, but they are described in detail in the VisiBroker for Java Reference Manual at http://www.visigenic.com/techpubs/htmlhelp/vbj30/ref/startme.htm.
This file is located in the Bank package. It contains the stub code for the AccountManager object on the client side. In the example, the client uses the AccountManager object open method to open an account.
The open method generated when the IDL file was compiled is really a stub method. When your client application calls the open method, a request is sent to the ORB with all the necessary parameters. The ORB ensures that the request is sent to the server that implements the AccountManager object. Once the method is executed on the server, the ORB returns the results to your client application.
Caution: Do not modify this generated file.
This file is located in the Bank package. It contains the stub code for the Account object on the client side. In the example, the client uses the Account object balance method to obtain an account balance.
The balance method generated when the IDL file was compiled is also a stub method. When your client application calls the balance method, a request is sent to the ORB with all the necessary parameters. The ORB ensures that the request is sent to the server that implements the Account object. Once the method is executed on the server, the ORB returns the results to your client application.
Caution: Do not modify this generated file.
Just as with the client, many of the files used in implementing the bank server are contained in the Bank package generated when the IDL file was compiled. The Server.java file is a server implementation that you create. A simple server can be created with the Generate CORBA Server Wizard, accessed by selecting CORBA Server from the Visibroker tab of the File|New menu.
This file implements the Server class for the server-side of our banking example.
To create Server.java,
A portion of the Server.java file, showing the server implementation.
// Server.java public class Server { public static void main(String[] args) { // Initialize the ORB. org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null); // Initialize the BOA. org.omg.CORBA.BOA boa = orb.BOA_init(); // Create the account manager object. Bank.AccountManager manager = new AccountManagerImpl("BankManager"); // Export the newly created object. boa.obj_is_ready(manager); System.out.println(manager + " is ready."); // Wait for incoming requests boa.impl_is_ready(); } }
The Server class does the following:
The AccountManagerImpl class in this file extends the Bank._AccountManagerImplBase class generated in the Bank package. This class provides the actual implementation of the open method used to obtain or create an Account. The manager uses a Dictionary to contain all the accounts. When a request to open an account is received, the open method does the following:
// AccountManagerImpl.java import java.util.*; public class AccountManagerImpl extends Bank.AccountManagerImplBase { public AccountManagerImpl(String name) { super(name); } public synchronized Bank.Account open(String name) { // Lookup the account in the account dictionary. Bank.Account account = (Bank.Account) _accounts.get(name); // If the account is not in the dictionary, create an account. if(account == null) { // Create a new account with between 0 and 1000 dollars. float balance = Math.abs(_random.nextInt()) % 100000 / 100f; account = new AccountImpl(balance); // Make the object available to the ORB. _boa().obj_is_ready(account); System.out.println("Created " + name + "'s account: " + account); // Save the account in the account dictionary. _accounts.put(name, account); } // Return the account. return account; } private Dictionary _accounts = new Hashtable(); private Random _random = new Random(); }
The AccountManagerImpl server class that you implement extends the Bank package's _AccountManagerImplBase class that was generated by the CORBA Settings Wizard. The skeleton class, _AccountManagerImpl, implements the AccountManager interface.
To build the example program, select Build|Make Project Bank.jpr.
If you encounter errors during the build process, see the FAQ at ORB Central on the Visigenic Web site at http://www.visigenic.com.
The Smart Agent, or OsAgent, provides a fault-tolerant object location service. Ordinarily, you will want the OsAgent to be running on at least one machine in the LAN environment for you to run your applications. The Smart Agent is described in detail in The Smart Agent, at http://www.visigenic.com/techpubs/htmlhelp/vbj30/pg/frames/vbj_10.htm
Start Smart Agent by selecting Tools|VisiBroker Smart Agent from the JBuilder menu. This option is toggled on when there is a check mark to the left, and is toggled off when there is not a check mark to the left.
Now, you can start the server by running Server.java. Running Server.java invokes the virtual machine and offers other special features. For command-line options and more information, see "Commands" in the VisiBroker for Java Reference Manual, at http://www.visigenic.com/techpubs/htmlhelp/vbj30/ref/frames/vbj_p.htm.
To run Server.java, select the file in the Navigation pane, then select Run|Run from the JBuilder menu.After starting the Smart Agent and the server, a client can be started in a different window, using either command-line options or by selecting Client.java in the Navigation pane and selecting Run|Run from the menu. If a command-line argument is provided to the client, that argument will be used as the name of the bank account to be opened:
Running the bank client application.prompt> vbj Client The balance in Jack B. Quick's account is $71.62 prompt> vbj Client "Jack Sprat" The balance in Jack Sprat's account is $322.38
Since the account balance is computed randomly, the actual output you see will differ from that shown above. If you encounter problems running the client application, refer to The VisiBroker for Java GateKeeper Guide at http://www.visigenic.com/techpubs/#VBJLink.
Since the Server prints out a message every time it creates a new Account, you will see the following output on the server side:
Output from the bank server.prompt> vbj Server AccountManager[Server,oid=...] is ready. Created Jack B. Quick's account: Account[Server,oid=...] Created Jack Sprat's account: Account[Server,oid=...]
VisiBroker is also used in the deployment phase. This phase occurs when a developer has created client programs or server applications that have been tested and are ready for production. At this point a system administrator is ready to deploy the client programs on end-users' desktops or server applications on server-class machines.
For deployment, the VisiBroker ORB supports client programs on the front end. You must install the ORB on each machine that runs the client program. Clients (that make use of the ORB) on the same host share the ORB. The VisiBroker ORB also supports server applications on the middle tier. You must install the full ORB on each machine that runs the server application. Server applications or objects (that make use of the ORB) on the same server machine share the ORB.
JBuilder includes a single DEVELOPMENT LICENSE of VisiBroker for Java 3.0 "Developer Version". This license must be used in conjunction with JBuilder. Additional licenses for multiple server machines on NT, UNIX, and MVS may be required during development.
In this topic, you will extend the banking client application to be an applet that can be run from any Java-enabled browser using these steps:
The GUI for this example will consist of four components that form a two-by-two grid:
To cause the Account Balance text field to be updated, the user will fill in the Account Name text field and then press the Check Balance button. If you are familiar with the JBuilder development environment, you can follow these steps to create the applet and accompanying HTML file. If not, create a new file called Applet1.java (be sure to add it to the project), and enter the following code:
public boolean actionPerformed(Event ev, Object arg) { if(ev.target == _checkBalance) { // Request the account manager to open a named account. // Get the account name from the name text widget. Bank.Account account = _manager.open(_nameField.getText()); // Set the balance text widget to the account's balance. _balanceField.setText(Float.toString(account.balance())); return true; } return false; }
Click Finish.
You need to provide the code to an actual call to the bank manager and bank account. The code will get the account name from the first TextField, use it to open an account, and then fill in the second TextField with the account balance.
Bank.Account account = _manager.open(_nameField.getText()); _balanceField.setText(Float.toString(account.balance()));
The final step is to incorporate this new code into your existing client program. You will also need to write the exception handling code and the ORB initialization code again.
Note: The ORB is initialized by passing the Applet as an argument to the ORB_init(Applet) method.
The complete client program is shown below. For information about all of the available methods, see the VisiBroker for Java Reference Manual at http://www.visigenic.com/techpubs/.
The complete client applet.// Applet.java import java.awt.*; public class Applet extends java.applet.Applet { private TextField _nameField, _balanceField; private Button _checkBalance; private Bank.AccountManager _manager; public void init() { // This GUI uses a 2 by 2 grid of widgets. setLayout(new GridLayout(2, 2, 5, 5)); // Add the four widgets. add(new Label("Account Name")); add(_nameField = new TextField()); add(_checkBalance = new Button("Check Balance")); add(_balanceField = new TextField()); // make the balance text field non-editable. _balanceField.setEditable(false); // Initialize the ORB (using the Applet). org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(this); // Locate an account manager. _manager = Bank.AccountManagerHelper.bind(orb, "BankManager"); } public boolean action(Event ev, Object arg) { if(ev.target == _checkBalance) { // Request the account manager to open a named account. // Get the account name from the name text widget. Bank.Account account = _manager.open(_nameField.getText()); // Set the balance text widget to the account's balance. _balanceField.setText(Float.toString(account.balance())); return true; } return false; } }
The following HTML is used to embed the Applet in a simple page. Click Applet1.html in the Navigation pane and click the Source tab to make any modifications to this file.
HTML used to embed Applet.<h1>VisiBroker Client Applet</h1> <hr> <center> <applet code=Applet.class width=200 height=80> <h2>You are probably not running a Java-enabled browser, Please use a Java-enabled browser (or enable your browser for Java)...</h2> </applet> </center> <hr>
This HTML does the following:
The GateKeeper enables VisiBroker applets to communicate with object servers across large networks while still conforming to the security restrictions imposed by Web browsers. The GateKeeper may also be used as a Web server. For more information about the GateKeeper, refer to The VisiBroker for Java GateKeeper Guide, at http://www.visigenic.com/techpubs.
Now you are ready to run the applet. It is usually best to run the example from the appletviewer before running it from your browser. The appletviewer can be started using the following command:
If you have trouble running the client applet, you can refer to The VisiBroker for Java GateKeeper Guide, at http://www.visigenic.com/techpubs, or to the Building Applications with JBuilder topic Running applets.
After testing your applet with the appletviewer, you are now ready to run the applet from a Java-enabled browser. Be sure you are using a Web browser that supports Java 1.0 release or later. The URL for the applet has the following format:
http://<machine-name>[:<port-number>]/<file-name>
The URL is composed of the following components:
Component | Description |
---|---|
<machine-name> | The name of the host that is running the HTTP server. |
<port-number> | This should be 15000 if you are using the GateKeeper as the HTTP server. Otherwise, it should be set to the port number of your HTTP server. If the port number is not specified in the URL, a default port number of 80 is used. |
<file-name> | This should be Applet.html. |
For example, if Applet.html resides in the directory pub/applets on machine foo.bar.com and the GateKeeper was started from that directory, the URL would be
http://foo.bar.com/pub/applets/Applet.html
If you were using the GateKeeper as your development Web server on the machine "foo.bar.com", the URL would be
http://foo.bar.com:15000/Applet.html
If the Gatekeeper was started in a directory different than the directory where the server is running, the entire path must be specified and double slashes must be used.
http://foo.bar.com:15000//vbroker/java_examples/bank/Applet.html
Every time the browser requests a Java class, the IIOP GateKeeper will print a status message to stdout. If the Web server encounters errors in loading the file, it will also print error messages to stderr.
Other examples using VisiBroker and JBuilder are located in the jbuilder\samples\visibroker\samples\ directory.
This subdirectory contains the "Bank" example application developed in several chapters of the VisiBroker for Java Programmer's Guide. This example has two simple interfaces supporting two operations - open, to open a bank account and balance, to query the balance in the user's account. The other examples based on the Bank example are bank_using_tie,dynamic_bank, event_bank, and URLNaming_bank.
This subdirectory contains the bank example and illustrates the implementation of the Bank Server using the TIE mechanism.
This subdirectory contains the bank example, where the client is implemented using DII (Dynamic Invocation Interface) and the Server is implemented using DSI (Dynamic Skeleton Interface).
This subdirectory contains the bank example showing how to use the Event Handler API provided by VisiBroker for Java and create communication event handlers for client applications and object implementations.
This subdirectory has two examples: sampleInterceptor and timerInterceptor. The interceptor examples are based on the Bank Example described above. They illustrate how to create an interceptor and associate it with the ORB. They also show how to add simple tracing or timing information to an existing client or server without modifying source code.
This subdirectory contains two examples, one of which looks up the interface associated with a given IDL name in the Interface Repository. The second one traverses the IR as a container and prints all the contents in an IDL-like fashion. These examples show how to bind to, query, and traverse the IR.
This subdirectory contains examples using the Location Service provided by VisiBroker for Java. The example demonstrates how to bind to and query the OsAgent to obtain information about all accessible globally scoped objects. It also shows how to implement triggers, which will be notified as globally scoped instances become available.
This subdirectory contains an example that uses a factory to create an arbitrary number of objects provided through a Service Activator. The objects may be activated and deactivated dynamically, simulating what is required when integrating VisiBroker servers with an Object Database.
The pass_by_value subdirectory contains two examples, the Dictionary and the List. These examples illustrate the use of the Caffeine compiler (java2iiop, selecting a Java file in the CORBA Settings Wizard) to generate client stubs and server skeletons from interface definitions written in Java instead of IDL. They also illustrate how to work with complex data types - in particular, passing by value using extensible structs.
The smart_stub subdirectory contains an example that shows how to cache information from server objects and reduce the number of actual server requests a client has to make.
The URL Naming example illustrates how a client can obtain a reference to an object by specifying the URL associated with an object's IOR instead of using the object name.