Getting Started Using Java IDL in 3-Tier JDBC

This page provides detail information to create a 3-tier JDBC example using CORBA. Basically, this example can divided into two parts. The first part contains the client communicate with server through IIOP via CORBA ORBs. The other is to build a connection between the server and the database servers using JDBC. In this page, we would like to go through a simple example instead of mentioning the detail concept of Java IDL and JDBC.

This page is designed under the assumption that users are familiar with Java and JDBC.
More documents can be found at Java IDL.

0. Setup Java IDL compiling/running environment

Please setup Three parameters (JAVA_HOME and JAVAIDL_HOME) to the right paths to these two home directories in you environment. For instance, in csh, you can enter the following settings at command line.
setenv JAVA_HOME /usr/npac/jdk1.1.4

setenv JAVAIDL_HOME /servers/cgi-http-class/htdoc/reference-docs/cwou/CORBA-JDBC/JavaIDL

setenv CLASSPATH .:${JAVA_HOME}/lib/classes.zip:/usr/npac/weblogic/classes:${JAVAIDL_HOME/lib/class.zip

---------------

1. Create a CORBA-complaint code using Java IDL

The interface between the client and server can be defined using CORBA IDL in the file "ClientApp.idl" as follow.
module ClientApp
{
    interface ClientQuery
    {
        void search(in  string a);
	string getName();
        string getAge();
        string getOcc();
        void open();
        void close();
    };

    interface Result
    {
        attribute string name;
        attribute string age;
        attribute string occ;
    };
};
To see the mapping from IDL to Java, please check Java IDL.

module definds remote object name ClientApp. In this module, 2 sets of interfaces have been defined as ClientQuery and Result.

ClientQuery defines interface to remote JDBC routines. Clients can access the remote database by search, getName, getAge, getOcc, open, and close.
search defines to search the database based on query string a.
getName,getAge, and getOcc define to get name, age, and occupation of the searched result, respectively.
open and close define to open and close the connection to the database server, respectively.

Result define the result interface of remote object. This is an example to show the client can access the parameters in the remote object.

2. Compile the IDL file using idltojava

After you IDL file is created, you can enter the following command to compilt the IDL file using idltojava. This will translate you IDL file to several Java interface and abstract classes for you to implement and to extend.

idltojava -fclient -fserver ClientApp.idl
After this is done, you will have a directory named ClientApp created by idltojava. This directory contains all necessary classes for you to implement CORBA-ORB connection via IIOP.

3. Check all java codes generated by idltojava in ClientApp

Ther will be 10 java files generated (5 java files for each interface) and listed below.
ClientQuery.java
ClientQueryHelper.java
ClientQueryHolder.java
_ClientQueryImplBase.java
_ClientQueryStub.java
Result.java
ResultHelper.java
ResultHolder.java
_ResultImplBase.java
_ResultStub.java
Two java codes, _ClientQueryImplBase and _ResultImplBase, are important for implementing server site object. We only use these two java codes to complete this tutorial. Detailed descriptions of the rest of files can be found at JavaIDL.

4. Develop the server based on _xxxxImplBase classes

Now, we need to implement the remote object. There are two server-side classes need to be extended, _ClientQueryImplBase and _ResultImplBase. We first implement all methods in interface ClientQuery
  1. implement a servant, ClientQueryServantImpl, to extend _ClientQueryImplBase class.
  2. create the servant object by creating and instantiating a database object (JDBC).
  3. write all methods (e.g., search, getName, etc.) in java.
  4. apply the above 3 techniques to implement the other servant (ResultServantImpl).
  5. the only thing that we have not done yet is to create the connection to response to the client. So we can start writing the server, DBServer, in this example.
We need to instantiate an ORB object on the server side. Java IDL provides two packages to accomplish this (org.omg.CORBA and org.omg.CosNaming). The server named DBServer.
create and initialize ORB
create servant and register it with ORB
get the root naming context
bind the Object Reference in Naming
wait for invocations from clients
This servant can be implemented as a multi-threaded or distributed servant objects to serve many clients. It is not included in this tutorial. This is left to readers to do the advanced homework.
import java.io.*;
import java.net.*;
import java.awt.*;

import org.omg.CORBA.*;
import com.sun.CORBA.iiop.*;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;

import ClientApp.*;

class ClientQueryServantImpl extends ClientApp._ClientQueryImplBase {

    private myDatabase database;

    public ResultServantImpl result = new ResultServantImpl("", "", "");

    public ClientQueryServantImpl() {
        database = new myDatabase();
    }

    public void search(String a) {

        StringBuffer asb = new StringBuffer();
        StringBuffer bsb = new StringBuffer();
        StringBuffer csb = new StringBuffer();

        database.find(a, asb, bsb, csb);
        this.result.name(asb.toString());
        this.result.age(bsb.toString());
        this.result.occ(csb.toString());
    }

    public String getName() {
        return this.result.name();
    }

    public String getAge() {
        return this.result.age();
    }

    public String getOcc() {
       return this.result.occ();
    }

    public void open() {
        database.open();
    }

    public void close() {
        database.close();
    }
}

class ResultServantImpl extends ClientApp._ResultImplBase {

    public String name_;
    public String age_;
    public String occ_;

    public
    ResultServantImpl(String name,
                      String age,
                      String occ) {
        name_ = name;
        age_ = age;
        occ_ = occ;
    }

    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append("Name: " + this.name_ + "\nAge: " + this.age_ +
                  "\nOccupation: " + this.occ_);
        return sb.toString();
    }

    public String name() {
        return this.name_;
    }

    public void name(String arg) {
        name_ = arg;
    }

    public String age() {
        return this.age_;
    }
   
    public void age(String arg) {
        age_ = arg;
    }

    public String occ() {
        return this.occ_;
    }

    public void occ(String arg) {
        occ_ = arg;
    }

}

