development 4 and inprise application server · c:\ias41 (not default) and the default osagent port...
TRANSCRIPT
EJB™ DevelopmentUsing JBuilder™ 4and Inprise™
ApplicationServer™ 4.1A Step-by-step Tutorial
by Todd Spurling, Systems Engineer, Inprise
AudienceEvaluators or new developers to EJB™ using JBuilder™ 4
and Inprise™ Application Server™ 4.1 can use this step-by-
step guide to get up and running with session and entity
beans, transactions, and clustering.
Table of ContentsIntroduction 2
Installation 2
Configuration 2
Part I Session Beans 4
Part II Entity Beans 8
Part III Transactions 11
Part IV Clustering 17
JBuilder
JBuilder
2
Introduction
JBuilder™ 4 is the RADest tool yet for developing EJB™
components and applications. This paper takes the
developer step by step through using JBuilder 4 wizards
and features to create and deploy session and entity
beans participating in container managed transactions.
The paper finishes with a brief demonstration of one
clustering feature of Inprise™ Application Server™ 4.1 (IAS
4.1).
The example described herein is a cut-down version of
the bank “transfer” example supplied in the Inprise
Application Server examples. It is cut down to reduce the
steps involved in creating a first-time EJB application.
Consult the actual bank transfer example for a more
complete set of code.
Installation
To be able to execute the steps in this paper exactly as
written you will need JBuilder 4, Inprise Application
Server 4.1, InterBase® 5.6 or 5.5, and InterClient™ 1.6 or
1.51. You can use your own database and JDBC® driver
instead of InterBase and InterClient if you feel confident
enough. The steps in this tutorial are written against an
NT install. For other operating systems, substitute drive
letters for directories as appropriate.
Evaluation versions of the products are available for
download from www.borland.com . Contact your local
Borland sales office for evaluation products on CD-ROM.
JBuilder 4 Enterprise www.borland.com/jbuilder
JDK 1.2.2 (for Inprise
Application Server
4.1)
java.sun.com
Inprise Application
Server 4.1
www.borland.com/appserver/d
ownload/index.html
InterBase 5.6 & www.interbase.com/open/dow
InterClient 1.6 nloads/ib_download.html
Install JBuilder 4. This guide assumes the install directory
will be c:\JBuilder40 (default).
• Install JBuilder Foundations first, then
• Install JBuilder 4 Enterprise.
Before installing IAS 4.1, download and install JDK™ 1.2.2
from java.sun.com .
• Install JDK 1.2.2 to c:\jdk1.2.2 (default).
Install Inprise Application Server 4.1.
• This guide assumes the install directory will be
c:\ias41 (not default) and the default osagent port
(14000) is used.
For the entity bean you will need access to a database.
I’m using InterBase 5.5 and Type III JDBC driver:
InterClient 1.51.
• Install InterBase to c:\Program Files\InterBase
Corp\InterBase (default)
• Install InterClient to c:\Program Files\InterBase
Corp\InterClient (default)
Configuration
We now need to tell JBuilder about the existence of IAS
4.1 and the supplied VisiBroker® 4.1 ORB to enable the
enterprise integration.
• Start JBuilder 4.
• Choose Tools | Setup…
• On the CORBA tab, select VisiBroker and press edit.
• Enter the path for ORB tools as the bin directory of
IAS 4.1.
• Press OK.
JBuilder
3
• On the Application Server tab, on IAS 4.1 enter the
install directory of IAS 4.1.
• Press OK and Restart JBuilder.
We will create a library consisting of the IAS 4.1 jars so
that JBuilder can compile projects that are dependent on
these classes .
• Choose Project | Default Project Properties…
• On the Required Libraries tab press Add…
• Press New…
• Add all the jar files in c:\ias41\lib
• Press Next, Next, Next, Next
• Set the New Library Name to ias.
Press Finish, OK, OK.
Part I Session Beans
Session Bean Development
In Part I we will create a JBuilder project, write a stateless
session bean called TellerBean with a method to return a
fictitious number that is the teller’s number, and a test
client to access the bean.
Later, in Part IV Clustering, we will use this method to
determine to which teller each client is load balanced. In
Part III we will add another method to this bean to
perform a transaction across two entity beans.
First, create the project:
• Choose File | New Project…
• Set the project name and directory to quickstart.
• Set the Root path to c:/project.
• Press Finish.
JBuilder
4
Now we will create an EJB Group. The EJB group will
cause JBuilder to automatically build a deployable jar file
containing our EJBs whenever we Make the project.
• Choose File | New… | Enterprise tab | Empty EJB
Group.
• Set the group’s Path: field to create a jar file called
quickstart in this project’s directory.
• Press OK.
Now to the Bean. We will use a wizard, of course:
• File | New… | Enterprise tab | Enterprise
JavaBean.
• Press Next to add the bean to the group we created.
• Set the Class name to TellerBean and press Next.
Leave the interface names as is, but change the
bean home name (JNDI) to TellerHome
• Press Finish.
You will now see three classes added to the project.
TellerHome and Teller are interfaces for the EJB container
to implement. TellerBean is our bean in which we will
add a method (our business logic). In the class
TellerBean, add the method:
public int getTellerNo() {
return 1;
}
Save All your work and Make .
We now need to add our method signature to the remote
interface, so that the container may expose the method
for remote invocation from a client. A new tab in the
Bean Tab called ‘Methods’ lets us tell JBuilder to write the
code for us:
• Double-click on TellerBean.java to view it.
• Select the Bean tab and then the Methods tab.
• Select the getTellerNo method checkbox.
JBuilder
5
If you look at the source code for Teller.java, you will see
the method declaration added to the interface.
We have now finished writing the Java code of our EJB.
We will now complete and verify the deployment
descriptor. The deployment descriptor is an important
part of EJB. It separates deployment settings from the
development code so that partitioning and tuning of the
application may take place without changes to source
code.
The deployment descriptor already exists in our project. It
was generated by the EJB group wizard. When we used
the wizard, it generated the TellerBean Java code for us
and added a matching entry into the deployment
descriptor. We will make some adjustments:
• Double-click quickstart.ejbgroup to view it.
In the structure pane (below), expand
TellerBean and click on Container
Transactions.
• Press Add to add a transaction attribute of ‘Required’
for our method.
The ‘Required’ transaction attribute will apply to all
methods and interfaces on the bean.
To verify that the settings in the deployment descriptor
have no errors, press verify . The message field
should show 0 errors and 0 warnings.
Save All your work and Make .
JBuilder
6
We have completed the server side of our application.
We will write a Java client to call getTellerNo on our
bean.
Use a new JBuilder 4 wizard to write a Test Client for our
EJB.
• File | New… | Enterprise tab | EJB Test Client
• Set the Class to Client
• Check Generate main function only.
• Press OK.
In the constructor of the created class, you will see a try
block containing the instantiation of a Naming Context, a
lookup of JNDI for ‘TellerHome’, and a narrow of the
returned object reference to the type TellerHome.
After these lines of code, but still within the try block,
add the following lines of code to create the bean, call
the remote method, and output the result:
Teller teller = tellerHome.create();
int t = teller.getTellerNo();
System.out.println(“Using teller No: “ + t);
Finally, this client requires the RMI/IIOP stubs to
be created in order to make the remote method
invocation.
• Right-click on TellerHome.java and choose
Properties.
• On the Build | VisiBroker tab, check Generate
IIOP.
• Press OK.
Save All your work and Make .
We have now finished the development of the stateless
session bean and a test client.
Deployment
For this first example we will execute the bean within a
container run within JBuilder 4. First run the VisiBroker
Smart Agent:
• Tools | VisiBroker Smart Agent
Setup a configuration to run the container:
• Run | Configurations…
• Edit the default configuration.
• Click on the EJB tab.
JBuilder
7
• Press OK, OK.
• Run the container in JBuilder 4 by pressing .
Wait for the container to initialize.
• Run the client by right-clicking on Client.java and
choosing run.
In the message tab for the Client you should see the
following output of a successful invocation:
C:\JBuilder40\jdk1.3\bin\javaw –class…
Using teller No: 1
Look at the message tab of container to see the
periodic printing of statistics showing the states
of EJBs.
Part II Entity Beans
Session Bean Development
In Part II we will create a Container Managed Persistence
Entity Bean that represents account data in a database.
We will create some accounts from a client.
Later, in Part III, our session bean developed earlier will
be modified to access two instances of this entity bean
and perform a transfer of funds between accounts.
An entity bean is an object representation of persistent
data, which in our case is in a relational database. We
will start with a predefined data dictionary (an existing
table definition in a database) and use a JBuilder 4 wizard
to create a CMP entity bean from this. At application
runtime the EJB container will implement the SQL for all
data transfers between the database and bean.
First we will create an InterBase database:
• Run InterBase Server.
• Run [InterClient] InterServer.
• Run InterBase Windows ISQL.
• Choose File | Create Database…
• Set the database name as
c:\project\quickstart\accounts.gdb
• Set the password as masterkey
JBuilder
8
• Press OK.
• Now create a table by entering in the top memo field:
create table account
(
name VARCHAR(20) NOT NULL,
balance INTEGER NOT NULL,
PRIMARY KEY (name)
);
• Execute the query by pressing the thunderbolt
button.
• Exit ISQL and answer Yes to commit your work.
Entity Bean Development
We will use a new wizard in JBuilder to generate the
code of our entity bean and add it to our existing project.
First, we need to install InterClient, the JDBC driver for
InterBase, onto the classpath of JBuilder or, more
specifically, the JDBC explorer.
• Shut down JBuilder.
• Copy interclient.jar from the InterClient install to the
JBuilder lib directory (just to shorten the path).
• Open c:\JBuilder40\bin\jdbce.config in an editor.
• Add the InterClient driver and save, i.e.:
# Add other database drivers here
addpath ../lib/interclient.jar
• Open JBuilder.
Check that the database has been created successfully by
viewing it in JDBC explorer.
• Tools | JDBC Explorer
• File | New…
• Select the driver interbase.interclient.Driver
• Use the browse button to select our
ACCOUNTS.GDB
The URL here is
jdbc:interbase://localhost/C:\project\quickstart\ACCOUN
TS.GDB
• Press OK.
• Expand the URL branch just created and…
• Login with user SYSDBA & masterkey. (CASE-SENS)
• Expand the tree to see the created table and columns.
JBuilder
9
• Close JDBC explorer, saving changes when asked.
The Bean
To add an entity bean to the quickstart project use the
EJB Entity Bean Modeller in JBuilder.
• File | New… | Enterprise tab | EJB Entity Bean
Modeller.
• Choose Next to add the bean to the existing group.
• In step 2, log in to the database using the interclient
driver, the URL of ACCOUNTS.GDB, the username
SYSDBA and the password masterkey (Use Choose
Existing Connection... as a shortcut to fill in the
first two).
• Press Next
• Select the Account table with the > button, and Next.
• Press Next for all columns to be used.
Press Next for standard type mappings.
• Press Next to use the class names and PK class
shown.
• Press Finish.
Save All your work and Make .
We have finished writing the entity bean. In fact, the
wizard has also added an entry to the deployment
descriptor as well a a datasource entry. An entity bean is,
practically, just generated code. Next, a client will be
written to access the entity bean, creating four instances,
and thus creating four rows in the accounts table in the
database.
Use the EJB Test Client Wizard again, but this time
create a test client against the Account EJB, use the
default class name AccountTestClient1, and generate a
main function.
In the try block this time add the following lines after the
casting/narrowing line of code:
Account ac1 = accountHome.create("John", 150);
Account ac2 = accountHome.create("Paul", 150);
Account ac3 = accountHome.create("George", 150);
Account ac4 = accountHome.create("Ringo", 150);
Create RMI/IIOP stubs for AccountHome.java by
right-clicking on it and in the properties dialog checking
Generate IIOP.
Save All your work and Make .
Deployment
We will run the client once against the container to create
the four accounts. We will still be running the container
within JBuilder.
JBuilder
10
First create a library so that the InterClient driver will be
added to the classpath when we run the container.
• Project | Project Properties
• On the Required Libraries tab press Add…
• Press New…
• Add the jar file c:\JBuilder40\lib\interclient.jar
• Press Next, Next, Next, Next
• Set the New Library Name to InterClient.
• Press Finish, OK, OK.
Running the application…
• Ensure Smart Agent, InterBase, and InterServer™ are
still running.
• Run the container in JBuilder 4 by pressing .
Wait for the container to initialize.
• Run the AccountTestClient1 by right clicking and
choosing run.
You should now be able to see the four accounts created
by using the JDBC explorer.
Part III Transactions
So far, we have used JBuilder 4 for Bean Development
and testing. In this section we will proceed through the
roles of Application Assembler and Deployer by
assembling the components in our application into one
jar file, deploying it to IAS 4.1, and configuring
transaction attributes.
Architecture
We will still be doing some bean development before we
assume the new roles. Our Bank Application will require
some new methods added to it so that we can perform a
funds transfer from one account to another within the
context of a transaction.
In the application, the client will make a remote
invocation on a new method called “transfer” on our
session bean to transfer money between accounts. The
client will pass in to the parameters of the method, the
name of the source account, the name of the destination
account, and the amount to transfer. The session bean
will look up the accounts using our entity bean, and
perform the transfer (a withdraw and a deposit) within a
transaction.
The entity bean will have two new methods to assist the
transfer. Add the following code to AccountBean.java.
public void deposit(int amount) {
balance += amount;
}
public void withdraw(int amount) {
if(balance < amount)
JBuilder
11
entityContext.setRollbackOnly();
else
balance -= amount;
}
Notice that the withdraw method forces a rollback of the
transaction if there are insufficient funds in the account.
Expose the new methods as remote by adding them to
the remote interface.
• Select the Bean tab and the Methods tab.
• Check the withdraw and deposit methods.
Rebuild the stubs for the AccountHome interface
• Right-click on AccountHome.java and choose
Rebuild.
Save All your work and Make . The entity
bean is finished.
The Teller Session Bean will now be modified to include
the transfer method that performs the funds transfer, by
withdrawing from one account and depositing to another.
Add the following code to the imports section of
TellerBean.java for the sake of easy coding of JNDI
access.
import javax.naming.*;
import javax.rmi.PortableRemoteObject;
Add the following code for the transfer method. What’s
happening here ? The client will call this method
specifying the source and destination accounts and the
amount. The method will use JNDI to look up a logical
name that maps to the AccountHome interface in the
deployment descriptor. The method looks up the ‘from’
and ‘to’ accounts using the findByPrimaryKey methods on
the AccountHome interface. At this point we have two
logical instances of the entity bean in the container. We
then call withdraw on the ‘from’ account and deposit
on the ‘to’ account.
public void transfer(String accountFrom, String
accountTo, int amount) throws RemoteException {
try {
//get naming context
Context ctx = new InitialContext();
//look up jndi name
String homeName =
"java:comp/env/ejb/accountdept"; // a logical name
to look up in DD
Object ref = ctx.lookup(homeName);
//cast to Home interface
AccountHome accountHome =
(AccountHome)PortableRemoteObject.narrow(ref,
AccountHome.class);
// find accounts
Account acc_from =
accountHome.findByPrimaryKey(accountFrom);
Account acc_to =
accountHome.findByPrimaryKey(accountTo);
// transfer
acc_from.withdraw(amount);
acc_to.deposit(amount);
}
catch(Exception ex) {
ex.printStackTrace();
throw new RemoteException(ex.getMessage());
}
}
Note: If this document is a PDF file, you can easily copy
the above text by changing the cursor with the Text
Selection Tool.
Expose the new methods as remote by adding them to
the remote interface.
• Select the Bean tab and the Methods tab.
• Check the transfer method.
JBuilder
12
Rebuild the stubs for the TellerHome interface
• Right-click on TellerHome.java and choose
Rebuild.
Save All your work and Make . The session
bean is finished.
We will now set the session to entity link, set the
transaction attributes, assemble the beans, and deploy
them.
Double-click on quickstart.ejbgroup to view the
deployment descriptor.
You will remember that the code in the transfer method
looks up a logical name to find the AccountHome
interface. The mapping of that logical name to a real
interface is determined in the deployment descriptor so
that partitioning can take place at a later date without
source code changes. We need to map the logical name
java:comp/env/ejb/accountdept to our Account bean.
• Click on the blue TellerBean in the structure pane.
• Change to the EJB References tab.
• Press Add.
• Set the name as ejb/accountdept and press OK.
• Check the isLink checkbox.
• Choose Account from the Link combo box.
By manipulating transaction attributes, we can instruct the
container to execute certain methods as a single unit of
work (a transaction). Doing this in the deployment
descriptor eliminates the need for writing specific Java
code to deal with transactions.
In our example we will tell the container to execute the
transfer method in a new transaction. The withdraw and
deposit methods of the entity bean will use the
transaction context created for the transfer method.
JBuilder
13
• In the structure pane expand the TellerBean branch.
• Click on Container Transactions.
Change the transaction attribute to Requires New.
• In the structure pane expand the Account bean
branch.
• Click on Container Transactions.
• View the transaction attribute as Required.
To verify that the settings in the deployment descriptor
have no errors press verify . The message field
should show 0 errors and 0 warnings.
Save All your work and Make .
In the role of the Assembler, we have decided that all the
beans in the project make up the application because all
of the beans are registered with the EJB group
quickstart.ejbgroup. The act of taking the components
and packaging them up as a single distributable (jar) file
was executed by JBuilder on the latest ‘Make’. You can
view the contents of the jar file by expanding the
quickstart.ejbgroup node, and then double clicking on
quickstart.jar.
Deployment
We will now assume the role of Deployer and push the
jar file to the application server. Note: the deployer has
the ability to change, at a later time, all of the settings we
set in the Deployment Descriptor in order to partition the
assembled package of components in the most suitable
configuration for his hardware. We will just deploy the jar
file to our instance of IAS 4.1.
• Make sure the container is no longer running in
JBuilder.
• Make sure InterBase and InterServer are still running.
• Run IAS 4.1.
• In JBuilder run Tools | EJB Deployment.
• Next for a quick deployment.
Browse to select the jar file we created (if it’s not here it
may be down in the classes\quickstart directory).
JBuilder
14
• Choose Next.
• Finish. The application is deployed to IAS 4.1.
As deployer, we have one further responsibility in this
deployment. We need to add the InterClient jar file to the
classpath of the container we deployed to. This is a one
off administration task that we will perform in the IAS
console.
• Run the IAS 4.1 console.
• Expand the Application Servers branch.
• Expand the <server> branch.
• Expand the EJB Containers branch.
• Right click on ejbContainer and choose Edit
Properties.
• Append c:\JBuilder40\lib\interclient.jar to the
classpath.
• Press OK.
• Let IAS restart the container now.
While we are in the console, we can see what we have
done.
Our EJB container is running the contents of
quickstart.jar, being the Account bean and the Teller
bean (at bottom). The beans’ home interfaces are
registered in JNDI / CosNaming (on right).
JBuilder
15
The server-side components are deployed and ready. We
are finished with the console.
We need to create a simple client in JBuilder to lookup
the teller and call transfer.
• File | New… | Enterprise tab | EJB Test Client
• Choose to create a test client to the TellerBean
Enterprise JavaBean.
• Name the class TransferClient.
• Select Generate main function only.
This time, add the following code to the usual spot in the
end of the try block to contact the teller and perform a
transfer.
Make sure you use $100 as the amount.
Teller teller = tellerHome.create();
teller.transfer("John", "Paul", 100);
Run the client by right-clicking on TransferClient.java
and choosing Run. Wait for the process to finish (Stop
button disables, play button enables).
The transaction completes and viewing the accounts in
JDBC explorer shows that $100 has been transferred from
John’s to Paul’s account.
JBuilder
16
Run the client again without making any changes to the
code.
This time when the withdraw method is executed within
the transfer transaction, there are insufficient funds in
John’s account and the transaction is set for Rollback
only. Subsequently, at the end of the transaction (the end
of the transfer method), the transaction service cannot
commit the transaction, so the change in balances is not
commited to the database. The balances are set to the
persisted values of the last transaction (John: $50, Paul:
$250).
Part IV Clustering
In this section, one feature of Inprise Application Server
clustering is demonstrated: JNDI name clustering,
facilitating load balancing across containers.
The Inprise Application Server is built upon VisiBroker,
and inherits the load balancing and fault tolerant features
of the ORB. The VisiBroker 4 Naming Service, which
implements JNDI, can be enabled for clustering,
supporting automatic load balancing of clients across
replicated beans in multiple containers.
In short, the same JNDI home name for a bean can be
used in multiple container deployments of that bean. The
Naming Service holds a reference to each container
implementing the home interface registered with that
home name, but only exposes the name once to the
client. When a client looks up the name in JNDI, the
naming service hands out a reference to the next
container, thus performing simple round-robin load
balancing.
In our example we will run two containers in IAS 4.1 and
deploy the bank application to each one. TellerBean in
the second container will be recompiled to return the
number 2 as its teller number so we can see the client
load balancing taking place.
First, we will add another container to IAS 4.1.
• Shut down IAS 4.1 (Use Ctrl-C in the DOS Window)
• In c:\ias41\properties\server\<your server> copy
(duplicate) the directory ejbcontainer to
ejbcontainer2
• Open ejbcontainer2/ejb.properties in a text editor
• Find the following lines:
ejb.jss.pstore_location=ejbcontainer_jss
ejb.jdb.pstore_location=ejbcontainer
• and change them to
ejb.jss.pstore_location=ejbcontainer2_jss
ejb.jdb.pstore_location=ejbcontainer2
• Save the file
We have set the new container to use its own session
state storage.
Tell the console to show ejbcontainer2:
• In the c:\ias41\properties\server\<your server>
directory open the file
adminster_services.properties
• Add ejbcontainer2 to the end of the line shown
below and save:
# Services to show in the admin applet
server.service.administer=webpageservice secureservice
osagentservice jdatastoreservice visinaming visitransact_tm
visitransact_xarf visimessage ejbcontainer ejbcontainer2
Enable Naming Service clustering:
• In c:\ias41\properties\server\<your
server>\java.options add the following line and
save: (CASE-SENSITIVE)
-Dvbroker.naming.propBindOn=1
JBuilder
17
• Start IAS 4.1
• Start the console
• Start ejbContainer2 from console by right-clicking
on it and choosing start.
To be able to tell which container the client is connected
to we will edit the teller number before deploying the
application to the second container.
In JBuilder:
• Edit the TellerBean’s getTellerNo( ) to return 2.
Save All your work and Make .
• Use Tools | EJB Deployment to deploy the jar file
to ejbContainer2.
• Run the Part I Client several times by right-clicking
on Client.java and choosing run repeatedly.
Consecutive executions of the client will return different
teller numbers as per load balancing:
C:\JBuilder40\jdk1.3\bin\javaw –class…
Using teller No: 1
C:\JBuilder40\jdk1.3\bin\javaw –class…
Using teller No: 2
Copyright © 2001 Inprise Corporation. All rights reserved. All Inprise and Borlandbrands and product names are trademarks or registered trademarks of InpriseCorporation. Java is a trademark or registered trademark of Sun Microsystems, Inc. inthe U.S. and other countries. CORBA is a trademark or registered trademark of ObjectManagement Group, Inc. in the U.S. and other countries. 11660
100 Enterprise WayScotts Valley, CA 95066-3249www.borland.com | 831-431-1000 | Fax: 831-431-4113