You are on page 1of 239

J2EE

Practical Guide
Bea Weblogic

Shree-Technologies
Shrikant
11/29/2008
Table of Contents

Module: Architecture ............................................................................................................................ 13

Lab exercise - WebLogic setup..................................................................................................... 13

Installing your WebLogic server................................................................................................... 13

Creating aliases for commonly used commands ........................................................................... 14

Deleting your WebLogic directory ............................................................................................... 15

Copying your WebLogic directory ............................................................................................... 15

Module: Architecture ........................................................................................................................ 15

Lab exercise - Familiarisation 1 - Installing Eclipse ..................................................................... 15

Installing Workshop For Weblogic ............................................................................................... 15

Creating a project .......................................................................................................................... 17

Deploying static HTML ................................................................................................................ 20

Running the HTML page .............................................................................................................. 22

Module: Architecture ........................................................................................................................ 25

Lab exercise - Familiarisation 2 .................................................................................................... 25

The environment ........................................................................................................................... 25

Familiarisation with the directory structure .................................................................................. 26

Starting your WebLogic server ..................................................................................................... 27

Getting started ............................................................................................................................... 28

Reading the configuration ............................................................................................................. 28

Relevant areas: .............................................................................................................................. 28

DOMAIN: ..................................................................................................................................... 29

Changing the configuration........................................................................................................... 30

Module: Servlets ............................................................................................................................... 32

Lab exercise - Hello World Servlet............................................................................................... 32

A HelloWorld servlet .................................................................................................................... 32

Using Eclipse to create a servlet ................................................................................................... 32

Packaging your servlet 1: directory structure................................................................................ 36

2
Packaging your servlet 2: deployment descriptor ......................................................................... 37

Packaging your servlet 3: static HTML files ................................................................................ 39

Packaging your servlet 4: create the WAR file ............................................................................. 41

Deploying your web application ................................................................................................... 42

Testing your web application ........................................................................................................ 43

Exploring the WebLogic console.................................................................................................. 43

Reflection ...................................................................................................................................... 46

Module: Servlets ............................................................................................................................... 47

Lab exercise - Counter Servlet ...................................................................................................... 47

A Counter servlet .......................................................................................................................... 47

Copying an existing Servlet .......................................................................................................... 47

Servlets and threading ................................................................................................................... 48

Running your servlet ..................................................................................................................... 48

Module: Servlets ............................................................................................................................... 51

Lab exercise - Form parameters .................................................................................................... 51

A SettableCounter servlet ............................................................................................................. 52

Request and Response objects ...................................................................................................... 52

Reading form parameters .............................................................................................................. 53

Aside: printing all form parameters .............................................................................................. 54

Module: Servlets ............................................................................................................................... 55

Lab exercise - HTTP Sessions ...................................................................................................... 55

A SessionCounter servlet .............................................................................................................. 55

The state problem.......................................................................................................................... 55

Sessions and Java .......................................................................................................................... 56

SessionCounterServlet .................................................................................................................. 57

Aside: common usage pattern for sessions ................................................................................... 57

URL Rewriting.............................................................................................................................. 57

Module: Servlets ............................................................................................................................... 60

3
Tutorial - Accessing resources (e.g. relative files) ........................................................................ 60

Some sample code......................................................................................................................... 60

Module: Servlets ............................................................................................................................... 61

Tutorial exercise - Creating a WAR file manually ....................................................................... 61

Manually creating a servlet ........................................................................................................... 61

Packaging your servlet 1: directory structure................................................................................ 62

Packaging your servlet 2: deployment descriptor ......................................................................... 63

Packaging your servlet 3: static HTML files ................................................................................ 64

Packaging your servlet 4: final check ........................................................................................... 64

Packaging your servlet 5: create the WAR file ............................................................................. 65

Deploying your web application ................................................................................................... 65

Testing your web application ........................................................................................................ 66

Reflection ...................................................................................................................................... 66

Module: JSP ...................................................................................................................................... 67

Lab exercise - Hello World JSP .................................................................................................... 67

A HelloWorld JSP......................................................................................................................... 67

Creating a subfolder (subdirectory) .............................................................................................. 68

Module: JSP ...................................................................................................................................... 70

Lab exercise - JSP and form parameters ....................................................................................... 70

More implicit objects in JSP ......................................................................................................... 70

Reading form parameters in JSP ................................................................................................... 70

JSP declarations, scriptlets and expressions.................................................................................. 71

The exercise - changing background colours ................................................................................ 72

Module: JSP ...................................................................................................................................... 73

Lab exercise - JSP and sessions .................................................................................................... 73

Accessing sessions in JSP ............................................................................................................. 73

Using Java class libraries in JSP ................................................................................................... 74

The exercise - storing a history of background colours ................................................................ 74

4
Module: JSP ...................................................................................................................................... 76

Lab exercise - JSP and sessions .................................................................................................... 76

Accessing sessions in JSP ............................................................................................................. 76

Using Java class libraries in JSP ................................................................................................... 77

The exercise - storing a history of background colours ................................................................ 77

Module: JSP ...................................................................................................................................... 78

Lab exercise - Web authentication ................................................................................................ 78

HTTP Basic Authentication .......................................................................................................... 79

Module: JSP ...................................................................................................................................... 83

Lab exercise - Using a JavaBean .................................................................................................. 83

Why use JavaBeans? ..................................................................................................................... 84

What are JavaBeans? .................................................................................................................... 84

Creating your JavaBean ................................................................................................................ 85

Packaging your JavaBean ................................................................................................................. 87

Creating your JSP page ................................................................................................................. 88

Adding new properties .................................................................................................................. 89

Beans and sessions ........................................................................................................................ 89

Module: JSP ...................................................................................................................................... 90

Lab exercise - Using Struts ........................................................................................................... 90

Adding support for Struts.................................................................................................................. 90

Our Lab example............................................................................................................................... 91

Struts Configuration ...................................................................................................................... 92

Struts layout .................................................................................................................................. 92

Modifying struts ............................................................................................................................ 92

More tasks ..................................................................................................................................... 94

References ......................................................................................................................................... 94

Module: JDBC .................................................................................................................................. 94

Lab exercise - Oracle Familiarisation - command line version .................................................... 94

5
Setting up your Oracle account ..................................................................................................... 95

Creating an SQL command file .................................................................................................... 95

Starting SQL*Plus ........................................................................................................................ 97

Running your SQL command file ................................................................................................. 98

Running ad-hoc SQL queries and SQL*Plus commands ............................................................. 98

Quick SQL*Plus Tutorial.............................................................................................................. 98

Changing your password............................................................................................................... 98

Disconnecting from SQL*Plus ..................................................................................................... 99

Oracle Tools .................................................................................................................................. 99

Oracle Documentation .................................................................................................................. 99

Module: JDBC .................................................................................................................................. 99

Lab exercise - Oracle Familiarisation - Workshop for Weblogic version .................................. 100

Setting up your Oracle account ................................................................................................... 100

Setting up your Workshop project .............................................................................................. 100

Creating an SQLpage file............................................................................................................ 100

Creating a Database Connection ................................................................................................. 102

Running your SQL command file ............................................................................................... 102

Exploring your Database............................................................................................................. 103

Disconnecting ............................................................................................................................. 104

Module: JDBC ................................................................................................................................ 105

Lab exercise - Hello World JDBC .............................................................................................. 105

A HelloWorld JDBC application ................................................................................................ 105

Running in Workshop ................................................................................................................. 106

Running from the Command Prompt .......................................................................................... 106

Notes ........................................................................................................................................... 107

Module: JDBC ................................................................................................................................ 107

Lab exercise - JDBC in a JavaBean ............................................................................................ 108

JDBC in a JavaBean.................................................................................................................... 108

6
A unit test for the JDBC JavaBean ............................................................................................. 109

Module: JDBC ................................................................................................................................ 110

Lab exercise - JDBC in a JavaBean in a JSP .............................................................................. 111

Adding JSP.................................................................................................................................. 111

Improving formatting .................................................................................................................. 112

Better Solution ............................................................................................................................ 112

Module: JDBC ................................................................................................................................ 113

Lab exercise - Connection Pools and Data Sources .................................................................... 113

JDBC Connection Pools.............................................................................................................. 113

Verifying your Connection Pool and Data Source...................................................................... 115

The exercise ................................................................................................................................ 115

Testing your new bean ................................................................................................................ 116

Module: JDBC ................................................................................................................................ 117

Tutorial - Using other databases with Weblogic 10 .................................................................... 117

Module: JDBC ................................................................................................................................ 120

Tutorial - ODBC example ........................................................................................................... 120

Creating an ODBC DSN ............................................................................................................. 121

Accessing the ODBC DSN from a Java program ....................................................................... 122

Module: JDBC ................................................................................................................................ 122

Tutorial - Oracle SQL*Plus ........................................................................................................ 122

Running SQL*Plus ..................................................................................................................... 123

Useful SQL*Plus commands ...................................................................................................... 123

Module: JDBC ................................................................................................................................ 124

Tutorial - Quick SQL Refresher.................................................................................................. 125

SQL SELECT statement ............................................................................................................. 125

SQL CREATE/DROP statements ............................................................................................... 128

SQL INSERT/DELETE statements ............................................................................................ 129

SQL UPDATE statements .......................................................................................................... 130

7
Module: RMI .................................................................................................................................. 131

Lab exercise - RMI client/server application .............................................................................. 131

Overview of RMI ........................................................................................................................ 132

Development Process .................................................................................................................. 132

Creating a simple RMI application ............................................................................................. 133

Running the HelloWorld example .............................................................................................. 137

Next step ... ................................................................................................................................. 138

Module: JNDI ................................................................................................................................. 139

Lab exercise - overview .............................................................................................................. 139

About LDAP and directory structures......................................................................................... 140

Accessing an LDAP Directory from the command line ............................................................. 140

Module: JNDI ................................................................................................................................. 142

Lab exercise - LDAP programming ............................................................................................ 142

An example first .......................................................................................................................... 143

Accessing an LDAP Directory from a web application .............................................................. 143

Module: JNDI ................................................................................................................................. 144

Tutorial - Looking up Weblogic LDAP ...................................................................................... 144

Viewing internal LDAP objects .................................................................................................. 144

Setting up Weblogic LDAP for external access.......................................................................... 144

Using the Weblogic Embedded LDAP directory server ............................................................. 145

Module: EJB ................................................................................................................................... 146

Lab exercise - Stateless Session Bean - Manual technique......................................................... 146

Overview of EJB ......................................................................................................................... 146

Development Process .................................................................................................................. 147

Creating an EJB stateless session bean ....................................................................................... 148

Running the HelloWorld EJB example ....................................................................................... 156

Next step ... ................................................................................................................................. 156

Module: EJB ................................................................................................................................... 156

8
Lab exercise - Using Eclipse + Xdoclet to generate EJB............................................................ 156

Rapid code development ............................................................................................................. 156

Using Weblogic Workshop EJBgen ........................................................................................... 157

Using Eclipse & XDoclet............................................................................................................ 157

Step 2 - Create a new Session Bean ............................................................................................ 161

Step 3: Enhancing the Enterprise JavaBean ................................................................................ 164

Step 4: Deploy the bean .............................................................................................................. 165

Step 5: Creating the client: .......................................................................................................... 165

Step 6: Running the client ........................................................................................................... 167

Problems you may encounter ...................................................................................................... 167

Next step ... ................................................................................................................................. 167

Module: EJB ................................................................................................................................... 168

Lab exercise - CMP Entity Bean- manually ............................................................................... 168

Overview of Entity Beans ........................................................................................................... 168

Development Process .................................................................................................................. 169

Creating an EJB CMP Entity bean .............................................................................................. 169

Module: EJB ................................................................................................................................... 175

Lab exercise - CMP Entity Bean-using Eclipse + XDoclet ........................................................ 176

Entity Beans using XDoclet ........................................................................................................ 176

Development Process .................................................................................................................. 176

Creating an EJB CMP Entity bean .............................................................................................. 176

Creating a custom ejbCreate() method........................................................................................ 179

Deploying it ................................................................................................................................ 181

Client code. ................................................................................................................................. 181

More things to do ........................................................................................................................ 183

Facade patterns................................................................................................................................ 183

What if the EJB's are in seperate projects? ................................................................................. 184

Module: EJB ................................................................................................................................... 184

9
Creating EAR files for deployment ............................................................................................ 184

Directory structure ...................................................................................................................... 185

application.xml deployment descriptor ....................................................................................... 185

Notes about EAR files (and why they are good)......................................................................... 186

Referencing EJBs that your components use .............................................................................. 186

Steps in deploying a Java application with many parts............................................................... 189

Using Eclipse to generate EAR files ............................................................................................... 189

An example EAR file .................................................................................................................. 190

Module: XML ................................................................................................................................. 191

Lab exercise - Parsing XML in a JSP ......................................................................................... 191

XML............................................................................................................................................ 191

Parsing an XML file with SAX................................................................................................... 191

Module: XML (DOM) .................................................................................................................... 196

Lab exercise - Writing XML via DOM ...................................................................................... 196

Understanding the code............................................................................................................... 196

Adding indenting to show nesting level ...................................................................................... 200

Formatting the data in a table...................................................................................................... 201

Printing a subset of the data ........................................................................................................ 201

Module: XML ................................................................................................................................. 202

Lab exercise - Transforming XML in a JSP ............................................................................... 202

Creating an XSLT sample file .................................................................................................... 202

Using a web browser to do transformations................................................................................ 204

Using Java to do transformations ................................................................................................ 204

More exercises: XSLT functions ................................................................................................ 205

Advanced exercises:.................................................................................................................... 205

Printing a subset of the data ........................................................................................................ 206

Formatting the data in a table...................................................................................................... 206

Module: Web Services .................................................................................................................... 206

10
Lab exercise 1 - Exploring RPC Web Services .......................................................................... 206

Finding Web services .................................................................................................................. 206

Using Xmethods.com .................................................................................................................. 207

Using the Weblogic Universal Test Client ..................................................................................... 207

Alternative testing points ............................................................................................................ 209

Lab exercise 2 - Exploring other Web Services .......................................................................... 212

Reflection ........................................................................................................................................ 213

Module: Web Services .................................................................................................................... 213

Lab exercise 3 - Writing a simple RPC client ............................................................................. 213

JAX-RPC Static clients ................................................................................................................... 214

Create new project .......................................................................................................................... 214

Generating a static client stub ..................................................................................................... 214

Module: Web Services .................................................................................................................... 216

Lab exercise 5 - Writing a simple web service ........................................................................... 216

Writing the server code ............................................................................................................... 217

Generating the code .................................................................................................................... 217

Test.............................................................................................................................................. 218

Problems ..................................................................................................................................... 218

Module: Web Services .................................................................................................................... 218

Lab exercise 6 - Adding Basic security to a simple web service ................................................ 218

Setting up usernames & roles...................................................................................................... 219

Writing the server code ............................................................................................................... 220

Redeploy & Test ......................................................................................................................... 220

Generating the Client skeleton .................................................................................................... 221

Test.............................................................................................................................................. 221

Module: Web Services .................................................................................................................... 222

Lab exercise 7 - Writing a more complex web service ............................................................... 222

Other data types .......................................................................................................................... 223

11
Lab Exercise: Returning complex types ......................................................................................... 223

Creating a JavaBean .................................................................................................................... 223

Add new complex methods to your class.................................................................................... 224

Building a client .............................................................................................................................. 224

Module: Security............................................................................................................................. 225

Lab exercise - Confidentiality ..................................................................................................... 225

Using SSL ................................................................................................................................... 226

Enforcing SSL ............................................................................................................................. 226

Module: Security............................................................................................................................. 227

Lab exercise - Web authentication .............................................................................................. 227

Declarative web authentication ................................................................................................... 228

Programmatic web authentication ............................................................................................... 228

Module: Transactions...................................................................................................................... 229

Lab exercise - Transactions......................................................................................................... 229

Transactions ................................................................................................................................ 230

Starting a transaction in a servlet ................................................................................................ 231

Module: Legacy .............................................................................................................................. 231

Lab exercise - Using CORBA..................................................................................................... 231

CORBA - C example .................................................................................................................. 232

Java CORBA client ..................................................................................................................... 234

Additional exercises .................................................................................................................... 235

Module: Legacy .............................................................................................................................. 235

Lab exercise - Using JMS ........................................................................................................... 235

Point-to-Point messaging ............................................................................................................ 236

Extra work................................................................................................................................... 239

12
Module: Architecture
Lab exercise - WebLogic setup

This laboratory exercise should be the first one you attempt, as it gives instructions on the
steps to follow to set WebLogic up for use in the Faculty of IT environment.

Level of Difficulty: 1 (easy)


Estimated time: 10 minutes

Installing your WebLogic server

With the WebLogic setup we are using, each person will run their own separate copy of the
WebLogic server on the lab workstations.
Each student will also have their own configuration for their server. This configuration is
stored in your home directory.

The first step is to logon to the lab workstations. You will have been allocated to a specific
machine. This will be the workstation allocated to you for the rest of the semester.

Open a terminal. To do this, select System → Terminal. If you are using KDE, you can also
press Right Mouse Button → Terminal.

Enter:

/opt/bea10/wlserver_10.0/common/bin/config.sh

Handy hint: Linux let's you complete the command line by pressing the first letter then the
tab key.

The BEA WebLogic Configuration Window should appear. Take the following steps to set
up WebLogic on your account:

1. At the Welcome panel:


Select [x] Create a new WebLogic domain. Then press the [Next] button.
2. At The Select Domain Source panel:
Select [x] Base this domain on an existing template
Leave the default directory and file:
(/opt/bea10/wlserver_10.0/common/templates/domains/wls.jar)
3. At The Configure administrator username panel:
Enter: Username: weblogic Password: weblogic
4. At The Configure server start mode and JDK panel:
Select [x] Development Mode and select [x] BEA supplied JDK, and select jRockit
5. At The Customize environment panel:
[x] No

13
6. At Create WebLogic Domain panel:
Domain name: weblogic & Domain location: /home/userid
(where userid is your Faculty of IT userid
7. At Creating Domain panel: [done]
8. Now note that the weblogic install is now in the in /home/userid/weblogic directory

Note: you have now completed the one mandatory part of this lab exercise. You should
read the following information, but you do not need to carry out the tasks below
immediately.

Creating aliases for commonly used commands

There are a few commands you will need to use over and over again. It might be useful for
you to create aliases for those commands to save you time and avoid repetitive typing.

Note that the following instructions assuming you are using the Bash shell (which is the
default within the Faculty). If you have changed your Unix shell to something else, the
following syntax may need to be adjusted to your shell.

Paste the following bash functions into a file in your home directory called: .bashrc (note the
leading "."). Create this file if it doesn't already exist.

Note: Don't forget the . (period) characters and spaces.

if [ -d /opt/bea10/wlserver_10.0 ] ; then
wlenv() { pushd .; . ~/weblogic/bin/setDomainEnv.sh; popd; }
wlstart() { cd ~/weblogic/; ./startWebLogic.sh; }
wlstop() { java weblogic.Admin -url t3://localhost:7001 \
-username weblogic -password weblogic FORCESHUTDOWN; }
wlenv
fi

With these aliases:

• 'wlenv' will set your environment variables ready to compile code for WebLogic
• 'wlstart' will start your server
• 'wlstop' will stop your server

You should also modify your: .bash_profile file with the following

source .bashrc
export PS1="[\u@\h:\w]\\$"

14
Deleting your WebLogic directory

During the semester, you may find that part of your WebLogic configuration becomes
corrupted, and your server will not start. If this happens, the easiest solution is to remove
your webLogic directory, and re-create it. Be sure you have kept a copy of all of your
deployed applications before you delete the directory though!

To delete your WebLogic directory, run the Unix command:

cd ~/weblogic
rm -r .

Note: be very careful to type this command correctly, as it will recursively delete all files in
the named directory. In particular, take care that there is no space following the tilde
character (~) or you will erase your entire home directory!

After deleting your webLogic directory, you can re-create it as described above.

Copying your WebLogic directory

If you wish to copy your webLogic directory, DO NOT use the Unix 'cp' command. Your
webLogic directory contains a number of symbolic links, and it is important that these are
kept as symbolic links.

Use the following command if you wish to copy your entire webLogic directory (replacing
'destdir' with the actual destination directory name):

cd; tar cf - weblogic | (cd destdir; tar xfBp -)

Module: Architecture
Lab exercise - Familiarisation 1 - Installing Eclipse

The laboratory exercise for this module to install Eclipse and then develop a one or two static
HTML pages

Level of Difficulty: 2 (moderately easy)


Estimated time: 30 minutes
Pre-requisites:

• Completed WebLogic setup lab exercise


• Run 'setDomainEnv.sh' to set your environment correctly

Installing Workshop For Weblogic

Open a terminal, then type the following commands

15
mkdir ~/workspace
tar xvf /pub/ajpcpe/workspace.tar

You now should have a directory called workspace. This is where your lab files will be stored
when using Workshop for WebLogic

To start workshop, type

cd ~/workspace
./workshop4WP

You now should


see

16
You should click on the X on the [Welcome] tab to close this window to get the following
window:

This is the main J2EE "perspective".

Creating a project

To create a new J2EE project, we are going to create a Web application first.

Step 1: From the Project Explorer:, Right Mouse Button click -> New-> Dynamic Web
Project
(alternatively: Choose the File->New->Other->Web->Dynamic Web Project )

17

18
Choose the name: labs
Target runtime: BEA Weblogic
Configurations: Weblogic Web Project Facets (minimal)
(hint: Press the down arrow in the Configuration box to get the list)

Then press [Next]

Step 2: We now get a Project Facets popup screen. A 'project facet' is Eclipse terminology
for the additional wizards and tools installed for this project. As you can see, there are many
to choose from such as Java Annotation processing (this handles Java 5 @annotations). For
the moment, don't change this screen.

Then press [Next]

Step 3: We now get a Web Module popup screen:

19
Change the Context root from "labs" to /
(note: this is the "subdirectory" of the web page, so we are now creating a home page for the
Weblogic server!)
Content directory: WebContent
Java source: src

Then press [Next]

Step 4: From the Weblogic Web Module panel: [x] Use Shared Libraries & press [Finish]

Deploying static HTML

The next challenge is to create HTML files for our web site

From Project Explorer select Labs

20
Now Right Mouse Button click -> New > HTML


(note: WebContent is highlighted)

21
Filename: index.html
& press [Next]

At the Select HTML Template panel: HTML 4.01 Transitional & press [Finish]

You can now see it generates a HTML page which you can edit.
Why not add some text or HTML formatting tags - change the title and maybe add a a <h1>
in the body would be nice.
Use Ctrl-S (or File->Save) to save this file.

Running the HTML page

Before you can start testing, you need to define a server to run this web page one. We will
use Weblogic as a normal web server for the moment.

Select the labs project in the Project Explorer and press the Right mouse button
Select Run As -> Run on Server

You will get a define new server panel:

22
Choose [x] Manually define a new server
Server host name: localhost
Server type: Bea Systems->BEA Weblogic Server v10
Server runtime: BEA weblogic v10

Select [x] Set server as project default:

You will now get a Define a weblogic server panel:

23
Domain Home: /home/userid/weblogic & select [finish] button
(note: userid should be your faculty userid)

You should get a "Add and Remove Projects" panel.

You can have more than one project running on each Weblogic server. For the moment, we
will leave this as-is. Press [finish] to continue.

You should get weblogic server starting in a new window - see the Console view on the
bottom right hand side for % progress)
Wait till the <Server started in RUNNING mode> message appears.

You should get a minibrowser in eclipse window with your web page!
You can add many extra pages. Try make them link eg: <a href=..">

If you get an error message saying "Publish was cancelled" this could be because your server
and project is already running.

If this is the case, you could start the server manually, by pressing the green arrow

If you double-click on the server name (eg: "BEA Weblogic Server V10.0" above), you can
also get the server configuration settings.
This will allow you to manually remove (ie: "undeploy" ) a project which may be preventing
weblogic from starting (for example, "labs" )

24
If you need to restart the internal browser for any reason, use Window -> Show View ->
Other -> General -> Internet Web Browser, however, it is better to start an external browser,
as the internal browser may not support all the latest browser functionality.

Test to see that your new application works. In a browser, open a URL like:

http://localhost:7001/index.html

Note that in most cases you will have a "Context root" which is effectively a subdirectory. So
if our web Context root was, for example, labs, our URL would be:
http://localhost:7001/labs/index.html

Notes:

• Write down notes as you go, particular parts of the process that seem difficult or
confusing.
• Ask questions.
• Use the WebLogic documentation to help you (start to become familiar with browsing
the documentation). You can find the documentation at:
o http://e-docs.bea.com/wls/docs1001/

For an introduction to WAR files, JAR files and EAR files, read Understanding WebLogic
Server Applications, URL: http://e-docs.bea.com/wls/docs100/programming/concepts.html

This will give you a head start on some of the later course material.

Module: Architecture
Lab exercise - Familiarisation 2

This laboratory exercise is intended to help you become familiar with running the application
server. It will cover starting up and shutting down the server, setting some of the
configuration options, and deploying static HTML web pages into the server.

Level of Difficulty: 1 (easy)


Estimated time: 45 minutes
Pre-requisites:

• Completed WebLogic setup lab exercise


• Completed Familiarisation 1 lab exercise

The environment

25
You will be running WebLogic Server on a Linux workstation. The WebLogic software is
installed centrally on file server, and is NFS mounted across all workstations, so everybody
will run the same version of the software.

In addition to the central installation of the software, every person will have their own private
WebLogic "domain". Each person will start up their own copy of the WebLogic software,
and load their domain. Your WebLogic domain configuration will be stored in a subdirectory
off your home directory.

There are three parts to using WebLogic:

1. running the server (starting/stopping)


2. using the management console (in a web browser)
3. installing your own applications

This lab exercise is designed to help you become familiar with the first two.

Familiarisation with the directory structure

Record your answers to the following questions.

• In which directory is your domain's config file, config.xml installed?

____________________________________________________________

• In the bin directory, there is a file called 'setDomainEnv.sh'. Have a look at the contents
of this file and see what it does. You should run this file every time, before you work
with WebLogic. If you haven't run it already in this session, do so now. Note that you
must run it by prefixing it with a dot, followed by a space, e.g. . setDomainEnv.sh

Note that the alias you created earlier called wlenv also executes this shell script. If
you have started a new shell, then this alias should be created and you can type wlenv
instead.

• In which directory is the WebLogic Server installed? (Hint: echo $CLASSPATH)

____________________________________________________________

• What version of Java are you using? (hint: java -version)

____________________________________________________________

26
• Does your PATH environment variable include the path to the correct version of
Java? (hint: echo $PATH). If not, you have not run setDomainEnv.sh correctly.
What is the path to the Java compiler?

____________________________________________________________

• In which directory are the WebLogic Java class libraries?

____________________________________________________________

• BEA provide some examples as part of the distribution of WebLogic. In which


directory are the examples located?

____________________________________________________________

• In your own WebLogic domain, in which directory is the file 'startWebLogic.sh' located
in?

____________________________________________________________

Starting your WebLogic server

IMPORTANT:
Make sure you only run 1 copy of weblogic at a time on the workstation.
This includes the test weblogic server running within Eclipse
Ensure that if this is the case, you should stop the weblogic server within eclipse first!

Use the following steps to start your WebLogic server:

1. First, check that you are logged in to a workstation machine, and NOT charlie or
sally. You must NOT run WebLogic on charlie or sally. If you are not sure which
host you are logged in to, type the Unix command:
2. hostname
3. Change into the directory where your 'startWebLogic.sh' script is located. You must run
the server from this directory. e.g.
4. cd ~/weblogic/
5. Start the server running:
6. ./startWebLogic.sh

You could also use the wlstart alias your set up in an earlier lab.

27
Getting started

• What are the ports your server is listening on? (hint: netstat -an )

____________________________________________________________

• Start your default WebLogic console by opening a web browser, and accessing the
URL:
• http://localhost:7001/console/

Note: If you are accessing this workstation from another machine, change localhost to
the name of the workstation

• Note that in the earlier lab, we defined an alias called wlstop, and this had hardcoded
the userid and password.
Is this a good thing to do? Why?

____________________________________________________________

____________________________________________________________

Enter 'weblogic' for the userid and 'weblogic' to logon to the WebLogic console.

Reading the configuration

Once you logon to the WebLogic console, you will see that there are various options to
change and view.

Relevant areas:

28
DOMAIN:

(this is the top of the menu tree [weblogic] in our console)


This provides management of the entire weblogic domain. Note in production you may have
more than 1 server.

We will just use the adminServer also as the development server.


You can start/stop server by [control] tab.
Select AdminServer(admin) & then you can start/resume/shutdown etc.

Shutting down the server: Note that if you just press Shutdown, WebLogic will wait until
all requests are serviced. If your program (JSP/Servlet etc) is in a loop, you can click on the
pull down and select Force Shutdown Now

29
ENVIRONMENT:

Don't worry about these options, this is used for clustering and production environments

DEPLOYMENTS:

You will see that this lists all J2EE applications and shared librarys installed ("deployed") on
your server. Some relevant tabs to look at:

[Control tab] You can individually (or globally) start or stop the applications.
If you have [Lock & Edit] the configuration, you can also install new apps, update and delete
existing apps. If you select any app, you will see it's [settings].