public class DBServer {

    public static org.omg.CORBA.ORB theOrb_;

    public ResultServantImpl servant1;

    public static void main(String[] args) {
        try {
            // create and initialize ORB
            theOrb_ =  org.omg.CORBA.ORB.init(args, null);

            // create Servant and register it with ORB
            ClientQueryServantImpl servant = new ClientQueryServantImpl();
            theOrb_.connect(servant);

            // get the root naming context
            org.omg.CORBA.Object objRef = theOrb_.resolve_initial_references("NameService");
            NamingContext ncRef = NamingContextHelper.narrow(objRef);

            // bind the Object Reference in Naming
            NameComponent nc = new NameComponent("ClientApp", "");
            NameComponent path1[] = {nc};
            ncRef.rebind(path1, servant);

            // wait for invocations from clients
            java.lang.Object sync = new java.lang.Object();
            synchronized (sync) {
                sync.wait();
          }
        }
        catch (Exception ex) {
            ex.printStackTrace();
            System.err.println("DB Server: Exception-> " + ex);
        }
  }
}

5. JDBC code

This is covered in the JDBC tutorial. Therefore, only the source code is shown here.
import java.sql.*;
import java.sql.*;

import java.util.Properties;

class myDatabase {
	
	private Connection conn;
	
	public void open() {
		Properties props = new Properties();
		props.put("user",     "njm");
		props.put("password", "njm");
		props.put("server",   "");

		try {
                  java.sql.Driver d = 
        (java.sql.Driver)Class.forName("weblogic.jdbc.oci.Driver").newInstance();
			DriverManager.setLogStream(java.lang.System.out);
			conn = d.connect("jdbc:weblogic:oracle", props);
		}
		catch (Exception e) { System.err.println("Error connection: " + e);}
	}

  public void find(String word, StringBuffer s1, StringBuffer s2, StringBuffer s3) {
		
		try {
			System.out.println("name passed = " + word);
                        PreparedStatement pstmt = 
                conn.prepareStatement("select * from persontable where NAME = ?");
			pstmt.setString(1,word);
			ResultSet rs = pstmt.executeQuery();

			rs.next();
			s1.append(rs.getString("NAME"));	
			s2.append(rs.getString("AGE"));	
			s3.append(rs.getString("OCCUP"));	
			pstmt.close();
		}
		catch (Exception e) {
			System.err.println("Error in dbase");
			e.printStackTrace();
		}
	}	

	public void close() {
		try {
			conn.close();
		}
		catch (Exception e) {System.err.println("Error in closing dbase");}
	}
}

6. Create a sample applet client

The following code is a complete sample code can be browsed through Netscape's Navigator 3.0, Microsoft's Internet Explorer 4.0, and Sun's appletviewer. The GUI design is vary based on user preference. We only provide a ab-inito client code to demonstrate hoe the client can talk to the server through CORBA ORB via IIOP.

The basic steps can be taken as follow:
create and initialize the ORB
get the root naming context
resolve the Object Reference in Naming
in init() in the applet.

import java.awt.*;
import java.net.*;
import java.io.*;
import java.applet.*;

import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;
import com.sun.CORBA.iiop.*;

import ClientApp.*;

public class Client extends Applet {
	
    private DisplayPanel dp;	

    public static org.omg.CORBA.ORB theOrb_;

    public static ClientApp.ClientQuery ref_;

