Programming Tutorials Browser Tutorials Articles Struts Tutorials Hibernate Tutorials

  Tutorial: J2SE 1.4 breathes new life into the CORBA community, Part 3

J2SE 1.4 breathes new life into the CORBA community, Part 3

Tutorial Details:

J2SE 1.4 breathes new life into the CORBA community, Part 3
J2SE 1.4 breathes new life into the CORBA community, Part 3
By: By Tarak Modi
Create enterprise-level apps with the POA
f you are just tuning in, we're in the midst of a four part series on the enterprise CORBA features included in J2SE (Java 2 Platform, Standard Edition) 1.4. Part 1 provided a whirlwind tour of those new features. That article ended with a quick Hello World example to set the stage for Part 2 , which detailed the Portable Object Adapter (POA), introduced in CORBA 2.2 to replace the Basic Object Adapter (BOA). I also delved into the mechanics behind Part 1's Hello World example. In this article, I show how to apply the knowledge you've gained about the POA to create an enterprise-level application. In the process, we look at how the POA enables us to create high performance, and highly scalable and available applications.
Read the whole series, "J2SE 1.4 Breathes New Life into the CORBA Community:"
Part 1: Get started developing enterprise CORBA applications with the latest version of J2SE
Part 2: Gain code portability with the Portable Object Adapter
Part 3: Create enterprise-level apps with the POA
Part 4: Portable interceptors and the Interoperable Naming Service
All ORBs (object request brokers) have a default POA called the RootPOA . You obtain a reference to the POA just as you would a reference to an ORB service such as the naming service, that is, via the resolve_initial_reference() method on the ORB instance. As you recall, each POA has an associated set of policies that govern its various characteristics, such as object reference lifetime, object ID uniqueness, and servant management. The POA specification (part of the CORBA specification) specifies a set of policies that all RootPOA s must have. Most large-scale projects typically require POAs with policies that differ from the RootPOA 's, which mandates new POA creation. To create a new POA, you need a reference to an existing POA, hence, you will always need to resolve a reference to the root POA, regardless of whether you will create object references with it. And finally, POAs observe a tree relationship similar to XML elements in the DOM (Document Object Model), with the RootPOA as the tree's root element.
An example: The CORBA bank
To put into perspective the various aspects of using a POA to create a more complex application (and to avoid boring you to death with theory), I will discuss a bank application. Using this application, a bank employee must:
Create a new account
Close an existing account
Perform basic operations on existing accounts, such as deposits, withdrawals, and balance checks
Define the IDL
Let's start by defining what our bank example's programming/implementation language-independent IDL (interface definition language) will look like. The IDL will consist of the following elements:
An enumeration that defines the different account types
A structure that defines the search/creation criteria for an account
Exceptions for different situations such as invalid account numbers and invalid account operations
The Account interface definition that contains methods to allow deposits and withdrawals, and an attribute to allow retrieval of an account balance
The Bank interface definition that contains methods to open, close, and find accounts
The complete IDL definition is shown below:
module bank {
enum AccountType { NIL, Checking, Saving };
struct AccountInformation
{
string accNum;
AccountType accType;
};
exception NoSuchAccountException
{
};
exception UnknownException
{
string reason;
};
exception InvalidOperationException
{
string reason;
};
interface Account
{
readonly attribute float balance;
readonly attribute string accountNumber;
readonly attribute AccountType accountType;
void deposit(in float amt) raises(InvalidOperationException, UnknownException);
void withdraw(in float amt) raises(InvalidOperationException, UnknownException);
};
typedef sequence Accounts;
interface Bank {
Account openAccount(in AccountInformation accInfo) raises(UnknownException);
void closeAccount(in string accNum) raises(UnknownException);
Accounts findAccounts(in AccountInformation accInfo) raises(UnknownException);
};
};
Create the database
We will store the account information in a database. I use SQL Server 2000 on my Windows 2000 machine. You can use any database of your choice. Here is the SQL script that I run to create the Account table in a database called Bank (consult your database vendor's documentation for instructions on creating a new database instance or add this table to an existing instance):
CREATE TABLE Account(
AccountNumber CHAR(15) NOT NULL PRIMARY KEY,
AccountType CHAR(1) NOT NULL,
Balance FLOAT NOT NULL
)
Implement the Bank object
Now implement the servant that implements the Bank interface. As you learned in Part 1 , the idlj compiler, used to compile the IDL, generates a class that you extend to create your servant implementation. This compiler-generated class mainly contains marshalling code. The bank servant will extend the BankPOA class, which is (you guessed it) generated by idlj. The bank servant implementation is fairly straightforward with the exception of some noteworthy points:
All the servant's methods use the static methods on the DBUtils class to access data from the database. For example, to create a new account record in the database, the openAccount() method calls the createAccount() method on DBUtils . DBUtils is an implementation of the Data Access Object pattern . To fulfill the data access function, you must configure DBUtils . Do that by placing the bank.properties file (available for download from Resources ) in the classpath along with the DBUtils.class file?they should be in the same directory (or jarred from the same directory). You may need to change bank.properties 's contents to match your database access parameters.
All account objects are created using a special POA called AccountPOA (more about that POA later). You obtain a reference to AccountPOA by calling the find_POA() method on the root POA as shown below:
POA accountPOA = this._poa().the_parent().find_POA("AccountPOA",true);
References, not actual objects, return from both the openAccount() and findAccounts() methods to speed request processing and because we do not know if the client really wants to call methods on the account object. We defer actual object creation to client method invocation. You create an account reference with the create_reference_with_id() method on the AccountPOA and use the account number as the reference's object ID. For example, look at the code fragment from the openAccount() method, which creates and returns a reference to a new account object:
Account theAccount =
AccountHelper.narrow(accountPOA.create_reference_with_id(accNum.getBytes(),
"IDL:bank/Account:1.0"));
return theAccount;
When a call to the closeAccount() method closes an account, the account information is removed from the database, a reference to the AccountPOA is obtained, and the CORBA object is deactivated by calling the deactivate_object() method on the AccountPOA . Calling this method causes two things to happen:
The entry corresponding to this servant and object ID drops from the active object map
The etherialize() method is called on the servant activator (discussed in the following section) if one has been registered with the AccountPOA
The complete bank servant implementation is shown below for reference:
package bank;
import org.omg.CORBA.*;
import org.omg.PortableServer.*;
import java.util.List;
import java.util.Iterator;
public class BankImpl extends bank.BankPOA
{
public bank.Account openAccount (bank.AccountInformation accInfo) throws
bank.UnknownException
{
try
{
DBUtils.createAccount(accInfo);
POA accountPOA = this._poa().find_POA("AccountPOA",true);
String accNum = accInfo.accNum;
Account theAccount = AccountHelper.narrow(
accountPOA.create_reference_with_id(accNum.getBytes(),
"IDL:bank/Account:1.0"));
return theAccount;
}
catch(Exception e)
{
throw new UnknownException(e.getMessage());
}
}
public void closeAccount (String accNum) throws bank.UnknownException
{
try
{
DBUtils.removeAccount(accNum);
POA accountPOA = this._poa().find_POA("AccountPOA",true);
accountPOA.deactivate_object(accNum.getBytes());
}
catch(org.omg.PortableServer.POAPackage.ObjectNotActive e)
{
}
catch(Exception e)
{
throw new UnknownException(e.getMessage());
}
}
public bank.Account[] findAccounts (bank.AccountInformation accInfo) throws bank.UnknownException
{
try
{
// Find the Accounts and return references
List accountNumbers = DBUtils.findAccounts(accInfo);
POA accountPOA = this._poa().find_POA("AccountPOA",true);
Account[] accounts = new Account[accountNumbers.size()];
Iterator it = accountNumbers.iterator();
int i=0;
while(it.hasNext())
{
accounts[i] = AccountHelper.narrow(
accountPOA.create_reference_with_id(((String)it.next()).getBytes(),
"IDL:bank/Account:1.0"));
i++;
}
return accounts;
}
catch(Exception e)
{
throw new UnknownException(e.getMessage());
}
}
}
Implement the Account object
As I mentioned above, the AccountPOA creates and manages account objects (and references). I will discuss three different ways to configure the AccountPOA and the resulting account servants. I list the three approaches below:
Use a servant activator
Use a servant locator
Use a default servant
Obviously, depending on how creative you are and how much time you have, you can create a solution using a combination of these three methods, but I will not discuss that here.
The above three solutions correspond to the USE_SERVANT_MANAGER and USE_DEFAULT_SERVANT values of the request processing policy values. The third (and default) value, USE_ACTIVE_OBJECT_MAP_ONLY , does not really work here since we would have to create all the account objects during sta


 

Read Tutorial at: Click here to view the tutorial

Rate Tutorial:
J2SE 1.4 breathes new life into the CORBA community, Part 3

View Tutorial:
J2SE 1.4 breathes new life into the CORBA community, Part 3

Related Tutorials:

RMI over IIOP - JavaWorld December 1999
RMI over IIOP - JavaWorld December 1999
 
Java security evolution and concepts, Part 1: Security nuts and bolts - JavaWorld April 2000
Java security evolution and concepts, Part 1: Security nuts and bolts - JavaWorld April 2000
 
Master Merlin's new I/O classes
Master Merlin's new I/O classes
 
J2SE 1.4 premieres Java's assertion capabilities, Part 1
J2SE 1.4 premieres Java's assertion capabilities, Part 1
 
J2SE 1.4 premieres Java's assertion capabilities, Part 2
J2SE 1.4 premieres Java's assertion capabilities, Part 2
 
Java security evolution and concepts, Part 5
Java security evolution and concepts, Part 5
 
Rumble in the jungle: J2EE versus .Net, Part 1
Rumble in the jungle: J2EE versus .Net, Part 1
 
J2SE 1.4 breathes new life into the CORBA community, Part 1
J2SE 1.4 breathes new life into the CORBA community, Part 1
 
Business process automation made easy with Java, Part 1
Business process automation made easy with Java, Part 1
 
J2SE 1.4 breathes new life into the CORBA community, Part 2
J2SE 1.4 breathes new life into the CORBA community, Part 2
 
J2SE 1.4 breathes new life into the CORBA community, Part 3
J2SE 1.4 breathes new life into the CORBA community, Part 3
 
Check out three collections libraries
Check out three collections libraries
 
J2SE 1.4 breathes new life into the CORBA community, Part 4
J2SE 1.4 breathes new life into the CORBA community, Part 4
 
Servlet 2.4: What's in store
Servlet 2.4: What's in store
 
Overcome J2SE 1.3-1.4 incompatibilities
Overcome J2SE 1.3-1.4 incompatibilities
 
Good article
Good article
 
Taming Tiger, Part 3
J2SE 5—code named "Tiger"—is the most significant revision to the Java language since its original inception. Tarak Modi's primary goal with his three-part series on Tiger is to familiarize readers with J2SE 5's most important additions and show how t
 
Bridging the Gap: J2SE 5.0 Annotations
Bridging the Gap: J2SE 5.0 Annotations It takes a long time for the Java community to fully absorb a major new JDK release; it seems to take about two more releases after a brand new version of the JDK before everything settles down. Application server v
 
Network Programming with JavaTM 2 Platform, Standard Edition 1.4 (J2SETM)
This article provides an overview of the new features and enhancements in the Java 2 Platform, Standard Edition 1.4 (J2SE), and shows you how to use them effectively.
 
Five Reasons to Move to the J2SE 5 Platform
Five important reasons to move to the Java 2 Platform, Standard Edition (J2SE platform) 5.0, supported by data and references to prove that the 5.0 release will reduce development and runtime costs.
 
Site navigation
 

 

Send your comments, Suggestions or Queries regarding this site at roseindia_net@yahoo.com.

Copyright © 2006. All rights reserved.