This has details like name, context root, path (if you generated this from eclipse, it will be
something like /home/chw/workspace/.metadata/.plugins/org.eclipse.core.resources/.projects/labs/
beadep/weblogic/labs !!

[Testing] tab is particularly handy to see what the full URL of the application is and any
welcome files in the web application.
[Monitoring] is good to see how many active servlets are being used (note: each JSP is also
considered
to be a servlet)
[Monitoring[Servlets]] is good for seeing the servlets available.
FileServlet, JSPServlet & WebServiceServlet are automatically generated ones from
weblogic.
[Monitoring [Sessions]] will track HTTP sessions being used.

SERVICES:

this section covers the J2EE services that the container must provide eg: JDBC, JMS etc
When using Database access, you need to define your JDBC details here.

SECURITY REALMS:

You can define a security realm to protect your web application. The default realm is
'myrealm' but you can create many more.Within this tab is [Configuration] & [Users and
Groups] where you can define users and groups.

Changing the configuration

Be careful at this point! Don't change anything you don't understand!

In order to change any parameter, you need to click the [Lock & Edit] button on the
upper left corner of the control panel

30
• Change the port that your server listens on to be port 12345. What additional step is
needed before the change is committed?

________________________________________________________

• Shut down your server using the WebLogic console. Generally, you should always
shut down gracefully using the console, or the command-line shutdown utility - don't
just close the Unix shell window.
• Restart your server (from the Windows Command Prompt).
• Change your port back to what it was before.
• Add some 'Notes' to your domain (or server).

Eclipse Links

http://www.stanford.edu/class/cs108/JavaTools/eclipse-guide/#NewProject

31
Module: Servlets
Lab exercise - Hello World Servlet

This laboratory exercise involves developing a Hello World servlet, step by step. It is a long
process, but each step should be simple enough. Take careful note of what you are doing at
each step, and the commands you need to run. It gets easier once you've worked out the
process - your first servlet will be your hardest!

Level of Difficulty: 1 (easy)


Estimated time: 30 minutes
Pre-requisites:

• Run 'setEnv.sh' to set your environment correctly


• Start your WebLogic server running in the background

A HelloWorld servlet

There are 2 main ways of creating a servlet

Manually creating a servlet

Before the days of Integrated Development Environments, programmers had to develop


servlets much like any other Java package (eg: Applets). The steps involved were

1. Create a development directory structure (typically a source code, build and deployment
directory).
2. Create a java class file which imports the relevant javax.servlet.* package (plus any other
utility packages you might need such as java.io.*)
3. This class needs to extend javax.servlet.http.HttpServlet and implements the doGet() (and
possibly doPost() )methods
4. You then compile this class into the build directory into the WEB-INF/classes directory
5. You then create & edit a deployment descriptor (WEB-INF/web.xml) with the relevant servlet
details
6. Add any extra files like graphics, html and .properties files into the top of the build directory.
7. You then use the jar cvf HelloWorldApp.war command to archive the entire build directory
into a single WAR file
8. You then deploy (copy) this .war file following the instructions of your particular web
application server.

You can optionally attempt this later by looking at the "tutorial: creating war files manually".

Using Eclipse to create a servlet

In this lab we will use Eclipse (Workshop for Weblogic) to create our first servlet.

This exercise will lead you step by step through writing and deploying your first Java servlet.

32
1. We will re-use the existing lab project from the previous module. However, there is
one change that we will make - we will remove the default context since this is
effectively hardcoding our URL!
From the Project Explorer, DOUBLE click on Weblogic Deployment Descriptor.
Select the Design tab and select the wls:context-root attribute.
Press RIGHT Mouse button, and select Remove. Save the changes (Control-S).

2. Now to create a servlet, highlight the project name (labs) and use the RIGHT mouse button to select
New -> Servlet

3.
4. In the Create Servlet wizard window, enter the Class name for the servlet - ie:
HelloWorldServlet. You can optionally enter a Java Package name but this and future lab

33
examples won't use one for the moment. Press Next to continue.

5. We finish by entering information about the servlet deployment descriptor - the name defaults
to HelloWorldServlet, but we will change this to HelloWorld.
Enter a description as well.
Finally, change the URL mapping (the default is /HelloWorldServlet). To do this, highlight
the URL mapping and click Edit.
Press Finish to create the Servlet.

34
6. Eclipse now creates a skeleton of the Servlet code. Eclipse tags the places where you enter
your own code with the comment // TODO: Auto Generated Method Stub

7. Replace this comment with the following code fragment. FOR THE MOMENT, PLEASE
DON'T CUT AND PASTE THE CODE. We will experiment with Eclipse's Code assist
features to help you enter the correct code as you type!

response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html><head><title>Hello, World response</title></head><body>");
out.println("<h1>Hi, this is from a servlet</h1>");
out.println("doesnt do much so far.");
out.println("</body></html>");

As you type resp, you can press Ctrl-spacebar to ask Eclipse to show you the valid
candidates which you can legally enter in the Java class that start with the letters resp. Try it...

35
8. Pressing Enter will insert the whole string response for you. Now if we press the . key to
continue, Eclipse will pop up a list of valid methods for this object - we can type-ahead to
narrow this list down. Try the first 4 letters setc to get the list down to setContentType. The
really neat thing about Eclipse is it also describes what the method does. This even works for
your own custom built methods. However, you do need to use Javadoc /** descriptors
before your methods for this to work...

Pressing Enter will insert the template for this method. You simply replace the
highlighted string with your own code.

9. Finish typing in the rest of the code now. In later labs you are welcome to cut and paste the
code directly into Eclipse, but for the moment, just get used to the Eclipse code editor by
typing it in by hand....

10.

Packaging your servlet 1: directory structure

36
Java servlets execute as part of a web server. You cannot run or test them from the command
line. The web server you will use to run your servlet is the web server built in to the
application server (WebLogic). To "run" your servlet, you will access a URL in your web
browser. This is quite similar to running a CGI program, or running a PHP script.

Before you can install your servlet into the application server, it needs to be packaged
properly. Servlets are part of what J2EE calls 'web applications', and web applications should
be packaged in a Web Application Archive file, or WAR file.

A WAR file is basically a compressed zip file that contains all parts of your web application.
The parts may include:

• static web site files (HTML, GIF, JPEG, CSS, etc)


• Java servlets
• a deployment descriptor (described later)

When you package your application as a WAR file, it must follow a particular directory
structure like the following.

Packaging your servlet 2: deployment descriptor

37
As mentioned above, a WAR file contains static HTML (etc) files, Java servlet classes, and a
deployment descriptor. The next step is for you to create a deployment descriptor.

A deployment descriptor is an XML file describing the properties of your 'web application'.
When your web application includes servlets, the deployment descriptor file describes the
name of each servlet, and what URL should be used to invoke the servlet.

In the case of web applications, the deployment descriptor is contained in a file called
web.xml, and it must be placed in the WEB-INF directory.

The Eclipse Servlet wizard automatically updates and generates this web.xml file. To view this
file, check the double click the Deployment Descriptor (alternatively, look in the WEB-INF
subdirectory for web.xml )

You could also view this in the Deployment Descriptor/Design tab

38
Points to note:

• servlet-name can be any name you choose. It does not have to be the same as the
filename in which the servlet class is stored. Every servlet referenced in your web.xml
must have a unique servlet-name within that one web.xml file.
• servlet-class specifies the name of the Java class file containing the compiled servlet
code.
• url-pattern specifies the URL by which you want users to be able to execute your
servlet. In the example shown above, the url-pattern is "/HW", so the URL that will be
used to invoke the servlet will look like http://hostname:7001/HelloWorldApp/HW

Packaging your servlet 3: static HTML files

Your WAR file can also include static HTML files, as well as images (GIF, JPEG), style
sheets (CSS), and any other static files you would expect to find on a web server.

In the WAR file, these files must be placed outside the WEB-INF directory. Any files not in
the WEB-INF directory can be accessed through the web browser. Any files that are inside the
WEB-INF directory (including your web.xml deployment descriptor, and your servlet class files)
will be protected, and are not accessible to users over the web.

39
You can create subdirectories visible to the user by selecting WebContent and Right Mouse
clicking and selecting New -> Folder.

CAUTION: Any subdirectory created OUTSIDE of WebContent will not be accessible


to web users - this includes any file placed in WEB-INF!!

You should already have a static HTML file called index.html from the previous lab. Modify
this file to link to your new servlet.

<h1>My first WAR file</h1>


<P>Run my <A HREF="HW">Hello World servlet</A>.</P>

NOTE: Notice that our HREF refers to HW not /HW or HelloWorldServlet.


This is because a putting a / in front of a reference will make the browser look for the
absolute URL at the root context (ie: / ) of the web site, not the relative sub-context (ie: /labs
) which we will be deployed as. So putting a /HW will force the web browser to look for
http://localhost:7001/HW instead of http://localhost:7001/labs/HW

Here is a rough mapping of how your Eclipse/Workshop project maps to a WAR file.

40
Packaging your servlet 4: create the WAR file

When testing using Eclipse/Workshop we have been running under what's called an
"exploded war directory", ie. the war file has not been archived. While this isn't specified in
the Java Enterprise standard, most vendors including Weblogic allow you to specify a
directory instead of a WAR file to deploy. This is great for application development and
testing. If you are curious about where this directory is located when developing using
Eclipse, look at the Weblogic console for a deployment module called
"_workshop_auto_generated_ear_" file.

Let's now create a war file which we can distribute and deploy seperately.

1. Step 1: Select the project you wish to create (in our case, labs ) and press Right mouse button.
Select Export -> WAR file

2. Next , choose the destination file - let's call this helloWorldApp.war. You should put this
into your own directory (I created a local directory called aip to put these files in)
Note: Normally you don't includfe source files, but when developing I tend to do this so when
I debug I can view which version of the source code I used.
You must export the source files when submitting assignments though, so let's Select "Export
Source Files" now..
You may also have to select "Overwrite existing file" if helloWorldApp.war exists already.

41
Also note that the META-INF directory and the MANIFEST.MF file are automatically
added by Eclipse.You can ignore them for the moment.

Deploying your web application

Now that you have a WAR file, you can "deploy" it to the web server. Deployment is the
process of installing an application.

In WebLogic, there are a variety of ways you can deploy an application. The simplest is just
to copy your WAR file into your WebLogic server's "autodeploy" directory.

cp helloWorldApp.war ~/weblogic/autodeploy

You can do this when the server is running. The server checks the contents of the autodeploy
directory every few seconds, and when it sees a new WAR file, or one with an updated
timestamp, it automatically deploys (or redeploys) it.

Note: if you don't have a weblogic.xml file with a wls:context-root entry in it, weblogic will
use the name of the war file as the context-root.

So in our case, the context-root will be helloWorldApp

NOTE: URL's in Java Enterprise are case sensitive!!! So if you type in /HelloWorldApp
or /helloworldapp on the browser, you will get a 404 Not Found error!!

42
Testing your web application

If you have followed the steps above exactly, try accessing your application through the
following URL:

http://localhost:7001/helloWorldApp/

It should show you the contents of your index.html file. If you click on the link to your servlet,
it should execute your servlet and display the servlet's "Hello World" message.

Note that when you deployed your WAR file into WebLogic, it created a virtual directory
under the root of your web server with the same name as your WAR file. So the name you
choose for your WAR files is important, because the WAR filename will become part of the
URL.

Exploring the WebLogic console

Open the weblogic console (hint: http://localhost:7001/console) and enter the usual
administrator userid and password (recall: we set this to weblogic and weblogic
respectively??)

On the left hand menu (Domain Structure menu) is a choice called deployments. Select this
and you should see the
Summary of Deployments" screen like:

43
(this may not be exactly the same as yours)

You should see a module called _appsdir_helloWorldApp_war (autodeployed) module. Click


on this to see the Settings for this deployed war file.

44
You can see that the path is where the actual WAR file resides - in our ~/autodeploy
directory. Also note that the console will display any sub-modules of your deployed module.
In our case, there is a Web Application called _appsdir_helloWorldApp_war (autodeployed)
which if clicked, returns to this very same page!! (this is more useful when we have an
Enterprise Archive (EAR) file which may contain many sub-modules.

Click on the Testing tab at the top. This allows you to check what Weblogic thinks the URL
to this application should be. If it is something other than "http://127.0.0.1" just ignore that
for the moment. (technically this is because Weblogic binds to all the available network
addresses of the host. So it could be something like http://138.25.16.222 or some other weird
number).

For the moment, the only important item we want to observe here is the URL and note that
the default URL is something like http://xxx.xxx.xxx.xxx/helloWorldApp

So if you are trying to debug your web application and can't seem to start, use this to find out
what the default URL should be.

As mentioned earlier, note that there is a Deployment module called


"_workshop_auto_generated_ear_". If you select this you could also click on this to see the
labs web module, and do the same exploring we did the the helloWorldApp module..

45
Reflection

This exercise took you through the steps to to create a Servlet using Eclipse (Workshop for
Weblogic). Certainly it is possible to create a WAR file by creating a directory structure
much like a WAR file, creating web.xml/weblogic.xml by hand, creating Servlet java files
and compiling them by hand (or with a build script like Makefile or Ant) and finally
generating a WAR file using the jar cvf command.

Using tools like Eclipse improve programmer efficiency by allowing you to incrementally
build and test and using wizards to generate & "instantly" test your application.

Note what steps you took, and don't forget to ask your tutor for assistance as necessary.

Furthur labs will not be as detailed as this one, so you must be comfortable using the Eclipse
IDE as we go on further

46
Module: Servlets
Lab exercise - Counter Servlet

This laboratory exercise involves modifying your Hello World servlet to make it keep count
of the number of times it has been invoked.

Level of Difficulty: 2 (moderately easy)


Estimated time: 15 minutes
Pre-requisites:

• Completed the Hello World servlet lab exercise

A Counter servlet

The goal of this exercise is to create a servlet that maintains a counter of the number of times
it has been invoked since it was last reloaded by the web server. It will use a class variable
(i.e. static) to keep count of the number of invocations. Each time the servlet is invoked, it
will print out the value of the counter.

There are 2 main ways to do this lab.

• Method 1 is to create a new Servlet (as per the Hello World Servlet lab) and name this
CounterServlet, with the URL mapping of /Counter. You then add the required code
to perform the desired task. This is fairly straight forward.
• Method 2 is to copy the existing Servlet and to add it into the deployment descriptor.
This is a touch more complicated, so we will do this in this lab to show you how to
copy an existing servlet class and insert it into the web project.

Copying an existing Servlet

Begin by copying your Hello World servlet code, and putting it into a file called
CounterServlet.java. You may keep it in the same project (WAR file) as before, or put it in a
separate WAR file (if you would like more practice at the process of creating WAR files).

Make the following modifications to your Hello World servlet source code:

1. You can cut and paste the HelloWorldServlet from the src folder. Rename the class to
CounterServlet
2. Declare a class variable to hold the value of your counter.
3. private static int numRequests = 0;
4. Declare a synchronized method to update the value of the numRequests variable.

private synchronized void incNumRequests() {


numRequests++;
}

47
5. Modify the code inside your existing doGet() method to make it call the incNumRequests
method you have just created, and print out the current value of the counter.

incNumRequests();
out.println("Number of requests since reload: "
+ numRequests);

Servlets and threading

The question you should be asking yourself right now is: why do I need to create an extra
method just to increment the value of numRequests? Why can't I just have my servlet increment
the value directly?

The answer lies in the way servlets handle threading. By default, every servlet you create is
multi-threaded. That means that at any given instant in time, multiple instances of your
doGet() method could be executing simultaneously.

Also recall the meaning of a class variable (i.e. declared as static) in Java. A static variable is
one that is shared between all instances of a given class. So if you have 10 instances of your
CounterServlet executing, all 10 instances will be sharing a single copy of the numRequests
variable.

What happens if two different instances of your servlet running at the same time both try and
update the value of numRequests at the same time? In theory, this could lead to a semantic error
in the program because two threads are trying to update the same shared resource
simultaneously. [Although strictly speaking in this case there is not much danger because all
we are doing is incrementing a single value.]

The general principle that you should follow is that if you ever write a Java servlet where
multiple threads will be accessing a single, non-shareable resource, you must
programmatically ensure that at most one thread can be accessing the resource at any one
time. Java provides this facility through the use of its synchronized keyword.

If you have studied operating systems, note that this is similar in concept to monitors and
semaphores used to ensure at most one process is executing a critical section at any given
time.

Running your servlet

48
Follow the same steps you used when creating your Hello World servlet to edit and compile
the code.

You now need to do some additional work..

Declare this servlet in your web.xml deployment descriptor. The following steps shows you
how to do this via Eclipse/Workshop, but do note that it can be easier just to type the extra
entries into the web.xml file directly! (see step 5 for the raw XML code to add)

1. Step 1: Right click on the Deployment Descriptor item. This should show you either
the source or the design views. The main advantage of using the IDE is the guarantee
of a correctly formatted xml file so let's select the design (also called Deployment
Descriptor) tab.
2. Step 2: Right mouse click on the Servlets entry and select New Servlet

3. Step 3:
You now create the servlet. You enter the servlet name (Counter) and the name of the
servlet class (CounterServlet).
Note that you can also use a JSP instead of a servlet class if you wish but we will wait
till a later lab to try this out.

49
4. Step 4:
You now enter the servlet URL mapping. We will use /Counter to point to our servlet.

You can optionally add more mappings by using the Add button on the Servlet
Properties page.

One neat trick is to map sub-contexts (which act like virtual subdirectories on the
URL) and file names to a servlet directly.

For example, you could choose a mapping called /*.counter or index.html to map to
CounterServlet!

5. Step 5:
If you inspected the generated XML code in web.xml, you should have entries
looking somewhat like:

50
<servlet>
<servlet-name>Counter</servlet-name>
<servlet-class>CounterServlet</servlet-class>
</servlet>

and later in the file ...

<servlet-mapping>
<servlet-name>Counter</servlet-name>
<url-pattern>/Counter</url-pattern>
</servlet-mapping>

Note that the ORDER of these XML entities are important in web.xml. Misplacing
them may result in an error or your web application to fail to deploy.

6. Eclipse automatically re-deploys the updated lab so you can now unit-test the
application. Note that each time you reload the browser with the refresh button, the
displayed counter should update.

7. You should now redeploy your WAR file by using the Export .. as WAR file menu
and by copying the war file to your WebLogic autodeploy directory.
8. cp HelloWorldApp.war ~/weblogic/autodeploy
9. Test your new servlet, in your web browser, by viewing a URL like the following (the
filename on the end of the URL will depend upon the name you chose for the <url-
pattern>
10. http://localhost:7001/HelloWorldApp/Counter

Module: Servlets
Lab exercise - Form parameters

This laboratory exercise involves modifying your Counter servlet so that you may set the
value of the counter to an arbitrary value. The servlet takes its input from a HTML form,
where the user can enter a value, and the counter will be set to that value.

Level of Difficulty: 3 (requires some thought)


Estimated time: 20 minutes
Pre-requisites:

• Completed the Counter servlet lab exercise

51
A SettableCounter servlet

The goal of this exercise is to create a servlet that can both print out the value of a counter (as
with the CounterServlet exercise), but also allows a user to set the counter to an arbitrary
value.

Begin by creating a HTML form that you will use to view and set the value of the counter.
Remember this HTML file must go inside your WAR file.

<FORM METHOD="GET" ACTION="SettableCounter">


<P> Set counter to equal:
<INPUT TYPE="TEXT" NAME="newvalue" SIZE="5">
</P>
<P><INPUT TYPE="SUBMIT" VALUE="Set Counter"></P>
</FORM>

<P><A HREF="SettableCounter">
Get counter value</A></P>

As you can see, your servlet code will need to be able to read the value of a parameter taken
from a HTML form. Moreover, because the same servlet is being used for both viewing the
counter value and setting it, you will need to check if there is a form parameter value
supplied. If so, set the counter to the supplied value. If not, just display the counter.

Don't forget to set the Servlet mapping to /SettableCounter

Request and Response objects

Reading the value of form parameters in a servlet is quite easy. However before we get to
that, first, notice the definition of the doGet() that you have been using in earlier servlets:

protected void doGet (HttpServletRequest request,


HttpServletResponse response) ...

In this definition, there is a "request" object (called request, although you may choose another
name if you wish), and a "response" object (called response).

The request Java object encapsulates all the details about the HTTP request that was sent by
the user's web browser. This includes the URL of the request, the request method (e.g. GET
or POST), the IP address of the client's machine, etc. The request object has methods
available to retrieve these various pieces of information about the request. Another piece of
information associated with the request object is the names and values of any form
parameters that the user might have supplied. This is what we need for this exercise.

52
The response Java object encapsulates all the details of the HTTP response that will be sent
back to the user's web browser. This includes the MIME type (content type) of the document,
plus the actual document itself. Even in the Hello World servlet, we have seen two examples
of using the response object:

• response.setContentType("text/html");
• PrintWriter out = response.getWriter();

What happens when you change the content type to to be "text/html" instead?

You should also browse the JavaDoc documentation for servlets, and get a feel for the
methods available on the HttpServletRequest and HttpServletResposne objects. Both are found in
the package javax.servlet.http.

Reading form parameters

By now we have established that to read HTML form parameters, we need to use a method
on the request object. The method we need is called getParameter().

To read the value of a HTML form parameter named "newvalue", use the following line of
Java code:

String formvalue = request.getParameter("newvalue");

If there was no form field named "newvalue", then the getParameter() function will return null.
To see whether a particular form field was supplied or not, you can just compare the result of
getParameter() against null. [Hint: you need to do this as part of your SettableCounterServlet.]

Finally, note that when you read form parameters, they are always read as Java String objects.
Your SettableCounterServlet will probably need to use the value as a Java int, not a String.
Here's a reminder of how to convert a String to an int, although in general you should be able
to work things like this out for yourself (remember this is not an introductory Java course).
Do not expect tutors to answer questions like this for you!

int formvalueint = Integer.parseInt(formvalue);

(this may throw a NumberFormatException that you must handle).

You should now have all the information you need to create your SettableCounterServlet.
You just have to put it all together!!!!

53
Aside: printing all form parameters

For debugging, sometimes it is useful to have your servlet print out a list of all form field
names and their associated values. Here is a piece of code to do that. Try it out in one of your
own servlets if you wish, and use a HTML form with several parameters to invoke your
servlet.

java.util.Enumeration e = request.getHeaderNames();
while (e.hasMoreElements()) {
String hdrName = (String) e.nextElement();
String hdrValue = request.getHeader(hdrName);
out.println(hdrName + ": " + hdrValue);
}

54
Module: Servlets
Lab exercise - HTTP Sessions

This laboratory exercise involves modifying your Counter servlet to introduce a second
counter. The second counter should keep count of how many times the current user has
accessed the servlet, and this counter will be different for each user.

Level of Difficulty: 4 (moderately difficult)


Estimated time: 20 minutes
Pre-requisites:

• Completed the Counter servlet lab exercise

A SessionCounter servlet

The goal of this exercise is to create a servlet that, when invoked, will print out two different
counter values:

• the original CounterServlet value (total number of times the servlet has been invoked
since it was reloaded);
• a counter that keeps count of the number of times the current user has invoked the
servlet in his/her current session.

This requires the use of sessions and session variables in your servlet.

The state problem

As you know, HTTP is a stateless protocol. This means that a web server sees each incoming
request as being completely independent from all earlier requests.

However many web applications need to keep state information at the server, so the
statelessness of HTTP is a problem. For example, when you access an online banking
application, you first log in with your account number and PIN, and then as you click through
various pages on the bank's web site, the application running on the bank's web server needs
to keep track of who you are.

Another example is the ubiquitous shopping cart. As you browse through a product catalog,
and add items to your cart, the web application needs to keep track of which items are
currently in your cart.

55
In web application terminology, the word session refers to the interaction between a user and
a web application, where the web application keeps state information about the user's
interactions even though they span multiple HTTP requests. A session typically lasts for a
single browsing session. If a user closes their browser and re-opens it and goes back to the
web application, they will have to begin a new session. If a user doesn't access the web
application for a period of time, their session might time out (whether or not it does is
application-dependent).

There are different ways to implement sessions on top of the stateless HTTP protocol. The
two typical ways are using cookies and URL rewriting. These will be described in the lecture
notes.

Sessions and Java

Java servlets have built-in support for session management that simplifies the task of creating
a web application that requires a session-based interaction with a user.

The abstraction used in Java is the notion of session attributes that can be stored in a session
object. The session object acts like a container. You can store attributes (name/value pairs)
into the session object, and you can retrieve attributes out of the session object. Attributes
that are stored in the session object will still keep their value in between successive HTTP
requests. Each "attribute value" is, of course, a Java object.

Each attribute stored in the session has a name, and a value. The name is just a String. The
value is a Java object. The HttpSession class uses the methods setAttribute() and getAttribute for
storing and retrieving attributes in sessions respectively.

Where do you get the session object from in the first place? From the request object. You get
the session from the request. If there was already a session established, then you will have
access to all the variables stored in the session. However if there was not already a session
established, one will be created automatically (by default), and you will then have access to a
blank session object in which you can store variables.

Now for some code snippets:

1. Getting hold of a session object (from the request):


2. HttpSession sess = request.getSession();
3. Storing an object into the session:
4. Integer counterval = new Integer(105);
5. sess.setAttribute("sessioncounter", counterval);
6. Retrieving an object from the session:
7. Integer newcounterval = sess.getAttribute("sessioncounter");

56
SessionCounterServlet

With that knowledge, work on modifying your CounterServlet to add a second counter - one
that keeps track of the number of accesses a user has made in the current session.

To test, try accessing your servlet from two different browsers (e.g. Firefox and IE
on the same machine, or two different browsers on two different machines). Don't
just use two different windows belonging to the same browser (because different
browser windows still share cookie data, which is used to maintain sessions).

Aside: common usage pattern for sessions

Typically a servlet has to be able to deal with the situation when a session does not already
exist and has to be initialised. One way to do this is to retrieve an attribute from the session,
and if it is null (or if a flag is set to indicate that the session is new), then automatically
initialise the attribute and store it in the session. This means that your servlet can both deal
with existing session attributes and automatically set up a new session attribute when needed.

Here is a code sample:

HttpSession sess = request.getSession();


Integer sesscounter;
sesscounter = (Integer) sess.getAttribute("numaccesses");
if (sess.isNew() || sesscounter == null) {
sesscounter = new Integer(0);
sess.setAttribute("numaccesses", sesscounter);
}

URL Rewriting

The following servlet illustrates the use of URL rewriting when cookies aren't supported in
your browser. This servlet also illustrates the use of Servlet API to extract various
information related to a session.

// Retrieve the count value from the session


Integer ival = (Integer) session.getAttribute("numaccesses");

// If the counter is not currently contained in the session,


// one needs to be created:

57
if (ival==null) {
ival = new Integer(1);
}
else {
ival = new Integer(ival.intValue() + 1);
}

session.setAttribute("numaccesses", ival);

// Print out how many times the user has hit the current page:
out.println("You have hit this page <b>" + ival +
"</b> times.<p>");
out.println("Click <a href=" +
response.encodeURL("SessionServletApp") +
">here</a>");
out.println(" to ensure that session tracking is working even " +
"if cookies aren't supported.<br>");
out.println("<p>");

// Finally, demonstrate some of the more common methods in the


// HttpSession object surrounding sessions:
out.println("<h3>Request and Session Data:</h3>");
out.println("Session ID in Request: " +
req.getRequestedSessionId());
out.println("<br>Session ID in Request from Cookie: " +
req.isRequestedSessionIdFromCookie());
out.println("<br>Session ID in Request from URL: " +
req.isRequestedSessionIdFromURL());
out.println("<br>Valid Session ID: " +
req.isRequestedSessionIdValid());
out.println("<h3>Session Data:</h3>");
out.println("New Session: " + session.isNew());
out.println("<br>Session ID: " + session.getId());
out.println("<br>Creation Time: " +
new Date(session.getCreationTime()));
out.println("<br>Last Accessed Time: " +
new Date(session.getLastAccessedTime()));

Ensure your browser accepts cookies by checking Tools -> Options -> Privacy (Firefox) or
Tools -> Privacy -> Sites (Internet Explorer). If the browser is not allowed to accept cookies,
please enable it to accept cookies for this exercise to work. You may need to start the browser
again for any changes to take place.

When you access the servlet for the very first time, observe the information returned from the
server. Among many things, it should display the session as new. If you press 'Reload'
button, the new session should be displayed as false. Also, the request session id from
cookie and URL are true and false respectively. This is because you browser is set to accept
cookies.

Now, disable the cookies (see Tools -> Options -> Privacy/ Tools->Privacy-Sites). Restart
the browser to take effect of this new change. Don't forget to reset to the setting you had
before after the exercise.

Access your servlet as before and session should be correctly reported as new. Press Reload
button and what you should observe is that the session is still reported as new (same
behaviour for multiple reloads). Remember, earlier new session is only reported for the first

58
time you access the page and false for any subsequent accesses (within a session). Even
though you didn't use Cookies explicitly, Weblogic uses a temporary cookie to store the
current session. Since your browser is set not to accept any cookies (including temporary
cookies), sessions do not work correctly.

However, press on 'Click here' link to enable URL writing and watch the URL that appears in
the Address/Location bar. You should notice some extra text on the end of the URL
indicating that URL rewriting is now being used to maintain the session state when cookies
are disabled. What is also interesting to observe is that the display correctly reports the
requested session id is from a URL and not from a Cookie.

59
Module: Servlets
Tutorial - Accessing resources (e.g. relative files)

Note that this is not a lab exercise - it is just some information that you may find useful when
using servlets (or JSPs).

So you create a web application and package it up in a WAR file. But then from within your
servlet or JSP code, you want to open a file which is also stored inside the WAR file.

But you can't use the normal Java File class, because it expects a full absolute pathname!!!

The solution: use methods on the ServletContext.

• java.net.URL getResource("/path") - this will return the URL to use to access a


specific file in the war file
• java.util.Set getResourcePaths("/path") - this will return a directory like listing of
files that start with /path
• java.io.InputStream getResourceAsStream("/path") - this will return the contents of
the file named /path

(Follow the links above to go to the Sun JavaDoc documentation.)

Some sample code

Use your right-mouse button to save this to a local file.

• ResourceTest.war
A WAR file containing an example of using these methods.

60
Module: Servlets
Tutorial exercise - Creating a WAR file manually

This laboratory exercise involves developing a Hello World servlet, step by step. It is a long
process, but each step should be simple enough. Take careful note of what you are doing at
each step, and the commands you need to run. It gets easier once you've worked out the
process - your first servlet will be your hardest!

Level of Difficulty: 1 (easy)


Estimated time: 30 minutes
Pre-requisites:

• Run 'wlenv' to set your environment correctly


• Start your WebLogic server running in the background

Manually creating a servlet

This exercise will lead you step by step through writing and deploying your first Java servlet
without an Integrated Development Environment (IDE) such as Eclipse.

1. Create a directory to store your source code. This directory should be completely
outside the WebLogic server directory hierarchy, e.g.

cd
mkdir aip
mkdir aip/servlets
mkdir ajp/servlets/helloworld
cd aip/servlets/helloworld

Create a file called HelloWorldServlet.java with the following contents. If you are familiar
with Unix, try the 'vi' editor, e.g. vi HelloWorldServlet.java

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;

public class HelloWorldServlet extends HttpServlet {

public void doGet (HttpServletRequest req,


HttpServletResponse res)
throws ServletException, IOException {

res.setContentType("text/plain");
PrintWriter out = res.getWriter();
out.println("Hello servlet world!");
out.close();
}

61
}

Compile your source code using javac.

javac HelloWorldServlet.java

If you see an error message that it cannot import the servlet packages (javax.servlet
and javax.servlet.http), then your environment is not set correctly. Go back and re-run
setEnv.sh.

Congratulations, you have just written your first Java servlet. Before you can run it though,
you must first package it, and deploy it. These steps are described below.

Packaging your servlet 1: directory structure

Java servlets execute as part of a web server. You cannot run or test them from the command
line. The web server you will use to run your servlet is the web server built in to the
application server (WebLogic). To "run" your servlet, you will access a URL in your web
browser. This is quite similar to running a CGI program, or running a PHP script.

Before you can install your servlet into the application server, it needs to be packaged
properly. Servlets are part of what J2EE calls 'web applications', and web applications should
be packaged in a Web Application Archive file, or WAR file.

A WAR file is basically a compressed zip file that contains all parts of your web application.
The parts may include:

• static web site files (HTML, GIF, JPEG, CSS, etc)


• Java servlets
• a deployment descriptor (described later)

Importantly, when you package your application as a WAR file, it must follow a particular
directory structure. Starting at the same directory where your HelloWorldServlet.java file is, run
the following commands. Note that the directory names are case-sensitive, so be careful to
type them correctly.

mkdir WEB-INF
mkdir WEB-INF/classes

Your compiled Java servlet class files must be placed in the WEB-INF/classes directory. When
you compiled your HelloWorldServlet earlier, you just put the .class file in the same directory
as the .java file. You'll need to fix that now.

rm *.class
javac -d WEB-INF/classes HelloWorldServlet.java

62
Note the use of the '-d' option to javac, which allows you to specify the output directory
(where the .class files go).

Packaging your servlet 2: deployment descriptor

As mentioned above, a WAR file contains static HTML (etc) files, Java servlet classes, and a
deployment descriptor. The next step is for you to create a deployment descriptor.

A deployment descriptor is an XML file describing the properties of your 'web application'.
When your web application includes servlets, the deployment descriptor file describes the
name of each servlet, and what URL should be used to invoke the servlet.

In the case of web applications, the deployment descriptor is contained in a file called
web.xml, and it must be placed in the WEB-INF directory.

Edit the web.xml file now, e.g.

vi WEB-INF/web.xml

(or use the text editor of your choice). Into the web.xml file, copy the following text:

<?xml version="1.0" ?><web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"


xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"><web-app>

<servlet>
<servlet-name>HWServlet</servlet-name>
<servlet-class>HelloWorldServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>HWServlet</servlet-name>
<url-pattern>/HW</url-pattern>
</servlet-mapping>

</web-app>

Points to note about the definitions in web.xml:

• servlet-name can be any name you choose. It does not have to be the same as the
filename in which the servlet class is stored. Every servlet referenced in your web.xml
must have a unique servlet-name within that one web.xml file.
• servlet-class specifies the name of the Java class file containing the compiled servlet
code.
• url-pattern specifies the URL by which you want users to be able to execute your
servlet. In the example shown above, the url-pattern is "/HW", so the URL that will be
used to invoke the servlet will look like http://hostname:7001/HelloWorldApp/HW

63
Packaging your servlet 3: static HTML files

Your WAR file can also include static HTML files, as well as images (GIF, JPEG), style
sheets (CSS), and any other static files you would expect to find on a web server.

In the WAR file, these files must be placed outside the WEB-INF directory. Any files not in
the WEB-INF directory can be accessed through the web browser. Any files that are inside the
WEB-INF directory (including your web.xml deployment descriptor, and your servlet class files)
will be protected, and not accessible to users over the web.

Let's create a static HTML file called index.html to go inside your WAR file. It can go in the
top-level directory of your web application (i.e. the directory that has the WEB-INF
subdirectory in it).

Use a text editor to create index.html with the following contents:

<HTML>
<BODY>
<H1>My first WAR file</H1>
<P>
Run my <A HREF="HW">Hello World servlet</A>.
</P>
</BODY>
</HTML>

Packaging your servlet 4: final check

When creating WAR files, it is very important that everything is in the correct directory. So
before we actually create the WAR file, take a moment to check when you view your
directory hierarchy, it looks something like the following:

$ ls -1F
HelloWorldServlet.java
WEB-INF/
index.html

$ ls -1F WEB-INF
classes/
web.xml

$ ls -1F WEB-INF/classes
HelloWorldServlet.class

i.e. the directory tree structure should look like:

64
- index.html
- HelloWorldServlet.java
/ WEB-INF
- web.xml
/ classes
- HelloWorldServlet.class

Note that it is not essential to have your Java source code file as part of the WAR file, but it is
convenient to keep all the files together.

Packaging your servlet 5: create the WAR file

Finally, you are ready to create your WAR file. Run the following command, which will
create a file called HelloWorldApp.war in the parent directory of where you execute it from.

jar cf ../HelloWorldApp.war *

In the above command, the "c" means "c"reate a WAR file.

Now view the contents of your WAR file to ensure that the file was created correctly. Run the
following command to list the WAR file contents:

jar tf ../HelloWorldApp.war

In the above command, the "t" means to show the "t"able-of-contents of the WAR file.

The output from the previous command should show something like:

META-INF/
META-INF/MANIFEST.MF
HelloWorldServlet.java
WEB-INF/
WEB-INF/classes/
WEB-INF/classes/HelloWorldServlet.class
WEB-INF/web.xml
index.html

The META-INF directory and the MANIFEST.MF file are automatically added by the jar utility.
You can ignore them.

Deploying your web application

Now that you have a WAR file, you can "deploy" it to the web server. Deployment is the
process of installing an application.

65
In WebLogic, there are a variety of ways you can deploy an application. The simplest is just
to copy your WAR file into your WebLogic server's "autodeploy" directory.

cp ../HelloWorldApp.war ~/weblogic/autodeploy

You can do this when the server is running. The server checks the contents of the autodeploy
directory every few seconds, and when it sees a new WAR file, or one with an updated
timestamp, it automatically deploys (or redeploys) it.

Testing your web application

If you have followed the steps above exactly, try accessing your application through the
following URL:

http://localhost:7001/HelloWorldApp/

It should show you the contents of your index.html file. If you click on the link to your servlet,
it should execute your servlet and display the servlet's "Hello World" message.

Note that when you deployed your WAR file into WebLogic, it created a virtual directory
under the root of your web server with the same name as your WAR file. So the name you
choose for your WAR files is important, because the WAR filename will become part of the
URL.

Reflection

Take note of what was required to write a single servlet, package it in a WAR file, and deploy
it to the web server. Note the commands, and the directory structure used.

When you go to create your second servlet, you might find it easier to set up the directory
structure first before beginning to write any Java source code. You will also probably find it
convenient to copy your web.xml file and simply edit the values inside.

You might even like to create yourself a Makefile, or a shell script which automates the
process of compiling, packaging and deploying your WAR file.

66
Module: JSP
Lab exercise - Hello World JSP

JavaServer Pages is quite similar in purpose to servlet code. However the big difference is
that JSP code is embedded inside a HTML web page rather than executed as a separate
program. So this exercise involves creating a HTML web page with some embedded Java
code.

Level of Difficulty: 1 (easy)


Estimated time: 15 minutes
Pre-requisites:

• Completed the 'Servlets' labs


• Be comfortable with running static HTML and servlets under Eclipse

A HelloWorld JSP

There are many approaches to developing servlets and JSPs. You can create/edit SP's using vi
(or notepad) and develop/package a WAR file by hand or use a code generator like XDoclet
to automatically build your WAR file structure.

We will cover the middle ground and will use an IDE like Eclipse/Workshop which has
'wizards' and templates to assist us to generate JSP's and WAR files. This fairly trivial
introduction lab will get you started...

1. Ensure that Weblogic server is not running since we will start this from within
Workshop for Weblogic.
2. Startup Workshop for Weblogic as usual and open our labs project from the Servlet
lab.
3. Use Right Mouse Button -> New -> JSP to create a file called HelloWorld.jsp. Note that
the "Create new Java Server Page" Wizard automatically highlights the webcontent
directory. This is the root of your web application.
Choose the New JSP file (html) template which should open an editor window with a
skeletal JSP (much like the static html exercise).
Edit the file to match the following contents:

(changes are in italics)


<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "
http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">

67
<title>My First JSP page</title>
</head>
<body>
<h1>My first JSP page</h1>
<p>
<% out.println("Hello JSP World"); %>
</p>
</body>
</html>

Note the following points:

o The Java code is embedded between the tags <% and %>
This is called a JSP scriptlet.
o There is an implicit object called out available in every JSP page that you can
use without pre-declaring. Think of it as a "built-in" object. This object is
basically of type java.io.PrintWriter. Servlets that you created also used a
PrintWriter, but in a servlet, you had to explicitly create the PrintWriter object,
e.g.
o PrintWriter out = request.getWriter();
o out.println("Hello Servlet World");

In a JSP page, you can use the out object without needing to create an instance
of it, as an instance is implicitly always available in every JSP page.

You do not need to compile your JSP page.


o
4. Run your new JSP by doing the usual Right Mouse Button, Run As -> Run On server.

Once your server is running, you can also view the JSP in a web browser, by viewing
a URL like the following.
Note that the first part of the URL path is the context root name (in our case, labs), but
this can also be the WAR filename if you exported the project as a WAR file and
copied it to the autodeploy directory.
5. http://localhost:7001/labs/HelloWorld.jsp

When the web server loads your JSP file, there will be a delay of up to a few seconds.
What is actually happening is that the JSP file you created is being compiled
automatically into a servlet (yes, a servlet!). The web server will then execute the
servlet it has generated from your JSP, and keep a cached copy of the generated class
file so that it doesn't need to recompile the JSP on subsequent requests.

So although there is a delay, it only happens once (or rather, only once each time you
modify the JSP file).

6. If you do any subsequent changes in Eclipse, the changes should be visible


immediately in the browser. HOWEVER, if you had exported and deployed a WAR
file, you will need to rebuild/export and redeploy the WAR file to reflect the changes.

Creating a subfolder (subdirectory)

68
1. Create a subdirectory (subfolder or subcontext in web terminology) by selecting
webcontent then pressing Right Mouse Button -> New -> Folder

Let's call this images

2. Now you can create more JSP or HTML files into this directory, but for this example,
we will demonstrate how to import files from the filesystem.
Select the images folder and click Right Mouse Button -> Import

Expand General, then choose -> File System

You can then type in a file name or use the Browse button to find one. Let's browse to
/pub/aip/images and select yellowstar.gif

You can now see this file in your WebContent/images directory and can refer to this
in your JSP

3. Modify your JSP to reference this image ie: add the line

<img src="images/yellowstar.gif">

(note that we do not put a / in front of images. This is because the file must be relative
to the context ie: labs)

Make sure you create the subfolder under the webcontent folder. If you have
the wrong directory (eg: Java Resources), bad things will happen:

1. The file will not be accessible from the web pages


2. The file may not be exported into the WAR file. So be careful.
3. Also note that the folder and filenames are Case sensitive!

4. Try it out. If running under Eclipse, you normally don't need to redeploy or even do
Run As -> Run on Server.
Just open the browse (or refresh the current page) to see the changes appear
dynamically!
5. Finally, add a link in your index.html page to this JSP (if you don't have an index.html
file, create it, this is normally the default home page of your web application!

69
Module: JSP
Lab exercise - JSP and form parameters

Just as servlets can access parameters from HTML forms, so can JSPs. This lab demonstrates
how, and also introduces JSP declarations and expressions.

Level of Difficulty: 2 (moderately easy)


Estimated time: 20 minutes
Pre-requisites:

• Completed the Hello World JSP lab exercise

More implicit objects in JSP

In the Hello World JSP exercise, you saw the use of one of the JSP implicit objects called out.
Now it's time to introduce two more implicit objects:

request
Encapsulates all information about the request that was sent by the web browser. It is
of type javax.servlet.http.HttpServletRequest
response
Encapsulates all information about the response that will be sent back to the web
browser. It is of type javax.servlet.http.HttpServletResponse

These should seem familiar. In a servlet, when you implemented a doGet() or doPost() or
service() method, the method implementation took two parameters - one of type
HttpServletRequest and the other of type HttpServletResponse.

In JSP, you do not have to declare the request and response objects before use - they are
implicitly available.

Reading form parameters in JSP

Now that you know about the existence of the request implicit object, reading form
parameters should be easy - the Java code has exactly the same syntax as you used for
servlets, e.g.

<%!
String formvalue;
%>
<%
formvalue = request.getParameter("newvalue");
%>

70
JSP declarations, scriptlets and expressions

Look again at the code from above:

<%!
String formvalue;
%>
<%
formvalue = request.getParameter("newvalue");
%>

Notice that this time the tag used to indicate the start of the first block of Java code was <%!
This sequence indicates that the enclosed block of Java code forms a JSP declaration, not a
scriptlet.

A JSP scriptlet (as used in the Hello World JSP example) can contain any arbitrary Java code.
However a JSP declaration can only contain declarations. Inside a declaration block, you can
declare variables, and you can declare functions. Code within a declaration block must never
generate any output.

It's time to introduce yet another kind of JSP code block - a JSP expression. Assume that you
wanted to print out (into the web page) the value that the user had entered into the
"newvalue" field, as shown above. In the above code, we created a Java variable called
"formvalue" which holds the data we need.

A JSP expression is used purely for displaying the value of a variable (or any Java
expression). It only generates output. It should not be used to do any other kind of processing.

So to print out the value of the "formvalue" variable, you can use the following JSP syntax:

<%= formvalue %>

This will embed into the output of the JSP page the contents of the "formvalue" variable.
Notice that for a JSP expression, the starting tag is <%=

Putting the example of the JSP declaration and JSP expression together, you might have a
JSP file with the following code in it:

<%! String formvalue; %>


<% formvalue = request.getParameter("newvalue"); %>
... other HTML code ...
The value entered was: <%= formvalue %>

Start
JSP block Can contain
tag

declaration <%! Variable and method declarations, nothing else. In particular, the code

71
must not generate any output

A Java expression that evaluates to a single value, which will be


expression <%=
printed out into the surrounding web page

Arbitrary Java code. This is the most general of the three, as you can
scriptlet <%
basically put any Java code you wish inside the tags

The exercise - changing background colours

Modify your HelloWorld JSP to process input from a HTML form. This form will allow
users to select a background colour from a drop-down list. When the JSP loads, it sets the
HTML background colour to the user's choice.

You should create a JSP file called ColourChooser.jsp with a form that looks like:

<%! ??? %>


<body bgcolor="...">
<form action="ColourChooser.jsp" method="post">
<select name="mycol" size="4">
<option selected="selected" value="red">red</option>
<option value="blue">blue</option>
<option value="green">green</option>
<option value="yellow">yellow</option>
</select>
<p><input type="submit" name="submit" value="Change Colour"/>
</p>
</form>
</body>

Note that the action of the form points to ColourChooser.jsp, i.e. it points to itself. The form has
a single input field, named "mycol".

At two points in the above listing, there is a ???? and a ... Your task is to fill in the two blanks
and solve the problem.

In your first solution, you should use both JSP declarations and expressions, rather than
trying to do everything in a scriptlet.

[Aside: If you want to be clever, after getting a basic solution working, think about changing
your code to check whether the value of the form parameter was null, and if so, using some
appropriate default colour. This will require a scriptlet, because you cannot put a Java "if"
statement inside either a declaration or an expression.]

Test your JSP by simply typing in the url eg: http://localhost:7001/labs/ColorChooser.jsp

Don't forget to add a link to this JSP to your index.html file.

72
Module: JSP
Lab exercise - JSP and sessions

JSPs can also access information from sessions. JSPs and servlets can use session information
interchangeably - they have the same interface to it. This lab illustrates how to access session
information in a JSP, and as an aside, shows how to import Java class libraries for use in a
JSP.

Level of Difficulty: 3 (requires some thought)


Estimated time: 30 minutes
Pre-requisites:

• Completed the JSP and form parameters lab exercise

Accessing sessions in JSP

You have seen already how to access sessions in a servlet. Accessing sessions in a JSP is
almost identical - actually it's even simpler because you don't have to create your own
instance of a HttpSession object - one is implicitly available.

Let's review the JSP implicit objects you already know about, and introduce a new one, called
session.

Implicit
Java Type Purpose
object

Use the print() or println() methods for


javax.servlet.jsp.JspWriter
out
(like a PrintWriter) generating output that will be sent back to
the browser

Used to access information about the HTTP


request javax.servlet.http.HttpServletRequest
request (from the browser)

Used to set information that becomes part of


response javax.servlet.http.HttpServletResponse
the HTTP response (sent to the browser)

Used to get and set attributes associated with


session javax.servlet.http.HttpSession
the current session

Using the implicit session object is quite similar as its use in servlets, e.g.

• Storing an object into the session:


• Integer counterval = new Integer(105);
• session.setAttribute("sessioncounter", counterval);

73
• Retrieving an object from the session:
• Integer newcounterval = session.getAttribute("sessioncounter");

Using Java class libraries in JSP

Sometimes you want to access classes in one of the standard Java class libraries, or perhaps
you want to import a class library you wrote yourself. In a Java servlet, you would normally
put an "import" statement near the top of your Java source file, but what about JSP?

JSP has a special syntax for importing, using what's called a JSP directive.

<%@
page language="java"
import="java.util.*"
%>

Note the new syntax again - this time the start tag is <%@ which indicates that this is a JSP
directive. JSP directives are like instructions to the compiler. In this case, we are telling the
compiler that the language embedded in this page is Java, and that we would like to import
the java.util.* library.

You can add more than one import by seperating each package with a , eg:
import="java.util.*,java.io.*"

Now you have seen four ways of embedding JSP information into a web page: declarations,
expressions, scriptlets and directives. Each has a different starting tag.

The exercise - storing a history of background colours

Modify your ColourChooser.jsp file to store a history of all background colours the user has
chosen in the current session. Make it so that the list of colours previously chosen is
displayed at the bottom of the web page, underneath the form.

Hints:

• The basic idea is to use a java.util.Vector object to store the list of colours. Recall that a
Vector is stores a set of values, and acts like a potentially infinite list of items.
Forgotten how to use a Vector? Go read the API documentation at
http://java.sun.com/j2se/1.4/docs/api/ and the Java platform tutorial

You can, if you wish, use another data structure that comes with the Java 2
Collections framework, like a java.util.LinkedList or java.util.ArrayList, but make sure you
use a synchronized version. The API docs tell you how. A Vector is good enough for
what we are doing however.

74
• Each time the user selects a colour (i.e. each time the page is reloaded), retrieve your
Vector from the session and add a new item onto the end of it.
• Note that you will need to use a JSP directive to import the java.util.Vector class before
you can use it.
• The following code snippet may help.
• <%! Vector colourhistory; %>
• <%
• colourhistory = (Vector) session.getAttribute("colhist");
• if (session.isNew() || colourhistory == null) {
• colourhistory = new Vector();
• session.setAttribute("colhist", colourhistory);
• }
• %>

Java 5 adds Generics to the Java Language. If you wish, you can convert your code to
be made type safe by declaring colourhistory as Vector<String> (along with
modifying the rest of the code to suit generics. Note that you may get a warning on
the cast to (Vector) which can be safely ignored.

• Hint: You can print out the Vector directly using the <%= colourhistory %> JSP
expression instead of using an Enumeration to loop through this.

75
Module: JSP
Lab exercise - JSP and sessions

JSPs can also access information from sessions. JSPs and servlets can use session information
interchangeably - they have the same interface to it. This lab illustrates how to access session
information in a JSP, and as an aside, shows how to import Java class libraries for use in a
JSP.

Level of Difficulty: 3 (requires some thought)


Estimated time: 30 minutes
Pre-requisites:

• Completed the JSP and form parameters lab exercise

Accessing sessions in JSP

You have seen already how to access sessions in a servlet. Accessing sessions in a JSP is
almost identical - actually it's even simpler because you don't have to create your own
instance of a HttpSession object - one is implicitly available.

Let's review the JSP implicit objects you already know about, and introduce a new one, called
session.

Implicit
Java Type Purpose
object

Use the print() or println() methods for


javax.servlet.jsp.JspWriter
out
(like a PrintWriter) generating output that will be sent back to
the browser

Used to access information about the HTTP


request javax.servlet.http.HttpServletRequest
request (from the browser)

Used to set information that becomes part of


response javax.servlet.http.HttpServletResponse
the HTTP response (sent to the browser)

Used to get and set attributes associated with


session javax.servlet.http.HttpSession
the current session

Using the implicit session object is quite similar as its use in servlets, e.g.

• Storing an object into the session:


• Integer counterval = new Integer(105);
• session.setAttribute("sessioncounter", counterval);
• Retrieving an object from the session:
• Integer newcounterval = session.getAttribute("sessioncounter");

76
Using Java class libraries in JSP

Sometimes you want to access classes in one of the standard Java class libraries, or perhaps
you want to import a class library you wrote yourself. In a Java servlet, you would normally
put an "import" statement near the top of your Java source file, but what about JSP?

JSP has a special syntax for importing, using what's called a JSP directive.

<%@
page language="java"
import="java.util.*"
%>

Note the new syntax again - this time the start tag is <%@ which indicates that this is a JSP
directive. JSP directives are like instructions to the compiler. In this case, we are telling the
compiler that the language embedded in this page is Java, and that we would like to import
the java.util.* library.

You can add more than one import by seperating each package with a , eg:
import="java.util.*,java.io.*"

Now you have seen four ways of embedding JSP information into a web page: declarations,
expressions, scriptlets and directives. Each has a different starting tag.

The exercise - storing a history of background colours

Modify your ColourChooser.jsp file to store a history of all background colours the user has
chosen in the current session. Make it so that the list of colours previously chosen is
displayed at the bottom of the web page, underneath the form.

Hints:

• The basic idea is to use a java.util.Vector object to store the list of colours. Recall that a
Vector is stores a set of values, and acts like a potentially infinite list of items.
Forgotten how to use a Vector? Go read the API documentation at
http://java.sun.com/j2se/1.4/docs/api/ and the Java platform tutorial

You can, if you wish, use another data structure that comes with the Java 2
Collections framework, like a java.util.LinkedList or java.util.ArrayList, but make sure you
use a synchronized version. The API docs tell you how. A Vector is good enough for
what we are doing however.

• Each time the user selects a colour (i.e. each time the page is reloaded), retrieve your
Vector from the session and add a new item onto the end of it.
• Note that you will need to use a JSP directive to import the java.util.Vector class before
you can use it.

77
• The following code snippet may help.

<%! Vector colourhistory; %>


<%
colourhistory = (Vector) session.getAttribute("colhist");
if (session.isNew() || colourhistory == null) {
colourhistory = new Vector();
session.setAttribute("colhist", colourhistory);
}
%>

Java 5 adds Generics to the Java Language. If you wish, you can convert your code to
be made type safe by declaring colourhistory as Vector<String> (along with
modifying the rest of the code to suit generics. Note that you may get a warning on
the cast to (Vector) which can be safely ignored.

• Hint: You can print out the Vector directly using the <%= colourhistory %> JSP
expression instead of using an Enumeration to loop through this.

Module: JSP
Lab exercise - Web authentication

78
In web applications, you will often need to restrict access to parts of your web site. The J2EE
specification has 2 basic types of authentication - Declarative and Programmatic.

This lab will examine how to use the Declarative method. In later labs, you will have the
opportunity to use a Programmatic method.

In this lab, you will be creating users, a security role and restricting access to the HelloWorld
JSP to that user.

Level of Difficulty: 2 (moderately easy)


Estimated time: 30 minutes
Pre-requisites:

• Completed the JSP Parameters lab exercise


• Running the Weblogic server - either through the Eclipse/Workshop IDE or from the
command line

HTTP Basic Authentication

HTTP Basic authentication is the oldest and one of the most commonly used forms of
authentication on the web. From a user's perspective, he/she attempts to visit a web page, but
before the page is displayed, has to enter a username and password into a popup dialog box of
the web browser. After entering correct credentials, the requested page is displayed.

Traditionally, basic authentication of web servers is set up as part of the web server
configuration. However with web applications, the authentication can be specified on a per-
application basis, by describing the authentication requirements in the application's
deployment descriptor (web.xml file).

Three elements are required in the web.xml file: <login-config>, <security-role> and <security-
constraint>. login-config specifies some global parameters for the application, security-role
declares the names of users (roles) used by the application, while security-constraint specifies
which file(s) should be protected and which users have access.

Finally, the actual creation of the user (username and password) is done within the web
application server (e.g. WebLogic) using its management console.

Setting up security roles in WebLogic

In J2EE applications, the descriptor file for the web application (web.xml) will contain the
security declarations for the types of groups of users who can access the application.

In this lab, we will create a group called "hellousers". A group is merely a set of users, and
maps directly to a role.

1. Open the WebLogic Server Console


2. Click on Lock & Edit in the top left menu.
3. In the left side menu, click Security Realms
4. Choose myrealm
5. Select the Users and Groups tab

79
6. Select the Groups pane (this is just below the Users and Group line)
7. Create a new group by selecting New

Enter the name hellousers and a short description. Leave the provider as
DefaultAuthenticator

8. hellousers should now be in the list of groups.

Creating users in WebLogic

1. At the top of the page, click the Users pane


2. Click New and enter a name such as student, and enter a suitable description and password.
(you must enter the password twice!)

Note that Weblogic enforces a minimum password size. Later on (not NOW!) you can
change this in the Securiy Realms -> myrealm -> Providers -> DefaultAuthenticator -
> Configuration | Provider Specific -> Minimum Password Length panel.

3. Now select the new user you created.


4. You should then select the Groups tab

You should see several groups here, including hellousers in the Available window.

Select hellousers and press the right-arrow button to move this into the Current Groups
window.

Click Save to update this.

5. If you wish, you can add many other users, just ensure that they are also members of the
hellousers group if you want them to access the Hello JSP
6.
7. Finish off with Release Configuration in the top left menu

Configuring the hello JSP web application for security

You will need to modify the Deployment Descriptor (ie: web.xml file) to enable security.

You can either update the web.xml file directly in the source editor (note that using Ctrl-
space will show you the allowed elements in the current cursor position), or you can use the
design tab to let the XML editor assist you. You right mouse button click and add a child
element.

Add the following tags into the web.xml file after the </welcome-file-list> tag.

<security-constraint>
<web-resource-collection>
<web-resource-name>Hello world</web-resource-name>
<description>The Hello world application</description>
<url-pattern>/*</url-pattern>
</web-resource-collection>

<auth-constraint>

80
<description>These users can use hello JSP</description>
<role-name>hellousers</role-name>
</auth-constraint>
</security-constraint>

<login-config>
<auth-method>BASIC</auth-method>
<realm-name>Hello World Application</realm-name>
</login-config>

<security-role>
<description>Hello JSP users</description>
<role-name>hellousers</role-name>
</security-role>

What do the parameters mean?

<login-config>

login-config specifies the authentication mechanism and the realm for authentication.

We have used code>BASIC for basic HTTP authentication. The realm refers to the scope of
the username and password that are supplied - typically each application will have a different
realm so that the credentials supplied for one application are not valid for another. The realm
name can be any string of text you choose.

You can only specify login-config once within your web.xml file (i.e. each web application can
have at most one login method).

<security-role>

declares the name of a role referenced by this application. It has a purely


security-role
declarative role.

You can have as many security-role elements as you need - one for each different role your
application requires.

<security-constraint>

specifies a set of pages to protect within the web application, and which users
security-constraint
should be permitted access.

In web-resource-collection you define a url-pattern of the pages you wish to protect. By specifying
/*,we have declared that all pages in the Hello World application are protected. /P>

In auth-constraint you define a list of users (or more correctly, roles) who are permitted access.
The <role-name> element may occur multiple times if you want multiple roles to have access.
Each role name should be declared elsewhere in the same web.xml file in a <security-role>
element.

81
The security-constraint element basically limits access to the specified url-pattern so that only
the listed roles (users) have access.

You may have many CODE>security-constraint elements in your web.xml file if you have
different parts of your application that need to be accessed by different sets of users.

Map the roles to groups

Weblogic now requires you to map these 'roles' to groups. Previous versions (such as
Weblogic 8.1) automatically did this.

For EACH project, update the Weblogic Deployment Descriptor weblogic.xml to do this
mapping.

Modify the Weblogic Deployment Descriptor (weblogic.xml) by adding the following


elements:

<wls:security-role-assignment>
<wls:role-name>hellousers</wls:role-name>
<wls:principal-name>hellousers</wls:principal-name>
</wls:security-role-assignment>

The <role-name> is the name of the role to be used by your web application

The <principal-name> is the name of the group to which this role will apply to. Note that
you can map users to this principal as well. Repeat the whole security-role-assignment block
for each role and principal assignment. You can map more than one principal to the same role
name.

Note: You can ask weblogic to do this automatically via the weblogic Administration
Console. ie:

• Lock&Edit, select Security Realms


• On myrealm -> Configuration -> General page -> deselect "Combined Role Mapping
Enabled"
• Expand Advanced ->
• Check Roles and Policies = "All web applications and EJBs",
When Deploying Web Applications or EJBs = "Initialize roles and policies from DD"
• Release Configuration to save
• You may need to Stop and Restart weblogic to enable this configuration setting.
Hint: Use the Servers tab at the bottom of the Eclipse screen & select the server & press the
red square to stop. Press the Green arrow to start.

Now Weblogic will automatically create the equivalent of the above weblogic.xml
descriptor... and you won't need to modify the weblogic.xml descriptor again..

Accessing authentication credentials in servlets/JSP

From within a servlet or JSP, you can determine the username that was used to authenticate
by calling the getRemoteUser() method on the HTTPServletRequest object.

82
In your HelloWorld.jsp file, add the following lines to see who is the current user

<p>The following user is logged in:


<%
String user = request.getRemoteUser();
if (user == null) {
user = "-none-";
}
out.println(user);
%>

If the web application wasn't protected, then the getRemoteUser() method will return null.

You can also check to see if the user is in a particular role via the isUserInRole()

<%
if (request.isUserInRole("hellousers")) {
out.println("Is a member of hellousers");
} else {
out.println("Is not a member of hellousers");
}
%>

Don't forget to repackage your .WAR f file and copy it into the applications directory for
redeployment.

Further reading

WebLogic specific security information can be found at http://e-


docs.bea.com/wls/docs100/security/thin_client.html#wp1037337

Module: JSP
Lab exercise - Using a JavaBean

83
So far, all the JSP code you have written has been embedded into the web page itself. If there
is a large amount of code, the page can get quite messy, as you might imagine. Also,
sometimes you need to reuse the same functionality in different pages.

JSP pages can make use of your own Java class files, as helper classes, if you wish. However
the preferred option is for JSP pages to use JavaBeans to encapsulate reusable functionality.
A JavaBean is just a "special" Java class. Note that a JavaBean is NOT the same thing as an
Enterprise JavaBean. This lab exercise takes you through the process of creating and
deploying your own JavaBean, and using it in a JSP page.

Level of Difficulty: 4 (moderately difficult)


Estimated time: 45 minutes
Pre-requisites:

• Completed the JSP and sessions lab exercise

Why use JavaBeans?

JavaBeans are Java's "client-side" component model. Typical uses of JavaBeans are in
creating components for use in GUIs (for example the Swing libraries use JavaBeans as their
underlying model). Remember that a component is just a collection of Java classes that
presents a single public interface to other objects.

While EJBs need to execute in the context of an application server, client-side JavaBeans can
be instantiated and used by any Java application or applet (or servlet, or JSP). Even though
JSPs are not generally thought of as a client-side technology, JavaBeans have been adopted
as the component model for use in JSPs. As we will see later, JSPs are a form of client in
J2EE applications - JSPs are clients of EJBs.

JavaBeans are used in JSPs to avoid having large amounts of code embedded in the web page
itself. This increases the potential for code reuse, and provides a good separation of design
tasks (performed by a web designer) and programming tasks (performed by a programmer).

What are JavaBeans?

A JavaBean is simply a normal Java class that follows certain design patterns. In this context,
a design pattern is a basically a naming convention that you must follow when creating a
JavaBean.

Here we will only consider one basic design pattern used in JavaBeans - using getter and
setter methods for properties. For more information on more complex design patterns used in
JavaBeans, see a JavaBeans tutorial, such as the one from Sun -
http://java.sun.com/products/javabeans/docs/javaBeansTutorial-Nov97/javabeans/

84
Since JavaBeans represent data of some kind it needs to be serializable ie: able to be
converted to some portable, transferable format. Therefore, JavaBeans have to implement the
serializable interface.

Creating your JavaBean

For this exercise, assume we are going to use a JavaBean to represent a person. The
attributes/properties of this person consist of only a name and a favourite colour.

1. The first step is to create a new Java project. Select New -> Project.. -> Java Project.
Call this project mybeans
2. The next step is to create a package. You should be familar with packages, but briefly
speaking this is simply a way to organise your Java classes (technically packages also
influence the scope of variables and method visibility on all classes in a package).
A more pragmatic view of a package is that it simply appears like a subdirectory!
Recall that there are many packages in Java by default such as java java.util & so on.

So let's create a simple package called myapp. This is basically a subdirectory called
myapp !!

Select mybeans, and Right Mouse Button -> New -> Package & enter myapp as the
package name. Note that the source folder is actually mybeans.
After Finishing our wizard, note that there is a new "myapp" folder.

3. Next, we will create a Java class skeleton to hold our JavaBean. If we Right Mouse
Button -> New -> Class, we will be prompted by a wizard to create a new Java Class

Enter myapp for the package name.(or alternatively, click the Browse button and
select MyApp - note that there is a (default package) folder which represents "no
package" or the top of your Java hierarchy.

Enter a Person as the name of the class and click the Add button in the Interfaces
section

You should get a Interfaces selection window. Start typing Serializable (and note the
typeahead assist to return Serializable (java.io)) then press OK

4. Now we are going to use the ability of the Eclipse IDE to generate code for us.
Modify the generated Java class file as follows (basically we just added the
declarations in italics.

package myapp;

import java.io.Serializable;

85
public class Person implements Serializable {
private String name;
private String favecolour;
}
Note that you may get a yellow warning light bulb icon which if you hover your cursor
over it mentions that the class does not declare a static final serialVersionUID field.
Don't worry about this, we will let Java use the default (which is system generated).

Now let's get Eclipse to generate the getters and setters.

Click on the top menu and choose Source -> Generate getters and setters.
(You could also select the two declaration lines above then press Right Mouse Button
-> Source -> Generate Getters and setters)

You will get a Generate Getters and Setters wizard appearing. You can select the
individual variable to generate code for using the check boxes and if you expand the
field names you can see the default methods declarations.
Note the other options - Insertion Point and Sort by. These just help you keep your
source code nice and tidy. You can also generate a default Method Comment which
generates JavaDoc style comments for you.
Select All, then OK to finish

Note the careful choice of method names. The methods are in pairs - one getter and
one setter method. They are also case-sensitive - the word "get" and "set" must be in
lower case, and the next character (the start of the property name) must be in upper
case. So for example the methods getName() and setName() together implement a
JavaBean property called "name" (in this case, the property name is all lower case -
the first uppercase 'N' is converted to lower case when you go to use it as a property).
Your code now looks somewhat like this

package myapp;

import java.io.Serializable;

public class Person implements Serializable {


private String name;
private String favecolour;
public String getFavecolour() {
return favecolour;
}
public void setFavecolour(String favecolour) {
this.favecolour = favecolour;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

86
While you are getting used to the Source code generation facilities of Eclipse, why
not experiment here and try things like Source -> Generate Element Comment, Source
-> Format, Source -> Correct Indentation etc?

Congratulations, you now have a JavaBean class

Packaging your JavaBean


A manifest file specifies that this class is in fact a JavaBean. Note that reading the source
code of the class, there is nothing special about it that reveals that it is in fact a JavaBean.
See http://java.sun.com/docs/books/tutorial/deployment/jar/manifestindex.html for
information about the manifest file

We will need to create our own manifest file in order to let Java (and other tools) know that
this module is a Java Bean module.

• Select mybeans, right mouse button -> New -> file called manifest.
• Add the following contents
• Manifest-Version: 1.0
• Name: myapp/Person.class
Java-Bean: True

Note that there is a blank line at the end of the file.

We repeat each Name/Java-Bean lines for each Java bean we are declaring in our
project.

• Because we would like our JavaBean to be a reusable asset for our project work, we
will simply Export the file to a Jar file.

Choose Right Mouse button -> Export -> Java -> JAR

This brings up a wizard to generate a Jar package and the various options to generate
a JAR file. For the moment, we will choose to Export java source files - this isn't
strictly necessary since sometimes we don't want others to see our source code.

Select a destination file - let's call it mybeans.jar in and place this into some external
development directory.

Click next which gives us the packaging options window. Click next to get the
Manifest window.

Now choose Use existing manifest from workspace and Browse to the manifest file
we created earlier.

• We can manually check the contents of the JAR file by using the following command
from a terminal:

87
• jar tvf mybeans.jar

The table-of-contents should look like the following:

0 Tue Aug 21 00:00:00 EST 2007 META-INF/


113 Tue Aug 21 00:00:00 EST 2007 META-INF/MANIFEST.MF
552 Tue Aug 21 00:00:00 EST 2007 myapp/Person.class
408 Tue Aug 21 00:00:00 EST 2007 myapp/Person.java

Congratulations, phase one is complete. You have built a JavaBean.

Creating your JSP page

Once the JavaBean has been created, and placed in a JAR file in the WEB-INF/lib directory,
creating the JSP file that accesses the JavaBean is easy.

You need to copy the jar file you created earlier into the labs project. Put the file into the
WebContent / WEB-INF / lib subdirectory.

Create a JSP file called FaveColour.jsp with the following contents and test it.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"


pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<jsp:useBean id="fred" class="myapp.Person" scope="session" />
<jsp:useBean id="jane" class="myapp.Person" scope="page" />

<jsp:setProperty name="fred" property="name" value="Fred Jones" />


<jsp:setProperty name="fred" property="favecolour" value="blue" />
<jsp:setProperty name="jane" property="name" value="Jane Chan" />
<jsp:setProperty name="jane" property="favecolour" value="red" />

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>My Java Bean Test</title>
</head>
<body>
<p>The favourite colour of
<jsp:getProperty name="fred" property="name" />
is
<jsp:getProperty name="fred" property="favecolour" /> .
</p>

<p>The favourite colour of


<jsp:getProperty name="jane" property="name" />
is
<jsp:getProperty name="jane" property="favecolour" /> .
</p>

</body>
</html>

88
Adding new properties

To test that you have grasped the use of JavaBeans, modify the Person bean and add another
property called "emailAddr". Modify your JSP pages accordingly.

Hint: It may be easier to export the Java Bean jar file directly into the labs / WebContent /
WEB-INF / lib directory.

You can also investigate modifying labs to directly access the mybeans project as a utility
library (we will talk about this later)

Beans and sessions

Note that in the above JSP code, the "fred" bean was defined with scope "session", while the
"jane" bean was defined with scope "page".

The "fred" bean, with all of its stored values, will be automatically stored in the HttpSession
object. To retrieve it in another page, you just use the same code, and it will be automatically
retrieved from the session, complete with its previously set values.

<jsp:useBean id="fred" class="myapp.Person" scope="session" />

To test the persistence of beans across sessions, make a second copy of the JSP file you
created above. Now in the copy, delete all of the "setProperty" actions.

To test, first access the original JSP file (the one with the "setProperty" actions). Then access
the second JSP file (the one without the "setProperty" actions). What do you notice?

89
Module: JSP
Lab exercise - Using Struts

Level of Difficulty: 4 (moderately difficult)


Estimated time: 30 minutes
Pre-requisites:

• Completed the Javabean lab exercise

Adding support for Struts


Workshop for Weblogic (unlike Standard Eclipse WTP) has some support for Struts. Do to
this, you need to add the "Struts" 1.2 facet to your project.

• Right Mouse Button click on your project, then press Properties


• You should see a property called "Project Facets" - note that this has Dynamic Web Module
2.4, JSTL 1.1 and Java 5 (plus maybe others)
• Click on Add/Remove Project Facets and check Struts. Ensure that version 1.2 is listed.

The main change to your application is that there is now a shared library called "Weblogic
J2EE library [Struts 1.2] in the Labs -> Java Resources -> Libraries folder on your project.
This also enables some support for the Struts configuration and validation xml files and tag
libraries.

You now need to modify your web.xml to support struts. To do this you need to edit your
Deployment Descriptor (web.xml) by adding the following tags:

<servlet>
<servlet-name>Struts Action Servlet</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
and

<servlet-mapping>
<servlet-name>Struts Action Servlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>

in the appropriate spots in your deployment descriptor, web.xml. (sample exists in


/pub/aip/struts/lab/WEB-INF/web.inc )

90
Our Lab example
We are going to create a simple application that records a persons name and favourite colour,
much like the servlet and JSP labs. However, we will use several struts features to show you
how to create a simple MVC application using Struts.

Basically we will only have a few 'states' at first - the welcome page (index.jsp), the list
Persons page (listPerson.jsp), the Add person page (createPerson.jsp) and finally a reset state
(which demonstrates a state with no actually JSP, we re-use the index page).

To transition between these 'states', we will use the following actions (which translate mostly
to a URL consisting of /action.do

index

JSP file if
Action Action Class Comments
successful

This has links to the 3 main actions of this


index application, and also /index.jsp
displays messages to the user.

listPerson ListPersonAction.java Checks if there a 'people' attribute in the /listPerson.jsp

91
session, if not, sets an error

This is a 'forward' which invokes the


createPerson.jsp, which displays
the input form. The submit action is
createPerson addPerson.do. /addPerson.do
Note that when we add validation, this form
will be re-invoked if validation
fails.

This is called by the createPerson.jsp form


when the "submit"
addPerson AddPersonAction.java button is pressed. It then creates the Person /index.jsp
bean and stores it in the
"database"

This bean just deletes the 'person' attribute


resetPerson ResetPersonAction.java from the session /index.jsp
& leaves a message for the main page.

Struts Configuration

The next step is to create a Struts configuration file to match the above configuration.

We have set up a struts example in the /pub/aip/struts/lab directory.

• Import into WebContent\WEB-INF: WEB-INF\struts-config.xml


• import into WebContent: index.jsp, createPerson.jsp and listPerson.jsp
• import into Java Resources\src: src\* (this includes myapp.* classes &
ApplicationResources.properties

Try it and see how it works

Struts layout

Take a look at the files in this directory. Note that this Struts application doesn't have
standardised messages and has no error checking and validations.

You can find the java source in the src directory.

Take special note of the ApplicationResource.properties file - this contains the strings which
our struts application uses.

The struts configuration files can be found in the WEB-INF directory.

Modifying struts
92
Your job is to create some validation rules that make name and color required. For hints, look
at the /pub/aip/struts/lab.answers directory. Note that we created a validation.xml file! Note
that validation-rules.xml comes with the default Struts configuration, you don't need to
modify this!

We also have a copy of the Eclipse/Workshop projects for each step to take: struts1 is the
same as the lab, struts2 has basic validation, struts3 has validation with Javascript.

Steps to take

First step: Change WEB-INF/struts-config.xml

Change references of org.apache.struts.action.DynaActionForm to


org.apache.struts.validator.DynaValidatorForm (This subclass of DynaActionForm
handles validation via the /WEB-INF/validation.xml and validation-rules.xml files)

Add validate="true" to <action path="/addPerson"

Add the validator plugin ie:

<!-- plugins -->


<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>
</plug-in>

2nd Step: Edit createPerson.java

• change import of DynaActionForm to import org.apache.struts.validator.DynaValidatorForm;


• change cast from (DynaActionForm) to (DynaValidatorForm) near line 37

You can check the steps by comparing the directory /pub/aip/struts/struts1 and
/pub/aip/struts/struts2

Optional Step: Add error highlighting to CreatePerson.jsp

• add the attribute errorStyle="background-color: red" to the <html:text elements.

Build & Test this

Optional Step: Add Cancel button to CreatePerson.jsp

This allows us to cancel even if we fail validation (since this can get you into a loop!)

• Add <html:cancel> to CreatePerson.jsp (just after the <html:reset>)


• Add the following to the <action path="/addPerson" element in struts-config.xml

<set-property property="cancellable" value="true"/>


<forward name="cancelled" path="/index.jsp"/>

Optional Step: Add Javascript validation

93
• Simply add <html:javascript formName="personForm" dynamicJavascript="true" /> to
createPerson.jsp
• Add onsubmit="return validatePersonForm(this);" to the <html:form element

You can also see that we have 2 versions of the createPerson.jsp file in the lab.answers.
createPerson_no_javascript.jsp doesn't have javascript validation and will highlight the error
field in red.

More tasks

How about change the color selection to be a drop down menu? Radio buttons? Selection
list? Use the appropriate Struts tag instead of the HTML one

One neat trick Struts provides is the ability to dynamically generate Selection/Menu/Radio
buttons from a java Collection class. See the Struts reference on how to do this.

References
Weblogic 10 has Apache Struts 1.2.9 support built in. You can read the reference guide at:
http://struts.apache.org/1.2.9/

Module: JDBC
Lab exercise - Oracle Familiarisation - command line version
94
In this module, we will be writing Java programs that connect to a database server, issue
queries, and update information. Before looking at the Java syntax, it is useful to take a
moment to become familiar with the Oracle database server we will mostly be using. Some
basic knowledge of databases is assumed, however no detailed technical knowledge is
expected as the queries we will be performing are very basic.

Level of Difficulty: 1 (easy)


Estimated time: 15 minutes
Pre-requisites:

• None

Setting up your Oracle account

The faculty provides an Oracle database server on a machine called smaug.it.uts.edu.au. In order
to administer this database, you will need to modify your profile to include certain
environment variables and will need to update your default PATH with the oracle database
code

Add the following to the end of your .bashrc file.

# oracle setup
export ORACLE_HOME=/opt/Oracle10g-client
export PATH=$PATH:/opt/Oracle10g-client/bin
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/Oracle10g-client/lib

You should have been provided with an Oracle userid. If not, ask your tutor for the id and
password.

Your default oracle database (also called SID) is called ell

This means the JDBC URL will be jdbc:oracle:thin:@smaug.it.uts.edu.au:1522:ell

Creating an SQL command file

Each person will have an Oracle database account set up which will contain your own
database tables, separate to everyone else's. However initially, your Oracle account will be
blank, so the first task is to create a test table.

When working with Oracle, we will be using a command-line interface that Oracle calls
SQL*Plus. In this command-line interface, you can enter SQL statements to create tables,
insert data, and issue queries. However if you have a complex sequence of SQL commands to
enter, it is best to create a command file, with the sequence of commands. Command files are
also useful if you later want to delete your data and recreate your tables in their "initial" state.

A command file is just a plain text file containing SQL commands. You create and edit it
using a normal text editor.

95
Create a text file called addressbook.sql using a text editor, and enter the following contents.
Substitute your own data if you prefer.

DROP TABLE addressbook;

CREATE TABLE addressbook (


name VARCHAR(30) PRIMARY KEY,
address VARCHAR(50),
email VARCHAR(50),
extn DECIMAL(4,0),
birthday DATE
);

-- note that dates are strings normally in the yyyy-mm-dd


-- formats for SQL92 eg:mysql, pointbase etc
-- oracle only accepts dd-mon-yyyy format, you need to use the non-standard
-- TO_DATE() function to convert other date strings to Oracle format
-- However, Oracle JDBC driver does accept the JDBC escape format eg:
-- {d 'yyyy-mm-dd'}

INSERT INTO addressbook VALUES ('chris','CB10.04.226',


'chw@it.uts.edu.au', 7938,
'01-jan-2001' );

-- Note: we use the Oracle specific TO_DATE(string, format) function

INSERT INTO addressbook VALUES ('Maolin','CB10.04.260',


'maolin@it.uts.edu.au', 7858,
TO_DATE('30.12.1990','DD.MM.YYYY'));

INSERT INTO addressbook VALUES ('Wayne','CB10.04.230',


'brookes@it.uts.edu.au', 7991,
TO_DATE('04/29/1992','MM/DD/YYYY'));

SELECT * FROM addressbook;

Points to note:

• Oracle SQL commands are not case sensitive. Case only matters when you are
entering literal strings (between quotes).
• When you first enter Oracle's command-line mode, by default it does not actually
save any of your changes until you exit. This is often not a good thing. By using the
"set autocommit on" command, it forces Oracle to save your changes after each
command. You should always set autocommit on, unless you are experienced with
Oracle and wish to do manual commits.
• Single quotes must be used around strings, not double.
• Comments start with two dashes (--). You can also use C-style comments. You should
not mix comments in with your SQL statements. Each single SQL command should
be uninterrupted, and the comments can be placed between SQL commands.
• VARCHAR is a string data type which can contain a VARiable number of
CHARacters, up to the specified maximum.
• DECIMAL is a data type for representing numbers, both with and without fractions.
In this case we want a fixed-point number with four digits before the decimal point
(integer part), and zero digits after the decimal point (fraction part). If you were

96
storing monetary values, you might choose a data type of DECIMAL(8,2) for
example, allowing for 2 digits of precision after the decimal point.
• Oracle has a non-standard representation of DATE, which only accepts strings in the
format of 'DD-MON-YYYY' where MON is a 3 character string representing the
month eg: JAN = January.
You can use the Oracle-only TO_DATE() function to convert from a string in many
date formats using a format string such as 'YYYY-MM-DD'.

Starting SQL*Plus

The next step is to enter Oracle's command-line interface and run your command file.

The version of Oracle installed at the faculty provides 2 main user interfaces

• A command-line client called sqlplus which can access the faculty Oracle database
server from your workstation
• A web based client called iSQL*Plus. This can be found at
http://smaug.it.uts.edu.au:7777/isqlplus
Note that you need to enter ell for the Connection Identifier if you use the iSQL*Plus
web page

We will use the command line version for this lab.

1. Logon to your workstation. If you have just edited your .bashrc with the Oracle
variables, you will need to close the terminal and restart it to ensure that the
variables are set.
2. Change directory to the directory in which you saved your SQL command file created
above.
3. At your Unix shell prompt, run the SQL*Plus command as follows. Please note that
you should use the Oracle username and password that you were assigned.

The faculty provides an alias that allows you to remotely access the Oracle server,
smaug.it.uts.edu.au. This is called ell_smaug. To use this, we pass a parameter to the
sqlplus command that looks like userid@ell_smaug (where userid is your ORACLE
userid).

workstation:~$ sqlplus userid@ell_smaug


SQL*Plus: Release 9.2.0.1.0 - Production on Mon Mar 29 17:10:28 2004

Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.

Enter password: xxxxxx

Connected to:
Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production
With the Partitioning, Oracle Label Security, OLAP and Oracle Data Mining options
JServer Release 9.2.0.1.0 - Production

SQL>

97
Your prompt has now changed to SQL>. You are no longer at your Unix shell, but are
in Oracle's command-line database interface. All the commands you type at this
prompt should be SQL or Oracle-specific commands.

Running your SQL command file

From the SQL*Plus prompt, type the following command, which instructs Oracle to load and
execute the contents of your command file.

start addressbook.sql;

Running ad-hoc SQL queries and SQL*Plus commands

While in the SQL*Plus environment, you can also run arbitrary SQL queries and other valid
SQL*Plus commands. Try the following commands, at the SQL*Plus prompt. Note that each
command ends with a semi-colon. If you forget the semi-colon, SQL*Plus will go into multi-
line editing mode. This is okay, just enter a semi-colon and press enter to finish the
command.

select * from addressbook;

describe addressbook;

select table_name from user_tables;

drop table addressbook;

start addressbook.sql;

Quick SQL*Plus Tutorial

There is also a quick SQL*Plus tutorial which summarises the few commands you will need
to use Oracle in this subject.

Feel free to experiment until you are comfortable with SQL*Plus.

Changing your password

You can change your password by typing the following SQL command from within sqlplus:

password

If you use the web interface, use the Preferences > Change Password menu instead

98
Disconnecting from SQL*Plus

When you are ready to leave SQL*Plus, use the quit command. If you are making changes to
the database regularly, you might like to keep a window with SQL*Plus open in the
background.

SQL> quit
Disconnected from Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production
With the Partitioning, Oracle Label Security, OLAP and Oracle Data Mining options
JServer Release 9.2.0.1.0 - Production

Oracle Tools

You can also use a browser based version of Sqlplus via


http://smaug.it.uts.edu.au:7777/isqlplus
Conveniently, this works remotely from home via a normal browser!

Oracle Documentation

There is some Oracle documentation available online. This can be found at


http://www.oracle.com/pls/db92/db92.homepage

Module: JDBC

99
Lab exercise - Oracle Familiarisation - Workshop for Weblogic version

In this module, we will be writing Java programs that connect to a database server, issue
queries, and update information. Before looking at the Java syntax, it is useful to take a
moment to become familiar with the Oracle database server we will mostly be using. Some
basic knowledge of databases is assumed, however no detailed technical knowledge is
expected as the queries we will be performing are very basic.

Level of Difficulty: 1 (easy)


Estimated time: 15 minutes
Pre-requisites:

• None

Setting up your Oracle account

The faculty provides an Oracle database server on a machine called smaug.it.uts.edu.au. In order
to administer this database, you will need to modify your profile to include certain
environment variables and will need to update your default PATH with the oracle database
code

Add the following to the end of your .bashrc file.

# oracle setup
export ORACLE_HOME=/opt/Oracle10g-client
export PATH=$PATH:/opt/Oracle10g-client/bin
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/Oracle10g-client/lib

You should have been provided with an Oracle userid. If not, ask your tutor for the id and
password.

Your default oracle database (also called SID) is called ell

This means the JDBC URL will be jdbc:oracle:thin:@smaug.it.uts.edu.au:1522:ell

Setting up your Workshop project

You will need to add the Oracle JDBC jar file into your project build classpath. To do this,
you need to Right Mouse Button -> Properties and select Java Build Path. (Alternative:
Right Mouse Button -> Build Path -> Add external Archives )

Choose the Libraries tab and Select Add External Jars. Browse to
/opt/bea10/wlserver_10.0/server/lib and select ojdbc14.jar

Creating an SQLpage file

100
Each person will have an Oracle database account set up which will contain your own
database tables, separate to everyone else's. However initially, your Oracle account will be
blank, so the first task is to create a test table.

Eclipse/Workshop for Weblogic provides an editor for creating SQL scripts. Later versions
have content assists and wizards, but the version currently installed does not provide this
feature.

You can create the SQL files in your project by using the Right Mouse Button -> New ->
Other -> Data -> SQL scrapbook page

Let's create one called addressbook.sqlpage using the following text.

DROP TABLE addressbook;

CREATE TABLE addressbook (


name VARCHAR(30) PRIMARY KEY,
address VARCHAR(50),
email VARCHAR(50),
extn DECIMAL(4,0),
birthday DATE
);

-- note that dates are strings normally in the yyyy-mm-dd


-- formats for SQL92 eg:mysql, pointbase etc
-- oracle only accepts dd-mon-yyyy format, you need to use the non-standard
-- TO_DATE() function to convert other date strings to Oracle format
-- However, Oracle JDBC driver does accept the JDBC escape format eg:
-- {d 'yyyy-mm-dd'}

INSERT INTO addressbook VALUES ('chris','CB10.04.226',


'chw@it.uts.edu.au', 7938,
'01-jan-2001' );

-- Note: we use the Oracle specific TO_DATE(string, format) function

INSERT INTO addressbook VALUES ('Maolin','CB10.04.260',


'maolin@it.uts.edu.au', 7858,
TO_DATE('30.12.1990','DD.MM.YYYY'));

INSERT INTO addressbook VALUES ('Wayne','CB10.04.230',


'brookes@it.uts.edu.au', 7991,
TO_DATE('04/29/1992','MM/DD/YYYY'));

SELECT * FROM addressbook;

Points to note:

• Oracle SQL commands are not case sensitive. Case only matters when you are
entering literal strings (between quotes).
• Single quotes must be used around strings, not double.
• Comments start with two dashes (--). You can also use C-style comments in one line
/* */. You should not mix comments in with your SQL statements. Each single SQL
command should be uninterrupted, and the comments can be placed between SQL
commands.

101
• VARCHAR is a string data type which can contain a VARiable number of
CHARacters, up to the specified maximum.
• DECIMAL is a data type for representing numbers, both with and without fractions.
In this case we want a fixed-point number with four digits before the decimal point
(integer part), and zero digits after the decimal point (fraction part). If you were
storing monetary values, you might choose a data type of DECIMAL(8,2) for
example, allowing for 2 digits of precision after the decimal point.
• Oracle has a non-standard representation of DATE, which only accepts strings in the
format of 'DD-MON-YYYY' where MON is a 3 character string representing the
month eg: JAN = January.
You can use the Oracle-only TO_DATE() function to convert from a string in many
date formats using a format string such as 'YYYY-MM-DD'.

Creating a Database Connection

The next step is to run the SQL page. You can do this via the Right Mouse Button -> Run
SQL command. This should open up a Select Connection wizard.

• Select Create New Connection


• Choose a database manager - in this case, choose Oracle -> 10. You then add the
following connection details:
o JDBC Driver: Other
o Database: ell
o JDBC Driver Class: oracle.jdbc.driver.OracleDriver
o Class location: /opt/bea10/wlserver_10.0/server/lib/ojdbc14.jar
o Connection URL: jdbc:oracle:thin:@smaug.it.uts.edu.au:1522:ell
o Enter your oracle userid and password in the User Information box
o You can then Test Connection to check your details. Press Next to continue
o The database connection wizard can filter out different schemas from the
database connection - since the oracle server contains possibly hundreds of
students entries, you should choose to narrow this list down to your own
schemas.
On the Filter wizard, Select Expression and Name "starts with the
characters". In the entry field, enter your Oracle userid in UPPER CASE.
(unfortunately, this is case sensitive).
o Press Finish to complete.

You should then see a Data Output window appear in the lower pane. Note that there now is
a Database Explorer view appearing too (If not, you can select Window -> View ->
Database Explorer from the main menubar)

Note that for each command that was executed, you will get a status line and SQL Editor box
showing relevant messages & results.

You can clear this by pressing Right Mouse Button -> Delete All to clear the results.

You can also follow the above setup sequence to create new connections from the Database
Explorer view by Right Mouse Button click on the Connections icon.

Running your SQL command file

102
Any time you are in an SQL Scrapbook page you can test an individual SQL statement by
highlighting (selecting) the relevant SQL statement and then using the Right Mouse Button -
> Run SQL command

Note that only valid SQL commands will work here. Do not use SQL*PLUS commands here
(such as set autocommit on, password, describe addressbook etc).

Exploring your Database

The Database Explorer allows you explore your database. If you select the Database Explorer
view, notice that there is a + symbol alongside the ell connection? Expand this and you
should see ell -> + Schemas (Filtered).

If you don't see the +, then you probably have an incorrect filter (Choose Right Mouse Button
-> Filter, then correct the filter - normally this should be an UPPER CASE userid. You can
optionally turn off filters by selecting the Disable Filter checkbox).