    private boolean isClose = true;

    public void init() {
        try {
            // create and initialize the ORB
            theOrb_ =  org.omg.CORBA.ORB.init(this, null);

            // get the root naming context
            org.omg.CORBA.Object objRef = theOrb_.resolve_initial_references("NameService");
            NamingContext ncRef = NamingContextHelper.narrow(objRef);

            // resolve the Object Reference in Naming
            NameComponent nc = new NameComponent("ClientApp", "");
            NameComponent path1[] = {nc};
            ref_ = ClientApp.ClientQueryHelper.narrow(ncRef.resolve(path1));
        }
        catch (Exception ex) {
            ex.printStackTrace();
            System.out.println("Client: Exception-> " + ex) ;
        }
    }

    public Client() {
  	setBackground(Color.pink);
	add("North",  new HeaderPanel(this));
	add("Center", dp = new DisplayPanel());
	add("South",  new ControlPanel(this));
    }

    public void showData(String name, String age, String occ) {
	PersonalData pd = new PersonalData(name, age, occ);
	dp.show(pd);
	dp.repaint();
    }

    public void getData(String a, String b, String c) {
	if (a.equals("")) {
	    dp.showerr(1);
	    dp.repaint();
	}
	else showData(a,b,c);
    }
	
    public void search(String a) {
        if (isClose) {
            dp.showerr(0);
            dp.repaint();
        }
        else {
            ref_.search(a);
	    getData(ref_.getName(), ref_.getAge(), ref_.getOcc());
        }
    }

    public void open() {
        if (isClose) {
            isClose = false;
            dp.showStatus(0);
            ref_.open();
        }
        else {
            dp.showStatus(2);
        }
        dp.repaint();
    }
 
    public void close() {
        if (isClose) {
            dp.showStatus(3);
        }
        else {
            isClose = true;
            dp.showStatus(1);
            ref_.close();
        }
        dp.repaint();
    }
}

class HeaderPanel extends Panel {

    private Label header;
    private Client par;

    public HeaderPanel(Client c) {
	par = c;
	setFont(new Font("Helvitica", Font.BOLD, 24));
	add(header = new Label("Database Connectivity Test"));
    }
}

class ControlPanel extends Panel {

    private Client parent;
    private TextField name;
    private Label lbl;

    public ControlPanel(Client clt) {
	parent = clt;
	setFont(new Font("Times-Roman", Font.BOLD, 14));
	add(lbl = new Label("Enter name to search"));
	add(name = new TextField(20));
        add(new Button("Open DB"));
        add(new Button("Close DB"));
	add(new Button("Search"));
	add(new Button("Clear"));
    }

    public boolean action(Event e, java.lang.Object what) {
        if (what.equals("Open DB")) {
            try {
                parent.open();
            }
            catch (Exception ex) {return false;}
            return true;
        }
        if (what.equals("Close DB")) {
            try {
                parent.close();
            }
            catch (Exception ex) {return false;}
            return true;
        }
        if (what.equals("Search")) {
	    try {
	        parent.search(name.getText());
	    }
	    catch (Exception ex) {return false;}
	    return true;
	}
	if (what.equals("Clear")) {
	    name.setText("");
	    return true;
	}
	return false;
    }
}

class DisplayPanel extends Canvas {

    private PersonalData pdata;
    private boolean nodata = false;
    private boolean noConnection = false;
    private boolean connected = false;
    private boolean closed = false;
    private boolean alreadyOpen = false;
    private boolean alreadyClose = false;

    String header = "Search Information";
    String nodatagot = "Sorry! There is no such person by that name.";
    String noConnectionMsg1 = "Sorry! No connection to the database server.";
    String noConnectionMsg2 = "Please connect to the database by clicking [Open DB]";
    String DBCloseMsg1 = "Please close the connection by clicking [Close DB]";
    String DBCloseMsg2 = "whenever you are done with the search.";
    String connectedMsg = "Connection established.";
    String closedMsg = "Connection lost.";
    String alreadyOpenMsg = "Connection has been established already!";
    String alreadyCloseMsg = "Connection has not been established yet!";

    public DisplayPanel() {
	pdata=null;
	resize(600,400);
    }

    public void show(PersonalData per) {
	pdata = per;
        nodata = false;
    }
		
    public void showerr(int op) {
        if (op == 1) {
            pdata = null;
	    nodata = true;
        }
        if (op == 0) {
            pdata = null;
            noConnection = true;
        }
    }

    public void showStatus(int op) {
        if (op == 0) {
            connected = true;
            pdata = null;
        }
        if (op == 1) {
            closed = true;
            pdata = null;
        }
        if (op == 2) {
            alreadyOpen = true;
            pdata = null;
        }
        if (op == 3) {
            alreadyClose = true;
            pdata = null;
        }
    }