Expanding this further you will see + tables, then your addressbook table.

The neat feature of Database Explorer is that you can drill down in further details (such as
column definitions, indexes etc).

If you select table (eg: ADDRESSBOOK) and pressing Right Mouse Button -> Data you can:

• Edit the table in a spreadsheet - this lets you view, update, add, delete rows in the
table
• Load - load data from text files (eg: CSV files)
• Extract - save data to a text file

Try adding, updating and deleting records from the addressbook table.

103
Finally, save the data by Extract'ing the records to a text file.

Disconnecting

When you wish to disconnect from the database, switch to the Database Explorer window
and select the connection (this will be called ell by default). Press Right Mouse Button ->
Disconnect

104
Module: JDBC
Lab exercise - Hello World JDBC

JDBC is the Java API for accessing databases. Eventually we will use JDBC for connecting
the business logic parts of our application to the necessary databases. But first we begin at the
beginning - with a Hello World example. This exercise is to create a simple command-line
application that connects to a database.

Level of Difficulty: 1 (easy)


Estimated time: 20 minutes
Pre-requisites:

• Run 'setEnv.sh' to set your environment correctly


• Completed the Oracle familiarisation lab exercise

A HelloWorld JDBC application

Because we are creating a standalone application, you do not need a WAR file, and we will
not be installing it into the application server. It also does not really matter which directory
you create this program in.

Create the following Java class & change the oracle_userid oracle_password to your
Oracle userid and password!!

import java.sql.*;

public class HelloWorldJDBC {

private static final String dbdriver =


"oracle.jdbc.driver.OracleDriver";

private static final String dburl =


"jdbc:oracle:thin:@smaug.it.uts.edu.au:1522:ell";

private static final String dbuser = "oracle_userid"; // change to your id


private static final String dbpass = "oracle_password";

public static void main (String [] args) {

try {

// Load the driver and create connection


Class.forName(dbdriver);
Connection conn =
DriverManager.getConnection(dburl, dbuser, dbpass);

// Create a statement and execute the query


Statement stmt = conn.createStatement();
stmt.executeQuery("select * from addressbook");

// Get the result set

105
ResultSet rs = stmt.getResultSet();

// Loop through and print out the values


while (rs.next()) {
System.out.print(rs.getString(1) + ",");
System.out.print(rs.getString(2) + ",");
System.out.print(rs.getString(3) + ",");
System.out.print(rs.getLong(4) + ",");
System.out.println(rs.getString(5));
}

// now release the connection.


conn.close();

} catch (Exception e) {
// If anything goes wrong, print the Exception message
e.printStackTrace();
}

}
}

To connect to the database, two essential pieces of information are required (other than the
username and password):

• JDBC driver class - the name of a Java class that knows how to communicate with
the particular kind of database you are connecting to. You will need to specify a
different driver class for each kind of database you wish to connect to.
• JDBC URL - a URL that specifies which database to connect to. JDBC URLs always
start with the protocol "jdbc:", but the format of the remainder of the URL differs
depending on the kind of database you are connecting to (i.e. each driver class has its
own URL format).

In the case of Oracle, the URL includes the driver type ("thin"), the hostname
("smaug.it.uts.edu.au"), the port number ("1522") and the database name ("ell").

Running in Workshop

First you have to load the Oracle JDBC library. To do this, select the project, Right Mouse
Button -> Build Path -> Add External Archives then navigate to
/opt/bea10/wlserver_10.0/server/lib and select ojdbc14.jar
(in Windows: c:\bea\wlserver_10.0\server\lib)

Note: You should pick the appropriate database driver jar file if you are using another
database eg: mysql-comnector-java-commercial-5.0.3.jar for mysql

To test your application, click Right Mouse Button -> Run As -> Java Application

The output should appear in the Console.

Running from the Command Prompt

106
To test your application, compile it using javac (hint: did you remember to run wlenv to set
your classpath?) and then run it using the command-line Java interpreter:

java HelloWorldJDBC

Notes

Note that hardcoding the JDBC URL, userid and password is not good practice to follow.
You would be better off storing these as seperately as parameter files.

Module: JDBC

107
Lab exercise - JDBC in a JavaBean