    public void paint(Graphics g) {
	setBackground(Color.orange);
	g.setFont( new Font("Times-Roman",Font.BOLD,22));
	g.setColor(new java.awt.Color(255,0,0));
	g.drawString(header,150,25);
	if(pdata!=null) {
	    g.setFont( new Font("Times-Roman",Font.BOLD,18));
	    g.setColor(new java.awt.Color(0,0,0));
	    g.drawString("Name       : " + pdata.getName(), 50, 60);
	    g.drawString("Age        : " + String.valueOf(pdata.getAge()), 50, 80);
	    g.drawString("Occupation : " + pdata.getOcc(), 50, 100);

            g.setFont( new Font("Times-Roman",Font.BOLD,18));
            g.setColor(new java.awt.Color(255,0,0));
            g.drawString(DBCloseMsg1, 50, 140);
            g.drawString(DBCloseMsg2, 50, 160);
	}
        if (connected) {
            g.setFont( new Font("Times-Roman",Font.BOLD,18));
            g.setColor(new java.awt.Color(0,0,255));
            g.drawString(connectedMsg, 50, 60);
            connected = false;
        }
        if (noConnection) {
            g.setFont( new Font("Times-Roman",Font.BOLD,18));
            g.setColor(new java.awt.Color(255,0,0));
            g.drawString(noConnectionMsg1, 50, 60);
            g.drawString(noConnectionMsg2, 50, 80);
            noConnection = false;
        }
        if (closed) {
            g.setFont( new Font("Times-Roman",Font.BOLD,18));
            g.setColor(new java.awt.Color(0,0,255));
            g.drawString(closedMsg, 50, 60);
            closed = false;
        }
	if (nodata) {
	    g.setFont( new Font("Times-Roman",Font.BOLD,18));
	    g.setColor(new java.awt.Color(0,0,0));
	    g.drawString(nodatagot, 50, 60);
            nodata = false;

            g.setFont( new Font("Times-Roman",Font.BOLD,18));
            g.setColor(new java.awt.Color(255,0,0));
            g.drawString(DBCloseMsg1, 50, 140);
            g.drawString(DBCloseMsg2, 50, 160);
	}
        if (alreadyOpen) {
            g.setFont( new Font("Times-Roman",Font.BOLD,18));
            g.setColor(new java.awt.Color(255,0,0));
            g.drawString(alreadyOpenMsg, 50, 60);
            alreadyOpen = false;
        }
        if (alreadyClose) {
            g.setFont( new Font("Times-Roman",Font.BOLD,18));
            g.setColor(new java.awt.Color(255,0,0));
            g.drawString(alreadyCloseMsg, 50, 60);
            alreadyClose = false;
        }
    }		       		
}

class PersonalData {

    private String Name;
    private String Age;
    private String Occ;

    public PersonalData(String name, String age, String occ) {
	Name = name;
	Age = age;
	Occ = occ;
    }

    public String getName() { return Name;}
    public String getAge()  { return Age;}
    public String getOcc()  { return Occ;}
}

7. Compile and Run

To compile all above java codes by entering the following statement at command line.
javac -classpath ${CLASSPATH} *.java ClientApp/*.java

To run this example:

  1. Start the naming server by entering

    nameserv -ORBInitialPort 8811

  2. Start the server
    java -classpath ${CLASSPATH} DBServer -ORBInitialPort 8811
  3. Start the client apple byt using browser to access your example

    (e.g., appletview 
    http://osprey7.npac.syr.edu:3768/arlspring98-docs/v11/JavaIDL/index.html)

Material

A Technical Introduction to Oracle RDBMSBasic Discussion of Oracle 7 Relational Database
Introduction to Java Language
Java Language and Object-Oriented Concepts
Java: Graphics and the Abstract Windowing Toolkit
Multithreading, useful Java classes, I/O, Networking, and the future
JDBC Access TutorialTutorial on using JDBC under Windows
JDBC including Access Java - Database Connectivity Overview Overview of JDBC and its use with Microsoft Access
JavaBeans CORBA ComponentWare
JDBC Guide: Getting Started
Java Resources at NAPC

References

JAVA
Java Interface Definition Language
JDBC Enhancements
JDBC Drivers
JDBCTM-ODBC Bridge Guide
Java Remothod Invocation
JavaBeans
JDK 1.1.5
Object Management Group

This page is maintained by Chao-Wei Ou

Last Update: Tue Jan 13 15:13:44 EST 1998