This exercise demonstrates one way of using a JavaBean for data access. In this example, we
use a JavaBean to issue arbitrary SQL commands on a database. The JavaBean is quite
generic - however it does have the database details hard-coded!!! (don't do this in real life :-).

Level of Difficulty: 2 (moderately easy)


Estimated time: 20 minutes
Pre-requisites:

• Run 'setEnv.sh' to set your environment correctly


• Completed the Hello World JDBC lab exercise

JDBC in a JavaBean

This time we are creating a JavaBean. We will also create a small program to test the
JavaBean before we try and use it in a JSP. This is an example of unit testing, which is
currently seen as a good software engineering approach.

Create the following Java class. This is the JavaBean.

package myapp;

import java.sql.*;
import java.util.*;

// All JavaBeans must be Serializable


public class OracleBean implements java.io.Serializable {

private static final String dbDriver =


"oracle.jdbc.driver.OracleDriver";

private static final String dbURL =


"jdbc:oracle:thin:@smaug.it.uts.edu.au:1522:ell";

/* Defining the attributes.


Notice that they are all declared private.
They cannot (and must not) be accessed directly
from other objects, or it would violate the
JavaBean rules.
*/
private String dbUser;
private String dbPass;
private Connection conn;

public void connect()


throws ClassNotFoundException, SQLException {
if (dbUser != null) {
Properties props = new Properties();
props.setProperty("user", dbUser);
props.setProperty("password", dbPass);

Class.forName(dbDriver);

108
this.conn = DriverManager.getConnection(dbURL, props);
}
}

public void close() throws SQLException {


this.conn.close();
}

public ResultSet query(String sql) throws SQLException {


Statement s = conn.createStatement();
return (s.executeQuery(sql));
}

public int update(String sql) throws SQLException {


Statement s = conn.createStatement();
return (s.executeUpdate(sql));
}

/* get/set the dbUser property */


public String getDbUser() { return this.dbUser; }

public void setDbUser(String dbUser) {


this.dbUser = dbUser;
}

/* get/set the dbPass property */


public String getDbPass() { return this.dbPass; }

public void setDbPass(String dbPass) {


this.dbPass = dbPass;
}
}

Notice that this JavaBean has two properties: dbUser and dbPass. These must be set at
runtime before calling the connect() method.

A unit test for the JDBC JavaBean

Now we need to unit test the JavaBean.

Add the following main() method to your JavaBean. Vary the SQL query if you wish, to see
different results. You can also test updating by using the o.Update() method. Now you can
test the bean by using Right Mouse Button -> Run As -> Java Application

public static void main (String [] args)


throws ClassNotFoundException, SQLException {
OracleBean o = new OracleBean();
o.setDbUser("oracle_userid");
o.setDbPass("oracle_password");
o.connect();
ResultSet r = o.query("SELECT * FROM addressbook");
while (r.next()) {
System.out.print(r.getString(1) + ",");
System.out.print(r.getString(2) + ",");
System.out.print(r.getString(3) + ",");

109
System.out.print(r.getLong(4) + ",");
System.out.println(r.getString(5));
}
}

Module: JDBC

110
Lab exercise - JDBC in a JavaBean in a JSP

Now that you have a JavaBean created to connect to the database, you can use it inside your
JSP.

Level of Difficulty: 2 (moderately easy)


Estimated time: 20 minutes
Pre-requisites:

• Run 'setEnv.sh' to set your environment correctly


• Completed the JDBC in a JavaBean lab exercise

Adding JSP

Now that you have a JavaBean, it is time to use it in a JSP. Below is a starting point for a
JSP.

<%@ page language="java" contentType="text/html"


import="java.sql.*, myapp.*" %>
<jsp:useBean id="mydb" class="myapp.OracleBean" scope="request" />

<%! ResultSet rs = null; %>

<jsp:setProperty name="mydb" property="dbUser" value="oracle_userid" />


<jsp:setProperty name="mydb" property="dbPass" value="oracle_password" />

<HTML>
<HEAD>
<TITLE>My JDBC JavaBean Test</TITLE>
</HEAD>

<BODY>

<% mydb.connect();
rs = mydb.query("SELECT * FROM addressbook");
while (rs.next()) {
%>
<P>
<%= rs.getString("name") %>
<%= rs.getString("address") %>
<%= rs.getString("email") %>
<%= rs.getLong("extn") %>
<%= rs.getString("birthday") %>
</P>

<% } %>

<% mydb.close(); %>

</BODY>
</HTML>

111
Notice how the majority of the database code is removed from the JSP and placed in the
JavaBean. The JSP should really only be printing out information from the JavaBean. In this
case we are using a JSP Model 1 architecture (no central controller), therefore the JSP itself
does contain some business logic (setting the properties on the bean, and also the SQL
query).

Improving formatting

Notice that the database output in the above example is not well formatted.

Use a HTML table to display the data.

Better Solution

Note that we have still hard-coded references to Oracle and JDBC in the bean

A better solution could be to hide the implementation even further by using the Data Access
Object pattern.

To do this, you need to create a Interface with common "CRUD" access methods such as
create, read, update, delete and find. This should deal with a JavaBean that represents the
object you are working with.

In our case, we can update the Person object from earlier labs by adding address details (such
as address, email, extn and birthday).

We then create a PersonDAO class which has the following methods.

void createPerson( Person)


Person readPerson(String name)
// since primarykey is name. Could also pass a Person object with name as key
// this effectively does select * from addressbook where name = 'name'
Person updatePerson(Person)
// this would do update addressbook set .. where name = Person.name
// note that we might have to put special processing for changing name
void deletePerson(Person)
// this would do delete from addressbook where name = Person.name
// alternatively, could pass the name since this is the primary key
Collection<Person> findAll()
// does a select * from addressbook
Collection<Person> findByName()
// does a select where name=name - note that this is the same as readPerson()
This PersonDAO will use the OracleBean to query and update the database.

We then change the JSP to use this PersonDAO bean. We then call PersonDAO. findAll() to
get the collection.

The best thing about this is that you can use Expression Language eg: ${person.name} and
also use the EL automatic understanding of Collection classes.

Try creating PersonDAO and Person and changing this JSP.

112
Module: JDBC
Lab exercise - Connection Pools and Data Sources

Establishing database connections is a very time consuming part of an application. Typically


the database runs on a different server, so there is network delay added on top of the time it
takes for the connection to be set up. One way to improve performance of applications that
use databases is to use connection pooling. This is described more below.

Level of Difficulty: 4 (moderately difficult)


Estimated time: 40 minutes
Pre-requisites:

• Run 'setEnv.sh' to set your environment correctly


• Completed the JDBC in a JavaBean in a JSP lab exercise

JDBC Connection Pools

The basic concept is that because establishing database connections takes so much time,
applications that use databases can be made more efficient by preventing them from having to
establish a new database connection each time they run. Instead, the idea is to have a pool of
connections pre-established so that when the application runs, it can reuse one of the existing
connections.

The pool of pre-existing connections is provided by the container in which the application
executes. In our case, the connection pool will be provided by the web application server.
When an application (servlet/JSP, and later EJB) needs to connect to a database, it asks the
container to give it one of the pooled connections.

Connection Pools provide an efficient way to reuse database connections. However they do
not make it easy to dynamically reconfigure where a particular application should get its data
from. In an effort to isolate the database details from the application even further, JDBC uses
the concept of a Data Source.

When your application wishes to connect to a database, it will ask the application server for a
data source. Inside the application server, each data source is mapped to a particular
connection pool. To change which database an application retrieves its data from means only
changing the data source configuration in the application server - no source code changes are
required.

This is best practice - you SHOULD use data sources in your production code.

Setting up a Connection Pool & Data Source in WebLogic

Because the connection pool & data source is managed by the container, you need to
configure it in the container, not in your application. To set up a connection pool & data
source in WebLogic, you need to use the web-based management console.

113
In the management console, use the menu on the left to locate "Services", then "JDBC" and
then "Data Sources".

Lock & Edit , then select "New" on the "Data Sources (filtered)" table.

Fill in the following details:

1. JDBC Data Source properties:


o Name = thinOracleDataSource
o JNDI name: thinOracleDataSource
o Database type = Oracle
oDatabase driver: *Oracle's Driver (thin)
Note: Use the pull down menu to get the list of drivers to use.
Note: Do not use the "*BEA's Oracle Driver .."!
o [NEXT]
o (leave defaults)
o [NEXT]
2. Transaction Options
o Database name: ell
o Hostname = smaug.it.uts.edu.au
o Port = 1522
o Enter your Oracle Database user name & password

Note that this is the same information you needed inside your earlier JDBC code
examples. But now instead of putting it in your Java source code, you are configuring
it declaratively within the application server.

o [NEXT]
3. Connection Properties
4. Test Database Connection
o You can now test this connection via the [Test Configuration] button
Note that webLogic has generated the following settings:

Driver Classname = oracle.jdbc.driver.OracleDriver


& URL = jdbc:oracle:thin:@smaug.it.uts.edu.au:1522:ell

o [NEXT]
o Choose AdminServer & click [Finish] to create the JDBC data source.
o Initial Capacity = 1
o Maximum Capacity = 2
o Capacity Increment = 1

This tab is used for performance tuning. You can adjust the number of pooled
connections, etc, to suit the size of your application, and capacity of your database.

oClick "[Save]"
oActivate changes
oClick on the [Activate Changes] on the top left menu to make the changes active
oUsually you don't need to restart the server. However, read the green message
response to check if you do need to restart weblogic or not.
5. Customising the connection settings
o You can now select the thinOracleDataSource from the Data Sources table.

114
o Choose the Configuration - Connection Pool tab & set the following defaults:

When your server restarts, watch the messages in the shell window where you start it
running. If there is an error in connecting to the database, it will show up as a Java exception
in this window.

Verifying your Connection Pool and Data Source

You should have already verified your connection pool is working when you restarted your
server. If there were JDBC error messages when the server was starting, then it means your
connection pool is not properly setup.

To verify your data source, in the management console, use the menu to go to "Servers", then
"AdminServer". Choose the link to "View JNDI tree". You should see your data source
name appear in the resulting web page. If your data source name does not appear, then there
is a problem with the setup of your data source (or connection pool). JNDI will be explained
separately.

The exercise

Now that the JDBC Data Source is available, you can use it from within your Java code.

The goal of the exercise is to modify the JavaBean you created earlier to use the JDBC data
source to establish the connection.

package myapp;

import java.sql.*;
import javax.sql.*;
import javax.naming.*;
import java.util.*;

// All JavaBeans must be Serializable

public class DataSourceBean implements java.io.Serializable {

private String dbDataSource;


private Connection conn;

public void connect() throws ClassNotFoundException,


SQLException, NamingException {
Context ctx = new InitialContext();
// Lookup using JNDI name.
DataSource ds = (DataSource) ctx.lookup(dbDataSource);
conn = ds.getConnection();
}

public void close() throws SQLException {


conn.close();
}

115
public ResultSet query(String sql) throws SQLException {
Statement s = conn.createStatement();
return (s.executeQuery(sql));
}

public int update(String sql) throws SQLException {


Statement s = conn.createStatement();
return (s.executeUpdate(sql));
}

/* get/set the dbDataSource property */


public String getDbDataSource() { return this.dbDataSource; }

public void setDbDataSource(String dbDataSource) {


this.dbDataSource = dbDataSource;
}

Notice now how all the database connection details (JDBC driver name, JDBC URL,
username, password) are removed from the Java code, because they are managed by the
application server. This also means that this bean is now completely database independent.
The same Java code can be used regardless of whether the database used is Oracle, Informix,
Ingres, etc.

When this JavaBean executes, it will ask the application server to provide a DataSource, and
the application server will allocate one of the available database connections to this JavaBean
for as long as it needs it. When the JavaBean closes the connection, the connection is returned
to the pool and available for other applications.

Testing your new bean

To test your new bean, you will need to modify your JSP code to reflect the properties of the
new bean. This is left up to you.

116
Module: JDBC
Tutorial - Using other databases with Weblogic 10

JDBC is a generic API that can be used for accessing any kind of database given the
appropriate drivers. The lab exercises in this module are written to use Oracle. This is a brief
explanation of how to convert the examples from using Oracle to using other JDBC databases

Weblogic 10 comes with some preinstalled commerical JDBC drivers. See


http://edocs.bea.com/wls/docs100/jdbc_admin/third_party_drivers.html for a definitive list
and how to use them.

Weblogic 10 also has a "universal" driver (called "Type 4 JDBC Drivers", also known as the
BEA drivers) which were written by Merant for BEA. See
http://edocs.bea.com/wls/docs100/jdbc_drivers/jdbcsupt.html for how to use them

You can also use other databases if they have a JDBC driver written for them. See
http://cayenne.apache.org/doc/database-support.html for a pretty good list of vendor JDBC
drivers.

Here is brief table of what drivers are installed by default. Note that these are already in the
pre-defined Weblogic classpath so you don't have to specifically add these jar file into your
classpath when running your WAR or EJB file.

However, do note that Workshop for Weblogic/Eclipse WTP does not automatically add
these files to your project build path properties.
You can find most of these files in the /opt/bea10/wlserver_10.0/server/lib directory.

Driver
Jar file Class Name URL
Name

Oracle
10g
(Thin ojdbc14.jar oracle.jdbc.OracleDriver jdbc:oracle:thin:@server:1521:db
client
Driver)

Sybase com.sybase.jdbc.SybDriver
jConne jConnect.jar com.sybase.jdbc2.jdbc.SybD
jdbc:sybase:Tds:server:port/db
ct 4.5, , jconn2.jar, river
5.5, jconn3.jar com.sybase.jdbc3.jdbc.SybD
and 6.0 river

mysql-
MySQ connector- com.mysql.jdbc.Driver
jdbc:mysql://server:port/db
L 5.0.x java- org.gjt.mm.mysql.Driver
commercial
-5.0.x-

117
bin.jar

pbclient51.j
ar
Pointba com.pointbase.jdbc.jdbcUni jdbc:pointbase:server://server:port/db
pbembedde
se 5.1 versalDriver jdbc:pointbase:embedded:db
d51.jar

Weblo wlbase.jar,
- -
gic wlutil.jar
type 4
drivers: weblogic.jdbc.db2.DB2Driv
wldb2.jar jdbc:bea:db2://server:port;DatabaseName=db
IBM er
DB2
8.2/9.1, wlinformix. jdbc:bea:informix://server:port;informixServer=s
weblogic.jdbc.informix.In
Informi jar erver;databaseName=db
formixDriver
x, MS
SQL wlsqlserver. weblogic.jdbc.sqlserver.SQL
jdbc:bea:sqlserver://server\\instance
server jar ServerDriver
2000/2
005, weblogic.jdbc.oracle.Oracle
wloracle.jar jdbc:bea:oracle://server:port;SID=db
Oracle Driver
9g,
10g,
Sybase weblogic.jdbc.sybase.Sybase
wlsybase.jar jdbc:bea:sybase://dbserver:port;SID=db
12.5/15 Driver
.1

Built into
JDBC
Java 1.4 & sun.jdbc.odbc.JdbcOdbcDriv
ODBC jdbc:odbc:odbc-dsn-name
later er
bridge
versions.

If you want to use the following databases (and corresponding JDBC drivers), you need to
download them and place
them into your classpath.

org.apache.derby.jdbc.Client
derbyclient. Driver
Derby jdbc:derby://server:port/db
jar org.apache.derby.jdbc.Embe
ddedDriver

Sqlite sqlitejdbc.ja jdbc:sqlite:/path/to/database.db


org.sqlite.JDBC
r jdbc:sqlite://path/to/database.db

118
sqlite.jar SQLite.JDBCDriver jdbc:sqlite:/:memory:

postgresql-
PostGr
8.3*.jdbc3.j org.postgresql.Driver jdbc:postgresql://server:port/db
es
ar

Step 1 - (Optional) Making WebLogic load the JDBC driver

Do this step ONLY if WebLogic does not have an existing JDBC driver (eg: for Apache
Derby)

Assuming you have downloaded the appropriate database client code and JDBC driver, your
next step is to place the JDBC driver (normally a JAR file) into the Weblogic classpath.

You can do this in three ways.

• Option 1: copy the driver into the default Java classpath (ie: the JRE_HOME/lib/ext ie:
/opt/bea10/jrockit_150_06/jre/lib/ext ).
This is NOT RECOMMENDED because this is not portable and often you will not have
root/administrator access to change these directories anyway.

• Option 2: Copy the jar files into the WEB-INF/lib directory (or into your EAR). This is
portable, but during development you will still need to place the JAR file into your classpath.

• Option 3: You can change the default Weblogic setup in your domain to include the JAR file
into the default classpath (assuming you have set up the wlenv alias). To do this:

• Edit your $DOMAIN_HOME/bin/setDomainEnv.sh and add the line:


EXT_PRE_CLASSPATH=path/to/driver.jar
(where $DOMAIN_HOME is your domain directory
eg: ~/weblogic, and path/to/driver.jar is the path to the JDBC JAR file)
• Add this just after the WL_HOME= line.
(Windows version: edit setDomainEnv.cmd and add SET
EXT_PRE_CLASSPATH=path\to\driver.jar )
• This is safer than editing the startWeblogic.sh command directly.

Step 2 - changing the parameters

Now that WebLogic can load the JDBC driver, you need to be able to change the code
examples to refer to the new database driver rather than Oracle. You need to change any
occurrence of the driver class and the matching URL. For example, for MySql, make the
following changes:

• JDBC driver class


oracle.jdbc.driver.OracleDriver
--> eg: Mysql: com.mysql.jdbc.Driver

119
• JDBC URL
Oracle: jdbc:oracle:thin:@smaug.it.uts.edu.au:1522:ell
--> eg: Mysql: jdbc:mysql://localhost/mydb

Step 3 - change Oracle specific SQL

• change any Oracle specific SQL (eg date formatting) to SQL92 formats. IF you used
the recommended JDBC escape sequence for dates eg: { d '2001-12-30'} instead of
the Oracle date format eg: '30-dec-2001', then you need to make no changes.

Module: JDBC
Tutorial - ODBC example

120
Microsoft Windows provides a universal interface to database & database-like services under
windows called ODBC.
For example, there are ODBC drivers for Microsoft Access, Excel spreadsheets, SQL Server
and so on.
There is a unix equivalent (unixODBC) on linux and solaris (and other unixes as well).

Java 1.4 upwards provides JDBC driver called the Sun JDBC-ODBC bridge. This driver is
provided in the default rt.jar library.

Driver class: sun.jdbc.odbc.JdbcOdbcDriver


URL format: jdbc:odbc:odbc-dsn-name

where odbc-dsn-name is the name of an existing ODBC Data Source Name (DSN) on the local
computer. This syntax will vary depending on the ODBC provider. Our example will use
Microsoft Access.

IMPORTANT NOTE: This driver is not thread-safe and should not be used in production.
Weblogic 10 does not allow you to use this driver for EJB's (though it will work for servlets
and JSP's)

For more details, read on ...

Creating an ODBC DSN

Windows ODBC works on the concept of data sources. Each data source has a name, called
the DSN or Data Source Name. Before you can access a database via ODBC, it should have a
DSN set up for it. Each DSN refers to one particular database that can be accessed via
ODBC.

Let's assume you want to allow your servlets/JSPs to connect to a Microsoft Access database.
ODBC data sources can connect to a variety of underlying file types including Access, Excel
and plain text files.

Here are the steps:

1. Create your database. Open up Microsoft Access with a blank database, create one
table with a few columns, and add a couple of rows of data.
2. Open up the ODBC Control Panel:
o Windows 2000/XP: "Start" menu -> "Settings" -> "Control Panel" ->
"Administrative Tools" -> "Data Sources (ODBC)"
3. Move to the "System DSN" tab and click the "Add" button.
4. Choose the "Microsoft Access Driver (*.mdb)".
5. Enter a name for the DSN. It can be any name you choose, but should start with a
letter and for simplicity should only contain alphanumeric characters. The DSN name
should somehow relate to the database name or its contents. Optionally enter a
description as well if you wish.
6. Under the word "Database", click on the "Select" button and locate the Microsoft
Access database (.mdb file) you created earlier.
7. Click "OK" in all the windows and your new DSN is created.

121
Accessing the ODBC DSN from a Java program

The key lines of Java code that differ between databases are loading the appropriate JDBC
driver, and specifying the database URL.

For accessing an ODBC DSN, the following are the two key lines:

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
...
conn = DriverManager.getConnection("jdbc:odbc:mydsn");

where you replace mydsn by the name of the ODBC DSN for your database.

Here is some example code you can download and try. It assumes you have a DSN actually
called "mydsn" and that in your database there is a table called "test".

Use your right-mouse button to save these to a local file.

• odbctest.java
A simple command-line application to test JDBC-ODBC.
• ODBCServlet.java
A servlet which connects to an ODBC data source.
• odbctest.war
A WAR file containing a (mostly) generic database access servlet and the appropriate
web.xml init-param's for it to connect to an ODBC data source. To extract individual
files, use the command: jar xvf odbctest.war

Module: JDBC
Tutorial - Oracle SQL*Plus

122
For working with an Oracle database, it is often convenient to use Oracle's command-line
interface to the database. This is the Oracle-specific program called SQL*Plus.

For the definitive SQL*Plus guide, see:

• Oracle documentation at http://dragon.it.uts.edu.au:9700/iplus/help/us/toc.htm

Running SQL*Plus
1. Log in to the Oracle database server. This is a Unix machine called dragon.it.uts.edu.au.
Connect with either ssh or telnet (ssh preferable). Use your regular Faculty login and
password (Unix login). You will be placed in your Unix home directory (same as
charlie/sally, and your X: drive on PCs).
2. Run the SQL*Plus program:
3. sqlplus
4. Enter your Oracle username and password. This is not the same as your Unix login.
5. You will now be at the SQL*Plus prompt. Here you can enter SQL statements, and SQL*Plus
commands.

Useful SQL*Plus commands

Firstly, note that generally, commands in SQL*Plus should be terminated by a semi-colon (;).

Secondly, if you press Enter in the middle of a command, Oracle will prompt you to enter
another line that is part of the same command - you can spread a command over multiple
lines. The command will be executed when you type a semi-colon. Each time you press
Enter, Oracle will prompt you by showing you the current line number that you are entering.

Using command files

Rather than typing complex commands directly into the SQL*Plus interface, create a file
containing the commands, and then run the command file in SQL*Plus. This also means if
the database data is lost for any reason, you can easily restore it to your chosen "initial" state.

Example:

start mycommandfile.sql;

or:

@ mycommandfile.sql;

You can include comments in your command file either using C-style comments /* ... */ or
comments starting with two dashes (--). The C-style comments must be placed on a line of
their own and not inside any block of SQL.

123
SQL*Plus also includes commands for saving the current edit buffer (SAVE) to a file and
loading a file into the current edit buffer (GET).

Committing changes

In SQL*Plus, the default behaviour is not to commit changes to the database until you
explicitly request it. Until changes are committed, they are not visible to other users
(including JDBC accesses).

There are two commands that may help:

commit;

will commit changes manually. Or:

set autocommit on;

will change the autocommit behaviour for the current SQL*Plus session so that changes are
automatically committed after each SQL command.

Examining table structures

The DESCRIBE command can show the structure of a table, e.g.

describe mytable1;

Running Unix commands

To run a Unix command from within the SQL*Plus interface, just prefix the command with
the keyword HOST, e.g.

host ls
host pico mycommandfile.sql
host vi mycommandfile.sql

Running SQL commands

In general, you will want to run SQL commands in SQL*Plus (preferably from a command
file).

If you need SQL help, here is a quick SQL refresher with lots of examples.

Module: JDBC

124
Tutorial - Quick SQL Refresher

The examples shown below are based on the Oracle dialect of SQL. Other databases use
slightly different syntax in some places (usually the available data types, and built-in
functions).

For the definitive Oracle SQL reference, see:

• Oracle documentation http://www.oracle.com/pls/db92/db92.homepage

SQL SELECT statement

Basic queries

General format:

SELECT column-list|*
FROM table-name-list
WHERE condition-list
ORDER BY column-list;

Firstly, here is how to retrieve all data from a table:

SELECT * FROM mytable;

You can retrieve specific columns (but all rows) from a table:

SELECT mycol1, mycol2 FROM mytable;

WHERE clause

You can limit which rows are returned according to some criteria:

SELECT * FROM mytable


WHERE mycol1 > 100;

Here is an example that limits with several conditions:

SELECT * FROM mytable

125
WHERE mycol1 > 100
AND mycol2 = 'hello world'
AND mycol3 IS NOT NULL;

Note that the phrases "IS NULL" and "IS NOT NULL" are special ways to check if a
particular column contains a NULL value, as distinct from having an empty value (e.g. the
empty string "")

Also note that single quotes are used around strings in SQL, and a single equals sign is used
to test equality.

LIKE operator

You can use the LIKE operator to do pattern matching. Within a pattern, you can use an
underscore (_) to match exactly one character, and a percent sign (%) to match zero or more
characters. For example:

SELECT * FROM mytable


WHERE mycol1 LIKE 'SM_TH%';

This pattern will match SMITH, SMYTH, SMITHSON, SMYTHE, etc. Any single character
can be placed between the M and T, and zero or more characters may follow the H.

Built-in Functions

You can apply an aggregate function to a column - e.g. counting the number of rows:

SELECT COUNT(*) FROM mytable


WHERE mycol1 > 100;

Here is a different function - maximum value in a column. There are lots of functions
available.

SELECT MAX(mycol1) FROM mytable;

Sorting

You can sort the result by a particular column:

126
SELECT mycol1, mycol2 FROM mytable
ORDER BY mycol2;

Here is more complex sorting. Sort by "mycol2" in descending order followed by "mycol1"
in ascending order (the default):

SELECT mycol1, mycol2 FROM mytable


ORDER BY mycol2 DESCENDING, mycol1;

Joining tables

If you want a single query to retrieve data that is in multiple tables, you can join the tables.
To join two tables you list both table names in the FROM clause, and you include (at least)
one join condition in the WHERE clause. A standard join condition should specify that a
column in one table equals a different column in another table.

For example, consider the following example tables and SQL query.

Table: PERSON Table: ORDERS

PersonID Surname Firstname OrderID PersonID OrderValue

1 Brookes Wayne 1 2 $99.99

2 Johnson Chris

SELECT person.surname, orders.ordervalue


FROM person, orders
WHERE orders.personid = person.personid;

This query would return one row, with the values "Johnson", "$99.99".

Note that the join condition is used to specify on which column the two tables should be
joined.

127
Subqueries

Sometimes you want to test membership in a set of values. For example, using the example
tables above, you might want a list of the names of all customers who have placed an order:

SELECT surname, firstname


FROM person
WHERE personid IN (
SELECT personid
FROM orders
);

The subquery is the one in parentheses. You can negate the condition if you want to see a list
of all customers who have not placed an order. Note that the subquery stays the same, just the
IN operator becomes NOT IN:

SELECT surname, firstname


FROM person
WHERE personid NOT IN (
SELECT personid
FROM orders
);

The subquery should return only one column of data.

SQL CREATE/DROP statements


Basic table creation

General format:

CREATE TABLE table-name (


col-name-1 data-type-1,
col-name-2 data-type-2,
col-name-3 data-type-3
);

For example:

128
CREATE TABLE mytable1 (
mycol1 VARCHAR(20),
mycol2 NUMBER(4,2),
mycol3 DATE
);

If a column is not allowed to contain NULL values, you can specify that it should be NOT
NULL. If the data in a column must be guaranteed to uniquely identify rows within the table,
you can declare it as a PRIMARY KEY. For example:

CREATE TABLE mytable1 (


name VARCHAR(20) PRIMARY KEY,
height NUMBER(4,2),
dateofbirth DATE NOT NULL
);

To remove a table definition, and all the data in it, use the DROP statement. Note: you will
receive no warning, and no second chance!

DROP TABLE mytable1;

SQL INSERT/DELETE statements

The INSERT/DELETE statements are for adding and deleting rows in an existing table.

Inserting rows

General format:

INSERT INTO table-name


VALUES ( col-1-value, col-2-value, col-3-value );

An example:

INSERT INTO table-name


VALUES (

129
'Wayne',
123,
TO_DATE('2001-01-01', 'YYYY-MM-DD'),
NULL
);

Notes on data types:

• Strings are enclosed in single quotes


• Numbers are not enclosed by any characters
• Dates need to be converted from strings into the DATE type using the Oracle TO_DATE()
function
• A null value for a column can be specified with the keyword NULL (no quotes)

Deleting rows

The syntax of the SQL DELETE statement is quite similar to the SELECT statement, except
no column-list is used.

You can delete all data in a table as follows:

DELETE FROM mytable1;

You can selectively delete rows by adding a WHERE clause, with the same syntax as for a
SELECT, e.g.:

DELETE FROM mytable1


WHERE mycol1 LIKE '%ayn%';

SQL UPDATE statements

The SQL UPDATE statement is for updating existing data within a table.

General format:

UPDATE table-name
SET column-name = value
WHERE condition-list;

Here's a simple example - update the orders table and set every row to have the OrderValue
set to 10.

130
UPDATE orders
SET ordervalue = 10;

The next example only updates certain rows in the table - not all of them. To do this, a
WHERE clause is used, with the same syntax as for an SQL SELECT.

UPDATE orders
SET ordervalue = 10
WHERE personid > 99;

You can update multiple columns at once if you need to, e.g.:

UPDATE orders
SET ordervalue = 10, personid = 0
WHERE personid > 99;

Module: RMI
Lab exercise - RMI client/server application

131
This lab exercise shows you how to create a simple RMI application in a non-J2EE context.

Level of Difficulty: 1 (easy)


Estimated time: 45 minutes
Pre-requisites:

• Run 'wlenv' to set your environment correctly

Overview of RMI

RMI is Java's Remote Method Invocation. It allows objects in different Java Virtual
Machines to communicate, by allowing one object to invoke a method on another object that
is remotely located. Typically these objects are executing on different machines, but not
necessarily. RMI is Java's implementation of Remote Procedure Call (RPC), a well-
established computing paradigm for building distributed applications.

RMI is a client/server protocol. In a J2EE setting, RMI may be used in a number of places:

• a servlet calling a method on an EJB


• one EJB calling a method on another EJB
• a (non-web) Java client calling a method on an EJB

This exercise demonstrates none of these. While RMI can be (and is) used in J2EE
applications, it can also be used by non-J2EE applications that wish to communicate. For
now, we will use "pure" RMI, not in a J2EE context.

Development Process

Because RMI uses a client/server architecture, you need to create both a client program and a
server program. Because there are many steps in developing a pure RMI application, it is
important to follow the correct sequence of steps, as outlined below.

1. Define the remote interface.


The "remote interface" is where you decide what kind of service(s) your server is
going to offer to its clients. The remote interface is a Java interface that defines a set
of method signatures that the server will implement, and that the clients can call. The
remote interface is shared by both clients and the server.
2. Implement the RMI server.
This is a Java class that implements all the methods you defined in your remote interface.
This is where you write the code for what the server is going to do.
3. Generate RMI skeletons and stubs.
RMI has a special pre-processor that will automatically generate some of the low-level
communications code for you. The autogenerated code is called stubs (for the client's part)
and skeletons (for the server's part).
4. Implement an RMI server registration class.
The class you created above when you implemented the RMI server only implements the

132
business logic methods. You also need a class to actually make your server run (i.e. one you
can execute from the command line - with a main() method). This is the server registration.
5. Implement an RMI client.
The final step is to implement a client class that will connect to your server.

Creating a simple RMI application

Step 1 - Define the remote interface

The remote interface is a Java interface declaration, containing a list of methods (signature
only) that you want your clients to be able to invoke.

Create and compile the following Java source file.

/**
The remote interface - both the client and the
server share a common view of this interface.
*/

import java.rmi.*;

public interface HelloWorld extends Remote {

String sayit() throws RemoteException;

Points to notice:

• Clients will only be able to invoke one method on the server - the method is called
sayit(), and it takes no arguments and returns a String.
• The interface extends Remote (java.rmi.Remote). All remote interfaces must do this.
• The method declares that it may throw a RemoteException. All methods in a remote
interface must declare this. A RemoteException may be thrown by the underlying
infrastructure if anything goes wrong with the communication between the client and
server.
• Although it is not clearly shown here, both the parameters and the return type of
remote methods must be Java classes that implement the java.io.Serializable interface.

Step 2 - Implement the remote methods

This is the server-side class that implements the remote interface. It must provide public
method implementations for all methods defined in the remote interface. The server class
may define other methods, but only the ones listed in the remote interface can be invoked
over the network by clients.

133
Create and compile the following Java source file.

/**
Class that implements the RMI server
*/

import java.rmi.*;
import java.rmi.server.UnicastRemoteObject;

public class HelloWorldImpl extends UnicastRemoteObject


implements HelloWorld {

// Implementation must have an explicit constructor


// in order to declare the RemoteException exception
public HelloWorldImpl() throws RemoteException {
super();
}

// Method implementation
public String sayit() throws RemoteException {
System.out.println("Got another request - returning result!");
return ("Hello World!");
}

Points to notice:

• The class name has "Impl" appended to its name to indicate that this is the server
implementation. This is a commonly used naming convention.
• The class extends UnicastRemoteObject. This is standard for a server that you will
start up manually from the command-line (as opposed to one that is started
automatically on demand, which is slightly more complex).
• The class implements HelloWorld. i.e. it implements the remote interface, which
implies all of the Java semantics associated with the "implements" keyword.
• We must declare a default constructor (i.e. one with no arguments) even if you don't
need to do anything special, because the constructor method must declare the
possibility of throwing a RemoteException. An RemoteException might be thrown by the
underlying RMI support library, not by your code itself.
• In the implementation of our remote method - sayit() - we do two things. The
System.out.println statement will cause the server to print a message in its window (on
the server machine). The return statement will return a String message back to the
client's machine.

Step 3 - Generate the RMI skeletons and stubs

After you have compiled both the remote interface and the implementation class, you can use
a tool to automatically generate some of the low-level code that deals with network
communication. These are called stubs (client-side) and skeletons (server-side).

134
From the command prompt, run the following command from the build directory ie: where
the compiled classes are located.

rmic HelloWorldImpl

rmic stands for "RMI compiler". Notice that you specify the name of the implementation class
(without any file extension).

After running this command, you will notice some extra files have been generated.

Note that the build directory in the Eclipse workshop lab is in the project/build/classes

Step 4 - Write an RMI server registration class

Notice that in the implementation class above, there is no main() method. So how do you run
it? The answer is that you don't.

The next task is to create a Java class whose purpose is to start the server running. When you
go to run your RMI server, it is this class that you execute.

Create and compile the following Java source file.

/**
This is the server registration class.
It has a main method (command-line application)
and creates a server instance and registers it
with the RMI registry.
*/

import java.rmi.Naming;

public class HelloWorldServer {

public static void main (String [] args) {


try {
// create instance of remote object
System.out.println("Creating instance of server object ...");
HelloWorld hw = new HelloWorldImpl();

// bind remote object to naming service


System.out.println("Registering object with the RMI registry ...");
Naming.rebind("rmi://localhost:1099/HelloWorldService", hw);
System.out.println("Registered!");
}
catch (Exception e) {
e.printStackTrace();
}
}
}

Points to notice:

• The registration class as a main() method. It is a Java application.

135
• It creates an instance of the server implementation class (called "hw").
• It registers the instance ("hw") with a name service, and assigns it a human-readable
name ("HelloWorldService").

So far we haven't mentioned a name service. The idea is that when a client starts
executing, it needs to know how to find where the server is. One way would be to
hard-code the server's location into the client's code, but this is not very flexible. You
could have the client read the server's location out of a configuration file, but this is
not very dynamic (if the server moves to a different machine, someone has to update
the configuration file).

A name service maps from simple, text-based, human-readable names into Java
remote object references (i.e. a reference to a Java object running on a remote server).
When a server starts executing, it advertises itself on the name service. When a client
starts up, it queries the name service to find out where the server is. This way the
client only has to know how to contact the name service, and from there it can find all
different kinds of servers.

• Exceptions must be handled (try...catch). When you call Naming.rebind(), a number of


different exceptions may be thrown - MalformedURLException, RemoteException,
AccessException. In this example, we catch all of them at once and just print out a
message. Obviously in a real application you would want some better error handling!

Step 5 - Implement an RMI client

Finally, it's time to implement the client application. This could be a GUI client, but to keep it
simple, we will just use a command-line client application.

Create and compile the following Java source file.

/**
The RMI client which looks up the object
in the name server, retrieves a reference
and invokes the sayit() method.
*/

import java.rmi.Naming;

public class HelloWorldClient {

public static void main (String [] args) {


try {
System.out.println("Looking up service in RMI registry ...");
HelloWorld hw_obj = (HelloWorld) Naming.lookup(
"rmi://localhost:1099/HelloWorldService");
System.out.println("Calling remote method ...");
String hw_text = hw_obj.sayit();
System.out.println(hw_text);
}
catch (Exception e) {

136
e.printStackTrace();
}
}
}

Points to note:

• When we do a lookup operation on the name service, we pass in a human-readable


name (disguised as part of a URL), and what we get back is a Java object reference
that we can store in a variable (hw_obj).
• The type of hw_obj is HelloWorld - i.e. the remote interface. The remote interface
contains information that is shared by both the server and client.
• We can then call the sayit() method on the hw_obj object. Notice that it looks just like a
local method call.
• Exceptions must be handled in the client application as well. In particular, if
something goes wrong with the communication, the client may have to handle a
RemoteException.

Running the HelloWorld example

As well as needing to run the RMI client and the RMI server, you also need to execute the
name service - the "RMI registry". The registry needs to be run first, then the server, and
finally the client.

Running the RMI registry

The RMI registry is a simple name service that comes supplied with the J2SE SDK.

Rmiregistry MUST be able to locate the interface and implementation and stub/skeleton class
files. This means that you should either modify your CLASSPATH to include the compiled
classes directory and/or change the current directory to the classes directory.
(You may have to also add . into your classpath for this to work)

Assuming your CLASSPATH is set correctly, you can run it by typing:

rmiregistry &

rmiregistry will listen at port 1099. You can change this by specifying the port number as an
argument to rmiregistry.

Note that you can only run ONE copy of rmiregistry per port. This is why setting the
CLASSPATH is a better solution.

Running your server

Remember that you run the server registration class, not the server implementation class.

137
Run the server registration class:

java HelloWorldServer

Running your client

In this example, we will run the client and server on the same machine for simplicity.
However they will be running in separate Java Virtual Machines, which is the key point.

Open a new window, set your environment correctly, and run the client:

java HelloWorldClient

True distribution

In theory, you can run the RMI registry, the server and the client all on different machines.
However, note the following:

• Both the server registration and the client have the hostname of the RMI registry hard-
coded. If you run the registry on a different machine, you need to adjust the code to
the new location.
• The server needs access to the Java classes for the remote interface, the server
implementation class, the server registration class and the auto-generated skeleton
classes.
• The client needs access to the Java classes for the remote interface, the client
implementation class and the auto-generated stub classes.
• The RMI registry needs access to the Java class for the remote interface.

Next step ...

Now that you have followed a step-by-step walkthrough, the next step is to be a bit more
independent.

Modify the example above to include a new remote method that will add together two
integers (i.e. it takes two integer arguments, and returns an integer result).

This will involve changing the remote interface, and then re-running all the subsequent steps.

138
Module: JNDI
Lab exercise - overview

The laboratory exercise for this module is to query an LDAP server and display a set of
attributes from a directory.

Level of Difficulty: 1 (easy)


Estimated time: 20 minutes
Pre-requisites:

• none

139
About LDAP and directory structures

Basically Lightweight Directory Access Protocol (LDAP) is a generic method of accessing


directory style information eg: address books but can be used for other purposes too, such as
Microsoft Active Directory manages all shared objects and security information in a
Microsoft Domain.

An LDAP-style directory is a hierarchical tree of objects, where the root of the tree normally
is what's called a "Base DN" (Base Distinguished Name)

Each entry in the tree:

• Is an instance of one or more ObjectClasses (such as Person)


• Has some attributes. Each attribute has a name and a data type (eg: string, number etc)
• Has a unique identifier called a Distinguished Name (dn). Often this is a concatenation of
attributes such as uid (userid), organisation etc.

All of these ObjectClasses and Attributes are defined in a schema. Luckily there are standards
which define some standards for directories such as X.500 compatible address books (which
the vast majority of LDAP servers support).

Be aware that an LDAP server can manage many independent tree's, each with different Base
DN's.

Security and LDAP

LDAP directories are also often used for Authentication. UTS uses a common single signon
for email, library access, workstation access etc.

To do this you need to 'bind' to the directory server with your userid and password. We can't
do this in our lab since this access is restricted but normally you would pass your own
"distinguished name" and password to LDAP to authenticate your password.

By default, we will use 'anonymous' access.

Accessing an LDAP Directory from the command line

We don't have any LDAP searching tools on the Linux workstations, so you will need to
logon to charlie for this exercise

You can search for a person using the UTS staff directory. To do this, we will use the
following command

ldapsearch -h host -p port -b base_dn -s scope filter attributes

The parameters are:

host the hostname of the LDAP server

140
port the TCPIP port - defaults to 389

the "top of the tree" ie: where to start the search from. You must have this option, there is
base_dn no default.
The UTS staff directory base_dn is: o=UTS

one of: base, one, sub. Base means only at the top level, one means only 1 level down to
scope search, sub means all subcontexts ("subdirectories"). You can leave this out since this
defaults to sub

This is the search string. It should meet RFC2254 syntax. eg:


(cn=christopher wong) would search for the "Common Name"="christopher wong"
(sn-=wong) would search for "Surname"=wong
(sn=*wong*) would search for "Surname" containing "wong"

The valid operators are:

= equal
>= bigger than (including alphabetic order eg: c > b)
<= less than
~= approximately equal (soundex search so sn~=wong would also return wang,
filter
wing, etc)

You can have logical "and" "or" and "not" filters by prefixing these criteria with a
& | ! character. eg:

(& (sn=wong)(givenName=christopher) ) --> returns all christoper wong's


(| (sn=wong)(sn=brookes)) --> returns all wong's & brookes's
(& (sn=wong) (! (givenName=christopher) ) ) --> returns all wong's except those
whose given names is christopher

The hard part is getting the bracketing correct....


This is a list of what attributes to return. The default is to return all.

rfc2256 has a huge list of what attributes are available. Common ones to use are:
attributes
cn (common name), dn (distinguished name ie: primary key), sn (surname),
givenName, initials, title, description, o (organisation), ou (organisation unit),
objectClass, c (country code), street, telephoneNumber

Example search

ldapsearch -h ldap.uts.edu.au -b o=UTS '(sn=wong)'

Try do a search for a person by "Common Name" ie: the cn attribute. See if you can find your
tutor's name in it.

141
How about restrict the attributes to just sn, givenName, telephoneNumber, mail ?

A good tutorial about LDAP can be found at http://edutechwiki.unige.ch/en/LDAP and


Introduction to LDAP (SAGE) http://quark.humbug.org.au/publications/ldap/ldap_tut.html

Module: JNDI
Lab exercise - LDAP programming

The laboratory exercise for this module is to query an LDAP server and display a set of
attributes from a directory.

Level of Difficulty: 1 (easy)


Estimated time: 45 minutes
Pre-requisites:

• LDAP Overview lab

142
• Run 'wlenv' to set your environment correctly

An example first

The following Java source code is for a complete JNDI application that queries the main UTS
LDAP server (which holds details of all UTS staff). It is a standalone Java application to be
compiled and run from the command line.

Try it out. Compile it for yourself and run it by typing:

java JNDITest brookes

Then study the source code to understand how it works. Use this as a basis for the exercise
below.
(note: to do this under eclipse, you need to run the class with a parameter ie:
Use Run As -> Run.
Then select JNDITest as the Main Class, and on the (x=) Arguments tab, enter the Program
Argument as brookes)

Source code:

• JNDITest.java

Accessing an LDAP Directory from a web application

Write a set of web application components (JSPs and/or servlets) that allow the user to
display all the LDAP attributes for a person in the LDAP directory shown below. The user
should be able to search based on the person's name ("cn" attribute).

To do this, you should create a DirContext and then perform a search operation on it.

The LDAP directory to use is shown below:

Host name: ldap.uts.edu.au


Port: 389
Base DN: o=UTS

No username or password is required (anonymous login).

143
Module: JNDI
Tutorial - Looking up Weblogic LDAP

Weblogic has an embedded LDAP server which provides 2 services

1. A naming services for objects such as data sources and EJB's


2. A directory service for the security domains, such as the default admin userid

Viewing internal LDAP objects

• Go to the Weblogic console:


• Choose Environment -> servers & select AdminServer
• Click on the "View JNDI Tree"

This will pop up a new window showing the existing JNDI objects. Notice that your
thinOracleDataSource should appear here.

Clicking on this would result in viewing the details such as the Binding Name
(thinOracleDataSource), the actual class name (something like
weblogic.jdbc.common.internal.rmiDataSource) and a ToString representation

The neat thing about LDAP and JNDI is that you can bind any serializable Java object to the
directory, so in theory, you could bind stuff like java.lang.String 's into the directory & so on.

Setting up Weblogic LDAP for external access

Normally Weblogic is setup not to allow external access to the embedded LDAP directory
server - there is a randomly generated bind password and anonymous bind is turned off.

We will change this to allow anonymous access.

• To allow this, go into the weblogic console, Lock & Edit

144
• Go to Domain (ie: weblogic) -> Security tab -> Embedded LDAP.
• In the Credential field, enter a new admin password (eg: weblogic) & confirm
• Also select Anonymous Bind Allowed ** (not recommended for security reasons)
• You will have to restart the Weblogic server to update these changes

See managing the Embedded LDAP server


(http://edocs.beasys.com/wls/docs100/secmanage/ldap.html) for information

Using the Weblogic Embedded LDAP directory server

Now you can use the weblogic embedded LDAP directory to view users in myrealm

The parameters you need to use for LDAP are:

• hostname: your weblogic server (if you are running this from charlie, you need to
know your workstation host name)
• port: 7001
• base dn: dc=domain (where domain is your weblogic domain). In our labs this is:
dc=weblogic
• bind DN: cn=Admin (this is the -D option on ldapsearch)
• password: weblogic (you get prompted for this in ldapsearch. You could use the -w
option to hard code this)

eg:

ldapsearch -h workstation.it.uts.edu.au -p 7001 -D cn=Admin -w weblogic -b dc=weblogic


(cn=weblogic)

would return details about the user called weblogic

You could also use the same information when you write JNDI Java programs.

Just set the JNDI environment hashes Context.SECURITY_PRINCIPAL to "cn=Admin" &


Context.SECURITY_CREDENTIALS to "weblogic" (or whatever your password is)

If you are using a jndi.properties file to hold this, the property keys are:

java.naming.security.principal=cn=Admin
java.naming.security.credentials=weblogic

145
Module: EJB
Lab exercise - Stateless Session Bean - Manual technique

In this lab exercise, we create your first Enterprise JavaBean. It will be a stateless session
bean.

Level of Difficulty: 2 (moderately easy)


Estimated time: 60 minutes
Pre-requisites:

• Run wlenv to set your environment correctly


• Start your WebLogic server running in the background

Overview of EJB

146
Enterprise JavaBeans implement the business logic of a J2EE application. Each EJB, or
"bean", is a component, i.e. it is treated as a single, logical entity that presents a public
interface defining its methods that can be accessed.

EJBs are deployed into an application server (in this context, also known as an "EJB
container"). In our case, this is WebLogic. Note that WebLogic contains both a web server
(for servlets/JSPs) and an application server (for EJBs). Logically they are separate, even
though they are implemented in the same product. An application server contains a collection
of EJBs. The application server provides a lot of support for the EJBs that it hosts.

There are different kinds of EJBs. These are discussed in more detail in the lecture, but for
now suffice to say that in this exercise we will be creating an EJB Session Bean. A session
bean is a transient kind of EJB that is created when a client requests it, and is destroyed when
the client is finished (i.e. it lasts for one "session"). To be more specific, we will be creating a
Stateless Session Bean, which means that during a single session with a client, the bean does
not maintain any internal state information.

The basic model of a stateless session bean is that it is a component with a set of public
business-logic methods, and the methods are all independent of each other. One method
should not rely upon any other method having previously been called.

In this example, the client of our EJB will be a servlet (the presentation tier calling methods
on the business-logic tier).

Development Process

Just as there were many steps in developing an RMI application, there are also many steps in
developing and deploying an EJB. It is important to follow the correct sequence of steps, as
outlined below.

1. Create the Remote interface.


The "Remote interface" is where you decide what kind of service(s) your EJB is going
to offer to its clients. The remote interface is a Java interface that defines a set of
method signatures that the EJB will implement, and that the clients can call. The
remote interface defines your business logic methods. The remote interface is shared
by both clients and the EJB implementation.
2. Create the Home interface.
We have already seen the Remote interface which contains business logic methods. The
"Home interface" of an EJB session bean contains methods for creating a new instance of the
bean. Clients first obtain a reference to a bean's home interface, and from the home interface,
can create one or more instances of the bean itself.
3. Create the EJB implementation class.
Naturally you need to create a Java class which provides the implementation of your
business-logic methods (and some others, as we will see).
4. Write the EJB deployment descriptor.
Recall how web applications (in a WAR file) required an XML deployment descriptor? EJBs
also require a deployment descriptor, that provides instructions to the EJB container as to how
the EJB should be deployed.

147
5. Package the EJB into a JAR file.
Web applications are packaged in WAR files. EJBs are packaged in JAR files. They are
basically the same concept.
6. Generate stubs and skeletons.
Next we use an "EJB compiler" tool that will take the JAR file created in the previous step,
and will generate stubs and skeletons for the EJB, and will also compile all the Java source
code. The EJB compiler will also check the syntax of your XML deployment descriptor. This
is quite similar to running "rmic" (the RMI compiler) to generate stubs and skeletons when
creating pure RMI applications, except now it is a different tool.
7. Deploy the EJB into an application server.
The JAR file containing your EJB must be deployed before it can be invoked, in the same
way as WAR files must be deployed before your servlets/JSPs can be invoked.
8. Create an EJB client - a servlet.
You cannot directly run your EJB and see results immediately. First you need to create a
client program that will invoke the business-logic methods on the EJB, and display some
results. In this exercise, we will create a servlet as our EJB client, but note that the client
could be a servlet, a JSP, a standalone Java application, or even another EJB.
9. Copy EJB stubs + home/remote interface classes to the WEB-INF/classes directory of
your WAR file.
Recall that in RMI, the client needed access to the Java classes for the interface and the stubs.
The same is true for EJB - an EJB client must have access to these classes. In the case of a
servlet client, that means we need to copy some of the EJB's class files into the servlet's WAR
file.
10. Create the WAR file and deploy.
This step is just the normal process of packaging and deploying a Java servlet.

Creating an EJB stateless session bean

Step 0 (Optional)- Using Eclipse/Workshop

You can use Eclipse to create the following files.

1. To do so, create a new EJB Project.


2. Create a new -> project -> , select Show All Wizards, type in EJB in the filter text & select
EJB Project
3. Change the configuration from Weblogic EJB Project Facets to Custom & enter a project
name
4. When in the Project Facets wizard, ensure Weblogic EJB Extension is not selected.

Step 1 - Create the Remote interface

The Remote interface is a Java interface declaration, containing a list of methods (signature
only) that you want your clients to be able to invoke.

Create and compile the following Java source file.

package myapp;
import java.rmi.*;
import javax.ejb.*;

public interface HelloWorld extends EJBObject {

148
public String hello(String name) throws RemoteException;
}

Points to notice:

• Clients will only be able to invoke one method on the server - the method is called
hello(), and it takes 1 string argument and returns a String.
• The interface extends EJBObject (javax.ejb.EJBObject). All EJB remote interfaces must
do this.
• The method declares that it may throw a RemoteException. All methods in a remote
interface must declare this. A RemoteException may be thrown by the underlying
infrastructure if anything goes wrong with the communication between the client and
server. This is the same as for RMI.
• Although it is not clearly shown here, both the parameters and the return type of
remote methods must be Java classes that implement the java.io.Serializable interface.

Step 2 - Create the Home interface

The Home interface is also a Java interface declaration, containing a list of methods
(signature only) that your clients can invoke. However the home interface has a special
function. Before clients can access the business-logic methods of your EJB (i.e. the ones
defined on the Remote interface), they must first obtain a Home interface, and from the
Home interface, create an instance of the EJB. Every EJB must have both a Home and a
Remote interface.

Create and compile the following Java source file.

package myapp;
import java.rmi.*;
import javax.ejb.*;

public interface HelloWorldHome extends EJBHome {


public HelloWorld create ()
throws RemoteException, CreateException;
}

Points to notice:

• To create an instance of the EJB, clients will call a method named create() that takes no
arguments, and returns an object whose type is that of the Remote interface.
• You could define more than one create method if you wish, as long as each one you
define takes a different set of arguments.
• The interface extends EJBHome (javax.ejb.EJBHome). All EJB home interfaces must
do this.
• The method declares that it may throw a RemoteException and/or a CreateException. All
"create" methods in a home interface must declare this. Either of these exceptions
may be thrown by the underlying infrastructure if anything goes wrong during the
creating of the EJB.

149
Step 3 - Create the EJB implementation class

This is the class that actually implements the EJB methods. It must provide public method
implementations for all methods defined in the Remote interface. It must also implement all
the create methods defined on the Home interface (except they are renamed slightly to
ejbCreate()). The EJB implementation class may define other methods, but only the ones listed
in the remote interface can be invoked over the network by clients.

Create and compile the following Java source file. If using Eclipse, you don't need to compile
as this is done automatically.

package myapp;
import javax.ejb.*;

public class HelloWorldBean


implements SessionBean {

SessionContext sessionContext;

// SessionBean methods
public void setSessionContext (SessionContext sc) {
this.sessionContext = sc;
}

// Argument list must match create() method


// in HelloWorldHome interface
public void ejbCreate() { }

public void ejbRemove() { }

public void ejbActivate() { }

public void ejbPassivate() { }

// Now our business logic methods


public String hello(String name) {
return ("Hello, " + name);
}

Points to notice:

• The class implements SessionBean (javax.ejb.SessionBean). All EJB session beans must
do this. Notice though that this class does not implement the Remote interface we
defined earlier. This is different to an RMI implementation class.
• The methods in the bean can be divided into two kinds:
o standard session bean methods
these include setSessionContext(), plus all the methods whose names start with ejb
(ejbCreate(), ejbRemove(), ejbActivate(), ejbPassivate()). These methods are defined
by the javax.ejb.SessionBean interface.

150
o business logic methods
these are the methods you you defined in your Remote interface. In this
example there is only one.
• The EJB container (e.g. application server, i.e. WebLogic) will pass to us a
SessionContext object. We store that object in case we later want to access some
facilities of the EJB container itself.

Step 4 - Write the EJB deployment descriptor

Just like packaged web applications (WAR files) needed a deployment descriptor, so too do
packaged EJBs. In fact, EJBs will need two deployment descriptors.

One is a J2EE standard deployment descriptor that will be the same regardless of which
application server you use (WebLogic, WebSphere, JBoss, etc). This one goes in a file called
ejb-jar.xml.

The other is a container-specific deployment descriptor - its syntax will be different


depending on which product you use to deploy your EJB. This one goes in a file called
weblogic-ejb-jar.xml.

EJB deployment descriptors are placed into a subdirectory called META-INF. Note that this is
different to the directory name you used for WAR files (which was WEB-INF).

Create the following file as ejb-jar.xml in a subdirectory called META-INF.

<?xml version="1.0"?>
<ejb-jar version="2.1"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd">
<enterprise-beans>
<session>
<ejb-name>HelloWorld</ejb-name>
<home>myapp.HelloWorldHome</home>
<remote>myapp.HelloWorld</remote>
<ejb-class>myapp.HelloWorldBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>HelloWorld</ejb-name>
<method-intf>Remote</method-intf>
<method-name>*</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
</assembly-descriptor>
</ejb-jar>

151
Secondly, create the following file as weblogic-ejb-jar.xml in the same META-INF directory as
your other deployment descriptor.

<?xml version="1.0"?>

<!DOCTYPE weblogic-ejb-jar PUBLIC


"-//BEA Systems, Inc.//DTD WebLogic 8.1.0 EJB//EN"
"http://www.bea.com/servers/wls810/dtd/weblogic-ejb-jar.dtd">

<weblogic-ejb-jar>
<weblogic-enterprise-bean>
<ejb-name>HelloWorld</ejb-name>

<stateless-session-descriptor>
<pool>
<max-beans-in-free-pool>100</max-beans-in-free-pool>
</pool>
</stateless-session-descriptor>

<jndi-name>ejb/HelloWorld</jndi-name>
</weblogic-enterprise-bean>
</weblogic-ejb-jar>

Step 5 - Package the EJB into a JAR file

EJBs are packaged in JAR files, which are created using the jar command. The syntax is
exactly the same as when you created WAR files.

If running Eclipse, you can do the following steps by using the Right Mouse Button ->
Export -> EJB Jar file option.

Before creating the JAR file, check that the files are in the correct directories. There is one
directory for the Java package that the classes are in, and the other directory is META-INF.

/myapp
- HelloWorld.class
- HelloWorld.java
- HelloWorldHome.class
- HelloWorldHome.java
- HelloWorldBean.class
- HelloWorldBean.java
/ META-INF
- ejb-jar.xml
- weblogic-ejb-jar.xml

Run the jar command from this directory as follows:

jar cf ../HelloEJB.jar *

152
Step 6 - Generate stubs and skeletons

With RMI, you have to run a tool that generates stubs and skeletons for the RMI application.
For EJB you also have to run a tool that generates stubs and skeletons, however it is a
different tool.

WebLogic uses a tool called appc. This tool takes either a JAR or EAR file as input. The
syntax is as follows.

cd ..
java weblogic.appc HelloEJB.jar

If you have errors in your JAR file (for example, incorrect directory structure, invalid syntax
in the deployment descriptor), appc will usually alert you.

Step 7 - Deploy the EJB into an application server

The process of deploying an EJB is identical to deploying a web application. You just copy
the JAR file into the "applications" subdirectory of your WebLogic installation.

cp HelloEJB.jar ~/weblogic/autodeploy

Watch the WebLogic server window to see if there were any errors during deployment.

If the EJB was deployed successfully, you will find its name will appear in the JNDI tree of
your WebLogic server. Open a management console, and go to "Servers", "myserver", then
move to the "Monitoring" tab and choose "View JNDI tree". Your EJB name should appear
with a purple dot next to it. This indicates that your EJB is advertising itself in the name
service as being available to clients.

Step 8 - Copy EJB stubs + home/remote interface classes to the WEB-INF/classes directory of your
WAR file

Just as with RMI, the "client" (in this case a servlet) needs access to the stub files generated
by ejbc.

Because the client is packaged separately from the EJB, the stubs need to be manually copied
from the ejbc-generated output into the servlet's WAR file.

Change directory into the WEB-INF/classes directory of your WAR file, and run the following
JAR command that will extract the contents of the EJB JAR file into the WEB-INF/classes
directory. This will make sure the compiled stubs and compiled home/remote interfaces are
available to the client. Note that it will also make other, unnecessary, classes available to the
client, but we ignore those now for simplicity.

cd WEB-INF/classes

153
jar xvf /mypath/HelloEJB.jar

You will need to change /mypath/ to represent the directory path of where you have placed
your EJB JAR file.

! ALTERNATIVELY could just just copy the entire jar file into the WEB-INF/lib directory

Step 9 - Create an EJB client - a servlet

Here we will use a Java servlet as the client to our EJB. You should create your WAR file
directory structure in a different place to where you created the JAR file for your EJB. The
WAR file and the JAR file are completely independent.

Create and compile the following Java source file.

import myapp.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import javax.naming.*;
import javax.rmi.PortableRemoteObject;
import java.util.*;

public class HelloWorldServlet extends HttpServlet {

public void doGet (HttpServletRequest req, HttpServletResponse res)


throws ServletException, IOException {

res.setContentType("text/plain");
PrintWriter out = res.getWriter();
out.println("----------------------------------------");

try {
Context ctx = new InitialContext();
out.println("Got context");
HelloWorldHome hwsh;

Object ref = ctx.lookup("ejb/HelloWorld");


hwsh = (HelloWorldHome) PortableRemoteObject.narrow(
ref, HelloWorldHome.class);

out.println("Got home interface");

HelloWorld hws = hwsh.create();


out.println("Created EJB");

out.println(hws.hello("chris"));
}
catch (Exception e) {
e.printStackTrace(out);
}
out.println("----------------------------------------");
}
}

154
Remember that the compiled servlet class must go in the WEB-INF/classes subdirectory.

Also note that the servlet will not compile unless you have the directory "." (which means the
current directory) in your CLASSPATH. The WebLogic setEnv.sh script does not
automatically put "." in your CLASSPATH, so you may have to add it manually if you have
not already. In a text editor, open the file ~/weblogic/bin/setDomainEnv.sh, and search for the line
that starts "CLASSPATH=...". In this line, add "." to the list of directories.

You could also equally place the EJB lookup & execution code (basically the entire try-
catch block!) into a scriptlet in a JSP.

This way you do not have to compile the servlet.

Regarding the servlet code itself, notice the sequence of operations for the client:

1. Create an InitialContext so we can look up a name service, to find the EJB. No


parameters are supplied when we create the InitialContext so we will use the name
service supplied by the container (WebLogic), which is what we want in this case.
2. Look up the "JNDI name" of the EJB. Recall that when you created the EJB, you
specified its JNDI name in the weblogic-ejb-jar.xml deployment descriptor. That is the
name that we use here to perform the lookup. If the lookup is successful, we will be
returned with a Java object of type HelloWorldHome - i.e. the EJB's Home interface.
3. Now that we have a reference to the Home interface, we can call the create() method
which will give us a reference to the EJB itself (i.e. its Remote interface).
4. Finally, now that we have a reference to the EJB's Remote interface, we can call
business logic methods of the EJB as defined on the Remote interface (in this case the
method hello()).

This may seem a slightly strange process. Just remember that first we obtain a reference to
the EJB's Home interface, and from that we create an instance of the EJB which returns an
instance of the EJB's Remote interface.

Step 10 - Create the WAR file and deploy

Now that you have created your servlet, and copied the stubs and interfaces so they are
accessible to the servlet, you can create the WAR file for the servlet, and deploy it to
WebLogic.

The process is the same as you have used for creating and deploying WAR files in the past.

Note that you will need to create a web.xml file in the WEB-INF directory for the servlet. There
is nothing special about this web.xml file - it will be the same as you have created before.

To deploy your WAR file, copy it to the "autodeploy" subdirectory of your WebLogic
installation.

155
Running the HelloWorld EJB example

To test your application, open a web browser window, and enter the URL of your servlet into
the Location field. If all goes well, your servlet will execute, and will make a remote method
call to the EJB that is executing in the application server.

Next step ...

Now that you have followed a step-by-step walkthrough, the next step is to be a bit more
independent.

Modify the example above to include a new remote method that will add together two
integers (i.e. it takes two integer arguments, and returns an integer result).

This will involve changing the remote interface, and then re-running all the subsequent steps.

Module: EJB
Lab exercise - Using Eclipse + Xdoclet to generate EJB

In this lab exercise, you will use Eclipse + Xdoclet to create an Enterprise JavaBean.

Level of Difficulty: 2 (moderately easy)


Estimated time: 60 minutes
Pre-requisites:

• Run wlenv to set your environment correctly


• Start your WebLogic server running in the background

Rapid code development

One of the biggest complaints about Enterprise JavaBeans as implemented by the J2EE
specification is the complexity of generating what seems like fairly straight forward business
component development.

156
This issue resulted in the development of competing frameworks such as Spring MVC,
Object-Relational Mapping systems such as Hibernate and Java Data Objects, where
developers bypass the whole EJB infrastructure entirely.

Sun recognised this by creating 2 new standards - the Java Persistence API (which front ends
ORM systems such as Hibernate) and the EJB 3.0 specification (which uses Java 5
annotations to 'tag' classes and methods as Enterprise Java Beans)

Using EJB 3.0 would be a simpler technique than using EJB 2.1, however, this is not
implemented in the J2EE 1.4 specification and is a fundamental part of Java Enterprise
Edition 5.

Most Java application servers &/or tooling are not yet fully certified at the Java EE 5 spec, so
we will concentrate on EJB 2.1 coding.

One technique similar to EJB 3.0 is to use Java 5 annotations or Javadoc-style annotations in
our code and let code generators create most of the tedious steps required to generate EJB's.

In our environment, there are 2 main ways to do this

1. Use the proprietary WebLogic workshop "ejbgen" tool.

2. Use the open source (and popular) Xdoclet tool

Using Weblogic Workshop EJBgen

See the tutorial called "Using EJBGen"

Using Eclipse & XDoclet

Xdoclet ( http://xdoclet.sourceforge.net ) is an open source product designed to remove most


of the tedium when developing EJB's.

The original product was called ejbdoclet but this tool is now generic and supports many
other technologies such as Servlets, Hibernate, Spring & so on and has large support for
major Application server vendors such as IBM and BEA WebLogic.

XDoclet is designed to be run using Apache ANT, a Java 'make' tool. You normally create a
build.xml file with various XDoclet specific 'tasks'.

You then create Plain Old Java Object (POJO) classes which implement the business logic.
You don't need to create tonnes of extra class files and deployment descriptors, everything is
in one source file!!

Using Eclipse Web Tools Project reduces the workload significantly further by providing
templates and wizards to generate more code.

Use the following steps to re-create the previous stateless session bean lab.

157
Step 1: Create the project and settings for Xdoclet development

Create a new EJB project by: new -> select Show All Wizards, , type EJB in the filter text &
select EJB Project

In the New EJB Project wizard: enter project name (HelloEJB), & change Configurations
(EJB Project with XDoclet)

158
[Next]
On the Project Facets wizard, ensure EJBDoclet (Xdoclet) selected & version 1.2.3 (use
dropdown on 1.2.3 to get this)

159
[FINISH]

You now need to set up the project's XDoclet settings

From the project menu, Right Mouse Button -> Properties -> Xdoclet -> ejbdoclet ->
select weblogic

160
This will ensure that the Xdoclet generator will execute the weblogic specific tasks. Note that
if you are using, say, JBoss, you would also select the JBoss task to generate the JBoss
specific deployment descriptors.

Step 2 - Create a new Session Bean

First step is to create a package. Use New -> Package & call the package myapp

To create a new EJB, select:

New -> Xdoclet Enterprise JavaBean


(or you may have to use New -> Other -> EJB -> Xdoclet Enterprise JavaBean)

If you get a message "Annotation provider definition is not valid", please select the
preferences link

161
You will need to set up Xdoclet provider preferences:

• Make sure Enable xdoclet builder is checked.


• Xdoclet Home: /pub/ajpcpe/xdoclet,
• Select version: 1.2.3

You will also have to check the XDoclet settings AGAIN! (this is a known bug in the
XDoclet wizard)

• Expand the Xdoclet menu on the left & select the ejbdoclet preferences.
• Ensure the Weblogic task is ticked (you can also select other tasks if you are using non-
weblogic application servers such as JBoss)

162
Once you do this step, you should not have to do this again for any further Enterprise Java
Bean creation.

Creating the bean

After the previous setup set has been completed, you should be back to Create Enterprise
Java Bean wizard.

• Ensure Session Bean is selected & press [NEXT]

• Select or enter a package name eg: myapp


Add a class name eg: HelloBean.
Leave superclass as Object. & press [NEXT]

• The next window will display some more parameters for the EJB.
Adjust EJB name, description, & display name as necessary.
** IMPORTANT ** Make the JNDI name ejb/Hello
(you could leave this as the default, but the standard is to have the ejb beans
under the ejb subcontext)
Leave State Type = Stateless &
Transaction Type: Container
Press [FINISH] to build your EJB

163
You should then see the HelloBean.java file in the code editor and some messages in the
console about Xdoclet.

It runs through various stages such as Init, Ejbdoclet. This is actually generating all the class
files and deployment descriptors.

Note: if you don't see the "Running <weblogic/>" Generating weblogic-ejb-jar.xml


message, you have failed to follow the Weblogic task setup above.

Step 3: Enhancing the Enterprise JavaBean

f you look in the ejbModule folder of your EJB project, you should see in the myapp package
the following files

Hello.java REMOTE interface Hello EJBObject = declarations

HelloBean.java IMPLEMENTATION SessionBean + business methods

HelloHome.java HOME interface EJBHome

HelloLocal.java LOCAL interface EJBLocalObject = declarations

HelloLocalHome.java LOCALHOME interface EJBLocalHome

HelloUtil.java Utility class helper class eg: getHome()

We will only change HelloBean.java. Everything else is Generated!!

To add business methods, edit the HelloBean source file class with the business method like
in the session bean lab.

Look for the automatically generated method called foo

Notice that there is a special javadoc tag in front called @ejn.interface-method view-
type="remote"

/**
*
* <!-- begin-xdoclet-definition -->
* @ejb.interface-method view-type="remote"
* <!-- end-xdoclet-definition -->
* @generated
*
* //TODO: Must provide implementation for bean method stub
*/
public String foo(String param) {
return null;
}

164
These tags are what XDoclet uses to generate code with. By default, this means XDoclet will
generate a declaration of this method (foo()) in the Remote interface.

If you change the view-type from remote to both then XDoclet will generate the business
method into both the remote and local interfaces.

For our exercise, let's change this method to the same as the stateless session lab:

/**
*
* <!-- begin-xdoclet-definition -->
* @ejb.interface-method view-type="both"
* <!-- end-xdoclet-definition -->
* @generated
*
*/
public String hello(String name) {
return ("Hello, " + name);
}

Notice that when you change any code in this file, XDoclet will automatically re-build the
files.

To stop this behaviour, you need to click on the main toolbar, select Project & de-select Build
Automatically.
However, be careful, since you will need to build manually if you don't build automatically.
Do this via the RMB -> Run XDoclet command.

Step 4: Deploy the bean

There are 4 main ways to do this (assuming the server is running)

• (1) From Workshop, right click on the Server (BEA Weblogic Server v10.0 @ localhost) in
the Servers view and click
"add and remove projects". You then choose the EJB and select Add & [finish]
This deploys the bean on the server

• (2) You can Export the bean to a Jar file. Select the EJB project, RMB -> Export -> Export
as EJB Jar file.
Copy the resultant JAR file into the weblogic/autodeploy directory

• (3) From the weblogic console, use the [Lock & Edit] & choose Deployment -> Install
option to upload the JAR file from step 2.

• (4) You can create an EAR project file which has project dependencies on it (containing the
lab Web project & the EJB project)
You then use step 1 to add the EAR project to weblogic -OR- use Export -> Export as EAR
file.
This EAR file can then be deployed by copying to the weblogic/autodeploy directory or via
the Weblogic console Deployments - install option

Step 5: Creating the client:

165
This is pretty much the same steps as the Stateless Session Bean lab.

Let's use a JSP to test this EJB.

You need to create a JSP into an existing Dynamic Web project with the following code in it.

<%@page import="myapp.*, javax.naming.*, javax.rmi.*" %>

<%
Context ctx = new InitialContext();
String jndi_name = "ejb/Hello";
out.println("Got context");
HelloHome hwsh;
out.println("Looking for JNDI name " + jndi_name);
Object ref = ctx.lookup(jndi_name);
hwsh = (HelloHome) PortableRemoteObject.narrow(
ref, HelloHome.class);

out.println("Got home interface");

Hello hws = hwsh.create();


out.println("Created EJB");

out.println(hws.hello("mate"));
%>

A Better way - using the XDoclet xxxutil class

XDoclet generates a utility class called bean_nameUtil.java to make your life easier. This
provides a method called getHome() which replaces all the context lookups etc.

This code implements a "Service Locator" pattern and can even cache the bean lookups to
make your code very efficient.

<%
HelloHome h = HelloUtil.getHome();
Hello bean = h.create();
out.println(bean.hello("mate"));
%>

A lot simpler eh?

Your client code will need to have access to the myapp.Hello & myapp.HelloHome classes.

You have 2 options:

(1) copy the EJB jar file exported earlier (helloEJB.jar) to WebContent->WEB-INF->lib
(The problem with this solution is that you need to update the jar whenever you change the
EJB)

(2) Set your Dynamic Web Project to have a "J2EE Dependency".


You select your Web project (eg: lab) & RMB-> Properties, J2EE Modules Dependencies
-> Select (helloejb) Jar module]

166
This will result in the .jar file being placed into the WEB-INF/lib directory at deployment
time automatically!!

Note: Normally you only need the Hello, HelloHome (& helloUtil) (& maybe the
HelloLocal* equivalents) classes,
but we will be lazy and import the whole lot.

Step 6: Running the client

Run as usual. (select the web project , RMB -> Run As -> Run on Server).

Normally most changes will get automatically deployed, as long as there is a dependency
between the web project and the EJB project.

Note: when you look at the web project on the server view, you now see a + symbol next to
the web project.
Expanding this shows the EJB bean jar

Problems you may encounter

You may need to re-deploy the EJB if you make any changes to the signatures of the bean
methods or add new beans into the EJB project.

Sometimes you Workshop does not correctly re-deploy changes into the dependent J2EE
projects (such as your Web project).

To fix this, re-do step 4 above.

Next step ...

Now that you have followed a step-by-step walkthrough, the next step is to be a bit more
independent.

Modify the example above to include a new remote method that will add together two
integers (i.e. it takes two integer arguments, and returns an integer result).

This will involve changing the remote interface, and then re-running all the subsequent steps.

167
Module: EJB
Lab exercise - CMP Entity Bean- manually

In this lab exercise, we create an Entity EJB that uses Container Managed Persistence (CMP).

Level of Difficulty: 4 (moderately difficult)


Estimated time: 90 minutes
Pre-requisites:

• Run 'wlenv' to set your environment correctly


• Start your WebLogic server running in the background
• Completed Stateless Session Bean exercise

Overview of Entity Beans

In the last exercise, you successfully created a stateless session bean. Recall that session
beans are transient beans created to perform some task on behalf of a client. However the
goal of this exercise is to create an entity bean. Entity beans represent data in the application.

Each instance of an entity bean corresponds to an individual instance of an entity. So for


example, if your application has an entity bean called 'Person', and your application knows
about 2 people, Mary and Joe, you will have two instances of the Person entity bean.

Entity beans must be persistent. That means that an entity bean must survive even if the
application server is shut down or crashes. This implies that the data associated with an entity
bean must be stored permanently, either in a database, or in a file on disk, or using some
other form of persistent storage.

Commonly, entity beans map to database records. In a simple example, one entity bean
corresponds to one row in a relational database table.

There are two ways to implement the persistence requirement of entity beans. One way is to
use a relational database for the persistent storage of entity data, and let the container
(application server) manage the mapping between attributes in your entity bean and columns
in the database table. This is called Container Managed Persistence (CMP). The other
alternative is to write the Java code to save and load the entity bean data yourself. This is
called Bean Managed Persistence (BMP).

CMP is easier to implement (less code to write), but it can only be used in very simple cases.
BMP is the more general kind of entity bean, but requires more programming effort.

Also note that we will focus entirely on EJB 2.0. Many books and examples on the web may
use EJB 1.1. One of the main areas of difference between these versions of the EJB standard
is the handling of CMP entity beans. Be careful that you only follow instructions for EJB 2.0!

168
Development Process

The development process for an entity bean is almost identical to that of creating a session
bean. The steps are listed below as a reminder, and the differences between session and entity
beans noted.

1. Create the Remote interface.


2. Create the Home interface.
Provide a create() method if you want users to be able to create new entities (add a new row to
the database). Provide a remove() method if you want users to be able to permanently remove
entities (delete a row from the database). Provide one or more findXXX() methods, including
the mandatory findByPrimaryKey() method.
3. Create the EJB implementation class.
You will need to declare abstract get/set methods for each of the CMP fields your bean will
use.
4. Write the EJB deployment descriptor.
In addition to the ejb-jar.xml and weblogic-ejb-jar.xml deployment descriptors, you will also
need to create a third deployment descriptor file for a CMP bean, typically called weblogic-
cmp-rdbms-jar.xml.
5. Package the EJB into a JAR file.
6. Generate stubs and skeletons.
7. Deploy the EJB into an application server.
8. Create an EJB client for testing - a session bean.
Servlets/JSPs should not invoke methods on an entity bean directly, but rather should access
entities via session beans. This means that the client of an entity bean should always be a
session bean.

Creating an EJB CMP Entity bean

Step 0 - Check your database table

This example assumes that you have an Oracle database table called addressbook as described
in the earlier JDBC exercises. If you do not have this table, you will need to create it before
continuing.

Step 1 - Create the Remote interface

Create and compile the following Java source file.

package addressbook;
import java.rmi.*;
import javax.ejb.*;

public interface Person extends EJBObject {

169
String summary() throws RemoteException;
}

Points to notice:

• Here we define one business logic method in addition to the methods that will be used
to access the fields of the addressbook (name, address, etc).

Step 2 - Create the Home interface

Create and compile the following Java source file.

package addressbook;
import java.rmi.*;
import javax.ejb.*;
import java.util.Collection;

public interface PersonHome extends EJBHome {


public Person create (String name, String address,
String email, String extn,
String birthday)
throws RemoteException, CreateException;

public Person findByPrimaryKey (String name)


throws RemoteException, FinderException;

public Collection findByEmail (String email)


throws RemoteException, FinderException;
}

Points to notice:

• We allow clients to create new addressbook entries, but we do not allow them to
delete any entries (there is no remove() method defined).
• We allow clients to search for a person in two ways: by name (the primary key), in
which case the finder method returns an instance of the Person object, or by email, in
which case the finder method returns a java.util.Collection of primary keys that represent
the records that match the search criteria.

Step 3 - Create the EJB implementation class

Create and compile the following Java source file.

package addressbook;
import javax.ejb.*;

public abstract class PersonBean


implements EntityBean {

private EntityContext entityContext;

170
// EntityBean methods
public void setEntityContext (EntityContext ec) {
this.entityContext = ec;
}

public void unsetEntityContext () {


this.entityContext = null;
}

// Argument list must match create() method


// in PersonHome interface
public String ejbCreate(String name, String address,
String email, String extn, String birthday)
throws CreateException
{
setName(name);
setAddress(address);
setEmail(email);
setExtn(extn);
setBirthday(birthday);
return null;
}

public void ejbPostCreate(String name, String address,


String email, String extn, String birthday)
throws CreateException
{}

public void ejbRemove() throws RemoveException { }

public void ejbActivate() { }

public void ejbPassivate() { }

public void ejbLoad() { }

public void ejbStore() { }

// Now the abstract methods for CMP fields


abstract public String getName();
abstract public void setName(String name);

abstract public String getAddress();


abstract public void setAddress(String address);

abstract public String getEmail();


abstract public void setEmail(String email);

abstract public String getExtn();


abstract public void setExtn(String extn);

abstract public String getBirthday();


abstract public void setBirthday(String birthday);

// Now our business logic methods


public String summary() {

171
String result = getName() + " " + getExtn() + "\n";
return (result);
}

Points to notice:

• The class implements EntityBean, not SessionBean.


• The class has methods setEntityContext() and unsetEntityContext().
• The parameter list of ejbCreate() must match the parameter list defined in the Home
interface.
• The ejbCreate() method returns the type of the primary key, but when it actually returns
at the end of the function, it returns a null value. Note that the type is different to what
is returned by the create() method in the Home interface (the one that the client calls).
The create() method on the home interface returns the type of the EJB remote interface
(i.e. the EJB type). It seems strange that ejbCreate() returns a different type of value to
create(), but it is the correct way to do it, according to the EJB specification!
• There is now a method called ejbPostCreate() with the same parameter list. ejbPostCreate()
is called by the container after the successful creation of a new entity bean.
• There are abstract method declarations for each of the CMP fields.
• The whole class itself is also declared abstract because of the abstract methods.

Step 4 - Write the EJB deployment descriptor

Now there are three deployment descriptors.

Create the following file as ejb-jar.xml in a subdirectory called META-INF.

<?xml version="1.0"?>

<!DOCTYPE ejb-jar PUBLIC


"-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN"
"http://java.sun.com/dtd/ejb-jar_2_0.dtd">

<ejb-jar>
<enterprise-beans>
<entity>
<ejb-name>Person</ejb-name>
<home>addressbook.PersonHome</home>
<remote>addressbook.Person</remote>
<ejb-class>addressbook.PersonBean</ejb-class>
<persistence-type>Container</persistence-type>
<prim-key-class>java.lang.String</prim-key-class>
<reentrant>False</reentrant>
<cmp-version>2.x</cmp-version>
<abstract-schema-name>PersonBean</abstract-schema-name>
<cmp-field>
<field-name>name</field-name>
</cmp-field>
<cmp-field>
<field-name>address</field-name>
</cmp-field>

172
<cmp-field>
<field-name>email</field-name>
</cmp-field>
<cmp-field>
<field-name>extn</field-name>
</cmp-field>
<cmp-field>
<field-name>birthday</field-name>
</cmp-field>
<primkey-field>name</primkey-field>
<query>
<query-method>
<method-name>findByEmail</method-name>
<method-params>
<method-param>java.lang.String</method-param>
</method-params>
</query-method>
<ejb-ql>
<![CDATA[SELECT OBJECT(p) FROM PersonBean AS p
WHERE p.email = ?1]]>
</ejb-ql>
</query>
</entity>
</enterprise-beans>
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>Person</ejb-name>
<method-intf>Remote</method-intf>
<method-name>*</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
</assembly-descriptor>
</ejb-jar>

Secondly, create the following file as weblogic-ejb-jar.xml in the same META-INF directory as
your other deployment descriptor.

<?xml version="1.0"?>

<!DOCTYPE weblogic-ejb-jar PUBLIC


"-//BEA Systems, Inc.//DTD WebLogic 6.0.0 EJB//EN"
"http://www.bea.com/servers/wls600/dtd/weblogic-ejb-jar.dtd" >

<weblogic-ejb-jar>

<weblogic-enterprise-bean>
<ejb-name>Person</ejb-name>

<entity-descriptor>
<entity-cache>
<max-beans-in-cache>1000</max-beans-in-cache>
</entity-cache>

<persistence>
<persistence-type>
<type-identifier>WebLogic_CMP_RDBMS</type-identifier>

173
<type-version>6.0</type-version>
<type-storage>
META-INF/weblogic-cmp-rdbms-jar.xml
</type-storage>
</persistence-type>
<persistence-use>
<type-identifier>WebLogic_CMP_RDBMS</type-identifier>
<type-version>6.0</type-version>
</persistence-use>
</persistence>

</entity-descriptor>

<jndi-name>ejb/Person</jndi-name>

</weblogic-enterprise-bean>

</weblogic-ejb-jar>

Finally, create the following file as weblogic-cmp-rdbms-jar.xml in the same META-INF directory
as your other deployment descriptors.

<?xml version="1.0"?>

<!DOCTYPE weblogic-rdbms-jar PUBLIC


'-//BEA Systems, Inc.//DTD WebLogic 6.0.0 EJB RDBMS Persistence//EN'
'http://www.bea.com/servers/wls600/dtd/weblogic-rdbms20-persistence-600.dtd'>
<weblogic-rdbms-jar>
<weblogic-rdbms-bean>
<ejb-name>Person</ejb-name>
<data-source-name>thinOracleDataSource</data-source-name>
<table-name>addressbook</table-name>

<field-map>
<cmp-field>name</cmp-field>
<dbms-column>name</dbms-column>
</field-map>
<field-map>
<cmp-field>address</cmp-field>
<dbms-column>address</dbms-column>
</field-map>
<field-map>
<cmp-field>email</cmp-field>
<dbms-column>email</dbms-column>
</field-map>
<field-map>
<cmp-field>extn</cmp-field>
<dbms-column>extn</dbms-column>
</field-map>
<field-map>
<cmp-field>birthday</cmp-field>
<dbms-column>birthday</dbms-column>
</field-map>

</weblogic-rdbms-bean>
</weblogic-rdbms-jar>

Also notice that this XML file refers to details relating to the database. In particular, the table
name, and the field names.

174
It also refers to the Data Source that the EJB should use for connecting. The XML file above
assumes that you already have a data source created in your WebLogic management console
called thinOracleDataSource. If you do not already have this data source, you must create it
before trying to deploy or use this EJB.

Remainder ...

The remainder of the steps are the same as for creating a stateless session bean.

Before you attempt to deploy your Person EJB, be sure to use the WebLogic management
console to set up a JDBC Data Source, and associated Connection Pool. Refer to the JDBC
notes to recall how.

For now, you can use a servlet as a test client for the entity bean (although in a real
application, servlets generally would not call an entity bean directly). If you reuse your
servlet from the stateless session bean exercise, you will need to change the following points:

• the import statement, to specify the correct package name;


• the class names;
• the JNDI name to look up - it should match the JNDI name specified in the weblogic-
ejb-jar.xml file;
• the home interface method used to get a reference to the EJB. In a session bean, the
client calls the create() method. In an entity bean, the client probably needs to call the
findByPrimaryKey() method with the right type of argument, or another "finder" method.
Recall that with entity beans, calling create() will actually add a row to the database;
• the business logic method (the remote interface method).

Refer to the course notes, the EJB 2.0 specification from Sun Microsystems, and the API
documentation for assistance.

Module: EJB
175
Lab exercise - CMP Entity Bean-using Eclipse + XDoclet

In this lab exercise, we create an Entity EJB that uses Container Managed Persistence (CMP).

Level of Difficulty: 4 (moderately difficult)


Estimated time: 90 minutes
Pre-requisites:

• Run 'wlenv' to set your environment correctly


• Start your WebLogic server running in the background
• Completed Stateless Session Bean exercise
• Complete the Entity Bean exercise

Entity Beans using XDoclet

Unlike the previous exercise, we will use Eclipse WTP and XDoclet to generate most of the
code you need to write an entity bean. Even though XDoclet can make writing Entity beans
easier, it is still a tedious process to write and annotate a JavaBean which represents your
table row.

Development Process

The good news for using rapid development tools is that Eclipse can read your database
tables and generate an appropriate xxxBean class with most of the common attributes and
annotations pre-set for you.

Once we have our xxxBean class generated, we then tailor the class to modify the datasource
name, add getData() if you want to use the XDoclet generated value objects, add business
methods, add finders and any other customisations that might be needed.

Creating an EJB CMP Entity bean


Check your database table

This example assumes that you have an Oracle database table called addressbook as described
in the earlier JDBC exercises. If you do not have this table, you will need to create it before
continuing.

Creating the Container Managed Bean

Assuming we are using the existing EJB project, create a new bean by using New -> EJB ->
Xdoclet Enterprise Bean

* Select Container Managed Bean


[Next]

* Select the package (myapp), & name "AddressBookBean"


[Next]

176
* On the CMP Entity Bean wizard, change the name of the generated Schema from
AddressBookSCHEMA to AddressBook & you can choose "usecase:" Import Attributes
from table (or you can "Define new Attributes" if you want to do the next part by hand!).
(leave the default for the moment)

* Now choose the JDBC Connection that you set up in the Oracle Lab. This would have been
called "ell"
[Next]

* Assuming that you can connect (or reconnect if prompted with your Oracle userid and
password), you can choose the
your addressbook table in the CMP Attributes Wizard in the following Step

* Select the dropdown in the Table field. You will need to type in your fully qualified table
name (normally your oracleuserid.addressbook) to get the correct table name. (I think there is
a bug in Eclipse WTP 1.5 which lists ALL the tables in the oracle database, hence the need to
filter it down to your own schema)

177
This should result in the list of columns you defined in the JDBC lab, eg:

[FINISH] when complete.

* Note that XDoclet will run and will create many files, hopefully including the weblogic-
ejb-jar.xml & weblogic-cmp-rdbms-jar.xml deployment descriptors. If these don't appear,
you should check your XDoclet preferences to ensure that weblogic was selected as a
checked task.

The files generated should be:

AddressBook.java (remote Interface)


AddressBookBean.java (The main IMPLEMENTATION)
AddressBookCMP.java
AddressBookData.java (a Data Transfer/value object/javabean)
AddressBookHome.java (home interface)
AddressBookLocal.java
AddressBookLocalHome.java
AddressBookUtil.java (utility classes - in particular, getHome() )

You will need to edit the AddressBookBean.java file to change the various Xdoclet attributes.

For weblogic deployments, you need to change the line with:

178
* @weblogic.data-source-name ${data.source.name}
* <!-- end-xdoclet-definition -->
* @generated

to

* @weblogic.data-source-name thinOracleDataSource
*
* @generated

When you save, this should automatically restart xdoclet.

Just to check, edit the META-INF/weblogic-cmp-rdbms-jar.xml file to see the data-source-


name is thinkOracleDataSource and that the correct table name is there.

Look at the generated code.

• Note that AddressBook is just like an ordinary JavaBean with getters/setters for the properties
of an addressbook bean

• AddressBookBean is similar, except for bean management methods such as ejbCreate(),


ejbLoad(), ejbRemove(), ejbStore() & so on.
Note that the generator has created a @ejb.finder called findAll() which basically dumps the
whole table!

• AddressBookCMP extends AddressBookBean and adds the method getData(), which is used
to obtain the AddressBookData value object.

• AddressBookData is just a plain old Javabean. However, note that there are 2 methods
generated for you - equals() and hashCode(). These are useful if you have a Collection of
AddressBookData (especially Sets) or just want to compare beans by content (rather than by
reference!)

• AddressBookHome & AddressBookLocalHome classes contain the methods used to find


beans such as findByPrimaryKey() & findAll() as well as the usual create() method.

• Finally, AddressBookUtil contains utility methods, of which only the getHome() &
getLocalHome() methods are useful.

• You can update AddressBookBean to add any extra business methods you wish. Xdoclet will
automatically run when you save these edits.

Creating a custom ejbCreate() method.

* When editing AddressBookBean you will notice that there is a TODO task on the
ejbCreate() method code.

* It is highly recommended that you COPY this entire create method by adding parameters to
populate the fields & leave the default null ejbCreate() method alone.

* Add the following code AFTER the existing ejbCreate() method.


Note that it is ESSENTIAL to keep the comments in the right spot (ie: before the Javadoc
comment before ejbPostCreate()

179
/**
*
* <!-- begin-user-doc -->
* The ejbCreate method.
* <!-- end-user-doc -->
*
* <!-- begin-xdoclet-definition -->
* @ejb.create-method
* <!-- end-xdoclet-definition -->
* @generated
*/
public java.lang.String ejbCreate(
String name,
String address,
String email,
java.math.BigDecimal extn,
java.sql.Date birthday
) throws javax.ejb.CreateException {
// begin-user-code
setName(name);
setAddress(address);
setEmail(email);
setExtn(extn);
setBirthday(birthday);
// EJB 2.0 spec says return null for CMP ejbCreate methods.
return null;
// end-user-code
}

You could optionally also create yet another ejbCreate() method passing an
AddressBookData object as the parameter (since this is the Value Object representing
AddressBook objects).

This is necessary since when you create an entity bean, you are actually performing an
INSERT into TABLE VALUES(... ).

Since you need to have the values populated before you can insert into the table, you have to
somehow pass the values to the ejbCreate() method!!!!

Creating Other methods in AddressBookBean

You can also add business methods like you did with the Session bean to AddressBean.
However, these should be closely related to the purpose of the Entity Bean - related to the
business data!!!

Add the following to allow you to automatically obtain a JavaBean (AddressBookData)


which you can treat as a Data Transfer Object instead of passing tonnes of parameters to
various business methods.

/**
* Provides access to the generated getData() method of the generated
* CMP class.
* @ejb.interface-method
*/
public abstract AddressBookData getData();

180
A very useful debugging method to add is print()

/**
* print of a string version of the entity bean
* @ejb.interface-method view-type="both"
*
*/
public String print() {
return "Name=" + getName()
+ ",Address=" + getAddress()
+ ",Email=" + getEmail()
+ ",Extn=" + getExtn()
",Birthday=" + getBirthday();

* Xdoclet should automatically run and re-generate the java files & deployment descriptors.
If not, select EJB project & RMB -> Run Xdoclet

* Do note that AddressBook.java also lists these 2 methods - getData() & print().

* Finally, the AddressBookData.java bean does not list any of the business methods we just
defined (print()). This is because the sole purpose of AddressBookData is to encapsulate data,
not business logic. (do note that it does provide a toString() method, which looks very much
like our print() method!!)

Deploying it

Since you added this entity bean into the existing helloEJB lab, your bean will be
automatically deployed and updated when you run the lab web project. Otherwise, follow the
same instructions for session beans

* Note: when you update an EJB lab in Workshop, this is rebuilt but not automatically
redeployed dynamically. You need to use Run As -> Run on Server on the DEPENDENT
web project to force the redeployment.

* Note: If there are any problems deploying, sometimes it is best to select the server, RMB ->
Add and Remove Projects then to remove the EJB project, and re-add it

* Note: if you get a warning about "The web project build path contains classes or jars which
are not inside the standard <WebAppRoot>/WEB-INF/classes, you can safely ignore this
message since we are using Weblogic Shared Libraries.

Client code.

Your code will look similar to the session Bean exercise except now you can deal with the
create(), findByPrimaryKey() & findAll() methods

Here is a sample code which looks up a row in the table by primary key (the name field)

<h1>This searchs AddressBook CMP by name</h1>


<%

181
AddressBookHome h = AddressBookUtil.getHome();
AddressBook bean = h.findByPrimaryKey("chris"); // does a select
%>
<ol>
<li>Name=<%=bean.getName() %>
<li>Address=<%=bean.getAddress() %>
<li>Email=<%=bean.getEmail() %>
<li>Extn=<%=bean.getExtn() %>
<li>Birthday=<%=bean.getBirthday() %>
</ol>

It is not good practice to call the Entity bean directly to retrieve the table columns. The better
way is to use a Value Object - AddressBookData is appropriate and pre-generated for you.

So you should add AddressBookData ab = bean.getData(); & thence refer to this object
instead of bean (ie: ab.getName() ) etc.
AddressBookData is an ideal object to pass to your JSP and to save in your sessions as an
attribute. It can be accessed quite nicely via the JSL EL.

Here is a sample code which creates a new row in the database

<%
AddressBookHome h = AddressBookUtil.getHome();
try {
AddressBook bean = h.create("sam",
"Sydney",
"sam@uts.edu.au",
java.math.BigDecimal.valueOf(1234L),
java.sql.Date.valueOf("1990-07-01")
);
out.println("Bean created");
out.println("key=" + bean.getName());
} catch (Exception e) {
out.println("<b>ERROR: ");
out.println(e.getMessage()); // return to JSP
e.printStackTrace(); // debug to console
}

And here is a sample which lists all records in the database

<%
AddressBookHome h = AddressBookUtil.getHome();
AddressBook bean;
java.util.Collection list = h.findAll(); // does a select *
for (Object i : list) {
bean = (AddressBook) i;
%>
<ol>
<li>Name=<%=bean.getName() %>
<li>Address=<%=bean.getAddress() %>
<li>Email=<%=bean.getEmail() %>
<li>Extn=<%=bean.getExtn() %>
<li>Birthday=<%=bean.getBirthday() %>
</ol>
<%
}
%>

182
More things to do

You can add your own custom Finders, which will be automatically generated for you

Edit the AddressBookBean & locate the xdoclet comment that starts with @ejb.finder

You can create your own query by adding the following line after it

* @ejb.finder
* query="SELECT OBJECT(a) FROM AddressBook as a WHERE a.email like ?1"
* signature="java.util.Collection findByEmail(java.lang.String email)"
*

Deploy as usual. Create a JSP which uses the above method.

Facade patterns
It's best practice not to have entity beans called in a JSP. This is for both seperation of
concerns and the violation of the MVC pattern.

The better way is to have a Session bean acting as a facade in front of the entity bean. This
allows us to both unit test, seperate the database code from the presentation code and improve
efficiency.

The simplest way to do this is to just add code to the facade which invokes the entity bean!
(much like what you used for a servlet/jsp)

Here's an example.

In the earlier Session Bean EJB, create a new xdoclet method with the following signature

/**
*
* <!-- begin-xdoclet-definition -->
* @ejb.interface-method view-type="both"
* <!-- end-xdoclet-definition -->
* @generated
*
*/
public String facade(String param) {
try {
AddressBookHome h = AddressBookUtil.getHome();
AddressBook bean = h.findByPrimaryKey(param);
return bean.print();
} catch (Exception e){
return (e.getMessage());
}
}

I'm assuming that the session bean and entity bean are in the same EJB project here.

Then to call it just use the session bean as normal (ctx.lookup etc) but call bean.facade()
instead to invoke the entity bean via the session bean.

183
What's neat is that the JSP has no idea that they are calling a database lookup. The session
bean could actually just cache beans that have already been read.

An even better pattern is to use a "Business Delegate" pattern and hide the session bean from
the JSP as well. This is just a POJO which hides all references to EJB's (eg: caches the
lookup, etc) from the caller.

Essentially this is just moving any reference to JNDI, lookups,


PortableRemoteObject.narrow(), Home & Bean methods etc into a seperate class &/or
method...

What if the EJB's are in seperate projects?

You have to create EJB references in the session bean.

This normally exists in the ejb-jar.xml and weblogic-ejb-jar.xml files, but Xdoclet makes this
easy to setup.

Edit the sessionBean source code and use the @ejb.ejb-ref and @weblogic.ejb-reference-
description tags,
for example, in HelloBean.java:

* @ejb.ejb-ref
* ejb-name="AddressBook"
*
* @weblogic.ejb-reference-description
* jndi-name="ejb/AddressBook"
* ejb-ref-name="ejb/AddressBook"
*

This will update the ejb-jar.xml and weblogic-ejb-jar.xml deployment descriptor files with
the required references

Refer to the course notes, the EJB 2.0 specification from Sun Microsystems, and the API
documentation for assistance.

Module: EJB
Creating EAR files for deployment

An EAR file is an Enterprise Archive. It is used to deploy a whole enterprise application,


which may include web components (servlets, JSPs) and EJB components, in a single file.

• WAR files - contain web files (servlets, JSP, HTML, images, etc)
• JAR files - contain EJBs

184
• EAR files - contain embedded WAR and JAR files

Directory structure

Like any Java archive, a particular directory structure is necessary, and a new deployment
descriptor file - application.xml.

The correct directory structure for an EAR file would look like:

- MyEJBs.jar
- MyWebApp.war
/ META-INF
- application.xml

application.xml deployment descriptor

The application.xml deployment descriptor is not very complex. Basically, it defines:

• the names of the JAR and WAR files inside your application
• the root path of the web tree where your web application files should be placed under
• declaration of any security roles that are global to the whole application

An example is shown below:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE application PUBLIC


'-//Sun Microsystems, Inc.//DTD J2EE Application 1.2//EN'
'http://java.sun.com/j2ee/dtds/application_1_2.dtd'>

<application>
<display-name>Transactional Application Test</display-name>
<module>
<web>
<web-uri>MyWebApp.war</web-uri>
<context-root>mywebapp</context-root>
</web>
</module>
<module>
<ejb>MyEJBs.jar</ejb>
</module>
<security-role>
<role-name>supplier</role-name>
</security-role>
</application>

185
Notes about EAR files (and why they are good)

Imagine a simple application that contains one servlet (or JSP) in a WAR file and one
stateless session EJB in a JAR file. When you deploy these separately, recall that you had to
deploy the EJB first, and then take the stubs and skeleton files that were generated by
compiling the EJB, and include a copy of these stubs and skeletons in your WAR file, so the
servlet could access them. Obviously it is generally not desirable to have two copies of the
same files in two different places (WAR and JAR) if possible, but with separate deployment,
it was the only option.

One of the main advantages of deploying an application as an EAR file is that this
redundancy can be removed. When the application server deploys the EAR file, it extracts the
contents of the file, and deploys:

1. JAR files (EJBs) first


2. WAR files (web) second

but more importantly, it arranges the Java classloaders so that Java code contained in the
WAR file can access any of the Java class files contained in the JAR file.

So, you should create a JAR file for your EJB(s), and in this JAR file put in the EJB stubs and
skeletons and any other helper classes you may create. The WAR file now does not need to
contain any stubs and skeletons - it can remain "pure" and contain only web components.

Referencing EJBs that your components use

The other thing you should do when creating the deployment descriptors for your web apps
and EJBs is declare any EJB references that they make.

e.g. if your servlet/JSP calls an EJB session bean, in the web.xml deployment descriptor, it
should include an <ejb-ref> tag to declare this to the container.

e.g. if your EJB session bean calls an EJB entity bean, in the ejb-jar.xml deployment
descriptor, for your session bean you should include an <ejb-ref> tag to declare this to the
container.

As well as declaring the reference to the container (and to anyone else who may in future
reuse your EJBs), it allows you to remove the need for hard-coded JNDI names inside your
servlet/JSP/EJB code, when looking up an EJB's home interface.

Have a look at the use of the <ejb-ref> tags in the web.xml deployment descriptor in the
example below. Also notice the JNDI lookup code in the servlet, and that it now uses a name
which maps into the deployment descriptor, not a hard-coded JNDI name. The mapping from
the "java:comp/env/ejb/..." name into the actual JNDI name is specified in the weblogic.xml
deployment descriptor.

186
In addition, if you have two EJBs in the same JAR file, and one is calling the other, you
should use the <ejb-link> tag to indicate to the deployer that the EJB being called is actually
in the same JAR file, so the deployer make make some optimisations.

Example: servlet/JSP referencing an EJB

In your servlet/JSP file, the section of code which looks up the EJB is like:

// This is the servlet/JSP file


// Lookup the home interface
MyEJBHome ejbHome;
Object obj = ctx.lookup("java:comp/env/ejb/MyEJB");
ejbHome = (MyEJBHome)
javax.rmi.PortableRemoteObject.narrow(obj, MyEJBHome.class);

Notice that this lookup uses the name java:comp/env/ejb/MyEJB.

Then in the web.xml deployment descriptor in the WAR file, there should be a declaration of
the EJB reference as follows.

<!-- This is the web.xml file -->


<ejb-ref>
<ejb-ref-name>ejb/MyEJB</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<home>pkg.MySessionHome</home>
<remote>pkg.MySession</remote>
</ejb-ref>

Then in the weblogic.xml deployment descriptor in the WAR file, there should be a mapping
from the name by which the EJB is referenced in the Java source code
(java:comp/env/ejb/MyEJB) into the actual JNDI name that the bean is advertised as in the server.
In the example below, it assumes that the actual JNDI name of the EJB is "johns-ejb", and that
the name by which it is called in the servlet should be mapped into this JNDI name.

<!-- This is the weblogic.xml file -->


<reference-descriptor>
<ejb-reference-description>
<ejb-ref-name>ejb/MyEJB</ejb-ref-name>
<jndi-name>johns-ejb</jndi-name>
</ejb-reference-description>
</reference-descriptor>

Recall that the <jndi-name> of an EJB is configured in that EJB's weblogic-ejb-jar.xml file. In the
example above, the weblogic-ejb-jar.xml file would have the JNDI name configured as "johns-
ejb" even though the class names of the home and remote interface are MySessionHome.class and
MySession.class respectively.

187
Example: session bean referencing entity bean

The following example is similar to the one above, but demonstrates specifying an EJB
reference from one EJB (session bean) to another (entity bean).

First, in the session bean Java code, you would look up the entity bean's home interface as
follows:

// This is the session bean Java file


// Lookup the home interface
MyEntityHome ejbHome;
Object obj = ctx.lookup("java:comp/env/ejb/MyEntity");
ejbHome = (MyEntityHome)
javax.rmi.PortableRemoteObject.narrow(obj, MyEntityHome.class);

Then in the ejb-jar.xml file, you declare the beans. The declaration, including the reference,
might look as follows:

<!-- This is ejb-jar.xml -->


<enterprise-beans>
<session>
<ejb-name>MyFirstSessionBean</ejb-name>
<home>pkg.MySessionHome</home>
<remote>pkg.MySession</home>
<ejb-class>pkg.MySessionBean</ejb-class>
...
<ejb-ref>
<ejb-ref-name>ejb/MyEntity</ejb-ref-name>
<ejb-ref-type>Entity</ejb-ref-type>
<home>pkg.MyEntityHome</home>
<remote>pkg.MyEntity</remote>
<ejb-link>MyFirstEntityBean</ejb-link>
</ejb-ref>
</session>

<entity>
<ejb-name>MyFirstEntityBean</ejb-name>
<home>pkg.MyEntityHome</home>
<remote>pkg.MyEntity</remote>
<ejb-class>pkg.MyEntityBean</ejb-class>
...
</entity>
</enterprise-beans>

Note that this time an <ejb-link> is used which specifies the ejb-name of the bean that is being
linked to. This allows the container to recognise that the referenced bean is local, and make
some optimisations.

Finally, the weblogic-ejb-jar.xml file is used to map from the <ejb-ref-name> into the actual JNDI
name by which the beans are advertised.

<!-- This is the weblogic-ejb-jar.xml file -->


<weblogic-enterprise-bean>
<ejb-name>MyFirstSessionBean</ejb-name>
<reference-descriptor>
<ejb-reference-description>

188
<ejb-ref-name>ejb/MyEntity</ejb-ref-name>
<jndi-name>janes-entity-bean</jndi-name>
</ejb-reference-description>
</reference-descriptor>
<jndi-name>janes-session-bean</jndi-name>
</weblogic-enterprise-bean>

<weblogic-enterprise-bean>
<ejb-name>MyFirstEntityBean</ejb-name>
<jndi-name>janes-entity-bean</jndi-name>
</weblogic-enterprise-bean>

Steps in deploying a Java application with many parts


1. Compile your EJB code using javac, as normal

cd jar
javac mypackage/*.java

2. Create an EJB jar file, using the same jar syntax as normal

jar cvf ../ear/MyEJBs.jar *.*

3. Run the appc compiler on your EJB JAR file to generate the generated stubs and skeletons.

java weblogic.appc MyEJBs.jar

4. Compile your servlet. Note that because the servlet will make references to some of the
classes in the EJB, you may need to adjust your Java CLASSPATH while compiling so that
the compiler can access the EJB home and remote interface class files.

cd war/WEB-INF/classes
javac *.java

5. Create WAR file, as normal.

jar cvf ../ear/webapp.war *.*

6. Make sure the JAR file and WAR file end up in the correct directory structure to make an
EAR file, and that you have created your application.xml deployment descriptor. Then use the
'jar' command (same syntax) to create the EAR file.

jar cvf ../myapp.ear *.*

Using Eclipse to generate EAR files


Eclipse WTP/Workshop treats an EAR as a special type of Project - an Enterprise
Application Project.

189
You create a new Enterprise Application Project (New -> Project -> Enterprise Application
Project) and use the wizard to select the various projects (J2EE Modules :-) which will be
part of this EAR.

You can later add more by editing the EAR project properties (RMB -> Properties -> J2EE
Module Dependencies) and selecting ANY project in the current workspace, but also
internal/external JAR files!

You will notice that from now on, the component projects (war, ejb etc) will now have a new
subfolder called "Enterprise Application Libraries (ear)". This indicates the current projects
that depend on your component project.

You can directly deploy the EAR file (by adding the project to the server definition) or you
can Export the EAR file using RMB -> Export -> EAR file

One of the side effects of having an EJB project as part of an EAR is that you can now
generate EJB Client jar's - these are files that contain the interfaces & stubs which allow
ordinary Java clients (such as applets & AWT/SWING applications) to access the EJB.

An example EAR file

Extract the pieces of the following EAR file to get an idea of the directory structures to use,
etc.

190
Module: XML
Lab exercise - Parsing XML in a JSP

XML is the Extensible Markup Language. In this exercise, we create a JSP that reads in and
parses an XML file.

Level of Difficulty: 1 (easy)


Estimated time: 20 minutes
Pre-requisites:

• Run 'setEnv.sh' to set your environment correctly


• Start your WebLogic server running in the background

XML

XML is a language for describing structured information. It uses a tag-based syntax like
HTML. However, for XML to be useful, it is typically necessary to parse it, or convert it into
a different format. This exercise introduces XML parsing. There are three main kinds of
XML parsers: SAX, DOM and StAX.

• SAX stands for "Simple API for XML" and supports sequential parsing of XML documents.
The document is read in, and parsed in the order in which the tags appear. Each time a tag
starts or ends, an event is triggered. An application programmer writes a set of event handlers
to respond to these events from the parser.
• DOM stands for "Document Object Model" and when parsing an XML document, builds an
in-memory structured representation of the document. The whole document is read in at once,
and the DOM tree is created in memory as a Java data structure and can be navigated by
calling methods.
• StAX stands for "Streaming API for XML" and is capable of parsing and writing an XML
Document. This API is very resource efficient because it only reads parts of the XML
document into memory at once. This way it provides similar capabilities to DOM while
maintaining a similar performance to SAX.

In this exercise we use a SAX parser inside a JSP to read in and display an XML file.

Parsing an XML file with SAX

There are three main files required for this exercise: an XML file, a JSP, and a Java class
which handles the XML processing.

Before beginning, you should set up the directory structure for a WAR file.

XML file

191
The first step is to create the XML file that we will parse. Create the following file as
addressbook.xml.

<addressbook>

<entry id="1">
<name>Wayne</name>
<address>Room 4/130</address>
<email>brooks@it.uts.edu.au</email>
<phonextn>4469</phonextn>
<birthday>2001-01-01</birthday>
</entry>

<entry id="2">
<name>Maolin</name>
<address>Room 4/520</address>
<email>maolin@it.uts.edu.au</email>
<phonextn>1858</phonextn>
<birthday>2001-01-01</birthday>
</entry>

</addressbook>

JSP file

The next step is to create a JSP file called printout.jsp as shown below.

<%@ page import="javax.xml.parsers.*"%>


<%@ page import="org.xml.sax.*"%>
<%@ page import="javax.xml.parsers.*"%>
<%@ page import="org.xml.sax.helpers.DefaultHandler" %>

<H1>
Parsed XML document
</H1>

<%
InputStream is =
application.getResourceAsStream("/addressbook.xml");

try {
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setValidating(false);
SAXParser myParser = spf.newSAXParser();
DefaultHandler h = new handlers.MyHandler(out);
myParser.parse(is, h);
}
catch (Exception e) { }

%>

Notice that this JSP has no reference to the structure of the XML file, or what to do with it.
All the JSP is responsible for is opening an InputStream to access the XML file, and then

192
creating a SAX parser to read from the XML file.

The rules for how to process the XML file are contained in the handler class. In the example
above, this is the Java object h, and the class is handlers.MyHandler.

Also notice that the example says setValidating(false). This means that the parser will not
attempt to validate the XML document against a DTD. If we had requested a validating
parser, a DTD file would also be necessary to describe the format/rules of the XML
document.

Handler class

The final main section of code required is a Java class that will act as the handler for the SAX
parser. It is this file that determines what will happen to the XML.

Create the following file as WEB-INF/classes/handlers/MyHandler.java.

package handlers;

import org.xml.sax.*;
import javax.xml.parsers.*;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.helpers.DefaultHandler;

import javax.servlet.jsp.*;

public class MyHandler extends DefaultHandler {

JspWriter out;

public MyHandler(JspWriter out) {


this.out = out;
}

public void startDocument()


throws SAXException {
try {
out.println("<p>Start of document</p>\n<p>");
} catch (Exception e) { }
}

public void endDocument()


throws SAXException {
try {
out.println("</p>\n<p>End of document</p>");
} catch (Exception e) { }
}

public void startElement(String uri, String name,String qName, Attributes attrs)


throws SAXException {
}

public void endElement(String uri, String name, String qName)

193
throws SAXException {
try {
if (name.equals("entry")) {
out.println("</p><p>");
}
} catch (Exception e) { }
}

public void characters (char ch[], int start, int length)


throws SAXException {
try {
out.println(new String(ch, start, length) + "<BR/>");
} catch (Exception e) { }
}

public void processingInstruction(String target, String data) {


}

public void ignorableWhitespace(char ch[], int start, int length) {


}

Note that this handler class extends DefaultHandler. It has a number of methods that can be
implemented as event handlers. As the parser is parsing the XML document, it will trigger
events that will call your event handler methods.

You will need to compile this file. Change into the WEB-INF/classes directory, and compile the
file:

javac handlers/MyHandler.java

Packaging and deployment

The final step is to package and deploy the files as a web application (WAR file).

First, create a WEB-INF/web.xml file with no information, as follows.

<?xml version="1.0" ?>


<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 1.2//EN"
"http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
<web-app>
</web-app>

Then create the WAR file, and deploy it into WebLogic and test it by opening the JSP in your
browser.

Additional Exercise

194
This doesn't present a nice interface to the user. Modify the jsp and handler class to result the
results as a table.

Notes

It is never a good idea to embed HTML into a handler class. The best practice would be for
the handler class to populate a collection of javabeans which can then be presented via the
JSP.

Apache Commons Digester (http://jakarta.apache.org/commons/digester) is one example of a


popular java library to do this automatically. XMLBeans is another example.

195
Module: XML (DOM)
Lab exercise - Writing XML via DOM

DOM stands for "Document Object Model" and when parsing an XML document, builds an
in-memory structured representation of the document. The whole document is read in at once,
and the DOM tree is created in memory as a Java data structure and can be navigated by
calling methods. In this exercise we use a DOM parser inside a JSP to display an XML file.

Level of Difficulty: 3 (medium)


Estimated time: 45 minutes
Pre-requisites:

• Run 'setEnv.sh' to set your environment correctly


• Start your WebLogic server running in the background
• Completed the XML SAX JSP lab

Understanding the code

In the section below, we will walk through the code provided and give an explanation of what
is happening. Let's create a file called dom.jsp

<%@ page import="javax.xml.parsers.*" %>


<%@ page import="org.w3c.dom.*" %>
<%@ page import="java.io.*" %>

<html><head> <title>DOM Parser</title> </head>


<body>
<h1>XML DOM parser test</h1>
<hr />

• The java.xml.parsers package contains some basic methods for working with XML
parsers (either DOM or SAX).
• The second package, org.w3c.dom, contains DOM-specific objects and methods. There
is also a related package, org.w3c.sax that we will use in another exercise.

<%
// Create the stream we will read from
InputStream is =
application.getResourceAsStream("/addressbook.xml");
// Create an instance of the DOM parser and parse the document
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(is);

// Begin traversing the document

196
traverseTree(doc, out);
%>

This section of code is where we set up the DOM parser to parse the document. The steps
involved are:

1. Create a InputStream object that refers to the particular XML file we want to open.
getResourceAsStream() will read a file from our war file.
2. Get a reference to a DocumentBuilderFactory and a DocumentBuilder object. The need for
this step is because there are potentially many different implementations of DOM
parsers available. For example, the implementation that we will be using is called
Xerces, and is part of the Apache project. Another implementation of a DOM parser
comes from IBM.

From an application programmer perspective, you aren't usually interested in which


implementation of the DOM parser is being used. You just want to get access to
whichever DOM parser happens to be installed on the system you are using. The
DocumentBuilderFactory class provides a generic way of locating the "default" DOM
parser implementation that is installed on any system. When you call
DocumentBuilder.newInstance(), it returns a reference to some implementation of a DOM-
compliant parser. The DocumentBuilder object refers to the actual DOM parser itself.

3. Parse the XML file, by calling the parse() method on the DocumentBuilder object. With
DOM, whenever you call the parse() method, in return you get back a reference to a
Document object that is the starting point for the parsed DOM tree.

If there was a syntax error during parsing and the DOM tree could not be built, then a
Java exception would be thrown and an error message would appear in the browser.
This error message will look like the message generated when testing well-
formedness of XML documents in an earlier exercise.

4. Finally, as a result of parsing we have a Document object which represents a DOM tree
that we can traverse. In this exercise, there is a specific Java method for performing
the traversal, called traverseTree(). We call the traverseTree() method and pass to it a
reference to the Document, and also to the pre-defined JSP object called out, which is
used for printing data into the HTML code that is sent back to the user's web browser.

Here we declare a Java method that will be used to perform the traversal. We will call this
method to handle each node in the DOM tree that has been built in memory by the parser.

<%!
/**
Handles one node of the tree. It accepts any type of node, and
will check the node type before processing it. This function
is recursive - if one node contains other "sub-nodes", this
function will call itself again to process the sub-nodes.

@param currnode the current node


@param out where to write the output
*/
private void traverseTree(Node currnode, JspWriter out) throws Exception {

197
// If the current node is null, do nothing
if(currnode == null) {
return;
}

// Find the type of the current node


int type = currnode.getNodeType();

// Check the node type, and process it accordingly


switch (type) {

Notice that for the current node we are processing, we first find out the node type, and then
use a switch statement to branch to a block of code to handle that particular type of node.

Now we will examine each of the different handlers in turn.

/*
* Handle the top-level document node.
* Just print out the word "DOCUMENT", and then get the
* root element of the document, and process it using
* the traverseTree method
*/
case Node.DOCUMENT_NODE:
{
out.println("<p>DOCUMENT</p>");
traverseTree (((Document)currnode).getDocumentElement(), out);
break;
}

There is only one "document" node for each XML document. In this case, first we just print a
message to indicate that we have encountered a document node. Seconly, we call the
getDocumentElement() method to retrieve the root node of the document. With that root node,
we then call the traverseTree() method to handle it. Note that from within the traverseTree()
method, we are calling the same method again. This is an example of recursion in
programming.

/*
* Handle an element node

198
* This is the most complex type of node dealt with.
* First, print out the name of the element, before
* processing any other sub-nodes (i.e. a preorder traversal).
* Secondly, check if this element has any attributes, and
* if it does, process those next, by calling the traverseTree()
* method.
* Finally, retrieve the children of this node (if any), and
* process them one by one using the traverseTree() method.
*/
case Node.ELEMENT_NODE:
{
String elementName = currnode.getNodeName();
out.println("<p>ELEMENT: [" + elementName + "]</p>");

if (currnode.hasAttributes()) {
NamedNodeMap attributes = currnode.getAttributes();
for (int i=0; i < attributes.getLength(); i++) {
Node currattr = attributes.item(i);
traverseTree(currattr, out);
}
}

NodeList childNodes = currnode.getChildNodes();


if(childNodes != null) {
for (int i=0; i < childNodes.getLength() ; i++) {
traverseTree (childNodes.item(i), out);
}
}
break;
}

This is the most complex of the handlers. There are three main parts to it:

1. Find out the name of this element (elementName) and print it out.
2. Check to see if this element has any attributes associated with it. If it does, then we
retrieve them (attributes) and then loop through them one by one using a for loop. In
DOM, every attribute is treated as a Node as well. So in this example, for each
attribute, we simply call the traverseTree() method to handle it.
3. The final step in this example is to process any child nodes of this element. We
retrieve a list of all the child nodes, and use a for loop to process each one in turn,
using the traverseTree() method to do the processing. Note that children of element
nodes are typically either text nodes (if the element contains text) or further element
nodes (if the element contains other XML elements nested inside it).

Note that this is where we decide the traversal algorithm to use. In this case, we are using a
preorder traversal, which is the most common kind of traversal for processing documents
with DOM.

/*
* Handle attribute nodes.
* Just print out the word "ATTRIBUTE", and then the name

199
* and value of the attribute itself.
*/
case Node.ATTRIBUTE_NODE:
{
String attributeName = currnode.getNodeName();
String attributeValue = currnode.getNodeValue();
out.println("<p>ATTRIBUTE: name=[" + attributeName +
"], value=[" + attributeValue + "]</p>");
break;
}

In the case of attribute nodes, we just retrieve the attribute name and value, and print them
out.

Attribute nodes are leaf nodes in the DOM tree. They have no children to process.

/*
* Handle text nodes.
* Trim whitespace off the beginning and end of the text.
* Then check whether there is any real text, and if so,
* print it out. This avoids printing out text nodes that
* consist of only whitespace characters.
*/
case Node.TEXT_NODE: {
String text = currnode.getNodeValue().trim();
if (text.length() > 0) {
out.println("<p>TEXT: [" + text + "]</p>");
}
break;
}
}
}

%>

In the case of text nodes, we retrieve the value, and "trim" it. Trimming it means that we
remove whitespace from either end of the string.

If the resulting string has any characters left after trimming, then we print it out. This avoids
printing text nodes that consist entirely of whitespace.

Text nodes are leaf nodes in the DOM tree. They have no children to process.

Adding indenting to show nesting level

First, copy your dom.jsp file to a new file named dom1.jsp. Make the following changes to

200
dom1.jsp.

At the moment, the sample JSP prints all nodes at the same level of indenting (against the
left-hand margin). The first goal of this exercise is to modify the code so that each time the
traversal algorithm enters a new level of "depth" in the DOM tree, we indent the output one
level further, and each time the traversal algorithm goes up one level in the DOM tree, we
remove the indenting.

The easiest way to achieve indenting is to use the HTML <blockquote> tag. When you want to
increase the indenting by one level, print out the following line of HTML:

<blockquote>

When you want to decrease the indenting by one level, print out the corresponding closing
tag:

</blockquote>

Think about how the code works. Each time you process a node, the traverseTree() method is
called. Another way to think of it is that the start of the traverseTree() method is the time at
which you "enter" (i.e. start processing) a node, and the end of the traverseTree() method is
when you "exit" (i.e. finish processing) the node.

The solution is quite short - it can be done by adding only two lines of code - but it does
require you to think about and understand how the code works (particularly the traverseTree()
method).

Formatting the data in a table

The next exercise with the DOM parser is to print out the data from the addressbook.xml file in
a HTML table. Your resulting output should look something like the following:

Name Address Email Phonextn Birthday


Wayne Room 4/536 brookes@it.uts.edu.au 1872 2001-01-01
Maolin Room 4/520 maolin@it.uts.edu.au 1858 2001-01-01

Copy the original dom.jsp file to become dom2.jsp, and make your changes to dom2.jsp.

Printing a subset of the data

The final exercise is to selectively print data from the DOM tree. Copy the original dom.jsp

201
file to become dom3.jsp, and make your changes to dom3.jsp.

Suppose that using the addressbook.xml file, we only want to print out a list of names and email,
and none of the other information.

Modify the code so that only the <name> and <email> element values are printed. It's not as
easy as it sounds - remember that the actual value isn't stored in the DOM "element" node, it
is stored in a "text" node that is a child of the element.

Module: XML
Lab exercise - Transforming XML in a JSP

We can use Extensible Stylesheet Language Transformations (XSLT) to transform XML into
different formats. We also use XPATH expressions to match elements and attributes.

Level of Difficulty: 2 (medium)


Estimated time: 40 minutes
Pre-requisites:

• Run 'setEnv.sh' to set your environment correctly


• Start your WebLogic server running in the background
• Finished SAX and DOM labs.

Creating an XSLT sample file

We will use the existing addressbook.xml file to transform using some XSLT files we will
write.

First, let's create addressbook1.xsl

<?xml version="1.0" encoding="ISO-8859-1"?>


<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:output method='html' version='1.0' encoding='UTF-8' indent='yes'/>

This is the header of our XSLT file:

• Since this is an XML document, the first line must start with <?xml

202
• We then indicate that this is a stylesheet which will be performing XSLT
transformations. Note that there is a synonym called <xsl:transform> instead of
<xsl:stylesheet>
• Finally, the <xsl:output> element tells the XSLT processor what type of output can be
expected. In this case, we will be using HTML.
This could also equally be 'xml' or 'text'
• See http://www.w3.org/TR/xslt#output for a definitive syntax of this element.

<xsl:template match="/">
<html>
<body>
<p><i>Start of document</i></p>
<!-- Go and apply all the templates for the root -->
<xsl:apply-templates/>
<p><i>End of document</i></p>
</body>
</html>
</xsl:template>

This element is called once since XML documents represent a logical tree. When the parser
reads in the first, or "root" element, this template is matched.

• Note that we display some header/footers around the main body


• When <xsl:apply-template> is reached, the XSLT processor will attempt to match the
next template, in priority order.

The rest of the file is fairly straight forward - for each element we encounter, we emit some
boilerplate code

<xsl:template match="addressBook">
<h1>Address Book</h1>
<!-- Go and apply all the templates for the root -->
<xsl:apply-templates/>
</xsl:template>

<xsl:template match="entry">
<hr/>
<h2>Entry <xsl:value-of select="@id"/></h2>
<!-- Go and apply all the templates for the root -->
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="name">
<p>Name:
<!-- Go and apply all the templates for the root -->
<xsl:apply-templates/>
</p>
</xsl:template>
<xsl:template match="address">
<p>Address:
<!-- Go and apply all the templates for the root -->
<xsl:apply-templates/>
</p>
</xsl:template>
<xsl:template match="email">
<p>E-mail:
<!-- Go and apply all the templates for the root -->

203
<xsl:apply-templates/>
</p>
</xsl:template>
<xsl:template match="phonextn">
<p>Phone:
<!-- Go and apply all the templates for the root -->
<xsl:apply-templates/>
</p>
</xsl:template>

</xsl:stylesheet>

Notice that for <entry> node we pick up the attribute id, so if we found <entry id="99">, the
<xsl:value-of ..> element would return 99

When the XSLT processor has no more matches, it will then return up the parsing tree and
will emit the element text contents.

Let's try this out on the command line

java org.apache.xalan.xslt.Process -IN addressbook.xml -XSL addressbook1.xsl

This invokes the Apache Xalan XML processor and returns the result to your terminal. You
can use the -OUT addressbook.htm option to save the file, or use standard redirection ">
addressbook.htm" to save this to a file.

Try the result in a web browser.

Using a web browser to do transformations

Most modern browsers (Internet Explorer 5+, Mozilla/Firefox, Opera) have a built-in XSLT
transform engine. If you modify your addressbook.xml file with the following header on the
2nd line after the <?xml > element...

<?xml-stylesheet type="text/xsl" href="addressbook.xsl"?>

If you open this in your browser (either directly or via a web page), you will find that this is
also displayed transformed into HTML.

Using Java to do transformations

Here is a JSP that will read in addressbook.xml and addressbook.xsl to use the JAXPack to
do XSLT transforms.

<%@ page import="javax.xml.parsers.*" %>


<%@ page import="org.w3c.dom.*" %>
<%@ page import="javax.xml.transform.*" %>
<%@ page import="javax.xml.transform.dom.*" %>

204
<%@ page import="javax.xml.transform.stream.*" %>

<%@ page import="java.io.*" %>

<html><head> <title>DOM Parser</title> </head>


<body>
<h1>XML DOM parser test</h1>
<hr />

<%
// Create the stream we will read from
InputStream is =
application.getResourceAsStream("/addressbook.xml");
InputStream xsls =
application.getResourceAsStream("/addressbook.xsl");
StreamSource xmlSource = new StreamSource(is);
StreamSource xsltSource = new StreamSource(xsls);

// Create a StreamResult pointing to the output file


StreamResult fileResult = new StreamResult(out);
// Load a Transformer object and perform the transformation
TransformerFactory tfFactory =
TransformerFactory.newInstance();
Transformer tf = tfFactory.newTransformer(xsltSource);
tf.transform(xmlSource, fileResult);
%>

The main method we use is javax.xml.transform.Transformer which is part of the standard


J2SE implementation from 1.4 onwards.

More exercises: XSLT functions

XSLT provides some functions such as count(), concat(), substring() and so on.

Let's try some. Add this into the main root template (... match="/"... )

<h3>Summary</h3>
<p>There are <xsl:value-of select="count(//name)"/> names</p>
<p>There are <xsl:value-of select="count(//*)"/> nodes</p>

Here are some quick idioms to remember:

• //name means "any <name> element under the root / element"


• //* means any element

Try it out. Note that this counts the number of names in our addressbook.xml and also the
total number of nodes.

Advanced exercises:

205
Printing a subset of the data

How about displaying only <name> elements?

HINT: Just removing the match="address" & so on templates won't work - the text contents
of the nodes will still be displayed.
Try replacing them all with a match="*" template

Formatting the data in a table

The final exercise with XSLT is to convert your results to a table looking somewhat like this:

Name Address Email Phonextn Birthday


Wayne Room 4/536 brookes@it.uts.edu.au 1872 2001-01-01
Maolin Room 4/520 maolin@it.uts.edu.au 1858 2001-01-01

Module: Web Services


Lab exercise 1 - Exploring RPC Web Services

In this exercise, we will view a public Web Services registry (http://www.xmethods.com) and
then will use the Weblogic universal test client to explore an existing web service,
http://cdyne.com/creditcardverify/luhnchecker.asmx

Level of Difficulty: 1 (easy)


Estimated time: 20 minutes
Pre-requisites:

Finding Web services

(from wikipedia)

Universal Description, Discovery and Integration (UDDI) is a platform-independent, XML-


based registry for businesses worldwide to list themselves on the Internet.

UDDI is an open industry initiative, sponsored by OASIS, enabling businesses to publish


service listings and discover each other and define how the services or software applications
interact over the Internet. A UDDI business registration consists of three components:

• White Pages — address, contact, and known identifiers;


• Yellow Pages — industrial categorizations based on standard taxonomies;
• Green Pages — technical information about services exposed by the business.

206
IBM, Microsoft and SAP supported a publicly accessible Universal Business Registry but
closed this down on January 2006.

Fortunately, there are 3rd party registries still available on the internet. http://xmethods.com
is one such provider.

Using Xmethods.com

Start a browser and navigate to: http://xmethods.com

You can browse this list for many publicly available web services.
Note that the listing includes a Publisher, Style, ServiceName, Description and
Implementation column.

Clicking on the service name will reveal a description page of the web service.

On this page is:

• The WSDL address (and alongside this is a "Analyze WSDL" link which you can use to
summarise the web service definition file)
• Owner details
• Description
• Informational website link
• End points (optional)
• Contributed Clients (where other people have written clients for this webservice in various
languages)
• Usage notes

If you wish, you can download the sample clients other people have written, but for the
moment, you can scroll down to the bottom to see a detailed description and usage notes of
this service. This information is not usually automatically generated or used by programs.

The key information here is the location of the WSDL file.

Using the Weblogic Universal Test Client


Weblogic includes a simplistic test client which you can use to view and try out publically
available web services.

Start your weblogic server (either via the command line or via Weblogic Workshop)

Use the URL http://localhost:7001/wls_utc and enter the following WSDL URL:
http://cdyne.com/creditcardverify/luhnchecker.asmx?WSDL

207
You can then press [TEST] and you will see the various operations that this web service
supports.

In this case, you should see an operation called CheckCC which has a single parameter called
CardNumber

Enter: 4111111111111111 and press the [CheckCC] button.

You should then get the following results screen

208
Now we can see the XML representation of this transaction. We have our SOAP Envelope
and Body for both the request (invocation of the web service) and the response (results
returned).

As you can see, you provide the parameter as an XML message called <CheckCC> and the
response comes back as an XML message called <CheckCCResponse>

These are just self-defined XML elements under the namespace "http://ws.cdyne.com".

Alternative testing points

Many web service frameworks (include Weblogic) provide an internal test client. The
CDYNE credit card checker is written in Microsoft .NET and this provides an internal test
client at the address http://cdyne.com/creditcardverify/luhnchecker.asmx

Try this out. Note that this web service supports not only SOAP 1.1 but SOAP 1.2 and a
HTTP interface as well.

WSDL file

Now let's look at the WSDL definition of the web service. By convention, most web service
frameworks also support returning the WSDL for the web service by using the ?WSDL (or
?wsdl) query string on the endpoint URL

209
So for the CDYNE credit card checker, we use
http://cdyne.com/creditcardverify/luhnchecker.asmx?WSDL

Try this out. Most browsers will show you the XML returned as a formatted document like:

Let's look at the WSDL in more detail:

Firstly, we have some header information: All WSDL documents must have one top level
element - the <definitions> tag. This contains the (optional) name of the web service and the
target namespace. (note: web browsers sometimes omit the namespace definitions so I added
them here)

<wsdl:definitions xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:tns="http://ws.cdyne.com/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
targetNamespace="http://ws.cdyne.com/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">

We then have the definition of the XML schemas for the messages

<wsdl:types>
<s:schema elementFormDefault="qualified" targetNamespace="http://ws.cdyne.com/">
<s:element name="CheckCC">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="CardNumber" type="s:string" />
</s:sequence>
</s:complexType>

210
</s:element>
<s:element name="CheckCCResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="CheckCCResult" type="tns:ReturnIndicator" />
</s:sequence>
</s:complexType>
</s:element>
<s:complexType name="ReturnIndicator">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="CardType" type="s:string" />
<s:element minOccurs="1" maxOccurs="1" name="CardValid" type="s:boolean" />
</s:sequence>
</s:complexType>
<s:element name="ReturnIndicator" type="tns:ReturnIndicator" />
</s:schema>
</wsdl:types>

This basically defines the following types in pseudocode. Note that the s: prefix represents
the standard W3C XML Schema

CheckCC {
String CardNumber
}
CheckCCResponse {
ReturnIndicator CheckCCResult
}
ReturnIndicator {
String CardType
Boolean CardValid
}

Next, we have our SOAP message definitions. Basically, these are the parameters we pass
and receive from our operations. The ones displayed below are relevant to SOAP 1.1

<wsdl:message name="CheckCCSoapIn">
<wsdl:part name="parameters" element="tns:CheckCC" />
</wsdl:message>
<wsdl:message name="CheckCCSoapOut">
<wsdl:part name="parameters" element="tns:CheckCCResponse" />
</wsdl:message>

Next, our <portType> element. Basically this defines what operations exist on for the given
port.

<wsdl:portType name="LUHNCheckerSoap">
<wsdl:operation name="CheckCC">
<wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
Enter 4111111111111111 to test a good credit card number.</wsdl:documentation>
<wsdl:input message="tns:CheckCCSoapIn" />
<wsdl:output message="tns:CheckCCSoapOut" />
</wsdl:operation>
</wsdl:portType>

211
ie: our operation is CheckCC with the input parameter message called CheckCCSoapIn and
the return message called CheckCCSoapOut

Next, <binding> element. This maps the portType to the specific protocol (in this case, SOAP
over HTTP, which is represented by the transport attribute
"http://schemas.xmlsoap.org/soap/http").

<wsdl:binding name="LUHNCheckerSoap" type="tns:LUHNCheckerSoap">


<soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="CheckCC">
<soap:operation soapAction="http://ws.cdyne.com/CheckCC" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>

Note that the style is document and the encoding usage is literal. This is the WS-I standard
which supplants the traditional RPC SOAP encoding.

Finally, we define the service itself. The previous elements defined an abstraction of the web
service, we now come to the implementation of the web service itself. This maps the service
end point (which is the <port> element here) to a physical address (in this case,
"http://cdyne.com/creditcardverify/luhnchecker.asmx" ). If we we using alternative transports
such as HTTP, this would be reflected here too. Note that for clarity I have omitted the
bindings for SOAP12 and HTTP.

<wsdl:service name="LUHNChecker">
<wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
Validates Credit Cards to ensure proper input...
</wsdl:documentation>
<wsdl:port name="LUHNCheckerSoap" binding="tns:LUHNCheckerSoap">
<soap:address location="http://cdyne.com/creditcardverify/luhnchecker.asmx" />
</wsdl:port>
... omitted other port bindings ...
</wsdl:service>

This essentially declares that the service called "LUHNChecker" has a SOAP 1.1
implementation at http://cdyne.com/creditcardverify/luhnchecker.asmx

Lab exercise 2 - Exploring other Web Services

Now that you have tried one web service, why not try other web services from
xmethods.com?

Another good source of web services is http://www.webservicex.net.

212
Reflection
Whilst fundamentally a simple concept, the Web services standards produce quite verbose
XML documents for what could be very simple RPC style services. This complexity is
needed to allow web services to be self describing, portable and interoperable between
systems and languages.

Our next step is to write a client for a web service then we will implement a very simple web
service later.

Module: Web Services


Lab exercise 3 - Writing a simple RPC client

In this exercise we will create a simple RPC client

213
Level of Difficulty: 1 (easy)
Estimated time: 20 minutes
Pre-requisites:

• Run 'setEnv.sh' to set your environment correctly


• Completed Lab exercise 1 - exploring Web services

JAX-RPC Static clients


JAX-RPC is the Java standard for web services. It encapsulates much of the complexity of
communicating via SOAP and also maps many Java value classes to the standard XML data
types.

In this lab, we will use Weblogic to generate client side stubs which will be invoked by our
Java class. Note that each JAX-RPC implementation generates different stub classes, so be
aware that you will need to re-generate the Stubs for each platform you are developing with
(eg: Apache AXIS)

Create new project


First step is to create a new development project ie:
New -> Project -> Dynamic Web Project & set the "Annoted Web Service Facets
(minimum)" configuration & name the project labws

Then configure the build path:

1. Project -> Properties -> Java Build Path


2. Select the Libraries tab & Add External Archives
(or go Right Mouse Button -> Build Path -> Add External Archives)
3. Add /opt/bea10/wlserver_10.0/server/lib/wseeclient.jar (or the equivalent path in your
configuration)

Generating a static client stub

If you have weblogic 10.3 you can use the ClientGen web service wizard to create a client,
however, for the weblogic 10.0 users you will need to have the following ANT build.xml file
to build the stubs.

File -> New -> XML & call the file build.xml

(you can import the build.xml here )

<?xml version="1.0" encoding="UTF-8"?>


<project name="webservicesLab" default="build-client" basedir=".">
<description>Weblogic JWS builder</description>
<target name="init">
<path id="weblogic.class.path">
<pathelement path="${java.class.path}" />
<pathelement path="${env_var:WEBLOGIC_CLASSPATH}" />

214
<fileset dir="/opt/bea10/wlserver_10.0/server/lib">
<include name="weblogic.jar" />
</fileset>
</path>
</target>

<target name="build-client" depends="init">


<taskdef name="clientgen"
classname="weblogic.wsee.tools.anttasks.ClientGenTask">
<classpath refid="weblogic.class.path" />
</taskdef>

<clientgen type="JAXRPC"
wsdl="http://cdyne.com/creditcardverify/luhnchecker.asmx?wsdl"
destDir="src" generateAsyncMethods="false"
classpath="${java.class.path}" autoDetectWrapped="true"
packageName="ws" />

</target>

<target name="build-server" depends="init">


<taskdef name="jwsc"
classname="weblogic.wsee.tools.anttasks.JwscTask" >
<classpath refid="weblogic.class.path" />
</taskdef>

<jwsc srcdir="src" destdir="src">


<jws file="**/*Bean.java" type="JAXRPC" />
<jws file="**/*Service.java" type="JAXRPC" />
</jwsc>

</target>

</project>

You then run this ANT build file by selecting build.xml


Right Mouse Button -> Run As -> Ant Build

You should see the ANT build running in the Workshop Console. Hopefully no errors occur.

The following files should be generated

com.cdyne.ws
ReturnIndicator.java
ws
LUHNChecker.java
LUHNCheckerSoap.java
LUHNCheckerSoap_Stub.java
LUHNChecker_Impl.java
LUHNChecker_saved_wsdl.wsdl

The main classes we are interested in are:

• LUHNChecker.java - this is the web service interface (<wsdl:service>)


• LUHNCheckerSoap.java - this is the binding (<wsdl:binding> & contains the operations for
that port (eg: checkCC(String) )

215
• LUHNChecker_Impl.java - this is the implementation of the web service interface ***
• LUHNCheckerSoap_Stub.java - this is stub that does the actual communications/marshalling
etc
• com.cdyne.ws.ReturnIndicator.java - this represents the complexType ReturnIndicator

You will need to do this analysis every time you generate a stub for a web service...

JSP Client

The next step is to create a JSP with the following code fragment in it

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"


pageEncoding="ISO-8859-1"%>
<%@page import="ws.*" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
Lunh checker: checking 4111111111111
<%
LUHNChecker checker = new LUHNChecker_Impl();
LUHNCheckerSoap port = checker.getLUHNCheckerSoap();
com.cdyne.ws.ReturnIndicator ri = port.checkCC("4111111111111111");
out.println(ri.getCardValid());
out.println(ri.getCardType());
%>
</body>
</html>

Build, deploy and run as usual

You can modify this JSP to take the credit card argument as an input field in a form.

Module: Web Services


Lab exercise 5 - Writing a simple web service

In this exercise we will create a simple web service.

216
Level of Difficulty: 3 (medium)
Estimated time: 40 minutes
Pre-requisites:

• Run 'setEnv.sh' to set your environment correctly


• Started the WebLogic server on your workstation
• Completed Lab exercise 1 - exploring Web services
• Completed Lab exercise 3 - simple client

Writing the server code

It's actually quite simple to write a Web Service if you have a JSR-181 compliant web service
framework.

Weblogic 8.1, 9 & 10 all support using Java Annotations to mark web services

• Create a new Web Services Project


(New -> Project -> Web Services Project, call it "ws" )

• Create a new Package


(New -> Package -> myapp )

• Create a new Weblogic Web service


(New -> Other -> Weblogic Web Service). Call this Hello (in the package myapp)

• By default, the wizard generates a method called void Hello().

Change this to the following:

package myapp;

import javax.jws.*;

@WebService
public class Hello {

@WebMethod
public String hello(String name) {
return "Hello, " + name;
}
}

Notice the annotations:

@WebService tells Java & Weblogic that this is a webservice (the default name is Hello)

@WebMethod declares that the following method is a web service Operation. By default, if
you dont have this annotation, ALL PUBLIC METHODS are exposed.

We will let the wonders of code generation do all the work for us to make this a web service!

Generating the code

217
No need to do any. Workshop will run a builder to do this under the covers for you.

Deploy

As usual, add this to the Server (BEA Weblogic Server v10 [weblogic] -> RMB -> Add and
Remove Projects)

or just run via highlighting Hello.java -> RMB -> Run As -> Run on Server

Test

Go to http://localhost:7001/ws/Hello

This gives you an application test page! Look at the WSDL and the Test Page

Problems

Sometimes when you do changes you need to clean the project, rebuild and also re-publish

select the Server (BEA Weblogic server v10 [weblogic] -> RMB -> Publish

Additional Exercise: Java Client (medium)

The next step is to create a JSP client for this service.

Follow the instructions in lab 3 and you should be able to write your own JSP client

Module: Web Services


Lab exercise 6 - Adding Basic security to a simple web service

In this exercise we will modify the previous simple web service to add basic HTTP security

218
Level of Difficulty: 3 (medium)
Estimated time: 40 minutes
Pre-requisites:

• Run 'wlenv' to set your environment correctly


• Started the WebLogic server on your workstation
• Completed JSP Lab exercise 4 - web authentication
• Completed Lab exercise 3 - simple client
• Completed Lab exercise 5 - simple web services

Weblogic (and J2EE in general) define three basic types of web services security. To quote
the weblogic documentation at http://edocs.bea.com/wls/docs100/webserv_sec/overview.html
, they are::

• Message-level security, in which data in a SOAP message is digitally signed or encrypted.


• Transport-level security, in which SSL is used to secure the connection between a client
application and the Web Service.
• Access control security, which specifies which roles are allowed to access Web Services.

Message level security is fairly complex and you can read about this independently at
http://edocs.bea.com/wls/docs100/webserv_sec/message.html. Basically you can sign and/or
encrypt individual SOAP messages according to the WS-security standard - and this could be
the entire SOAP message, or just the header or just the body or even just specific elements!

You could also include a Token (username, SAML or X.509 based) which represents the
user.

Transport-level security is basically setting up SSL (or TLS in this case) on the connection
between your client and web service. You could use a client based certificates to authenticate
the connection. However, this is not the same as USER authentication since this only
authorises the network connection.

Access control security is the simplest authentication - this re-uses the HTTP basic
authentication (which you did in JSP Lab 4 - web authentication) by setting access control
security on our web service project. Effectively all you need to do is to pass the username and
password on the SOAP call at the client end and the web application server which the web
service is running on will handle the security.

Again, this could be via simple plain text username/password (like "student", "password") or
you could use Digest authentication using a client-side certificate (a lot harder).

This lab will use HTTP Basic Authentication and will re-use your existing security setup
from the JSP Lab 4 - web authentication.

Setting up usernames & roles

This step has been done in JSP Lab 4 - web authentication.

Basically you set up a group called "hellousers" which maps to a role called "hellousers".

219
You then created users who were members of this group. In the lab you created a username
"student" with password "password" (or whatever)

Writing the server code

Keep the existing HelloWorld.java file

Modify the web.xml and weblogic.xml files.

Basically copy the code fragment from the JSP Lab 4 iafter the </welcome-file-list> tag in
web.xml

<security-constraint>
<web-resource-collection>
<web-resource-name>Hello world</web-resource-name>
<description>The Hello world application</description>
<url-pattern>/*</url-pattern>
</web-resource-collection>

<auth-constraint>
<description>These users can use hello JSP</description>
<role-name>hellousers</role-name>
</auth-constraint>
</security-constraint>

<login-config>
<auth-method>BASIC</auth-method>
<realm-name>Hello World Application</realm-name>
</login-config>

<security-role>
<description>Hello JSP users</description>
<role-name>hellousers</role-name>
</security-role>

You can optionally modify the URL pattern (we used /*) to the web service name itself.
You also have to modify the weblogic.xml file to add the following:

<wls:security-role-assignment>
<wls:role-name>hellousers</wls:role-name>
<wls:principal-name>hellousers</wls:principal-name>
</wls:security-role-assignment>

Redeploy & Test

Just redeploy as usual. You can test that you now have to enter a userid and password by
typing in the URL in a browser (or in the Weblogic test client).

Note that if you run your previous client, you should get an 500 error with a message like
something like

java.rmi.RemoteException: SOAPFaultException - FaultCode


[{http://schemas.xmlsoap.org/soap/envelope/}Client.Authentication] FaultString [Failed to
receive message weblogic.wsee.util.AccessException: The server at

220
http://localhost:7001/ws/Hello returned a 401 error code (Unauthorized). Please check that
username and password are set correctly and that you have permission to access the requested
method.The server at http://localhost:7001/ws/Hello returned a 401 error code
(Unauthorized). Please check that username and password are set correctly and that you have
permission to access the requested method.]

Generating the Client skeleton

You can keep the existing client you wrote the the previous lab and therefore do not need to
re-generate the client code.

However, if you need to use the Clientgen Ant task, you now have to change the call to add
the username and password parameters.

To do this change your build.xml clientgen elemnt to the following:

<clientgen type="JAXRPC"
wsdl="http://localhost:7001/ws/Hello?wsdl"
destDir="src" generateAsyncMethods="false"
classpath="${java.class.path}" autoDetectWrapped="true"
packageName="ws" >
<sysproperty key="javax.xml.rpc.security.auth.username"
value="student"/>
<sysproperty key="javax.xml.rpc.security.auth.password"
value="password"/>
</clientgen>

Don't forget to tailor this for your configuration - ie: change the wsdl, student and password
values to your configuration!!!

Modifying the client

When you wrote your test JSP to invoke this web service, you needed to locate the port.

This was via a method on the service class called getXXXSoapPort() (mine is called
getHelloSoapPort() ).

The code generated by Weblogic ClientGen includes a variant of this method called
getXXXSoapPort(byte[] username, byte[] password)

So modify the method call to look like getXXXSoapPort(username.getBytes[],


password.getBytes[] )
(assuming that String username contains the username eg: "student", and String password
contains the password eg: "password")

Test

Rebuild, and redeploy (if necessary), your client. Check that this now works as expected.

221
Module: Web Services
Lab exercise 7 - Writing a more complex web service

In this exercise we will experiment with different return types from a web service.

Level of Difficulty: 3 (medium)


Estimated time: 40 minutes
Pre-requisites:

222
• Run 'wlenv to set your environment correctly
• Started the WebLogic server on your workstation
• Completed Lab exercise 5 - simple web service

Other data types

JAX-RPC defines the following simple Java datatypes to an equivalent in XML schema. See
Java Enterprise in a Nutshell, 3rd Ed, chapter 12 for a more complete list.

Java Types XML Type: Document-Literal


boolean, java.lang.Boolean xsd:boolean
byte, java.lang.Byte xsd:byte
double, java.lang.Double xsd:double
float, java.lang.Float xsd:float
int, java.lang.Integer xsd:integer
long, java.lang.Long xsd:long
short, java.lang.Short xsd:short
java.lang.String xsd:string
java.math.BigDecimal xsd:decimal
java.math.BigInteger xsd:int
java.net.URI xsd:anyURI
java.util.Calendar xsd:dateTime
java.util.Date xsd:dateTime
java.xml.QName xsd:QName
byte[] xsd:base64Binary

In addition to this, it will map arrays and JavaBeans to an equivalent xsd:ComplexType,


xsd:sequence and xsd:element combination.

Lab Exercise: Returning complex types


We will see the impact of returning a simple object array, a and a more complex type as a
JavaBean.

Creating a JavaBean

Create a javabean called myapp.HelloBean. This should have the properties String name &
int age

(hint: create a class in the package myapp called HelloBean, add


private String name;

223
private int age;
& use source -> Generate getters and setters)

Add new complex methods to your class

Append the following methods into your Hello.java class

@WebMethod
public String[] sayHellos (String mate) {
String[] list = new String[3];
list[0] = "hi " + mate;
list[1] = "hola " + mate;
list[2] = "nihao " + mate;
return list;
}
@WebMethod
public Vector sayHola (String mate){
Vector<String> v = new Vector<String>();
v.add("hola " + mate);
v.add("ciao " + mate);
return v;
}
@WebMethod
public HelloBean sayBean (String mate) {
HelloBean hb = new HelloBean();
hb.setName(mate);
hb.setAge(99);
return hb;
}

Deploy and look at the WSDL generated.

What do you notice?

Note that we now have a complexType called "ArrayOfJavaLangstring_literal" - this is the


representation of String[]. Ugly isn't it?

We also have complexType "HelloBean" - this is the Javabean we created. Note that it has 2
elements, Age and Name of xsd:int and xsd:string respectively.

Finally if you look at the "sayHolaResponse" element, we have an anonymous ComplexType


with an element called return, with type "java:vector". This is the result of the
Vector<String>

Building a client
We can build a client as usual, just do remember to re-run the ant build.xml script in the
client project.

Modify your existing client to call the new methods added to your web service.

You should look at the Hello.java file (the interface).

224
It should contain the method signatures for sayHellos(), sayHola() and sayBean().

Notes:

Rather than generating a String[] array, jax-rpc (and in particular, the weblogic
implementation of it), generates a holding class, which you then have to call another method
(in this case, getJavaLangString() ) to return the String[] array.

Rather than generating a vector, java jax-rpc returns an array of Object[].

When you have a Javabean, jax-rpc will return a Javabean back to you.

Module: Security
Lab exercise - Confidentiality

In security terms, "confidentiality" is ensuring that information cannot be accessed by those


who do not have permission. It is typically satisfied by encrypting data. This lab exercise
looks at how you can use encrypted communication between a client and the presentation
tier.

225
Level of Difficulty: 1 (easy)
Estimated time: 20 minutes
Pre-requisites:

• Run 'wlenv' set your environment correctly


• Start your WebLogic server running in the background
• Completed an earlier exercise using servlets or JSPs

Using SSL

The laboratory exercises for this module do not involve writing any new code. It assumes that
you have some code from a previous lab, preferably a stateless session EJB, and a Java
servlet (or JSP) that calls a business method on the EJB.

SSL stands for Secure Sockets Layer, and is also sometimes known as TLS (Transport Layer
Security). It is basically a mechanism for encrypting application traffic for transmission over
a TCP/IP network. Its most common use is to encrypt HTTP (web) traffic between a web
browser and a web server.

• To enable SSL on weblogic 10, go to the Weblogic Console, choose Environment >
Servers & select AdminServer
• You need to click the [Lock and Edit] tab on the top left menu to enable updates
• Then, on the General tab, select the SSL Listen Port Enabled. Note that the default
listen port is 7002.
Finally, [Save] and [ACTIVATE CHANGES] to enable SSL.

Try accessing the Weblogic console using SSL:

https://localhost:7002/console

Try loading one of your earlier web applications (servlet or JSP) using SSL, by using the
URL

https://localhost:7002/labs/index.jsp (change /labs & index.jsp to match your context & JSP
names )

Note that no change was required to the application.

You can ignore any messages from your browser about invalid certificates, since effectively
we have a 'self-signed' SSL certificate issued from "MyOrganization" to "MyOrganization"
!!

In a production environment, you would normally purchase an SSL certificate from a


commercial vendor such as Verisign or Thawte. You can read your web application server's
documentation for the particular process you should follow.

Enforcing SSL

226
Change the web.xml deployment descriptor for the application you just tested, so that it has a
<transport-guarantee> tag, specifying that SSL must be used.

Insert the following XML into your deployment descriptor after the <welcome-file-list> tag
you may have used.
You can optionally add <auth-constraints> to enforce login authentication too..

<security-constraint>
<web-resource-collection>
<web-resource-name>My App</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>

<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>

Then try invoking your application again, first using the SSL URL (starting with https://) as
described above. Then try invoking the JSP using a non-SSL URL (use http:// at the start of
the URL and use port 7001). What happens (hint: pay close attention to the URL in the
browser if you think nothing happens)?

Module: Security
Lab exercise - Web authentication

In a J2EE application, you can require authentication either at the web tier, or at the EJB tier.
This lab exercise looks at different ways you can use authentication information in a web
application.

227
Level of Difficulty: 1 (easy)
Estimated time: 30 minutes
Pre-requisites:

• Run 'wlenv' to set your environment correctly


• Start your WebLogic server running in the background
• Completed an earlier exercise using servlets or JSPs

Declarative web authentication

The laboratory exercises for this module do not involve writing any new code. It assumes that
you have some code from a previous lab, preferably a stateless session EJB, and a Java
servlet (or JSP) that calls a business method on the EJB.

Declarative web authentication involves adding authentication to a web application without


changing the Java source code at all. The authentication requirements are specified purely in
the XML deployment descriptor(s).

For this exercise, take an existing application, and change the deployment descriptor to
require a user to authenticate before being granted access to the application.

In the first instance, use HTTP "Basic" authentication. Follow the instructions in the tutorial
on using HTTP Basic authentication in web applications.

Programmatic web authentication

Generally, declarative authentication is preferred wherever possible, because it allows the


container to manage the authentication process, and reduces the possibility of programmer
errors.

However, sometimes declarative authentication is not enough. With declarative


authentication, the smallest section of an application you can protect is one servlet or JSP.
Sometimes, within a single servlet or JSP, you need finer-grained control.

With programmatic web authentication, you add some Java code to your servlet/JSP program
that checks which user is logged in, and takes appropriate action depending upon the user's
identity.

For a servlet that you have already created, and set up declarative web security before
(previous section), try the following steps for some simple programmatic web authentication.

1. In the servlet's source code, first of all, import the class java.security.Principal (or import
java.security.* if you prefer).
2. Somewhere in the doGet() method, add code similar to the following:

228
String username = null;
Principal p = req.getUserPrincipal();
if (p != null) {
username = p.getName();
}
out.println("You are logged in as: " + username);

Module: Transactions
Lab exercise - Transactions

Transactions in J2EE applications are largely managed by the container. That means you can
modify the transactional properties of an application by altering values in the deployment
descriptor (ejb-jar.xml), so there is not a lot of code to write. This exercise is just to explore an
application where a transaction is initiated in a servlet.

229
Level of Difficulty: 1 (easy)
Estimated time: 15 minutes
Pre-requisites:

• Run 'wlenv' to set your environment correctly


• Start your WebLogic server running in the background

Transactions

There is not much to do, programmatically for transactions. With container-managed


transactions, it is an issue of choosing the correct values in the deployment descriptor.

Examine an EJB deployment descriptor you created earlier (ejb-jar.xml). You would have
created a <container-transaction> declaration like the following.

<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>HelloWorld</ejb-name>
<method-intf>Remote</method-intf>
<method-name>*</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
</assembly-descriptor>

This example says that for all method-names on the remote interface of EJB HelloWorld, we
want to use the transaction attribute "Required". You can change how this EJB method
behaves in the context of a transaction by changing the value of the transaction attribute.

Transaction Meaning
attribute

Required This method must participate in a transaction. If an existing transaction is already in


progress, it will join that one, otherwise a new transaction will be started.

RequiresNew This method must participate in a transaction. It will always create a new
transaction. If an existing transaction was already in progress, it will suspend that
one and create a new one. The new transaction created will have no relationship to
the old one.

NotSupported This method will not participate in a transaction. If an existing transaction was
already in progress, it will suspend that one, and execute without a transaction
context.

Supports This method may or may not participate in a transaction. If an existing transaction is
already in progress, it will join that one and run in a transaction. If no transaction is

230
in progress, it will not create a new one, and therefore it will not run in a transaction.

Never This method will not participate in a transaction. Further, if an existing transaction
was already in progress, it will throw an exception. i.e. it will refuse to run with a
transaction.

Mandatory This method must participate in a transaction. Further, if an existing transaction was
not already in progress, it will throw an exception. i.e. it will refuse to run without a
transaction that is already in progress.

Optional: If you wish to try out some different values, create two different EJBs with one
method each. Let's call them EJB1 and EJB2. Set the transaction attribute of EJB1's method
to Required, and the transaction attribute of EJB2's method to Never. Make a servlet that
invokes EJB1's method. Make EJB1's method invoke EJB2's method. An exception should be
thrown.

Starting a transaction in a servlet

So far we have considered transactions only applied to EJB methods. In practice, this is how
transactions are used in J2EE applications. However, in rare circumstances, it might be
necessary to create a transaction in a servlet or JSP. The following example illustrates how.

This lab exercise is merely exploratory - examine the following example of a web application
(servlet) that creates a UserTransaction, and then calls a stateless session EJB. The
UserTransaction object is created by the application server and is advertised in the JNDI tree, so
the servlet merely does a naming lookup to retrieve the transaction context object.

Note that using transactions in this way is not usually done in J2EE applications, so you
should not try to copy this behaviour in your own applications.

Example application: starting a transaction in a servlet

The application is provided in a separate JAR file and WAR file, for the EJB and servlet
components respectively.

• TransStatelessSessionEJB.jar
• TransClient.war

Module: Legacy
Lab exercise - Using CORBA

Many legacy systems use CORBA as their main distributed systems model of programming.
This is because CORBA provides an vendor-independent, language-neutral, platform

231
agnostic and open standard. There even exists bridges between proprietary systems such as
Microsoft DCOM and CORBA.

CORBA can also be more efficient than the J2EE platform - sometimes due to the legacy
code such as C being compiled.

In the lab environment, a minimal CORBA ORB is provided - this is the open source ORBit
and ORBit2 packages under Redhat Linux. Incidentally, this is also required for the GNOME
GUI, which uses CORBA to manage the desktop!

Level of Difficulty: 3 (medium, extra exercise is hard)


Estimated time: 45 minutes
Pre-requisites:

• Run 'setEnv.sh' to set your environment correctly


• Ensure . is in your $CLASSPATH

CORBA - C example

We have provided a sample calculator application, written in C, which provides 2 simple


functions - add and sub

This can be found here as a zip file or alternatively, on /pub/aip/corba/src.zip. For the
intrepid, this comes from the orbit documentation package
http://www.gnome.org/projects/ORBit2/orbit-docs.tar.gz

CORRECTION: There is a bug in Makefile, remove the reference to -llinc in the


LDFLAGS= section
You can also download the corrected Makefile here.

You can also read the Orbit Documentation for this sample at
(http://www.gnome.org/projects/ORBit2/orbit-docs/orbit/x478.html) if you are brave (and
understand C).

Unzip this into a subdirectory.

Let's look at the IDL for this application

//
// Calculator interface
//

interface Calculator
{
double add(in double number1, in double number2);
double sub(in double number1, in double number2);
};

Basically, this defines 2 functions called add() and sub().

232
Both a server (calculator-server.c) and a client (calculator-client.c) are provided. There is a
Makefile available, so you can compile this example.

make

You can test this now by starting up the server in a seperate window and typing

./calculator-server

Let's try the client - run this in your original window..

./calculator-client

Simple eh? 1+2 = 3

Look at the calculator.ref file. This is where the IOR of the server client is temporarily stored.
In real life, it would be better to have a lookup mechanism for this object reference, and
CORBA 2 provides a human readable naming mechanism based on the URI standard for this
very purpose. The IOR is a string that looks something like

IOR:010000001300000049444c3a43616c63756c61746f723a312e3000000300000
00054424f5c0000000101020005000000554e495800000000170000006361747368
61726b2e69742e7574732e6564752e61750000280000002f746d702f6f726269742
d6368772f6c696e632d3431302d302d323730323739383736386434340000000000
caaedfba5400000001010200280000002f746d702f6f726269742d6368772f6c696
e632d3431302d302d3237303237393837363864343400000000001c000000000000
00c0fa8c60a80c68a86b70282828282828010000006f9971a101000000480000000
100000002000000050000001c00000000000000c0fa8c60a80c68a86b7028282828
2828010000006f9971a101000000140000000100000001000105000000000901010
000000000

If you want this decoded, copy this into your clipboard and enter it into the following URL:

http://www2.parc.com/istl/projects/ILU/parseIOR/

Note that if you choose Parse(Brief) it shows the NIL object. This is because by default,
ORBit does not use IIOP and uses unix domain sockets instead. Let's correct this.

You need to create a file called ~/.orbitrc with the following contents

ORBIIOPIPv4=1

Re-run the server, and get the IOR from calculator.ref and try the IOR parser again. You
should get a response like

object key is <#00#00#00#00#1C#BCm#FC#A7#D8?#C2#B9#F7#0D#E2#16#FA


$#8E#01#00#00#00R#DE#C4#F0>;
no trustworthy most-specific-type info; unrecognized ORB;
reachable with IIOP 1.2 at host "catshark.it.uts.edu.au",
port 34286

Now we can develop CORBA IIOP clients, such as a Java based one.

233
Java CORBA client

We need to generate skeletons for the Java client. Type

idlj calculator.idl
You should get the following files generated

• CalculatorHelper.java
• CalculatorOperations.java
• Calculator.java
• CalculatorHolder.java
• _CalculatorStub.java

We also need to write the client code itself. Create calculator_client.java


import org.omg.CORBA.*;
import java.io.*;
import java.util.*;

class Calculator_client {
public static void main( String args[] ) {
try{
Properties props = System.getProperties();
System.out.println( "Initializing the orb.");
// now get a new instance of an application ORB
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,props);

// read in the IOR reference file


BufferedReader in = new BufferedReader(
new FileReader("calculator.ref"));
String iorString = in.readLine();

// replace above with the following if you are running JDK 1.4.2
// org.omg.IOP.IORHolder ior_holder = new org.omg.IOP.IORHolder();
// String iorString = ior_holder.readIORFile("calculator.ref");

org.omg.CORBA.Object object = orb.string_to_object( iorString );


Calculator calc = CalculatorHelper.narrow( object );
System.out.println("Now calling add");
double res = calc.add((double)1.0,(double)2.0);
System.out.println("Call to Corba Calculator="+res);

} catch ( org.omg.CORBA.SystemException e ) {
System.err.println( "CORBA System Exception ");
System.err.println( e );
e.printStackTrace();
} catch (Exception e) {
System.err.println("Other java error "+e);
e.printStackTrace();
}
}
}
And compile the lot
javac *.java
(in the supplied Makefile, we have added an extra target called alljava, so you could also
type make alljava)

234
If you had errors, correct them, or check that you have '.' in the classpath.

Start the calculator-server again, then

java Calculator_client

Hopefully, you should see the correct result come out.

Additional exercises

If you sufficiently skilled in C, you could add extra functions to this application, such as mult
or div.

Here is the process to follow:

1. Edit calculator.idl file and add the extra definitions.


2. Clear the old code
make distclean
3. Edit the calculator-skelimpl.c - you add your methods at the bottom of this file. Use
add or sub as a template.
4. Re-generate the code
make all
5. You can then also edit the calculator-client.c file to call these extra methods. Don't
forget to make all each time you make changes!
6. Finally, you can follow the above steps and modify/compile/run the Java client.

One more exercise is to run the client and server on different machines. Since you will be
logging onto different machines with the
same userid, you should make sure you run the server and client from the same directory, so
as to have the same calculator.ref file present.

Module: Legacy
Lab exercise - Using JMS

235
Java Message Service (JMS) provides a Java API for Message Oriented Middleware such as
IBM MQseries and integrated JMS providers
such as SonicMQ and WebLogic JMS.

In this lab, we will experiment with both point-to-point and publish-subscribe messaging
patterns.

Level of Difficulty: 3 (medium, extra exercise is hard)


Estimated time: 45 minutes
Pre-requisites:

• Run 'wlenv' to set your environment correctly


• Ensure . is in your $CLASSPATH
• Ensure WebLogic server is running

Point-to-Point messaging

Before we can do any programming, we need to setup queues and topics into WebLogic.

Enter the WebLogic console.

Part 1: Creating a JMS server and Destinations

Weblogic 9 and 10 have a concept called "JMS Modules". These contain the definitions of all
the JMS messaging queues/topics etc. They can be application specific (which requires the
creation of a Weblogic-specific XML deployment descriptor) or a System module (which is
system wide). We will use the System module in our lab.

First we create a JMS Server:

• From the weblogic console, press the [Lock & Edit] button to get into edit mode.
• Choose Services > Messaging > JMS Servers & choose [NEW]
• Name the server: JMSServer & [Next]
• Select AdminServer as the Target & [Finish]
• Choose the [Activate Changes] at the top left menu

Now create the Queue

• From the weblogic console, press the [Lock & Edit] button to get into edit mode.
• Choose Services > Messaging > JMS module & select [New]
• Give the new module a name: SystemModule & [Next]
• Select the AdminServer & [Next]
• Select the "Would you like to add resources to this JMS System module" checkbox & [Finish]
• Now we can create the queue for our lab. Select [New] in the "Summary of Resources" table
• Choose the Queue radio button & [Next]
• Now enter: name: MyMessageQueue
JNDI Name: jms.MyMessageQueue
& [Next]
• Choose [Create a new Subdeployment] - keep the name the system generates & [OK]
• Choose targets: JMSServer & [Finish]
• Don't forget to [ACTIVATE] changes (top left menu)

236
Check that the queue exists by going to the Environment > Servers > AdminServer &
selecting the "View JNDI tree" link.
You should see jms. Expand this and you should see MyMessageQueue appear.

We will use the default WebLogic JMS connection factory


weblogic.jms.ConnectionFactory. You can optionally create your own
connection factory by following the steps when creating a Queue, but choosing Connection
factory instead.. We don't need to do this for our lab

Part 2: Create a receiver and sender Java program

Create a subdirectory eg: ~/jms to develop these programs. Note that they are not JSP or
servlets, just ordinary Java applications.

Here is a simple receiver program called receiver.java

import javax.jms.*;
import javax.naming.*;
import java.util.Hashtable;

public class Receiver implements MessageListener {

private QueueConnectionFactory qconFactory;


private QueueConnection qcon;
private QueueSession qsession;
private Queue queue;
private QueueReceiver qreceiver;

public static void main (String[] args) throws Exception {


Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
env.put(Context.PROVIDER_URL,"t3://127.0.0.1:7001");
try {
InitialContext ctx = new InitialContext(env);
System.out.println("Setting up receiver...");
Receiver r = new Receiver();
r.init(ctx, "jms.MyMessageQueue");

System.out.println("Run init, hit Ctrl-C to stop..");


// loop here if need be.
synchronized(r) {
r.wait(100000); // wait 100 seconds
}
System.out.println("Finished waiting, bye...");
} catch (Exception e) {
e.printStackTrace();
}
}

public void init(Context ctx, String queueName) {


try {
qconFactory = (QueueConnectionFactory) ctx.lookup(

237
"weblogic.jms.ConnectionFactory");
qcon = qconFactory.createQueueConnection();
qsession = qcon.createQueueSession(false,
Session.AUTO_ACKNOWLEDGE);

queue = (Queue) ctx.lookup(queueName);


System.out.println("looked up "+queueName);

QueueReceiver qreceiver = qsession.createReceiver(queue);


System.out.println("Created queueReceiver...");
qreceiver.setMessageListener(this);
System.out.println("Starting QueueConnection...");
// start the thread which listens for incoming messages
qcon.start();
} catch (Exception e) {
e.printStackTrace();
}
} //init

public void onMessage(Message msg) {


try {
String msgText = ((TextMessage)msg).getText();
System.out.println("Message Received: "+ msgText );
} catch (JMSException ex) {
ex.printStackTrace();
}

} // onMessage

}
And here is simple sender program called sender.java

import javax.jms.*;
import javax.naming.*;
import java.util.Hashtable;

public class Sender {

public static void main ( String[] args ) throws Exception {

try {
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
env.put(Context.PROVIDER_URL,"t3://127.0.0.1:7001");
InitialContext ctx = new InitialContext(env);

QueueConnectionFactory qconFactory =
(QueueConnectionFactory)ctx.lookup(
"weblogic.jms.ConnectionFactory");

QueueConnection qcon = qconFactory.createQueueConnection();


QueueSession qsession = qcon.createQueueSession(false,
Session.AUTO_ACKNOWLEDGE);

Queue queue = (Queue) ctx.lookup("jms.MyMessageQueue");


QueueSender qsender = qsession.createSender(queue);

TextMessage msg = qsession.createTextMessage();

238
qcon.start();
msg.setText ("Hello world");
qsender.send (msg);
} catch (Exception e) {
e.printStackTrace();
} //catch
} // main
}

Compile this code.

Test by running "java sender" from the shell.

NOTE: if you run this from Eclipse/Weblogic Workshop, you will need to add EITHER
wljmsclient.jar OR weblogic.jar from your weblogic installation directory (ie:
/opt/bea10/wlserver_10.0/server/lib) otherwise you may get a run-time error.

Note that you can monitor your queues by using Services-> Messaging > JMS Servers
Choose the server (JMSServer) & then choose the Monitoring tab & then "Active
Destinations"
Note that the name of the queue is actually "SystemModule!MyMessageQueue".

Note that the Messages count increases each time you run the "sender".

Now let's receive the messages

If you run the receiver in a seperate window, you should see the messages get consumed.

Extra work

Develop a publish/subscribe version of the above.

Hints:

Refer to the lecture notes for the different names of the classes, for example, replace Queue
with Topic.

Also instead of receiving, you subcribe. Instead of sending, you publish.

239

You might also like