You are on page 1of 656

Team-Fly

iSeries and AS/400 Java at Work


by Don Denoncourt (ed) ISBN:1583470182
MC Press ?2001 (761 pages)
C ollected for OS/400 programmers who already have an
understanding of Java basics, these 64 previously
published articles are presented to help programmers gain
greater expertise in developing real-world applications.

Table of Contents

iSeries and AS/400 Java at Work


Preface
Section I - Overview
C hapter 1 - Business C ase For Java
C hapter 2 - Applets and Applications
C hapter 3 - An AS/400 Programmer's First Look At Java
Section II - A S/400 Toolbox for Java
C hapter 4 - Record-Level Access With The AS/400
C hapter 5 - C ommitment C ontrol For Record-Level Access
C hapter 6 - Encapsulation: Java Power With RPG Simplicity
C hapter 7 - Qshell And IBM's Java Toolbox For The AS/400
C hapter 8 - Java Servlet Programming For The HTML-C hallenged
C hapter 9 - Reducing Applet C ode Size With Proxy C lasses
Section III - JDBC: SQL For Java
C hapter 10 - JDBC Basics
C hapter 11 - Getting To Know JDBC
C hapter 12 - Prepare Your JDBC Applications For Performance
C hapter 13 - Using C ommitment C ontrol With JDBC
C hapter 14 - A Few JDBC Tips And Techniques
Section IV - Java Gui Programming
C hapter 15 - Java Foundation C lasses Basics
C hapter 16 - JFC Development With Templates
C hrome-Plate Your Java Gui With Dynamic Menus And A Status
C hapter 17 -
Bar
C hapter 18 - Just Browsing With JDBC
C hapter 19 - C heap Java Subfile Programming Tricks
C hapter 20 - GUI Builder Makes Java GUI Development Easy
Section V - Legacy Interoperability
Application Modularization—Separating Presentation And
C hapter 21 -
Programming Logic
C hapter 22 - Breaking Apart The Monolith
C hapter 23 - The Business of Java
C hapter 24 - C alling RPG From Java
C hapter 25 - Invoking RPG Via JDBC
C hapter 26 - TC P/IP Sockets Programming
C hapter 27 - Using Java Sockets Programming
C hapter 28 - Servlets, Sockets, And RPG
C hapter 29 - Using The JNI To C all RPG From Java
Section VI - Not Java
C hapter 30 - HTML Basics
C hapter 31 - HTML: The New 5250
C hapter 32 - HTML Form Validation With Javascript
C hapter 33 - Advanced HTML Form Validation With Javascript
C hapter 34 - Using C ookies To Pass Parameters Between Web Pages
C hapter 35 - XML: The Ubiquitous Language Of The Internet
C hapter 36 - XSL Stylesheets: Display Files Of The Web
C hapter 37 - Unix Developers Find A Home In Qshell
Section VII - Server-Side Java
C hapter 38 - The "Little Web Server" Project
C hapter 39 - Serving Up Host-Based Java Apps
C hapter 40 - JavaServer Page Basics
C hapter 41 - Servlets—The New Application Architecture
C hapter 42 - Maintaining Session State With Java Servlets
C hapter 43 - Send A Message With Javamail
C hapter 44 - Synchronization Issues With Java Servlets
C hapter 45 - Tomcat For AS/400: An Open-Source Web Application Server
C hapter 46 - Jump-Start Servlets And JSPs With Websphere Version 3.0.2
Section VIII - Java Performance
C hapter 47 - A Programmer's Notebook—Making Servlets Run Faster
C hapter 48 - Java Performance Tuning
C hapter 49 - Java Performance Tips
Section IX - Enterprise Javabeans
C hapter 50 - E-Business By Design With EJB
C hapter 51 - Enterprise Javabeans—Show Me The C ode!
C hapter 52 - EJB—What's Going On Here
C hapter 53 - Open-Source Enterprise Javabeans
C hapter 54 - Distributed Java C omputing With RMI
Section X - Odds A nd Ends
C hapter 55 - Soft-C oding Values For Java Applications
C hapter 56 - Java Source Level Debugger For The AS/400
C hapter 57 - Deliver Your Programs With Java Message Service
C hapter 58 - How To Build Opsnav Java Plug-Ins
C hapter 59 - Java Packaging
Section XI - Sample A pplications
C hapter 60 - A Java GUI For DSPFFD
C hapter 61 - Spool File To PDF, PDQ
The Spartan Order System—An Exercise In Java Application
C hapter 62 -
Design
C hapter 63 - Tracking AS/400 Vital Signs With SysStats
C hapter 64 - Free And Easy With WebSQL
Appendix - Software Loading Instructions
Index
List of Sidebars
List of Figures
List of Tables

Team-Fly
Team-Fly

Back Cover

If you are a good Java programmer who wants to become an excellent Java application developer, this book is for you. Originally
compiled by Don Denoncourt as a personal resource to help him develop and code Java applications for his consulting business,
iSeries and AS/400 Java at Work contains all the essential information Denoncourt has gleaned from his years as the editor of
AS/400 NetJava Expert technical journal, as contributor to Midrange Computing magazine, and as an award-winning seminar
speaker.

This book contains 64 chapters written by 18 leading Java experts on Java technologies. It is not a book for the beginner Java
programmer. Rather, it is the definitive second-tier education for Java programmers. Many know the language; those who
succeed in IT will know how to make the language work in a business environment. This book will show you how the experts are
getting it done.

Working with this book will help you to:

 Understand how to use the powerful classes that encapsulate access to OS/400 interfaces found in the AS/400 Toolbox for
Java
 Master the ins and outs of SQL access to the AS/400 database through JDBC
 Leave Abstract Window Toolkit (AWT) behind and start using the Java Foundation C lasses (JFC ) package to build tables,
trees, and tabbed dialogs
 Leverage both existing legacy applications and existing legacy knowledge to develop Web and GUI applications
 Integrate Java into the other Web application heavies: HTML, XML, XSL, HTTP, and UNIX shell programming
 Gain insight into how to harness the power of server-side Java and servlets
 Tune Java applications for ultimate performance
 Become an Enterprise Java Bean (EJB) expert
 Study real-world Java applications and utilities to learn how to integrate Java technologies

About the Author

Don Denoncourt was named Java subject matter expert for C OMMON in 1999. He programmed in RPG and C OBOL on the AS/400
for eight years before become an accomplished object-oriented C ++ and Java programmer. Don has been developing object-
oriented applications for over 10 years and has written dozens of articles on Java that have been published in a variety of
magazines. Today, Don is a successful IT consultant, editor of WebSphere Pro Developer Tips, and contributor to iSeries News
and WebSphere Professional magazines.

Team-Fly
Team-Fly

iS eries an d A S /400 Java at W o rk


E d ite d b y D o n D e n o n co u rt

Developed by Merrikay Lee, the at Work series gives working professionals the tools, techniques, and usable code they need
to craft streamlined solutions to everyday challenges.

Merrikay Lee is series editor for the MC Press line of professional books, which comprises more than 75 titles. She has spent
more than 20 years as a technical professional in the IBM midrange industry and 15 years in the publishing field. She is the
author of four books and has worked with numerous IT technical professionals to develop titles for the IBM midrange
community of IT professionals. She is president of MC Press, LLC in Dallas, Texas, and can be reached at
mlee@MCPressOnline.com.

Published by MC Press, LLC


President: Merrikay B. Lee
Publisher: David M. Uptmor

MC Press, LLC
Corporate Offices: 125 N. Woodland Trail, Double Oak, TX 75077 USA
Sales and Customer Service: P.O. Box 4300, Big Sandy, TX 75755-4300
Contact: 877.226.5394 or www.mcpressonline.com

First Edition
Second Printing—May 2002

© 1997- 2001 MC Press, LLC


ISBN: 1-58347-018-2

Every attempt has been made to provide correct information. However, the publisher and the authors do not guarantee the
accuracy of the book and do not assume responsibility for information included or omitted from it.

The following terms are trademarks of International Business Machines Corporation in the United States, other countries, or
both: IBM, AS/400, OS/400, and 400. Other trademarked company names and product names mentioned herein are the
property of their respective owners.

Printed in Canada. All rights reserved. No part of this publication may be reproduced in any form without prior permission of
the copyright owner.

For information on translations or book distribution outside the USA or to arrange bulk-purchase discounts for sales
promotions, premiums, or fund-raisers, please contact MC Press sales office at the above address.

M C P re ss E d ito ria l R e vie w B o a rd

Bob Cozzi
Don Denoncourt
Ron Hawkins
Ted Holt
David Morris Shannon O'Donnell
Doug Pence
Joe Pluta
Brian Singleton
Kevin Vandever

I'd lik e to dedicate this book to the guy who introduced me first to writing, then, years later, to Java—Richard Shaler. Richard
helped me become a writer back in 1991, he told me what the Internet was in 1994, and then, in 1996, he cajoled me into
investigating and then writing about the hot new Java programming language.

A ckn o w le d g m e n ts

I absolutely must acknowledge and thank the authors who contributed to the chapters in this book. Some of them are well-
known as leading experts on Java on the AS/400. I truly feel that Java wouldn't have been as successful as it has been
without the efforts of people like Joe Pluta, Paul Remtema, Alex Garrison, Keith Rutledge, and Jim Barnes. I also enjoyed
being pushed technically by Jeff Markham as he wrote a number of quality pieces.

I must give thanks to Kevin Vandever, Ted Holt, David Mayle, Richard Shaler, and Shannon O'Donnell because their
uncommon grasp of the English language allowed them to author pieces that made Java and Internet basics easier for all of
us to understand.
Walter Goodwin and Michael Polutta are top-quality programmers whom I had the good fortune to work with and learn from for
several years. Both Walter and Michael are natural writers whom I coerced into writing for Midrange Computing. I also worked
with Eduardo Ross, but whereas Walter and Michael were peers, Eduardo was my mentor. Eduardo taught me object-
oriented programming, C++, and, in general, computer science. In addition, I thank Brendan Farragher for his help in testing
the code.

Finally, this book wouldn't have happened without Merrikay Lee. But, then, no books for the AS/400 happen without some
intervention from Merrikay Lee. I think we all owe her a thanks.

Team-Fly
Team-Fly

P reface
Don Denoncourt

For IT shops to adopt radically new technologies requires a big hard push. What seems like ages ago, machine language
programmers scoffed at the idea of using assembly languages. Rapid advances in computer platforms and the heavy demand
for the automation of accounting applications forced machine language programmers to move to assembly languages. The
next big technology was higher-level, or third-generation, languages. This time it was the assembly language programmers
who scoffed at high-level languages (HLLs). But, once again, the speed with which HLL programmers could develop business
applications far surmounted that of the assembly language programmer.

The HLL languages of RPG and COBOL were used to develop the applications that coordinate a large portion of the world's
business activity. But even in the 30-year reign of HLL, there was yet another major technological advancement—relational
databases. I was a part of the mass of RPG programmers who had to let go of the hierarchical databases of System/3
applications for the advanced capabilities of relational databases. The dynamic capability of relational databases accounts for
many of the advances RPG III made over RPG II.

RPG and COBOL programmers still have not yet adopted two other technological advances: modular programming and
object-oriented (OO) programming. Yes, RPG IV has powerful modular programming strengths, and the OO language of C++
has been available for OS/400 programming since Version 2 Release 3. Why weren't these two technologies adopted?
Because there wasn't a big enough push to drive programmers from the reliable programming practices to RPG IV or to make
a complete switch to C++.

N o w 's T h e T im e T o L e arn Jav a


Yet Java has been adopted at a rate far faster than C or C++ ever was. So what was the technological push that forced
application programmers to move to Java? The Internet. Java is known as an Internet language because most of its APIs use
a TCP/IP interface. Do you want to extend your company's applications to the Internet? Then you need to consider using
Java.

Today, Java is a pervasive technology. AS/400 shops are clamoring for Java expertise so that they can modernize their
business applications. Many of you have learned the basics of Java and now you're ready to use it in real-world applications.
Java architectures, Java development environments, and Java APIs have matured, and now you are ready to learn the real
business-world techniques required to develop 21st-century quality applications. You are ready to put Java to work.

To assist OS/400 programmers in learning the best techniques for authoring Java applications, I've selected 24 (64) of the best
Java technology pieces from various MC authors for inclusion as chapters in this book. As a result, this book contains
chapters written by leading experts in the field of Java programming for OS/400. Java at Work is second-tier education for
Java programmers. Many of its chapters are excellent tutorials with great example code. That example code is on the CD.
There are also a number of chapters that provide useful Java utilities, such as one that converts OS/400 spool files to Adobe
Photoshop Acrobat Reader (PDF) files. Again, the code for those chapters is on the CD.

Team-Fly
Team-Fly

G e ttin g S tarte d
The first three chapters provide a great introduction to the business side of Java programming. Keith Rutledge, an executive
with IBM, authored Chapters 1 and 2: "Business Case for Java" and "Applets and Applications." Keith is frequently consulted
by IT directors of major corporations, and his "Business Case for Java" summarizes the information that he provides to these
Fortune 500 companies. Numerous companies have achieved the return on investment that Keith qualifies in Chapter 1. The
second chapter, "Applets and Applications," introduces two of the three main deployment options for Java. The third option is
covered in detail in Section VII, "Server-side Java." Server-side Java was introduced by Sun Microsystems in the spring of
1998, which the original publication date of Keith's chapter predates.

Richard Shaler, the person who introduced me to Java, wrote the third chapter, "An AS/400 Programmer's First Look at Java."
Back in 1997, Richard had originally asked me to write this piece, but I turned the opportunity down because, at that time, I
couldn't see wasting my time with this new language. I quickly changed my mind, but now you have a great chapter on Java
syntax that was written by a better author than me.

While the three chapters that make up Section I provide a solid overview to the Java language, I have made no attempt to
teach Java syntax in this book. This book is for good Java programmers who want to become excellent Java application
developers. You might want to have a complete book on Java syntax, such as George Farr and Phil Coulthart's Java for RPG
Programmers or Java for S390 and AS/400 COBOL Programmers, within arm's reach of your development machine.

Team-Fly
Team-Fly

F u ll T h ro ttle
After the introduction to the Java programming language, the next sections include chapters that explain how to use Java for
real-world applications. Section II, "AS/400 Toolbox for Java," covers how to use the IBM package of Java components. IBM's
AS/400 Toolbox for Java contains components that will allow you to do with Java all the same things that you can do as a
power RPG, COBOL, or CL programmer. Section III, "JDBC: SQL for Java," covers how to use the SQL of Java Database
Connectivity to manipulate relational data. Though OS/400- specific techniques are covered, for the most part, the examples
in this section will run on any relational database. Section IV, "Java GUI Programming," gets you started with event-driven
programming for client-side Java applications.

Most OS/400 shops will be using Java as Internet "middleware" that puts a Web front-end to RPG and COBOL applications.
Section V, "Legacy Interoperability," covers half a dozen different ways for Java and RPG/COBOL to communicate: Java
Native Interface, SQL stored procedures, sockets, data queues, the ProgramCall class, and HTTP tunneling.

Some say the hardest part of learning Java is learning all the other supporting technologies: HTML, HTTP, JavaScript, XML,
and Extensible Stylesheet Language (XSL). The chapters of Section VI, "Not Java," tell you much of what you need to know
about these various technologies.

Truth be told, I think Java would have died were it not for server-side Java. As a client-side language, Java competes with too
many other great languages, not the least of which are Visual Basic, C++, and Delphi. Java applets have the infamous
problem of slow download speeds. Server-side Java is where it's at with Java. There are still many viable reasons to use Java
for client-side apps or to use Java applets, but 90 percent of Java applications are written as server-side Java. That's why
Section VII, "Server-side Java," is probably one of the most important sections of this book.

But once you deploy those server-side Java applications, you may have to revisit your code so that the application performs
adequately. Section VIII, "Java Performance," includes three chapters that will provide you with the knowledge base to
performance tune your applications.

If you are going to develop an all-Java application, then the use of Enterprise JavaBeans (EJBs) bears serious consideration.
Section IX contains several chapters that will provide you with enough information to decide whether the technologies of EJBs
are needed for your next application.

Section X, "Odds and Ends," contains some chapters that cover how to use technologies that didn't cleanly fit in other
sections. In this section, you'll learn how to soft-code configuration settings, debug Java on the OS/400, and communicate
asynchronously with Java Message Service. You'll also learn how to code Operations Navigator plug-ins with Java and how to
properly package your Java applications for reuse.

The last section, Section XI, "Sample Applications," includes five cool sample applications. One shows how to build a Java
GUI for the Display File Field Description (DSPFFD) command's output. Another shows how to convert spool files to PDF.
The third chapter shows a complete, if trivial, application that contains all the code to wrapper access to relational data and
present a GUI for an order-entry application. Another chapter gives an example of how to track your AS/400's vital signs with a
sophisticated Java GUI. Finally, there's a server-side Java application that gives you interactive SQL.

Java at Work is an indispensable toolkit that should be kept not on your bookshelf but on your desktop. It is an essential
book for the Java application developer and programmer. You need to interface Java with RPG? There's a whole section on
how to do that. Want to know how to create an HTML subfile with server-side Java or know where XML and XSL fit into Web
applications? A dozen experts share their techniques. Want to know how to edit HTML form fields with JavaScript?
Supporting Web technologies such as HTML, JavaScript, XML, and XSL are covered. Are you ready to move on to the full-
blown, all-Java technologies of EJBs? There is a section on that. Are you sitting at a client site and can't quite remember the
cool Java coding technique that would easily solve your current problem? Look it up in Java at Work and then copy the
example code from the CD. Whatever you need to know…trust me, it's in here!

Team-Fly
Team-Fly

S e c tio n I: O verview
C h ap te r L ist
Chapter 1: Business Case For Java

Chapter 2: Applets and Applications

Chapter 3: An AS/400 programmer's First Look as Java

P art O v e rv ie w
Section I includes three chapters that are great introductions to the business side of Java programming. Keith Rutledge, an
executive with IBM who is frequently consulted by IT directors of major corporations, authored the "Business Case for Java"
and "Applets and Applications." Keith's "Business Case for Java" summarizes the information that he provides to Fortune 500
companies. Numerous companies have achieved the return on investment that Keith qualntifies in Chapter 1.

The second chapter, "Applets and Applications," introduces two of the three main deployment options for Java. The third
option is covered in detail in Section VII, "Server-side Java."

Richard Shaler wrote Chapter 3, "An AS/400 Programmer's First Look at Java." This chapter presents a condensed
introduction to Java from an AS/400 perspective.

While the three chapters that make up Section I provide a solid overview to the Java language, no attempt is made to teach
Java syntax. The intent here is for good Java programmers to become excellent Java application developers.

Team-Fly
Team-Fly

C h ap ter 1: B u sin ess C ase F o r Java


O v e rv ie w
Keith Rutledge

Java is hot! Or is it? If you ask a technical person, Java is most decidedly hot! If you ask a businessperson—such as the
comptroller at your company—Java might look like yet another soon-to-be-unfulfilled promise of Nirvana in the IT department.
Businesspeople have a well-earned skepticism about any new IT panacea, and right now they could be forgiven for mistaking
Java for the latest one.

Businesspeople evaluate trends like the Java phenomenon in monetary terms. If it proves itself a moneymaker over some
reasonable business period, then it's probably a good thing. If it doesn't, and it isn't mandated by some external controlling
body like the government, then business logic says don't do it—no matter how technologically exciting it is.

When you look at the reasons companies cite today for moving to Java as a primary software technology, most of them
appear, at first glance, to have a propeller-head bias. Reasons often mentioned for using Java today are cross-platform
compatibility, programmers' interest in Java, and an open computing environment.

Hmmm, OK, I'm a businessperson, and I'm supposed to go to Java because it runs on a lot of computers and my
programmers like it. Please! In my business, we don't let the dump-truck drivers pick the trucks, and we don't let the
programmers pick the IT infrastructure technology.

There are solid business reasons for using Java and for using AS/400e as your primary Java server, but most analyses of Java
to date have focused on the gee-whiz technological aspects of Java. Such reasons won't cut it when Dr. No gets hold of your
pet Java project. (Every successful company has a financial officer with the responsibility of saying "No" to fanciful, but
unjustified, projects.)

In AS/400e shops, the business case for Java rests on the twin pillars of Java capabilities and the inherent strengths of
AS/400e as a Java server. Java provides a never-before-seen capability to change the way businesses create and use
software. This capability derives from the combination of Java's universal deployability, object-oriented (OO) characteristics,
accessibility (here, I use the term accessibility in the educational sense, meaning that programmers can get at, understand,
and use its capabilities), and TCP/IP support (i.e., World Wide Web) computing.

OO software can be deployed in an iterative, piecemeal fashion that closely matches the way that people develop and use
business processes. OO software development and deployment can be more responsive and less affected by change than
other software technologies. When you combine OO capabilities with AS/400e Java servers and systems, you have an
integrated, reliable, and manageable business-process software infrastructure that can yield real-dollar benefits for your
company. You will be supporting software reuse, establishing an incremental software development and deployment
capability, enabling an any-to-any strategy for access to enterprise IT resources, and permitting skill-set reductions.

The following sections examine those twin pillars (Java's capabilities and the strengths of AS/400e as a Java server) in detail.

Team-Fly
Team-Fly

W rite O n ce , R u n A n y w h e re
Write Once, Run Anywhere (WORA) code is a reality with Java. If such code weren't possible, Java usage on the Internet
would be nonexistent. Sure, it's possible to write Java code that will run on only one platform, and sometimes it makes sense
to do so. It's also possible to optimize Java for performance. But, most of the time, it makes business sense to write Java
code that is optimized for portability.

The key terms (which Sun Microsystems coined) are "100% Pure Java" and "Java Compatible." The phrase 100% Pure Java
means using the Java language itself to accomplish the task at hand, rather than going around or outside the language to use
an external component or add-on. Java Compatible is the other side of the portability coin. To be certified as Java Compatible,
a system must pass an exhaustive suite of tests that ensures it will correctly run 100% Pure Java programs.

Most businesspeople understand the value inherent in WORA code: The benefits of portable code and skill-set reduction
result in lower cost, and more effective software development and deployment. What those businesspeople aren't sure about
is the claim's credibility. Companies that want Java to succeed as a language but not as a cross-platform software
deployment technology have exploited this insecurity.

However, experienced Java programmers know that WORA code is real and that it is an achievable coding practice. I have
written Java code on OS/2 and then run it on OS/2, Windows 95, and AS/400e. I have also assisted in porting large Java
programs (low six-figure lines of code) from Windows NT and UNIX to AS/400e. Porting meant copying the program to the
AS/400e and seeing if it ran. It did. WORA is a real business advantage for Java.

IBM's SanFrancisco project is another example of meaningful cross-platform Java deployment. SanFrancisco is a set of
cross-platform business objects written in Java. These objects constitute the core functionality of business applications such
as general ledger, accounts receivable, accounts payable, order management, and warehousing. Together, these objects
make up a large (hundreds of thousands of lines of code) line-of-business application that runs on OS/2, Windows 95,
Windows NT, AIX, Sun, AS/400e, and several other platforms. WORA code works.

The value of portable, WORA code is skill-set reduction. If your programmers can work in only one language, then they can
concentrate their energies on the most effective use of that language. And you can reduce the number of software
development tools that you buy and support. When I switch from one language to another, even to a language that I know
well, a certain amount of paradigm shifting occurs. Paradigm shifting does not contribute to programmer productivity.

Team-Fly
Team-Fly

P ro d u ctiv ity
Productivity is often touted as a strength of Java. Because all new languages claim productivity as a benefit, I was skeptical
when I first heard this theory.

Java productivity comes in three forms:

 Language-inherent productivity gains.

 Tool-based productivity gains.

 OO reuse of code.

Java is more productive than some languages for some tasks and less productive than other languages for other tasks. In
other words, it's pretty much the same as any other language. For Web development, Java is the winner hands down. No
other language even comes close. Because Java requires less (as in none is less than some) management of machine-
oriented details such as memory, pointers, and the operating system, C++ programmers consider Java a major productivity
improvement.

Programmers coming to Java from other non-OO languages find mixed results. However, within six months to a year, as
these OO neophytes become proficient in Java, they too begin to see productivity improvements.

Tool-based productivity gains appear to be real. Java is the most recent language introduced in our industry. Being the newest
means having the newest, most evolved development tools. My experience with IBM's VisualAge for Java (VAJ) indicates that
the productivity gains are quite large. With VAJ, I have produced code at a rate of better than 30,000 lines per day. While that
isn't sustainable, large quantities of code can be cranked out using a visual development tool. And, the code is high quality.

OO code reuse is a very important business benefit, and Java is an OO software development tool with a well-documented,
pragmatic set of standards for writing reusable code. Good OO strategy involves developing software components that
combine with other components to produce an application. These software components can work at many different levels
within the hierarchy of component combinations. A software component can be a fundamental component (like a brick in a
house), or it can be a component that is a combination of many fundamental components (just as a stove in a house
combines a metal structure, heating elements, and control switches).

Once a component is developed, tested, and given the capability to tell other systems about itself, it can be widely reused,
just as a standard brick can be used interchangeably in the structures of many different houses. Just as the original brick
specification is implemented as many individual bricks, so the Java component (a.k.a. JavaBean) is implemented as
individual objects based on the original component specification. The business productivity gain is real. A little care in design
today means that the component that you write today can be reused well into the future. And you don't have to rewrite the
functionality represented by the component again and again, as you have come to expect with legacy applications (or even a
poorly designed OO application for that matter).

Team-Fly
Team-Fly

L e v e rag e T h e W e b
Java is the language for Web development. It was designed to include TCP/IP network support such as sockets, URLs, and
the other IP network functionality necessary to develop network-centric software. You can extend the reach of your existing
enterprise software, data, and computing resources to the Web via Java without redoing the existing resource base. An
existing program can be front-ended with a Java applet to make it available to anyone you choose anywhere in the world.
Although some might decry this as "screen scraping," it makes excellent business sense. Your existing programs are a large
investment of time and dollars. Increasing their value by extending the reach and utilization of those programs is a smart move
and an effective use of technology. Java can do the same for your enterprise data and computing resources. Java applets can
help you provide your authorized users with access to your enterprise databases and server resources from anywhere.

Actually, this access by any authorized user to any (authorized) content on any (authorized) server is one of the main
reasons that the Web has been so successful. Instead of providing predefined mechanisms—and especially predefined
paths—for access to IT resources, authorized users are permitted access to any IT resource that helps to accomplish their
jobs. Java, as the software development component of the Web, is an important part of an "any-to-any" information-de- livery
strategy. Of course, it's important to ensure that only authorized users are allowed access. Java was designed with security
in mind and provides the necessary tools to ensure that your business knowledge base can be delivered safely over the Web.

An important part of "any-to-any" access is server-side computing. Server-side computing takes advantage of your expensive
servers by using them for computationally intensive tasks such as searching large databases, building complex knowledge
bases, or making large-scale changes to enterprise data (e.g., all prices just went up by 3.5 percent).

Business-rule layer content is generally placed on the server as well. Business-rule content is the expression in software of
how you run your business. For example, if your policy is to provide a 2 percent discount for receivables paid within 10 days,
then your receivables software must implement logic that supports this policy. This implementation of your business policy is
contained in the business-rule layer of your software. Java's client/server programming capabilities and fundamental OO
nature support the realization of your business policies into client and server software components that match your business
model.

Portability is a major issue for servers, too. Very few shops of any size have only one (or only one type) server. Most shops
today have multiple servers of multiple types (e.g., AS/400e, NT Server, UNIX, etc.). The ability to run server-side code on any
of those servers is an important aspect of WORA code and skill-set reduction. The heterogeneous server farm is a reality
today for business. Java is an important step toward using those varied servers more effectively and returning greater business
value from expensive capital assets.

I believe that server-side Java will eventually dwarf client-side Java in terms of value delivered to business. There will probably
always be more client Java programs on a unit-count basis, but on a dollar-value-delivered-to-business basis, server-side Java
will be much larger and more important.

Team-Fly
Team-Fly

A S /400e A n d Jav a
The business case for Java on AS/400e is built on the Java capabilities I've discussed combined with the AS/400e business
case for Java. The AS/400e business case for Java depends on the details and the excellence of the implementation of Java
technology using a combination of AS/400e hardware and OS/400 and integrating these two components with Java to provide
a complete Java server.

AS/400e has true 64-bit computing. Bits are like dollars; you might or might not benefit from having more of them, but
everybody wants more. Having more bits in a process means a larger addressable memory space, wider data paths, and the
potential capability to execute more instructions per clock cycle. That all adds up to more powerful computing. So, if the
engineers at IBM have been clever (and they have) in exploiting 64-bit processor technology, AS/400e has a potential
advantage over most servers available today.

Because Java programs run in a large memory space, the memory-space issue is especially important to Java. AS/400e also
has up to 12-way symmetric multiprocessing (SMP) support. Therefore, an AS/400e can grow (or scale) to support very large
business computing tasks with Java. AS/400s also have many dedicated auxiliary processors to handle chores like the
network interface or disk I/O. As a result, Java server programs running on AS/400e are less affected by low-level hardware
tasks. AS/400e has many other hardware technology advantages; a dispassionate analysis yields that AS/400e is a good
hardware platform for Java.

OS/400 is very interesting in how it matches up with and supports Java. First, OS/400 is an object-based operating system.
Everything in the system is an object and can be accessed only by externally described mechanisms (methods in OO speak)
and attributes.

One of the more important mechanisms is a security mechanism that can distinguish user objects from system objects and
can prevent user objects from accessing or modifying unauthorized areas of the system. AS/400e security is a clear
advantage for implementing Java on an AS/400e. OS/400 provides a facility called system-managed storage.

Programmers and data analysts can concentrate on the business-rule layer content and spend less time on low-level storage
management issues. AS/400e system- managed storage complements Java's information storage paradigms, which hide the
underlying physical structure of the information from the programmer by representing it as objects. And OS/400 runs Java
programs below the Technology Independent Machine Interface (TIMI). Programs running below the TIMI perform better, are
more scalable, and are more resistant to being hacked.

AS/400e integration is an important part of the AS/400e business case for Java. IBM combines the hardware and operating
system to yield a very reliable server. Designing and testing an AS/400e as a complete unit means that hardware and
software can be optimized for each other. The AS/400e has an uptime percentage of better than 99 percent. Less downtime
means less expense for your business. That's one important reason why AS/400e-based information systems have the lowest
life-cycle cost of computing for client/server systems (Source: Server Life Cycle Ownership Costs: Support Costs
Relationship to Operating Environment Integration IDC, August 1997, Framingham, MA 508/872-8200).

Team-Fly
Team-Fly

A S /400e Jav a T e ch n o lo g y
Now for AS/400e Java technology. AS/400e Java technology includes the Java Virtual Machine with Java Transformer, a Java
Development Kit (JDK), the AS/400e Toolbox for Java, VisualAge for Java for AS/400e, and the SanFrancisco project.
Borland's JBuilder Java development tool also supports the AS/400e by integrating the AS/400e Toolbox for Java into it.

The AS/400e Java Virtual Machine (JVM) is a 64-bit Java Compatible JVM. It runs under the TIMI, includes a dynamic Java
Transformer, and has advanced garbage collection. The Java Transformer converts your Java programs at load time into 64-bit
machine instructions to take advantage of AS/400e large memory spaces and processor capabilities. In short, it makes your
Java programs run faster. There is no loss of portability, because the byte code is still 100% Pure Java. Java programs just
run faster on AS/400e.

Advanced garbage collection is a key scalability issue for large Java programs. Sun Microsystems has done research that
indicates that Java programs spend 20 percent of their program runtime on garbage collection. For more information, see the
article at:

www.javaworld.com/javaworld/jw-03-1998/jw-03-hotspot.html.

In Java, garbage collection is the disposal of unused objects. It is done automatically in Java (like I wish it was done at my
house). Most JVMs use "stop and copy" garbage collection. This is just like at my house. When I'm taking out the garbage,
I'm not doing something productive—like watching football. AS/400e has an advanced garbage collector that does not stop the
running program to do garbage collection. Again, Java programs run faster on AS/400e.

The AS/400e JDK is the AS/400e version of Sun Microsystems' JDK. The AS/400e JDK includes the static Java Transformer.
The static Java Transformer will let you convert—ahead of runtime—your Java programs into optimized 64-bit AS/400e
executable objects. These optimized, compiled, 64-bit programs run faster because the conversion to machine instructions is
done ahead of time, and AS/400e can optimize the code. There is no loss of portability, because the 100% Pure Java
program still exists and is completely portable. Your Java programs just load and run faster on AS/400e.

AS/400e Toolbox for Java is a set of software components for accessing AS/400e resources. These components provide
access for Java-capable client computers to get to the AS/400e database, print files, data areas, programs, and other
resources on the AS/400e. Remember that a client is any computer that accesses another computer's resources. So, a
client using the AS/400e Toolbox for Java could actually be another server or a traditional client. These software components
provide access to AS/400e for client/server or network-centric computing. Using these components to provide access to
AS/400e improves programmer productivity and enables faster delivery of AS/400e resources to any authorized user on any
Java-capable client that can manage an IP connection to the AS/400.

VAJ for AS/400e is an award-winning, highly productive development tool that can be used to develop Java programs that run
on AS/400e or that run on clients to access AS/400e resources. It is tightly integrated with AS/400e, offering cooperative
debugging and "smart guides" for interacting with AS/400e resources. IBM's SanFrancisco is a large collection of business-
process Java objects that provide business-rule layer functionality.

Team-Fly
Team-Fly

Jav a M ake s G o o d B u sin e ss S e n se


So, what does all the above add up to? The business cases for Java and AS/400e complement each other. Java offers WORA
software technology, the most usable OO software technology yet delivered to the commercial marketplace, and dramatic
gains in programmer productivity. AS/400e offers a powerful, scalable, integrated system that provides better support for large
Java server-side programs, enables the "any-to-any" computing model with broad and deep client support, and provides the
most reliable server on the market today. All in all, Java is pretty compelling to both CIOs and AS/400 programmers.

Team-Fly
Team-Fly

C h ap ter 2: A p p lets an d A p p licatio n s


O v e rv ie w
KEITH RUTLEDGE

Many folks new to Java find the distinctions between applets and applications unsettling and more than a little confusing. I
have even had programmers learning Java make the case to me that these distinctions and the differing requirements and
capabilities between running in a browser and running in a Java Virtual Machine (JVM) belie the Write Once, Run Anywhere
hyperbole about Java. The distinctions, however, are relatively straightforward, and once they are mastered, a programmer can
use a reasonable programming technique—discussed in this chapter—to create a Java program that will run in a browser (an
applet) or in a JVM (an application).

First, I'll define some terms. An applet is a Java program that runs in a browser. Stated more accurately, a browser provides a
context in which an applet can execute. A context is defined pretty much as the dictionary defines it: the circumstance in
which a particular event occurs; the situation. The browser (which is itself a program) can and does invoke methods to
initialize, start, stop, and destroy the applet program. This chapter discusses how the browser starts the applet program,
finds the resources for the program to run, updates and refreshes the program, and, finally, disposes of the program.

Also covered are Java applications and how they compare with applets. Java applications are programs that run in the context
of a JVM rather than in a browser. The services provided by the JVM are different from those provided by a browser. The
capabilities afforded to an application, especially I/O capabilities, are different by design; applications have more control over
their life cycles from start to finish. At the end of the chapter, I present a practical design model for real-world Java software
and position AS/400e as a Java server.

Team-Fly
Team-Fly

T h e S tru ctu re O f A n A p p le t
Looking at some code will illustrate how the two types of programs differ in their architecture. Figure 2.1 shows the skeleton
of an applet with the four milestone methods (in
in it rt, sto p , and d e stro yy) of an applet's life cycle in place, but with no code
it, sta rt
in the methods.

F ig u re 2.1: An applet has four milestone methods: init, start, stop, and destroy .

First is the in it method. The in it method is called by the browser that loads the applet. The browser knows to load the applet
because of the applet tag in the HTML document, which the browser loaded first (more about that in a moment). The in it
method contains (as you might expect from its name) initialization code, plus code that you want to run once and only once
for your program. The in it method is guaranteed to precede sta rt and runs only once.

The sta rt method runs after the in it method and is called by the browser whenever the HTML page is revisited. An example of
revisiting a page is pressing the Reload or Refresh key. When a user loads or reloads a page, the browser calls the sta rt
method. Code that you want to run only once for program initialization should definitely not go here.

I once wrote a program that added a text box to the applet in the sta rt routine. Each time I refreshed the screen, the program
dutifully added the text box again. This was not the behavior that I wanted, but it was the behavior that I specified by putting
a d d in the sta rt method. It would have been much better to put a d d in the in it method.

The sto p method is called by the browser each time the page is exited. This prevents running applets from continuing to use
processor resources when they are not being viewed in the browser. S to p is guaranteed to run prior to the d e stro y method
and runs one last time if the d e stro y method is called. The sto p method is a good place to temporarily release resources to
avoid contention.

The d e stro y method runs just prior to garbage collection (disposing an object) and always follows the sto p method. The
d e stro y method is the method that should contain final cleanup code. It should release all open resources, finalize any
necessary states, and release any connections back to the server that served the applet.

Three other methods that are often used when writing applets are worth mentioning: p a in t, re p a in t, and u p d a te
te. These
methods are not shown in Figure 2.1, but applets that have a dynamic display will use one or more of these three methods to
present a customized graphic, such as animation. The p a in t, re p a in t, and u p d a te methods are defined in the base
component class, appropriately called C o m p o n e n t, in the ja va .a w t package. The p a in t method is the fundamental
mechanism that Java's Abstract Window Toolkit (AWT) components use to draw themselves on the screen.

Most components, such as buttons, list boxes, and so forth, handle their own painting, but if you use components that don't
know how to draw themselves (e.g., Canvas, Panel, or Applet), then your derivation of that class must define a p a in t method
to draw your desired graphic. You don't have to directly call the p a in t function; Java's AWT task manager automatically
invokes p a in t when the component needs to be redrawn, when the component is first brought on-screen, or when the
component is re-exposed or scrolled. P a in t is also called by the u p d a te method.

On the other hand, the re p a in t function is designed to be directly called. When you invoke re p a in t, it basically asks the
AWT task manager to call the u p d a te method on the component as soon as possible. The u p d a te method then works with
p a in t to update the appearance of components.

The thing to remember is that, as long as you are using standard graphical components such as lists, menus, and text fields,
you don't have to worry about coding your own p a in t, re p a in t, and u p d a te methods. But once you require a custom
graphical display, you will have to understand and use these three methods.

Team-Fly
Team-Fly

R u n n in g A n A p p le t
How does a browser know to load an applet? There is a tag in HTML called the applet tag. Figure 2.2 provides the complete
syntax of the applet tag in Java Development Kit (JDK) 1.0.2. JDK 1.1.x adds two new attributes: ARCHIVE and OBJECT.
Figure 2.3 shows how the applet tag might look in actual use in an HTML file.

F ig u re 2.2: HTML has a tag that allows you to embed a Java applet inside a Web page.

F ig u re 2.3: The applet tag qualifies the name of the applet and the size and location of the Java window with the Web
page.

The following is a brief explanation of the applet tag. For more information on applet tags and attributes, consult an HTML
manual. An applet tag starts with a less-than symbol (<) and the keyword APPLET (<applet). The rest of the attributes
follow in what is actually no particular order (within the applet tag).

The CODE attribute specifies the compiled class file that contains the applet. This code is located relative to the code base.
The applet name, but not the extension (.cla ss), is given. The CODEBASE is an absolute URL that specifies the location
.cla ss
where code and resources will be loaded from. ALT specifies what text to display if the browser can read and understand
applet attributes but can't run Java code.

WIDTH and HEIGHT are required attributes that give the initial width and height in pixels. NAME is an optional attribute that
specifies a name for the applet on the browser page, which makes it possible for applets running on the same page to find
and communicate with each other. ALIGN is an optional attribute that specifies the alignment of the applet (i.e., left, right, top,
middle, or bottom). VSPACE and HSPACE are optional attributes that specify the number of pixels above, below, and beside
the applet. PARAM is a method for specifying an applet-specific parameter. PARAM is how you pass parameters into an
applet. Use a lte rn a te h tm l to provide HTML for browsers that don't understand the applet tag. A greater-than sign (>) ends
the applet attributes, and the applet tag ends with </applet>.

Team-Fly
Team-Fly

Jav a A p p licatio n s (N o B ro w se r R e q u ire d )


Now I'll explain a Java application. Remember that a Java application runs in a JVM rather than in a browser. Figure 2.4 shows
an application skeleton.

F ig u re 2.4: The main method is the entry point of a Java application; it is automatically called when you invoke the JAVA
command and the application's class name from a command line.

The first line is an IMPORT statement. In this case, the program is importing the ja va .io package, which provides file and
stream I/O functionality. The second line declares a class. Following the class variables (only a comment line in this program)
is the m a in method. The m a in method is unique to applications. A Java application does not have the system-defined
milestones of in it rt, sto p , and d e stro y that an applet does. When you run a Java application, the system implicitly
it, sta rt
locates and runs the m a in method. The m a in method must be preceded by three keywords: PUBLIC, STATIC, and VOID.
The m a in method accepts a single argument, which is an array of strings that act as the entry parameters list. In addition to
the m a in method, your program will probably have other methods that do useful tasks.

Team-Fly
Team-Fly

A p p le ts C o m p are d W ith A p p licatio n s


Applets and applications differ in their capabilities and behavior. Applets are well-mannered guests from another system.
Applications are resident on the local system and behave as though they are at home. Table 2.1 summarizes the differing
capabilities and behavior of applets versus applications.

T a b le 2.1: A p p le ts vs. A p p lica tio n s

A p p le t A p p lica tio n
Not resident on local system; loaded from server at Must be installed on local file system.
runtime.
Loaded by HTML tag. Runs explicitly as parameter to JVM invocation.
Must run within GUI framework or context. Can be GUI or non-GUI.
Has well-defined life-cycle milestones (init, start, stop, Starts at main method.
destroy).
Flow of execution partially controlled by browser. Flow of execution completely under program control.
Runs in a "sandbox," so it is more secure. Security is according to the Java security model.
No constructor; uses the init method to initialize. Best to provide a constructor; compiler provides default
constructor if none present.
Socket connections permitted to host that served applet. Socket connections permitted to arbitrary hosts.
Can't load native code. Access provided to native code.
Audio interface. No audio interface.

It is possible to write a Java program that will run as an applet or an application depending on the calling context (browser or
JVM). To do so, you write an applet that includes a m a in method. The m a in method will provide a place for the applet to start
running when it is called as an application; the m a in method will be ignored if the Java program is run as an applet. This
method must create an applet instance and place it within a frame. The m a in method must also invoke the applet life-cycle
methods (inin it rt, sto p , and d e stro yy) at the appropriate times to simulate a browser context.
it, sta rt

Examples of this technique can be found in many books on Java, but the one that I recommend is The Java FAQ by Jonni
Kanerva, published by Addison-Wesley (ISBN 0201634562).

Team-Fly
Team-Fly

Jav a Is S to re d In JA R S
Java programs are often loaded across a network. They can be packaged to make moving them across the network easier
and faster. The JAR file format (Java is stored in jars, get it?) creates an archive of multiple Java programs that can be moved
and stored as a single entity. The JAR file format is a general-purpose storage format based on the well-known PKWARE .zip
file format. Packaging your programs into JAR files permits the single movement of a compressed file, rather than multiple
movements of uncompressed files. Individual entries in the JAR file can also be digitally signed to authenticate their origin.

A JAR file is created using the JAR utility that came with your JDK 1.1 JVM. Applets created prior to JDK 1.1 can use JAR
files by adding the ARCHIVE attribute to their HTML applet tags. The ARCHIVE attribute is a rch ive = "ja rs/ja rfile .ja r"
r".

The JAR format handles audio and image files as well as class files, works with existing applets, and is itself written in Java.
The JAR format is the preferred way to package the pieces and resources needed for an applet to run. The syntax for the JAR
command is shown in Figure 2.5.

F ig u re 2.5: The JAR command is similar to the Zip utility in that it has options that allow you to create a file that contains
compressed files and then to decompress those files.

Team-Fly
Team-Fly

W h ich T y p e Is R ig h t F o r Y o u ?
Which type of Java program will you write? That's a philosophical, an architectural, and a program-design question. If you
want to let someone else manage much of the user interface services, if you don't want or need your programs to access the
executing machine's file system, and if you want everything to run from a central code base, then applets could be a good
choice. If you require access to local file systems and multiple arbitrary hosts in your network, or if you need to run in batch,
then applications are probably the way to go.

Most of the noise so far in Java has been about client applets. Web programming in Java delivers client applets that interact
with the user and maybe the host that served them. Applets can be very useful for graphical tasks or for front-end tasks such
as a data entry screen. Applets are in wide use today and will most likely be part of any significant Java code portfolio.
Applets are the mechanism for extending an existing enterprise application to the Web.

Applications can do heavier lifting than applets. Applications have access to the local file system, have access to native code
(through the Java Native Interface, or JNI), and can run without a GUI (making them well suited for unattended tasks such as
batch execution). Also—and this is not yet widely appreciated—because applications run in a JVM instead of a browser, they
can be used to handle larger computing tasks. JVMs run on both client machines (e.g., Windows 95) and server machines
(e.g., AS/400e). A JVM running on an AS/400e with 256 MB of memory (or more) and 8 GB of disk (or more) can run a much
larger program than a browser running on a Windows 95 machine with 16 MB or 32 MB of memory.

Team-Fly
Team-Fly

Jav a A n d A R e alistic D e sig n M o d e l


Most software implementations done in Java will use both applets and applications. Applets will provide access across the
network to the functionality contained in the software. Applications will be used for client software where the infrastructure is
under control, supports Java application requirements, and will be used for the other tiers of an n-tier client/server architecture.
Java software will be done as a multiple-tier (2, 3, or n) client/server system.

Many people use the term network -centric to describe the architecture of software written using Java. That term probably is
better; it avoids all those tiresome discussions of client/server models.

I think that software written in Java will, over time, arrive at a four-layer (or tier) model. I deliberately avoid the terms client and
server here to avoid mapping this relatively simple conceptual architecture onto an existing model; I feel that this approach is
simpler.

In the four-layer model, there will be a user interface layer, which will use Java applets or applications. There will be a request
broker layer, the function of which is to manage (prioritize, schedule, and monitor) requests from the various users in the
network to the various providers in the network. There will be a business-rule layer. The business-rule layer will contain "debits
equal credits" kinds of logic and will provide business functionality. And, finally, there will be a data layer. The data layer will
provide data management and integrity functionality.

Already in use today, this is a straightforward model against which to design software. I feel compelled to acknowledge that,
in any real system, a lot of functionality crosses these conceptual, arbitrary layer borders. So, let the consultants argue about
whether this is a 2-, 3-, or n-tier model. The proposed model is an effective software design and implementation model.

In the four-layer model, applets are used only at the user interface layer and not for all of that layer. The request broker,
business-rule, and data layers are all Java applications. These applications are all Java server applications. Based on analysis
of the functional content of large software systems, server-side Java will be much larger than client-side Java. Server-side Java
will also encapsulate much more business value.

Team-Fly
Team-Fly

W h at A b o u t A S /400e ?
Where does the AS/400e fit in this brave new Java world? It runs the request broker(s), the business-rule layer, and the data
layer. It also serves the applets that provide network access through the user interface layer. In addition, it can provide local
file storage for the clients that use applications for the user interface layer. AS/400e is well positioned to be a Java server as
the business content of Java software continues to increase.

AS/400e has all the components necessary to be a Java server. It has a JVM that is suited to large computing tasks and
large numbers of users. It has a range of options for HTTP serving (HTTP or Internet serving is a prerequisite to serving
applets). It has good componentry (the AS/400e Toolbox for Java) for providing access to AS/400e resources. It has excellent
cooperative development tools (VisualAge for Java for AS/400e or Borland's JBuilder). It has good TCP/IP network support.
And it has the necessary security tools (e.g., AS/400e object-based security, firewall support, and encryption support for the
network).

Team-Fly
Team-Fly

C h ap ter 3: A n A S /400 P ro g ram m er's F irst L o o k A t Java


O v e rv ie w
RICHARD SHALER

By now, most of you have probably read at least one article about Java, so you don't need a long discussion about why there
is so much interest in the subject. The primary focus of this chapter is to get right into the language and start teaching you
how to program with Java. This chapter certainly isn't a complete tutorial, but there is lots of additional information as you get
into other sections of the book. What I'm trying to present here is a condensed introduction to Java from an AS/400
perspective.

To get the most out of this chapter, you should key in the sample Java code and compile it. Anyone can download Sun
Microsystems' Java Development Kit (JDK) off the Web (java.sun.com). Many other more sophisticated integrated Java
development environments (most of them with visual development tools), such as IBM's VisualAge for Java, Symantec's
Visual Café, and Borland's JBuilder, are available for less than $100.

Team-Fly
Team-Fly

W h y Jav a?
There are many reasons why Java is being promoted as the language of network computing—the Holy Grail of programming
languages. Here are a few of the more important reasons:

O b je ct-o rie n te dd—Java is an object-oriented (OO) language that improves reliability and reusability of code. Many computer
languages today, such as C++ and Smalltalk, are OO. Even legacy languages such as COBOL are evolving into OO-capable
languages. One of the benefits of Java is that it was designed from the ground floor as an OO language. Unlike C++, Java
makes it more difficult to ignore OO rules.

S m a ll e x e cu ta b le ss—Java generates very small executables, which means that it is well suited to an environment where
application code needs to be downloaded from the server to a client machine.

S e cu rity
rity——Java programs execute within the Java Virtual Machine (JVM) instead of the native mode of the client operating
system. Java cannot corrupt memory outside its process space. For example, a Java program that runs in a Web browser
cannot access anything that the client machine doesn't grant it access to. This kind of Java program (applet) can't even
perform file I/O.

M a ch in ee--in d e p e n d e n t—Because Java code runs through a JVM and JVMs are available on most computers (through
browsers or natively through the operating system) and network stations, there's no need for the program to be machine-
dependent. You write your Java code once, for all platforms.

le—Although similar to C++, Java is simpler. Many of the complexities of C++ have been removed. For example, in
S im p le
Java, you don't need to be concerned about memory allocation and deallocation, and you don't have to work with pointers. The
Java byte codes allow for portability, but the downside is that Java programs are interpreted. Of course, interpreted code runs
slower than the native executable code. To improve performance, there is a technique known as Just-In-Time (JIT)
compilation. The JIT method works like this: When a Java program is first received by a client computer, the JIT compiler
converts the Java byte code into a native program.

Team-Fly
Team-Fly

H o w Jav a W o rks
When you compile a Java program, the compiler does not create an executable program for the particular architecture of the
machine on which you're compiling. Instead, the Java compiler creates what is known as Java byte codes. These byte codes
are instructions that a JVM understands and executes. JVM is available in browsers such as Netscape Navigator (2.0 and
3.0) and Microsoft's Internet Explorer 3.0. Some of the major computer operating systems such as OS/2 include a JVM in the
operating system.

There are two types of Java programs: applets and applications. Java applets are programs written to run on a Web browser.
Applets are actually launched from an HTML document through special embedded HTML statements. The HTML source code
in Figure 3.1 is an example of how you might embed a Java applet within an HTML document.

F ig u re 3.1: The applet tag qualifies the name of the applet and the size and location of the Java window with the Web
page.

Java applications, unlike Java applets, do not run from a Web browser; applications run on the computer like a native program.
For example, the current JVM available for the AS/400 runs Java applications within OS/400, not a Web browser. However,
you will need a JVM to execute the application. You can execute the Java application from a command line or through the
Java development system you are using.

Team-Fly
Team-Fly

Jav a S tate m e n ts
A Java statement can be a comment, a declaration, a conditional statement, or a block. Most Java statements end with a
semicolon (;).

C o m m e n ts
Comment statements do not end with a semicolon. There are three types of comments.

O n e : A double slash (//) comment continues from the two slashes to the end of the statement. These types of comments are
usually just one line long. In the following example, the executable Java statement is preceded by a comment:
// add 1 to integer variable x
x = x + 1;

In the next example, the comment is appended to the executable Java statement. Notice that the executable portion of the
statement ends with a semicolon.
x = x + 1; // add 1 to integer variable x

T w o : For multiple lines of comments or blocks of comments, use the slash asterisk (/*) and asterisk slash (*/) combination.
The slash asterisk comment continues until an asterisk slash is encountered. This type of comment makes it much easier to
deal with blocks of comment statements.
/* This is a block of comment statements that continues line
after line
after line
until here */

T h re e : The final type of comment allows comments to be extracted from a program and converted into an HTML file,
producing professional-looking documentation of your program. For this type of comment, start with a slash double asterisk
(/**) and end with an asterisk slash (*/). Each separate line between the beginning and the end must begin with an asterisk.
These comments are normally used to document classes and methods. A whole chapter could be written about these special
comments. To find out more, refer to the Javadoc utility that comes with the Sun JDK.

D e claratio n S tate m e n ts
Declaration statements, as the name implies, declare something such as a variable or a class. For example, the following
declaration states, "I declare integer variable x and initialize it to the value of 1":
int x = 1;

In this statement, I add 1 to variable x and assign the value to x :


x = x + 1;

As in RPG, variables in Java can be defined on the fly; they don't have to be defined at the beginning of the program. In the
following example, the statement performs an assignment to variable x and defines x at the same time:
int x = x + 1;

C o n d itio n al S tate m e n ts
Conditional statements are used for program flow control. There are basically four conditional statements: the IF statement,
the WHILE loop (which can also function as a Do Until), the FOR loop, and the SWITCH statement. Here is the structure of
the IF statement:
if (boolean expression) {
// statement here
} else {
// statements here
}

And here is an example of the IF statement:


if(amount >= 100.00) {
discount = .10;
} else {
discount = .00;
}
}

The WHILE loop is similar to the DOW or DOWxx loop in RPG. The statement or block following the w h ile is executed while
the condition in the w h ile expression is true. There are actually two forms of the WHILE loop. The first form is as follows:
while (boolean expression) {
// statements here
}

Here is an example of the WHILE statement:


while (ctr <100) {
ctr = ctr + 1;
}

The second form of the WHILE loop (a.k.a. the DO statement) is similar to an RPG DOU or DOUxx loop. The block of code is
always executed at least once. The loop continues until the w h ile condition is not true.
Do {
// statements here
} while (boolean expression)

Here is an example of the DO statement:


Do {
ctr++;
} while (ctr < 100)

The FOR loop is probably the most popular form of loop structure. You will see this used often in Java. There is no equivalent
of a FOR loop in RPG.
for (expression1; boolean_expression; expression3) {
// statements here
}

Here is how the FOR statement works:


a. e x p re ssio n 1 is evaluated.

b. b o o le a n _e x p re ssio n is evaluated.
1. If true, the body of the FOR loop is executed.

2. If false, control passes to the statement after the FOR statement (or beyond the closing brace if the statement
is a block statement).

c. e x p re ssio n 3 is evaluated.

d. Go to step 2.

In the following example of a FOR loop, an array is being loaded with the numbers 0 through 9:
for (ctr = 0; ctr < 10; ctr++) {
numbers[ctr] = ctr;
}

The SWITCH statement is used when you want to select one of many alternatives. For example, you could use a SWITCH
statement to process the selected option of a menu of options. The SWITCH statement is similar to the RPG
SELECT/WHEN/ENDSL operations. Figure 3.2 shows an example.

F ig u re 3.2: Java's SWITCH statement is similar to RPG's SELECT statement.

Figure 3.3 contains an example of a SWITCH statement used to process three possible options.
F ig u re 3.3: A behavior of Java's SWITCH statement that you need to be aware of is that without BREAK statements,
control logic continues to drop through the CASE clauses.

S tate m e n t B lo cks
You might have noticed the braces ({}) contained within the group of statements in Figure 3.3. Because I wanted to condition
more than one statement with the conditional SWITCH statement, I formed a statement block by surrounding the group of
statements with opening and closing braces. (Java statement blocks do not end with a semicolon.) Often, blocks are
associated with conditional statements. For example, in the Java code in Figure 3.4, the first block of code executes if
T o ta lS a le s is greater than or equal to $100,000; otherwise, the second block of code executes.

F ig u re 3.4: Blocks of code within IF/THEN/ELSE clauses are demarcated with braces.

The two statement blocks in Figure 3.4, like all statement blocks in Java, are identified by the opening and closing braces.
For RPG programmers, it might be helpful to compare the preceding example to an RPG equivalent: the IF, ELSE, and ENDIF
operators.

Team-Fly
Team-Fly

D ata T y p e s
The size of each variable type is an intrinsic part of the language. No matter what platform you are running Java on, the size of
each data type is the same. This greatly improves the language's portability. There are eight variable types, as shown in
Figure 3.5.

F ig u re 3.5: Java has eight basic data types.

Team-Fly
Team-Fly

D e clarin g V ariab le s
All variables must be declared before they are used. Java is case-sensitive, so the variable name a n u m is different from the
variable A N U M . If you don't initialize a variable, a default value is assigned, as shown in Figure 3.5. You must declare the
variable type when you define a variable. Figure 3.6 shows several examples.

F ig u re 3.6: Variables can be declared and initialized with the same statement.

If you want to define more than one variable of the same type, you can declare them all in one statement. For example:
// define three variables of type integer
int x, y, z;

Team-Fly
Team-Fly

A rith m e tic O p e rato rs


Arithmetic operators for add, subtract, multiply, and divide are, respectively, the plus sign (+), the hyphen (-), the asterisk (*),
and the slash (/). Here are some examples of arithmetic operators:
linetotal = (qty * price) - discount;
percent = amounbotal + amount;

The m o d (or remainder) operation is also supported through the percent symbol (%). For example, the following statement
will assign the value of 2 to variable x :
x = 12 % 5;

There is no symbol for exponentiation; you must use the Java p o w method of the M a th class (MM a th .p o w ). (For an example
of raising a quantity to a power, see Figure 3.11.)

Team-Fly
Team-Fly

U n ary O p e rato rs
There are four unary operators in Java: negation (-), increment (++), decrement (—), and bitwise complement (~). The
negation operator is simple. If you want to negate a value, you simply precede it with a – (hyphen).

The increment and decrement operators can be used two different ways: pre- increment or postincrement (or predecrement
and postdecrement). For example,
ctr = 1;
totalctr = ++ctr; // totalctr equals 2

Because the unary increment operator precedes the variable c tr tr, c tr is incremented before the value is assigned to to ta lc tr
tr. If
c tr was equal to 1 prior to this operation, to ta lc tr would equal 2. You can postincrement a variable by following the variable
with the unary increment operator.
ctr = 1;
totalctr = ctr++; // totalctr equals 1

In this example (to


to ta lctr = ctr+ + ), if c tr equals 1 before the operation, to ta lc tr would be equal to 1. (Variable c tr is not
incremented until after the assignment is performed.)

The bitwise complement operator works on bit patterns. Working on bit patterns is beyond an introductory chapter such as
this. For further information on bit patterns, see your Java development systems help text.

Team-Fly
Team-Fly

R e latio n al A n d B o o le an O p e rato rs
Although the equal sign (=) is used for assignment in Java code, double equal signs (==) are used to compare for an equal
relationship. Use an exclamation point and an equal sign (!=) for not equal.

Use a less-than symbol (<) for less than, a greater-than symbol (>) for greater than, a less-than symbol and an equal sign
(<=) for less than or equal, and a greater-than symbol and an equal sign (>=) for greater than or equal. Java, like C, uses two
ampersands (&&) for the AND operator and two pipes (||) for the OR operator.

Team-Fly
Team-Fly

A rray s
Arrays are basically defined by specifying the type of data they will contain, the name of the array, and then the number of
elements. For example, in the following declaration, I am defining an integer array called In tA rra y with 10 elements:
int[] IntArray = new int[10];

An array is actually an object, and you must use the NEW operator to explicitly create it. An array also can be defined with
the brackets after the array name (e.g., in t In tA rra y[] = n e w in t[10];
t[10];), but I've read that placing the brackets before the array
name is more common.

You reference the first element of an array in Java with a 0, the second element with a 1, and so on. For example, the
following statement prints the third element of the array:
System.out.println("The third element of IntArray = " + IntArray[2]);

In this example, the plus sign is a concatenation symbol. Here I am concatenating the value in element three of In tA rra y to
the character string preceding the plus sign. Here's a snippet of code that loads an integer array of 10 elements with the
numbers 0 through 9:
for (int = 0; i < 10; i++)
IntArray[I] = i;

Team-Fly
Team-Fly

S trin g s
String is not a data type in Java; it is a class called S trin g . Strings are simply a sequence of characters. Declare a string as
follows:
String CoName;
Declare and initialize a string like this.
String CoName = "Midrange Computing";

You can concatenate a string with the plus sign. In the following example, I concatenate a blank to F irstN a m e and then
concatenate the L a stN a m ee.
FullName = FirstName + ' ' + LastName;

Unlike in a Java array, you cannot change a specific character within a string. For example, I can't change the spelling of
"Midranje" to "Midrange" by replacing the "j" with a "g." However, I can modify the string by concatenating the characters I
want to replace with the substring of the portion of the string I want to keep. Assuming the name of my string variable is
N a m ee, to change the string M id ra n je to M id ra n g ee, I can use the following statement:
Name = Name.substring(0,5) + "ge";

In Java, you invoke an objects method with the .m e th o d notation. In the example, su b strin g is a method of object N a m ee.
The first argument of the su b strin g method (0) references the first position of the substring; the second argument (5) specifies
the ending position of the substring. In this case, the substring value is "Midran." Notice that the first position of the substring
is referenced with a 0, not a 1, and the ending position is referenced with a 5, not a 6. As with Java arrays, you reference
relative positions of strings starting with 0.

Team-Fly
Team-Fly

C o n stan ts
In Java, you define constants for the entire class; you cannot define a local constant for a specific function (method) of the
class. So, it stands to reason that you define constants prior to the m a in function. Use sta tic fin a l to declare a constant, as
illustrated in the example shown in Figure 3.7.

F ig u re 3.7: A Java application's main method is the entry point to the class.

In this example, the scope of p ie is to this class only. To declare the p ie constant in Figure 3.7 as global, precede sta tic
fin a l with p u b lic (i.e., p u b lic sta tic fin a ll).

Team-Fly
Team-Fly

L ite ra ls
A literal is a symbol or quantity that is itself the data, rather than a reference to the data as with a variable. Java contains five
different types of literals:

 Integer.

 Numeric containing a decimal point or exponent.

 Boolean.

 Character.

 Special character.

Integer literals by default are 32-bit (4 byte) signed decimal numbers similar to an in t variable. Any integers greater than
2,147,483,647 are assumed to be long integers. You can force a number smaller than this to be long by ending with an "l" or
"L." To force 31 to be a long integer, specify "31L."

Any numeric literal that contains a decimal point or an exponent is assumed to be a floating-point number, type double. An "f"
or "F" can be appended to the end of a literal to force it to be a floating-point number, type float. A "d" or "D" can be appended
to the end of a literal to force it to be a floating-point number, type double.

Literals can be expressed in octal by preceding the number with a 0 (zero). For example, 037 would be an octal literal.
Literals also can be expressed in hexadecimal by preceding the number with a "0x" or "0X." Java uses two Boolean literals:
true and false. Boolean literals do not need to be defined. You simply specify one or the other literal. For example:
while(true) {
//statements here }

Character literals must be enclosed in single quotes: ' ' is a space. You can also define a character literal with the Unicode
value. A space could be defined like this: 'x 2 0 '. There are some special character (some nonprintable) literals that may be
useful, such as new line, horizontal tab, and so on. You express these characters with special values, as shown in Figure
3.8.

F ig u re 3.8: Special characters can be inserted into a Java string using special values.

Team-Fly
Team-Fly

S am p le P ro g ram s
I'll start by giving you a very simple example. This is a Java application or what can be referred to as a stand-alone program.
(All three programs in this section are stand-alone programs.) The program in Figure 3.9 simply displays "Hey, Java is cool!"

F ig u re 3.9: The syntax required for creating a Java "Hello World" program is quite simple.

The first statement of the program in Figure 3.9 names a class (sa
sa m p le 11). Every Java program must be inside a Java class.
The Java compiler looks at the name of the class and not the name of the source file to determine the file name of the
compiled byte code. (This is similar to RPG II programs where you would define the program name in the Header
specification. The RPG compiler would always use the name in the Header specification for the compiled program name.)

Execution of a Java program always starts with the m a in function. If any parameters are passed to m a in in, they are passed
through a S trin g array (in this case, the array is called a rg ss). In Figure 3.9, there is only one statement within the m a in
function S yste m .o u t.p rin tln ("H e y, Ja va is co o l!"). S yste m .o u t is an object that refers to the system that is executing the
program; p rin tln is a function or, in OO terms, a method of object S yste m .o u t, which I am invoking. The p rin tln method
prints the STRING ARGUMENT (parameter) contained within the parentheses.

Figure 3.10 shows a slightly more complex sample program. The comments and code in the example provide some insight
into string handling.

F ig u re 3.10: The System.out.println method is an easy way to create simple screen output.

As shown in Figure 3.11, the Java program, using math, calculates a mortgage payment. For simplicity, I've initialized the
variable to the values I wanted to use. This way I didn't have to get into I/O operations.

F ig u re 3.11: Mathematical operations are easily performed on Java's basic data types (int, double, long, and
float).

Notice the p o w method of the M a th class (MM a th .p o w ). Java doesn't have an exponentiation operator, so you have to use a
M a th method.

Team-Fly
Team-Fly

E asy D o cu m e n tatio n W ith Jav a


As a C++ programmer, one of my earlier but unfounded criticisms of Java was that the class definitions were not separate
from the code implementation. It is a C++ convention that your class definitions are kept in a "header" or *.H file and the code
is kept in a *.CPP file. The C++ headers are then very easy to review for documentation. But in Java, if you follow some
simple commenting conventions, you can run the Java software development kit utility, Javadoc, over your Java code to
dynamically create HTML documentation.

 Use description comment blocks delimited by a slash double asterisk (/**) and asterisk slash (*/) preceding every class
statement, as well as attribute and method declarations.

 For method declarations with parameters, add a line to the function's block comment with an @PARAM command for
each parameter:
@param paramName parameter description

 For method declarations with a return value, add a line to the function's block comment with an @RETURN command:
@return description of return value

Figure 3.12 shows a Java class that will self-document with Javadoc. Figure 3.13 shows a sample HTML page that was
generated from ja va d o c.e x e over the preceding class code.

F ig u re 3.12: This code is a self-documenting Java class.

There are some other @ commands that you may research on your own, such as @EXCEPTION, @VERSION, and
@AUTHOR.

For complex classes, these HTML files are invaluable, and, with the simplicity of coding for Javadoc, there is no excuse not to
use the @ command as a coding standard. Javadoc can also parse some HTML tags, such as < P R E > and < T T >>, as well as
some special prefixes such as x .
F ig u re 3.13: The screen shows a sample HTML page generated with javadoc.exe.

Team-Fly
Team-Fly

Y o u 'v e G o t T o T ry It
If you've never programmed in C, C++, or Java, some of this material might seem a little strange. But I encourage you to get
yourself a Java development system (e.g., download Sun Microsystems' JDK), look at the many chapters in this book, and
start playing with the language. It really isn't difficult, just different. I think before you know it, you'll love it.

Team-Fly
Team-Fly

S e c tio n II: A S /400 T o o lb o x fo r Java


C h ap te r L ist
Chapter 4: Record-Level Access With The As/400

Chapter 5: Commitment Control for Record-Level Access

Chapter 6: Encapsolution: Java Power with RPG Smplicity

Chapter 7: Qshell and IBM's Java Toolbox for the AS/400

Chapter 8: Java Servlet Programming for the HTML-Challengeo

Chapter 9: Reducing Applet code size with Proxy Classes

P art O v e rv ie w
The AS/400 Toolbox for Java is a bundled program product that ships with OS/400. What's in the toolbox? A bunch of classes
that encapsulate access to nearly all OS/400 interfaces. In fact, I will go as far as to say that anything that you can do as a
power programmer on the AS/400, you can do with the Java classes in the toolbox. Record-level access and SQL access to
DB2 for OS/400, job and spool management, and data queue and program calls, for example, can all be performed with the
Java Toolbox.

RPG and COBOL programmers are so proficient with the dynamic database access capabilities of RPG and COBOL that,
when they move to Java, they want the same access capabilities. The record-level access classes of the Java Toolbox for the
AS/400 provide the dynamic access capabilities you are familiar with. Richard Shaler's chapter, "Record-level Access with the
AS/400," tells you what you need to know to get started. "Commitment Control for Record-level Access" covers the
techniques required to ensure transactional integrity in your Java applications.

The problem with the toolbox's record-level access classes is that the class and method names do not directly correspond to
the op codes of RPG. Joe Pluta resolved this problem using good old object-oriented encapsulation. Joe created a package of
classes that encapsulate access to the toolbox's record-level access classes with class and method names such as CHAIN,
SETLL, and DELETE. Joe explains how to use his open-source package in "Encapsulation: Java Power with RPG Simplicity."

Becoming an AS/400 Java programmer means that you need to become familiar with OS/400's Qshell environment. You can
think of Qshell as the Command Entry screen for Java. Qshell is covered in detail in Section VI in Walter Goodwin's chapter
"UNIX Developers Find a Home in Qshell." But in this section, my chapter "Qshell and IBM's Java Toolbox for the AS/400"
provides enough coverage of Qshell to give you the ability to configure and use Qshell for Java development.

The toolbox classes are full of a variety of utility classes, but this section limits the rest of its coverage to two: HTML classes
and applet proxy classes. In "Java Servlet Programming for the HTML-challenged," I show how you can use the classes that
encapsulate access to HTML. In "Reducing Applet Code Size with Proxy Classes," Jeff Markham explains how you can
improve the performance of your browser-based Java applets with the use of AS/400-based Java proxy servers.

All in all, I think you'll find this section extremely helpful as you begin to test your Java skills against your beloved AS/400.
You'll really want to know a good bit about the toolbox. The chapters in this section provide tutorials and some of the more
powerful facilities in the AS/400 Toolbox for Java.

Team-Fly
Team-Fly

C h ap ter 4: R eco rd
rd--L evel A ccess W ith T h e A S /400
O v e rv ie w
RICHARD SHALER

You've probably heard enough Java theory and hype to last you a lifetime. It's time to look at a working AS/400 Java
application and learn a little about this language. Java and the object-oriented (OO) model on which it is built aren't just
hypothetical solutions; they actually have a lot to offer the AS/400. And there's more good news: Java isn't all that mysterious
and hard to learn, as will become apparent if you study the sample application presented in this chapter.

The tremendous momentum of Microsoft's operating systems, applications, and application development products—including
some of the more recent network computing products—make it seem that network enablement and the Java promise of
"Write Once, Run Anywhere" may not be all that important. After all, Microsoft has a great track record for creating,
marketing, and delivering great products. Plus, it is delivering network-enabling technology, and a huge majority of desktop
systems already belong to Microsoft. Embracing its products would seem to be a pretty safe bet for software developers and
IT managers.

So, who really needs this Java stuff? Actually, at least two important groups: (1) anyone who believes in the benefits of
competition and in having choices and (2) the AS/400 market. Although Java may not end up being all that some predicted, it
could be good for competition, and there's no doubt that it's the best thing that could happen to AS/400 application
development.

IBM has been aggressively enabling Java on AS/400. Since V4R2, the OS/400 has a native, embedded Java Virtual Machine
(JVM), and with IBM's AS/400 Toolbox for Java (JT400), Java programmers have dozens of useful tools they can use to
access AS/400 resources and data. Today, you can develop Java applications using the AS/400 features you're used to, such
as record-level access and packed decimal data support. The JT400 also provides easy access to existing applications, with
features such as n a tive .p ro g ra m call support and support for data queues. It even includes a JDBC driver for those who need
an SQL interface to their AS/400 databases.

The purpose of this chapter is to give you a glimpse into what Java can do on the AS/400. It will also give you some insight
into the underpinnings of an AS/400 Java application and the record-level support provided by the JT400. I urge you to study
this application and the Java code. I think you'll find that Java and OO programming aren't all that difficult to understand. You
will learn that Java and the special AS/400 Java tools IBM has provided make Java a good bet for AS/400 application
development today and an even better bet for the future as Java gains wider acceptance. OK, enough talk. I'll move on to
something you can sink your teeth into—a working AS/400 Java application.

Team-Fly
Team-Fly

T h e S am p le A p p licatio n
I've written a client/server application called L istC u sto m e rs that runs from a client desktop system (e.g., a PC or network
computer) and retrieves information from an AS/400 (the server). More specifically, the application connects to the AS/400
through a sign-on dialog (see Figure 4.1), reads sequentially through the QCUSTCDT file in the QIWS library, and displays the
customer number and last name in a graphical list box contained within a Java window (or frame), as illustrated in Figure 4.2.
This is the simplest of applications. The list is the only component in the frame (there are no text boxes or buttons). The
application uses IBM's JT400 to connect to the AS/400, open the QCUSTCDT file, and read its records.

F ig u re 4.1: If you construct an object of the AS400 class without specifying system, user ID, and password, a Java sign-
on dialog will prompt the user for that information.

F ig u re 4.2: The ListCustomers application used the JT400's record-level access classes to list all the records of
OS/400's sample QCUSTCDT file located in the QIWS library.

This is a Java application, not a Java applet. Java applets need a browser, such as Internet Explorer or Netscape Navigator, in
order to function. (For more information on the differences between a Java application and a Java applet, see Chapter 2,
"Applets and Applications.") Java applications don't need a browser; they need only a JVM. All I needed on my PC was Sun
Microsystems' Java Development Kit (JDK) and the AS/400 Toolbox for Java. The JDK can be downloaded and used for free
from Sun's product Web site at http://java.sun.com/products/index.html. IBM's JT400 program product (5798-JC1) ships free
with OS/400, VisualAge for Java, and Borland's JBuilder Java development environment for the AS/400. If you don't have any of
the software just mentioned, contact IBM and ask for product 5798-JC1. (For a complete list of the requirements to create and
run this application, see the "Application Requirements" section.)

Team-Fly
Team-Fly

O b je ct-O rie n te d D e sig n


If you're new to Java, the source code for this application might look a little strange. I'm not going to explain Java syntax here.
Besides, you don't really need to be concerned with that much detail to understand how this application works. The important
thing to see is the general design and workings of the application. My explanation of the application and the illustrations will
do just that.

Java uses the OO design paradigm. With Java, you describe objects. For example, objects can represent visual components,
such as a user interface dialog; nonvisual components that represent real-world objects, such as customers, employees, and
invoices; or abstract objects, such as records and record formats. Objects are described with class-definition source code.
When you compile a Java class definition, the result is an intermediate code (a.k.a. Java byte code) that can be interpreted
by a JVM. It is this intermediate code that gives Java its portability, since most computers today contain a JVM that can run
Java byte code.

Describing a class definition is somewhat analogous to describing an AS/400 file object with DDS source code. With DDS,
you create the file object directly from the source code. Once the file is created, it is persistent unless you explicitly delete it.
With Java class definitions, you create an object indirectly: First, you create the Java byte code from the class definition, and
then you run the byte code to actually create the object. Also, with Java, objects that get created at runtime aren't normally
persistent; they dematerialize when you end the application.

Java class-definition source files use an extension of .java. You can see my sample application source file
(LL istC u sto m e rs.ja va
va) in Figure 4.3. When you describe a class, you describe its attributes (what it is made of) and the
methods (or functions) that can be performed against the object. But the first thing you do is name the class, as illustrated at
Label A in Figure 4.3. You can optionally inherit from another class, as I have done through the keyword EXTENDS. My
L istC u sto m e rs class inherits from the JDK-supplied F ra m e class.

 
 

F ig u re 4.3: Java GUI application classes normally extend the Abstract Window Toolkit's Frame class .

Now, at Label B, you can see that I define the main visual attribute (or component) of the L istC u sto m e rs class: the list that
will contain the customer information. I define the list as an Abstract Window Toolkit (AWT) L ist component and I name it
stlist. (AWT is a set of Java graphical classes included with JDK 1.1x.) The c u stlist object will contain the list of customer
c u stlist
record information that the application displays. Later, when I describe the reading of the customer file, you will see how
easily the list is populated.

As mentioned previously, a Java source file is compiled to Java byte code. The result is the creation of a file (or files) with an
extension of .c la ss
ss. A Java source file can contain more than one class definition. At this point, you still haven't created an
object. The object isn't created until you run the class and the class explicitly instantiates or materializes itself. You can see
this instantiation of my L istC u sto m e rs object at Label C. Using the Java keyword NEW is like saying "create an object"—in
this case, the L istC u sto m e rs F ra m e object. The keyword NEW causes a special method known as the constructor method
to be invoked automatically. The purpose of the constructor method (as its name implies) is to construct and initialize the
object. This special method uses the same name as the class.

Notice that the constructor method defined at Label D is called L istC u sto m e rs
rs, the same name as the class defined at Label
A. As mentioned previously, the constructor method initializes an object. You can see evidence of this at Label E, where I'm
setting the size of the L istC u sto m e rs frame (400 400).

Moving through the constructor method at Label F, you can see the NEW keyword again. Here, I'm instantiating the c u stlist
object. As you've already learned, the NEW keyword invokes the constructor method of a class—in this case, L ist ist. However,
you won't find a constructor method for L ist in the source code of L istC u sto m e rsrs, because the Java compiler creates a
default that simply invokes the constructor of the parent class—in this case, the F ra m e class. F ra m e has a constructor
method for L ist
ist. Once the c u stlist object exists, it can be added to the L istC u sto m e rs F ra m e object through the a d d
method, as shown at Label G.

Team-Fly
Team-Fly

T h e A s/400 T o o lb o x F o r Jav a F u n ctio n s


The focus of this section is the JT400class methods. The first thing the program does related to the AS/400 is create the
syste m object, which encapsulates the TCP/IP connectivity to an AS/400. This occurs at Label I. When the A S 400 object
gets created, the user is prompted with an AS/400 Java sign-on dialog (as illustrated in Figure 4.1). Notice that the system
name already contains a value. That is because I passed the system name to the AS/400 constructor method (see Label I).

Once the A S 400 object variable called syste m is created, the co n n e ctS e rvice method is used to connect to the AS/400, as
shown at Label J. Notice that the connection request is preceded by the TRY statement. In Java, you can trap exceptions
with the TRY and CATCH keywords. The TRY keyword essentially tells Java to try to execute the following statement(s) and,
if any exceptions occur, process the statement(s) within the corresponding CATCH block. You can think of this TRY and
CATCH technique as similar to the use of the Monitor Message (MONMSG) command in CL programming. The code that is
contained within the CATCH braced block of code is similar to the DO portion of MONMSG; it is executed when an error is
thrown. CATCH, however, is concerned only with errors that occur within the TRY block. Furthermore, Java forces you to add
error- handling code when a function has the potential to throw errors, as is the case with the co n n e ctS e rvice function call.
There, the application anticipates that a connection may not be able to be established. If the connection fails, the application
displays some information concerning the error.

After the connection is made, the application creates an object for the file name and a path to the file (file
file P a th N a m ee) at
Label K. With this path and file name object, a S e q u e n tia lF ile object can be created, as shown at Label L. Now, a record
description has to be created (see Label M) to contain the format of the file. After the record description is created, the
application retrieves the record format of the AS/400 file and uses it to set the format for the application's file object (th th e F ile
ile),
as you can see at Label N.

One thing should be apparent by now: In Java, you create objects before you operate on them. Finally, the file can be opened,
as is done at Label O. Here, I open the file for reading only; I've blocked the reads with a factor of 100 and no commitment
control. At this point, the application enters a WHILE loop (see Label P), where it retrieves fields with the g e tF ie ld method of
the re co rd object (see Label Q). The g e tF ie ld function will return the Java object that most closely approximates the DB2-
for-OS/400 data type of the field passed to it (see Table 4.1). In the case of CUSNUM, the Java object returned is an integer.
The Java S trin g class's value function (va
va lu e O f) is used to convert the number value contained within that integer object into
a string. For the LSTNAM field, the g e tF ie ld function returns a S trin g object. The resulting two field strings are concatenated
with two blanks in between (see Label R) and placed into the variable cu stN u m N a m ee.

T a b le 4.1: A S /400 D a ta T yp e s to Ja va C la sse s

A S /400 D a ta T yp e Ja va C la ss
Signed binary 2 bytes Short
Signed binary 4 bytes Integer
Unsigned binary 2 bytes Integer
Unsigned binary 4 bytes Long
Float 4 bytes Float
Float 8 bytes Double
Packed BigDecimal
Zoned BigDecimal
Character String

That's pretty much it for the JT400 functions, except for a little cleanup, such as closing the file and disconnecting from the
AS/400. Now, I'll return to a discussion of the Java code.

Team-Fly
Team-Fly

B ack T o Jav a
Now that the data is available for the window's list box, it needs to be added to the list. The cu stN u m N a m e variable is added
to the c u stlist object with the a d d Ite m method at Label S. Notice the syntax of using object methods. For example, at Label
S, the a d d Ite m method gets invoked with the cu stlist.a d d Ite m (cu stN u m N a m e ) method call. Method invocation is specified
with the syntax o b je ct_n a m e .m e th o d _n a m ee. This is standard syntax in OO languages.

At Label T, the application finally displays the L istC u sto m e rs object with the sh o w method. You might expect the object
name for the sh o w method to be L istC u sto m e rs
rs, but instead it is th is
is. The THIS keyword is a special keyword you can use
to refer to the object itself. There are numerous ways to take advantage of the THIS keyword, but I won't go into them now. I
just wanted you to know what this meant (in the context I'm using it).

Team-Fly
Team-Fly

A W o rd A b o u t E v e n t H an d lin g In Jav a
JDK 1.1 includes the AWT for developing graphical components. You can see the AWT package being included (im im p o rt
t.*) at the beginning of the Java source code in Figure 4.3. Graphical components and other objects need a way to
ja va .a w t.*
communicate and handle object events. For example, a Java program needs a way to handle the event of a user request to
close an application. With version 1.1.x of the JDK, Sun rewrote the Java object event-handling system to a delegation-based
model. The new event-handling model is based on three objects: a source, an event, and a listener. The source object is any
AWT component that interacts with a user, like Figure 4.3's list box. An event object is simply the encapsulation of a user
event—such as a user double-clicking a list element. The event object is passed to a listener object as an argument to the
method that is to handle the event.

To get an event listener object to respond to an event object, it must be registered with the source object that generated the
event. In my sample application, the L istC u sto m e r class registers the L istW in d o w L iste n e r object with the
a d d W in d o w L iste n e r method (see Label H in Figure 4.3). The L istW in d o w L iste n e r event listener handles various events,
such as the user requesting the window be closed, as shown in the L istW in d o w L iste n e r class in Figure 4.4. Notice the
various methods, such as w in d o w C lo sin g and the dispose method it invokes. To understand the basics of the Java event
model, follow the sequence of events for the L istC u sto m e rs sample application illustrated in Figure 4.5.

F ig u re 4.4: The ListWindowListener handles the window-closing event by terminating the application.

F ig u re 4.5: Event-driven programming with Java requires three objects: source, event, and listener.

Team-Fly
Team-Fly

Jav a Is W h at T h e A S /400 N e e d s
If you've spent some time studying this application and the concepts described in this chapter, I think you should see that
Java isn't just hype. It really works. Java and OO programming really aren't that strange or hard to grasp. The AS/400 needs a
standards-based, modern, graphical, OO, network-enabling development environment. Java delivers it today.

Team-Fly
Team-Fly

A p p licatio n R e q u ire m e n ts
The requirements for you to run the sample application are as follows:

 OS/400 V4R2 or better.

 Sun's JDK 1.1.x or higher.

 IBM's AS/400 Toolbox for Java.

 IBM's TCP/IP Connectivity Utilities for AS/400.

 A TCP/IP connection to your AS/400.

 The QCUSTCDT sample customer file supplied by AS/400 Client Access or a file that you create, with the same name
and format, in library QIWS.

I won't go into detail about installing or configuring these components, but, if you're at all serious about learning Java for the
AS/400, the first four items in the preceding list are a must.

You run the application from a command line (from Windows, you use the DOS command prompt) with the following
command:
java ListCustomers.

To create the application, you compile the single source file (LL istC u sto m e rs.ja va
va) with the Java Compiler (JAVAC)
command, like this:
javac ListCustomers.java

Before you create or run this application, you must ensure that your CLASSPATH environment variable is set to point to the
JT400 classes file (jt400.zip
jt400.zip ). For example, I set my CLASSPATH environment with the following DOS batch command:
SET CLASSPATH= c:\jt400\lib\jt400.zip

I installed the JDK on parent directory JD K 1.1.8; I installed the JT 400 on parent directory JT 400
400. I also set my p a th to point
to the Java executable files, such as the compiler (jaja va cc) and the JVM (ja va), with the following DOS batch command:
ja va
path=%path%;c:\jdk1.1.8\bin

Team-Fly
Team-Fly

G e ttin g IB M 's Jav a T o o lb o x F o r T h e A S /400 W o rkin g


It's the same with Java and IBM's JT400 as it is with any new language and utility: When you first begin to use them, your
code often just doesn't work. You look over the examples provided by Midrange Computing and IBM, and you double-check
the syntax of your code, and still it doesn't work. This scenario is especially frustrating when the code you are using is the
sample code you downloaded for a look-see, and it just doesn't work. This is exactly what happened to me when I first began
to use IBM's JT400. Worse, sometimes my Java code worked for a while and then, a month later, it didn't work. Through trial
and error and some lengthy research on IBM's Java Web site, I have come up with the following list of items that I check first
when my Java code does not work:

 The Start Host Servers (STRHOSTSVR) command must be started on your AS/400, because the IBM Toolbox for Java
uses the AS/400 servers. To start the servers, use the following command:
STRHOSTSVR *ALL

 The file and database servers run in the QSERVER subsystem. If that subsystem is not started, start it with the Start
Subsystem (STRSBS) command (STRSBS QSERVER) before attempting to start the servers.

 The QUSER user profile must be enabled with a valid password. JT400 uses this profile during its initial connection to the
AS/400. After the initial connection is established, JT400 then uses the user profile specified from the Java program or
entered by the user in JT400's sign-on dialog.

 Be sure that your AS/400's PTF level is current—especially if your OS/400 version and release is prior to V4R2. Recent
PTFs include a number of fixes to the AS/400 database servers.

 Note that JT400 requires that the level of your JVM be at least at JVM 1.1.2.

Team-Fly
Team-Fly

R e co rd
rd--L e v e l A cce ss S e tu p
If you are on OS/400 V4R2 and are attempting to use JT400's record-level access, be sure to start the Distributed Data
Management (DDM) server with the Start TCP Server (STRTCPSVR) command:
STRTCPSVR *DDM

JT400's record-level access also requires that your DDM Request Access Network attribute be set to object authority
(*OBJAUT). You can check this setting with the Display Network Attributes (DSPNETA) command and change its setting
with the Change Network Attributes (CHGNETA) command:
CHGNETA DDMACC(*OBJAUT)

The AS/400's JT400 record-level access server runs in the QCMN subsystem. Check to see if the QCMN subsystem is
started with the Work with Subsystem Jobs (WRKSBSJOB) command:
WRKSBSJOB SBS(QCMN)

If the subsystem QCMN is not running, execute the following STRSBS command:
STRSBS SBS(QCMN)

If the resulting Work with Objects display lists these objects, then the user profile has enough authority. Otherwise, use the
Grant Object Authority (GRTOBJAUT) command to set the appropriate *USE authority for that user.

Team-Fly
Team-Fly

C h ap ter 5: C o m m itm en t C o n tro l F o r R eco rd


rd--L evel A ccess
O v e rv ie w
DON DENONCOURT

IBM's AS/400 Toolbox for Java (JT400) offers two types of database access: JDBC's SQL access and dynamic record-level
access. Most AS/400 programmers are more comfortable with record-level access than SQL access because record-level
access is what RPG and COBOL applications have been using for years. Regardless of which type of database access you
choose to use in your Java applications, because your applications most likely are deployed over some form of TCP/IP
communications line, you need to consider using commitment control. This chapter covers how to use commitment control
with record-level access. (For information on the use of JDBC isolation levels in a commitment control
environment, see Chapter 13.)

The JT400 comes with three classes: A S 400F ile ile, and S e q u e n tia lF ile
ile, K e ye d F ile ile. The A S 400F ile class is the base class
for both K e ye d F ile and S e q u e n tia lF ile
ile. The K e ye d F ile class supports keyed reads and positions the file by key. The
ile, on the other hand, supports sequential reads and positions the file by relative record number. Any of the
S e q u e n tia lF ile
READ operations for files that are open for update lock the record, which is just as you'd expect, since that's what READ
operations in RPG do for update files.

By itself, the automatic record lock has an advantage over the read access of JDBC's SELECT statements. But there are two
problems with relying on record locks for database integrity. First, your application will probably be deployed over a
communications line, and communication lines are not as fault-tolerant as the twinax lines used in the 5250 data stream
applications of legacy AS/400 applications. And second, if your application is developed in an object-oriented (OO) fashion
(where access to business entities represented in record formats is encapsulated in Java classes), its business classes do
not read records in a procedural strategy where record locks work well.

Team-Fly
Team-Fly

E x am p le A p p licatio n
All discussions and arguments aside, now I'll cover how to use commitment control with the K e ye d F ile and S e q u e n tia lF ile
classes. For an example database, I'm using an order file and an order-detail file. For your convenience, I've created a Java
class called G e n O rd e rT a b le s (shown in Figure 5.1) that invokes the SQL CREATE TABLE and CREATE INDEX statements
required to create these tables on your system. (Be sure to change the library name from DENONCOURT to the name of your
library.) Note that the G e n O rd e rT a b le s class uses both a JDBC and an AS/400 Connection object so that you'll have to log
in twice. Optionally, rather than running G e n O rd e rT a b le ss, you could simply cut and paste the SQL and OS/400 commands
onto a green-screen session.

 
 

F ig u re 5.1: The GenOrderTables Java application creates the order header file, order- detail file, and unique indexes, and
starts journaling .

Consider for a moment the various application strategies for taking orders over the Internet. If you are using Java servlets, the
client could add a couple of line items and then decide to leave the Web site without confirming the order. Your application
would have to remove any added order and order-detail records. There are strategies to take orders without writing to the
database, but these strategies complicate the programming effort.

Now consider an applet deployment of an order-processing application. Web-browsing customers are a fickle bunch who often
leave online order- processing pages in the middle of an order. Remember, they're not sitting in front of a 5250 screen; they're
in front of a Web browser, where with a single mouse click, they can leave your Web site. Also, realize that the Internet
connection can go down at any time, and their system can lock up at any time. Another strategy for deploying the order-
processing application is as a Java client/server application. This strategy more closely models the 5250 application, but the
app still has connection volatility because the communications protocol is still TCP/IP.

Chapter 62 presents an OO application that uses record-level access and commitment control. For this chapter, I am
simplifying the application to the batch application (Figure 5.2) to explain the basics of record-level access commitment
control.

 
 

F ig u re 5.2: The OrderProcess Java application adds two orders, but the second order is not committed to DB2/400—it's
rolled back.

Notice that in Figure 5.2 the m a in method adds an order for customer number 25 that is due on October 15, then it adds an
order for customer 98 that is due in December. The first order has two line items, and the co m m it operation
(oo rd e rF ile .co m m it()) completes the order. The second order has three line items. Figure 5.3 shows the order-detail file just
before the second transaction is rolled back with the o rd e rF ile .ro llb a ck() operation. Figure 5.4 then shows the remaining
records in the order-detail file after the rollback removed the three detail records and the order record from DB2/400.

F ig u re 5.3: An SQL view of the order-detail file shows that records that are added to DB2/400 are available even before a
commit or rollback operation.
F ig u re 5.4: The rollback method retracts all operations made to the database within the most recent transaction
context.

That's commitment control in a nutshell: The co m m it operation confirms a transaction set, and the ro llb a ck operation
removes any updates, deletions, or writes to the database for a transaction set. A transaction set is all updates, deletes, and
additions of the records of all files under commitment control from one co m m it or ro llb a ck operation to the next.

Team-Fly
Team-Fly

Jo u rn alin g
For commitment control to work, however, you have to start commitment control. But even before that, you need to have
journaling enabled for the database files to be put under commitment control. The G e n O rd e rT a b le s Java application in Figure
5.1 performs the following four commands to begin journaling over the order files:
1. CRTJRNRCV JRNRCV(DENONCOURT/JRNRCV)
2. CRTJRN JRN(DENONCOURT/JRN) JRNRCV(DENONCOURT/JRNRCV)
3. STRJRNPF FILE(DENONCOURT/ORDER) JRN(DENONCOURT/JRN) IMAGES(*BOTH)
4. STRJRNPF FILE(DENONCOURT/ORDDTL) JRN(DENONCOURT/JRN) IMAGES(*BOTH)

Without journaling enabled over your files, you will not be able to start record-level access's commitment control.

The O rd e rP ro ce ss Java application shown in Figure 5.2 performs the standard operations to open a file:

 Construct a K e ye d F ile (or S e q u e n tia lF ile


ile) object.

 Get a record format from an instance of an A S 400R e co rd D e scrip tio n object.

 Set the record format for the K e ye d F ile object.

 Open the file.

Note that commitment control is started between the open for the order header file and the order-detail file. The odd thing
about record-level access's commitment control is that, once it has been started on one file, all other files that are
subsequently opened are also automatically under commitment control. This is not very OO; I would have thought the
commitment control operations of sta rt
rt, co m m it, and ro llb a ck would be in the AS/400 Connection object, not in one file. But
the way it works is that you use one file to manage commitment control, and then all other files for the same AS/400
connection are affected by the co m m it and ro llb a ck operations.

Team-Fly
Team-Fly

A ll, C h an g e , A n d C u rso r S tab ility


There are three options for commitment control: All, Change, and Cursor stability. Use All (COMMIT_LOCK_LEVEL_ALL)
when you want every record accessed to be locked until the transaction is committed or rolled back. Use Change
(COMMIT_LOCK_LEVEL_CHANGE) when you want added, updated, and deleted records to be locked until the transaction is
committed or rolled back. And use Cursor stability (COMMIT_LOCK_LEVEL_CURSOR_STABILITY) when you want added,
updated, and deleted records to be locked until the transaction is committed or rolled back, and you don't want to lock
records that are read and released without being modified.

Team-Fly
Team-Fly

S h arin g Y o u r C o m m itm e n t
Actually, there are five, not three, options for commitment control. The two others are NONE
(COMMIT_LOCK_LEVEL_NONE) and DEFAULT (COMMIT_LOCK_LEVEL_DEFAULT). The use of the None option is
obvious, but the Default option requires a little explanation. I said earlier that all files opened after one file object has already
started commitment control are also under commitment control. In truth, those files will only be under commitment control if
they do not specify COMMIT_LOCK_LEVEL_NONE. If they have any one of the other four options, then they are under
commitment control. The COMMIT_LOCK_LEVEL_DEFAULT options default to whatever commit option was specified in the
sta rtC o m m itm e n tC o n tro l method (as shown in the middle of the O rd e rP ro ce ss class's constructor method in Figure 5.2). I
would suggest that you always specify COMMIT_LOCK_LEVEL_DEFAULT on the file-open operation regardless of whether
you plan to use commitment control. Later, when you find that you need commitment control, your file opens will be ready.

Team-Fly
Team-Fly

C o m m it C h ap te r
Even though the AS/400 has had commitment control for many years, most shops have opted not to use it. But now that you
are looking at developing n-tier applications, commitment control warrants another look. IBM's AS/400 Toolbox for Java
provides a powerful set of record-level access classes, and those classes include commitment control features that are
relatively easy to use. Don't forget to check out Chapter 62, where you'll find a complete (if trivial) application that prescribes
an OO strategy for commitment control.

Team-Fly
Team-Fly

C h ap ter 6: E n cap su latio n : Java P o w er W ith R P G S im p licity


O v e rv ie w
JOE PLUTA

Editor's Note: For many AS/400 shops, the cost of learning an entirely new language is too high, even when the benefit is the
brass ring of e-business. It's difficult to justify retraining your entire staff without a concrete payback . It would mak e better
business sense to gradually move to Java, without entirely disrupting your day-to-day business. In this chapter, Joe Pluta
explains the concept of encapsulation, which hides the complexity of a new language behind an easy-to- learn interface. His
JDB/400 pack age (which is free on the Web) allows RPG programmers to use familiar RPG op codes such as SETLL,
READ, and UPDAT to access AS/400 data from Java programs and to develop e-business applications that use the logic of
existing legacy programs.

I've been listening lately as the discussion about Java, pro and con, has waged throughout boardrooms, lunchrooms, and chat
rooms. The debates are held at the highest levels of technical expertise and are often fraught with esoteric terminology, but
the general consensus seems to be that—and pardon my technical jargon—Java is "a nice place to visit, but [most
programmers] wouldn't want to live there."

I admit that I'm in the minority here. I think Java is going to play a major role in software design in the new millennium. But
somehow having that opinion makes me a fanatic (OK, that and the fact that I spend a lot of my spare time writing and giving
away free Java software). To the majority of programmers, we Javaphiles fall into one of two camps: Either we declare Java to
be the vanguard in the holy crusade against Mighty Bill and his minions, striding alongside Sir Linux to slay the Microsoft
dragon, or we consider Java to be the "one and only true language," brought down from on high to sweep aside the Babel of
high-level languages that has kept us from our true calling.

The truth is that neither of these is the truth. Java is an extremely robust and powerful language designed from the ground up
to provide platform-independent object-oriented (OO) programming today. It has no magical powers and won't grow hair or
remove unsightly blemishes. But what Java will do is bring the power of platform-independent OO programming into the hands
of any programmer who wants it.

What sort of power? OO techniques bring certain benefits to software design. Among these are code reuse and
encapsulation. The advantages of code reuse are well documented: reduced development time, reduced debugging time, and
fewer bugs. However, even more important to software design in my opinion is the concept of encapsulation. In this chapter, I
focus on a simple example of encapsulation and the power it can have.

Team-Fly
Team-Fly

K e e p in g It S im p le
For many years, RPG evolved very slowly, with incremental additions to the language designed to disrupt legacy code as little
as possible. As a result, legions of RPG programmers have happily transitioned from one version to the next, learning some
new skills but doing so with a sense of comfort about their old abilities.

This gentle forward movement had been crucial to RPG's long-term success as a language.

RPG IV changed all that. With its new look and new features, RPG IV is a radical departure from the RPG of old. It has been
difficult for some programmers to make the move from RPG III to RPG IV. I'm no exception. I still write much of my RPG code
using the RPG III style and syntax, and while I can rationalize that it's because most of my clients still use RPG III almost
exclusively, there's also a bit of discomfort with the new RPG syntax. I lik ed my columns nice and tidy.

Add to that the new complexities of the OS/400 APIs (and the associated data structure specifications), and RPG IV
becomes a perfect example of putting a little something for everyone in one bag. To IBM's credit, this approach has always
been its philosophy. Rather than provide half an interface, it tends to go to the other extreme and provide a solution that
supports every conceivable situation. We programmers then have to live with that complexity, and some of us just don't have
the time to master everything.

This is where encapsulation becomes so important. One person in an organization can be appointed to learn a given API and
determine how it needs to be used. That person can then write a "wrapper" program that accepts a few simple parameters
and then does all the work of formatting the API data structures, calling the program, and deciphering and returning the
results. This is encapsulation.

Team-Fly
Team-Fly

IB M 's Jav a T o o lb o x F o r T h e A S /400


IBM's Java Toolbox for the AS/400 (JT400) is another shining example of an incredibly robust set of APIs that can be utterly
incomprehensible to the casual user. Don't get me wrong; it is my opinion that "the toolkit," as it's sometimes called, is one
of the best pieces of free software available today. Used properly, the toolkit provides access to nearly every AS/400 service
imaginable, from user profiles to data queues to record-level access functions. The problem lies in the fact that, because the
JT400 allows so many options, it is difficult to determine which options to use. Encapsulation is the key, and in this chapter, I
encapsulate the record-level access functions.

Take a look at a simple piece of RPG code that will read the file QRPGSRC until EOF (Figure 6.1). As you can see, it's a
simple routine. The JT400 allows you to write Java code that does exactly the same thing. The only problem is that it requires
several more lines of code (Figure 6.2). The code is quite a bit more complex and far less understandable. To give the JT400
some credit, however, this same code will run without change on either the AS/400 or a workstation connected to the AS/400
via TCP/IP. But the cost for such connectivity seems a little high. For example, among the things the Java code must do are
establish a connection with the AS/400 database, convert the AS/400 file name to an AS/400 Integrated File System path
name, and determine the record format to use. The RPG compiler automatically does that sort of work for you. In effect, the
RPG compiler encapsulates much of the work in creating database applications.

F ig u re 6.1. This is a simple program fragment to read a source file.

F ig u re 6.2: This is the same code in Java, using only the classes in the JT400 .

Well, since Java is an OO language, a programmer who understands the details of the record-level access classes should be
able to create classes that encapsulate all those details and should, in theory, be able to create classes that mimic the
simpler RPG syntax.

Team-Fly
Team-Fly

E n te r JD B /400!
I've written several Java packages, which you can download from my free software site at www.zappie.net. You can go directly
to the download page at www.zappie.net/java/techniques/pbd.htm to get the latest version of p b d .ja r (version 2.0P at this
writing), and you can also join the mailing list here. One of the packages in p b d .ja r is JDB/400, a Java package designed to
hide the details of record-level access behind classes that support basic AS/400 and RPG syntaxes. For example, operations
such as READ, WRITE, CHAIN, and UPDAT are implemented, along with support for key lists and partial keys. By simply
declaring a file (using standard AS/400 LIBRARY/FILE syntax) and then executing the READ() method repeatedly, one can
read through a file using the same logic in the original RPG program. Figure 6.3 shows the Java code required using the
JDB/400 routines. The code fragment actually requires fewer lines of code than the original RPG.

F ig u re 6.3: This is the same code using the JDB/400 package .

The idea is simple. The common logic used to access AS/400 files via the record-level access classes is already coded
within the JDB/400 classes. The Jd b 400F ile class, which is the superclass of all the JDB/400 file classes, provides basic
support, such as connecting to the AS/400 and determining the correct IFS path name. Note that JDB/400 currently supports
only files with a single record format, which covers most database applications. If you need to support multiple formats, feel
free to extend or modify the class yourself—source is provided for all classes. (Extensibility is another key feature of OO
design; unfortunately, I don't have the time to dive into those waters in this chapter.) Other classes inherit the base behaviors
of connection and file naming and add specific behavior for that class. For example, the Jd b 400S e q u e n tia lF ile class
supports a CHAIN() method to retrieve a record with a specific record number. Meanwhile, the Jd b 400K e ye d F ile class also
supports a CHAIN() function, but it requires a key field or a key list. The Jd b 400K e ye d U p d a te F ile and
Jd b 400S e q u e n tia lU p d a te F ile classes support the DELET(), UPDAT(), and WRITE() methods.

Using these classes, you can quickly develop applications that mimic the business logic of your existing legacy applications.
But there's a subtle difference: Once the encapsulating classes are written and debugged, application programmers never
have to worry about them. No code is "cloned"; instead, the JDB/400 classes are automatically incorporated into the
application, much in the same way that the RPG compiler incorporates its initialization and file handling code. What this
means is that only one programmer needs to be assigned the task of learning the internal functions of the JT400; that
person's knowledge is then disseminated through the encapsulating classes. And in the case of JDB/400, it's already written
and freely available, so you don't need to assign any additional resources, unless you want to be able to extend the classes
yourself someday.

Team-Fly
Team-Fly

E n cap su latio n : N o t Ju st F o r D atab ase A cce ss


After I had the JDB/400 classes written, it became obvious that if I wanted to create a real "RPG-like" development
environment, I'd have to write more classes to support other functions. For example, I'd need to develop classes to mimic the
behavior of display files. This effort eventually became the Java Blockmode User Interface (JBUI) package (also available at
www.zappie.net). JBUI supports concepts such as output and entry fields, screens, buttons, command keys, and errors.

The amount of code required to write a graphical interface that mimics a simple 24-by-80 character-based screen is
surprisingly large. (Well, it takes a large amount of code to do it with some aesthetic appeal, anyway.) Rather than a simple
fixed-font recreation of typical AS/400 screens, JBUI uses the features of Java, especially Swing, as often as possible.
Subfiles are represented as tables, not simply rows of fields. This sort of design, although difficult, began to pay off when I
realized that the package would have to support building screens dynamically. Because I was using the standard Java
classes, it was fairly easy to add scrolling to panels that were too large.

The JBUI package is several times larger than the JDB/400 package, but, once again, because it is already written and
available for download, you don't have to reinvent the wheel. And if you need to change some of the basic behavior of the
package, you need to have only one good, solid programmer study the internal workings of the package. If done correctly, any
changes that person makes will automatically enhance the programs written by your application programmers.

After I had the JBUI package working, I realized that I should write some real database applications combining JBUI with
JDB/400. However, a funny thing happened as I was writing. I began to notice that many of the calls to these encapsulating
classes could indeed be encapsulated themselves. This was the first step toward the development of the JAO/400 package
(again, at www.zappie.net). JAO (for Java Application Objects) is designed to provide a standard way to develop applications.

JAO/400 is an example of a "frameworks" package. Frameworks are the ultimate expression of encapsulation. The designer
distills the portion of a given application that is common across implementations and provides base classes with minimal
functionality in support of that application. In the case of JAO/400, I wanted to design classes that would support basic
business applications. The implementer can then add site-specific extensions to the base classes.

One of the primary requirements of business systems is the ability to inquire into and modify master files; to that end, I
developed some classes to support single-file lists and single-record display panels. Ja o 400L ist is a data list panel similar to
a subfile, and Ja o 400D isp la y is a detail panel. I began to experiment with linking the JDB/400 information to the JBUI
screens and came up with a way to automatically retrieve the characteristics of an AS/400 file and translate it directly into
JBUI screen fields without actually having to define each individual field. Implementing a JAO/400 class became simply
defining the AS/400 file name and the field names I needed to work with.

You may notice a trend here: You can tell that your OO programming is going correctly when your interfaces become simpler
rather than more complex. Because of encapsulation, common functions tend to be combined, and interfaces between those
functions are hidden. The best example of this to date is the Ja o 400S p lit class. Ja o 400S p lit is the culmination of a year of
research and development. It's still a fairly simple class, but it's also very powerful. It takes advantage of all the strengths of
Java but still works pretty closely with the old 24-by-80 paradigm.

A Ja o 400S p lit is a split panel: The left pane is a record list, and the right pane contains the details for the selected record.
The primary acquiescence to the GUI paradigm is that record selection is a double-click rather than a selection code and a
command key. Figure 6.4 shows a Ja o 400S p lit panel that has been extended to display the Shop Order file from System
Software Associates' Business Planning and Control System (BPCS). The class is called F S O S p lit, and it requires a grand
total of 16 lines of code, four of which are blank and three of which consist only of a closing brace. The code for the F S O S p lit
class is shownin its entirety in Figure 6.5 .
F ig u re 6.4: This Jao400Split panel has been extended to display the Shop Order file from System Software Associates'
BPCS.

F ig u re 6.5: This is the entire code for the FSOSplit application.

Team-Fly
Team-Fly

D iv isio n O f L ab o r: D iv id e A n d C o n q u e r
I hope this chapter gives you a glimpse of how encapsulation can dramatically improve your productivity. By designing your
classes so that different areas of expertise are encompassed in different levels of the hierarchy, you can actually begin to
divide your workload in a rational manner and allow your programmers to become subject-matter experts. In the examples in
this chapter, one package requires in-depth knowledge of the record-level access classes but little else, one package requires
a strong understanding of graphical and nongraphical user interfaces, and one package requires an understanding of business
applications. Even though I wrote all three, there is no reason why each package couldn't have been developed independently
and linked together. The result is a set of classes that even a novice Java programmer can use to create sophisticated, robust
client/server applications. This is the power of encapsulation.

Team-Fly
Team-Fly

C h ap ter 7: Q sh ell A n d IB M 's Java T o o lb o x F o r T h e A S /400


O v e rv ie w
DON DENONCOURT

Java is executed on OS/400 through a UNIX-style command entry screen called Qshell. The Qshell program product is
bundled with OS/400. All the commands that come with a Java Development Kit (JDK) are available from the Qshell screen.
To make the most of Qshell, you need to know how to use some of its basic features.

This chapter covers Qshell basics and then explains how to personalize your Qshell Java work environment with an initial
program. First, you should note that Java on OS/400 runs out of the Integrated File System (IFS). Your Java source (.ja .ja va
va)
and your Java executables (.cla ss) exist in IFS directories. Actually, OS/400's library system is also within the IFS. Your
.cla ss
libraries, and the objects that they contain, are under the IFS directory called QSYS.LIB, as shown in the Work with Object
Links (WRKLNK) screen in Figure 7.1. Your Java files are typically kept in directories that you create, such as
my /h o m e /D e n o n co u rt directory shown in Figure 7.2. To become comfortable with the IFS, I suggest you use the WRKLNK
command and browse around the directory under your AS/400's IFS.

F ig u re 7.1: Using the Work with Object Links panel is an excellent way to become comfortable with the
IFS.

F ig u re 7.2: Java files are stored in directories within the IFS.

Enough about the IFS and WRKLNK; I want to return to Qshell. After you have brought up the Qshell Command Entry panel
with the QSH command, you can issue Qshell's built-in commands. Table 7.1 lists the Qshell commands that are used most
often.

T a b le 7.1: B a sic Q sh e ll C o m m a n d s
C om m and F u n ctio n
cd Change current directory.
cp Copy
echo Display the value of an environment variable.
export Make an environment variable accessible to jobs spawned by Qshell.
java Start the Java Virtual Machine.
javac Compile a Java source file.
mkdir Make a new directory.
mv Move or rename object.
pwd Print working directory.
rm Remove a file.
rmdir Remove a directory.
system Execute an OS/400 command.

I'm not going to go into detail about how to use all of these commands because help is readily available from your Qshell
command screen. To find out how to use a command, simply key in the command name and press Enter without any
parameters. Qshell will respond by listing the syntax of the command, as shown in Figure 7.3. Two of the commands that I
will overview are syste m and e x p o rt. The syste m command can be used to execute a standard OS/400 command from within
Qshell. I often use this command to optimize my Java class files with the Create Java Program (CRTJVAPGM) command:
> system "crtjvapgm ArnerRLALocal.class optimize(40)"
JVAB564: USEADPAUT and USRPRF parameter values were ignored.
JVAB522: Java program created for "ArnerRLALocal.class".
/home/Denoncourt

F ig u re 7.3: To display help for a command, simply issue it without parameters.

Team-Fly
Team-Fly

A P ath W ith C lass


The e x p o rt command is used to make an environment variable available to processes started by Qshell. There are two
environment variables that are important to your Qshell environment: PATH and CLASSPATH. Qshell uses the PATH
environment variable to search for commands. PATH is already set up on your machine with the directory qualification of the
built-in utilities (/u
/u sr/b in ).

CLASSPATH, however, is not automatically configured on your machine. To create an environment variable in Qshell (you
could use Add Environment Variable [ADDENVVAR] from an OS/400 command line), you simply key in a variable name, the
equal operator, and the variable's value:
CLASSPATH=.:/qibm/ProdData/HTTP/Public/jt400/lib/jt400.jar:/home/Denoncourt:

Often, however, companies will create a systemwide CLASSPATH. This can be done either with the ADDENVVAR command
with Level option set to *SYS or with the p ro file file (which I will discuss in the "Qstartup and Initial Program" section). From
within your Qshell session, you might not want to replace the systemwide setting; if you don't want to replace the
systemwide setting, you append the existing CLASSPATH with the following command:
CLASSPATH=$CLASSPATH:/home/Denoncourt:

The dollar sign ($) qualifies the string that follows as an environment variable. It's a good idea to use this syntax all the time
because, even if the CLASSPATH variable doesn't exist, the command still works.

Here are a few tips on the CLASSPATH environment variable. First, make CLASSPATH all uppercase. I know on your PC,
lowercase works, but, whereas DOS is case-insensitive, UNIX-style shells like Qshell are case-sensitive. Second, use a
colon (:), not a semicolon (;), to separate paths. Once again, Windows may use the semicolon, but Qshell doesn't see the
semicolon as a separator, and Qshell will never tell you that your CLASSPATH is wrong. Third, if you want to see the value of
your CLASSPATH, simply use the e ch o command:
echo $CLASSPATH

Finally, if you expect Java classes to be executed from your current directory but you don't want to qualify that directory
explicitly in your CLASSPATH, add an entry that is simply a period between two colons, which basically tells Java, "Hey,
look right here, where I am now."

Team-Fly
Team-Fly

Y o u r O S /400 H o m e
All UNIX platforms have the concept of a home directory (it's sort of like a user library), and because OS/400's Qshell
environment is patterned after UNIX, the AS/400 has a home directory also. Each user profile has a home directory specified.
It defaults to a directory of your name underneath the /h o m e directory. For instance, mine is /h o m e /D e n o n co u rt. There is
also a default environment variable called HOME, so from within Qshell, you could look at your home directory by issuing
e ch o $H O M EE. You can change your home directory with OS/400's Change User Profile (CHGUSRPRF) command:
CHGUSRPRF USRPRF(DENONCOURT) HOMEDIR('/home/Denoncourt')

Note that once a home directory is set for your user profile, the OS/400 WRKLNK command, if issued without any options,
automatically displays your home directory. This can be a nuisance if you want to look at another directory, but all you need
to do is issue the WRKLNK command with the explicit directory qualification. For instance, to view all of the IFS directories, I
use the root slash:
WRKLNK "/"

Team-Fly
Team-Fly

Q startu p A n d In itial P ro g ram


OS/400 has a special program called Qstartup that is executed when you do an IPL. Typically, you code this program to start
subsystems and to otherwise issue systemwide one-time startup commands. Most AS/400 programmers create initial
programs that are qualified in their user profiles. In those initial programs, they make settings that are job-specific. UNIX
shells, such as Qshell, have a similar concept.

There are two special files in Qshell: p ro file and .p ro file (one with no suffix, and one with no prefix). Environment settings
(such as CLASSPATH) that you want to be systemwide can be made in the p ro file file. Environment settings that are
specific to one programmer can be placed in the .p ro file file. When you execute the OS/400 QSH command, Qshell will look
in your home directory for a file called .p ro file (no prefix), and, if it exists, it will execute the Qshell commands contained
within that file. Qshell will also look in the /e tc directory for a file called p ro file (no suffix) and, if it is found, execute the
commands that it contains.

Team-Fly
Team-Fly

C lassp ath , T h e H ard W ay


You will find that AS/400 Java application testing is simpler to do from the Qshell environment than it is with OS/400's Run
Java (RUNJVA) command. The RUNJVA command requires the specification of the application's Java CLASSPATH in the
CLASSPATH option:
RUNJVA CLASS('ListRecords') +
CLASSPATH('/home/DENONCOURT:/qibm/ProdData/HTTP/Public/jt400/lib/jt400.jar:')

Alternatively, the CLASSPATH may be specified in an environment variable with the ADDENVVAR command:
ADDENVVAR ENVVAR(CLASSPATH) +
VALUE('/qibm/ProdData/HTTP/Public/jt400/lib/jt400.jar:/home/DENONCOURT:')

With the CLASSPATH environment variable set, the RUNJVA command will then be able to find that environment variable,
which relieves you of the trouble of manually setting the CLASSPATH option of the RUNJVA command. (Note that
CLASSPATH must be in uppercase.) The following three RUNJVA commands will perform exactly since ENVVAR is the
default:
RUNJVA ListRecords RUNJVA CLASS('ListRecords') RUNJVA
CLASS('ListRecords') CLASSPATH(*ENVVAR)

Notice that I adhered to Java's case sensitivity when I keyed my example Java class name of L istR e co rd ss.

The RUNJVA command may be a "shortcut" alternative to Qshell, but it simply turns around and invokes Qshell anyway. The
only difference is that, when your application completes processing, the Qshell exits as soon as you press the Any key.

Team-Fly
Team-Fly

C lassp ath , T h e E asy W ay


To set up my Qshell environment's initial program, I set up my default .p ro file script for Qshell. My .p ro file script (Figure 7.4)
sets up the directory prompt (PS1); specifies the CLASSPATH to the JAR file for IBM's AS/400 Toolbox for Java, as well as a
couple of other JAR files; and then makes that CLASSPATH available to subprocesses with the e x p o rt command. The cd
function effectively replaces Qshell's Change Directory command. Each time I use cd from Qshell, my own cd function calls
the real cd command, with co m m a n d cd $@ , and then resets the prompt to be equal to the new working directory. If you
look at Figure 7.5, you'll see that the default prompt of the dollar sign (see Figure 7.3) is now replaced with my current
working directory. (It is interesting to note that when you execute a command in Qshell, the input inhibit indicator, typically an
X, does not stay on while the command executes. That's because Qshell runs commands as threads, or subprocesses.
You'll know that a command is complete when the prompt is displayed.)

F ig u re 7.4: The special .profile script is executed each time you go into Qshell.

My user profile is DENONCOURT, so I have a directory underneath the IFS /h o m e directory called Denoncourt
( /home/Denoncourt). My .profile script is the simple text file shown in Figure 7.4 with the fully qualified file name of
file. You can create your own .p ro file on your PC and copy it to your AS/400's home directory, or
h o m e /D e n o n co u rt/.p ro file
you can use OS/400's Edit File (EDTF) command:

F ig u re 7.5: You can create an initial program for Qshell by putting a .profile script in your home
directory.

EDTF '/home/Denoncourt/.profile'

If the file exists, EDTF will present it for edit, but if the file doesn't exist, EDTF will create it. Note that OS/400 follows the
UNIX convention of suffixless files being considered hidden, so OS/400's WRKLNK panel and Qshell's List (ls) command
won't show your .profile. However, the ls command does have an –a option to list all files, and with that option set, you'll see
the .profile.

With my .profile script set up, I tested a class that I had just written called Inv001, as shown in the Qshell screen capture in
Figure 7.5. Inv001 uses IBM's AS/400 Toolbox for Java's Modification 3's PCML. My CLASSPATH required the d a ta 400.ja r
and x 4j400.ja r files. The three output lines of zo n e d F ie ld , p a cke d F ie ld , and ch a rF ie ld are from In v001
v001, but the path that
follows them is automatically generated from the $PWD setting of the PS1 prompt directive in my .p ro file script. It's certainly
handy to know what your current path is. That's exactly why your PC DOS prompt shows the current directory.

With a .p ro file set up, you don't have to laboriously set up your CLASSPATH each time you enter Qshell. After a while, you
may find that you want to establish systemwide CLASSPATH settings. To do so, you simply create a p ro file script in
the /e tc directory and all your Qshell users will benefit from a predefined CLASSPATH. Chapter 37 in Section VI, "UNIX
Developers Find a Home in Qshell," goes into advanced features of Qshell.
Team-Fly
Team-Fly

C h ap ter 8: Java S ervlet P ro g ram m in g F o r T h e H T M LL--


C h allen g ed
O v e rv ie w
DON DENONCOURT

I'm HTML-challenged. I love coding Java and I like to think that my Java code is exemplary, but, for me, HTML coding is just a
necessary evil. I like to make my Java code look pretty with proper indention and naming conventions and such, but,
regrettably, I don't have the same feeling about my HTML code. Basically, all I want to do is get the information up on a
browser and get the user's response back. And I don't like coding all those ugly HTML tags in my servlet code. One great
alternative is to use JavaServer Pages (JSPs) and let a Web designer, who does love to code HTML, do the user interface.

IBM's Java Toolbox for the AS/400 (JT400) Modification 3 has an additional alternative strategy for generating HTML. The
JT400 now includes packages called co m .ib m .a s400.u til.h tm l and co m .ib m .a s400.u til.se rvle t.

The HTML utilities package provides Java class wrappers for HTML tags, as shown in Table 8.1. Note that none of these
classes is AS/400-specific. Also note that Rochester's JT400 programmers were not the first Java coders to come up with
such utilities. I've seen such classes before for other vendors of Java integrated development environments and even as
shareware. Nevertheless, IBM did a nice job on these classes. Through the use of these classes, my Java code now looks
"pretty" again because it is not littered with embedded HTML tags. But more than beautifying my code, the classes also
provide more structure to the design of an HTML page.

T a b le 8.1: Ja va C la ss W ra p p e rs fo r H T M L

H T M L C la ss H T M L C la ss H T M L C la ss
ButtonFormInput HTMLTableRow ResetFormInput
CheckboxFormInput HTMLText SelectFormElement
FormInput HiddenFormInput SelectOption
GridLayoutFormPanel ImageFormInput SubmitFormInput
HTMLForm LabelFormElement TextAreaFormElement
HTMLHyperlink LayoutFormPanel TextFormInput
HTMLTable LineLayoutFormPanel ToggleFormInput
HTMLTableCaption PasswordFormInput URLEncoder
HTMLTableCell RadioFormInput  

HTMLTableHeader RadioFormInputGroup  

To give an example of what I mean, look at the Web page in Figure 8.1. Now look at the HTML code in Figure 8.2 that builds
the table shown in Figure 8.1. What are all those tags about? What is not obvious to the HTML-challenged (like myself) is the
hierarchy of tags. At the top of the hierarchy is the table tag. Inside the table tags are rows (<< tr> tags), headers (<< th > tags),
and elements (<< td > tags). Now, using the HTML utilities of JT400, you can create a table object with the H T M L T a b le class,
and into that object, you add the headers, rows, and elements using methods that have meaningful and descriptive names.
Then, when you are done building the table with the HTML utility classes, you use the H T M L T a b le class's g e tT a g method to
spit out all the ugly HTML tags. This makes much more sense to me than directly embedding the HTML code in my servlet.
F ig u re 8.1: HTML tables are the "subfiles" of the Internet.

F ig u re 8.2: The HTML tags required to generate an HTML table manually are somewhat terse.

Take a look at the Java servlet code shown in Figure 8.3, which generated the HTML code shown in Figure 8.2.

F ig u re 8.3: The com.ibm.as400.util.html allows you to generate an HTML table using the meaningful methods of object-
oriented classes rather than cryptic HTML tags.
First, note that my table is populated from a "fake" database (I used a couple of parallel arrays) in the H T M L C la sse s servlet
class. The table is built in the d o G e t method (which is automatically invoked by the Web application server from a URL
servlet request). The d o G e t method does the standard setup and then it creates an H T M L T a b le object:
HTMLTable table = new HTMLTable();

Then it sets a couple of table attributes:


table.setAlignment(HTMLTable.CENTER);
table.setBorderWidth(1);

That's certainly easier than using cryptic HTML to set table attributes. Next, the servlet sets the table's headers with a few
simple calls to the H T M L T a b le class's a d d C o lu m n H e a d e r method:
for (int i = 0; i < headers.length; i++) {
table.addColumnHeader(headers[i]);
}

With the headers set, the servlet then iteratively adds rows to the table, again, with a method of the H T M L T a b le class:
for (int i = 0; i < headers.length; i++) {
table.addRow(getNextRow(i));
}

I did a little encapsulation myself by coding a method for my H T M L C la sse s servlet called g e tN e x tR o w . My g e tN e x tR o w
method constructs an H T M L T a b le R o w object from the next element in my "fake" database. A table is made up of rows and
columns. Similarly, an H T M L T a b le object is made up of H T M L T a b le R o w objects, which, in turn, are made up of
H T M L T a b le C e ll objects. Those cells are filled with H T M L T e x t. Why H T M L T e x t? Why not just a S trin g object? The
H T M L T e x t object is smart enough to encode characters that have special meaning to HTML. A quote, for instance, would be
replaced with a backslash quote (\"). My g e tN e x tR o w method creates an H T M L T a b le R o w , and then it creates H T M L T e x t
ob-jects to hold the database information to be placed as columns in that row. Next, it creates H T M L T a b le C e ll objects that
encapsulate the H T M L T e x t objects and adds them to the H T M L T a b le R o w with the a d d C o lu m n method (shown in Figure
8.4).

F ig u re 8.4: The getNextRow method, with minimal lines of code, builds a new row for your HTML
"subfile."

Finally, the HTML is pulled out of the H T M L T a b le object with the g e tT a g method and stuffed into the H ttp S e rvle tR e sp o n se
object:
out.println(table.getTag());

Team-Fly
Team-Fly

S e rv le t C lasse s
This hierarchical structure of the object- oriented Java classes of the co m .ib m .a s400.u til.h tm l package makes a lot of sense
to me.Furthermore, I believe my code is far more maintainable than code that contains ugly HTML tags. IBM's JT400 went
another step further with its co m .ib m .a s400.u til.se rvle t package. The co m .ib m .a s400.u til.se rvle t package has more than
a dozen classes (a subset of which is shown in Table 8.2) that dynamically construct data retrieved from either JDBC or
record-level access into HTML forms.

T a b le 8.2: T h e A S /400 S e rvle t U tility C la sse s

H T M L C la ss
HTMLFormConverter
HTMLTableConverter
ListMetaData
ListRowData
RecordFormatMetaData
RecordListRowData
RowData
RowDataEvent
RowMetaDataType
SQLResultSetMetaData
SQLResultSetRowData
StringConverter

To test out the co m .ib m .a s400.u til.se rvle t classes, I developed the Java servlet shown in Figure 8.5 to list rows from the
QIWS/QCUSTCDT file in an HTML table.

 
 

F ig u re 8.5: The ServletClasses servlet uses JT400's com.ibm.as400.util.servlet classes to list rows from the
QIWS/QCUSTCDT file in an HTML form .

The only HTML tags that you'll find in my servlet are < H T M L > < B O D Y > and < /B O D Y > < /H T M L >>. The rest of the tags are
inserted into the HTTP response with the class of the co m .ib m .a s400.u til.se rvle t package. Also note that you won't find
code that loops through an SQL result set; that is done automatically by the co m .ib m .a s400.u til.se rvle t classes.

My servlet retrieves a JDBC R e su ltS e t object using the following SQL SELECT statement in its d o G e t method:
SELECT cusnum, lstnam, baldue
FROM qiws.qcustcdt
ORDER BY baldue DESC

The d o G e t method then passes that R e su ltS e t object to the constructor for the package's S Q L R e su ltS e tR o w D a ta class:
co m .ib m .a s400.u til.se rvle t
recs = new SQLResultSetRowData(rs);

It then creates an H T M L T a b le object (the same H T M L T a b le from the co m .ib m .a s400.u til.h tm l package) and sets a few
attributes for the table:
HTMLTable table = new HTMLTable();
table.setHeader(headers);
table.setBorderWidth(2);
table.setCellSpacing(1);
table.setCellPadding(1);

Then the d o G e t method creates an H T M L T a b le C o n ve rte r object. It is the job of this converter to transform the data in the
S Q L R e su ltS e tR o w D a ta object into an HTML table. The converter class has a method called co n ve rtT o T a b le s that requires
the object variable that references an S Q L R e su ltS e tR o w D a ta object and returns an array of HTML. My d o G e t method sets
the default table with the se tT a b le method and then invokes the converter (Figure 8.6).

F ig u re 8.6: The HTMLTableConverter class has the smarts to create a complete HTML table from an SQL result
set.

After the converter does its stuff, the HTML table can be inserted into the H ttp S e rvle tR e sp o n se object:
out.println(htmlTable[0]);

Figure 8.7 shows how the resulting Web page looks in Internet Explorer, and Figure 8.8 shows the HTML code generated by
the servlet.
F ig u re 8.7: It is handy to be able to quickly generate an HTML table from an SQL result set with minimal
coding.

 
 

F ig u re 8.8: The HTMLTableConverter object does all the work of transforming data from an SQL result set into an HTML
table .

Team-Fly
Team-Fly

E n cap su late , E n cap su late , E n cap su late


If the basic rule of real estate is location, location, location, then the basic rule of Java is encapsulate, encapsulate,
encapsulate. That's what IBM has done with its co m .ib m .a s400.u til.h tm l and co m .ib m .a s400.u til.se rvle t packages. It has
encapsulated the complexity of HTML coding and table generation from a relational database into easy-to-use Java classes.
The net result is code that is easier to write, easier to read, and easier to maintain. Personally, I don't want to be challenged
by writing HTML code—I want to be challenged by writing solid code with Java.

Team-Fly
Team-Fly

C h ap ter 9: R ed u cin g A p p let C o d e S ize W ith P ro xy C lasses


O v e rv ie w
JEFF MARKHAM

Java programmers who want to write full-featured, powerful business applications to be used as applets usually have their
enthusiasm for such projects tempered by the reality of applet download time. Not helping this problem is the 2.7 MB
jt4 0 0 .ja r file used by AS/400 Java developers. In general, the more functionality an applet features, the larger it is. A large
applet takes a long time to download and will invariably give users an unfavorable view of it. Proxy support in the AS/400
Toolbox for Java (JT400) Mod 3 takes the form of a 526 KB file called jt400P ro x y.ja rr, which helps to alleviate some of this
problem. This chapter takes the wraps off this feature. You'll see if there are better or at least other ways to ease the
download troubles associated with a large applet.

The goal of proxy support is to make the downloaded .jar file in your applet as small as possible so that it can be downloaded
as quickly as possible. Proxy support accomplishes this mission by making only the interface to the supported classes
available in the .ja r file and executing the specific tasks of the supported class on another machine, usually a server. For
example, if your applet uses the P ro g ra m C a ll class from the jt4 0 0 .ja r file, it can now use the P ro g ra m C a ll class in the
jt400P ro x y.ja r file without any modifications to your applet code. The class in the jt400P ro x y.ja r file simply gives the
developer an interface to the "real" class in the jt4 0 0 .ja r file, which would presumably reside on a server.

Proxy support requires that a server be listening on a specified port, the default of which is 3470. In other words, there must
be a server application constantly running on a specified server. It doesn't have to be the AS/400 your applet is trying to use;
in fact, it doesn't have to be an AS/400 at all. If you use proxy support, you have the ability to partition your application among
servers, thereby distributing resource requirements to other machines.

Also, if your applet must be allowed through a firewall, there is only a single port used by proxy support. Without proxy
support, a firewall must allow your applet access to as many ports as your applet requires. JDBC requires one port,
P ro g ra m C a ll requires another, an AS/400 object yet another, and so on. Not all classes of the JT400 are available for proxy
support. The following are classes that are supported by proxy:

 JDBC.

 Record-level database access.

 AS/400 IFS file.

 Print.

 Data queues.

 Command call.

 Program call.

 Service program call.

 User spaces.

 Data areas.

 AS/400 object.

 Secure AS/400 object.

The A S 400T o o lb o x Ja rM a ke r class plays an important part in making a .ja r file as small as possible for download. What
this utility class does for you is create a .ja r file by extracting only the classes necessary for whatever base component of
the toolbox your applet requires. For example, if an applet requires only those classes necessary to facilitate JDBC
functionality, this utility class could be used to extract the JT400 classes required by AS/400 JDBC. The command to
accomplish this task would look like this:
java utilities.AS400ToolboxJarMaker -component JDBC

I'll use an example applet to illustrate the concepts I've covered so far. To do a bit of comparing and contrasting, I'll also
demonstrate a way to write an even smaller applet with identical functionality. The applet makes a JDBC query to the
QIWS/QCUSTCDT file and displays it in a JTable (Figure 9.1). There are five configurations of the example applet: using the
entire jt4 0 0 .ja rr, the jt4 0 0 .ja r with JDBC only, the jt400P ro x y.ja rr, the jt400P ro x y.ja r with JDBC only, and a servlet that
handles jt4 0 0 .ja r processing.
F ig u re 9.1: Java applets deployed in a business scenario often require the presentation of information retrieved from
complex relational database files.

In the first four examples, in which the applet is responsible for handling the classes of the JT400, the code is basically
consistent throughout each. There's only a one-line difference if the applet wants to use proxy support: the line that
instantiates a Properties object that sets the system property of p ro x yS e rve rr. Setting the system property this way is
explained in detail in the AS/400 Toolbox for Java documentation and is the method I chose to perform this task. In a nutshell,
this process identifies the host that will run the p ro x yS e rve rr:
put ("com.ibm.as400.access.AS400.proxyServer", "hostorIP");

In the fifth configuration of the example, I chose to have a servlet be responsible for handling the requests for JT400 classes. I
believe this is a valid comparison because—according to the AS/400 Toolbox for Java documentation—the whole point of
using proxy support is to make the downloaded .ja r file smaller, thereby decreasing download time. An application using
applet-to-servlet communication accomplishes this goal by leaving the jt4 0 0 .ja r file on the server and requiring the browser to
download only a class that handles the GUI display. Because I've moved all the statements handling the JDBC access and
result set processing to the servlet, the class identified in the CODE parameter of the HTML applet tag is even smaller than
the class in the CODE parameter of the first four examples.

Also, I mentioned that proxy support funnels all requests to a single port, thus requiring only one additional port to be made
accessible by a firewall. Using the servlet of the example, however, there are no additional ports required. All communication
in this applet-to-servlet example flows through the Web server's HTTP port, which is usually the well-known port number 80.

The servlet handles all the JDBC access and will even create the vector required to populate the JTable with rows of data. A
servlet that serializes an object will have to implement the S e ria liza b le interface. The S e ria liza b le interface contains no
methods or fields. Implementing it in a class only serves as a flag to the Java Virtual Machine (JVM) that the class is allowed
to serialize itself or other objects encapsulated by the class. When the servlet is finished creating the V e cto r object, it will
write the V e cto r object to an O b je ctO u tp u tS tre a m using the w rite O b je ct() method.

There are more than a few methods of applet-to-servlet communication. The more robust and complex methods of Remote
Method Invocation (RMI) and CORBA are generally used when objects need to call each other's methods. Furthermore, RMI
and CORBA can be used with remote objects if you ever find yourself in a situation where the Web server you're working with
does not have a servlet engine.

If simple text is all that is required of your communication, you could have your servlet create a PrintWriter object and write
your text using the println() method. In my example, I use object serialization as a means of communication. Object
serialization is simply a way to write the values of an object's data to a stream of bytes. When you turn an object into a
stream, you can write it to a file, print it, or, in this case, send it across a socket connection. The servlet code is shown in its
entirety in Figure 9.2.
 

F ig u re 9.2: The DBServlet servlet acts as a mediator between applets and DB2/400; it performs database retrieval from
DB2/400 and passes the result back to the applet as a serialized (text) file .

There are essentially three hosts that need to be determined when considering proxy support: the AS/400 that houses the
data and other objects that are the target of your applet, the machine acting as the proxy server, and the HTTP server. They
can all be the same machine or split into different machines. Practically speaking, however, one machine should act as both
the proxy server and the HTTP server. Unsigned applets can create network connections only on the machine from where
they were downloaded. In other words, if you choose three separate machines in this scenario, only a signed, trusted applet
can create the connection to the machine acting as the proxy server.

After determining your host configuration, start the proxy server on the machine you designate. If it is an AS/400 and your
CLASSPATH environment variable contains the jt400.jar of the JT400 Mod 3, start the Qshell Interpreter and enter the
following command:
java com.ibm.as400.access.ProxyServer –verbose.

At the very least, make sure that the jt4 0 0 .ja r file is in the CLASSPATH of the host acting as the proxy server.

As I discussed, it's advantageous to make the downloaded .jar file as small as possible by using the AS400ToolboxJarMaker.
Use this class to extract only those classes your applet requires from the toolbox. Using the default settings on this
command will cause the utility to append the word Small after the file name and before the file extension. For example,
running the utility on the jt400Proxy.jar file will result in a file named jt400ProxySmall.jar. Keywords for the –component flag
are referenced in the JT400's documentation.

I mentioned earlier that an applet that uses proxy support must set the proxyServer system property. I used the convenient
example in the toolbox's documentation, which accomplishes this task with the following statement:
put("com.ibm.as400.access.AS400.proxyServer", "ProxyServerHostName");.

After placing all class, .ja rr, and HTML files in their appropriate directories, you'll refer to the .ja r file you created with the
A S 400T o o lb o x Ja rM a ke r in your applet's ARCHIVE property. When all these tasks are complete, you're ready to take
advantage of proxy support.

There are many variables in testing the performance gains in proxy support. It is sufficient to say that the less your applet has
to download, the better. But what about other performance issues such as runtime performance? With proxy support comes
extra communication between the proxy classes and the "real" classes archived in the jt4 0 0 .ja r file. This isn't a trivial factor:
The documentation for the proxy classes states that applications (not applets) that use the proxy classes will suffer
performance degradation for the sole reason of the extra overhead of communicating between the two groups of classes. All
things being equal, an applet's runtime performance, as well as an application's runtime performance, will be affected because
of the same extra communication. The amount of degradation will, of course, depend on the network resources and the
resources available to the machines performing the applet download, the proxy support, and serving HTML pages.

In all the variations of the example in this chapter, there exists communication overhead. The least amount of communication
overhead is found where there is no proxy support. Obviously, the trade-off is that download times are decreased but runtime
performance is diminished.

Figure 9.3 shows the sizes of the entire download for each variation of the example. The first example uses the jt400.jar file
and the main class in the applet's CODE parameter. The KB sizes are the total of all the classes and JARs that must be
downloaded to execute the applet. As you can see, using applet-to-servlet communication surpasses proxy support in
accomplishing the goal of making downloads as small as possible while achieving identical results.

F ig u re 9.3: Each of the five applet configurations has a progressively smaller JAR file size.

Proxy support is certainly a step in the right direction as far as creating leaner, faster-downloading applets. Experienced Web
users have all been to Web sites where applets take forever to download, causing frustration and, more likely, causing users
to abandon the Web site while making a mental note never to go back.

Web stores where core functionality relies on applets to guide the customer from product and/or service offerings all the way
through to checkout will never be as successful as they can be if those applets take too long to get to the customer.
Similarly, companies that are links in a Web-based supply chain could be looked upon as less than capable by their
upstream and downstream partners if their applets are the bottleneck in the flow of data.

AS/400 shops looking to decrease the download time for their applets—and thereby increase their chances of a favorable user
impression—will look to the proxy support provided by the AS/400 Toolbox for Java as an immediate fix. Departments that are
just starting out in using the toolbox classes in their applets might want to think twice about using the proxy support
approach and opt for a more robust solution such as the applet-to-servlet example in this chapter. Think through your
implementation thoroughly and consider every option available to you before deciding if it's the right method for putting your
solution into production.

Team-Fly
Team-Fly

S e c tio n III: JD B C : S Q L F o r Java


C h ap te r L ist
Chapter 10: JDBC Basics

Chapter 11: Getting to know JDBC

Chapter 12: Prepare Your JDBC Application for Performance

Chapter 13: Using Commitment Control with JDBC

Chapter 14: A Few JDBC Tips and Techniques

P art O v e rv ie w
Once business programmers learning Java become comfortable with coding "Hello World"-style applications, they are ready
to start to access data—relational data, that is, which for us AS/400 programmers is stored in DB2 UDB. For AS/400
programmers, there are two main options for accessing DB2 for OS/400: record-level access and SQL access via JDBC.
Record-level access is covered in Section II. This section comprises five chapters that collectively provide a solid introduction
to JDBC.

The first chapter, "JDBC Basics," provides a fast-paced overview of JDBC, complete with a "one-minute" guide to SQL. In the
next chapter, "Getting to Know JDBC," Ted Holt provides a basic JDBC example application and then discusses accessing
database metadata (data about data) with JDBC.

The next two chapters take it up a notch. "Prepare Your JDBC Applications for Performance" introduces JDBC's
P re p a re d S ta te m e n t class. The use of SQL prepared statements can substantially improve the performance of your Java
application, and they are very easy to use. "Using Commitment Control with JDBC" explains how to use commitment control.
Many AS/400 shops do not use commitment control, but, as you move to SQL access with JDBC, you need to reconsider
the use of commitment control to ensure the integrity of your applications. Commitment control is practically a requirement
when you have concurrent JDBC access to your database.

This section finishes with "A Few JDBC Tips and Techniques." The tech tips include how to use library lists with JDBC
connections and how to set your record buffer. The chapter also explains the two JDBC drivers available for your DB2 UDB on
OS/400—a 100% Pure Java driver and an optimized native driver.

If you are really interested in JDBC, you might want to skip ahead to Chapter 24, "Calling RPG from Java," in Section V.
JDBC has a mechanism for invoking RPG and COBOL programs from your Java applications that you will find to be an
important aspect of your JDBC knowledge.

Team-Fly
Team-Fly

C h ap ter 10: JD B C B asics


O v e rv ie w
DON DENONCOURT

Java is heralded by many as the most successful cross-platform language ever. But this is simply not true; the world's most
successful cross-platform language is SQL, not Java. SQL was developed decades ago to be the preferred data definition and
data manipulation language for relational databases (RDBs). In fact, most vendors of RDBs provide no access facilities other
than SQL. These RDB products have no data description specifications and no record-level access. In the mid-1980s, when
client/server architectures were coming into vogue, SQL became even more successful because ODBC was introduced to
provide a cross-vendor C API for SQL-based database access.

Although SQL was a standard, until ODBC, there was no standard C API for accessing the database. The ODBC standard
greatly simplified porting from one database to another. Eventually, vendors began to make ODBC APIs for a variety of
languages, the most predominant of which is Microsoft's Visual Basic. Then, when the Java programming language was being
developed by Sun Microsystems, the obvious access mechanism for relational data was ODBC, so the developers at Sun
created JDBC.

The JDBC API was based on ODBC, but its developers simplified the interface and streamlined processing. Initially, however,
the only JDBC drivers that were available used ODBC drivers in the background to connect with your RDB of choice. What
programmers did was use the default JDBC driver that was (and still is) shipped with the Java Development Kit (JDK). That
driver is known as a JDBC-to-ODBC driver because it requires an ODBC driver. The problem with JDBC-to-ODBC drivers is
that, because you are essentially using two middleware products, your applications run slow. But RDB vendors quickly saw
the potential for Java and developed 100% Pure JDBC drivers that did not require the use of an ODBC driver. Many of those
JDBC drivers were faster than their ODBC counterparts, and most RDB vendors made their JDBC drivers available for free.

Eventually, for optimal performance, RDB vendors created what are known as native JDBC drivers. These drivers were
implemented to use the architecture of the RDB's native platform rather than the interpreted cross-platform Java language.
Today, the AS/400 has both a 100% Pure JDBC driver for cross-platform client access to DB2 for OS/400 and a native JDBC
driver for host-based access to DB2/400. The AS/400 Toolbox for Java (license program 5763-JC1) contains a 100% Pure
JDBC driver, and the AS/400 Developer Kit for Java (license program 5769-JV1) contains a native AS/400 JDBC driver.

Team-Fly
Team-Fly

O n ee--M in u te G u id e T o S Q L
SQL is a relatively simple language to learn because it is a combination of a relatively small number of commands. To define
files (tables in SQL parlance), you use the CREATE TABLE command:
CREATE TABLE invdtl
(invno INT, lineno INT, itemno INT, amount FLOAT)

To create indexes, you use the CREATE INDEX command. Indexes are implemented on the AS/400 as logical views. Another
command, CREATE VIEW, also creates logical files on the AS/400, but it is used to create alternate "views" of a file with
subsets of fields and so forth. The DROP TABLE command is used to delete files.

The four SQL data manipulation statements are SELECT, INSERT, UPDATE, and DELETE. The SELECT statement is used
to read a set of records based on a selection criterion. That set can be a set that contains only one record. The selection
criterion is usually called the predicate because the logic behind SQL selection criteria is relational algebra. The predicate is
placed in the SQL statement following the WHERE keyword:
SELECT invno, lineno, itemno, amount
FROM invdtl
WHERE invno = 101

These WHERE clauses can be very extensive. In addition, SELECT statements can join together multiple files based on
relations specified in the WHERE clause.

The INSERT statement allows you to add records to your data files:
INSERT INTO invdtl
(invno, lineno, itemno, amount )
VALUES(101, 1, 1001, 2.98)

The UPDATE statement allows you to modify the values of existing database records. The records selected for modification
are based on the SQL WHERE clause:
UPDATE invoice
SET cust = "Agway"
WHERE invno = 101

In the preceding example, because the invoice number is unique, only one record is modified. However, one UPDATE
statement will affect all records that match the SQL predicate of the WHERE clause.

The DELETE statement also uses the WHERE clause:


DELETE invoice
WHERE invno = 101

Team-Fly
Team-Fly

T h e JD B C A P I
There are four Java classes that constitute the main components of JDBC: D rive rM a n a g e rr, C o n n e ctio nn, S ta te m e n t, and
R e su ltS e t. Before you can access your database with JDBC, you first need to load the appropriate JDBC driver. The best
way to do this is by qualifying the driver name within a call to the C la ss class's fo rN a m e method. For instance, the following
specifies the AS/400 Toolbox for Java's 100% Pure JDBC driver:
try {
Class.forName("com.ibm.as400.access.AS400JDBCDriver");
} catch( ClassNotFoundException e) { /* driver not found */ }

This example hard-codes the driver name, so if you expect to use various databases (for instance, I use a local database
driver during testing, then the AS400JDBC driver for production), you should pull the driver name from a Java properties file.
(For more information on soft-coding the JDBC driver name with the Java P ro p e rtie s class, see Chapter 55, "Soft-coding
Values for Java Applications.") Once the driver is successfully found (the CATCH clause for the fo rN a m e method invocation
did not execute), you will then be able to establish a connection to your database. The C o n n e ctio n class is used to connect
to the platform on which your relational database resides. To obtain a C o n n e ctio n object, you use the D rive rM a n a g e r
class's g e tC o n n e ctio n method:
Connection con =
DriverManager.getConnection (
"jdbc:as400://your400DomainOrIP/OptionalDefaultLibraryName",
"user", "password")

The first STRING parameter to the g e tC o n n e ctio n method has four sections: protocol, subprotocol, data source name, and
an optional default library name. The protocol is always jd b cc, but the subprotocol varies with each JDBC driver. For the
AS/400's 100% Pure JDBC driver, which is available with the AS/400 Tool- box for Java, the subprotocol is a s400s400, but for the
native JDBC driver from the AS/400 Developer Kit, it's d b 22. I've used other database drivers and they have their own
subprotocol names; for instance, the shareware database M in iS Q L uses m sq l. The data source name is simply the domain
name or IP address of your AS/400. By the way, you are already familiar with a URL that contains protocols. The URL
http://www.midrangecomputing.com has a protocol of "http," no subprotocol, and a data source name of
www.midrangecomputing.com.

The second and third STRING parameters to the g e tC o n n e ctio n method are the user's name and password. The PROFILE
and PASSWORD parameters are optional. When executing this application on a machine that has a GUI, the AS/400 Tool-
box for Java's JDBC driver will prompt for the profile and password. But if you are running your JDBC application on the
AS/400 (where your IP qualifier is the special "loopback" address of 127.0.0.1), note that you can use the special value of
*cu rre n t for both the profile and password and the JDBC driver will automatically use the profile and password of whoever
started the job that the JDBC application is running in.
Connection con =
DriverManager.getConnection (
"jdbc:as400://127.0.0.1/OptionalDefaultLibraryName",
"*current", "*current")

With an SQL C o n n e ctio n object available, the JDBC S ta te m e n t class can be used to execute any one of the SQL
statement types covered earlier. A S ta te m e n t object is obtained from the cre a te S ta te m e n t method of the C o n n e ctio n
object:
Statement stmt = con.createStatement();

The S ta te m e n t object has two powerful methods for the execution of SQL statements: e x e cu te Q u e ry and e x e cu te U p d a te
te.
The e x e cu te Q u e ry method accepts an SQL SELECT statement as a string, asks the RDB to execute that query, and then
returns the set of records that match that query's predicate. That set of records is returned in the JDBC R e su ltS e t object. The
following Java statement returns all the records from the in v d tl file because there is no WHERE clause specified:
ResultSet rs =
stmt.executeQuery(
"SELECT * FROM invdtl");

Team-Fly
Team-Fly

S e t P ro ce ssin g
To iterate through the set of records contained in the R e su ltS e t object, use the R e su ltS e t object's n e x t method. You can
think of the n e x t method as manipulating a file cursor, except it's a set cursor. When the n e x t method positions the cursor to
the subsequent element of the set, you can then use the R e su ltS e t object's getter methods to retrieve the values of the fields
of a particular record. The getter methods convert the data from the internal format of your RDB to Java objects. There is a
getter method that corresponds to every data type from DB2/400. There are too many getter methods for me to cover in this
chapter, but, for the most part, you will be using g e tS trin gg, for character fields, and g e tB ig D e cim a l, for packed and zoned
values. Each getter method is overloaded to accept two options for parameters. The first option accepts a field name, and the
second option accepts a number that represents the ordinal position of the field as it occurs in the SQL SELECT statement.

The JD B C B a sics class shown in Figure 10.1 spins through all the records retrieved from the QCUSTCDT file with the w h ile
(rs.n e x t ()) statement. The first g e tS trin g method invoked inside the WHILE loop uses the index of the customer number
(CUSNUM) field as it appeared in the SELECT statement. The second invocation of g e tS trin gg, however, uses the field name
LSTNAM. The g e tB ig D e cim a l method then takes the fifth of the customer master file's field listed in the SELECT statement
and converts it into a Java B ig D e cim a l object.

F ig u re 10.1: Most JDBC applications use the DriverManager, Connection, Statement, and ResultSet classes to access
relational data .

Team-Fly
Team-Fly

D ata M o d ificatio n s
I mentioned in the "One-minute Guide to SQL" section that RDB modifications are done with SQL's UPDATE statements. The
UPDATE, INSERT, and DELETE

statements must be executed with JDBC S ta te m e n t class's e x e cu te U p d a te method. The following Java code executes the
UPDATE statement shown in that section:
stmt.executeUpdate(
"UPDATE invoice SET cust = "Agway" WHERE invno = 101");

Team-Fly
Team-Fly

S tu ff H ap p e n s
Things don't always work, so your code must be prepared to handle potential problems. When things go wrong, most of the
JDBC methods generate an error object called S Q L E x ce p tio nn. The invocation of the e x e cu te U p d a te method near the
bottom of the code in Figure 10.1, for instance, results in an error because there is no customer with the number 1234. During
execution of the JD B C B a sics application, the CATCH clause of the TRY block prints an error:
"update error: com.ibm.as400.access.AS400JDBCException: [SQL0100]
Row not found for UPDATE."

The S Q L E x ce p tio n object has three interesting methods: g e tM e ssa g ee, g e tE rro rC o d ee, and g e tS Q L S ta te
te. The
g e tM e ssa g e method returns the full error string, and the g e tS Q L S ta te also returns a string. The g e tE rro rC o d e method,
however, returns an integer, and if it were invoked on the A S 400JD B C E x e ce p tio n object in the e x e cu te U p d a te method
invocation's CATCH, the integer value returned would be 100. In certain situations, you might want to base your error
processing on this integer error code. A "row not found" error, for instance, could easily be handled by the application. Note,
however, that this error code is JDBC-vendor specific.

Team-Fly
Team-Fly

O dds A nd E nds
Java is an interpreted language, and the SQL statements executed with the S ta te m e n t class's e x e cu te Q u e ry and
e x e cu te U p d a te methods are interpreted by SQL. This doubling up of interpreted processing can become slow, so whenever
you find yourself coding a loop around an e x e cu te Q u e ry or e x e cu te U p d a te statement, you need to replace the use of the
S ta te m e n t class with the P re p a re d S ta te m e n t class. To do this, create the P re p a re d S ta te m e n t object before you enter
the loop. The JDBC process then does a "precompile" of the SQL statement so that, during the loop, performance is greatly
enhanced.

Obviously, you are not going to iteratively call the same SQL statement. Each call to that statement would change perhaps a
field value in the WHERE clause or the value of a field being set with an UPDATE statement. To handle slight variation in SQL
statements, the P re p a re d S ta te m e n t class has what are known as parameter markers. These parameter markers are simply
question marks, and, at runtime, during the loop, the parameter markers are replaced with values specified with setter
methods. (For more on using the P re p a re d S ta te m e n t class, see Chapter 12, "Prepare Your JDBC Applications for
Performance.")

One other extension to the JDBC S ta te m e n t class is the C a lla b le S ta te m e n t. The C a lla b le S ta te m e n t allows you to call
SQL stored procedures. On the AS/400, SQL stored procedures can be any AS/400 program object, including legacy RPG
programs. Therefore, the C a lla b le S ta te m e n t class allows you to easily integrate your legacy AS/400 applications with your
Java applications. To specify the required parameters for those stored procedures, again, you'll be using parameter markers.
(For more on using the C a lla b le S ta te m e n t class, see Chapter 25, "Invoking RPG via JDBC.")

Remember that Java and SQL are both powerful cross-platform languages, but also realize that by developing applications
using Java and JDBC, not only will your applications be cross-platform, so will you.

Team-Fly
Team-Fly

C h ap ter 11: G ettin g T o K n o w JD B C


O v e rv ie w
TED HOLT

JDBC lets Java programs access relational databases through a standard SQL interface. Just like Java, JDBC is supported by
most platforms, including the AS/400. This chapter shows you how to use JDBC to access DB2 for OS/400 data and
metadata from a PC. JDBC is simple to use and provides an easy way to access AS/400 data from PC programs.

Java excites and scares me at the same time. The excitement comes from developing programs that run on any machine.
The scary part is looking through all the $50, 800-page Java tomes at my local bookstore. I am finding out, however, that Java
is not as difficult as it looks. The topic of this chapter, Java Database Connectivity, is a good example. I sat down to
understand JDBC and found out it was very easy to use, especially since I had some good examples to follow. I hope this
chapter will encourage you to dig into JDBC. If I can do it, so can you.

Team-Fly
Team-Fly

W h y JD B C ?
To understand the purpose of JDBC, you must first understand the purpose of SQL. IBM developed SQL ages ago as part of
the System/R project, the experiment to design an RDBMS. The original name was SEQUEL, which stood for Structured
English Query Language. The name was later shortened to SQL, which is pronounced either "sequel" or "S-Q-L."

SQL was designed to define, manipulate, and retrieve data. Many of us programmers use it primarily or exclusively as an ad
hoc query tool, but it was intended to be a standard way for high-level language (HLL) programs to interact with a relational
database. JDBC is one way Java programs use SQL to communicate with a database. I'm told other methods are in the
works.

Team-Fly
Team-Fly

C o m p o n e n ts O f JD B C
JDBC has four components: Driver Manager, Connection, Statement, and Result Set. I wrote a short example program,
JD B C E x a m p le 01.ja va (shown in Figure 11.1), to illustrate how to use them. Please refer to Figure 11.1 as I explain the use
of these four JDBC components to retrieve and present records from a sample AS/400 database file.

F ig u re 11.1: Java applications that use JDBC for data access are not tightly coupled to the AS/400 .

A Java program that uses JDBC must load the Driver Manager object, D rive rM a n a g e rr, before it can communicate with a
database. At Label A of Figure 11.1, I load the AS/400 JDBC driver, found in the AS/400 Toolbox for Java. If I were connecting
to some other database management system (DBMS), I'd load some other driver instead. If I were going to connect to more
databases in the same program, I would load those drivers as well.

If you look at programs written for JDBC on other platforms, you might see the C la ss.fo rN a m e method used instead of the
D rive rM a n a g e r.re g iste rD rive r method. (I will be using the term method throughout this chapter. A method is simply the
object-oriented term for a function that is an explicit part of an object.) Once the driver manager is loaded, I can establish a
connection, as in Label B. The D rive rM a n a g e r uses the g e tC o n n e ctio n method to establish a connection to a database.
The various versions of the g e tC o n n e ctio n method of the D rive rM a n a g e r object accept different parameter lists, but the first
parameter is always a URL, a unique identifier for the database. You can also optionally specify a default library by adding a
qualifier just after the IP:
DriverManager.getConnection ("jdbc:as400://111.222.333.50/QGPL");

The URL consists of three parts: protocol, subprotocol, and data source name. For JDBC, the protocol is always jd b cc. The
subprotocol for DB2/400 is a s400
s400. (Contrast this with the World Wide Web, where the protocol is h ttp and there is no
subprotocol.) The data source I use in the example is the IP address 123.123.123.123, but, of course, that is not the real
address I used when I ran this program. You'll have to fill in the appropriate value in your JDBC programs.

I chose to add two more STRING parameters—a user ID and password—after the URL. I represent them here with the values
MYUSERID and MYPWD. If I had omitted these parameters, I would have been prompted for them every time the program
ran.

Now that the driver manager has established a connection, I'm ready to start sending SQL statements to the database. The
C o n n e ctio n object creates one or more SQL statements. I could have chosen from three statement classes: S ta te m e n t,
P re p a re d S ta te m e n t, and C a lla b le S ta te m e n t. The S ta te m e n t object is good for ad hoc querying. The
P re p a re d S ta te m e n t class is better in situations in which an SQL statement is executed over and over. Prepared statements
are precompiled, so that the entire SQL statement does not have to be translated into a usable form each time it is executed.
C a lla b le S ta te m e n t objects are used to execute stored procedures on the server.

In this program, the statement is executed only one time, so I chose to use a S ta te m e n t object. You can see it at Label C.
Once the S ta te m e n t object is created, I can run SQL commands, as shown at Label D. I build a simple SQL SELECT
command in variable S Q L S tm t, then run the C o n n e ctio n object's e x e cu te Q u e ry method to query the database. The DBMS
returns a result set, a group of zero or more rows (records), which satisfies the query.
Now my Java program has to read these rows, one at a time (see Label E). It uses the R e su ltS e t object's n e x t( ) method,
which is something like FETCH in AS/400 HLL programs that use embedded SQL. The n e x t( ) method moves from row to row
the same way that an RPG or COBOL READ works its way through a sequential file. The n e x t( ) method returns a Boolean
TRUE each time it finds another row in the result set, and it returns FALSE when all records in the set have been processed.
Unlike an HLL READ, n e x t( ) does not copy data into variables. Other RESULTSET methods, starting with the letters get, do
that. In this example, I've used g e tS trin g ( )), a method that returns a data value as a Java string. Some of the other g e t
methods of note are g e tD a te le, and g e tB ig D e cim a l. The g e tB ig D e cim a l method is especially important
te, g e tIn tt, g e tD o u b le
because it is used to retrieve the value of DB2/400 zoned and packed decimal fields. For my purpose, the g e tS trin g method
works fine because I am not doing any numerical calculations on the retrieved AS/400 data.

The g e tS trin g method needs one parameter—the number of the column to return—so g e tS trin g (1) references the data in the
first column of the current row. Since the SQL SELECT statement asked the DBMS for columns (fields) CUSNO and
CUSNM, g e tS trin g (1) refers to CUSNO (customer number), and g e tS trin g (2) refers to CUSNM (customer name). Inside the
WHILE loop (at Label E), the p rin tln method displays the customer number, tabs to the next tab stop, displays the customer
name, and moves to the next line.

All that's left to do is close everything down and end the program.

Team-Fly
Team-Fly

R u n n in g T h e P ro g ram
I compiled and ran this program in a DOS window on a Pentium running Windows 95. The compiler I used was the Java
Development Kit Version 1.1.3. The AS/400 was MC's RISC machine, to which I connected through the Internet. Here's what I
had to do to make this run: First, I had to compile the program. To do so, I created a directory called jt4 0 0 on the Pentium's
hard disk and installed the file jt4 0 0 .ja rr, from the AS/400 Toolbox for Java, into it. To make the program find this JAR file, I set
the CLASSPATH environment variable to point to the JAR file:
C:\> SET CLASSPATH=.;C:\jt400\jt400.jar

To compile, I ran this command from a command line:


C:\> javac JDBCExample01.java

To run the program, I dialed up my ISP and connected to the Internet. Then, I typed this command:
C:\> java JDBCExample01

Figure 11.2 shows what I saw on the monitor of my PC. As I requested, DB2/400 sent the customer records to my Java
program in name sequence, and the Java program dumped them to the screen.

F ig u re 11.2: Relational data is available to your Java applications via JDBC.

Team-Fly
Team-Fly

M e tad ata
If the only thing JDBC could do is retrieve data from servers, it would be useful. But JDBC has another powerful capability.
JDBC can retrieve data about data, or metadata, as it's called. The C o n n e ctio n and R e su ltS e t classes both have
g e tM e ta D a ta methods.

Program JD B C E x a m p le 02.ja va (Figure 11.3) illustrates how these methods work. To help you understand the metadata
methods, the output of the program is included in Figure 11.4.

F ig u re 11.3: Both the JDBC Connection and ResultSet objects contain metadata .

At Label A of Figure 11.3, the C o n n e ctio n class's g e tM e ta D a ta builds an object of type D a ta b a se M e ta D a ta


ta. This object
contains information about general things such as the URL to which the program is connected, the driver, and the DBMS.

The rsm e ta object, at Label B, uses the g e tM e ta D a ta method to retrieve information about the columns (fields). This object
can determine how many columns are in the result set and the characteristics of each one. I've made this program tell the
name, data type, and size of each column. If you want to see all of the methods available to you, run the following JAVAP
command:
C:\> javap java.sql.ResultSetMetaData

The ability to access metadata opens the door for all sorts of possibilities for query tools and flexible applications.
 

F ig u re 11.4: The metadata from the Connection and ResultSet objects can be used to dynamically set display attributes
such as column headers and entry lengths .

Team-Fly
Team-Fly

S o m e F in al P o in ts
I hope you're convinced that JDBC is not hard to use, even if you don't fully understand all the things I've shown you. Keep
working with it, and I'm sure it will eventually make sense.

Now, let me add a few points. First, these programs are portable to other clients. Ideally, I should be able to port these class
files to other types of machines, and they should run against the same server. Second, these programs are portable to other
servers. If I had a CUSTMAS table of the identical description defined in an Oracle database on a UNIX machine, I would have
to change only the re g iste rD rive r statement. Third, you don't have to use two machines to run JDBC. You can compile and
run a Java program on an AS/400 and access that same AS/400's database through JDBC. Finally, JDBC is slow (relatively
speaking). It may not always provide an acceptable response time. You may find you need to use other methods, such as
record-level access, in some situations.

Team-Fly
Team-Fly

C h ap ter 12: P rep are Y o u r JD B C A p p licatio n s F o r P erfo rm an ce


O v e rv ie w
DON DENONCOURT

The use of SQL statements for DB2 for OS/400 database access is easy with JDBC. In Chapter 10, "JDBC Basics," I
explained how the JDBC S ta te m e n t class allows you to read, write, update, and delete records. The S ta te m e n t class
seems to support everything. What more could you possibly need? Well, there's a problem with the S ta te m e n t class. When
you use an SQL statement repetitively, such as in a loop, the S ta te m e n t class doesn't perform well. For iterative operations,
your Java code should use the JDBC P re p a re d S ta te m e n t class.

Team-Fly
Team-Fly

P se u d o co m p ile s
Consider a Java GUI application that uses an SQL SELECT statement in a loop to read DB2/400 records associated with a
customer number that was, for instance, entered by a user on a GUI panel. The JDBC code for the SQL statement might look
like the following:
stmt.executeQuery ("SELECT * FROM qiws.qcustcdt WHERE custnum = " +
guiCusNumInput.getText());

But you need to realize that every time a S ta te m e n t object's SQL statement is executed, Java's runtime environment must
do what I call a pseudocompile to verify the validity of the SQL statement. That pseudocompile operation takes time. For a
GUI application, the time may not be an issue, but for batch processing and certainly for host-based server processing (e.g.,
with a servlet), that pseudocompile time becomes a real issue.

The whole idea behind the JDBC P re p a re d S ta te m e n t is to do the pseudocompile once, before the SQL statement
(contained within the P re p a re d S ta te m e n t object) is iteratively invoked. P re p a re d S ta te m e n t objects are so easy to use that
there is no reason not to use them. The example Java application shown in Figure 12.1 creates a P re p a re d S ta te m e n t object
in its constructor, just after the JDBC driver is registered and the C o n n e ctio n object is instanced. That's a good place for a
P re p a re d S ta te m e n t—in the constructor—because the P re p a re d S ta te m e n t is built once and may then be used iteratively
by the other methods of the class. Notice how the SQL SELECT statement passed to the p re p a re S ta te m e n t method of the
C o n n e ctio n class looks much as it would in a S ta te m e n t object's e x e cu te Q u e ry method except for the question mark (?):

F ig u re 12.1: The main method of this example iteratively invokes the getCustomer method, which uses the
PreparedStatement object that was created in the application's constructor .

PreparedStatement stmt = con.prepareStatement(


"SELECT * QIWS.QCUSTCDT WHERE CUSNUM = ?);

When the p re p a re S ta te m e n t method executes, it does the pseudocompile on the SQL statement and returns the
P re p a re d S ta te m e n t object. Note that any SQL statement can be used in a P re p a re d S ta te m e n t object. To execute the
prepared statement, you invoke the P re p a re d S ta te m e n t object's e x e cu te Q u e ry method for SQL SELECT statements and
e x e cu te U p d a te for INSERT, UPDATE, and DELETE statements.

Team-Fly
Team-Fly

A P lace F o r E v e ry th in g , E v e ry th in g In Its P lace


Before you can invoke the e x e cu te methods, you have to tell the P re p a re d S ta te m e n t object what the runtime values are for
the variable portions of the statement. The question mark shown in the SELECT statement is known as a placeholder. The
placeholders identify parameters that are set before each invocation of the SQL statement. To set those parameters, you use
one of the setter methods of the P re p a re d S ta te m e n t class, as shown in Figure 12.2.

F ig u re 12.2: The setter methods of the PreparedStatement class are used to set the values of SQL statement
parameters.

In my example JDBC application, the placeholder is looking for the value of a customer number. The
JD B C P re p a re d S ta te m e n t class shown in Figure 12.1 has a method called g e tC u sto m e r that returns the C u sto m e r class
(an inner class that is defined just before the JD B C P re p a re d S ta te m e n t constructor) that has the customer's name, city,
state, ZIP code, and balance. After creating local R e su ltS e t and C u sto m e r object variables, the g e tC u sto m e r method sets
the placeholder value of the P re p a re d S ta te m e n t with the se tIn t method. Note the commented code that follows the se tIn t
method. You can use whatever setter method you want—the P re p a re d S ta te m e n t just turns it into a string anyway—so you
simply use the method that works best with the object class you have at hand. I had an integer, so se tIn t makes more sense
than se tB ig D e cim a l or even se tS trin g .

After my SQL parameter is set in the g e tC u sto m e r method, the code runs the P re p a re d S ta te m e n t object's e x e cu te Q u e ry
method and then stuffs the values from the first element of the result set into a n e w C u sto m e r object. (Note that my WHERE
clause uses a unique key, so only one customer record will be in the result set.)

I coded a m a in method in my JD B C P re p a re d S ta te m e n t class to test the code. It simply uses a FOR loop to list all the
customers that have a customer number between 1 and 10 (the results of which are shown in Figure 12.3). The point is that
each invocation of the g e tC u sto m e r method does not require pseudocompiles. Because P re p a re d S ta te m e n t is so easy to
use, there is no excuse for iteratively using S ta te m e n t objects.

F ig u re 12.3: The JDBCPreparedStatement class's main method lists all customers that have key values between 1 and
10.

Team-Fly
Team-Fly

B e P re p are d
Anytime an SQL statement is to be used iteratively, for better performance, it should be used in a P re p a re d S ta te m e n t
rather than the simple S ta te m e n t object. The only additional complexity to using the P re p a re d S ta te m e n t is using those
simple question mark parameter placeholders and then using setter methods to affix runtime values to placeholder
parameters. The SQL statement does not even have to be in a loop to be considered for P re p a re d S ta te m e n t; methods that
are called iteratively and that contain SQL statements should use P re p a re d S ta te m e n t objects that were created in the
class's constructor. My suggestion is to make P re p a re d S ta te m e n t your default JDBC class and use the S ta te m e n t class
only when it is truly warranted.

Team-Fly
Team-Fly

C h ap ter 13: U sin g C o m m itm en t C o n tro l W ith JD B C


O v e rv ie w
DON DENONCOURT

The Java programming language's de facto standard facility for accessing information from relational databases is JDBC. For
relational data that resides in DB2 for OS/400, the record-level access classes of IBM's AS/400 Toolbox for Java are an
alternative facility. The dynamic access capabilities of record-level access show a performance advantage over the set-based
access of JDBC's SQL implementation. The reality, however, is that most Java applications under development today use
JDBC. Why? Well, many Java developers are not familiar with dynamic record access. Also, many CIOs want their Java
applications to work on all the platforms that have a Java Virtual Machine (JVM) and a relational database. All arguments
about which access method is superior aside, we AS/400 experts are just going to have to deal with JDBC.

Learning and using JDBC is not too tough, though. However, once you get past learning the simple techniques required to
maintain DB2/400 with JDBC, you run into a little snafu when you begin to write a real Java application that deals with real
data. Business applications have multiple and related database files. A single business transaction normally affects multiple
files. While the application program processes that business transaction, it has to ensure that no update anomalies occur,
such as other user jobs updating the same record or communications failures (especially now with unreliable TCP/IP
connections and n-tier applications). With the good old RPG and COBOL programs, programmers could count on the
automatic record locking when a record was read for update; this is not so with JDBC. Database reads are done in JDBC with
SQL SELECT statements, and the default behavior of the SELECT statement does not lock records.

What good is JDBC then? Don't discount JDBC so quickly. JDBC has a relatively easy mechanism for controlling update
anomalies. I'm going to show you how to code a JDBC business application that ensures database integrity, but first I want to
categorize these update anomalies into three types: dirty reads, nonrepeatable reads, and phantom reads. A dirty read
occurs when a record that was read by one client is modified by another client but not yet committed. A nonrepeatable read
takes place when one client reads a record a second time but another client has changed that record since it was first read.
A phantom read occurs when a client rereads a group of records based on a selection criterion and another client has
subsequently added a record that now fits the selection predicate.

Team-Fly
Team-Fly

T ran sactio n B o u n d ary


Imagine that you have a simple application that deals with two related files: an invoice file and an invoice-detail file. If you add
an invoice and then add a dozen detail records for that invoice, for example, this would be a single business transaction. If the
TCP/IP connection drops in the middle of the transaction, you have an update anomaly. JDBC (well, not just JDBC but SQL,
the language that JDBC interfaces with) has a concept known as a transaction boundary to remedy this anomaly. The
addition of one invoice and its 12 detail records would constitute a single transaction boundary. So, by using the transaction
management facilities of JDBC (which, by the way, are the same as SQL's), you can be sure that either all or none of the
database updates occur.

Team-Fly
Team-Fly

A n Iso late d E x am p le
I've created a small JDBC example application (Figure 13.1) that provides a tutorial for transaction control. The first step to
using JDBC's transaction control mechanism is to select an isolation level for your application. You specify an isolation level
to qualify the type of record locking that your application requires. The isolation levels shown in Table 13.1 are constant (static
and final) attributes of the C o n n e ctio n class.

F ig u re 13.1: The JDBCTransactions class is an example application that shows how to use commitment control to
ensure database integrity .

At Label A of the JD B C T ra n sa ctio n s class shown in Figure 13.1, the se tT ra n sa ctio n Iso la tio n method of the C o n n e ctio n
class is used to disable record locking completely. The se tA u to C o m m it method is also used to tell SQL to go ahead and
commit INSERT, UPDATE, and DELETE operations immediately following the execution of an SQL statement. The
transaction control state set by the invocation of these two methods is the default setting for JDBC: automatically commit
modifications and don't use transaction boundaries. Therefore, these two method calls are unnecessary. I just wanted to show
their use. The sta rtC o m m itm e n tC o n tro l method uses these same two methods after the b u ild F ile s method, at Label B,
completes. Commitment control cannot be enabled when creating a database file.

T a b le 13.1: Iso la tio n L e ve ls o f JD B C

TRANSACTION_READ_UNCOMMITTED Data changes immediately available, even without commit;


loosest isolation level.
TRANSACTION_SERIALIZABLE Locks data until commit; tightest isolation level.
TRANSACTION_READ_COMMITTED Prevents dirty reads but allows nonrepeatable and
phantom reads.
TRANSACTION_REPEATABLE_READ Prevents dirty and nonrepeatable reads but allows
phantom reads.
TRANSACTION_NONE Transactions not supported.

For your convenience, the b u ild F ile s method of the JD B C T ra n sa ctio n s class creates the invoice and invoice-detail files
(tables in SQL parlance) and sets up OS/400 journaling. (Files must be journaled to use SQL transaction management.) The
d ro p T a b le s method is used to wipe out existing files (so you can iteratively test the application). The b u ild F ile s method
uses the cre a te T a b le method to create the two files with SQL statements, as shown in Figure 13.2.

F ig u re 13.2: The invoice and invoice-detail files can be built with two simple SQL CREATE TABLE
statements.

The b u ild F ile s method then creates a journal and a journal receiver and starts journaling the two files by invoking the OS/400
commands shown in Figure 13.3.

F ig u re 13.3: To be able to use commitment control with JDBC, the files must be journaled.

The code for these methods is omitted from Figure 13.1, but it is available on the CD included with this book. Note, however,
that when an AS/400 library is specified as an SQL collection, then anytime a table (file) is created in that collection (library),
it is automatically under commitment control, complete with a journal and a journal receiver.

Team-Fly
Team-Fly

T h e T ran sactio n
Typically, your application database files will already exist with journaling started, so, finally, with all that setup work done,
my example application at Label C gets rolling. There I call my sta rtC o m m itm e n tC o n tro l method, and, if you look at Label
F, that's where I turn off SQL's A u to C o m m it and set the transaction isolation to SQL's tightest locking level:
TRANSACTION_SERIALIZABLE. You might want to use a similar method in your own applications along with a partner
method called e n d C o m m itm e n tC o n tro l. The e n d C o m m itm e n tC o n tro l can then be used to allow automatic database
commits with no locking so that you can update files that don't require journaling, such as logs. The JD B C T ra n sa ctio n s
class at Label D then adds an invoice record and two invoice details. This seems trivial, but in a real application, the addition
of these records would be handled with the collaboration of several Java classes.

At this point, just before the code at Label E rolls back the insertions, I added a breakpoint to test the JD B C T ra n sa ctio n s
class. I then popped over to a 5250 session and used SQL/400 to look at the added records. They were there, but once I tried
to modify one of the inserted records with the following SQL UPDATE, I ran into a little problem:
UPDATE denoncourt/invoice SET cust = 'Amay' WHERE invno = 101

OS/400's transaction management prevented my attempt to modify that particular record because my JD B C T ra n sa ctio n s
application had a lock on it. My SQL/400 session presented me with the error message "Row or object INVOICE in
DENONCOURT type *FILE in use." Note, however, that updates to records not locked by other applications work, and any
INSERT operations are also fine. I was also unsuccessful at my attempt to clear or delete the files with the Clear Physical
File Member (CLRPFM) or Delete File (DLTF) commands.

Team-Fly
Team-Fly

T ran sactio n al In te g rity


Yep, those three records were there, but after I continued the execution of the JD B C T ra n sa ctio n s application and the
C o n n e ctio n object's ro llb a ck method was called at Label E, those records were nowhere to be found. My transaction had
completed when my application saw fit to back out of the database updates with the ro llb a ck method. A transaction
boundary is completed when either the co m m it or ro llb a ck method is invoked. Your application should have calls to the
ro llb a ck method to handle error conditions. SQL, by the way, also automatically rolls back transactions if the application
ends abnormally (e.g., a communications disconnect). Hopefully, however, everything proceeds according to plan and your
application calls the co m m it method to release the record locks and solidify database modifications.

Team-Fly
Team-Fly

C o m m ittin g T o JD B C
It's hard for most of us AS/400 RPG and COBOL veterans to give up our dynamic record access. Many of us have
enthusiastically jumped into learning this new Java language, but when it comes to giving up record-level access for the set-
based processing of SQL, we balk. But for many Java applications, JDBC, good or bad, is the access mechanism we have to
use. To continue developing the same quality business applications with Java and JDBC that have been developed for years
using RPG, SQL transactions and commitment control must be used. If you are still considering using record-level access
instead of JDBC for your database access, read Chapter 5, "Commitment Control for Record-level Access."

Team-Fly
Team-Fly

C h ap ter 14: A F ew JD B C T ip s A n d T ech n iq u es


O v e rv ie w
DON DENONCOURT

To be able to access data from a relational database using JDBC, you need a JDBC driver. The AS/400 ships with not one but
two JDBC drivers. To understand why the AS/400 ships with two drivers, you need to understand a little bit about JDBC driver
types. There are four types of JDBC drivers. The first type is known as a Pure Java driver. The name Pure Java is trademarked
because it is Sun Microsystems' seal of cross-platform Java compliancy; in other words, a Pure Java JDBC driver will work on
any platform. The AS/400's Pure Java driver is in the AS/400 Toolbox for Java (JT400) program product's JAR file called
jt4 0 0 .ja rr. That file can be copied to your Windows 98 machine (or your Linux workstation, or your S/390, or whatever). The
JDBC driver contained in jt4 0 0 .ja r will give you TCP/IP Java access to DB2 for OS/400.

The next JDBC driver is known as a native driver. Native means that the JDBC driver is optimized for the platform and,
therefore, cannot be copied and used on other platforms.

The third type of JDBC driver allows you to plug in an ODBC driver to your JDBC driver. Sun's Java Development Kit (JDK)
ships with one of these JDBC drivers. These drivers are helpful because if you can't find a JDBC driver for some obscure
database but you do have an ODBC driver, then you'll still have JDBC access—albeit, indirectly.

The last kind of JDBC driver is one that allows you to access nonrelational databases. For instance, there are JDBC drivers
for Lotus Notes, which keeps its data in an object-oriented fashion rather than relationally.

Team-Fly
Team-Fly

JD B C D riv e r O n e
OS/400 ships with a Pure Java driver and a native driver. To access your AS/400's database with the Pure Java driver in the
JT400's JAR file called jt4 0 0 .ja rr, you need to add that JAR to your CLASSPATH and then qualify the driver with the following
clause in the cla ss.fo rN a m e method:
com.ibm.as400.access.AS400JDBCDriver

This JDBC driver is 100% Pure Java, which means that it will execute on all platforms with a Java Virtual Machine (JVM).
Again, note that this is the JDBC driver that is bundled with IBM's JT400. The JT400 is a separate Licensed Program Product
(LPP), 5769JC1, but it comes free with OS/400. The JDBC C o n n e ctio n class requires the following URL parameter:
jdbc:as400://<system_name>/<library_name>.

The protocol is jd b cc, and the subprotocol is a s400


s400. For the driver to function properly, you must add full qualification for the
jt4 0 0 .ja r file to your CLASSPATH. If you are executing your Java application from the AS/400, you can set the Java
CLASSPATH with the Add Environment Variable (ADDENVVAR) command. (Be sure that CLASSPATH is uppercase.)
ADDENVVAR ENVVAR(CLASSPATH)
VALUE('/qibm/ProdData/HTTP/Public/jt400/lib/jt400.jar')

Team-Fly
Team-Fly

JD B C D riv e r T w o
OS/400's native driver is qualified with the following clause in the cla ss.fo rN a m e method:
com.ibm.db2.jdbc.app.DB2Driver

Your JDBC application must execute on the AS/400. The native driver was optimized for the AS/400, so it runs faster than the
100% Pure Java driver that is included in IBM's AS/400 Toolbox for Java (com.ibm.as400.access. AS400JDBCDriver). The
DB2 JDBC driver is part of LPP 5769JV1, which is a chargeable program product. The JDBC C o n n e ctio n class requires the
URL parameter of:
jdbc:db2://<system_name>/<library_name>

where jd b c is the protocol and d b 2 is the subprotocol. The AS/400 JVM will be able to find the DB2 JDBC without an explicit
qualification in Java's CLASSPATH environment variable with JDK 1.1.8, but with JDK 1.2 or higher you need to appropriately
set your CLASSPATH. The classes are in the following:
/QIBM/ProdData/Java400/ext/db2_classes.jar

The easiest way to add that to your CLASSPATH is to use the following Add Link (ADDLNK) command:
ADDLNK OBJ('/QIBM/ProdData/Java400/ext/db2_classes.jar') +
NEWLNK('/QIBM/UserData/Java400/ext/db2_classes.jar')

Team-Fly
Team-Fly

A L ib rary L ist F o r JD B C
AS/400 programmers love library lists. After all, they are a great way to test multiple versions of the same application. Library
lists allow you to put the same set of database files but with different data into various libraries, so it's nice to know that your
AS/400 JDBC drivers support library lists. Without a library list, you have to explicitly qualify your file names in your SQL
statements:
stmt.executeUpdate(
"INSERT INTO DENONCOURT.invoice " +
" (invno, cust) " +
" VALUES(101, 'Acme')");

Fully qualifying files in AS/400 applications may not be reason for dismissal, but it certainly is provocation for ridicule. You
simply shouldn't qualify files. To specify a library list for your JDBC application, you append the lib ra rie s JDBC property in
the first parameter of the g e tC o n n e ctio n method (following the protocol, subprotocol, domain, and a semicolon [;]). In the
following example, I specify a comma-delimited library list to contain my user library and the QGPL library:
DriverManager.registerDriver(
new com.ibm.as400.accessAS400JDBCDriver());
Connection con = DriverManager.getConnection (
"jdbc:as400://your400Domain;libraries=DENONCOURT,QGPL",
"profile", "pass");

Optionally, if you want to use the job's library list, you can specify *LIBL. With the library list specified, I can now execute my
INSERT operation without explicit library qualification:
stmt.executeUpdate(
"INSERT INTO invoice " +
" (invno, cust) " +
" VALUES(101, 'Acme')");

Note that the library list associated with the C o n n e ctio n object is also used to resolve stored procedure calls.

You can also qualify the default library in the connect method call. The following makes DENONCOURT the default library:
Connection con = DriverManager.getConnection (
"jdbc:as400://MY400/DENONCOURT", "profile", "pass");

Team-Fly
Team-Fly

R e co rd B u ffe rin g
All JDBC drivers have some form of record-blocking data retrieval. With the JT400's JDBC, the default blocking buffer size is
32 KB. To modify the default block size, add property entries to parameters sent to your call to the D rive r M a n a g e r object's
g e tC o n n e ctio n method. The properties section is added just after the URL and a semicolon separator:
Connection con = DriverManager.getConnection (
"jdbc:as400://your400;block criteria=2,prefetch=true,block
size=512" , username, password);

The properties that you should be most interested in are b lo ck crite ria , p re fe tch
tch, and b lo ck size . To set the values for
JDBC properties, specify the property name, an equal sign (=), and the value you wish to assign. The b lo ck crite ria property
can be set to 0 for no record blocking (which I don't think you want), 1 to block only when FOR FETCH ONLY is specified in
the SELECT statement, and 2 to block unless FOR UPDATE is specified.The p re fe tch Boolean property specifies whether to
prefetch data upon executing a SELECT statement. And, finally, the b lo ck size property allows you to specify the block size
(in kilobytes) to retrieve from the AS/400 server and cache on the client. The b lo ck size property has no effect unless the
b lo ck crite ria property is set to 1 or 2. The b lo ck crite ria property value can be set to 8, 16, 32, 64, 128, 256, or 512, with
the default, again, being 32.

Team-Fly
Team-Fly

S ectio n IV : Java G u i P ro g ram m in g


C h ap te r L ist
Chapter 15: Java Foundation Classes Basics

Chapter 16: JFC Development With Templates

Chapter 17: Chrome-Plate Your Java Gui With Dynamic Menus And A Status Bar

Chapter 18: Just Browsing With JDBC

Chapter 19: Cheap Java Subfile Programming Tricks

Chapter 20: Gui Builder Makes Java Gui Development Easy

P art O v e rv ie w
When Java first came out, the standard user interface was a GUI. Java coders initially used the Abstract Window Toolkit
(AWT) package of classes for GUI programming. But AWT's look and feel sometimes left a little to be desired. AWT also
lacked some window components that are very important for business applications: tables, trees, and tabbed dialogs. One of
the major enhancements to Java 1.2 (a.k.a. Java 2) was the addition of the Java Foundation Classes (JFC) package. The JFC
package provides the required table, tree, and tabbed dialog classes and greatly improves the user interface.

This section includes no chapters on AWT, preferring to focus on JFC instead. The first chapter, "Java Foundation Classes
Basics," provides a fast-paced introduction to JFC with template-style examples so that you can quickly get started with your
own JFC code. "JFC Development with Templates" expands on the first JFC chapter with more template examples: frame with
a list, tabbed dialog, and frame with a menu. The chapter finishes with a tutorial on how to add tool tips (to assist users who
are new to your GUI) and accelerator keys (for your power users to reduce the need for the mouse).

In "Chrome-Plate Your Java GUI with Dynamic Menus and a Status Bar," Alex Garrison tells you how to make professional-
looking GUIs with the proper use of menus and the addition of status bars.

As I mentioned, one of JFC's biggest enhancements over AWT was the inclusion of a table component. JFC's table
component is the replacement paradigm for OS/400 subfiles. Jeff Markham explains how to use JFC tables in "Just Browsing
with JDBC."

The AS/400 Toolbox for Java contains a class that allows you to create a "subfile" (JFC table) with one Java statement. The
problem with this class, however, is that the table is read-only. But in "Cheap Java Subfile Programming Tricks," I provide a
simple technique that will allow you to use the toolbox class for an updateable table.

Because of the learning curve associated with GUI event-driven programming, IBM came up with a brilliant strategy to simplify
the whole GUI development process. Midrange Computing's Shannon O'Donnell, in "GUI Builder Makes Java GUI
Development Easy," describes how to use IBM's PDML. Note that PDML is not OS/400-specific. In fact, IBM has requested
that Sun make PDML a standard Java extension. So, if you want to bypass the complexity of Java GUI development, check
out Shannon's chapter.

Team-Fly
Team-Fly

C h ap ter 15: Java F o u n d atio n C lasses B asics


O v e rv ie w
DON DENONCOURT

When Java 1.0 was first introduced, Sun Microsystems' intended strategy for programming GUIs was to use its Abstract
Window Toolkit (AWT) package. The AWT classes, however, had some limitations. For one, they lacked a few components
that are considered standard for industrial-strength GUIs (specifically, trees, tables, and tabbed dialogs). Second, AWT had
no direct support for advanced features such as tool tips and keyboard mnemonics. Third, to get the first version of Java out
the door quickly, Sun developed the AWT window components as a thin veneer covering the native windowing components of
the various platform-specific implementations of a Java Virtual Machine (JVM). The result of AWT's reliance on the native
components was a set of components that had a different look and feel on various platforms.

A number of third-party vendors scrambled to fill the market hole left open by Sun, including Microsoft, which created the
Windows Foundation Classes (WFC) package of Java GUI components. But Sun soon came out with a new package of GUI
components called the Java Foundation Classes (JFC). This package was initially distributed as a widely successful beta
called Swing. Early adopters of Java were in such dire need of the advanced capabilities of the JFC package that they
deployed commercial products using the Swing beta. The Swing name stuck: The JFC package in Java 2 is called
ja va x .sw in gg. The names Swing and JFC are used interchangeably in most Java literature (although JFC, which is a standard
part of Java 2, includes things such as graphics and accessibility in addition to Swing), and I use them so here. (For
information on using the JFC components with Java 1.1, visit www.java400.net.)

The Swing package, with its JFC components, solved the problems inherent in the AWT components. Among Swing's many
new and advanced components are JT re ee, JT a b le
le, and JT a b b e d P a n ee. All the components of the Swing package also have
methods for assigning tool tips and keyboard mnemonics. Furthermore, the Swing components are known as lightweight
components because they don't carry the extra burden of a native component, as did their ancestor AWT heavyweight
classes.

The lightweight feature of Swing components makes the look and feel of JFC applications standard across all platforms.
Actually, the look and feel of a JFC application can be assigned. The default look and feel for an application is set to one that
is "cross-platform," so that it appears and behaves similarly on most platforms. However, you can specifically set your Java
GUI to the look and feel of Windows, Motif, or Macintosh (or a variety of others such as Heavy Metal or one made available by
a third-party vendor) with a call to the User Interface Manager.

Team-Fly
Team-Fly

JF C In tro
Extremely complex and sophisticated graphical applications have been developed with the components of the Swing
package. For instance, the KAWA integrated development environment for Java (see tek -tools.com/k awa/) was developed
(with 100% Pure Java) by taking full advantage of the Swing components. Even sophisticated games with complex animation
have been developed with Java and Swing. Although entire books have been written on how to use JFC, you need to know
only a few basics to develop business applications with Swing.

Table 15.1 shows the standard JFC components that you can use to develop many of your applications. Note that your AWT
knowledge will be leveraged when you are developing JFC applications. Java is an object-oriented language. When the
developers at Sun decided to create advanced GUI components, they built them on top of the base AWT component
ja va .a w t.co n ta in e rr. As a result, most of the JFC components that have a corresponding AWT component still have most of
the same attributes, methods, and events as their corresponding AWT ancestor (with a few exceptions, such as J L ist ist). As
your application design becomes more sophisticated, you might use some of the advanced JFC components. Table 15.2
shows a few of the more interesting ones.

T a b le 15.1: JF C to A W T C o m p o n e n t C o m p a riso n

JF C C o m p o n e n t A W T C om ponent D e scrip tio n


Japplet Applet A base class that is subclassed during the design of Web-
deployment Java applets.
Jframe Frame A top-level window that has a title, a border, and support for a
menu bar; often subclassed for the creation of a Java application.
Jlist List A list of selectable items.
Jpanel Panel Provides space in which an application can attach any other
component, including other panels.
JmenuBar MenuBar A bar, used for the placement of menus, which appears
immediately under a window frame.
Jmenu Menu A window that contains menu items.
JMenuItem MenuItem An option, similar in function to a button, that is added to a menu.
JPopupMenu PopupMenu A context-sensitive menu that appears with options that are
relative to the current cursor position.
JtextField TextField A single-line text input area.
JtextArea TextArea A multiline text area for displaying and editing text.
Jbutton Button A graphical push button that the user can click.
JCheckBox CheckBox A graphical component that is used to represent a Boolean value
such as true/false or yes/no.
JRadioButton RadioButton A group of mutually exclusive Boolean values, only one of which
can be true.
JScrollPane ScrollPane A window that automatically scrolls horizontally and vertically to
display information that otherwise could not be viewed with the
amount of available window space.

T a b le 15.2: JF C 's M o st In te re stin g C o m p o n e n ts

JF C C o m p o n e n t D e scrip tio n
JSlider A component that lets the user graphically select a value by sliding a knob within a
bounded interval.
JSplitPane A componentis used to divide two (and only two) components.
JTabbedPane A component that lets the user switch between a group of components by clicking on a
tab with a given title and/or icon.
JTable A user-interface component that presents data in a two-dimensional table format.
JTree A control that displays a set of hierarchical data as an outline.
Team-Fly
Team-Fly

M in im al JF C A p p licatio n
The biggest problem AS/400 RPG programmers have with developing a Java GUI application is simply getting started. I will
provide you with a tutorial on a minimal JFC application that consists of only an application frame. It is my intent that you use
the code from this application as a template for your own Java GUIs. As you can see in the application window shown in
Figure 15.1, my minimal application has no functional purpose because it has no components in its frame.

F ig u re 15.1: The JFrame component is a top-level application window that features a title and, optionally, a menu
bar.

The Java source for the class called F ra m e O n ly (shown in Figure 15.2) begins by importing two Java packages:
ja va x .sw in g and ja va .a w t.e ve n t. The need to import the ja va x .sw in g package is obvious: It contains the JFC
components. But you might be wondering why I've imported an AWT package. As I mentioned earlier, the classes of the
Swing package use the AWT 1.1 event model, and, as a result, the Swing window components often generate AWT events.
The F ra m e O n ly application had to import the AWT event package in order to handle the window-closing event (which it does
by properly shutting down the application when the user closes the window). The F ra m e O n ly class subclasses JFC's
JF ra m e class with the following syntax:

F ig u re 15.2: Most of your JFC GUI applications will use similar code to set up the window frame .

class FrameOnly extends JFrame

This style of designing a GUI application is typical of most JFC applications, because the JF ra m e (as its entry in Table 15.1
explains) is a top-level application window with a title. The F ra m e O n ly application "bootstraps" itself in its m a in method by
instantiating (creating) an object variable called g u i (of the F ra m e O n ly class). I call this process bootstrapping because the
F ra m e O n ly class's m a in method metaphorically picks itself up by its bootstraps to load the application. The g u i object
variable of the m a in method then invokes the se tV isib le method, passing to that method a tru e value that forces the window
frame to be displayed. This simple code of the F ra m e O n ly class's m a in method is all that the majority of your JFC
applications will ever need. Most of the work involved in setting up your application window is done in its constructor (a
constructor is a function that bears the same name as its class).

Team-Fly
Team-Fly

F ram e C o n stru ctio n


The F ra m e O n ly class's constructor method begins by setting the title and size of the window frame with calls to the se tT itle
and se tS ize methods. If this were an AWT application that extended AWT's F ra m e class, instead of JFC's Jfra m e class,
the AWT app could start adding components directly to the window frame. But the JF ra m e component has an odd behavior
that AWT's F ra m e component does not have: The JF ra m e component does not allow you to add components directly to the
JF ra m e object.

All JFC applications have a topmost panel. The F ra m e O n ly class, after setting its title and size, creates a JP a n e l object
called to p P a n e l and invokes a unique function called g e tC o n te n tP a n ee. The g e tC o n te n tP a n e method retrieves a JF ra m e
component (which the Sun designers call a root pane) and allows you to add a panel to that root component. To that topmost
panel, you add the other components of the application (this is why I always name my topmost panel to p P a n e l). Therefore,
the following two lines of code will always be in your JFC applications:
JPanel topPanel = new JPanel();
getContentPane().add(topPanel);

After the topmost panel is created and set, your application can then begin to add the components required for your
application GUI. My F ra m e O n ly application, however, does nothing more than set up the window frame. The only other thing
the F ra m e O n ly constructor function does is handle the window-closing event by exiting the application. It handles this event
easily with the following four lines of code:
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e)
{System.exit(0);}
});

This code uses a bit of Java magic called an inner class. I will not explain inner classes here because their design is
moderately complex. Suffice it to say that you should use this snippet of code to shut down your JFC applications properly. In
fact, I suggest that you use the F ra m e O n ly class as a template for all your JFC applications.

Team-Fly
Team-Fly

W in d o w D re ssin g
Now that you know how to build the frame for your applications, your next step is to flesh out your Java GUI by adding the
JFC components that provide the user interface for the window frame. A brief explanation of this process will suffice: You
select components from the list in Table 15.1, instantiate them, and add those objects to the topmost panel. For example, if
you want to add a label and a text field to the application, you insert the following lines in your JFC's application constructor
just after the code that creates the topmost panel:
JLabel prompt = new JLabel("Enter stuff here:");
topPanel.add(prompt);
JTextField entry = new JTextField(20);
topPanel.add(entry);

Figure 15.3 shows the resulting GUI prompt. Chapter 16, "JFC Development with Templates," provides several more examples
of simple extensions for this minimal application: F ra m e W ith M e n uu, which shows you how to add menus to your Java GUI,
create tool tips, and add keyboard mnemonics; F ra m e W ith L ist, which shows you how to use JFC's J list component; and
F ra m e W ith T a b b e d D ia lo gg, which shows how easy it is to implement tabbed dialogs.

F ig u re 15.3: JFC components are added to the topmost panel of your application's GUI.

Team-Fly
Team-Fly

B e A S w in g e r
Even though the Java Foundation Classes are powerful enough to support the most sophisticated GUI applications and the
slickest advanced game software, using JFC is still easy enough for Java neophytes to develop their own cool Java GUIs. So,
don't let the thickness of the books available on JFC scare you away from developing with it. To use JFC, you really need to
understand only a third or perhaps even a fourth of the content covered in those overbloated books. By following the standard
JFC template application shown in this chapter and then adding components as required for your own application, you can
easily craft your own GUI complete with menus, tool tips, and keyboard mnemonics. As you get more comfortable with Java
and JFC, you can add more advanced features such as trees, tables, pop-up menus, and tabbed dialogs.

Team-Fly
Team-Fly

C h ap ter 16: JF C D evelo p m en t W ith T em p lates


O v e rv ie w
DON DENONCOURT

Chapter 15, "Java Foundation Classes Basics," includes a tutorial on how to write a minimal Java GUI application using the
Java Foundation Classes (JFC). That GUI application serves no functional purpose because it has no components in its
frame. The example served as a template for programming GUIs with JFC. This chapter extends that tutorial by providing four
other JFC examples: a frame with a list, a frame with a tabbed dialog, a frame with a menu, and a frame with a menu that
adds tool tips and keyboard mnemonics.

Team-Fly
Team-Fly

M in im al JF C A p p licatio n O v e rv ie w
Chapter 15 provides a complete tutorial on the implementation for the JFC skeleton application shown in Figure 16.1, but I will
quickly overview the application. Figure 16.2 shows the source code for the F ra m e O n ly class. The code begins by importing
two Java packages: ja va x .sw in g and ja va .a w t.e ve n t. The class needs the Swing package for the JFC GUI components and
the Abstract Window Toolkit (AWT) package for the GUI that the JFC components generate. The F ra m e O n ly class
subclasses (extends) JFC's JF ra m e class, so the F ra m e O n ly class is a JF ra m ee.

F ig u re 16.1: The minimal JFC application extends JFrame, bootstraps the application in main, and sets a topmost panel
in its constructor.

F ig u re 16.2: A minimal JFC application has a window frame and code that handles the window-closing
event.

The F ra m e O n ly application's m a in method "bootstraps" itself by instantiating (creating) an object variable called g u i that
has the same class as the application—FF ra m e O n ly ly. The g u i object variable of the m a in method is then used to invoke the
se tV isib le method, passing to that method a tru e value that forces the window frame to be displayed. This simple code of the
F ra m e O n ly application's m a in method is all your JFC applications should ever need.

Most of the work involved in setting up your application window is done in its constructor. The F ra m e O n ly constructor
method sets the title and size of the window frame, creates a JP a n e l object called to p P a n e l, and adds that "topmost panel"
to the JF ra m e with a call to the g e tC o n te n tP a n e method. The F ra m e O n ly constructor then uses an inner class to handle
the window-closing event by exiting the application.

Team-Fly
Team-Fly

F ram e W ith A L ist


The F ra m e O n ly application is only a skeleton of an application; it has no GUI components in its frame. If you already know
how to use the AWT components, then adding basic JFC components such as labels, buttons, and text fields to the
F ra m e O n ly application is a fairly simple process. So, as an example of adding JFC components, I wanted to use a
component that was different from the AWT components. I chose J L ist because, even though AWT has a list box (LL ist ist), the
use of JFC's J L ist is different from the use of AWT's L ist
ist.

The code for the list box application is shown in Figure 16.3. Note that the F ra m e W ith L ist class has the same skeleton of
code that the F ra m e O n ly class has. The F ra m e W ith L ist class has a m a in method that bootstraps the application, and its
constructor has a topmost panel and inner class (to handle the window-closing event). The F ra m e W ith L ist class is designed
to present the simple to-do list application shown in Figure 16.4. At the top of the F ra m e W ith L ist application, you can see
that it declares four class-level object variables: a V e cto r called d a ta M o d e l, a JL ist called lis tt, a JT e x tF ie ld called te x tt,
and a JB u tto n called a d d Ite m . The elements of the d a ta M o d e l Vector are presented in the application's J L ist component.

F ig u re 16.3: To handle the events generated from the application's GUI components, the simplest JFC applications
extend ActionListener and implement the actionPerformed method .
F ig u re 16.4: JFC's JList list box component has a different behavior than its AWT predecessor, List.

V e cto r is a class that encapsulates access to what are essentially dynamically sizable arrays. The d a ta M o d e l object was
instantiated with the V e cto r class's default constructor (one that has no parameters):
dataModel = new Vector();

I then populated the d a ta M o d e l object with the V e cto r class's a d d E le m e n t method:


dataModel.addElement("one");
dataModel.addElement("two");
dataModel.addElement("three");
dataModel.addElement("four");

The next step was to associate the d a ta M o d e l Vector with the J L ist component:
list = new JList(dataModel);

JFC's J L ist component can be populated with elements from a Vector, an array, or an implementation of the L istM o d e l
interface. The use of the L istM o d e l interface with a J L ist is beyond the scope of this chapter, but the use of an array is
enabled with the following code:
String[] dataModel = {"one", "two", "three", "four"};
JList list = new JList(dataModel);

I prefer, however, to use a Vector because arrays are statically sized, which means you can't add an element to the J L ist
without building a new array. So, with the J L ist component constructed, the F ra m e W ith L ist application then adds it to the
application's topmost panel:
topPanel.add(list, BorderLayout.CENTER);

Notice the alignment qualification of CENTER. The topmost panel had been set to the B o rd e rL a yo u t layout manager with the
following code:
topPanel.setLayout(new BorderLayout());

To make the F ra m e W ith L ist application look a little more professional, you can put the J L ist component inside a
JS cro llP a n ee. That way, when the elements of the list exceed their viewable space, a scroll bar will automatically be inserted.
To use the scroll pane, replace the statement that adds the list with the following code:
topPanel.add(new JScrollPane(list), BorderLayout.CENTER);

Team-Fly
Team-Fly

M o re T o D o
What good is a list if you can't add to it? The F ra m e W ith L ist application has the to-do list input-enabled in a panel that is
placed at the southern border of the frame. The panel is created and has its layout manager set to F lo w L a yo u t with the
following code:
JPanel bottomPanel = new JPanel();
bottomPanel.setLayout(new FlowLayout());

F lo w L a yo u t is used so that the components—a JL a b e l for a prompt, a text field for input, and a button for the user to ask
the application to add the text value to the list—are automatically laid out, left to right, in the order that they are added to the
panel. The JL a b e l is created on the fly without the excess baggage of a variable name (because there is no need to reference
the JL a b e l component program- matically) as it is added to the bottom panel:
bottomPanel.add(new JLabel("New list element:"));

On the other hand, the text field and button components do need to be referenced programmatically, so they are created and
then added to the bottom panel in a two-step process:
text = new JTextField(20);
bottomPanel.add(text);
addItem = new JButton("Add");
bottomPanel.add(addItem);

To be able to handle the click event, the F ra m e W ith L ist application is associated with the button object, a d d Ite m , with the
following code:
addItem.addActionListener(this);

Finally, the bottom panel is added to the topmost panel to the southern border of the application's frame with the
B o rd e rL a yo u t alignment qualifier SOUTH:
topPanel.add(bottomPanel, BorderLayout.SOUTH);

Team-Fly
Team-Fly

L ist P ro ce ssin g
When a user clicks the Add button, the a ctio n P e rfo rm e d method of the F ra m e W ith L ist application is invoked (because it
was specified with the THIS qualifier in the a d d Ite m object's a d d A ctio n L iste n e r method). The a ctio n P e rfo rm e d method
begins by checking the source of the event:
if (e.getSource() == addItem) {

The condition doesn't seem necessary because there is only one component that generates events that the F ra m e W ith L ist
class must handle. However, the a ctio n P e rfo rm e d method of a "real" application typically handles the events from many
buttons. Anyway, the F ra m e W ith L ist class's a ctio n P e rfo rm e d method pulls the S trin g value out of the te x t object with the
g e tT e x t method of JT e x tF ie ld
ld:
String data = text.getText();

That string is then added to the d a ta M o d e l Vector with the V e cto r class's a d d E le m e n t method:
dataModel.addElement(data);

Then, after clearing the text field, the d a ta M o d e l Vector is reassociated with the list box:
list.setListData(dataModel);

That last step might seem odd, but the use of the se tL istD a ta method forces the list box to "redraw" itself so that the new list
element is viewable.

Team-Fly
Team-Fly

F ram e W ith A T ab b e d D ialo g


Tabbed dialogs are an advanced GUI component that can make your applications look more professional.

Adding tabbed dialogs to your JFC application is much easier than you might expect. Figure 16.5 shows each of the three
panels of the F ra m e W ith T a b b e d D ia lo g application, and Figure 16.6 shows the complete code for the
F ra m e W ith T a b b e d D ia lo g class, which, once again, is based on the code from the F ra m e O n ly class.

F ig u re 16.5: A JTabbedPane component is a container for one or more JPanels.

F ig u re 16.6: The FrameWithTabbedDialog application adds three JPanel objects to a JTabbedPane (part 1 of
2).

The F ra m e W ith T a b b e d D ia lo g adds three panels, aptly named one, two, and three. Panel one simply contains a JL a b e l;
panel two, a JB u tto n ; and panel three, a J list (which I quickly populated with an array, as shown in Figure 16.7).

F ig u re 16.7: The various panels of a tabbed dialog can each contain completely different components.

But it really doesn't matter what panels this sample application uses. The point is that tabbed dialogs can contain whatever
panels you want. The complexity of using tabbed dialogs is not in the use of the JT a b b e d P a n e component but in designing
the panels that are contained in the tabbed pane. The code snippet shown in Figure 16.8 shows just how easy it is to code
tabbed dialogs.
F ig u re 16.8: Panels are added to a tabbed dialog with the addTab method of the JTabbedPane class.

All that the code in Figure 16.8 does is create a JT a b b e d P a n e object and then add the JP a n e l objects to that tabbed pane
object with the JT a b b e d P a n e object's a d d T a b method. The a d d T a b method takes a title (to be used as the text for the tag)
and the name of the JP a n e l object variable. An overloaded a d d T a b method also accepts an icon to be placed as a graphical
identifier in the tab. After all the panels have been added to the tabbed pane, the tabbed pane itself is added to the center of
the application's topmost panel.

Team-Fly
Team-Fly

F ram e W ith A M e n u
Most applications have a menu, and, like tabbed dialogs, menus are also easy to code with JFC. Figure 16.9 shows my
simple example application that displays merely a window frame and a menu. Figure 16.10 shows the code for the
F ra m e W ith M e n u V 1 class (version 2 adds a few extra features).

F ig u re 16.9: Adding a menu to the window frame is a straightforward process.

F ig u re 16.10: The FrameWithMenuV1 class shows how easy it is to add a menu to a window frame .

F ra m e W ith M e n u V 11, as you may have already guessed, is also based on the F ra m e O n ly class. You need a spot to place
the menu, or, as it is called, a menu bar. JFC's JF ra m e component supports the addition of a JM e n u B a r component with its
se tJM e n u B a r method:
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);

The next step is to create a menu to hold menu selections, and that menu is then added to the menu bar:
JMenu fileMenu = new JMenu("File");
menuBar.add(fileMenu );

At this point, the menu has no selections, so the application needs to add JM e n u Ite m components. The JM e n u Ite m
constructor accepts a text title, and, after a JM e n u Ite m object is created, it is then added to a JM e n u object:
JMenuItem newAppItem = new JMenuItem("New Application");
fileMenu.add(newAppItem);

Team-Fly
Team-Fly

M e n u S e le ctio n
The only problem with the F ra m e W ith M e n u V 1 application is that when a user selects one of the menu options, nothing
happens. The application needs to handle the events generated by menu selections. The F ra m e W ith L ist class shows how to
handle button events. So, since the JM e n u Ite m is a cousin of a JB u tto nn, you also know how to handle JM e n u Ite m events.
The JM e n u Ite m class extends the JA b stra ctB u tto n class, just as does JB u tto nn. It is the code of the Ja b stra ctB u tto n that
generates an A ctio n E ve n t that the F ra m e W ith L ist class handled in its a ctio n P e rfo rm e d method. When a user clicks a
menu item, that same A ctio n E ve n t is generated. So, to handle that event, all your application has to do is implement the
A ctio n L iste n e r interface, provide an a ctio n P e rfo rm e d method, and then set the application itself as the action listener by
specifying the keyword THIS in the a d d A ctio n L iste n e r method.

Version 2 of the F ra m e W ith M e n u application, F ra m e W ith M e n u V 22, coded its a ctio n P e rfo rm e d method to exit the
application when the menu item is selected, but when the new application menu item is selected, it simply spawns another
F ra m e W ith M e n u V 2 application, as shown in the code snippet in Figure 16.11.

F ig u re 16.11: The GUI events generated with menu selection and button clicks are handled with the actionPerformed
method.

Note that the a ctio n P e rfo rm e d method is automatically invoked when a user clicks one of the menu items because the
F ra m e W ith M e n u V 2 application specified itself to be the listener object for the A ctio n E ve n t:
newAppItem.addActionListener(this);
exitItem.addActionListener(this);

Team-Fly
Team-Fly

F ram e W ith T o o l T ip s A n d M n e m o n ics


Version 2 of the frame with a menu application does more than handle menu selection events. It also adds two features that
all the best GUI applications have: help for the beginner and support for experts. Quality GUI apps enable what is commonly
referred to as "expert mode." Expert mode is the ability to use an application without resorting to the use of the mouse. It is
called expert mode because regular users of an application quickly tire of moving back and forth between the keys and the
mouse. The solution is to use what is known as k eyboard mnemonics. A keyboard mnemonic is a special handling that is
associated with a keyboard combination of the Alt key and an alphanumeric key. Adding keyboard mnemonics with JFC is so
easy to do that there is no reason for your applications not to use them. All you do is invoke the se tM n e m o n ic method over
your application's JM e n u Ite m or JB u tto n objects:
newAppItem.setMnemonic((char) 'N');

The se tM n e m o n ic method has to be used with the strange casting of a character to the Java primitive ch a r data type. This is
because the se tM n e m o n ic method does- n't really take a character; it takes an integer. That integer is the numerical value
that is associated with an alphanumeric character. If you want to do a little research, you could simply specify the numerical
value that is associated with a character, but I'd suggest you simply use the cast and the first letter of the menu item text.
Once the mnemonic is set, as shown in Figure 16.12, the letter specified in the mnemonic is underlined in the associated
menu item to let expert users know it exists. (Figure 16.13 shows the complete code for the F ra m e W ith M e n u V 2 class.)

F ig u re 16.12: Version 2 of the frame with a menu application handles the menu selection events and provides tool tips
and keyboard

 
 

F ig u re 16.13: The FrameWithMenuV2 class adds tool tips to help user neophytes and keyboard mnemonics to appease
user experts.

The other features that the F ra m e W ith M e n u V 2 application adds are tool tips. The bottom of Figure 16.12 shows a tool tip
that popped up when my mouse hovered over the Exit menu option for a couple of seconds. Setting that tool tip was
extremely easy:
exitItem.setToolTipText(
"Shutdown all FrameWithMenu applications");

Note that tool tips can be set for any JFC component, whereas mnemonics can be set for only JB u tto n and JM e n u Ite m
components.

Team-Fly
Team-Fly

JF C T e m p late s
Extremely sophisticated applications have already been developed with JFC. Those applications were coded by programmers
who were extremely well-versed in object-oriented programming, Java, and the complete ins and outs of JFC coding. But, by
using the example classes of F ra m e O n ly
ly, F ra m e W ith L ist, F ra m e W ith T a b b e d D ia lo gg, and the two F ra m e W ith M e n u
classes, you will be able to create perhaps not Java integrated development environments or game software, but at least
some pretty slick, professional-quality GUIs for business applications.

Team-Fly
Team-Fly

C h ap ter 17: C h ro m ee--P late Y o u r Java G u i W ith D yn am ic M en u s


A n d A S tatu s B ar
O v e rv ie w
ALEX GARRISON

So, I'm guessing that you have worked through some of the earlier Java tutorials in this book and can now create simple Java
applets and applications. Now it is time to consider a few bells and whistles that users have come to expect from all GUI
programs. Two of the most common features are a menu bar at the top and a status bar at the bottom of the GUI application.
The menu bar is expected to reflect the current state of the application; actions that are currently inappropriate should offer
visual feedback such as being grayed out or disabled. Status bars are the common vehicle used to communicate noncritical
information to the user without interrupting the workflow.

In this chapter, I will explain how to set up menu and status bars by providing a short template program called
D yn a m icM e n uu, showing how an application might handle connecting and disconnecting from an AS/400. D yn a m icM e n u
can be easily expanded to develop new applications. The program requires Java Development Kit (JDK) 1.2 or later (unless
you use JDK 1.1 and the Swing package from Sun).

Team-Fly
Team-Fly

D y n am icm e n u
D yn a m icM e n uu, as shown in Figure 17.1, allows a user to connect and disconnect from an AS/400 by selecting an option
from the CONNECTION menu. Note that once you select the Connect option, the program displays a message in the status
bar. If you click on the CONNECTION menu again, you will notice that the menu option now says Disconnect. Changing the
menu option from Connect to Disconnect is an example of using a dynamic menu to make sure that all options displayed to a
user are appropriate for the current state of the application. Figure 17.2 shows the full source code for the D yn a m icM e n u
application.

F ig u re 17.1: The menus of GUI applications should reflect the current state of the application by enabling, disabling,
adding, or removing menu options.

 
 

F ig u re 17.2: The DynamicMenu Java application can be used as a skeleton from which you can develop your own
dynamic menus .

The JM e n u and the JM e n u Ite m objects are created in the constructor for D yn a m icM e n uu. Creating a usable menu involves
four steps: creating a JM e n u object; adding JM e n u Ite m objects to the JM e n u ; adding the JM e n u to the content pane of the
JF ra m e ; and, finally, adding some A ctio n L iste n e r objects to the JM e n u Ite m objects. The first three steps take care of the
visual aspects of the menu (i.e., how it looks and where it goes). The last step provides a way for some action to be taken
when the menu option is selected.

Two different approaches are commonly used to assign A ctio n L iste n e r objects: anonymous inner classes and assignment
to the outer container. The Exit option in the FILE menu uses the inner class approach. Notice that the parameter for
q u itIte m .a d d A ctio n L iste n e r() is a new A ctio n L iste n e r object that has only one method: a ctio n P e rfo rm e dd. You don't have
to put any code in a ctio n P e rfo rm e d to detect which menu option was selected. This inner class object only listens to the
Exit menu option. The inner class approach is appropriate when response to a menu is simple (such as S yste m .e x it(0)).

The second way to handle menu actions is to add the outer container as an A ctio n L iste n e rr. The co n n e ctIte m object adds
the JF ra m e as a listener with the following:
connectItem.addActionListener(this);

The JF ra m e now must implement the A ctio n L iste n e r interface and provide its own a ctio n P e rfo rm e d method. This
technique is appropriate when responses to a menu option are not trivial or when you have a lot of menu options and want to
put all the handling code in a single a ctio n P e rfo rm e d method. For example, if multiple menu items use the JF ra m e as the
listener, then the JF ra m e a ctio n P e rfo rm e d method will require special code to detect which menu item has been selected.

The D yn a m icM e n u class's a ctio n P e rfo rm e d method provides an example of how you detect which menu option has been
selected. The best way to determine the selected menu option is to use the g e tT e x t method. Some programmers use the
g e tA ctio n C o m m a n d (); however, this method returns null if the event was actually triggered by a keyboard shortcut for the
menu item (in JDK 1.1.n). The g e tT e x t method works correctly for both cases.

Now you are at the heart of dynamic menu items. Changing a menu item is as simple as calling the se tT e x t method of the
JM e n u Ite m . The a ctio n P e rfo rm e d method, for example, will execute ite m .se tT e x t("D isco n n e ct") if the user clicks on the
Connect menu item. Note that you could just as easily have disabled the menu option by calling ite m .se tE n a b le d (fa lse ), but
it would not give you a way to allow the user to disconnect from the AS/400 once connected.

Once you get the feel for making changes to menu items, you can easily begin to use other advanced techniques such as
adding new menu options on the fly or adding or changing submenus. The key is to keep the primary goal in mind: Only let
the user select options that are appropriate for the current state of the application.

Team-Fly
Team-Fly

S tatu s B ar
In the previous section, you learned that clicking on the Connect menu option caused a message to appear in the status bar
at the bottom of the application. The status bar is created using the S ta tu sB a r class (shown in Figure 17.3), which is simply
a JL a b e l that has been put in a JP a n e l with a nice beveled border. To place the status bar in the JF ra m e in the
D yn a m icM e n u constructor (shown in Figure 17.2), use the following:

F ig u re 17.3: The StatusBar class manages the presentation of an application's status at the southern border of the
window frame .

getContentPane().add(stsbar, "South");

Since JF ra m e uses the B o rd e rL a yo u t layout manager by default, the layout manager will ensure that the status bar always
remains at the bottom of the JF ra m e and will take care of resizing the status bar when the dimensions of the JF ra m e
change.

For example, when the user clicks on the Connect menu option, an A ctio n E ve n t is put on the Abstract Window Toolkit
(AWT) event queue for each registered listener (just the JF ra m ee, in this case). The AWT event thread then takes the event off
the queue and calls the a ctio n P e rfo rm e d method of the JF ra m ee. The a ctio n P e rfo rm e d method then changes the status
bar by simply executing the following:
stsbar.setMsg("Connected to as/400");

You can set the status bar from anywhere in your application just by calling the S ta tu sB a r.se tM sg (S trin g ) method.

The S ta tu sB a r class is deceptively simple. By inheriting from JP a n e l, the class has encapsulated a lot of functionality in
only a few lines of code. In the best tradition of object orientation and code reuse, you can now use the S ta tu sB a r class in
other applications that need a status bar.

Team-Fly
Team-Fly

M e n u in g A n d S tatu s C o n sid e ratio n s


Dynamic menus are a useful tool in GUI design. However, like any tool, they can be misused. The overuse of dynamic menus
can disorient users by drastically changing their frame of reference. Overuse can also dramatically increase the complexity of
an otherwise simple program.

Status bars should be used wherever possible to keep the user informed and involved. Long processes may cause the user to
think the program is "stuck" unless visual feedback like a status bar is provided to show periodic progress. Be aware that the
S ta tu sB a r class is not threadsafe (just like all Swing classes). When setting the status bar message from any thread other
than the AWT event thread, use the in vo ke A n d W a it or in vo ke L a te r methods as laid out in the various Sun Microsystems
documents.

Creating a useful application in any programming language requires careful consideration of the user interface, and Java is no
exception. By using the simple techniques required to present dynamic menus and a status bar, a programmer can chrome-
plate an application by adding features that are expected by the user and that increase productivity.

Team-Fly
Team-Fly

A d d in g M e n u s A n d A cce le rato rs T o A W T A p p licatio n s


The menuing classes that come with the Java Foundation Classes (JFC) are an improvement over the menuing classes of
AWT. But some shops may not be able to use the JFC components. For instance, if you are deploying your Java using Web-
based applets, you are constrained by the limitation of the JDK supported by your client's Web browsers. Many browsers
support only JDK 1.1, which does not provide the JFC components. You can get around this by providing the S w in g a ll.ja r
file, which provides JFC to JDK 1.1, as an applet archive or by using Sun's JDK 1.2 plug-in; however, these options either
increase applet startup time or require your clients to accept a plug-in.

F ig u re 17.4: Accelerator keys save you the time of selecting items from menus.

At any rate, should you be constrained to JDK 1.1, relax, because adding menus and accelerator keys for menu options to
your AWT applications is easy. For instance, in the example shown in Figure 17.4, the Ctrl-A keystroke sequence invokes
the Attach menu option. The A W T M e n u Java class in Figure 17.5 shows just how simple adding menus and accelerator keys
can be when you are using the Java AWT classes that come with your JDK 1.1 or favorite Java integrated development
environment.

 
 

F ig u re 17.5: The Java source for AWTMenu shows just how easy it is to assign accelerator keys to menu
options .

The m a in function of A W T M e n u starts by creating an object instance of its own class type called a w tM e n uu. The m a in
function then creates the application's F ra m e and a M e n u called FILE. Next, it creates M e n u S h o rtcu t, which will be the
accelerator for the Attach menu option. The parameter for the M e n u S h o rtcu t constructor is K e yE ve n t.V K _A (VV K _A is a
constant that means that the virtual key is the letter A).

Next, the m a in function creates a M e n u Ite m for the Attach option. The M e n u Ite m constructor can take either just the menu
label as a single parameter or a menu label and a M e n u S h o rtcu t as multiple parameters. A menu item was created with the
M e n u Ite m constructor with a label of "Attach" and a M e n u S h o rtcu t called h o tA tta ch (which is the Ctrl-A accelerator key).
The M e n u Ite m then has a listener attached to it to handle user selection of that menu option. (I'll explain this point further in
the last paragraph.) The m a in function then adds the newly created menu item to the menu.

The A W T M e n u class's m a in function uses the same process to add the Detach and Exit menu options, both of which are
assigned accelerators equal to their first letter. Finally, m a in creates a M e n u B a r that is to be displayed at the top of the
application window frame. The M e n u B a r will hold the menu, add the menu to the menu bar, set the menu in the application's
frame, and then size the frame.

The event handling for the selection of a menu option is taken care of in the a ctio n P e rfo rm e d function. After each menu item
was created, the a w tM e n u object (which is the application class itself) was assigned to that menu item as an action listener
with a call to the a d d A ctio n L iste n e r function. When a user selects a menu option, the a ctio n P e rfo rm e d function of the
object specified in the a d d A ctio n L iste n e r function will automatically be called. In this case, the class that contains the
a ctio n P e rfo rm e d function is the same one that creates and holds the F ra m ee, the M e n uu, and all the M e n u Ite m objects. At
any rate, when the a ctio n P e rfo rm e d function is invoked, it uses the g e tS o u rce function to obtain the label of the menu
selected by the user and then executes the appropriate code.

Team-Fly
Team-Fly

C h ap ter 18: Ju st B ro w sin g W ith JD B C


O v e rv ie w
JEFF MARKHAM

To many people, e-business is only a term used by computer companies in marketing campaigns and is not yet a concept
that has been internalized and put into practice by many AS/400 shops. Most developers are quite skilled at accessing and
manipulating data in AS/400 files by using RPG, but they have a difficult time transferring those skills to accommodate the
growing e-business trend. By now, everyone knows that IBM has Java-enabled the AS/400; it's time to figure out how to get to
that data and how to display and manipulate it using the JDBC APIs.

Team-Fly
Team-Fly

L ay o u t O f T h e L an d
I'm going to show you how to display information in fields called JL a b e ls and in a tabular format using JT a b le ss. JL a b e ls are
similar to display file DDS output fields; JT a b le s are equivalent to standard subfiles. To explain the process, I use the
example of allowing customers to inquire about their orders. They do so by accessing your Web page, which has an applet
that, in turn, accesses your AS/400 using JDBC.

The first thing to do is lay out the data in a format that customers will find appealing and easy to understand. One way to
accomplish this is to use a layout manager. A layout manager is comparable in functionality to the User Interface Manager
(UIM) found on every AS/400. To use the layout manager, simply declare in your code the items you'd like displayed in your
applet (JL
JL a b e ls le, and JB u tto n in the example) and let the manager perform the details of the layout for you.
ls, JT a b le

The example in Figure 18.1 uses the G rid B a g L a yo u t layout manager. This layout manager gives you the simplest method of
placing several fields in a form-type display on the screen. Unlike display file DDS, which allows a developer to place fields
beginning at a specified row and column, Java has no such capabilities. Instead, you create the JL a b e ls that will display both
database information and its descriptive text.

F ig u re 18.1: The Inquiry applet displays a custom JTable "subfile" after the user fills in the customer and order
number.

Team-Fly
Team-Fly

M ake T h e C o n n e ctio n
My Java Web application consists of three Java classes: In q u iry iry, which is an applet; F o rm , which is the panel that contains
the JT a b le ; and D e ta il
il, which constructs the JT a b le
le. The meat of the code is in the F o rm class, where the SQL connection
is made to the AS/400 database. (See Figure 18.2 for a subset of the F o rm class's Java source.) Java uses a driver manager
that identifies the classes containing JDBC drivers. Loading the AS/400 JDBC driver in your applet is the first step in making
the connection to your AS/400, and it requires only one Java statement:

F ig u re 18.2: The Form class loads the JDBC driver, establishes a connection, and creates the GUI components of the
applet .

DriveManger.registerDriver (
New com.ibm.as400.access.AS400JDBCDriver ());

The AS/400 JDBC driver is provided as one of the many features of the AS/400 Toolbox for Java. The toolbox is simply a
collection of Java classes provided by IBM and compressed into a file called jt4 0 0 .ja rr.

After the driver is registered, make the connection to the AS/400 with another single statement:
Connection c =
DriverManager.getConnection(
"jdbc:as400://mySystem", "usrprf", "pwd");

The connection created is an open connection to JDBC statements, which, in turn, pass SQL statements to the AS/400.
Once the open connection exists, you can use it to perform all the data manipulations that you are used to doing in RPG
(only now you use SQL). In addition, you can use the Connection object as you would any other object. The example passes
the Connection object from the class that constructs the header of the form to the class that constructs the detail lines of the
form. This, of course, saves resources by minimizing the number of times you must close and reopen connections throughout
your code. You can even optimize the performance of the applet further by having the In q u iry class spawn a thread to handle
the connection in the background while it draws the initial GUI components of the applet—namely, the customer number and
order number fields and the Look Up button.

Team-Fly
Team-Fly

M ake A S tate m e n t
The JDBC statement is created next. This statement passes an SQL statement to the AS/400 database management
system (DBMS). The example physical file Orders contains information about customer orders, and another file named
Customer serves as the customer master file. The customer number and order number are passed as parameters to the
statement, which is then sent directly to the AS/400.What is returned to your program in an SQL SELECT statement is an
object called a Result Set. A Result Set has rows and columns of the selected data that your program will use to fill out the
form. You can position the cursor of the Result Set to row one by calling its firs t() method, since this particular example only
requires the use of one row.

Now that you have the Result Set, the labels that were created to display database information are ready to be populated.
You accomplish this by calling the Result Set's g e tS trin g () method (using the column numbers as parameters). In the
example, calling the g e tS trin g () method on the fourth column of the Result Set returns the date at which the order was
placed; you can put the date into the JL a b e l you created to house such information.

In the F o rm .ja va class example, after all the SQL statements have been executed, the statement and connection are both
closed (as a matter of good housekeeping) by calling their respective c lo se () methods.

Team-Fly
Team-Fly

S e t T h e T ab le
The detail of the order is displayed in a JT a b le le, which is constructed using an object called a D e fa u ltT a b le M o d e l (as shown
in Figure 18.3). The D e fa u ltT a b le M o d e l is responsible for providing the values for the cells in the JT a b le
le. The
D e fa u ltT a b le M o d e l gets its data from a Vector object (essentially, a dynamically sizable array) that contains row data
retrieved via JDBC. In constructing the JT a b le le, you receive the Connection object (created when you populated the JL a b e ls
of the header and footer of the form) and get a new Result Set. This time, you scroll forward through the Result Set by looping
through it (and populating a Vector object in the process). Because the Result Set's column headings are in row one, that row
is skipped. Instead, another Vector object is populated with String objects to be used as the headings for the JT a b le le. To
deploy the applet, the three source files are compiled into three class files and then compressed into a single .ja r file using
the Java Development Kit (JDK) JAR utility. You now return to the AS/400 Toolbox for Java and its jt4 0 0 .ja r file, which
provides the JDBC driver you need.

F ig u re 18.3: The Detail class subclasses Java Foundation Classes' JTable "subfile" class to create a custom
multicolumn view .

When you've created your JAR file and placed it in an HTML document's applet tag, you must take care to grant appropriate
permissions to the applet: namely, the permission to create a socket connection on the AS/400. To deploy your applet, JDBC
does not require that it be a trusted applet. At the very least, however, the applet must be granted permission by a policy file
to create the socket connection. Typically, the policy file will reside in your user home directory.

Team-Fly
Team-Fly

R e ad y , S e t, G o
Applet deployment aside, you can see that it takes only two lines of code to register a JDBC driver, connect to the AS/400,
and start working with your files. At first, it might feel unnatural working with result sets and SQL after working with RPG and
DDS for so long. But the benefits of becoming familiar with, and skilled at, presenting AS/400 data on the Internet or your
intranet through a browser will outweigh any learning curve you might encounter.

Team-Fly
Team-Fly

C h ap ter 19: C h eap Java S u b file P ro g ram m in g T ricks


O v e rv ie w
DON DENONCOURT

In 1998, I introduced Midrange Computing readers to Sun Microsystems' Java Foundation Classes' (JFC) JT a b le component
as the replacement paradigm for AS/400 subfiles. Since then, Sun's JFC classes have become the standard package for the
development of advanced Java GUI applications. However, the fact remains that programming subfiles with JT a b le can be
complex. (I argue that AS/400 subfile programming is actually more complex.) IBM's AS/400 Toolbox for Java has two
alternative components for replacing your subfiles: S Q L R e su ltS e tT a b le P a n e and R e co rd L istT a b le P a n ee. Through either of
these classes, you can build a Java subfile (or table, in Java terms) with one Java statement. The only problem with these
components is that the data presented in the table is read-only.

During one of my 1999 Java seminars, I suggested using the S Q L R e su ltS e tT a b le P a n e and R e co rd L istT a b le P a n e
components for view-only tables and JT a b le when update capabilities are required. However, one of the seminar attendees
(who had listened attentively to my event-driven programming presentation) asked if it was possible to capture an item-
selected event from IBM's table pane components. He suggested that if you could capture that event, you could present an
update panel that had only one record in it. I stared at him for a moment, looked down at my laptop for another moment,
stared at him for yet another moment, and finally said, "Well, yes. I guess you could do that." That afternoon, in front of the
class, I fleshed out the attendee's idea into the Java application presented in this chapter.

Team-Fly
Team-Fly

B u ild in g A T ab le
The user interface of my Java Customer subfile application is quite simple. Figure 19.1 shows the data retrieved and
presented from the S Q L R e su ltS e tT a b le P a n e component. When a user clicks on an item, the window shown in Figure 19.2
allows the user to update the record. After the user cancels or updates the customer record, the update panel disappears and
the user can select another customer to update.

F ig u re 19.1: Users of the customer update application click on the row of a customer to modify that customer's
record.

The best way to show an application's object design is to use a UML object model, as shown in Figure 19.3. (Note that this
particular object model was generated with the Together/J UML tool [www.togetherj.com]. Together/J is itself developed with
100% Pure Java by Object International, and its introductory project, the Whiteboard Edition, is available as a free download.)
There are only five objects in this simple application, yet it still follows the basic tenets of object-oriented programming (OOP).
The most important of these tenets is the separation of the user interface from the business logic.

The C u sto m e rT a b le class shown in Figure 19.4 is the GUI that presents the S Q L R e su ltS e tT a b le P a n e shown in Figure
19.1. The C u sto m e rU p d a te class is the GUI that allows the user to update a single customer, as shown in Figure 19.2. The
S Q L C o n n e ct class shown in Figure 19.5 is an example of the use of the singleton design pattern that I used to ensure that
there is only ever one SQL connection for the application. (For a more detailed description of the singleton design pattern, see
Chapter 62, "The Spartan Order System: An Exercise in Java Application Design.") The C u sto m e r class encapsulates
access to the DB2 for OS/400 file (QIWS/QCUSTCDT), which is on any AS/400 with Client Access installed. Finally, the
In va lid L e n g th E x ce p tio n class is an example of an application-specific exception.

F ig u re 19.2: The Update Customer Master Record window allows the user to update the customer selected from the
Customer subfile.
F ig u re 19.3: The UML object model of the customer update application graphically displays the collaboration of Java
objects to host an application.

 
 

F ig u re 19.4: The CustomerTable class uses the AS/400 Toolbox for Java's SQLResultSetTablePane to create a subfile
with one Java statement .

F ig u re 19.5: The SQLConnect class is an example of the singleton design pattern, which is used to ensure that only one
SQL connection is used in the application.

Team-Fly
Team-Fly

L iste n in g In
The C u sto m e rT a b le class builds the S Q L R e su ltS e tT a b le P a n e in one Java statement in the C u sto m e rT a b le constructor
method:
custSfl = new SQLResultSetTablePane(
connection, "SELECT * FROM QIWS.QCUSTCDT");

So much for the complexity of coding a subfile in Java. Actually, there are a few more points to using the
S Q L R e su ltS e tT a b le P a n ee. One is that you have to invoke its lo a d method to force the subfile to fill. Another point is that, as
with most of IBM's toolbox visual classes, S Q L R e su ltS e tT a b le P a n e does not generate exceptions that would normally be
handled in a TRY/CATCH block. Instead of throwing Java exceptions, the S Q L R e su ltS e tT a b le P a n e object sends error
objects using Java's event-handling facilities. The a d d E rro rL iste n e r method call that you see in the C u sto m e rT a b le
constructor is used to set IBM's E rro rD ia lo g A d a p te r GUI class to handle error events. The call to g e tC o n te n tP a n e simply
adds the Customer subfile to the application frame.

The code that the C u sto m e rT a b le class requires to be able to handle the selection of a particular customer in the table is an
example of basic Java event handling. The user selection event that my Java seminar attendee suggested is called a L ist
S e le ctio n E ve n t event. I coded the C u sto m e rT a b le class to handle that event by implementing the L istS e le ctio n L iste n e r
interface. (Note that the class statement explicitly says it implements the L istS e le ctio n L iste n e r interface.) The
L istS e le ctio n L iste n e r interface has one method: va lu e C h a n g e dd. I'll get to the code for va lu e C h a n g e d in a moment, but
first I want to mention that the C u sto m e rT a b le class's constructor registers itself to be notified at the occurrence of a user's
selection of a row by calling the S Q L R e su ltS e tT a b le P a n e a d d L istS e le ctio n L iste n e r method:
custSfl.addListSelectionListener(this);

Note that the rest of the code in the C u sto m e rT a b le constructor, the a d d W in d o w L iste n e r method call, handles the
window-closing event by closing the SQL connection and exiting the application.

The C u sto m e rT a b le class is coded to handle the L istS e le ctio n E ve n t with its implementation of the va lu e C h a n g e d
method. Because the C u sto m e rT a b le object is registered to handle that event, the va lu e C h a n g e d method is automatically
called by Java's event-handling facilities whenever a user clicks on a different item on the table. The va lu e C h a n g e d method
begins by retrieving the index of the user-selected row using the L istS e le ctio n E ve n t object's g e tF irstIn d e x method. I
discovered by trial and error that L istS e le ctio n E ve n t is fired off at odd times (such as when the index is –1 or when the index
is from a prior selection). The va lu e C h a n g e d method handles those weird situations by simply returning. But when the index
is valid, the customer number located in column zero of the selected row is retrieved with the g e tS trin g V a lu e A t method of
S Q L R e su ltS e tT a b le P a n ee. The va lu e C h a n g e d method uses that customer number to instantiate a C u sto m e r object. Then,
to invoke the update panel shown in Figure 19.2, va lu e C h a n g e d instantiates the C u sto m e rU p d a te GUI, passing the
C u sto m e r object to the C u sto m e rU p d a te constructor .

Team-Fly
Team-Fly

C u sto m e r E n cap su latio n


Before I go into the implementation of the C u sto m e rU p d a te GUI, I want to cover the C u sto m e r class's encapsulation of the
QCUSTCDT file. The implementation of the C u sto m e r class is not the concern here; you can get industrial-strength
implementations through IBM's VisualAge for Java's Data Access Builder (DAX) or one of many third-party tools such as The
Object People's TOPlink (www.objectpeople.com). It is the Java interface to DB2/400 business entities that is the concern.

If you look at the UML diagram shown in Figure 19.3, you can see a partial list of the C u sto m e r class. The attributes (a.k.a.
global fields) of the C u sto m e r class correspond to fields in the QIWS/QCUSTCDT file. Those fields are all private (private
fields in a UML object model are noted with a hyphen [-], public fields are noted with a plus sign [+], and protected fields with
a pound sign [#]), so that users of the C u sto m e r class cannot access or modify their values. To access or modify field
values, the programmer needs to use the public setter or getter methods. Note that setter methods should always perform
some sort of validation and throw application-specific exceptions when the new value passed as a parameter is bad. For
instance, the se tL stN a m method of the C u sto m e r class throws an In va lid L e n g th E x ce p tio n object when the STRING
parameter is longer than the eight characters supported in the AS/400's QCUSTCDT file.

To update, add, or delete records in the QCUSTCDT file, the C u sto m e r class has u p d a te te, a d dd, and d e le te methods. Well,
actually, my implementation has only the u p d a te method, but I'll leave it as a reader exercise to add the other methods. The
C u sto m e r class's constructor builds a C u sto m e r object by retrieving DB2/400 values retrieved based on the integer value
passed as the customer number. Other than that, that's all you need to know about the C u sto m e r class. Information hiding,
encapsulation, and so forth—that's what OOP is all about. If you must look at its implementation, the code for the C u sto m e r
class, along with all the other code in this application, is available on this book's companion CD.

Team-Fly
Team-Fly

C u sto m e r U p d ate
Now I'll go back to the Customer subfile. When the user clicks on a row, that event is handled in the C u sto m e rT a b le class's
va lu e C h a n g e d method by creating a C u sto m e r object and subsequently creating a C u sto m e rU p d a te object to present the
update panel. If you look at the C u sto m e rU p d a te constructor in Figure 19.6, you can see that it begins by setting the size of
its frame and storing the passed C u sto m e r object as a private global field. The C u sto m e r constructor method then uses the
two following prototypical JFC statements to set a topmost panel for the frame:
JPanel topPanel = new JPanel();
getContentPane().add(topPanel);

 
 

F ig u re 19.6: The CustomerUpdate class uses a JFC JPanel set to the GridLayout layout manager to prompt the user to
update customer fields .

The update GUI then puts another panel called d a ta F o rm in the center of the topmost panel to prompt the user to update the
customer values. The d a ta F o rm panel is set to the G rid L a yo u t layout manager (which works very well for update forms). The
data values presented in the form are retrieved from the getter methods of the C u sto m e r object. Note that the calls to the
getter methods must be enclosed in TRY/CATCH blocks because the C u sto m e r getter methods throw exceptions. Finally,
the C u sto m e rU p d a te constructor adds a panel called b u tto n F o rm to the southern portion of the topmost panel, where it
then adds a Cancel and an Update button.

Team-Fly
Team-Fly

C an ce l T h at
Obviously, the C u sto m e rU p d a te class has to handle user clicks of the Cancel and Update buttons. It handles those events
by implementing the A ctio n L iste n e r interface and then registering itself to be notified when the user clicks on either of the
buttons with the following two Java statements:
cancel.addActionListener(this);
update.addActionListener(this);

The A ctio n L iste n e r interface contains only the a ctio n P e rfo rm e d method. C u sto m e r U p d a te implements that method by
disposing the window (in the case of a click of the Cancel button) or modifying the values of the C u sto m e r object and invoking
the C u sto m e r object's u p d a te method. Note that the a ctio n P e rfo rm e d method uses the g e tA ctio n C o m m a n d to discern
whether the Cancel or Update button was clicked.

One other section of code in the a ctio n P e rfo rm e d method that I'd like to point out is the handling of the
In va lid L e n g th E x ce p tio n (the class code for which is in Figure 19.7) in the TRY block for the call to the se tL stN a m method.
If the In va lid L e n g th E x ce p tio n is caught, I use the JO p tio n P a n e to present the error dialog shown in Figure 19.8.

F ig u re 19.7: The InvalidLengthException class is an example of how easy it is to create application exception
messages.

F ig u re 19.8: The JFC's JOptionDialog is easily used to present an error dialog.

You might be wondering why the C u sto m e rU p d a te class has a m a in method when the design of the application doesn't
require one. In a production scenario, only the m a in method of the application driver is invoked, which, in this case, is the
C u sto m e rT a b le class's m a in method. I used the C u sto m e rU p d a te class's m a in method for unit testing so that I could
bypass going through the interface of the C u sto m e rT a b lele.

Team-Fly
Team-Fly

R o o m F o r Im p ro v e m e n t
The techniques prescribed in this chapter allow you to quickly create a Java subfile application without the complexity of
using a JFC JT a b le
le. The C u sto m e rT a b le and the C u sto m e rU p d a te classes are each well under 100 lines long. Clearly,
there is much that can be added to my example subfile application:

 I limited error handling.

 I didn't use any type of SQL isolation levels for transaction control.

 The C u sto m e r class doesn't contain all the code required for complete encapsulation of the business entities stored in
the QIWS library's QCUSTCDT file. For instance, the C u sto m e r class needs a d d and d e le te methods.

 The C u sto m e r class needs to throw more application-specific exception objects in its setter methods.

 The C u sto m e r class would benefit from adding some methods to collaborate with associated objects, such as a
g e tP u rch a se O rd e r method or a getInvoices method.

 You might want to have the C u sto m e rU p d a te class reload data into the C u sto m e rT a b le class's
S Q L R e su ltS e tT a b le P a n e so that the subfile will show the user modified values.

Still, the example classes use basic OOP techniques, and it separates the user interface from the business logic. Most
important, the technique I presented in this chapter allows you to quickly and easily generate Java subfile update programs
without resorting to the complex coding required to use JFC's JT a b le component.

Team-Fly
Team-Fly

C h ap ter 20: G U I B u ild er M akes Java G U I D evelo p m en t E asy


O v e rv ie w
SHANNON O'DONNELL

If you've ever written an interactive Java program, you know that designing the GUI interface is not exactly a straightforward
process. Basically, you have two choices. You can code each component of the interface in a Java source file piece-by-piece,
or you can use one of the visual development tools. No matter which technique you use, there's a trade-off. Using the
traditional method of coding every component means you need to have a thorough understanding of layout managers,
containers, and action listeners, to name a few. The traditional method is not easy. On the other hand, if you use an
integrated development environment (IDE) such as VisualAge for Java, designing the GUI is very easy. But tying all the GUI
components together into a working application is a lot more difficult.

To successfully use one of these IDEs, you first need to have a thorough understanding of Java. If you ever have to go back
and modify one of the Java source files generated by an IDE and you don't have the IDE available, then you'll quickly discover
that IDEs are nothing more than code generators, and the code they generate is unduly complex and nearly
incomprehensible. Manual modifications are a nightmare. There needs to be a way to combine the flexibility of coding the
pieces you want to code by hand along with a simple GUI designer that lets you quickly create a Java GUI. If it could make
the generated code easy to understand and modify, two-thirds of the battle for programming in Java would be over.

Evidently, IBM also felt that something like this was needed. IBM created a Java GUI design tool, GUI Builder, that lets you
very rapidly build reusable Java GUI panels. However, before you can appreciate the ease GUI Builder will bring to your
programming life, you must first understand why writing interactive Java programs the conventional way is so tedious. Since
developing Java apps with an IDE is a monumental undertaking in and of itself, I'll skip any comparisons between that and the
GUI development tool. I'll leave it to you to try the IDEs for yourself.

Team-Fly
Team-Fly

T rad itio n al G U I D e sig n


I'm going to do something very simple: create the Java GUI panel shown in Figure 20.1. This is a simple application that can
be called from any DOS command line. As you can see, the only components on this panel are a label, a text box, and a
button. Pretty basic, huh? At least it seems that way until you start digging into the code that makes it work. I'll show you
what I mean. Figure 20.2 contains the code that displays the panel shown in Figure 20.1. I've added some labels to the code
to point out some of the key areas of this generic Java GUI design.

F ig u re 20.1: Here's a very simple Java GUI.

 
 

F ig u re 20.2: This is the traditional method of coding a Java GUI .

Team-Fly
Team-Fly

T h e P ie ce s
In Figure 20.2, at Label A, I've told Java to define a new Canvas object named G U IC a n va s. G U IC a n va s is a separate Java
class and does nothing more than extend the Java C a n va s class interface. It is the area where the GUI components will be
displayed, inside a standard Windows frame. Label B tells Java that I want to use the G rid B a g L a yo u t layout manager to
define how components will be displayed in the GUI panel. It's up to you to decide which layout manager you'll need to use.
Label C, in conjunction with the statement at Label B, is used to instantiate the G rid B a g layout manager. Label D is used to
instantiate the new canvas.

The statements at Label E are used to define the GUI components, which, for this example, include a label, text field, and
button. Each of these groups of instructions calls the a d d C o m p o n e n t method defined at Label H to actually add the
components to the canvas. Because you have to specify the exact grid coordinates of each component in relation to all the
other components, it's easier to create one method to handle the placement and adding of the components to the canvas.
Label F registers an A ctio n L iste n e r to the button. This tells Java that some activity will be occurring with this GUI component
and it should "listen" for this activity and take appropriate action. In this case, the action to be performed is to close the GUI
panel. After all that, you're finally ready to display the GUI panel, which is what happens at Label G.

Piece of cake, right? Probably not, unless you've been programming in Java for quite some time and are used to it. And this is
a really simple Java GUI too! Imagine if you had a very complex GUI to design and had to manually lay it out on your canvas.
Yeesh! This is one of the reasons why Java is still on the back burner of acceptance by traditional AS/400 green-screen
programmers. After all, once you've used a tool like Screen Design Aid on the AS/400 to create display files, you're not going
to be very accepting of something that makes you go back to graph paper and coordinate marking. Besides the drudgery of
having to add all these components manually, and define the layout manager and canvas, and on and on and on, all this stuff
makes your code unnecessarily confusing. Now, I will show you a tool that removes most of this complexity.

Team-Fly
Team-Fly

G U I B u ild e r
GUI Builder is a Java-based WYSIWYG GUI design tool that was introduced with Modification 2 of the AS/400 Toolbox for
Java. If you have Version 4, Release 4, of OS/400 or higher on your AS/400, then the Mod 2 version of the toolbox resides
there. I suggest, however, that you download the latest version of the AS/400 Tool- box for Java from the JTOpen site (go to
www.as400.ibm.com/toolbox/ and follow the JTOpen links).

GUI Builder is a visual design tool that lets you very rapidly and easily build Java GUI panels from scratch. It also lets you
convert existing Windows Resource files (file type of RC) into an XML representation that can be understood by GUI Builder.
This lets you very quickly turn your existing Windows GUI definitions, those you created in C++ for example, into a format
that can be understood by Java. In other words, in just a few minutes you can take a library of C++ GUI definitions you
designed for Windows machines and make them completely platform independent.

GUI Builder is able to accomplish all this by using a technology developed by IBM called Panel Definition Markup Language.
PDML is based on XML and is a way of describing GUI interfaces that are platform independent. PDML, like XML or HTML, is
a tag-based language. That is, each component of a GUI panel is defined with appropriate tags such as < B U T T O N > or
< T E X T F IE L D >>. Java programs can then access the PDML file using a call to some new IBM-designed Java user interface (UI)
classes that parse the PDML source file and turn it into a visible GUI.

Team-Fly
Team-Fly

C o n fig u rin g A n d R u n n in g G U I B u ild e r


The GUI Builder utility resides in a JAR file named U IT O O L S .JA R . When you install the Mod 3 version of the AS/400 Toolbox
for Java, this JAR file will reside in the same directory where all the AS/400 Toolbox for Java JAR files reside. To use GUI
Builder, you're going to need to add the U IT O O L S .JA R file to your PC's CLASSPATH. To do this, edit your A U T O E X E C .B A T
file and add the following lines:
SET CLASSPATH=%CLASSPATH%;C:\JT400\LIB\JT400.JAR
SET CLASSPATH=%CLASSPATH%;C:\JT400\LIB\UITOOLS.JAR
SET CLASSPATH=%CLASSPATH%;C:\JT400\LIB\JUI400.JAR
SET CLASSPATH=%CLASSPATH%;C:\JT400\LIB\X4J400.JAR
SET CLASSPATH=%CLASSPATH%;C:\JT400\LIB\DATA400.JAR

In this example, I've installed the Mod 3 version of the toolbox to a directory on my hard drive named JT 400\L IB \. You'll need
to change this path to match the location of the JAR files on your own PC. The JT 400.JA R file contains all the base Java
classes for accessing the AS/400 and working with AS/400 data. The U IT O O L S .JA R contains the GUI Builder classes as
well as other Java UI classes. The JU I400.JA R file contains the Runtime classes used to parse and interpret the PDML files
generated by GUI Builder. The X 4J400.JA R and D A T A 400.JA R files contain XML parsers and XML utilities used by GUI
Builder.

The other piece you're going to need is a Java Development Kit such as the JDK 1.2 or JDK 1.3 available from Sun
Microsystems at java.sun.com/j2se/. Download and install this free JDK on your PC, following the instructions that come with
it. You'll be making use of at least one command, JAVA, from that JDK when you use GUI Builder.

Once you've added the Mod 3 toolbox and the JDK from Sun Microsystems and modified your A U T O E X E C .B A T file, reboot
your PC. When Windows restarts, your system should now be ready to work with GUI Builder. To start the utility, you'll need
to enter the following command at a DOS command line:
java com.ibm.as400.ui.tools.GUIBuilder -plaf Windows

This command starts GUI Builder and gives it the Windows look and feel. You also have the option of using the Metal or Motif
look and feel if you'd rather.

When GUI Builder opens, click on the New Panel icon from the toolbar and you'll see a panel somewhat similar to that shown
in Figure 20.3. This figure duplicates the panel I created in Figure 20.1. Now you can add items such as buttons, text fields,
labels, and list panels to the GUI panel by clicking on the appropriate component icon from the GUI Builder toolbar and
dragging and dropping it anywhere on the panel. Compare this method with the traditional method of positioning the various
components by grid position, and the ease of a visual designer such as this becomes obvious.

F ig u re 20.3: GUI Builder lets you develop Java GUIs very rapidly.

Team-Fly
Team-Fly

B u ild in g S ke le to n C o d e
Using GUI Builder, you also have the option of letting the tool create skeleton Java code for you for each component on your
GUI panel. It works this way: Add a component, such as a text field, to the panel and then double click on it to display its
properties. Among the properties you can select are the component's DATA CLASS and ATTRIBUTE. When you enter a
name in the DATA CLASS field, you are telling GUI Builder that this component will retrieve its data from a Java class of the
name you give it. In other words, if you create a text field and enter a value of T e x tC la ss in the DATA CLASS field of that text
field's properties, GUI Builder will specify in the PDML file that the data for this component comes from a Java class named
T e x tC la ss
ss.

The ATTRIBUTE property lets you define the name of the methods GUI Builder will expect the class T e x tC la ss to contain.
Each method—gg e t, se tt, and so on—will have the name g e tA ttrib u te or se tA ttrib u te , where "AA ttrib u te " will be replaced by
the name you enter into the ATTRIBUTE property field. So, assume that the ATTRIBUTE property contains the name
ta. Your Java program would refer to the g e t value of this component with this form:
Y o u rD a ta
TextClass.getYourData();

You'll specify the DATA CLASS and ATTRIBUTE for each component that contains data on your panel. You can also indicate
whether or not a given component will contain help information. If you enter something in the GENERATE FIELD HELP
property and tell GUI Builder to do so, the tool will create HTML help using the names you supply in the Properties panel. GUI
Builder will also put the tags into the PDML document to point to the correct help file when the user selects HELP on that
field. All you have to do is edit the HTML files to provide as much detail on each component's HELP that you require. Pretty
cool, huh?

When you are satisfied that you have designed your GUI panel just the way you want it, you are ready to save it. But, before
you do, click on the panel name and then click the Properties option from the View toolbar item in GUI Builder. In the
Properties panel that displays, you'll find several options. Among them are the options to Generate help, Generate data
Beans, and Generate event handlers. If you set these properties to TRUE when you save your work in GUI Builder, it will
generate the HTML help file(s) and skeleton Java code for each component you set DATA CLASS and ATTRIBUTE properties
for. After that, all you have to do is edit the Java source files created by GUI Builder to add the logic to retrieve and add the
data to your GUI components and you're in business.

Team-Fly
Team-Fly

P D M L F ile
The PDML source file generated by GUI Builder (Figure 20.4) is very easy to understand, unlike the Java code generated by a
typical IDE such as VisualAge for Java. Although it's not recommended, if you needed to modify the PDML file generated by
GUI Builder manually, you could do it quite easily. You'd just have to ensure that the modifications you made conform to the
PDML standards, which aren't very difficult to understand. Another plus is that if you do make modifications to the PDML file,
any Java class that references it can continue to use it without needing to be recompiled. That should save a lot of time.

F ig u re 20.4: Here's the PDML file generated by GUI Builder for the example.

OK, so now you've designed your new GUI and you're ready to display it. How do you go about this? Actually, that's the
easiest part of all. GUI Builder comes with some runtime Java classes called Panel Managers that parse the content of the
PDML file into a GUI that displays on your screen.

Look at the code shown in Figure 20.5. There are only four lines of code your Java program needs to display a PDML GUI.
These are the two import lines:

F ig u re 20.5: Contrast this Java code with that shown in Figure 20.2. Both display the same GUI.

pm = new PanelManager(…)
pm.setVisible(true)

That's it. Compare this to all the code required by the traditional programming method. Of course, as with anything else, you
can quickly get a lot more complex than this example.
For a complete tutorial on how to use the GUI Builder utility, refer to the online documentation for the AS/400 Toolbox for
Java. The subsection titled "GUI Builder" contains a very comprehensive set of help documentation that will get you up and
running with the GUI Builder utility in no time.

Team-Fly
Team-Fly

S e n d in g A M e ssag e
Developing applications in Java is something that all programmers need to learn how to do. The fact that most don't should be
sending a signal to IBM and Sun Microsystems and the other major players that perhaps the tools available for learning and
developing Java apps are less than successful. IBM has made a very good step in addressing this problem by providing the
GUI Builder GUI design tool. Give it a try. With a little practice, you'll find that creating interactive Java applications isn't as
hard as you may have first thought.

Team-Fly
Team-Fly

R e fe re n ce s
 IBM AS/400 Toolbox for Java Modification 3 Programmer's Guide: www.as400.ibm.com/toolbox/downloads.htm

 IBM AS/400 Toolbox for Java Modification 3 Web site: www.as400.ibm.com/toolbox/

 Sun Microsystems Java Development Kit 1.2 Web site: java.sun.com/j2se/

Team-Fly
Team-Fly

S ectio n V : L eg acy In tero p erab ility


C h ap te r L ist
Chapter 21: Application Modularization: Separating Presentation And Programming Logic

Chapter 21: Breaking Apart The Monolith

Chapter 23: The Business Of Java

Chapter 24: Calling RPG From Java

Chapter 25: Invoking RPG Via Jdbc

Chapter 26: TCP/IP Sockets Programming

Chapter 27: Using Java Sockets Programming

Chapter 28: Servlets, Sockets, And RPG

Chapter 29: Using The JNI To Call RPG From Java

P art O v e rv ie w
My hobby is martial arts. In fact, when I was a teenager in the '70s, I expected to make a career out of the martial arts.
Initially, I studied karate because it was popular. And, by the end of the '70s, I had risen to some local fame (if only in my own
mind). In the '80s, however, kickboxing became the latest fad in martial arts. So I pulled off my gi top, donned a pair of gloves,
put on some headgear, and went at it. I even had two semiprofessional matches, netting myself almost $200. For years I
participated in discussions that pondered the "best" martial art. Was it karate, kung fu, judo, jiujitsu, kickboxing, or aikido?
Until the '90s, these discussions were as far as it went. For the most part, karate practitioners stayed in the dojo, kickboxers
stayed in the ring, and grapplers kept to the mat.

In the early '90s, however, a new style of competition came into vogue, the "ulti- mate fights championships." These were no-
holds-barred competitions where you used what worked. Eye gouging and groin strikes were frowned upon, but other than
that, the match continued until one person was knocked out, choked unconscious, or quit. One of the better-known
competitions was called the Octagon, because the match took place in an eight-walled arena. For several years, jiujitsu
experts dominated these matches. Traditional martial artists like me began to question many of the methodologies and
strategies that we had been using for years.

Many, including me, began taking jiujitsu lessons. But in the last couple of years, the winners of the ultimate fights were no
longer the jiujitsu experts. Traditional martial artists who adapted their strategies to incorporate the grappling techniques of
jiujitsu began winning the Octagon.

T h e In te rn e t O ctag o n
For decades, we programmers have been discussing the "best" programming language. In the '70s, traditional languages
such as RPG and COBOL became prevalent. In the '80s, C became popular, and then in the early '90s, the hot language was
C++. So, which language was the best? Was it RPG, COBOL, C, C++, Prolog, Lisp, or what? Plenty of evenings were spent
arguing this topic, but, like martial artists, programmers pretty much stayed to their own playing field. RPG and COBOL
programmers stayed on IBM midrange and mainframe platforms while C programmers stayed on PC and UNIX boxes.

All that is changing because the ultimate fight championship of computer languages has burst onto the scene. Is the shape of
this arena also an octagon? No, it's round, or rather, spherical. The arena is the world, and the promoter of this fight is the
Internet. (And you thought the Octagon was brutal.) Initially, the winners of this fight were not the traditional RPG and COBOL
programmers. The champions were initially from platforms that attracted computer scientists and TCP/IP wizards. We RPG
programmers on our midrange platforms were left bruised and battered by programmers who knew the technologies of UNIX
and Windows NT.

But, just like the ultimate fight championships, people adapted technology to survive. The AS/400 programmers can now take
advantage of the superior platform-specific technologies of OS/400 because IBM has provided cross-platform APIs and
integrated Internet technologies. The top fighters in the Internet Octagon are no longer UNIX geeks and NT wizards but
business programmers who leverage their legacy technologies to their greatest advantage while adapting to new technologies.

S u rv iv al
Yes, you can comment on the brutality of watching two men battling it out in an arena until one man is knocked out, or has
his elbow broken, or screams in pain and anguish as he submits to the superiority of his opponent. The Internet Octagon,
however, is far more brutal. Companies will go under, millions of dollars will be lost, and careers will be destroyed. But so,
too, will companies rise to dominance, billions will be made, and careers will be forged. Perhaps our lives don't depend on the
outcome of the Internet Octagon, but our livelihoods do.

All the cheerleading aside, this section provides nine chapters on how to leverage both your legacy applications and your
legacy knowledge. Kevin Vandever's "Application Modularization: Separating Presentation and Programming Logic" eases
you into the revitalization of your legacy applications by showing you how to separate your DDS display file interface from the
RPG business logic. Kevin also makes suggestions for how to replace the DDS user interface with Java. Joe Pluta's
"Breaking Apart the Monolith" goes into more detail on how to split your user interface from business logic. Joe's next
chapter, "The Business of Java," then details how to use Java as the user interface with RPG interoperability via OS/400 data
queues.

If your RPG apps don't have screen I/O, they can be called directly from Java. Michael Polutta's "Calling RPG from Java"
explains the use of IBM's Java Tool- box for the AS/400's P ro g ra m C a ll class. I provide an SQL stored procedure alternative
in "Involving RPG via JDBC."

If you want optimal performance for your Java-to-RPG interoperability, then you need to consider TCP/IP sockets. Jim
Barnes's "TCP/IP Sockets Programming" shows how to use sockets in RPG. Kevin Vandever then shows the Java side of
things in "Using Java Sockets Programming."

Most often, the Java application is the client and the RPG app is the server. Sometimes, however, you may have a
requirement for a Java server application that is accessed by RPG clients. Jeff Markham, in "Servlets, Sockets, and RPG,"
explains how an RPG client can access a Java servlet via sockets.

For those of you who are interested in the most sophisticated Java-to-RPG integration environments, read Jim Barnes's
"Using the JNI to Call RPG from Java." Java Native Interface (JNI) allows you to develop a Java class with methods that are
coded with your legacy language. In truth, however, the designers at Sun Microsystems felt that the legacy language was C,
so JNI, by default, helps you create the C interface files (header files) and not the RPG prototypes. Regardless, Jim explains
what you have to know to create your own RPG prototypes so that you can use RPG modules to flesh out the code for Java
class methods.

As programmers, our job is to use the technologies provided in this section to develop Web middleware for our existing
applications. Creating an all-Java application may be a nice thought, but the truth of the matter is that our legacy code and
legacy coding strengths must be leveraged. The fastest way to get Web applications up is to integrate Java with existing
code. The chapters in this section tell you how to do that.

Team-Fly
Team-Fly

C h ap ter 21: A p p licatio n M o d u larizatio n —S ep aratin g


P resen tatio n A n d P ro g ram m in g L o g ic
O v e rv ie w
KEVIN VANDEVER

Competition, customer requests, and new technology dictate that you take your business in a new direction, or at least in
more than one direction. Green-screens alone won't cut it anymore. Customers want Web access to enter their own orders
and view the status of those orders. If you don't provide this capability, your loyal customers may order from someone who
does. But what about your legacy applications?

Many years of development work have been invested in the complex business logic contained in your RPG code. You don't
have the time, people, money, or intestinal fortitude to rewrite all your business logic so that it can be placed on the Web. So,
how do you leverage what you have and still get to the Web? Is it even possible? Now you're not feeling so wonderful
anymore. Well, don't worry. There is a fairly simple step you can take to get your business on the Web and, at the same
time, not disrupt your current green-screen users: Separate the user interface (UI) from the business logic.

Team-Fly
Team-Fly

A lte rn ativ e s
Now that I have offered this idea, however, I must tell you that there are other ways to move your business to the Web without
separating the UI from the business logic. Before going on, take a moment to look at a few of them.

The only way to directly use a green-screen UI on the Web is to use Workstation Gateway Server (WSG) to dynamically
convert the 5250 data stream to HTML. However, you lose any cursor-sensitive prompting or help in the process, and the
screen that is displayed on the Web—when compared to Web page standards—is horrid at best.

You can also replace the green-screen with CGI, which allows you to use APIs and other tools to build dynamic HTML from
your RPG. This is an improvement over WSG simply because you have better control over the HTML that is produced and
displayed; however, you are still limited in the types of applications you can employ. CGI is not ideal for heads-down data
entry or maintenance applications but may serve you well if you require only light data entry or inquiry screens.

Another way to get to the Web is to completely rewrite your RPG legacy code in some object-oriented (OO) language such
as Java. The results from such an endeavor might make it seem like a good idea, but to take your existing legacy application
and try to rewrite it may be biting off more than you can chew. The OO goal is better obtained in a staged approach, once
you've prepared your legacy application for such a change.

The last approach that I've seen used—but do not recommend—is to copy your legacy application and use the original for
your green-screen users and then convert the copy into something that can be put on the Web. The problem with this
approach is that you are now maintaining two sets of the same business logic. It's difficult enough to keep one version
working properly, let alone two. Think of the potential maintenance nightmare as you put your entire business on the Web.

Team-Fly
Team-Fly

T o d ay 's R P G W o rld
The beauty of separating the UI from your business logic is that it opens up the business logic to so many more
opportunities. In fact, if you happen to prefer using WSG or CGI, you can still do so by separating out the UI first. The key is
to allow your business logic to remain independent of the UI so that it has the potential to be shared by many UIs.

Figure 21.1 shows the typical structure of an RPG program. The UI is integrated with the business logic. In this case, the
business logic is nothing more than moving a literal into a field, but you get the picture. The program displays the screen,
which allows the user to enter something into the bogus field. When the user presses Enter or a valid function key, control is
returned to the program and a specific action takes place, depending on which key was pressed. In this program, if the user
presses F3 or F12, the program ends. If the user presses Enter, the literal 'S u cce ss!' is placed in the field called RESULT
(the business logic) and the screen is redisplayed. Figure 21.2 shows what the screen looks like when you run it. There is
nothing fancy or complicated here. The purpose is to take a typical-looking RPG program (in structure) and show how you
might separate out the UI.

F ig u re 21.1: User interface and business logic are traditionally linked together in this way .

Team-Fly
Team-Fly

W h e re B u sin e ss W an ts T o B e
Imagine that your company has decided to put its business on the Web and it wants to start with the screen from Figure
21.2. As I mentioned before, you could simply start WSG and be finished, but your business might also be finished if that's
what you decide to present to the outside world. OK, so WSG is out. You could use CGI and replace the interaction to a
green-screen with calls to CGI

F ig u re 21.2: This is what the screen looks like when you run it after a request is entered.

APIs that build and display HTML. However, management doesn't want to replace the green-screen applications, they want to
add to them. They don't want the current green-screen users to miss a beat. This management wish can be handled easily if
you separate out the UI from the business logic. Now, instead of one interface to the business logic (the green-screen), you
will have more than one (the green-screen and whatever other approaches you employ to get to the Web).

The good news is that there are many protocols that allow you Web access, and they all use messaging as the underlying
tool for communication. All you need to do is decide which messaging protocol best suits your application and use it. The
details are taken care of with messages. The following subsections present four of the protocols available to help you get at
your legacy application's business logic.

M Q S e rie s
MQSeries is a third-party tool that uses messages (high-level, user-formatted messages, not the underlying communication
messages used in all these protocols) and message queues to pass data back and forth between the UI and the business
logic. MQSeries is a very programmer-friendly, high-level means of passing data between applications. In my opinion, it is
more popular with business analysts than with programmers, because programmers can handle most of what MQSeries
accomplishes by using native AS/400 techniques such as data queues and message queues (sometimes the business folks
don't know that). However, for passing data between programs running on different operating systems, MQSeries may make
things much easier.

D ata Q u e u e
Many of us AS/400 programmers are accustomed to using data queues as a means to pass data between programs. Using
data queues here is no different except that these programs may be on different machines and written in different languages.
The AS/400 Toolbox for Java includes the APIs necessary to allow Java to use AS/400 data queues as a means of
communication. The primary advantage to using data queues is that they are native to the AS/400 and are already used in
many RPG programs. My only concern is the speed. When I used the data queue APIs in Java 1.1.6 to communicate with
RPG programs, I found the results unacceptable (1 second to 2 seconds per transaction). Subsequent versions of the Java
Development Kit (JDK) have shown increases in performance, and I now feel more comfortable employing data queues as a
strategy.

R P G C alls
This one may seem a bit obvious, but you can call RPG programs directly from Java by using a couple of techniques, both of
which involve the AS/400 Toolbox for Java. The first method is to call the RPG programs directly using the call APIs provided
in the toolbox. The second method involves creating a stored procedure from your RPG program and using the JDBC API to
perform an SQL call to your stored procedure. This method involves the extra step of creating the stored procedure from your
RPG code (which is very easy to do and doesn't change your RPG), but it may be worth your while if you are using a Web
application server, such as WebSphere, that can easily provide and maintain JDBC connections to your AS/400. Using RPG
calls also makes it easier to allow your green-screen user to get at your business logic since "calling" programs is so natural
to us RPG folks. I definitely recommend employing calls to RPG programs if you're working with Java; they perform well and
require the least amount of disruption to your RPG code.

T C P /IP S o cke ts
This method is a little more foreign to RPG programmers but definitely deserves a look as a means of communication.
Sockets work a lot like data queues in that they allow requests and responses to be "queued" for processing. You can use
APIs to send data to and receive data from sockets, not unlike the APIs used with data queues. However, sockets are much
faster, and they are run over TCP/IP, which is platform independent. They boldly go where no data queue can go. Sockets are
easy to implement in Java because they are native to the language. Although you can work with sockets directly from RPG
by using the sockets APIs, not all of the sockets features are supported. The best way I've found to work with sockets is by
calling the socket functions written in C. This way, you are certain to have all the sockets features at your disposal. (To find
out more on how to use the C socket functions, see Chapter 26.)

Team-Fly
Team-Fly

U se r In te rface
I just mentioned a few ways to get at your legacy code. Now I want to talk about what you will do once you choose a method
to communicate with your business logic. In my example, I am going to use data queues as the means for communication. I
chose this method because it is recognizable to many RPG programmers. I also chose it because it requires you to
implement API calls in your RPG program, which will be the case with many of the available messaging protocols.

To separate the UI from the business logic, you need to remove anything that relates to the display file and make it its own
program. Assume that a Web designer has already developed a Web page and written some Java that uses the data queue
API to communicate with RPG business logic (big assumption, I know, but work with me here). That's one UI down, one to
go.

Figure 21.3 is the result of separating out the UI while still providing the green-screen users the UI they are accustomed to.
Notice that I am using the same display file as the code in Figure 21.1. The green-screen user sees no change. The purpose
of this program is to allow the user to enter a request on the screen (the bogus field). It will not perform any business logic.
Instead, it will take the request from the screen and send it to the business-logic program via a data queue with a call to the
Send Data Queue (QSNDDTAQ) API. It will then wait for a response from the business-logic program by calling the Receive
Data Queue (QRCVDTAQ) API and display that response on the screen.

F ig u re 21.3: Separating out the user interface from the business logic gives green-screen users the UI they are
accustomed to .

Team-Fly
Team-Fly

B u sin e ss L o g ic
Figure 21.4 shows the new version of the business-logic program. Notice that there is no code that directly communicates
with a UI. This program's only purpose is to receive requests from a data queue, regardless of where they come from, and
perform business logic on those requests (move 'Success!' to the RESULT field, in this case). The business-logic program is
initiated by either submitting it to batch or making it an autostart job in a particular subsystem. It will wait at the call to the
QRCVDTAQ API until an entry is written to that queue. The green-screen program I just discussed will write an entry, or an
entry will be written from my assumed (make-believe) Java program that was created to communicate with a Web page.

F ig u re 21.4: The new version of the business-logic program uses data queues to communicate with the UI.
.

Once the program receives an entry in the data queue, it first checks to see if it is an end-of-job request. If it is, the program
is terminated. If not, the request is processed by the business logic and sent back to the UI via the QSNDDTAQ API. In a
production environment, you will want to keep track of which UI sent which request so that you can send the response back
to the appropriate UI. In my example, though, I am not concerned about where the request came from. This simple, working
tutorial will help you understand the concept of separating the business logic from the UI.

Team-Fly
Team-Fly

S e p aratio n A n x ie ty N o M o re
Separating the UI from the business logic is a simple, yet powerful, technique. By removing the green-screen communication
and processing from your business logic, you allow the opportunity to communicate with that logic from a variety of protocols.
Just as important, you add this ability without disrupting your current green-screen users. You immediately deem your
business logic open to the world and can start shedding terms such as legacy, old, outdated, and obsolete from statements
that define your business applications.

Team-Fly
Team-Fly

C h ap ter 22: B reakin g A p art T h e M o n o lith


O v e rv ie w
JOE PLUTA

What is a monolith? Merriam-Webster defines it as (1) a single great stone often in the form of an obelisk or column, (2) a
massive structure, or (3) an organized whole that acts as a single unified powerful or influential force.

The first definition is what Arthur C. Clarke had in mind in his screenplay 2001: A Space Odyssey, but the other two
definitions better suit this discussion. When much of the legacy software used today was written, there seemed little use for
the CALL instruction. In fact, most programs were single monolithic entities, massive and powerful, although you could argue
whether or not they were "organized." A normal item master maintenance program alone was about 4,000 lines of RPG code,
not counting the display file DDS source.

Team-Fly
Team-Fly

Y o u S ay T h at L ike It W as A B ad T h in g
Well, it was, especially if you wanted to modify your application. These programs did everything, from business rules to
screen formatting. It's no wonder they were large and cumbersome. Add RPG's global variables, and it's easy to see how
program modification backlogs continued (and still continue) to grow.

The other major issue with monolithic design came as installations grew larger and more diverse. Different sites and different
users within a single site had different requirements. Some users needed to update certain fields, while others couldn't.

One solution was to add more code to the already unwieldy maintenance program, introducing errors into a previously stable
program. The other solution was to clone the program and change the clone to suit the new requirements. Unfortunately, that
meant having two or more programs executing the same business rules. As business requirements changed, all those cloned
programs had to change too. In SSA Global Technologies' BPCS, most of the material requirements planning (MRP) inquiries,
reports, and processing programs started with virtually the same processing code. However, they immediately began to
diverge. Soon, while you could still recognize that the programs had the same origins, they could no longer be called clones.
A fix for one program could not be applied to another without thorough analysis.

Team-Fly
Team-Fly

S o H o w D o W e F ix It?
This has been a goal of distributed programming from the beginning. "Client/server" often implies PCs talking to mainframes,
but I can create a perfectly good client/server application where both client and server run on the same machine. Why would I
do that? For one thing, to separate the user interface from business logic.

By creating one program that communicates with the user and another that accesses the database, I can change one without
affecting the other. User interface programs tend to be small because they do very little work. However, application changes
often involve only changing how the user communicates with software and not how the software actually functions. You don't
want to change the way your business works every time you turn around, even though your users can dream up new bells and
whistles every day. By separating user interface from business rules, you can provide changes of convenience for your users
without impacting day-to-day business functions.

For example, say the shipping department needs to change the shipping addresses of its customers without seeing their
account information, while accounting needs access to the customers' credit limits. Business rules on maintaining fields don't
change from user to user. In a distributed program environment, you would simply clone accounting's user interface, remove
the sensitive fields, and give the new copy to shipping. Because both user interface programs call the same editing program,
all business rules would be enforced, regardless of which interface was used.

Team-Fly
Team-Fly

C lie n t/S e rv e r V s. S e rv e r/C lie n t


You can use two basic strategies to reach the goal of separating the user interface from business logic. To illustrate the
difference, I need to introduce some terms that identify which portion of the architecture has actual control over program flow.
For these examples, I'm assuming that the original monolithic program is broken in two: the user interface portion and the
business rules portion. As I discuss the two types of architecture, I'll address the user interface portion first and then the
business rules.

In client/server architecture, the user interface is the client. The client makes requests from the business rules processor,
which is the server. For example, instead of reading a record from the database, the client sends a GET request to the server,
and, instead of editing the user's data, it lets the server do the editing.

However, the client must also interpret user requirements. When the user wants to add a record, the client program first
displays a blank input screen. The user enters data, and the client sends an ADD request to the server. If the user wants to
copy a record, however, the client program first sends a GET request to get the original record and displays the data to the
user. The user then enters new data, and the client again sends an ADD request. If there are errors in either case, the client
receives them from the server and displays them to the user.

The other strategy is server/client architecture. In this configuration, the user requests a program, such as item maintenance.
The user interface submits a call to that program, which typically runs in batch and perhaps on another machine. The program
that runs in batch is almost exactly like the original monolithic program, except that instead of talking directly to a screen, it
sends requests to the user interface. For example, wherever the program would originally do an EXFMT to a screen, it calls a
program that sends the data fields to the user interface. The user interface then displays the data to the user, waits for input,
and sends the user data back to the caller. In effect, the user interface is a display server, responding to requests from the
"client" program running in batch.

Each approach has its benefits. If your goal is simply to change the mechanics of the user interface, server/client architecture
is easier to implement. Servlet technology is one of the most talked about approaches today; the original programs simply
speak HTML instead of 5250. (This is a bit oversimplified but close enough for the purpose of this chapter.)

On the other hand, the client/server approach is the first step toward a truly object-oriented environment. Any program can
use the server used by the item maintenance client. You begin to encapsulate access to your database within single
programs. In a distributed environment, controlling access to your database is vital.

Having introduced the two architectures, I'll immediately discard one. Server/client architecture has its uses but requires no
real architectural savvy: Replace screen I/O op codes with calls to a program that sends a message containing the screen
data and write a program that accepts those messages and displays them on the screen. When the user hits Enter, do the
same process in reverse. This can be automated. Programs that can split an existing monolithic RPG program into user
interface server and business processing client have been written.

In contrast, splitting a program into user interface client and business rules server takes more effort but is ultimately far more
powerful. In this chapter, I do just that for a very simple master file maintenance program.

Team-Fly
Team-Fly

T h e O rig in al P ro g ram
For this example, I wrote a simple maintenance application that maintains a simple item master file. The item master file has
five fields: ITEM NUMBER, ITEM DE SCRIPTION, QUANTITY ON HAND, INVENTORY UOM (unit of measure), and SELLING
UOM. The application has two other files as well: the UOM master file and UOM cross-reference file, which contains
conversions (e.g., pounds to ounces).

My business rules are simple, too:

 Duplicate item numbers cannot exist.

 Descriptions cannot be blank.

 Quantities cannot be negative.

 UOMs must exist.

 Inventory UOM and selling UOM must have a valid cross-reference.

S tru ctu re
I've written the original, monolithic program ITMMNT to be called by another program, such as an item list panel. ITMMNT
takes an op code, item number, and return code. The structure is very straightforward, as shown in Figure 22.1.

F ig u re 22.1: The pseudocode for the original, monolithic program is straightforward. .

The design is simple yet can maintain just about any master file where all fields fit onto a single screen. Errors are handled
via a message subfile, which can display multiple errors. I also wrote a front-end program that prompts for an item number and
performs an operation based on the command key pressed (see Figure 22.2).
F ig u re 22.2: The item select program allows the user to enter an item number and select the action to
perform.

For example, by pressing Enter, I get the View mode shown in Figure 22.3. If I press F10 instead, I get Modify mode, as in
Figure 22.4. In Modify mode, the nonkey screen fields are now unprotected, so that I can change them. I can press Enter to
edit my changes or F6 to edit and post them, assuming there are no errors. Errors cause a screen like the one in Figure 22.5
to display, showing invalid fields in reverse image and displaying error messages at the bottom of the screen. F3 or F12 will
exit the screen.

F ig u re 22.3: In View mode, all entry fields are protected.

F ig u re 22.4: While in Modify mode, only the key fields are protected.
F ig u re 22.5: If errors are encountered, the invalid fields are highlighted and the messages are displayed in a message
subfile.

Team-Fly
Team-Fly

S p littin g T h e P ro g ram
In the client/server model, I need a client that performs user interface and a server that performs database access. The
following sections show how that split is accomplished.

T h e C lie n t
The client changes very little. After removing all database files, the first 100 or so lines are virtually identical. You add data
structures to support the middleware and initialization and exit calls. The basic program structure remains the same.

S tru ctu ral C h an g e s


The program doesn't stay exactly the same, but the changes aren't extensive. For example, the GETITM routine, which
attempts to retrieve the requested item, is modified to request the item from the server rather than access the database
directly. Figure 22.6 shows the changes. The CHAIN is replaced with two program calls: one to send the request and another
to receive the response.

F ig u re 22.6: To break apart your monolith, you must separate your business logic from the display
logic.

The other primary change comes in error handling. In the original program, the PROCESS subroutine first calls an EDIT
subroutine and then an UPDATE subroutine (assuming no errors). The EDIT subroutine checks each business rule and, if one
is broken, sends an error message. In the client/server model, there is no EDIT subroutine.

Instead, the data is sent to the server with two additional pieces of information: the operation required (ADD, UPDATE,
DELETE) and whether it is edit-only or edit and update. The server checks every field and returns any error messages. The
client simply relays those errors to the user. See Figure 22.7 for an example of the changes. (With edit and update, the server
also performs the requested master file I/O if there are no errors.)
 

F ig u re 22.7: It is the responsibility of the client to relay messages to the user.

In the monolithic program, code like this exists for each business rule, setting a specific error indicator and sending a specific
hard-coded error message.

Team-Fly
Team-Fly

T h e S e rv e r
To create the server, I just copy my EDIT and UPDATE subroutines and do a little rearranging. In the original program, the
same database routines are called for every mode, so the routines check the mode indicators to determine what to do. The
server, however, has a slight advantage because it is passed an op code right away, telling it whether to get, add, modify, or
delete a record.

S tru ctu re
The program is highly modular. There are four primary routines: GET, ADD, MODIFY, and DELETE. GET is sort of on its own;
it attempts to retrieve the record and either returns the record with success or returns an error if the record is not found. The
other routines share some subsidiary routines, as shown in Figure 22.8.

F ig u re 22.8: The structure of the maintenance program is very modular.

In all cases, each error causes an error message to be sent to the client using the DQMSSND middleware program (see the
"Middleware Programs" subsection) rather than to a message subfile. After all editing is done, a final result record is sent
reflecting the overall status of the request.

Team-Fly
Team-Fly

M id d le w are
Middleware transports requests from client to server and transports responses from server back to client. In my example, a
single message structure is used for all messages, and all programs use a common error message structure.

Clients execute initialization once at the beginning of the program to establish a session and exit at the end to shut down the
session. In between, they make as many requests as they need by executing the Client Send program to send data to a
server and Client Receive to receive responses.

Servers receive the request message as their entry parameter. They send their responses back to the client with the Server
Send program. Errors are sent one per message, using the predefined error message structure.

M e ssag e S tru ctu re


In this simple application, a message has eight fields:

 The session ID is assigned to the client during initialization.

 The server ID identifies the request target. (There is only one server in this case, but a client may talk to many servers in
a single session.)

 The segment code controls multiple-message requests or responses.

 The operation code identifies the operation requested.

 The operation subcode modifies the operation requested.

 The return code indicates the success or failure of the request.

 The return subcode extends the return code when necessary.

 The message data contains the actual data specific to the request. (For example, for master file maintenance, it contains
the record image of the master file.)

E rro r S tru ctu re


The error structure is a special structure designed to return field-specific error information to the client. If the return code
indicates an error on a file maintenance request, the message data contains the error structure. Multiple errors can be
received, one per message. The error structure has only three fields: FIELD NUMBER, MESSAGE ID, and MESSAGE DATA.
The field number is the index of the field causing the error. Note that the client and server must agree on which field these
numbers represent.

M id d le w are P ro g ram s
The application uses five simple programs as its API (all programs and fields in the API start with DQM, which stands for Data
Queue Messaging):

 DQMCINIT is called at the beginning of a session to create a session ID (and response data queue).

 DQMCSND sends a message from the client to the server.

 DQMCRCV receives a response from the server.

 DQMCEXIT is called at the end of the session to delete the data queue.

 DQMSSND sends a response from the server to the client.

Although this seems excessive, all five programs (and two subprograms) total less than 100 lines of code.

Team-Fly
Team-Fly

T h e S cre e n s R e m ain T h e S am e
You may have noticed that I don't have a figure showing screens for the client/ server version of the program. There's a good
reason for that: Those screens are exactly the same as the monolithic screens. Externally, the programs are exactly the
same. However, you now have a client that can easily be cloned and modified and a server that can be called to do file
updates while adhering to business rules.

The programs went from 229 lines of code for the monolithic program to 402 lines for the client and server, with another 90 or
so lines of middleware. This might seem like a big increase for no apparent gain, but that's not really the case. Those roughly
200 additional lines of code required for the client and server are pretty much all that will ever need to be added to make any
program into client/server. Programs that are more complex will not require that much more additional coding, and you still
get all the benefits of a truly distributed client. To see one of the benefits, read Chapter 23, "The Business of Java," which
redeploys the client in Java on the workstation.

Team-Fly
Team-Fly

W h e re D o W e G o F ro m H e re ?
Technology is racing ahead. Those who live on the bleeding edge are changing their methodologies quicker than their socks.
Last week's solution was applets; this week it's servlets. We've gone from Write Once, Run Anywhere (WORA) clients to
rewriting your entire legacy application in Java (not to mention replacing all those green-screen terminals with PCs). RPG
programmers are nervous, IS managers are confused, and users are sure they aren't getting all the benefits they should be.
What's an IS department to do?

My idea is to leverage everything we have and slowly move forward. We break the monolith into small, manageable pieces of
code and then move forward. We provide both green-screen and GUI clients while using the bulk of our existing legacy code.
RPG programmers work on servers while Java programmers redevelop our interfaces on the workstation. And this is any
workstation, from Macintoshes to Linux machines. Cloned code is eliminated while functions are enhanced, and the
workstation wizards build applications we never even dreamed of, combining images and sound with the good old business
data we've grown to depend on. That business data comes from the programmers who've been with you the longest.
Remember, most, if not all, of your application knowledge is in the heads of your legacy programmers; this is an irreplaceable
resource. Any methodology that makes them obsolete is a recipe for disaster.

Object technology? We'll get there. There's a perfectly acceptable interim technique called "wrappering" that encapsulates
existing legacy code into objects that can then be used by technologies such as Enterprise JavaBeans (EJB). What's the first
step? Separating the user interface from the business processing logic, just as I've done in this chapter.

Don't let the snake-oil salesmen tell you to get rid of your legacy code. They've tried that several times already. Today's magic
elixir is Java and JDBC, WORA, and EJB. Tomorrow's may be something different. Don't predicate your future on the latest
quick-fix technology. Remember, there is no silver bullet, and there is no quick answer. Success is a journey, not a
destination, and one we can all travel together.

Team-Fly
Team-Fly

C h ap ter 23: T h e B u sin ess o f Java


O v e rv ie w
JOE PLUTA

All right, I'll admit it. This chapter came about as an answer to the current wisdom that Java can't do business applications.
Yes, indeed, I've heard those words so many times now that they're getting under my skin just a little bit. Yep. I've talked
myself blue in the face trying to answer the naysayers, but it finally became obvious to me that I had to put my money where
my mouth is.

Well, folks, I'm here to say that Java does business. However, I need to clarify that a bit. I'm not saying you should use Java
and object-oriented programming (OOP) for everything and throw away all that you've ever learned about RPG (or COBOL, for
that matter) and business applications. In my opinion, Java isn't at that point yet, and neither is object technology (it's
coming, though). Instead, Java provides the impetus to finally create those client/server applications programmers have talked
about for so many years.

Team-Fly
Team-Fly

T h e C lie n t/S e rv e r P arad ig m


In true client/server architecture, a client controls the user interface and sends requests to a server to perform all database
functions. Many other models can be used, but none of them are the focus of this chapter, and hopefully I can explain why I
believe client/server to be so important.

With client/server, the client is free to request whatever data it chooses from the server. That means that, while you're
converting your legacy systems, you're also providing servers for brand-new, previously unthought-of applications. Servers are
essentially software components that provide relevant data on request without the client application's having knowledge of the
actual database. (Note that this is also the first step toward object technology, freeing the client application programmer from
the business rules.)

In most other distributed models, the user is trapped into whatever business flow the host programmer decides is important,
and the user interface is a very strict replica of the old green-screen approach. In a client/server model, however, there is
much more flexibility. A client programmer can use all the tools available to her on the workstation. For example, she can
easily program the ability to drag and drop a customer number onto a form, which will trigger the customer's mailing address
to be added. This sort of freedom simply isn't available with the generic "facelift" architectures.

Team-Fly
Team-Fly

W h y W o ra?
Write Once, Run Anywhere (WORA) is the carrot that can justify the effort of reengineering for client/server. When I first
designed client/server applications back in the early '90s, the only operating system that was robust enough for such use was
OS/2. Unfortunately, after programmers made the decision to develop for OS/2, they were locked into that platform. As OS/2's
fortunes dwindled, so did those of some wonderful graphical products. And that signaled the end of the client/server strategy
for many years. It's really too bad, now that I look back on it, because had the company continued to develop along those
lines, it would have been poised to take over the world with the advent of Java.

You see, with Java, I no longer have to worry about my target platform. If I stick with the core classes, such as Swing (also
known as the Java Foundation Classes, or JFC), I know that my clients will run on any platform, anywhere-OS/2, Windows,
Mac-OS, UNIX, Linux, it doesn't matter. Java is becoming ubiquitous; someday, I'll be able to run my applications on my
toaster.

Team-Fly
Team-Fly

W h at A b o u t T h e S e rv e r?
Ah, herein lies the rub, and much of the confusion about Java. Somehow, the goal has become to quickly rewrite all of your
legacy code to Java, but that simply isn't necessary or even advisable in most cases. In our particular niche, that of the
AS/400, server-side Java simply isn't ready for prime time yet, and the other option of transferring all of the business logic to
the workstation is a poor design choice. One simple reason is that, by keeping all the business rules on the server, you don't
have to worry about distribution issues. If the business logic is on the workstation, business-logic changes must be
distributed to every client in the network. Distribution of upgrades never happens uniformly, which leads to having outmoded
business logic on some of your clients. Therefore, the business logic should remain on the server, and for now, at least,
traditional programming languages, such as RPG, are the best tools for server-side development.

My personal choice is to design client applications written in Java on the workstation that communicate with servers written in
RPG on the AS/400, using data queues to pass messages back and forth. I use IBM's AS/400 Toolbox for Java for the
necessary classes to connect to the AS/400, to call my message APIs, and to convert between AS/400 data types and Java
data types. That said, I'm going to show you how to design a Java user interface that means business.

Team-Fly
Team-Fly

W h at's R e ally In A n In te rface ?


In a 24 x 80 green-screen business environment, there are really only a few basic interface types. For the most part, you have
single-panel inquiry and entry, multiple-panel inquiry and entry, and subfile inquiry and entry. Anything else is a combination
of these basic types. (The difference between single- and multiple-panel entry is that fields from one panel need to be
validated in conjunction with fields from another; the difference between single- and multiple-panel inquiry is semantic.)

My example is going to use one of the simpler interface types but one that demonstrates most of the issues involved in
interface design: the single-panel entry interface. In its simplest form, the single-panel entry interface consists of the following
components:

 Output fields-These can include things such as company name, user ID, date and time, and so forth. The user never
modifies them.

 Entry fields-These are the standard data fields. They include numeric and alphanumeric fields.

 Function k eys-This is usually how the user indicates what to do next.

 Error messages-Sometimes overlooked, error messages are essential to a business application.

I've deliberately left out a few things, such as help text and support for double-byte character sets, to fit all this in one chapter.
These issues are important, but they can be dealt with at another time.

Team-Fly
Team-Fly

S o H o w D o I Im p le m e n t T h e se T h in g s In Jav a?
Standard components in the JFC can be used to mimic the AS/400 screen features. For example, a text field is the
equivalent of an input-capable field on the AS/400, while a label can be used in place of an output-only field. JB u tto n s
generally replace function keys. The furthest stretch is the message subfile on the AS/400, but it can be adequately replaced
by a drop-down list.

I've created an application called Ite m M a in ta in e r that acts as the client for item master maintenance. For comparisons,
please refer to Chapter 22, "Breaking Apart the Monolith." The Ite m M a in ta in e r client communicates with the RPG server
designed in that chapter. The first four figures in this chapter are the Ite m M a in ta in e r GUI replacements for Figures 22.2 to
22.5 in that chapter.

Figure 23.1 shows the front-end program, which prompts for an item number. I select the operation to perform by pressing the
appropriate button.

F ig u re 23.1: The item select program allows the user to enter an item number and select the action to
perform.

If I press View, I get a View panel, as shown in Figure 23.2.

F ig u re 23.2: In View mode, all entry fields are protected.

If I press Revise instead, I get the Revise panel in Figure 23.3.

F ig u re 23.3: While in Revise mode, only the key fields are protected.

Notice that in Revise mode, the nonkey screen fields are now unprotected, so I can change them. At this point, I can hit Edit
to simply edit my changes or Accept to accept them and try to post them (assuming there are no errors). If there are errors, a
screen like Figure 23.4 is displayed, with the prompts for the invalid fields in red and a drop-down list with all the error
messages. At any point, I can simply close the window to cancel (not undo!) any changes.
F ig u re 23.4: If errors are encountered, the invalid fields are highlighted and the messages are displayed in a drop-down
list.

One key difference between the Java client and the AS/400 client is that, on the workstation, the user can have multiple
maintenance windows all running at the same time, something that is all but impossible on the AS/400. As I noted earlier, a
good programmer will allow drag and drop between fields; think how beneficial that would be when trying to copy a few key
fields from one item or one customer to another.

Team-Fly
Team-Fly

G re at! W h e re 's T h e D D S F o r T h e se S cre e n s?


Java doesn't really have a DDS. You can get an integrated development environment that helps you create forms, but I am
highly averse to those for reasons that are outside the scope of this chapter. And to be honest, it's not that difficult to put
together a Java panel from scratch, especially if you have some base classes to work with.

If you have a strong PC background, you may have noticed some things about the panel that aren't exactly standard. For
example, my protected fields have a black background, and the text for the prompts turns red for fields that are in error. These
are features of a base class I've developed called E n tryF ie ld ld. If you don't like my conventions, you can make your own by
modifying or extending the class; if you do like them, you can use them as they exist. I've also created two other classes,
V e rtica lE n tryF ie ld P a n e l and B u tto n P a n e l. These classes make it pretty simple for me to throw together a single-panel
entry screen. About 230 lines of code in total, these classes can be used by any program that needs a standard look for its
entry panels.

The other utility class used in this application is the D q m S e ssio n class, which provides all the support needed to
communicate with the AS/400. This class is another 158 lines, but like the interface classes just mentioned, it doesn't need
to be modified to be used in another application.

Together, these base classes provide the underlying support for the classes that actually make up the Ite m M a in ta in e r
application, sort of the way RPG and DDS provide built-in support for database access and screen I/O, respectively.

Team-Fly
Team-Fly

W h at's In A Jav a C lie n t?


On the AS/400, the program ITMSEL displays the item number prompt, then calls ITMCLT with the item number and the
appropriate operation code (ADD, MODIFY, COPY, DELETE, or VIEW). ITMCLT displays the item entry panel, sending
requests to ITMSRV for database access. The idea is similar on the workstation, though encapsulated in classes. These
application classes require a little more than 350 lines of Java.

The Ite m M a in ta in e r class is a very simple application class. It displays a panel with one entry field and five buttons (Add,
Revise, Copy, Delete, and View). Rather than testing to see which function key has been pressed (as you would in an RPG
program), in Java, each button has a listener assigned to it that is invoked when the button is pressed. Each of the buttons in
Ite m M a in ta in e r has a listener that creates a new instance of Ite m P a n e l and then executes the appropriate method,
passing the item number if appropriate. (The fact that each listener creates a new instance of Ite m P a n e l is what allows
Ite m M a in ta in e r to launch many item maintenance panels concurrently.) Figure 23.5 shows the code for Ite m M a in ta in e r in
its entirety.

 
 

F ig u re 23.5: ItemMaintainer, at less than 100 lines, replaces the ITMSEL program (and its DDS) on the AS/400. (part 1
of 2)

Ite m P a n e l is the equivalent of ITMSRV on the AS/400. (Figure 23.6 shows the code snippet that creates the Ite m P a n e l
user interface; observe how easy it is to configure a completely different interface using the same utility classes as
Ite m M a in ta in e rr.) The vie w () method simply gets the item and shows it to the user, hiding the buttons. The user can exit
only by closing the window. The other methods get the selected item and move its data to the entry fields (except for a d d (),
which clears all the fields), protecting whichever fields need to be protected. They then show the panel. In addition, they set
the request op code for the Edit and Accept buttons. The a d d () and co p y() methods set the op code to WRITE, re vise sets it
to UPDATE, and d e le te sets it to DELETE. When one of these buttons is pressed, the appropriate request is sent to the
server by a call to the Ite m class. Upon return, any errors are displayed, and the corresponding fields are highlighted.

F ig u re 23.6: It's easy to configure a completely different entry panel using the base classes EntryField,
VerticalEntryFieldPanel, and ButtonPanel.

The Ite m class is the final piece of the client. It is basically a surrogate for the ITMSRV server on the AS/400. The Ite m P a n e l
class makes a request, which is forwarded via a call to DQMCSND, and the responses are retrieved via DQMCRCV. The Ite m
class is responsible for converting the AS/400 data types for the item record to Java data types and back, but that's pretty
much all it does.

Team-Fly
Team-Fly

A S id e B e n e fit
An often overlooked side benefit of moving to client/server technology is the immediate hardware cost savings. By moving your
green-screen 5250 applications to Java clients, you reduce your interactive load on the AS/400, thereby allowing you to
choose a less expensive server model. Now you have inexpensive workstations talking to a less expensive server and still
have the same great performance. Yet another benefit of the client/server architecture is that you can deploy green-screen
clients beside workstation clients using the same servers, phasing out your dumb terminals as you see fit, rather than forcing
an en masse cut-over.

Team-Fly
Team-Fly

A G o o d S tart
Although not the quick fix of a facelift server/client approach, true client/server technology can produce immediate benefits by
reducing interactive workload without any mass disruptions of either hardware or software. And, unlike the server/client route,
this is not an architectural dead end but, rather, the first step in an evolutionary road to object technology.

While most can agree that the ideal of distributed object processing has long been one of the ultimate goals of computing, the
worry has always been that it's too dangerous and expensive a destination. Well, it's finally a journey you can afford to begin
today. In fact, it may well be a journey you can't afford not to take.

Team-Fly
Team-Fly

C h ap ter 24: C allin g R P G F ro m Java


O v e rv ie w
MICHAEL POLUTTA

I've read dozens of articles on Java and a couple of books, pored over the documentation, and written numerous example Java
programs, but I want to be able to call my legacy RPG program from Java! I have this intricately crafted date routine that is a
work of art, and I want to call it from my Java application. Well, IBM's AS/400 Toolbox for Java enables program calls. You
can pass parameters in, receive parameters back, or pass parameters in and get them back. The AS/400 Toolbox for Java
makes it easy. In this chapter, I'll show you how to call your legacy application programs from Java. For context, I used IBM's
VisualAge for Java (VAJ) Enterprise Edition Version 1.0.1. The Java Toolbox was included on the CD-ROM as part of the
AS/400 feature.

Team-Fly
Team-Fly

W h at Is T h e A S /400 T o o lb o x F o r Jav a?
The AS/400 Toolbox for Java is a set of classes from IBM that enables a variety of AS/400-specific access methods. For
instance, you can use the AS/400 Tool- box for Java to enable both record-level database access and AS/400 Integrated File
System (AS/400 IFS) access. The classes contained in the AS/400 Toolbox for Java will also let you access user spaces,
send and receive data queue entries, run commands and receive any generated messages, and call your legacy AS/400
programs. To enable program calling, IBM provides the P ro g ra m C a ll object. To send and receive parameters, you call your
program with either a single P ro g ra m P a ra m e te r object or an array of P ro g ra m P a ra m e te r objects. You can also call a
program with no parameters if none are required.

Team-Fly
Team-Fly

W h at's In v o lv e d ?
There are two ways to generate a program call. The first method is to handle all of the work yourself using the AS/400 Toolbox
for Java classes. The second is to use the Program Call Generator, which is a utility program provided as part of the AS/400
feature of VAJ. I'll show you how to call a simple program using the toolbox classes, then give a brief overview of using the
Program Call Generator.

For this example, I wrote a simple RPG IV program (Figure 24.1) that receives a packed-decimal field (e.g., 5,2), increments it
by 10 into a zoned-decimal field, then uses the %EDITC function to edit the zoned number into a 15-byte character field.
There are seven basic steps to call a program from Java:
1. Define a connection to the AS/400.

2. Define the path to the object.

3. Define a P ro g ra m C a ll object.

4. Define your list of P ro g ra m P a ra m e te r objects.

5. Set your P ro g ra m C a ll options.

6. Call your program.

7. Handle any errors or interpret the returned parameters.

F ig u re 24.1: The XMPCALR3 RPG program accepts two parameters: packed and character.

Team-Fly
Team-Fly

T ake A C lo se r L o o k
Now, I'll examine the class E x a m p le P ro g ra m C a ll in Figure 24.2. Since many of the classes in the AS/400 Toolbox for Java
throw exceptions, all of this method's code is contained in a TRY block. The class receives the name of the AS/400 to
connect to as a parameter. This is usually supplied in URL format. There are several different constructors for the AS400
object. The idea is that if you just supply the name (URL) of the AS/400 when you first try to connect, the AS/400 will ask for
the user profile and password. (Don't worry too much; the password is encrypted. This is not the case if you're using terminal
emulation on your network; those passwords are fair game for any network sniffer.) However, with my version of VAJ, the
prompt never would come up, even if it does outside the VAJ integrated development environment. To get around this VAJ
problem, I supplied the user profile and password in the source (Label A of Figure 24.2).

F ig u re 24.2: The ExampleProgramCall constructor encapsulates the implementation to call


PROGRAMLIB/XMPCALR3.

The next task is to define the path to the program object with the Q S Y S O b je ctP a th N a m e (Label B). You supply the library,
object name, and object type. The Java server uses this AS/400 IFS path to find the OS/400 program object that is in the
QSYS library system of your AS/400.
Next, you create the P ro g ra m C a ll object with the AS400 object you declared earlier (Label C). You can declare a
P ro g ra m C a ll object without any parameters, but you'll have to supply the system, program object, and parameter list later.
You can declare a P ro g ra m C a ll object with all three. Since the parameter list hasn't been set up yet, just use the
constructor that takes the AS400 object.

Now, define the parameter list (Label D). Since there are two parameters, declare an array of P ro g ra m P a ra m e te r objects.
The first parameter is a 5,2 packed decimal number. Here is where you use one of the conversion classes, as shown in Table
24.1. The binary representations for the data of the parameters of an AS/400 program are very different from those of the basic
data types and objects of a Java program. The biggest task of using P ro g ra m C a ll is converting between Java data types and
AS/400 data types.

T a b le 24.1: C o n ve rsio n C la ss D e scrip tio n

Ja va C la ss D e scrip tio n
AS400Text Java String objects and AS/400 text.
AS400Bin2 Java short object and AS/400 signed two-byte binary number.
AS400Bin4 Java integer object and AS/400 signed four-byte binary number.
AS400ByteArray Java byte array and AS/400 fixed-length byte array.
AS400Float4 Java float object and AS/400 four-byte floating-point number.
AS400Float8 Java double object and AS/400 eight-byte floating-point number.
AS400UnsignedBin2 Java integer object and AS/400 unsigned two-byte binary number.
AS400UnsignedBin4 Java long object and AS/400 unsigned four-byte binary number.
AS400PackedDecimal Java BigDecimal object and AS/400 packed decimal number.
AS400ZonedDecimal Java BigDecimal object and AS/400 zoned decimal number.

To help meet this need, the AS/400 Toolbox for Java provides a number of AS/400 conversion classes. Java does not provide
packed-decimal numbers, but it does provide a fixed-decimal number class called B ig D e cim a l. The gap between Java's
B ig D e cim a l class and the packed-decimal format on the AS/400 must be bridged. Generally speaking, to convert from a
Java type to an AS/400 type, you use to B yte s() s(). To convert from an AS/400 type to a Java type, use to O b je ct()
ct(). In my
example, I declare an A S 400P a cke d D e cim a l of the proper size. Then I create a B ig D e cim a l object with the value to pass to
the program, convert it to the AS/400 format with the to B yte s() method, and store this in a byte array. This byte array
becomes the first P ro g ra m P a ra m e te r array element.

Since the second parameter is returned from the caller, you only have to allocate sufficient space to hold the result. So,
declare the second P ro g ra m P a ra m e te r array element to be 15 bytes long. Now that the parameter list has been set up, the
setup of the P ro g ra m C a ll object can be completed (Label E). Use the se tP ro g ra m () method to do this.

Team-Fly
Team-Fly

M ake It S o !
All that is left to do is run the program and check the result. To run the program, just use the ru n () method (Label F). Assume
that everything ran as planned. To investigate the value returned in the second parameter, you have to do some more work.

First, retrieve the parameter value into a byte array using the g e tO u tp u tD a ta () method. Then, convert that byte array into a
S trin g object with the to O b je ct() method of the A S 400T e x t converter class, casting the result to a S trin g . If things don't go
as planned, the example will list all the messages returned by the called program on the AS/400. You can see how easy this
is (Label G). Simply declare an array of A S 400M e ssa g e objects and tell the P ro g ra m C a ll object to get the list of AS/400
messages with its g e tM e ssa g e L ist() function. Then you simply iterate over the message array, retrieving the text of each
message object.

Team-Fly
Team-Fly

B u t W ait, T h e re 's M o re !
Pretty easy, huh? Yeah, but we AS/400 types are spoiled. IBM really wants us to adopt Java, so Big Blue has made it even
easier. Take a look at Figures 24.3 and 24.4. IBM supplies a SmartGuide (a wizard in the rest of the Windows world) to
create an AS/400 program call. What's really cool is that the SmartGuide is actually a Java application that uses the Java
Runtime Environment (JRE). On the first panel (Figure 24.3), you specify the program name and location. You also specify
where on your PC you want the generated code to go.

F ig u re 24.3: VAJ's SmartGuide for creating a ProgramCall object prompts for the class name to create and the name
and location of the AS/400 program.

On the second panel (Figure 24.4), you define the list of parameters to pass. A drop-down list contains all the valid data
types. Once you've completed those tasks, the SmartGuide generates a *.ja va file that you can then import into VAJ (or the
environment of your choice).

F ig u re 24.4: VAJ's ProgramCall SmartGuide makes it easy to specify AS/400 program parameters and their associated
Java data types.

That's right. The SmartGuide generates stand-alone Java code that is not tied to VAJ. You will have to create a m a in ()
method for the generated class, but all of the methods needed to perform the task will be there. And, believe it or not, the
generated Java code is pretty readable.

Team-Fly
Team-Fly

P ack It U p A n d T ake It H o m e (O r T o W o rk!)


IBM has really worked hard to make Java accessible to AS/400 programmers and the AS/400 accessible to Java
programmers. P ro g ra m C a ll is just one example. As I have shown, there are several critical AS/400 technologies available for
Java access. With a little creativity, you can take your modular designs on the AS/400 and put a GUI face on them using Java
and P ro g ra m C a ll. Or, to put a new twist on an old phrase, "Run on the client what should run on the client, and run on the
AS/400 what should run on the AS/400!"

Team-Fly
Team-Fly

C h ap ter 25: In vo kin g R P G V ia JD B C


O v e rv ie w
DON DENONCOURT

In Chapter 24, Michael Polluta explains how to invoke RPG programs with the P ro g ra m C a ll class. In this chapter, I present
another strategy for calling AS/400 programs using JDBC SQL stored procedure calls.

So why yet another strategy for calling RPG from Java? One problem with using the P ro g ra m C a ll class is that it uses a Java
package that is AS/400-specific: co m .ib m .a s400.a cce ss ss. The JDBC stored procedure call method uses a Java package that
comes standard with Java: ja va .sq ll. This gives you two advantages. First, non-AS/400 programmers are already familiar with
JDBC and stored procedures. And second, if the host system ever changes to a non-AS/400 platform, the Java classes won't
have to be modified. Originally, before I tested the JDBC stored procedure call, I thought that this strategy would reduce the
requirement for classes from the jt4 0 0 .ja r file, but, in practice, the AS/400 Toolbox for Java's JDBC driver internally uses
many of the same classes to perform such things as Java object-to-EBCDIC conversions.

Team-Fly
Team-Fly

S to re d P ro ce d u re s
In reality, you don't directly call legacy AS/400 programs from Java applications; instead, you call a stored procedure. But
RPG programs can easily be registered as a stored procedure using SQL's CREATE PROCEDURE statement. If you look at
my example Java application in Figure 25.1, you can see in the constructor method-after registering the JDBC driver and
getting a C o n n e ctio n object-that I create a stored procedure with a call to the cre a te S ta te m e n t method:
con.createStatement().execute(
"CREATE PROCEDURE denoncourt.inv001 " +
" (INOUT zonedField NUMERIC (6, 0), " +
" INOUT packedField DEC (9, 2), " +
" INOUT char20Field CHAR (20 )) " +
" LANGUAGE RPG ");

F ig u re 25.1: JDBC's CallableStatement class can be used to invoke AS/400 RPG programs .

You can call the procedure anything you want, but if it is anything other than the program name, you'll need to add an
EXTERNAL NAME clause. The parameters to the program must be specified with care. They are identified parenthetically
following the procedure name as IN, OUT, or INOUT with the parameter name, the data type, and attributes.

If you look at my INV001 RPG program shown in Figure 25.2, you can see that parameter one is zoned 6,0, parameter two is
packed 9,2, and parameter three is character 20. Through trial and error, I discovered that NUMERIC works well for zoned
numbers and DEC works well for packed parameters. SQL has far more numerical data types than zoned and packed, such
as integer, long, float, and double, but most AS/400 application programs do not use those data types. All three of the
parameters to my INV001 RPG program are used as both input and output.

F ig u re 25.2: The INV001 RPG program has zoned, packed, and character parameters.

The last clause of the CREATE PROCEDURE statement identifies the language used to implement the stored procedure. In
this case, it's RPG, but it can also be C, CL, COBOL, COBOLLE, C++, FORTRAN, PLI, REXX, or RPGLE. Take note that
you can use the DROP PROCEDURE statement to delete existing stored procedures.

You really do not want to create the procedure in your Java code as I did; it should be created once. The best thing is to
create the procedure using SQL/400's interactive screen. That way, you get the syntax errors up front and you also have the
online help. But if you don't have SQL/400, you might create a Java utility class that creates your stored procedures.

Team-Fly
Team-Fly

JD B C C lasse s
The JDBC class that is used to encapsulate the program call is C a lla b le S ta te m e n t. A C a lla b le S ta te m e n t object is
obtained from a call to the C o n n e ctio n class's p re p a re C a ll method. The CALL statement simply identifies the stored
procedure name with a set of question mark (?) placeholders to represent variable parameters enclosed within parentheses:
CallableStatement inv001 =
con.prepareCall("CALL denoncourt.inv001 (?,?,?)");

Note that some of the parameters can have values hard-coded, but those constant values can also be used for input-only
character data type parameters.

The C a lla b le S ta te m e n t object's e x e cu te U p d a te method is used to call the stored procedure, but before you do that, you
need to register all the output parameters; otherwise, you'll receive an S Q L E x ce p tio nn:
inv001.registerOutParameter(1, java.sql.Types.NUMERIC);
inv001.registerOutParameter(2, java.sql.Types.DECIMAL);
inv001.registerOutParameter(3, java.sql.Types.CHAR);

I registered the INV001 parameters in the constructor, but I invoke the stored procedure in a method appropriately called
ca llIn v001
v001:
void callInv001(BigDecimal zonedIn,
BigDecimal packedIn,
String char20In)

Each of the three arguments to the ca llIn v001 method corresponds to the parameters of the INV001 RPG program. The
ca llIn v001 method uses its arguments to set the parameters of the INV001 RPG program, calls the program, and then
retrieves the return values. Stored procedure parameters are set with the setter methods of the C a lla b le S ta te m e n t class, as
shown in Figure 25.3. (Actually, these setter methods are from the C a lla b le S ta te m e n t parent class, the
P re p a re d S ta te m e n t class.) The following three methods set the values of the first, second, and third parameters of INV001
from the values of three arguments passed to the ca llIn v001 method:
inv001.setBigDecimal(1, zonedIn);
inv001.setBigDecimal(2, packedIn);
inv001.setString(3, char20In);

F ig u re 25.3: The CallableStatement class inherited its setter methods from its parent class,
PreparedStatement.

Team-Fly
Team-Fly

M an y H ap p y R e tu rn s
The ca llIn v001 method of the JD B C C a lla b le S ta te m e n t class then invokes the e x e cu te U p d a te method of the in v001
C a lla b le S ta te m e n t object to call my INV001 RPG program. After calling the stored procedure, you need to retrieve the
returned values. The ca llIn v001 method uses a few of the getter methods from the C a lla b le S ta te m e n t class (shown in
Figure 25.4) to retrieve the parameters modified by INV001:

F ig u re 25.4: Return values from your RPG program are retrieved from calls to the CallableStatement object's getter
methods.

BigDecimal zonedOut = inv001.getBigDecimal(1, 0);


BigDecimal packedOut = inv001.getBigDecimal(2, 2);
String char20Out = inv001.getString(3);

All the getter methods except for the g e tB ig D e cim a l method have only one argument: an integer that is used to specify the
index of the question mark placeholder parameter of the CALL statement specified in the p re p a re C a ll method. The
g e tB ig D e cim a l method's second argument is where you specify the decimal precision. The first INV001 parameter is a
zoned field with no decimals, so the second argument to the g e tB ig D e cim a l method is 0 (zero). The second INV001
parameter is a packed field with two decimals, so the second argument of g e tB ig D e cim a l is set to 2. Note that the
g e tB ig D e cim a l method works for both the NUMERIC and the DEC parameters of the INV001 stored procedure.

The JD B C C a lla b le S ta te m e n t class uses a m a in method to unit test itself. The m a in method bootstraps itself by instancing
a JD B C C a lla b le S ta te m e n t object and then invokes several invocations of the ca llIn v001 method:
inv001.callInv001(new BigDecimal("9"), new BigDecimal("4.57"), "bogus input");
inv001.callInv001(new BigDecimal("3"), new BigDecimal("0.23"), "garbage in");

Figure 25.5 shows the results.

F ig u re 25.5: You should create a Java class that is an object-oriented wrapper to your legacy program using standard
encapsulation techniques so that the class can be used over and over.

Team-Fly
Team-Fly

P ro g ram C all, P C M L , O r C allab le S tate m e n t?


IBM's AS/400 Toolbox for Java has a class called P ro g ra m C a ll, but that class is specific to the AS/400. If the stored
procedure is to ever reside on a platform other than the AS/400, it is best to use the cross-platform JDBC
C a lla b le S ta te m e n t class. However, the P ro g ra m C a ll class gives you far better feedback for abnormal program termination
because it throws exceptions such as A S 400S e cu rityE x ce p tio n and A S 400E x ce p tio nn. The PCML strategy is built on top of
the P ro g ra m C a ll class to reduce the complexity of setting and getting parameter values through an XML interface. I suggest
you use JDBC's C a lla b le S ta te m e n t if your application uses JDBC for data access, but use PCML when your app uses the
AS/400 Toolbox for Java's record-level access. Whichever method you use, be sure to always hide the implementation with at
least modular code, if not proper object-oriented programming techniques.

Team-Fly
Team-Fly

C h ap ter 26: T C P /IP S o ckets P ro g ram m in g


O v e rv ie w
JIM BARNES

Prior to RPG IV, the RPG developer could not develop a TCP/IP socket program without using C or some other language that
could bind to C functions. With RPG IV, you can now bind to C service program functions without having to resort to another
language and licensing an additional compiler for the AS/400. This chapter demonstrates the use of the C-based TCP/IP
socket functions in RPG IV applications.

Team-Fly
Team-Fly

S o , W h at A re T C P /IP S o cke ts A n y w ay ?
The UNIX operating system was developed with a series of communication interfaces to make the operating system
somewhat independent of the underlying network hardware, thus promoting interprocess communication, portability, and
openness of applications. These interfaces promoted plug compatibility and became known as sockets. A socket is an
endpoint connection for communications that can be named and addressed in a network. A socket is a unique number
assigned to an interprocess connection. That number consists of a machine's IP address and the port number selected for
the connection. Therefore, different machines can communicate on the same port since their IP addresses are different. Each
machine in a connection has a socket number that uniquely identifies the machine at the other end of the connection.
Through this socket number (also termed a sock et descriptor), a machine sends data to and receives data from another
machine. Each function invoked after the so cke t function (the function that assigns the number) will use the socket descriptor
to identify itself.

On the AS/400, the set of socket functions is available in the form of a service program, but on a PC, they are available as a
DLL. Table 26.1 presents each socket function needed to complete a typical conversation between two processes. As you
can see in the table, a server application needs to perform only a minimal set of the sockets functions: so cke t, se tso cko p t
(set socket options), b in dd, liste n , and a cce p t. A client application needs to perform only two of the sockets functions:
so cke t and co n n e ct.

T a b le 26.1: S o cke t A P Is

S o cke t fu n ctio n D e scrip tio n In vo ke d b y


socket() Creates a unique socket descriptor number. Client and Server
setsockopt() Sets socket options. Server
bind() Binds a socket to a particular IP address and port number. Server
listen() Places a listener on the port specified by the bind function. Server
accept() Accepts a connection required from another process. Server
connect() Connects a client to the server endpoint specified in the socket Client
address structure.
read() Reads data using the socket description returned by the accept Client and Server
function.
alphawrite() Writes data using the socket descriptor. Client and Server
close() Closes the socket descriptor, preventing further connection Client and Server
requests.

Both the client and server can perform re a d and w rite functions for two-way communication. And both are required to close
the connection to end the processes. Although Table 26.1 shows certain functions as being invoked only by the server
process, any of these functions may be invoked by the client as well; however, that would indicate a role change between the
two communicating processes.

Team-Fly
Team-Fly

F in d in g A n d B in d in g
To properly utilize socket functions, you need to become familiar with their arguments and return types. Most of the TCP/IP
sockets function prototypes can be found in the member called SOCKET of the SYS source file in the QSYSINC library. The
prototypes for the sockets' re a d and w rite functions can be found in the QSYSINC library in the UNISTD member of the
source file called H. The QSYSINC library is available as a free, optionally installable feature of the operating system
(5769SS1: OS/400-System Openness Includes). The include headers are required to determine the number of arguments
passed and the data types to be passed to the sockets functions (which are implemented in C), as well as values returned
from these functions. Only when your application program has access to this information can it be successfully bound to the
TCP/IP sockets functions.

Table 26.2 presents the function prototypes for the functions that will be used in the sockets programs. With the proper C
function prototypes in hand, you can map arguments passed and values returned to comparable data type definitions in RPG
IV. I used the C prototypes to develop the comparable RPG D-spec prototypes (see Figure 26.1) for the socket functions that
I will be using to implement this chapter's example sockets application. The complete RPG copy code for the socket function
prototypes is on this book's companion CD. The name of that copy file is $S o cke tsH . It contains not only the RPG D-spec
prototypes for the socket functions but also the TCP/IP constants that will be used as arguments to socket functions.

 
 

F ig u re 26.1: The C APIs are available from RPG given the appropriate set of RPG prototypes.

T a b le 26.2: S o cke t A P I P ro to typ e s

F u n ctio n P ro to typ e
socket() int socket_descriptor socket(int address_family, int type, int protocol)
setsockopt() int return_code setsockopt(int socket_descriptor, int level, int option_name, char*
option_value, int option_length)
bind() int return_code bind(int socket_descriptor, struct sockaddr* local_address, int
address_length)
connect() int return_code connect (int socket_descriptor, struct sockaddr* destination_address, int
address_length)
listen() int return_code listen (int socket_descriptor, int back_log)
accept() int return_code accept(int socket_descriptor, struct sockaddr* address, int
address_length)
read() int #of_bytes_read read(int socket_descriptor, void* buffer, int #of_bytes_to_read)
write() int #of_bytes_written write(int socket_descriptor, const void* buffer, int #of_bytes_to_write)

Team-Fly
Team-Fly

T h e T C P /IP D isp lay L ib rary U tility


To demonstrate the implementation of sockets in RPG IV, I contrived a small example application that allows users to list the
objects of a library. The Display Library (DSPLIB) command would have been an easier approach, but the purpose of this
simple application is as a TCP/IP tutorial. To implement this DSPLIB application, I will write a TCP/IP server application that
will respond to a request by printing out the listing of a library. I'll begin with the development of the server application, then
wrap up by developing a client application.

Team-Fly
Team-Fly

T h e S e rv e r
For the server application to accomplish the task, it must be able to do the following:

 Create a socket with the application's Start Socket Server (STRSKTSVR) command.

 Set socket options.

 Bind an IP address and port address for the host AS/400 to the socket.

 Place the server in listening mode.

 Accept connection requests.

 Read data from the client socket descriptor.

 Translate the library name from ASCII to EBCDIC.

 Execute the DSPLIB OUTPUT(*PRINT) command.

 Return the server to read new requests.

 Return the server to accept new connection requests.

 End the server in response to the application's End Socket Server (ENDSKTSVR) command.

The RPG D-spec prototypes for the socket functions that will be used to implement the DSPLIB server application are listed
in Figure 26.1. The $S o cke tsH copy file is included in the RPG client program at compile time via the /COPY statement in
Figure 26.2 at Label A:
/COPY QRPGLESRC,$SocketsH

 
 

 
 

F ig u re 26.2: RPG socket clients need to copy the socket prototypes.

Label B of Figure 26.2 presents the data structure that will contain the information necessary to bind to the socket created in
Label E with the so cke t function execution. Label C contains stand-alone field definitions for fields that will be used to support
other functions in the application such as error handling, DSPLIB command execution, and data translation from ASCII to
EBCDIC. (Label D simply defines constant values for invoking the DSPLIB command.) To begin the server application, the
server will need to create a socket to communicate to the client process, which it does at Label E with the following
statement:
C EVAL SDID = Socket(AF_INET:SOCK_STREAM:UNUSED)

To create the socket, three arguments need to be specified:

 The family protocol for which the socket will be created (Internet, SPX, SNA, etc.).

 The type of data stream to be sent/received.

 The protocol for the data stream.

The AF_INET constant in the first argument informs the so cke t function that the address family of the socket is to be in the
Internet domain. The SOCK_STREAM constant informs the so cke t function that the type of data stream is to be a byte-
stream configuration. The third argument is set to zero with the constant called UNUSED; this tells the so cke t function to use
the default protocol for the data stream type specified in the second argument. In this case, since SOCK_STREAM was
specified for the type, TCP is the default protocol.

In Figure 26.2, at Label F, I make the socket reusable for multiple client connections by setting the reuse indicator on, with
the following:
C EVAL rc = SetSockOpt(SdId:SOL_SOCKET:
C SOL_REUSEADDR:%ADDR(On):%SIZE(On))

At Label G, I bind the IP address and the port that I have selected for the DSPLIB service to the socket ID created by the
so cke t function at Label E:
C EVAL rc = Bind(SDID:%ADDR(serveraddr):
C svaddrlen)
Setting most of the values is a straightforward procedure of simply assigning the proper values to the proper data structure
elements in the se rve ra d d r socket structure. However, you must use another function, G e tH o stId
stId, to return the integer
representation of the AS/400's IP address (for example, 190.50.38.7 in this case). The prototype for this function is included in
the $S o cke tsH member. The following function shows how it is called:
C EVAL sin_addr = GetHostId

After the RPG server program binds to the socket, you now have a name to address the socket by, and using that socket
address, your client process can request connection events. Label H shows how the server accepts connection requests by
placing itself in listening mode:
C EVAL rc = Listen(SdId:10)

Once this function has been executed, the RPG server program can execute the a cce p t function, as at Label I, to enable its
services to a client program that has made a connection request:
C EVAL rc =
C Accept(SDID:%ADDR(serveraddr):%ADDR(
C svaddrlen))

Once a connection request has been made by a client and accepted by the server, the server can address the client through
the client's socket descriptor that was returned by the accept function execution. At Label J, a call to the re a d function is
made using the client's socket descriptor, which is addressable through the S d Id 2 variable:
C EVAL TotCharRead = Read(SdId2:%ADDR(Buffer):
C BufferLen)

That function passes a pointer to the buffer that will hold the data read-in and the length of the buffer. Completion of the re a d
function is signaled when it has read the number of characters enumerated by the buffer length argument. The return value
from the re a d function will be either the number of characters read (which should equal the buffer length), -1 (indicating a
failed read), or 0 (indicating a close socket signal from the client partner process). After a successful read, the data
conversion (QDCXLATE) API will be called at Label K to convert the data from ASCII to EBCDIC so that the server application
can continue to the next step of its service.

In the code at Label L, I pass the translated library name to the command execution (QCMDEXC) API to print out the list of
library objects. Then the RPG server program returns to the re a d function at Label J to restart the wait for another request
from that client. If the client terminates the connection, the server branches to Label M to close the socket for the client:
C Eval rc = Close(SdId2)

The code then loops back to the accept function at Label I, where it waits for a connection request from another client.

The only way the server process will end is through a client request to stop the server using the application's ENDSKTSVR
command. When such a request is made, all loops will be exited, and the socket clo se function for the server process will be
executed (as shown at Label N of Figure 26.2) along with termination of the process.

Team-Fly
Team-Fly

G o tch as A n d M isce llan e o u s


If you experience a problem when your server application attempts to bind to your selected port on the AS/400, check the port
restrictions for the port in question to determine if that port is restricted to a particular user profile. If it is, select another port
that does not have any restrictions (and don't forget to change it in your applications). Avoid port numbers below 255 because
these are typically reserved for various TCP/IP functions (20 for FTP, 23 for Telnet, 80 for HTTP, etc.). You can review your
AS/400 port restrictions by entering GO CFGTCP at the command line and selecting option 4 (Work with TCP/IP port
restrictions).

Adding a port restriction is as simple as entering the Add TCP/IP Port Restriction (ADDTCPPORT) command, prompting with
F4, and completing the parameters. You can review ports allocated by particular services by selecting option 21 (Configure
related tables) at that same menu, then option 1 (Work with service table entries) at the subsequently presented menu.

You can add a service table entry for the server program developed in this chapter by entering the Add Service Table Entry
(ADDSRVTBLE) command, prompting with F4, and completing the required parameters. While your server application is
running, you can review the TCP/IP connection status of the job by entering the Display the Work with TCP/IP Connection
Status List (NETSTAT *CNN) command or by entering the Work with TCP/IP Network Status (WRKTCPSTS) command and
selecting option 3 (Work with TCP/IP connection status). Either method presents the same information and can yield valuable
information concerning your server application.

Team-Fly
Team-Fly

T h e R P G IV C lie n t
As previously mentioned, a TCP/IP client/server application does not need to be on separate machines. TCP/IP enables
communication between two processes on the same machine. Figure 26.3 illustrates the source code for a client process
running on the AS/400; it is activated by the user submitting a request for a library to be printed with the Send Socket
Request (SNDSKTRQS) command (which is also available on the companion CD).

 
 

F ig u re 26.3: RPG socket clients also use the same C APIs .

As with the server application, the client includes the $S o cke tsH copy file at Label A of Figure 26.3. At Label B, again I
create a unique socket identifier with the so cke t function:
C EVAL SdId = Socket(AF_INET:SOCK_STREAM:UNUSED)

Since this client will be running on the same AS/400, the socket address data structure is established with the same values
that I set for the server application (i.e., the same port and same IP address). I used the G e tH o stId function to retrieve the
server's IP address. If my client existed on an AS/400 that was different from the server application, I would need to set that
address manually (because the G e tH o stId function would retrieve the IP address for the client AS/400, not the server
AS/400). In that case, you must overlay the field sin _a d d rr, the unsigned integer field that is to contain the IP address, with a
4-byte alphabetic field, sin _a d d rA , to assign the hexadecimal equivalent of the 32-bit (or 4-byte octal) values of the IP
address. For example, you cannot simply assign 190.50.38.7 to the sin _a d d r field because it is not a valid assignment. You
need to convert each octet (190, 50, 38, 7) to its hexadecimal equivalent and assign it on that basis. The sin _a d d rA variable
is set to the value X'BE322607' (in the commented code above Label C in Figure 26.3) for the IP address of 190.50.38.7.

Next, at Label C of Figure 26.3, rather than doing a bind, as I did with the server application, I will use the co n n e ct function to
request a connection from the server application, which at this point will be waiting at the call to the sockets a cce p t function:
C EVAL rc = Connect(SdId:%ADDR(serveraddr):
C svaddrlen)

At Label D, I translate the library name to its ASCII equivalent using a call to QDCXLATE, because the server application is
expecting the name to be encoded as an ASCII value. Then, I submit the request to the server with the w rite function, as
shown at Label E:
C EVAL rc = Write(SdId:%ADDR(Buffer):BufferLen)
Finally, at Label F, after the request has been submitted, I will close the connection:
C Eval rc = Close(SdId)

This section has dealt only with an AS/400 client process. There are some special considerations that you need to be aware
of when interfacing the AS/400 server application with a PC client application.

Team-Fly
Team-Fly

C o m p ilin g T h e T C P /IP S e rv e r A n d R P G IV C lie n t


To compile the TCP/IP server and RPG IV client, use the following commands:
CRTBNDRPG PGM(YourLib/SKTSERVER) DFTACTGRP(*NO) +
ACTGRP(QILE) BNDDIR(QC2LE QUSAPIBD)
CRTBNDRPG PGM(YourLib/SKTCLIENT) DFTACTGRP(*NO) +
ACTGRP(QILE) BNDDIR(QC2LE QUSAPIBD)

The QC2LE binding directory contains all the service programs that make up the standard C function library and contains the
__e rrn o and stre rro r functions needed to retrieve the error information described in this chapter. These functions are located
specifically in the QC2UTIL1 service program.

The QUSAPIBD binding directory contains the service programs that include the socket functions demonstrated in this
chapter. You will find most of the functions that have been discussed in the QSOSRV1 service program in QSYS. The re a dd,
rite, and clo se socket descriptor functions can be found in the QP0LLIB1 service program, also in the QUSAPIBD binding
w rite
directory. Compile instructions for the programs demonstrated in this application and commands used to start, stop, and
send requests to the socket server application are detailed in the code on the companion CD-ROM.

Team-Fly
Team-Fly

M ake s Y o u T h in k...
Given what this chapter has presented, it makes you think about what can now be accomplished by mixing languages in the
ILE. Why recreate the wheel when another language, such as C or Java, already has the needed functionality built right in? It
can no longer be taken for granted that RPG IV applications in the immediate and near future will be purely RPG. This
situation, in turn, will raise the expectations for RPG applications and will raise the base requirement of skills and capabilities
for the RPG IV developer. I think this is a good thing.

Perhaps this will also give RPG developers more credibility in the eyes of IBM, a company that reportedly does not have a
good opinion of typical RPG programmers and doesn't think much of their skills and capabilities. According to sources inside
IBM, the company feels that only a small segment of legacy AS/400 applications programmers will make the transition to
fully object-oriented Java development.

In addition, the source stated that the company holds the opinion that legacy AS/400 programmers are strong business
applications programmers but poor computer scientists; conversely, UNIX programmers are strong computer scientists but
poor applications programmers. What do you think?

Team-Fly
Team-Fly

R e fe re n ce s
 AS/400 System API Reference V4R2 (SC41-5801-01, CD-ROM QB3AMA01)

 ILE C/400 Programmer's Reference (V3R7 - SC09-2070-01, CD-ROM QBJAQY01)

 OS/400 Sockets Programming V4R2 (SC41-5422-01, CD-ROM QB3ANN01)

 OS/400 UNIX-Type APIs V4R2 (SC41-5875-01, CD-ROM QB3AM401)

 Sockets Programming V4R1 (SC41-5422-00, CD-ROM QB3ANN00)

 V4R2 (SC09-2514-00, CD-ROM QB3AG100)

Team-Fly
Team-Fly

C h ap ter 27: U sin g Java S o ckets P ro g ram m in g


O v e rv ie w
KEVIN VANDEVER

Much has been written and discussed about Java and its interoperability with RPG legacy applications. With Java spreading
faster than office gossip and the AS/400 able to run Java and host Web sites, the content of these articles, white papers, and
discussions grows increasingly important. Fortunately, developers concerned with providing Web-based business applications
while keeping intact the back-end business rules of RPG, have received good news concerning RPG communication with Java
and, subsequently, the Internet.

However, two problems have come out of this information. One is that the technology related to Java seems to be a moving
target. Just as you decide which technology to implement, something better and faster comes along. I realize that this is
common in the IT industry as a whole, but it occurs even faster with Java. The other problem is that, because so many
potential solutions are available to solve RPG-Java interoperability, developers have no time to test which ones might work the
best. Therefore, before you make your decision, you should consider things such as portability, speed, and ease of
implementation. One tool that fits these criteria is sockets.

Team-Fly
Team-Fly

S o cke ts 101
A socket is basically an endpoint, a port that can be addressed in a network. You can use sockets to communicate with
other sockets in a communication area. This area can be as large as the Internet or as small as any two points that can
connect using TCP/IP. You can even use sockets to communicate between programs on the same machine, something I
have done using RPG and Java on the AS/400.

I chose sockets to solve my interoperability dilemma because they meet my selection criteria. First, sockets are portable;
they are part of Java's core API and go everywhere Java goes. No extra toolkit or extensions are necessary to implement
them. I even compiled and ran a Java socket client servlet on the AS/400 to communicate with an RPG socket host on the
same AS/400. I then moved the servlet to a Windows NT server; the servlet worked just as well with the socket host on the
AS/400. Second, sockets are fast. How fast? Well, results may vary, but I consistently get my desired data in less than a
second. As for my third criterion, ease of implementation, you will soon see that implementing socket classes in a Java
program is very easy.

Team-Fly
Team-Fly

T h e E x am p le
Figure 27.1 shows a Java servlet using socket classes. This is a simple servlet that throws a Web page after sending a
request to a socket and receiving an answer back. I'll touch briefly on what makes this Java code a servlet but won't go into
too much detail about servlets. (See Chapter 39 in Section VII, "Serving Up Host-based Java Apps," for a servlet tutorial.)
Label A of Figure 27.1 shows the im p o rt statements required for servlets. The code marked by Label B is the remainder of
code that really makes this a servlet.

F ig u re 27.1: Servlets dynamically construct HTML to communicate with Web users and can communicate with legacy
applications through Java's simple sockets API .

I've created a class called te stS e rvle tt, which inherits, extends, or is a child of (pick your term) class H ttp S e rvle t. The servlet
engine calls the d o G e t method based on the URL request. The d o G e t method requires two parameters. The first parameter,
H ttp S e rvle tR e q u e st, contains information about the request, and the second parameter, H ttp S e rvle tR e sp o n se
se, houses the
dynamically generated HTML response. The socket client starts at the code in Label C.

A lot is going on here, but you wouldn't know it from the code. First, you need to declare the socket objects you are going to
use. In my example, I've declared the S o cke t object as te stS o cke t, the P rin tW rite r object as to S e rve rr, and the
B u ffe re d R e a d e r object as fro m S e rve rr. The S o cke t object defines the host and port number; P rin tW rite r sends requests
to the socket; and B u ffe re d R e a d e r receives information from the socket.
Once the objects are declared, they are instantiated at the three lines marked by Label D. The te stS o cke t object is set to a
new socket with the TCP/IP address or host name of the server from which you are requesting information and to which the
socket host code will run. The port number (3004 in this case) is the remote port that listens for the request, and the client
uses any local port it can bind to.

The to S e rve r object instance of the P rin tW rite r class contains the request to the socket, and the fro m S e rve r object
contains information received from the socket host. The fro m S e rve r object is constructed a little differently than te stS o cke t
and to S e rve r because Sun recommends wrapping the In p u tS tre a m R e a d e r into B u ffe re d R e a d e r for performance. Who am
I to argue with Sun?

Next is to send the request to the socket and wait for the response. Label E denotes the two lines of code that accomplish
that. In this example, I am sending the string "M y te st m e ssa g e " to the socket host and waiting for a response, which I am
storing in the string named te m pp. The fro m S e rve r object waits for the response before going to the next line of code that
displays the response on the Web page. The last thing to do in te stS e rvle t is to close the socket connections; Label F
shows the code for doing that.

Team-Fly
Team-Fly

T h e Jav a H o st S o cke t C lass


Now, I'll take a look at the Java host socket class. Label G shows the entire m yH o st class, which is a separate class and not
part of the socket client servlet. I've coded both the socket host and the socket client classes as part of te stS e rvle t.ja va
va.
When you compile this Java code, you create two classes: te stS e rvle t.cla ss and m yH o st.cla ss
ss. You don't have to do it this
way; I did it for simplicity. What's interesting about coding them in the same source member is that the two classes may run
on different machines. (You'll have to excuse my excitement, but, for an RPG-learning-Java programmer like me, this is pretty
cool.)

OK, back to m yH o st. You first declare S e rve rS o cke t and S o cke t classes, instantiating the S e rve rS o cke t class to port
3004. The a cce p t method waits for a connection request from a client to the host and port of your server (in this example,
port 3004). When you request and successfully establish a connection, the a cce p t method returns a new socket object
bound to a new local port. The server can then communicate with the client over this new socket and continue to listen for
client connection requests on the S e rve rS o cke t bound to port 3004. After the request is accepted, it is read by using the
re a d L in e method, which returns the request to the clie n tD a ta object. In my example, the request reads "M y S e rvle t T e st
P a g e "". You then append the string ""-- S u cce ss" to the clie n tD a ta object and send that string back to the client through a
new port. Finish by closing the socket connections.

To run the servlet and have it communicate successfully with a host socket, you must first run the m yH o st class on the
AS/400. You can run m yH o st interactively by using the RUNJVA or JAVA command, or you can submit the RUNJVA
command to batch by using Submit Job (SBMJOB). As soon as m yH o st is running on the AS/400, you can load your servlet
to whatever Web application server you're using. I used WebSphere on the AS/400 for my example. When the servlet is
loaded, bring up your browser and type the URL to your server, followed by the /servlet/ directive and name of your servlet
(i.e., http://MyServer/servlet/ testServlet). If all goes well, you should see a Web page similar to the one in Figure 27.2 with
the message "My Servlet Test Page. My test message - Success!"

F ig u re 27.2: A servlet responds to remote requests from URLs and HTML form submissions.

Team-Fly
Team-Fly

A R e cip e F o r E -B u sin e ss S u cce ss


By understanding how to implement sockets in RPG and Java, you possess a powerful tool that allows interoperability
between the two. (For more information on sockets, see Chapter 26, "TCP/IP Sockets Programming.") Add servlets and their
dynamic Web pages into the mix, and you're well on your way to a full-fledged e-business solution that takes advantage of
your legacy applications

on the AS/400. For more information on the socket classes available in Java, visit Sun's tutorial site at

www.java.sun.com/docs/book s/tutorial/network ing/Sock ets/index.html.

A u th o r's N o te :  I would like to thank Java programmer extraordinaire Will Houck of Boise Cascade Office Products,
who provided me with much-needed code examples, some Java training, and a little HTML.

Team-Fly
Team-Fly

R e fe re n ce s
 "Lesson: All About Sockets," The Java Tutorial: www.java.sun.com/docs/book s/tutorial/network ing/Sock ets/index.html

 OS/400 Sock ets Programming V4R4 (SC41-5422-03, CD-ROM QB3ANN03)

Team-Fly
Team-Fly

C h ap ter 28: S ervlets, S o ckets, A n d R P G


O v e rv ie w
JEFF MARKHAM

Even though it's a relatively new concept for AS/400 shops, cross-platform computing is quite pervasive these days. In plenty
of departments already, no new development takes place without the staff giving thought as to how the new kid on the block
will fit in with the networked neighborhood. Some departments are heading toward letting Java servlets be the glue that binds
together various components of the network-servlets that run on any Web server, access any database, and communicate
with any client. It's a nice idea, but, as they say, the devil is in the details.

How is an AS/400 able to conform to the paradigm of cross-platform computing? Well, for starters, it has become less
dependent on its original SNA communication platform and has added more TCP/IP features with each OS/400 release.
These TCP/IP features are important because TCP/IP is an absolute necessity for systems that have e-commerce
aspirations.

The AS/400 found itself lagging behind other systems in this area but has quickly caught up. At home, I still have the OS/400
V2R3 Softcopy Library, which is the oldest AS/400 documentation to which I have readily available access. I can open up the
AS/400 TCP/IP Guide manual and see that it's dated November 1993 (three years after HTTP hit the Internet). I can find out
how to configure TCP/IP support, configure the Telnet and FTP servers, use the Line Printer Daemon (LPD), and read how
SMTP is so tied into SNADS that it really isn't SMTP. And that's it. Oh, and there are instructions on how to PING and a
definition of an internet (not the Internet but an internet). However, since the release of V4R4, OS/400 boasts a rich set of
TCP/IP applications that enable it to participate to the maximum extent in the networked economy.

Team-Fly
Team-Fly

T C P /IP A p p licatio n A rch ite ctu re


I'll use the popular FTP service as an example to illustrate how TCP/IP applications work. When the AS/400 FTP server is
started, it runs in the background, listening on its designated port for FTP client requests. Ports are the logical locations in
the TCP/IP service through which TCP/IP sends and receives data. FTP servers are usually listening on port 21 for connection
requests. There are 65,535 available ports to use, and many of them are so-called well-known ports. Well-known ports are
usually reserved for particular services so that everybody doesn't use a different port for the same service. Using the FTP
example, suppose you start your FTP server and have it listen on a port, say 22, and I try to connect using the well-known
port 21. I would be unable to connect my FTP client to your FTP server, even though my machine would recognize your IP
address and yours would recognize mine.

Assume everything is running smoothly and your FTP server job is listening on port 21 for FTP client requests. What does
that really mean? What happens when it receives a connection request? Here's where the concept of threads is introduced. If
your FTP server did not implement threads, it would be able to handle only one FTP connection at a time. This restriction
would mean that, if your AS/400 served MP3 files via FTP, you'd have to wait to download your Sinatra tune until I was done
downloading the entire works of Van Halen. And you better hope I log off before going away for the weekend. Thanks to
threads, no FTP server would behave this way.

A server job must implement threads to accommodate as much or as little activity as necessary. When running, your FTP
server is probably performing a loop to listen for and accept a connection request. Once a client has made a connection
request, your server will create a new thread (called spawning a new thread or fork ing) to service the connection and then go
back to listening for new connection requests while the newly connected client deals with the newly spawned thread. The
server will continue to do this for all connection requests or until the machine runs out of resources. The concept of threads is
fairly straightforward. Programming for them, however, can be tricky (although Java 2 makes great strides in simplifying things
for developers).

Team-Fly
Team-Fly

In te rn e t Illu m in atio n
Inevitably, once one understands how TCP/IP servers work, the light bulb comes on and it becomes evident that this concept
would work great for just about anything. A person could think of plenty of reasons to have a background job running quietly
and dutifully and have it increase or decrease its own activity level all by itself. For example, a transaction-based server job
could receive transaction requests to update database files by several clients of unknown platforms. All you would have to do
is write a program to do the same thing the FTP, Telnet, and HTTP servers do on your machine, only, instead of transferring
files and sending out terminal emulation, you'd receive the transactions and promise the client you'd do the transaction for
him. But this explanation is like saying that all you have to do to be a millionaire is go out and get a million bucks. There are
a few extra steps involved.

As I mentioned, the idea of threads may be easy to understand, but it can get rather complicated pretty quickly. The more
robust your server job is, the more likely it is that you'll become painfully familiar with concepts such as thread pooling, lock
starvation, thread scheduling, and race conditions. I wouldn't recommend that your first foray into programming with a
language that supports threads be this type of scenario. So, say you've checked out the details of what it would take to roll
your own server and you decide that writing a threadsafe server would be a very daunting task. But, man, it sure would be nice
to have that server job to process your transactions. Enter WebSphere Application Server and the servlet programming model.

Team-Fly
Team-Fly

S tart Y o u r A p p licatio n E n g in e s
One of the many functions of WebSphere Application Server is that it performs as a servlet engine. A servlet engine is simply
software that supports the Java servlet API reference implementation-in other words, software that can do servlets the way
Sun intends servlets to be done. Servlet engines come in stand-alone or embedded form, but they are usually an add-on to an
existing Web server. In the AS/400's case, WebSphere Application Server is the servlet engine plug-in for IBM's HTTP Server
for the AS/400.

Servlet engines evoke servlets and run them through their life cycle in much the same way that a browser runs an applet
through its life cycle. For example, the in it() and d e stro y() methods of a servlet are called by the servlet engine automatically,
just as applets have their in it() and d e stro y() methods called automatically by the browser.

How does the servlet engine know when to evoke the servlet in the first place? The most common method is simply hitting a
URL with a browser-again, as occurs with an applet. Your Web server notifies the servlet engine when it has received a
request for a URL that is mapped to a servlet. When the servlet engine receives this notification, it will fire up the servlet by
creating an instance of the servlet object in the Java Virtual Machine (JVM) of the servlet engine.

Where one really sees the benefits of servlets is in the way the servlet engine implements threading. A developer isn't entirely
free of the worries of threads in the servlet world, but ensuring your servlet is threadsafe is a smaller beast to tame than
creating your own server application. A servlet is said to be threadsafe when it acts the same way no matter how many
clients are requesting its services. For the most part, the servlet engine itself takes care of the bulk of concurrency, or
multithreading. In the most common scenario, the Web server's servlet engine creates an instance of the servlet in the JVM
when the servlet is evoked, as in the case of a browser hitting a URL. Once the servlet is active in the space of the JVM, the
servlet engine simply channels all requests for that servlet to the single instance of the servlet. In other words, one instance
of, or one call to, a servlet is usually all that the Web server and servlet engine need to service an unlimited number of
requests.

Team-Fly
Team-Fly

R P G A s A S e rv le t C lie n t
When I began writing this chapter, I thought I'd write a servlet that would interact with client requests by receiving some data
and sending some back to both an RPG and a Java client. Then I thought that, if I wrote a couple of clients to work with a
servlet already on the Web, I could illustrate the power of servlets as well as drive home the point that TCP/IP is the cross-
platform enabler. So here I go.

Nearly every servlet engine comes with a handful of examples. WebSphere has some, and their location in the AS/400
Integrated File System (AS/400 IFS) depends on which version of WebSphere you're using. For this example, though, I'll
borrow a sample servlet from Sun's Java Web Server Web site (jserv.javasoft.com/products/java-
server/documentation/webserver1.1/servlets/ sample.html). If you visit this site, you can find the source code for the servlet as
well as other samples.

The specific sample I'll use is the Phone servlet. It simply takes a NAME parameter and returns the phone extension for that
name. If you don't send any parameters, the servlet returns all the names and their extensions. Now, you'll notice if you point
your browser to the Phone servlet sample, you'll see the URL http://jserv.javasoft.com/phone.html. Don't let this confuse you.
Even though the URL has a suffix of .html, it is not a static HTML page. The HTML is dynamically generated by the servlet.
Typically, servlets will have a URL with no suffix at all. Anyway, Figure 28.1 shows the RPG code necessary to accomplish
the task. I'll spare you the details about setting up a socket to which you can read and write data. What I do want to point out
is that, thanks to TCP/IP, even RPG can be a client to a Java servlet.

 
 

 
 

F ig u re 28.1: With TCP/IP, RPG can be a client to a Java servlet .

In order for the servlet to understand my RPG client's request, my RPG client will have to "sprechen sie HTTP" (speak the
language of the Web). Optionally, your servlet could extend G e n e ricS e rvle t; then, your client wouldn't have to speak HTTP.
However, because most servlets extend H ttp S e rvle t, I coded my RPG client to use HTTP. HTTP is one of the easier TCP/IP
protocols to get a handle on, because it has only a handful of commands. In fact, my RPG client has to use only one HTTP
command: the g e t method. And once you see how to set up sockets in RPG, you can knock yourself out creating your own
text browser, email client, Telnet client, and newsgroup reader-all from RPG.

Figure 28.2 shows the Java client used to get the same end result achieved with the RPG client. I worded that last sentence
carefully because I cheated. Java can create a socket and perform I/O on it the same way the RPG client does, but why
would I do that when I can take the easy way out and use the URL class?
F ig u re 28.2: A Java client can speak to the servlet and receive data back just as the RPG client in Figure 28.1
does.

Team-Fly
Team-Fly

R P G A n d Jav a S e rv le ts: M arriag e O f C o n v e n ie n ce


Imagine, however, that the servlet was not written to send out its results in HTML format. Obviously, this sample servlet was
written so that a Web browser could see its results. But what would happen if a servlet sent out its results in a different
format, such as a data stream, that could be easily reconstructed by clients? Those clients do not have to be browsers. There
is no law that says only HTML documents can be sent out over the HTTP port. I could write a servlet that sent out non-HTML
data that a client could use; if I did, I would be employing a concept known as HTTP tunneling. Even in the tightest of
firewalls, HTTP traffic is customarily allowed, meaning that there is at least one port open, usually port 80.

Team-Fly
Team-Fly

B ack T o T h e S e rv e r
I'll wrap up by returning to the server side. If you take a look at the source code for the Phone servlet at the URL I gave, you'll
see that it's an everyday, ordinary servlet. It doesn't concern itself with workload or how many or even what kind of clients
might call upon its services. I'll bet that million bucks I mentioned that the author of the servlet never thought an RPG client on
an AS/400 would come calling.

This is a concept that most AS/400 developers have no trouble at all understanding. Usually, when one writes an RPG
program, he or she does so as if only one user would be using it at a time. OS/400 takes care of concurrency, object locks,
and so forth. The same goes for comparing the server job model of servicing clients with the servlet model. Make life easier on
yourself the next time you consider this type of application. Resist the urge to write your own server and let WebSphere
Application Server do the heavy lifting for you.

Team-Fly
Team-Fly

R e fe re n ce s
 Sun Java Web Server Web page:
jserv.javasoft.com/products/javaserver/documentation/webserver1.1/servlets/sample.html

Team-Fly
Team-Fly

C h ap ter 29: U sin g T h e JN I T o C all R P G F ro m Java


O v e rv ie w
JIM BARNES

Wouldn't it be nice to dump all your RPG and C code and develop all your applications in Java? That suggestion should raise
a few eyebrows from discerning developers. The fact is it's not a completely "caffeinated" world yet and is not likely to be for
quite some time. Many programmers still prefer a native 5250 user interface over a Web browser or client/server user
interface, and others are chained to an OS/400 version that does not have a Java Virtual Machine (JVM). So, to be
competitive in these markets (assuming this is your concern), you must provide support for these options for a prospective
customer. Yet it could become cost-prohibitive to maintain two separate versions of your software. In addition, until V4R4,
Java performance precluded developing serious (competitive-edge) applications. So, what is a programmer to do?

Team-Fly
Team-Fly

E v e r H e ard O f Jav a N ativ e In te rface ?


A little jewel known as Java Native Interface (JNI) enables you to reuse procedural code written in languages such as RPG IV
or C as native methods in Java classes. In other words, you can use RPG subprocedures as plug-ins for Java functions.
However, the native methods must be developed as ILE service program functions or procedures to be accessible using JNI. A
service program is essentially a DLL on the AS/400. All JNI services are provided via an AS/400 service program, QJVAJNI in
the QSYS library, with roughly 216 functions. But why choose JNI over dynamic program calls and a pure Java solution?

The advantage of using JNI is that both the calling program and the called program run in the same process (job) on the
AS/400 system while the other methods start a new process (job). This makes JNI calls faster at startup time and less
resource-intensive. However, because Java applications run in the Technology Independent Machine Interface (TIMI) and user
native methods require a user address space to run, some overhead is initially required to create a user environment that uses
16-byte address pointers instead of the 8-byte pointers used below TIMI. So, what does this all mean? It simply means that
your reasons for using JNI should be based on more than performance.

Your reason for using JNI may be the need to preserve a large investment in legacy code. However, a Java Toolbox class will
enable a dynamic program call, right? And JNI requires the native procedures to be in a service program before they can be
addressed as a native method, meaning that you might have to do some reengineering of your existing code to translate it
into a service program consisting of a set of subprocedures. How much reengineering you'll have to do will be based on the
modularity of your existing code. So where is the preservation?

Team-Fly
Team-Fly

W h y U se JN I?
At this point, you should be asking yourself, "Why use JNI if I have to rework my code anyway? Why not just do a Java
Toolbox program call?" There are two reasons why you would want to use JNI over a pure Java solution and a Java Toolbox
program dynamic call. For one, the function required does not exist as a bindable Java option, and the Java Toolbox program
call does not yield the required level of performance. (JNI does create some runtime overhead, but it is minimal compared to a
Java Toolbox program call.) The second reason is that you must provide "caffeine-free" access to your application to be
competitive in serving less developed IS shops (i.e., you must be able to provide a marketable solution where Java is not an
accepted standard). In today's AS/400 applications market, that means being able to provide a user interface access
paradigm that can be adapted to both the older, green-screen style of access and the newer, browser-based access method.

However, you can't afford to develop core functionality in some ILE native methods and then turn around and develop the same
code in Java. You should be addressing the same back-end database using either method, and you can ensure better data
integrity by being consistent in addressing and handling data with the same data access functions. Keeping features in sync
between two releases is difficult enough without having multiple versions of the same product (one pure Java and one totally
"caffeine-free"). JNI allows you to code your back-office code in RPG to be accessed directly from both a Java front-end and
an RPG front-end.

Team-Fly
Team-Fly

W h at's T h e P lan ?
You should review the following factors that will determine the amount of effort required to reengineer your existing code for JNI
native methods:

 How modular is your code?

 What is the lowest level of OS/400 you are required to support?

 How much data must be shuffled back and forth?

 What is the required response time of the application?

 Do results have to be real-time, or is batch update allowed?

Answering these questions will determine whether only JNI-level access is needed, client/server data queues or sockets are
required (with the data queue or socket server task running in the background), or batch update is necessary. In truth, your
solution will probably lie in a combination of all of these methodologies.

Team-Fly
Team-Fly

C o n stru ctin g A Jav a S h e ll T o "W rap " R P G IV N ativ e M e th o d s


The example application I've provided takes a customer number passed as an argument and uses background native methods
(implemented as RPG subprocedures) to retrieve information from a customer master file. Figure 29.1 shows sample output
from the execution of the Java class running in Qshell. My example Java application uses five native methods, developed
using RPG IV, to perform necessary functions that, you should assume for purposes of this example, could not be
accomplished in Java with the same required performance or functionality.

F ig u re 29.1: Java applications can benefit from legacy "native" application code.

Figure 29.2 shows the Java class C u stP ro cs and the five native methods (shown at Label B). This simple application takes
only one argument (cu stid, the customer number), parses out the integer value of this argument using p a rse In t (at Label C),
cu stid
creates a new instance of the C u stP ro cs class (Label D), and, finally, calls each of the native methods in turn to get the
required customer information that each function supplies.

F ig u re 29.2: You can use RPG subprocedures to provide code implementations for Java methods .

Note that, before any native functions can be called, the service program that contains the native methods is loaded with the
S yste m .lo a d L ib ra ry method (at Label A). The lo a d L ib ra ry method is usually invoked in the class initializer because, much
like the *INZSR in RPG, the class initializer is automatically called the first time the class is accessed. Methods are bound
dynamically on the first call, and subsequent calls are as fast as statically bound calls.

You should also note that the object cp at Label D in Figure 29.2 can be reused as many times as required, so that you don't
have to create a new object each time you wish to call one of the native methods again. Actually, the object cp is really not
required in the example application (because there are no member variables or methods, just the static native methods I have
defined), but I have included it here to avoid confusion. Those of you who have been working with Java will already have
realized this. However, for purposes of demonstration, you should assume the existence of other member variables and
functions requiring an object instantiation. At Label E, the native method calls are made inside the S yste m .o u t.p rin tln
function to execute and display the results returned by each of those functions. Finally, S yste m .e x it(0) shuts down the
C u stP ro cs application.
Team-Fly
Team-Fly

S o , W h at D o e s T h e N ativ e F u n ctio n C o d e L o o k L ike ?


Figure 29.3 shows a code snippet of the logic necessary to implement the native functionality required by C u stP ro cs
cs. For
example, look at the g e tN a m e function.

F ig u re 29.3: Modularized back-office RPG code can be used by both Java and RPG front-ends .

I should first point out that you must code the N o M a in H-spec keyword at Label F to avoid initialization code being generated
for your service programs. Next, I have coded a compiler directive at Label G that will enable me to use the same source code
to generate both a threadsafe version of the service program and a single-threaded version for pure native applications. This is
done to enable Java threads of execution to be serialized for each call instance of your native methods (i.e., program variable
instances will be marked for a particular thread). Yet you will want to avoid serialization when other RPG programs call your
service program.

All that is required to generate the two different binary versions is to pass the ja va In clu d e d text for the DEFINE parameter of
the Create RPG Module (CRTRPGMOD) command to generate the threadsafe version and leave it off for the pure native
version. Each threadsafe binary has the same name as the single-threaded binary plus an "_r _r," using the same notation that
_r
IBM uses to denote threadsafe C functions. This enables both versions to reside in the same library for distribution. Service
program documentation instructs programmers on the proper way to create these binaries.

Note that g e tN a m e takes an unsigned integer as an input argument (Label I) to represent the customer number in the
customer master file. It returns a 30-byte alpha field (Label H) that will contain the name as retrieved from the customer
master file. This would be fine except for a couple of things. For one, JNI cannot call the native methods in this manner and
provide access in the other direction (access to Java classes and objects from native methods) and access to JNI functions
required for the interface to work. Also, Java applications use a data-encoding method (called UCS Transformation Format-8,
or UTF-8) that is closer to ASCII than it is to EBCDIC. So, for a native method to understand text data passed to it, a
translation from ASCII to EBCDIC must occur. Likewise, any text data (referred to as a String object) returned to the Java
application must be encoded using the UTF-8 or Unicode data-encoding format. So, how do you handle these requirements
for Java applications but not impose any superfluous requirements on your pure native applications?

Team-Fly
Team-Fly

W rap It U p
Recall the reason(s) why you are using JNI. The idea is to preserve native functionality with as little modification for the JNI
interface as possible. To do this, you must create a shell or JNI wrapper for the native functions. One reason for creating the
wrapper is that the JVM passes two arguments that your native methods will not require when running in pure native mode: (1)
a pointer to the JNI function table (which contains an array of pointers to JNI functions) and (2) a reference to a class (if the
method is called from a class-static method) or a reference to an object (if the method is called from an instance of a class).
After that, any arguments the native method requires are specified.

Another reason for the wrapper is to provide the necessary services of data extraction or encapsulation (as in the case of a
String object) and translation for textual data passed to (ASCII to EBCDIC) and returned from (EBCDIC to ASCII) native
methods. Because running in pure native mode does not require data extraction (encapsulation) or translation, the wrapper
serves to encapsulate only the functionality that is required for the Java application. Figure 29.4 shows the wrapper
(CC u stP ro c_J service program) required for the g e tN a m e function.

F ig u re 29.4: Each RPG subprocedure requires a wrapper to convert EBCDIC to Java data types.

Note in Figure 29.4 that the name of the wrapper function for the g e tN a m e function (Label J) is
Ja va _P e n ta S a fe S ysP kg _C u stP ro cs_g e tN a m ee. This four-part name (the parts are separated by a single underscore) is
required by the JNI. The name consists of Ja va va, designated as the language library; the name of the package (in my
example, P e n ta S a fe S ysP kgkg, as shown in the first statement in Figure 29.2) containing the referenced native method; the
name of the class (CC u stP ro cs cs) declaring the native methods; and, finally, the name of the native method to be called
(gg e tN a m ee).

The first argument passed to the g e tN a m e function is JN IE n vv, followed by cla ssP a rm typecast as a jo b je ct
ct. After these two
required parameters, any native method arguments are specified. In the case of g e tN a m ee, all that is required is the cu stid
typecast as a jin tt. For a complete list of Java reference types used in JNI, refer to the copy member Jn iM D _h included in the
downloadable material for this chapter (all the code for this chapter is on the companion CD).

What about the return value for g e tN a m ee? In the procedure prototype (Label J) and procedure interface (Label K) lines, I
defined the return value as a jstrin g type. This will actually be a "reference" to the String object created with a call to the
N e w S trin g JNI function.

Now take a look at the procedural section. The first thing it does is assign the pointer to the JNI function table that was
passed from the JVM to the basing pointer JN IE n v@ (Label M), which is associated with the Ja va _JN I_E n v data structure in
the jn i_h copy member shown in the snippet in Figure 29.5. (The full source code and the SQL necessary to create and load
the customer file are on the companion CD.) You'll need at least one pointer out of the array of pointers that is passed to
create a new String object that will contain the name of the customer retrieved from g e tN a m ee. The first pointer in this array
points to an array of pointers that point to each of the 216 functions in the QJVAJNI service program.

F ig u re 29.5: To use the JNI environment, you'll need access to a copy book of data structures.

Before you can create the String object, you must first call the wrappered native function g e tN a m e (at Label N) and convert
the returned text from EBCDIC to Unicode as required by the JNI function N e w S trin g (Label O). To accomplish this
conversion, simply use the RPG IV built-in function %UCS2 that was added in V4R4. (If you are not at V4R4, you can convert
the text to a straight ASCII, null-terminated string and use N e w S trin g U T F instead; however, this does not accommodate all
national languages as Unicode does.) The Unicode data is placed in a Universal Multiple-Octet Coded Character Set-2 (UCS-
2)-compliant field named d N a m e O u t (Label L) defined as a c data type. Finally, after creating the String object, you return a
reference to this new object to the C u stP ro cs Java application, as shown at Label P.

Team-Fly
Team-Fly

IB M D o cu m e n tatio n B u g
The instructions for compiling the native methods service program and wrapper are presented in the banners of the source for
each of the downloadable materials. One thing I should mention is a discrepancy in the way the AS/400 Java Development Kit
documentation on the IBM AS/400 Web site describes which options to use to compile your native methods service program:
"Be sure that the ACTGRP parameter on the CRTSRVPGM [Create Service Program] command is *CALLER. This is the
default value. Do not specify a named activation group." The problem is that, when you follow these instructions, a runtime
exception is thrown that causes your application not to run the first time. This exception is caused because an RPG runtime
routine attempts to register an activation group exit procedure on a call to CEE4RAGE. Because your service program is
compiled using the *CALLER option for the activation group as suggested in the documentation and because the caller is a
method in the Java JNI service program (QJVAJNI) and is running in the default activation group, a call to CEE4RAGE cannot
be processed (it must be called in an ILE named activation group).

A so u rce a t IB M re p o rte d th e fo llo w in g :

The problem is caused by using the THREAD(*SERIALIZE) keyword in conjunction with ACTGRP(*CALLER) when the
activation group turns out to be the default activation group. Java native methods are called from the default activation
group, so *CALLER native-method service programs run in the default ACTGRP.

The RPG runtime was trying to call CEE4RAGE to register a cleanup procedure to be called when the activation group
ended; the cleanup procedure would destroy any mutexes that the runtime had created for THREAD(*SERIALIZE) RPG
modules that ran in the activation group. Because CEE4RAGE cannot be called from the default activation group, the
RPG runtime should not have been trying to call it for RPG modules running in the default activation group.

Here's the problem description from APAR SA86663: "An ILE RPG program compiled with THREAD(*SERIALIZE) and
ACTGRP(*CALLER) fails with MSGCEE3101 if it is called from Java, or from any program or procedure running in the default
activation group." Note that PTF SF60936 is the V4R4 fix for this bug.

Team-Fly
Team-Fly

Y o u 'll W an t T o R e ad T h is
There are many other JNI functions besides the ones presented in this chapter. For example, the g e tS trin g C h a rs and
g e tS trin g U T F C h a r JNI methods enable your native methods to extract a Unicode and UTF-8 character set string,
respectively, from a String object passed to them. Integers and floats are primitives and can be passed as such to native
methods (all that you need to know is whether they are short or long). Zoned and packed numeric fields must be converted
using a related helper class (in the AS/400 Java Toolbox) to integers and floats of the same magnitude, since these data
types are not supported by Java.

Prior to my experience with JNI, I had been warned often by many that JNI was too difficult to be implemented by mortal man.
Yet I found it extremely easy. Programming by nature is a detail-oriented process, and JNI is another tool that can be
exploited to accomplish the magic you are always expected to conjure up for your users. In that endeavor, you will find on the
AS/400 Redbooks Web site (www.redbook s.ibm.com) a helpful Redbook titled Building AS/400 Applications with Java (SG24-
2163-02). This book was invaluable in my quest to utilize JNI to call RPG IV native methods on the AS/400. In addition, it
gives some tips on establishing your environment for compiling and running Java applications. I strongly recommend you
download the PDF version of the Redbook and additional related materials and upload the save file containing a complete
functioning application implementing JNI. I challenge you to take the techniques from this chapter and IBM's Redbook and
further explore the functionality provided by JNI on the AS/400.

Team-Fly
Team-Fly

R e fe re n ce s
 Building AS/400 Applications with Java, Redbook (SG24-2163)

 Essential JNI: Java Native Interface. Rob Gordon. Colorado Springs, Colorado: Prentice-Hall, 1998

 IBM AS/400 Developer Kit for Java Documentation Web site: www.as400.ibm.com/developer/java/devk it/rzaha.htm

 Sun's Java 2 SDK Standard Edition Documentation Web site: java.sun.com/products/jdk/1.2/download-docs.html

Team-Fly
Team-Fly

S ectio n V I: N o t Java
C h ap te r L ist
Chapter 30: HTML Basics

Chapter 31: HTML: The New 5250

Chapter 32: HTML Form Validation With Javascript

Chapter 33: Advanced Html Form Validation With Javascript

Chapter 34: Using Cookies To Pass Parameters Between Web Pages

Chapter 35: XML: The Ubiquitous Language Of The Internet

Chapter 36: XSL Stylesheets: Display Files Of The Web

Chapter 37: Unix Developers Find A Home In Qshell

P art O v e rv ie w
Not Java? What's a section on non-Java technologies doing in a Java book? This section covers HTML, XML, Extensible
Stylesheet Language (XSL), JavaScript, HTTP cookies, and UNIX shell programming, but no Java. Well, the most prevalent
use of Java today is on the server in the development of Web applications. Web applications use HTML as the user interface,
XML for a universal data delivery mechanism, XSL to format XML, JavaScript to do browser-side editing, HTTP cookies to
maintain state, and, on OS/400, UNIX, and Linux, some shell programming.

In the first chapter of this section, "HTML Basics," Teresa Pelkie delves into the nitty-gritty details of HTML. Joe Pluta's
executive overview, "HTML: The New 5250," explains how HTML is replacing 5250 as the new user interface. As you'll find out
in Section VII, "Server-side Java," you use HTML as the user interface and a combination of Java servlets and JavaServer
Pages for the business logic.

One problem with Web deployment is that every time the user clicks the Submit button, all the data on the panel gets sent to
the server for processing. And often the data is passed right back to the client because of a validation error. That's where
JavaScript comes in. JavaScript is embedded into the HTML sent to the browser and, when the user clicks the Submit button,
JavaScript performs basic edits. My "HTML Form Validation with JavaScript" provides the basics of JavaScript editing, and Jeff
Markham's "Advanced HTML Form Validation with JavaScript" gives you some advanced JavaScript editing techniques.

Another problem with Web applications is that the HTTP is stateless. Because the same program invocation handles all
browser requests, user-specific information is overlaid each time a new request is handled. You are going to have to do a little
extra work to maintain state information for your browser-based users, and David Mayle shows you just how to do that in
"Using Cookies to Pass Parameters Between Web Pages."

As Internet applications get more prolific, there is a greater need for a standard way to disseminate information. In "XML: The
Ubiquitous Language of the Internet," I explain how XML is poised to be the universal strategy for the storage, transfer, and
manipulation of data across the Internet. XML is similar in structure to HTML, but, unlike HTML, XML does not say how
information should be presented. XSL takes XML and formats it for any type of output you want, from HTML to PostScript.
Eduardo Ross explains XSL in "XSL Stylesheets: Display Files of the Web."

The last non-Java technology covered in this section is shell programming. Walter Goodwin discusses the OS/400 Qshell
Interpreter in "UNIX Developers Find a Home in Qshell." AS/400 Java programmers need to understand how to use Qshell to
manipulate programs in files in OS/400's IFS, much like the Command Entry screen is used to manipulate RPG programs
and database files in the QSYS library system.

Team-Fly
Team-Fly

C h ap ter 30: H T M L B asics


O v e rv ie w
TERESA PELKIE

Hypertext Markup Language, commonly known as HTML, is the primary language used to display and exchange information
on the World Wide Web. HTML is probably the easiest computer-based language to learn and use, which accounts for its
ubiquity and popularity. HTML is not a new technology, but for the AS/400 programmer, it has only recently begun to prove
itself as a valuable and useful tool.

HTML was developed in 1989 by Tim Berners-Lee while he was working at CERN, the European Laboratory for Particle
Physics, in Switzerland. The first Web servers were UNIX computers, followed by Microsoft's Windows NT Server with Internet
Information Server. When IBM introduced HTTP serving capabilities to the AS/400, AS/400 programmers began to pay more
attention to HTML. If you know HTML, you can use AS/400 programming tools such as CGI, Net.Data, Java servlets, and
JavaServer Pages running in WebSphere Application Server.

Team-Fly
Team-Fly

W h at Is H T M L ?
HTML is a markup language. A markup language describes the structure and appearance of the contents of a document.
Tags are placed around parts of the document to describe or format it. Tags are also used to link files, insert graphics, create
forms, embed scripts, and execute programs. The HTML tags are interpreted by the browser, which renders a Web page
based on its content and its tags.

A tag begins with a less-than symbol (<) and ends with a greater-than symbol (>). The name of the tag is placed between the
opening and closing delimiters. Most tags use an opening tag and a closing tag to enclose the content; the closing tag is
indicated by the opening delimiter sequence of a less-than symbol and slash (</). For example, the paragraph tag has an
opening < P > and closing < /P > tag. You indicate that a section of text is a paragraph by placing tags around it:
<P>This is a paragraph</P>

Some tags are used alone, such as the break tag, < B R >>. Break tags do not have a closing tag because they do not enclose
content. The browser renders the content as designated by the tag, as shown in the following example:
<P>This sentence is on one line
<BR>
and this sentence is on another line.</P>

HTML tags can also have attributes. Attributes are characteristics or properties that further describe the structure or
appearance of the content. Most attributes are optional, but some are required. An attribute is assigned a value. For instance,
the < P > tag in the following example has an ALIGN attribute with a value of CENTER. The image tag, < IM G >>, in the example
must have a source attribute, SRC, but the WIDTH and HEIGHT attributes are optional.
<P ALIGN=CENTER></P>
<IMG SRC="LOGO.JPG" WIDTH="400" HEIGHT="100">

Team-Fly
Team-Fly

H T M L D o cu m e n ts
An HTML document is an ACSII text file and can be created using any text editor. The tags are not case sensitive. The
document begins with an opening HTML tag, < H T M L >>, and ends with a closing HTML tag, < /H T M L >>. The HTML document is
divided into two parts: the head and the body. The head section is identified by the < H E A D > < /H E A D > tags. The head
contains information that is processed by the browser, such as a scripting language. The title tag, < T IT L E > < /T IT L E >>, is
located in the head section. The title is actually displayed at the top of the browser above the menu bar, not inside the
browser window. The body section is identified by the < B O D Y > < /B O D Y > tags. The body contains the content of the Web
page that is displayed in the browser window.

The basic tags needed for an HTML document are as follows:


<HTML>
<HEAD>
<TITLE></TITLE>
</HEAD>
<BODY>
</BODY>
</HTML>

Team-Fly
Team-Fly

H T M L T ag s
There are currently about 50 HTML tags. Although most tags can be used anywhere, some can be used only with certain
other tags. Tags are grouped into categories according to the type of function they perform.

Structural tags break up an HTML document into sections. The most frequently used structural tags are paragraph, < P > < /P > ;
break, < B R > ; horizontal rule, < H R >>, which inserts a horizontal line; and division, < D IV > < /D IV >>, which allows you to group
and align content.

Formatting tags, such as bold (<< B > < /B >>) and italic (<< I> < /I>
/I>), are used to change the appearance of text. Six heading tags,
< H 1> < /H 1> through < H 6> < /H 6> 6>, control the size of the font from a level 1 (the largest) to a level 6 (the smallest). The font
tag, < F O N T > < /F O N T >>, is used to change the font size, font face, and font color.

There are several list tags. The unordered list or bulleted list, < U L > < /U L >>, and the ordered list or numbered list, < O L > < /O L >>,
are the most frequently used. In these lists, the actual list item is indicated with an < L I> tag, as shown in the following
example:
<UL>
<LI>bulleted item one
<LI>bulleted item two
<LI>bulleted item three
</UL>

Table tags are used to organize content into rows and columns. The table (<< T A B L E > < /T A B L E >>) contains rows
(<< T R > < /T R >>), and rows contain columns or table data cells (<< T D > < /T D >>). All of the content, including other HTML tags, is
located inside the < T D > < /T D > tags. The syntax for a table is as follows:
<TABLE>
<TR>
<TD>column one, row one</TD>
<TD>column two, row one</TD>
</TR>
<TR>
<TD>column one, row two</TD>
<TD>column two, row two</TD>
</TR>
</TABLE>

The tag that gave HTML its instant success is the anchor tag. The anchor tag, < A > < /A >>, creates a hyperlink to another
HTML document or to another file, such as a sound, video, or graphic file. The following is the basic syntax of a hypertext link:
<A HREF="file_name.html">click here</A>

Team-Fly
Team-Fly

F o rm E le m e n ts
The most important HTML elements for Web programming are the form (<< F O R M > < /F O R M >>) elements, which are elements
that accept user inputs. Figure 30.1 shows a sample of a query-prompting form that accepts several types of user inputs. The
inputs are used to formulate the query request to the database; the results are returned on another Web page.

F ig u re 30.1: The Query Options form accepts several types of user inputs.

The Query Options form in Figure 30.1 uses the following types of form elements:

S e le ctio n list: Two types of selection lists are shown in the figure. The first type is the multiple-item selection list, shown in
the "Fields to Include" section; this is used to display more than one list element at a time. This list box also allows the
selection of more than one list element. The other type of selection list is the drop-down list, shown in the other sections of
the form. The drop-down list displays additional list items when the user clicks the downward-pointing arrow.

The HTML syntax for a multiple-item and single-item list is shown in Figure 30.2 at Labels B and D, respectively.
 

F ig u re 30.2: Form elements, the most important HTML elements for Web programming, accept user
inputs .

C h e ck b o x : Check box selections are used in the "Fields to Include" section and the "Optional Selections" section. The
"Fields to Include" check boxes function as group check boxes, since they are used to select items from a set. The "Optional
Selections" check boxes are used as single-item selections, since each check box (Show Date, Show Time) functions
independently of the other. The HTML syntax for a group of check boxes and a single-item check box is shown in Figure 30.2
at Labels C and G, respectively.

T e x t in p u t fie ld : A text input field is used in the "Include Selections" section (the field with the numeric value 50.00 entered
into it). Text fields can be single or multiple lines. Unlike with AS/400 DDS display files, you cannot assign field type
characteristics to a text input field. For example, you cannot limit the user to entering numeric characters using HTML alone.
Field-level edits and data type restrictions are commonly programmed using JavaScript. The HTML syntax for a text input field
is shown at Label E in Figure 30.2.

R a d io b u tto n : The "Order by Selections" section includes two radio buttons to select the sort order for the query. Radio
buttons are used in sets of at least two to provide a mutually exclusive selection capability. For example, if you click the
Ascending selection, the Descending selection is unselected. The HTML syntax for a group of radio buttons is shown in
Figure 30.2 at Label F.

S u b m it b u tto n : The Submit Query button at the bottom of the form is used to invoke the CGI program that will process the
Query Options form (Figure 30.2, Label H). The name of the CGI program is usually indicated on the < F O R M > tag in the
HTML document (Figure 30.2, Label A).

Team-Fly
Team-Fly

M o re A b o u t T h e < F O R M > T ag
For a simple form like the Query Options form shown in Figure 30.1, you can use a simple < F O R M > tag. The tag is shown in
Figure 30.2 at Label A.

The < F O R M > tag is usually placed immediately after the < B O D Y > tag that opens the description of the main part of the form.
The ending < /F O R M > tag is usually located immediately before the closing < /B O D Y > tag.

The < F O R M > tag is used to indicate to the Web server that it is to process input from the form using the POST method, as
opposed to the GET method. In CGI programming terms, that means that the form input is sent to your program in a file
named STDIN (Standard Input), rather than in environment variables. IBM HTTP Server for AS/400 provides ILE APIs that you
can use to access the incoming data stream, using either STDIN or environment variables (QQ zh b C g iP a rse for POST,
Q tm h G e tE n v for GET). Most forms that you create will use the POST method, because there is no restriction on the amount
of data that can be sent from the browser to the Web server when you use POST (GET is limited to 1,024 characters).

The ACTION part of the < F O R M > tag identifies the path and program name that is invoked to process the form. In this case,
the path is MCTEST. The path name is processed using a MAP directive in the HTTP Server configuration file, which is paired
with an EXEC directive that indicates that CGI programs are allowed to be executed in certain libraries that you define.

The < F O R M > tag is activated when the user clicks the Submit Query button. The code for the submit button is shown at
Label H in Figure 30.2. The T Y P E = "S U B M IT " is used to indicate to the browser that it should render a button and that, when
the button is clicked, it should perform the action specified in the < F O R M > tag. The VALUE is used to describe the caption
that is to be on the button.

Team-Fly
Team-Fly

M o re A b o u t F o rm E le m e n ts
Now I will discuss the remaining form elements in more detail. There are two specific issues that you should be aware of
when using form elements for Web page design:

 What are the user interface issues that pertain to a form element?

 What is the format of the input provided by the form element to the CGI program?

The form elements are used almost exactly like elements in other GUI environments (Windows or Mac) or like the enhanced
DDS screen elements. Elements other than text fields are generally used to select one or more items or options from a list of
selections.

L ist B o x e s
List boxes are usually used when you have many possible selections but only limited space to display the selections. You
can see several examples of list boxes on the sample form.

There are two ways to display list boxes: with multiple items at a time or a single item at a time. The list box in the "Fields to
Include" section (Figure 30.1) shows three list selections at a time. You can scroll through the rest of the items in the list.
The list boxes in the other sections show only one item at a time. You click the arrow to display a drop-down or pop-up list of
additional items.

In addition to the two display techniques, there are two types of list boxes:

 Multiple selection-The list box in the "Fields to Include" section allows multiple simultaneous selections. To select more
than one selection, you press and hold the Ctrl key or the Shift key when clicking additional items. Ctrl selects additional
individual items, whereas Shift selects all the items between the first item selected and the next item that you click.
Multiple-selection list boxes function similarly to a group of check boxes.

 Single selection-The other list boxes on the form allow only one element at a time to be selected. If you click another
item in the list, the previous selection is unselected. Single-selection list boxes are used like a set of radio buttons.

When you use list boxes, there are two user interface issues that you should be aware of. First, it can be very difficult for
users to work with multiple-selection list boxes. You should consider placing explanatory text near the list box to indicate
how to make multiple selections. Second, in general, list boxes should not contain so many elements that the list requires
extensive scrolling. For example, a list of the 50 states is about the maximum number of elements that you would want to
work with in a list box. If you have several hundred items to select from, you should consider providing an alternate selection
method, such as another Web page that scrolls, or provide some method to select only a subset of the list.

Input from a list box is returned to your CGI program in a name/value pair. The name is the name assigned to the list box,
such as INCLUDE_FIELDS (the first list box in Figure 30.1, the code for which is shown in Figure 30.2 at Label B). For a
multiple-item list, the value is a comma-delimited list of selected values. For example, if the Part number and Quantity items
are selected, as shown in Figure 30.1, the value returned to your program is as follows:
PARTNO, PARTQTY

Although it may be difficult to parse the field names from the list in an RPG program, that format of data returned to your
program is ideal if you are dynamically constructing an SQL statement. For example, you can use that list in the SELECT
clause to indicate which database columns are to be selected from a table.

C h e ck B o x e s
Check boxes can be used in sets or individually. In Figure 30.2, Label C, I show how to code a group of check boxes by
assigning the same name to each check box. Label G shows how to assign a single-item checkbox.

Although there is no requirement that group check boxes appear in proximity to each other on a form, it is conventional to
place the group together. For example, the "Fields to Include" section of Figure 30.1 shows how to use a group of check
boxes to select database fields to include in a query. (Note that the form shows both a multiple-selection list box and check
boxes to accomplish the same selection. On your forms, you would use only one of the techniques.)

As with list boxes, input from check boxes is returned to your program in name/value pairs. For a group of check boxes, the
value list is comma delimited when multiple items are checked. For a single check box, the value is either the value assigned
to the check box or blank.

Check boxes, which are relatively easy for users to work with, are a good choice when you have enough space to include
them and the selections are known in advance. If you are populating selections from a database file, a list box is usually a
better option, since it is difficult to predict how many elements will be in the list.

T e x t In p u t
Text input fields are used to accept character data and are used as output fields when displaying a form. HTML neither
imposes nor allows restrictions on what can be entered, other than the maximum number of characters.

You should always specify both the size of the text field and the maximum number of characters that can be entered, as
shown in Figure 30.2, Label E. You will generally want to specify the same values for both, although you can specify a
maximum length greater than the size. You should use that technique only when you have limited space to display a text
field. When the maximum number of characters is greater than the size of the text field, the text scrolls as it is entered.

Not only is that somewhat annoying, it makes it very difficult for users to review what they entered before submitting the form.

Input from a text box is returned to your program as a name/value pair.

R ad io B u tto n s
Radio buttons are (or should be) always used in sets of at least two. Each radio button in a set has the same name, as
shown in Figure 30.2, Label F. When one of the radio buttons is clicked, it becomes the current selection; any other button in
the same group is unselected.

I once saw a spectacular example of radio button abuse, where only one radio button was in the group. In that example, the
button was "one way"; you could select it but never unselect it. You should use a single-item check box for those types of
selections, not a radio button set of one.

Input from a radio button set is returned as a name/value pair to your program. By definition, only the one selected value is
returned.

Team-Fly
Team-Fly

W e b A ctio n
Now that you know some of the Web page design elements and form elements to use, you can begin designing highly
functional Web pages. Along with studying HTML, you should also study JavaScript, since you will undoubtedly want to add
some editing capabilities to your Web pages.

Although there are many advances in store for HTML in the near future, you will be well served by understanding the basics
presented in this chapter.

Team-Fly
Team-Fly

C h ap ter 31: H T M L : T h e N ew 5250


O v e rv ie w
JOE PLUTA

Throughout the AS/400 industry, there has been a lot of talk about e-commerce and the new storefront applications that the
Web makes available, but there hasn't been a lot of discussion on how to put existing systems online. Although a lot of
attention has been focused on new, graphical applications, I have instead concentrated my attention on making existing
applications accessible through a browser. In this chapter, I explain how a green-screen application can be emulated in a
browser.

Few interfaces have had the kind of success that the 3270 protocol and its descendant, the 5250 protocol, have had.
Designed to provide a low-bandwidth connection from a relatively inexpensive data entry device to a much more expensive
host, the protocol does two things: It presents a block of data to the user and collects a block of data from the user. Other
than a few simple attributes-such as reverse image and blinking and function keys-there was little more to it.

An entire class of programs grew up around that simple idea. At their heart, most midrange business applications are very
much a part of that class of programs that send data one screen at a time and get it back the same way, which is why there
has always been such discomfort whenever programmers try to graft a GUI on top of a 5250 data stream.

The nearly infinite diversity of the graphical interface can actually hinder the development of simple data entry applications.
GUI designers start trying to decide which type of widget best represents a numeric entry field or how to figure out the correct
dimensions for a scroll bar when displaying a subfile. In reality, though, most of the widgets are unnecessary for the bulk of
our applications, especially when they're being put in the hands of experienced users. In that environment, I think it's best to
revert to the old standards, and HTML does just that.

Team-Fly
Team-Fly

W h at's A N ice In te rface L ike Y o u D o in g In A P ro to co l L ike T h is?


The HTTP protocol that underlies the HTML interface is strikingly similar to 5250 interactions, especially with the advent of
JavaServer Pages (JSPs). A JSP-enabled interface basically takes a bunch of fields from the host and outputs them on a
Web page along with a bunch of constant information, and then sends the data, entered into the form fields on the Web page,
back to the host. This sounds suspiciously like a typical 5250 interaction to me.

Not only that, using HTML, you can easily emulate the three primary components of a 5250 display: output fields, input fields,
and function keys. Output fields are simply text output to a Web page, input fields are represented by form fields, and function
keys are shown as submit buttons. Take a look at a very simple 5250 input screen and its HTML equivalent. Figure 31.1
shows a simple 5250 maintenance screen, and Figure 31.2 shows the maintenance screen as it might appear in a browser.

F ig u re 31.1: A typical 5250 maintenance screen presents a panel that the user fills in. After the user presses Enter or
one of the 24 function keys, the contents of its record format are sent to a program for processing.

As you can see, the Web interface lends itself quite well to a simple maintenance panel. The fields can be nicely aligned,
with the buttons representing the function keys at the bottom of the screen. The user can tab through each of the fields,
entering data in each one as necessary. The only difference between the keying sequence in the two panels is that the user
cannot press a function key on the browser panel. Instead, after entering the "Selling UOM" field, the user would have to tab
to the appropriate button and hit Enter. But that could still be done in a "heads-down" environment since it would always be
the same number of tab keys to get to the desired button. For example, if the user wanted to hit the Accept button, he could
hit the Tab key three times from "Selling UOM" and then hit Enter or the space bar to "press" the button.

F ig u re 31.2: A Web-based maintenance screen functions much like its 5250 ancestor.

Team-Fly
Team-Fly

W h at's M y S u b file L in e ?
The other basic interface is the subfile. The bane of RPG programmers, from time immemorial, is that the subfile is absolutely
indispensable in modern midrange business applications. Subfiles are uniquely AS/400, and entire sections of applicant
examinations have been built around their use. Unfortunately, subfiles don't lend themselves particularly well to the graphical
world, because, despite their "multiple-line" appearance, the subfile is still a one-screen-at-a-time interface in many ways. In
fact, depending on the programming technique you use, a subfile can be no more than an array of lines on a single screen;
this was actually the way that multiple-line entry screens were coded back in the days before subfiles.

Attempts to attach a graphical interface to a subfile have met with limited success. The closest "natural" interface in the GUI
world is that of a grid, such as one you might see in a Lotus spreadsheet. But the shifting columns and scroll bar positioning
of a spreadsheet aren't really applicable to the far more structured nature of a subfile. What you need is a number of rows of
fixed fields; what you need is an HTML table. If you look at Figure 31.3, you'll see a typical 5250 subfile; Figure 31.4 shows
the browser equivalent of a subfile.

F ig u re 31.3: Any competent AS/400 programmer knows how to effectively code 5250 subfiles.

F ig u re 31.4: AS/400 programmers who become Web programmers will need a strategy that is equivalent to 5250
subfiles.

Figures 31.3 and 31.4 show how a browser panel can be used to emulate a 5250 subfile. And although creating the browser
panel might have been fairly difficult for a typical CGI program, a relatively simple JSP can do it in just a few lines.

Team-Fly
Team-Fly

U sin g A Jav ase rv e r P ag e A s A S u b file


Figure 31.5 shows the source code for a JSP designed to support the subfile browser panel in Figure 31.4. Although I won't go
into a lot of detail, I will at least point out some of the basic components.

F ig u re 31.5: This is the source code for a JavaServer Page designed to support the subfile browser panel in Figure
31.4 .

 The < h tm l> tag identifies this as an HTML file.

 The < h e a d > and < /h e a d > tags define what will display in the title bar of your browser.

 The < B E A N > and < /B E A N > tags define the variable passed from the servlet to the JSP. In this case, it is a variable of
type Jd sp fD isp la yF ile
ile. Jd sp fD isp la yF ile is designed to emulate a display file.

 The < b o d y> tag indicates the beginning of displayable data. Everything between the < b o d y> tag and the < /b o d y> tag is
sent to the user.

 The < fo rm > tag indicates the start of a form field. All defined fields between the < fo rm > tag and the < /fo rm > tag are
included when the submit button is pressed. In this case, the data will be sent back to the servlet IT M L S T 1_S e rvle t.

 The < ta b le > tag defines the start of a table; the < th > and < /th > tags define column headings.

 The line containing jd sp f.se tC u rre n tR e co rd shows the first use of the variable received from the servlet. The display file
emulation object jd sp f contains data from both the subfile record SFL01 and the subfile control record CTL01. To make
sure I'm getting data from the right format, I execute a se tC u rre n tR e co rd call in Java. An embedded Java statement
starts with a less-than symbol and a percent sign (<< % ) and ends with a percent sign and a greater-than symbol (%% >>).
Then, output a row of data by using the < tr> and < /tr> tags to define a row and the < td > and < /td > tags to define the
data. Inside each pair of < td > and < /td > tags is a Java call to the g e tF ie ld method. Calls to g e tF ie ld return the data
from the named field, making it input-capable if necessary. Note that this row puts out only two columns of data.

 Now switch to the subfile record using another call to se tC u rre n tR e co rd


rd. The n e x tR o w method returns FALSE when
there are no more records, so the WHILE loop serves to output the row that follows once for each record in the subfile.
The row itself (defined by the < tr> and < /tr> tags) simply outputs a column for each field by using the
< td > jd sp f.g e tF ie ld ("F L D N A M ") < /td > syntax.

 The < /ta b le > tag indicates the end of the table.

 Switch back to the subfile control record and use it to retrieve the HTML that defines the roll buttons and the command
buttons via calls to g e tR o llB u tto n s and g e tC o m m a n d B u tto n ss, respectively.

 The < /fo rm > tag indicates the end of the form.

 The < /b o d y> tag indicates the end of the displayable data.

 The < /h tm l> tag indicates the end of the HTML.

And that's all there is to it. As you can see, the code required for the JSP really isn't all that much different, in essence, than
that for a subfile: define the column headings, define the nonrepeating fields, define the repeating fields, and define the
command keys. The source is different because it uses JSP syntax rather than DDS, but the concepts are the same.

Team-Fly
Team-Fly

A n d H e re 's T h e K icke r
The surprising thing about these examples is not that both interfaces share the same basic architecture. The real surprise is
that they share the same RPG application program. The green-screen in Figure 31.1 and the browser panel in Figure 31.2
interface with the same RPG program on the host, as do the screens in Figures 31.3 and 31.4. By designing a set of
emulation classes in Java, it's possible to make the browser behave just like a 5250 screen: Your application program
executes an EXFMT operation (well, actually, it performs a call to an API where it used to execute an EXFMT), and the
browser window pops up for the user.

The features of the 5250 interface can all be emulated within the boundaries of the HTML syntax, with the possible exception
of field-sensitive help (and I suspect even this can be accomplished with a little JavaScript in the HTML). The browser is not
just a place for graphics and animated icons and whack-a-mole games; it's a place to do business, and HTML lets you do
just that.

Team-Fly
Team-Fly

C h ap ter 32: H T M L F o rm V alid atio n W ith Javascrip t


O v e rv ie w
DON DENONCOURT

Our neighbor once asked my wife how her husband could be traveling all over the country teaching Java. He figures he, a
nonprogrammer, taught himself JavaScript in a couple of weekends, so why would programmers travel somewhere to learn
Java or JavaScript (or whatever they call it). Well, my neigh- bor-or anyone else for that matter-is not going to be developing an
accounts payable system in JavaScript soon, but a good programmer can develop an A/P system in Java.

The point is that JavaScript is not Java. JavaScript is a small interpreted scripting language that runs in the context of a
browser. JavaScript's most common use is to jazz up user interfaces and perform simple validation of user input. Java, as with
RPG and COBOL, is a complete, compiled programming language that professional programmers use to build entire
applications.

Originally, JavaScript was called LiveScript. When Netscape, the LiveScript creator, first introduced its new scripting
language, no one cared, but when Netscape's marketing department renamed LiveScript to JavaScript, Netscape's stock
jumped $20 in one day.

Team-Fly
Team-Fly

V alify in g D ata (S h o rt F o r "V alid ate " A n d "V e rify ")


You can do a lot of cool things with JavaScript to liven up your Web pages. Personally, I leave all that stuff up to the Web
developers. For me, as a business programmer, all I want JavaScript to do is validate HTML input fields on the browser. The
trick to developing Web applications that perform well is to use the Internet as little as possible. A Web application that
passes data from an HTML input form to a server-side application program is inefficient if the server-side application responds
with "invalid date" or "quantity must be entered." This is true if it's an AS/400 RPG CGI program, cross-platform Java servlet,
or a Microsoft Active Server Page (ASP). Simple editing of HTML input fields can be done on the client side of the application
by the browser using JavaScript, and this chapter shows you how easy it is.

Figure 32.1 shows a simple address input form. The user entered her address but keyed the wrong state abbreviation. The
pop-up window on top of the form informs the user of the inappropriate value. Figure 32.2 shows the HTML file that contains
the HTML input form in Figure 32.1 as well as the JavaScript that edits that form. (For more on HTML forms, see Chapter 30,
"HTML Basics.")

F ig u re 32.1: Basic editing of dates, codes, and mandatory fill fields should be performed on the client, not on the
server.

 
 

F ig u re 32.2: JavaScript is embedded into HTML. It is parsed and interpreted by the Web browser, not the Web
server .

Team-Fly
Team-Fly

O n S u b m it
The FORM statement includes an option called o n S u b m it. Qualifying the o n S u b m it option with the RETURN keyword and
the name of a JavaScript function creates the link between an HTML input form and a JavaScript edit function. The keyword
THIS, by the way, simply means that the va lid a te function is passed the form data from the current form. If an AS/400
systems programmer had designed JavaScript, he would have probably used *C U R R E N T instead.

The code for the va lid a te function in Figure 32.2 immediately follows the HTML FORM. Notice that the va lid a te function is
embedded into the HTML document. This means that, as with standard HTML, the browser is responsible for parsing the
JavaScript code. The Ja va S crip t function is wrapped by a set of < S C R IP T > tags. The opening < S C R IP T > tag identifies the
language as JavaScript. Many browsers support several scripting languages. For example, you could use VBScript (although
that would limit your clients to those using Internet Explorer). Since both Netscape Navigator and Microsoft Internet Explorer
(IE) support JavaScript, I recommend that you stick with JavaScript. If you think your client base may not be running
Netscape 2.x or IE 3.x or later, you should add the comment line that follows the opening < S C R IP T > tag and its associated
close that precedes the closing < /S C R IP T > tag:
<!- begin hiding of JavaScript from older browsers
// end of hiding JavaScript code ->

These two lines effectively hide the JavaScript code from browsers that don't support JavaScript.

Team-Fly
Team-Fly

M an d ato ry C o d e
The va lid a te routine begins by defining and initializing a set of variables. Notice that the parameter to the function, called
fo rm , is a handle to all the input values from the HTML form. The function retrieves values from input fields by qualifying the
field name with the form parameter name and then asking for its value. For instance, to set the value of the c ity variable, I
used the following statement:
var city = form.city.value;

The va lid a te function then checks to see if the mandatory fill fields contain data. The exclamation point (!) is a NOT operator,
so !firstN a m e is a Boolean condition that evaluates to TRUE when no value is entered for the HTML form's first name field
(firstN
firstN a m e != "" would work just as well). The bodies of the mandatory fill conditional statements all position the cursor to the
form field and then append an error statement to the e rro rM e ssa g e string. After all mandatory fill fields are checked, the
following block of code pops up an error window if the e rro rM e ssa g e contains any data:
if (errorMessage != "") {
errorMessage = "Required field: " + errorMessage;
alert(errorMessage);
return false;
}

The a le rt function popped up the error window shown in Figure 32.1. The re tu rn statement forces the va lid a te function to
exit and, when it returns FALSE, it tells the browser not to send the invalid HTML input data to the server for processing.

Team-Fly
Team-Fly

N u m b e rs A n d A rray s
The code for validating the state code illustrates how you can use arrays in JavaScript, although it would be better if the form
contained a select list for state. To declare an array, you initialize its value with a comma-separated list. The states array is
all uppercase, so the va lid a te function uses JavaScript's to U p p e rC a se function to convert the user-entered state code to
uppercase. The in d e x O f function, which is automatically available to any array and is comparable to RPG's lo o ku p op code,
is then executed on the states array, passing the upper- case value of the state code. When the in d e x O f function returns -1,
you know the user entered an invalid state.

The value of a fo rm variable can be modified with a JavaScript method, as shown in the following statement to force an
uppercase state code:
form.state.value = upState;

The ZIP code is validated by checking two steps: first, making sure that it is a number using the isN a N function and, second,
that the number is either five or nine digits long.

Birth dates are sensitive pieces of information, so the date routine validates only if the year, month, or day is entered. I use
the p a rse In t function, which ignores nonnumeric characters, to convert the string value entered by the user into an integer
before I perform some simple date edits. You might want to strengthen this routine further to handle things such as leap year
and the number of days in a particular month.

Team-Fly
Team-Fly

L ast-M in u te T ip s
Let me leave you with a few last-minute tips. First, to debug your JavaScript, make liberal use of alerts. Second, take
advantage of modular programming techniques by putting your JavaScript routines into separate files, then including them in
your HTML files with the src option of the < S C R IP T > tag, as shown in Figure 32.3 (note that the code for F o rm C h e k.js is on
the companion CD). Third, test your JavaScript code on both Netscape and IE because scripts may behave differently on the
various browsers. Both Netscape and IE have tempting extensions to the base JavaScript language, as standardized by the
European Computer Manufacturers Association (www.ecma.ch) in the ECMA-262 specification. For more information on
JavaScript, visit the Web sites listed in the References section.

F ig u re 32.3: You should use modular programming techniques with JavaScript.

Team-Fly
Team-Fly

R e fe re n ce s
 "e-RPG: Building AS/400 Web Applications with RPG," Bradley V. Stone, Midrange Computing (www.mc-store.com/mc-
store)

 Microsoft Windows Script Technologies Web site: www.msdn.microsoft.com/scripting/

 Sun Microsystems/Netscape Communications Alliance Java Script Sample Code Web site:
developer.netscape.com/tech/javascript/index.html?content=/docs/ examples/javascript.html

 webreference.com/authoring/languages/html/validation.html

 webreference.com/js/tips/browse.html

Team-Fly
Team-Fly

C h ap ter 33: A d van ced H T M L F o rm V alid atio n W ith Javascrip t


O v e rv ie w
JEFF MARKHAM

One of the essential skills in today's e-commerce developer's toolbox is JavaScript. JavaScript, originally developed by
Netscape and released as LiveScript, has undergone a few transformations since its inception, even finding its way to the
server side of e-commerce applications. Probably more often than not, however, it's still used primarily on the client or, more
specifically, with the browser. I'll show you how to use JavaScript for one of the more common tasks in e-commerce
development: form validation.

Team-Fly
Team-Fly

A S h o rt H isto ry L e sso n
JavaScript is a common term to most, but some may still be wondering how JScript or even ECMAScript fit in the scheme of
things. By now, you should be painfully aware of the battles between Microsoft and Netscape. Everybody knows about the
browser wars, but a lesser-known battle within that war is over scripting. Shortly after Netscape developed JavaScript, it was
turned over to the European Computer Manufacturers Association (ECMA), an international standards organization. ECMA
issued its standard, commonly known as ECMA-262, which has the title of ECMAScript language specification. Both JScript
and JavaScript have arisen from this specification. ECMA-262 attempts to solve the matter of cross-browser compatibility, but
this being the real world, there are obstacles to overcome. Microsoft's standard practice of "extending" technologies means
that JScript is ECMA-262-compliant and then some, adding a few more features here and there. In addition, Netscape runs a
little behind when it comes to keeping Navigator in pace with ECMA-262, although its JavaScript version 1.3 claims full
compliance.

JavaScript can reside in a source file external to the HTML page using the source, or it can be embedded directly into the
HTML. When a JavaScript-enabled browser comes across a Web page that has JavaScript in it, the browser activates its
scripting engine and begins to execute, or interpret, the JavaScript code. Without poring through the details of the ECMA
standard, it's hard to say which browser complies with the standard. The ECMA-262 document can be downloaded at
www.ecma.ch, so I'll leave it up to you to read the specification and see how it leaves the two scripting languages plenty of
wiggle room, especially concerning the event model. Nevertheless, they both claim that they are in full compliance with
ECMA-262; however, there are still some instances in which certain object properties and methods work in either Navigator or
Internet Explorer but not both. In other words, cross-browser JavaScript is still the burden of the developer.

Fortunately, there is a way within JavaScript to detect the browser and version by which the developer will want to condition
the processing of the script. For example, the following code snippet will detect your browser's name and version. It works for
all browsers despite using the n a vig a to r object.
var browser = navigator.appName;
var version = navigator.appVersion;

Team-Fly
Team-Fly

Jav ascrip t F o r C lie n tt--S id e V alid atio n


Among the many things you can use JavaScript for is to validate data that a user inputs into a form before that data gets sent
across the wire to whatever you have waiting for it on the server. This is probably the most common use of JavaScript in Web
application programming. Your server-side component may be a Java servlet, an Active Server Page (ASP), or a CGI script.
Whatever it is, you don't want it to choke, gasp, and wheeze by sending it data that it isn't prepared to handle. JavaScript is
an excellent choice to handle this task because all the validation is done on the client (i.e., the browser). Validation done
through the browser gives far greater performance than having to send that form data to the server, having some sort of server-
side data validation, and then having the server send back to the browser any errors that may have occurred. Sometimes this
situation is unavoidable, however.

There are several aspects to form validation, and I'll cover them one by one. I'll start by discussing a little of what is known as
the event model. Every browser has an event model, which means that each browser has a way to let JavaScript know what
event is taking place. For example, when a user presses a key on the keyboard, the o n K e yP re ss event takes place, and if
your JavaScript code does some processing on the o n K e yP re ss event, it will be executed at that time. A major event for form
validation is the o n S u b m it event, which is what normally begins form validation. The o n S u b m it event typically happens when
a user presses an HTML button, created by the < IN P U T > tag, that has su b m it as the value for the tag's TYPE parameter.

Some of the common tasks involved with form validation are checking for missing values in required fields, checking the
format of the data, providing the user with drop-down lists of valid data to enforce validity, and prompting the user for valid data,
as with the F4 key in OS/400.

Checking for missing values in required fields is relatively easy. Assuming that a form called m yF o rm was submitted as a
form to be validated by a script, the way to check if F ie ld A contained any value at all is as follows:
if(myForm.FieldA.length == 0)
.. processing for missing data

Once a field that has data in it is passed to your validation script, you'll probably want to make sure that it's in the format you
want before handing it off to the server. The best example of this is validating dates. Of course, you'll want to make sure that
your dates are valid, that they're in the correct month-day-year sequence, and that they have a valid date separator. That's
actually a lot to check for most developers, but since many of you have plenty of experience in RPG III, I'm sure you're not
scared to perform this basic but essential task.

Figure 33.1 is a simple HTML form with a collection of required fields to be validated. Note the reference to a file called
checkForm.js on the < S C R IP T > tag at the sixth line of Figure 33.1. That file is the modular JavaScript that contains the form
editing functions (ch
ch e ckF o rm .js is available on the code CD included with this book). Figure 33.2 shows how this form looks
in a Web browser.

 
 

F ig u re 33.1: The HTML input form contains input fields that should be validated on the client .
F ig u re 33.2: This form will be validated with JavaScript.

Look at the drop-down list of states in Figure 33.2. You'll notice that the first value in the list is a text value: Select a state. By
default, it is the value that is selected when the form first loads. You want to make sure that a user selects a value in the
drop-down list other than the first value, which is commonly a request to select a value, as in this example. To validate this
field, you'll use the code in Figure 33.3.

F ig u re 33.3: This code is used to validate that the user has selected a value from the drop-down list other than the first
value.

The variable called fo rm is the object that is passed to the validation script. A property of any form is a field name-in this
case, STATE. Because STATE is a drop-down list created by the HTML tag < S E L E C T >>, you can use the se le cte d In d e x
property, which is simply a zero-based number of what value in the list was selected. Here, the value S e le ct a sta te has the
value of 0. If I assign a variable to that se le cte d In d e x value, then I know that if the value is 0, the user hasn't selected a state
value. If this happens, I add that error to an error array. (For more about error arrays, see the "Handling Errors" section.)

Team-Fly
Team-Fly

Is T h at A R e g u lar E x p re ssio n ?
A good way to validate the format of values entered into fields is by using what is known as a regular expression. The fields of
ZIP code, phone number, and birthday will give you a little introduction. Regular expressions are rooted in research that was
done on the human nervous system back in the 1950s. Later, when UNIX was invented, they were called on to provide the
foundation for search algorithms. Regular expressions are quite common in UNIX environments and have shown up in
JavaScript as well, which is a good thing, because without regular expression support, validating fields would be a more
involved programming task. There is no better way to begin a discussion about regular expressions than by showing you what
one looks like.

For a ZIP code in the United States, there are really only two formats: a five-digit number or a five-digit number followed by a
four-digit number separated by a dash. The following formats are two possible ways to show the two ZIP code formats as
regular expressions:
/^(\d{5})$/
/^(\d{5})(\-)(\d{4})$/

As you can see, the format of regular expressions is not exactly intuitive. I'll break apart the second regular expression to
look at some of the syntax. In JavaScript, regular expressions are contained within slash (/) characters, as this one is. The
caret (^) character signals the beginning of an input line, meaning a line that will be matched up against the regular
expression.

You can see that there are three groups of characters or "patterns" enclosed in parentheses. This is just a matter of
programming style. I've gotten into the habit of breaking apart regular expressions into these patterns because, when they are
matched against a string, I can get at the values of those patterns in an array that's created when the matching takes place.
The first and third patterns are basically the same. The backslash (\) character indicates that some kind of special character
is next. In this case, it's the letter d, which is used to match a digit 0 to 9. The values placed in enclosing brackets, "5" in the
first pattern and "4" in the third pattern, tell the expression to match that many times for the value before them. In this case, it
is the special character d that means, for the first pattern, check for five digits, and for the third pattern, check for four digits.
The dollar sign ($) character signals the end of the input line. (To find out more about regular expressions, see the Web sites
in the "References" section.)

Assuming that you are comfortable with regular expression syntax, how do you use regular expressions? Here is some code
from the example to validate the BIRTHDAY field:
var datePat = /^(\d{2})(\/)(\d{2})\2(\d{2}|\d{4})$/;
var dateMatchArray = bday.match(datePat);

I've declared a variable called d a te P a t, which is essentially the regular expression. I then declare an array that is populated
by matching the BIRTHDAY field against the regular expression. Take a second to look at the snippet. How is the array
populated? What's in the array? The array is populated as a result of calling the m a tch () method. The array is populated with
any and all matches for the entire string being matched against the regular expression and the values of the patterns
mentioned earlier. In this example, a valid date will be the first value in the array, followed by the values of the month, date
separator, day, and year. A date is a good example of not only validating an entire string but also breaking apart values into
the patterns of the regular expression. That way, the month can be validated as well as the day to see if the combination of
the two is valid. The example takes care of that scenario as well.

Team-Fly
Team-Fly

H an d lin g E rro rs
What happens when the form has errors in it? I mentioned that errors are sent into an error array to be displayed for the user.
I suppose that this topic falls under the category of programming preference and style, but I've always thought it to be good
practice for a form to collect as much error information as possible and display it at once, rather than catching an error,
showing an error dialog box, and iterating through that process until all the errors have been caught and corrected.

Figure 33.4 illustrates what I'm talking about. The error shows that I've forgotten to select a state from the drop-down list and
that I've entered incorrect values for the ZIP code, Phone number, and Birthday fields. Rather than catching the first error (not
selecting a state) and displaying that error for the user to correct, I populate an error array that is in fact a string array and
then cycle through the array at the end of the script, formatting the elements of the error array into one String object to be
displayed in the JavaScript alert window.

F ig u re 33.4: Display as many error messages as you can in a single dialog box.

Team-Fly
Team-Fly

D e te ctin g Jav ascrip t S u p p o rt


Now, some of you may be more familiar with JavaScript than others, and while reading this chapter, you may think, "Yeah,
but what if the user disables JavaScript in the browser?" It's true, all of your good form-validating intentions and whiz-bang
JavaScript could be for naught if the browser displaying your page has no JavaScript capabilities or has those capabilities
disabled. What then? In this situation, your users will be able to submit just about any value they wanted if form validation
depended solely on JavaScript. You could validate all the data on the server, but that would defeat JavaScript validation
altogether and would be a waste of server resources.

JavaScript forums and newsgroups are littered with a common question JavaScript newcomers often ask: "How can I write a
script that will detect if JavaScript is disabled or not?" The answer, of course, is you can't, because if JavaScript is disabled,
no detection script will be able to run. A little trick that I use in this situation is to put a hidden field inside the form called
va lid a te dd. If you look at Figure 33.1, you'll see it has a value of n oo. In the script, if there are no errors, I set the field's value to
ye ss. On the server, you'd have to have a component check the value of that field, and if it is yes, then JavaScript did its job in
checking the field values before they were passed to the server. If it's no, then JavaScript couldn't change the value from its
original state, indicating that JavaScript was disabled on the browser that sent the form. In this case, either a server-side
component would be responsible for data validation or you could send back a standard reply to the user's browser informing
the user that JavaScript is required to use the site.

Form validation is a great and sometimes necessary way to become acquainted with JavaScript. Also, as AS/400 developers,
you're already acutely aware of how important form validation is in creating business applications. Combine this client-side
technology with your already mature server-side knowledge so that your browser-based applications are as efficient and well
rounded as possible.

Team-Fly
Team-Fly

R e fe re n ce s
 Client-side JavaScript Reference (online reference manual available at
developer.netscape.com/docs/manuals/js/client/jsref/index.htm)

 ECMA home page: www.ecma.ch

 Microsoft Windows Script Technologies: msdn.microsoft.com/scripting/

Team-Fly
Team-Fly

C h ap ter 34: U sin g C o o kies T o P ass P aram eters B etw een W eb


P ag es
O v e rv ie w
DAVID MAYLE

While cookies are a staple in the diet of Homer Simpson, the cookies I'll discuss in this chapter aren't edible. Cookies are
used as a part of an Internet design strategy for the purpose of adding state to a Web page. HTML, by design, is a static
(stateless) language. When an HTML document is loaded, it has no idea of what has occurred beforehand. RPG, on the other
hand, is a language that has state. By using constructs such as data areas and parameters, an RPG program can discern
what has occurred in previous processes and react accordingly.

Cookies were developed to act as data areas for Web pages. Plain and simple, a cookie is a chunk of data that a server
application can store on the client system in the form of an entry in a text document. This data can then be retrieved at a later
time by another Web page (on the same domain) in order to identify the user, determine the date and time of the last visit,
and so on. By using this mechanism, Web pages are now able to have state.

Request for Comments (RFC) 2109, which was published in February 1997, lays down the groundwork for cookies. See
http://info.internet.isi.edu/in-notes/ rfc/files/rfc2109.txt for a document that describes an HTTP state management mechanism
and introduces two new methods: cookie and set-cookie. Netscape originally developed the concept of the cookie, but the
accepted implementation today is based on RFC 2109.

Cookies are probably one of the most misunderstood Web tools currently available to the Internet developer. There is a great
deal of misinformation that surrounds their use. The only information that can be retrieved by using a cookie is information that
was placed on the client by the server.

A cookie cannot retrieve an email address, a user's name, a Social Security number, or any other private information unless
the user has volunteered that information in the first place. A cookie is not a two-way street; the server serves the cookie and
the server retrieves it as well. Since cookies are stored in text format and are not executable, they cannot be used for
malicious activities such as spreading viruses. For further information on the security aspects of cookies, visit
www.ciac.org/ciac/bulletins/i-034.shtml to view an assessment by the Computer Incident Advisory Capability Division of the
U.S. Department of Energy.

Team-Fly
Team-Fly

C o o kie C re atio n
Now that I have covered the basics of what cookies are, it is time to delve into the aspects of coding them. Figure 34.1
presents a simple cookie written in JavaScript that determines the number of times a user has visited a Web page, as shown
in Figure 34.2. The example script consists of two functions, se tC o o kie and re trie ve C o o kie
kie. The rest of the script is used to
control the logic of setting and retrieving the cookie. This script will work in either Netscape Navigator or Microsoft's Internet
Explorer; this is important when working with scripts because they sometimes behave differently in each browser.

F ig u re 34.1: With a few lines of JavaScript (which work in both Netscape and Internet Explorer), you can maintain user
state with cookies .
F ig u re 34.2: This simple cookie JavaScript application informs the browsing user how often he has visited this
page.

I'll begin by examining the se tC o o kie function of the script. This function is the portion of the script that places the text string
in the cookie file. The se tC o o kie function has six parameters that provide all of the necessary information for setting the
cookie. The NAME parameter is used to identify the cookie, because a single Web page can set multiple cookies if
necessary. In this example, my cookie is called co u n te rr. The next parameter, VALUE, is the value of the cookie. Here, I am
just using it to store a number, but it could be used for virtually anything. If you examine the co o kie s.tx t file on your PC, you
are bound to find all sorts of cryptic information that is only meaningful to the server that put it there. The expiration date of the
cookie (EXPIRES) is the next parameter. It determines when the cookie will be purged from the co o kie s.tx t file. The next
parameter, PATH, is a path name. If this parameter is not specified, it defaults to the path of the document that is setting the
cookie. Next is DOMAIN; the domain name is optional and defaults to the domain where the document resides. The final
parameter, SECURE, is a Boolean value that determines whether the cookie needs to be served from a secure server.

Now that the parameters have been covered, it's time to examine the actual code that sets the cookie. Setting the cookie
only requires two lines of code and is quite straightforward. The variable statement builds a string called C o o kie N a m e that
will be placed in theco
co o kie s.tx t file. The d o cu m e n t.co o kie method sets the string C o o kie N a m e in the cookie file. If you
visit my Web site at www.bushforprez.com/cook ie3.htm, the following tab-delimited line of text will be in your co o kie s.tx t file:
www.bushforprez.com[tab]FALSE[tab][tab]FALSE[tab] 959521544[tab]
counter[tab]1

Team-Fly
Team-Fly

R e trie v in g C o o kie s
Now I'll explain how to go about retrieving a cookie, which is what the function re trie ve C o o kie does in the example. Placing
a cookie on the client isn't worth much if there isn't a way of retrieving it at a later time.

The re trie ve C o o kie function performs two tasks. First, it retrieves the cookie from the client, and, second, it parses the
information retrieved to extract the number of visits the user has made to the Web page. The function has only one parameter:
the cookie to be retrieved. The re trie ve C o o kie function uses the in d e x O f method to determine an offset for the starting
position of the number of visits in the string. Next it determines the length of the value and extracts it via the su b strin g
method. If a null value is returned, that null indicates that this is the user's first visit to the page. Finally, the RETURN
command is used to pass the number of visits back to the main part of the program.

Team-Fly
Team-Fly

C o o kie s P ro g ram m in g
It's time to examine the main program portion of the script in order to tie everything together. The first thing the script does is
calculate the expiration date for the soon-to-be-set cookie. The following code seems odd, but there is a simple explanation
for it:
expdate.setTime(expdate.getTime() +
365 * 24 * 60 * 60 * 1000);

Cookies calculate dates in milliseconds, which is the reason for this rather bizarre method of calculating the expiration date.
Simply put, the expiration date equals the current date plus 365 days in milliseconds.

Next, the function re trie ve C o o kie is invoked and returns to the variable called n u m visits the number of times the client has
visited. If the value is null (nn u m visits = = n u ll), it is the client's first visit, and the appropriate greeting is displayed. If the value
is not null, a message is shown indicating the number of visits that have been made.

The variable n u m visits is then incremented by one to reflect the return visit, and the se tC o o kie function is invoked to update
the co o kie .tx t file. It should be noted that the call to se tC o o kie only sends three of the six possible parameters to the
function. The final three parameters (PATH, DOMAIN, and SECURE) are optional and will default to the values mentioned
earlier if not passed.

Team-Fly
Team-Fly

M ain tain in g A p p licatio n S tate


Congratulations! You have just learned all that you need to know to use cookies in your Web design strategy. (Well, maybe
not everything, but it's a start.) At this point, you might be thinking that this is a nice technology, but is it really that useful?
The simple example in this chapter is just one of an endless array of functions that cookies may be used for. Imagine trying
to code an application in RPG or COBOL and not being able to pass parameters. If that were the case, you probably would
end up with one massive program that was neither flexible nor efficient.

If you have ever visited an online store, chances are you have accepted cookies onto your PC. Cookies make online shopping
carts possible. Every time you select an item for purchase, a cookie is set to record the purchase. At checkout time, all of
the cookies that have been set are retrieved to tally up your order. If cookies were not available, the entire online store, the
order form, and so forth would have to be on the same Web page.

Another popular use for cookies is site customization. What do I mean by that? Well, if you have ever been to a Web site that
allows you to choose things such as what background color you want, the color of the text, or the kind of news you like, that
is being done with cookies.

Team-Fly
Team-Fly

D o I H av e T o U se Jav ascrip t?
The cookie example in this chapter is written in JavaScript because, in my opinion, JavaScript is the most easily
comprehended scripting language, but it is certainly not the only solution out there. Just about any scripting language-Perl,
CGI, or any of the multitudes of scripting languages available-can be used for cookies. (Editor's note: Java servlets have a
standard API for cookies that is very easy to use.) What language is best depends on the level of complexity of the cookie
script. For more complex cookies, such as those used in shopping carts, Perl or CGI is probably a better choice than
JavaScript because they are more robust languages.

Team-Fly
Team-Fly

S e rv in g C o o kie s W ith Jav a


Web applications must maintain state between server and client interactions, but there's the small problem of HTTP being a
stateless protocol. After an HTTP server responds to a client request, the connection is closed. As I've shown, the use of
HTTP cookies allows you to circumvent this problem. Cookies were being used to maintain state long before Java servlets
became available, but the Java servlet API makes using cookies extremely easy. Figure 34.3 shows a Web application called
C o o kie sS e rvle t. All C o o kie sS e rvle t does is list all the cookies sent from the Web browser. If no cookies are found, the
servlet creates one called p ro file and sets its value to d e n o n co u rt.

F ig u re 34.3: This Web application, called CookiesServlet, lists all the cookies sent from the Web
browser.

Using cookies with Java is easy. The se rvice rvice, d o G e t, and d o P o st methods (which are called by the Web server to respond
to a user request) all have two parameters: an H ttp S e rvle tR e q u e st object and an H ttp S e rvle tR e sp o n se object. The
H ttp S e rvle tR e q u e st class has a method called g e tC o o kie s that returns an array of Cookie objects. The C o o kie class
encapsulates access to the cookie information in an HTTP header; it has methods to get and set all the attributes of a
cookie. The C o o kie class's se tM a x A g e method, for instance, sets the EXPIRES attribute with an integer that is the number
of seconds from its creation time. (In the example in Figure 34.3, I used 30 days' worth of seconds.)

The H ttp S e rvle tR e sp o n se class has a method called a d d C o o kie so that you can add or update cookies that are to be
stored by the Web browser in the file system of the client's machine. All your application needs to do is instantiate a Cookie
object, set its attributes with setter methods, and add the cookie to the HTTP response with the a d d C o o kie method of the
H ttp S e rvle tR e sp o n se class. Then, on subsequent user requests, your Web application can find the cookie in the array
returned from the g e tC o o kie s method of the H ttp S e rvle tR e q u e st object.

Team-Fly
Team-Fly

P o w e r C o o kie P ro g ram m in g
Cookies are a valuable tool for an Internet developer because certain functions simply are not possible without them. The
script presented in Figure 34.1 provides the framework for just about any kind of cookie you wish to create. Have fun with it.
Be creative, and you will learn the true power of cookies.

Team-Fly
Team-Fly

C h ap ter 35: X M L : T h e U b iq u ito u s L an g u ag e O f T h e In tern et


O v e rv ie w
DON DENONCOURT

One of the hottest subjects in Web development today is the Extensible Markup Language. XML is extensible because it is
used to quickly develop custom languages. Just what we need, you may be thinking; not only do we have another language,
but that language is used to proliferate even more languages.

When I first heard of XML, I too felt the same way. XML reminded me of the story of the Tower of Babel from the book of
Genesis. The people of Shinar decided to build a tower that reached up into the heavens. According to the book of Genesis,
the Lord said, "Behold, they are one people, and they have all one language; and this is only the beginning of what they will
do; nothing that they propose to do will now be impossible for them." To thwart their efforts, the Lord caused them to speak in
so many different languages that their inability to communicate resulted in the failure of the tower's construction.

Today, Java is the one language that enables us to unify the construction of what might not reach the heavens but certainly
extends to the far reaches of the world. Then someone comes along and introduces XML, a language used to propagate other
languages. My initial reaction to this new language, and the languages that it spawns, was what the people of Shinar felt-
confusion. Ah, but after only a little research, my confusion turned to understanding as I discovered that XML accomplishes
exactly the opposite.

XML is a standard strategy for defining the content in documents and databases. XML is poised to be the universal strategy
for the storage, transfer, and manipulation of data across the Internet. As with the story of the Tower of Babel, there appears
to be one people because all the powers-Microsoft, IBM, Sun, Netscape, and so forth-seem to agree that XML is a great tool
for the unification of documents and databases on the Internet. (Coincidentally, among the early adopters of XML were
publishers who wanted to improve the dissemination and presentation of the Bible on the Internet.)

Team-Fly
Team-Fly

M in i D atab ase s
When I first began to program on the PC in the late '80s, I continually searched for database tools. On the AS/400, the
database was integrated into its operating system, but PCs had no standard database. Often, I ended up using Lotus 1-2-3 or
Microsoft Excel as a substitute for a standard PC-client database so that I could transfer AS/400 data to PC clients for local
database access.

When I first started to program in Java, I was still looking for a standard PC- client database, but the problem had grown much
larger. That database was no longer limited to one company; now that data had to be available across the Internet with
storage on dissimilar databases.

Today, there are more database options available than there were 15 years ago (such as Microsoft Access and IBM's
Universal Database). However, although these databases are sophisticated and powerful, they are not inexpensive or
standardized. XML provides a free method for the storage and delivery of data and documents. XML will be the ubiquitous
database of the Internet.

Its marriage with the Java programming language makes XML already available for deployment on the Internet. You will find
that Java is to XML what RPG is to DDS, with two primary differences. First, Java is portable code, whereas an RPG program
is not. Second, XML is portable data, whereas DDS is limited to the AS/400.

Team-Fly
Team-Fly

C o n te n t, S tru ctu re , A n d P re se n tatio n


Any stored piece of information-whether in the form of a relational database file, a text document, or an HTML Web page-has
content, structure, and presentation. On the AS/400, information content is retained in DB2 for OS/400 database files, and
the structure of that data is maintained in data description specifications. The presentation of DB2/400 data is enabled
through RPG and COBOL programs and screen files described with DDS.

On the Web, information is stored as HTML files. With HTML, information content, structure, and presentation are all
maintained in one file. HTML tags such as < h e a d > , < p >>, and < ta b le > demarcate the structure and presentation of an HTML
file, and the content of an HTML file is maintained between those HTML tags. The problem with HTML is that the content of a
document is tightly coupled with its presentation. Furthermore, the tags of an HTML document do not describe its content;
they describe only its presentation.

XML resembles HTML in that it also contains tags that enclose data content. However, XML differs from HTML in that its tags
more accurately describe the structure of data; furthermore, those tags do not specify anything about the presentation of an
XML document's data. For instance, an HTML file that contained personnel information might use the bold tag (<< b >>) to
contain an employee's name:
<b>Teresa Pelkie</b>

When you look at the HTML file, you see tags that control the presentation of that document but say nothing about its
content. With an XML file, on the other hand, the employee name might be enclosed in a custom tag that clearly describes
its content:
<employee>Teresa Pelkie</employee>

XML allows you to define the elements of a document just like DDS allows you to define the fields of a record. In fact, a
DB2/400 record can easily be converted to an XML document. Figure 35.1 shows the DDS for two files: a purchase order file
and a purchase order line-item file. Figure 35.2 shows the contents of information stored in an example purchase order
database and retrieved with SQL. The DDS field names for those files can easily be used as XML tags to define the structure
of an XML document such as the one shown in Figure 35.3.

F ig u re 35.1: Using the AS/400's DDS, you can define the structure for a database file.

F ig u re 35.2: SQL can be used to list the contents of related files.

 
 

F ig u re 35.3: DDS field names can be used as XML tags to define the structure of an XML document.

Within these figures, I have generated the syntax for a new language, an XML language. I'll call it Purchase Order XML, or
POXML. Notice that the purchase order data becomes the information content of the XML document. You can see that it
takes little effort to write utilities that convert DB2/400 files into XML data, such as my example POXML. At this point, you
might be wondering how an XML document such as the one in Figure 35.3 is to be displayed since it does not contain any
presentation tags like those that would be used in an HTML document.

Because the POXML document shown in Figure 35.3 is a text file, it can already be displayed in a Web browser. The browser
simply ignores all the tags that it is not familiar with to present the following:
11 Exxon 01151998 9832 7 3241 4 12 Disney 01121998 7391 2

But this is just raw data; it is not information because its presentation is not readable. XML must be formatted before it can be
properly presented in a Web browser. Internet Explorer 4.0, for example, ships with a Java applet called X M L D S O that can be
used to present XML data in an HTML file. Figure 35.4 shows a Web page that Internet Explorer 4.0 presents when I open the
HTML file shown in Figure 35.5. The HTML file uses Microsoft's X M L D S O Java class to retrieve content from the XML
document specified in the HTML's applet tag. The particular elements of the POXML document of Figure 35.3 are referenced
in the HTML file by the d a ta src and d a ta fld options of HTML's < ta b le > and < d iv> tags, respectively. Note that this HTML
won't function properly in Netscape Navigator, which points out the need for a standard method for the presentation of XML
content.

F ig u re 35.4: Internet Explorer 4.0 ships with a Java applet that can be used to present XML data in an HTML
file.
 

F ig u re 35.5: HTML's applet tag is used to invoke Microsoft's XMLDSO Java class that retrieves content from an XML
document for HTML presentation .

The standard strategy for presenting XML content entails the use of yet another language called the Extensible Stylesheet
Language (XSL). The World Wide Web Consortium (W3C) officially recommended the XML specification in February 1998.
Since that time, a number of XSL utilities have become available. IBM's alphaWorks site (www.alphaWork s.ibm.com) hosts a
free XSL processor called LotusXSL (as well as a half-dozen XML utilities). Apache has its xalan (available at
jak arta.apache.org). Microsoft's Internet Explorer version 5.0 actually has the ability to dynamically convert XSL into
presentable HTML.

But if you want to service other Web brows- ers, you should use a server-based XSL processor that creates HTML pages from
XML documents as an interim step before being served to a browser. The Web page presented in Figure 35.6, for instance,
displays content from an HTML file that was generated using IBM's LotusXSL processor. The XSL file that the LotusXSL utility
used to process the POXML file of Figure 35.3 into HTML is shown in Figure 35.7.

F ig u re 35.6: HTML can be generated using one of the several available, free XSL processors.
 

F ig u re 35.7: Lotus's LotusXSL is an XSL processor that converts XML to HTML .

XSL is kept separate from the XML data because XML may also be used to generate output other than HTML. Suppose you
have a system that prints purchase orders. You might also want that system to send purchase orders to another party in the
form of an email. You might even want to convert the purchase order XML document-which was generated from DB2/400-to an
Oracle database.

Team-Fly
Team-Fly

R u le s
An order is not an order without at least one line item, and a line item is not valid without a quantity or a part number.
DB2/400 ensures such constraints with referential integrity, triggers, and explicit coding in high-level language programs. XML
handles these constraints through a mechanism called document type definitions (DTDs). DTDs are used to define rules that
control how XML documents are structured. The DTD then forces users of a specific XML language to conform to the DTD
rules in the creation of XML documents.

Figure 35.8 shows an example DTD for the purchase order implementation of an XML language. The DTD says an order must
have an order number, a customer name, an optional date, and a purchase order lines element. The POLINES element must
then contain one or more POLINE, and each POLINE element must have a part number and a quantity (the cost is optional).
For an XML document to be validated against a specific DTD, it must have a < D O C T Y P E > tag added to the top of the XML
document:

F ig u re 35.8: Document type definitions are where you specify rules that an XML document must conform with to be a
valid document for that specific implementation of an XML language.

<!DOCTYPE PO SYSTEM "PO.dtd">

Team-Fly
Team-Fly

H e ritag e
Although XML may be a new language, it has a rich heritage. Charles Goldfarb of IBM developed Generalized Markup
Language in 1969, and in the late '80s, the standards community extended the idea into the International Organization for
Standardization Standard Generalized Markup Language. SGML, however, is too complex and bulky for most Internet
applications, so XML was introduced several years ago as a powerful but simplified subset of SGML. In fact, XML is itself an
implementation of SGML. Any SGML processor will be able to parse any XML document. It is interesting to note that HTML is
also a subset of SGML. The main difference between HTML and XML is that XML is a framework for creating markup
languages and HTML is just an example of a markup language.

Team-Fly
Team-Fly

U se s
Even in my limited domain, I see great potential for XML for the storage, transfer, and manipulation of cross-platform
databases. But the potential of XML goes far beyond what my legacy relational database mentality can fathom. One obvious
industry for XML is electronic data interchange (EDI). EDI has already greatly contributed to the automation of business-to-
business transactions. Yet despite EDI's proven cost-saving strategy, only 2 percent of businesses are using EDI today,
mostly as a result of its complexity. An XML language called Online Transaction Processing (OTP) is already making inroads
as a new and improved EDI. OTP drastically reduces the complexity of EDI's cryptic protocol, thus making EDI accessible to
more companies.

XML is more than just a promise; it is already used in a wide variety of industries. In all likelihood, you are using XML today
without knowing it. If you have Internet Explorer 4.0 installed on your system, you are using an XML language called Channel
Definition Format (CDF). If you use a financial package, you could be using an XML language called Open Financial
Exchange (OFX). And if you are using IBM's AS/400 Client Access Express for Windows, you might not realize that IBM
adopted XML as a protocol for the transfer of information from the AS/400 and your PC client. Many companies are using XML
as a part of innovative Internet strategies for market dominance in their industry-they just don't want you to know how easy it
is to use XML.

Team-Fly
Team-Fly

C h ap ter 36: X S L S tylesh eets: D isp lay F iles O f T h e W eb


O v e rv ie w
EDUARDO ROSS

Alittle over a year ago, I created my first Web application to publish AS/400 data. The application was based on a three-tier
architecture. In the first tier, a Web browser presented the data to the user. In the middle tier, Active Server Pages (ASPs)
coupled with ASNA Visual RPG (AVR) components implemented the business rules. In the third tier, an AS/400 was serving
the data. The technologies involved were pretty easy to grasp. Besides learning the basic mechanics of Web serving, I had to
learn a little HTML and how to create ActiveX components to interact with the ASP machinery.

Even though I could have created an ActiveX component or Java applet to deliver logic to the user, I opted against it for three
reasons. First, users can be impatient and might not have waited for the component to download to their machines. Second,
the application would have become dependent on the user's platform, especially in the case of an ActiveX program, and some
users might have been marginalized. The third reason for avoiding this model was scalability. When a component is running
on a browser and accessing data directly on the AS/400, the architecture being used is the traditional client/server, which,
apart from increasing the security concerns, imposes huge demands on the AS/400. Each user navigating through the Web
application would start at least one AS/400 job. Imagine the number of active jobs the machine would have to support at Web
rush hour! For these reasons, I chose the three-tier model, which nicely addressed all of these issues.

Team-Fly
Team-Fly

W h y U se X M L ?
Under the three-tier architecture, the middle tier accesses data from DB2 for OS/400, processes it, and produces HTML. The
HTML is then sent to the browser, which presents the data in its window. HTML is a format used to direct the browser on how
to present the data. However, developers producing HTML directly from within their application end up "contaminating" the
application by inserting code for HTML alongside that of the application's business rules. They also end up with applications
that are useful only when accessed from a Web browser. Modern Web applications should produce XML. (For an introduction
to XML, see Chapter 35, "XML: The Ubiquitous Language of the Internet.")

To get an idea of how problematic it is to generate HTML from an application, imagine that, within your RPG or COBOL
program, you had to deal with the details of the 5250 data stream used with dumb terminals. Your program would end up
being very hard to maintain, and any changes to the appearance of the screen would imply code changes and program
recompiles. In the case of Web applications, this problem is compounded because Web masters, usually hired by the
marketing department, have strong opinions on how information should be presented to the user.

Team-Fly
Team-Fly

S e p aratin g P re se n tatio n F ro m D ata


On traditional AS/400 applications, you separate the data itself from the way the data is to be presented to the user. A
display file serves as a template, which is merged with the data calculated by a program to form what the user sees on the
screen. This merging happens when the program issues a write or an execute-format to the display file. The need to separate
the presentation from the data becomes more demanding as the dynamism of the Web site grows. The trick to this
separation is to output the data produced by the application in XML and then apply a transformation to it using some form of
an externally described format.

Extensible Stylesheet Language (XSL) is a language used to define stylesheets. A stylesheet contains templates indicating
how to transform data from XML into HTML. XSL is a declarative language, not a procedural one. Conceptually, it is more like
O-specs than C-specs. With XSL, a set of templates is built to process specific types of XML documents and transform them
into HTML or even to create a new XML document with a different structure or format. When the HTML is needed, a processor
(which I'll describe in a moment) takes the templates in the stylesheet and applies them to the document. This process is
similar to doing a "mail merge" using a word processing program.

Team-Fly
Team-Fly

L ike A T re e
A well-formed XML document can be described as a tree, with a single element as its root and multiple elements and
subelements as the branches and leaves. The elements in the tree are known as nodes of the tree. At runtime, templates in
the stylesheet are matched with the nodes of the trees. When a match is made, the corresponding template is applied. This
results in a transformation of the XML document to, for example, another XML document of a different type or an HTML
document. This transformation is done by an XSL processor, and it can occur either on the client side (if the user has a newer
Web browser) or on the Web server itself.

When the process is done on the server, the programmer needs to call processor methods. XSL processors are also bundled
with other Web products. Microsoft provides its processor as an ActiveX component, which is included with Internet Explorer
5.0; it is accessible from languages such as Visual Basic (VB) and AVR. IBM makes the LotusXSL processor, a set of Java
classes that is available as part of WebSphere Application Server Version 3.

Formally, XSL is divided into two areas. One area deals with the selection of nodes, and the other area deals with the actual
transformations. The World Wide Web Consortium (www.w3c.org) released the two standards defining these areas in
November 1999: XSL Transformations (XSLT) and XML Path Language (XPath).

Team-Fly
Team-Fly

A C lo se r L o o k A t X sl
XSL uses XML as its syntax, which has several advantages. The main advantage is that, in general, the tools and
technologies created for XML can be used for XSL immediately. Currently, programmers and Web masters have to create the
stylesheets by hand with text editors. However, the wave of WYSIWYG editors for stylesheets is approaching the shore
quickly. For now, though, having XSL use the XML syntax frees XML authors from having to learn another markup language.

Take a look at an example. Figure 36.1 shows an article listing in XML format. In the example, the element < C a ta lo g > is the
root. It contains two branch elements, < C a te g o ry> and < A rticle s> . The < A rticle s> element has five subelements, all of
them of type < A rticle > . Each < A rticle > subelement has four attributes, the details of which pertain to individual articles.
Figure 36.2 shows a stylesheet written in XSL that contains a single template to transform the list of articles into a
displayable table. Figure 36.3 shows a browser displaying the result of the transformation.

F ig u re 36.1: This is the XML article listing to be transformed into HTML.

F ig u re 36.2: A single template in this XSL stylesheet is used to transform the list of articles into a displayable HTML
table.
F ig u re 36.3: The transformation from XSL to HTML gives this browser display.

The template matches the root node by indicating a slash (/) as the pattern to find. The content of the template is basically an
HTML file with "holes" in it that are to be filled with data coming from the XML document. These holes are marked by the
element < x sl:va lu ee--o f>
f>, which outputs the actual value of the selected node. The node is selected by specifying its path
from the root or whatever the current node might be. To access attributes of an element, prefix the attribute name with an at
sign (@), like this:
Catalog/Category/@ID.

To work with a list of similar nodes, such as the actual list of articles, use < x sl:fo rr--e a ch > . This instruction will iterate over the
list of selected nodes, applying whatever transformations are indicated within it. At every iteration, the selected node becomes
the current node. References to elements and attributes of the node are done by using their names directly, such as
< x sl:va lu ee--o f se le ct= "@ D e sc" /> . The < x sl:ch o o se >>, coupled with < x sl:w h e n > and < x sl:o th e rw ise >>, is very similar to
RPG's SELECT op code, allowing for conditional execution of the template sections.

XSL transforms the XML tree into a new tree, allowing extensive reordering, generated text, and calculations. This is in
contrast to Cascading Style Sheets (CSS), which only "decorate" an XML tree with formatting properties.

The XML source generation can be maintained by the programmer from the perspective of "pure content" and can be delivered
simultaneously to different users by providing different stylesheets. In my example, I could deliver basic catalog information,
article ID, and quantity available to a palm-top device just by switching the stylesheet.

Team-Fly
Team-Fly

A n d It's Ju st G e ttin g S tarte d


You can use stylesheets to convert an XML document from one schema to another without having to write a program. This
capability will become extremely useful as XML technology starts to encroach into the electronic data interchange (EDI)
domain. And even though the current implementations of XSL-supporting products may differ from vendor to vendor, it is
worthwhile getting a head start with the technology that will change the landscape of data processing by starting some pilot
projects within your organization.

Team-Fly
Team-Fly

R e fe re n ce s
 Converting XML to HTML Using XSL in the IBM WebSphere Environment: www.developer.ibm.com/library/ref/xmlxsl.html

 MSDN Online Web Workshop-XSL Developer's Guide: msdn.microsoft.com/xml/xslguide

 W3C Extensible Stylesheet Language (XSL): www.w3.org/Style/XSL

Team-Fly
Team-Fly

C h ap ter 37: U n ix D evelo p ers F in d A H o m e In Q sh ell


O v e rv ie w
WALTER GOODWIN

With the release of the Qshell Interpreter in V4R3, IBM took another step toward making Java and UNIX developers feel more
at home.

Qshell was not IBM's first attempt at attracting UNIX developers. But while previous OS/400 enhancements such as the ILE-C
compiler, Integrated File System (IFS) stream files, and the POSIX-based openness APIs were significant modifications, UNIX
users may have been discouraged by the CL command interface of OS/400. The fact is that many UNIX developers use a
toolbox full of extendable command scripts that simplify their work. Although OS/400 is still a long way from being another
UNIX, Qshell on the AS/400 may be the program these developers have been hoping for.

IBM believes there are several reasons why Qshell is a compelling AS/400 development tool. One reason is that the Java
Development Kit (JDK) tools provided with the AS/400 Developer Kit for Java have a UNIX-style command syntax. Another
reason is the open-source software (OSS) phenomenon. Many OSS projects have produced large, robust server applications,
such as the Apache Web server, which are freely available on the Internet. Almost all OSS projects were initially developed on
a UNIX platform, and many, including Apache, have been ported to other platforms. Qshell may provide OSS developers with a
less painful route to port applications to the AS/400.

Team-Fly
Team-Fly

W h at Is A S h e ll P ro g ram ?
A shell program is a command interpreter and set of associated commands, much like the QCMD CL command interpreter of
OS/400. Commands can be gathered into a script file, and the shell program can run scripts in much the same way that CL
programs are run on OS/400.

There are literally dozens of different UNIX shells, each with its own features and quirks. Most shells provide a common base
of functionality. However, Qshell is designed to be most compatible with the Bourne shell (one of the most widely used shells-
it's the default shell for most Linux distributions), and its feature set will be familiar to UNIX users. And for the standards-
conscious, Qshell is POSIX and X/Open standards-based but not fully compliant.

IBM has provided complete Qshell documentation on its AS/400 Partners in Development Web site
(www.as400.ibm.com/developer/qshell/index.html). This documentation covers each Qshell command in detail and provides
information on tuning Qshell for performance and scripting compatibility.

Team-Fly
Team-Fly

Q sh e ll C o m p o n e n ts
So, you have V4R3 (or higher) and you would like to try out Qshell, which is part of the base operating system. Before you
begin, you should understand that Qshell has two physically separate parts. The first part, comprising the interpreter and
built-in utilities components, is distributed with base OS/400 (option 30). The second part, which is the regular utilities
component, must be ordered separately from IBM.

The built-in utilities are shell commands embedded within the interpreter. There are almost 50 commands that provide very
basic functionality. Among these are the 12 AS/400 Developer Kit for Java commands shown in Table 37.1. The Java
commands are identical to their Sun Microsystems' JDK counterparts. Many of these Java commands have options
specifying either unimplemented or irrelevant features on the AS/400 JDK 1.1-level development platform. These options are
quietly ignored, which means that a Java developer who has used the JDK 1.1 tools can be immediately productive using
Qshell and the AS/400 Developer Kit for Java.

T a b le 37.1: B u ilt
ilt--in Q sh e ll C o m m a n d s

C om m and F u n ctio n
appletviewer Runs applets without a Web browser.
java Runs Java programs.
javac Compiles Java programs.
javadoc Generates API documentation from Java source code.
javah Creates C header files and C stub files for a Java class.
javakey Generates digital signatures for archive files.
javap Disassembles compiled Java files.
jar Combines multiple files into a single Java Archive (.jar) file.
native2ascii Converts non-Unicode Latin-1 files to Unicode Latin-1.
rmic Generates stub and skeleton class files for Java objects using Remote Method Invocation.
rmiregistry Starts a remote object registry on a specified port.
serialver Returns the serialVersionUID for one or more classes.

The other built-in utilities are UNIX commands. Sadly, there just aren't enough of the most common commands in the built-in
utilities set to do much of anything. The few commands provided are mostly for querying and manipulating Qshell sessions. It
would be difficult to write a useful shell script that only uses the built-in utilities.

The commands in the regular utility set are implemented as external programs and are invoked from the interpreter in the
same manner as built-in commands.

Included in the regular utilities are essential UNIX commands such as ca tt, ls
ls, and cp
cp. The commands making up the regular
utilities include almost all of the most familiar UNIX-style commands. Even if your favorite command is missing, a command
or command option with equivalent functionality is likely to be available. The regular utilities are used primarily for special-
purpose file system functions, such as listing, copying, and renaming files; creating a file archive; filtering character streams;
or compressing and uncompressing files. In Qshell, these commands operate on objects in any file system that is supported
by the IFS. There are more than 50 commands in the regular utilities set.

Some useful but limited software development tools are also included in the regular utilities set. These are mostly wrappers
around CL commands for creating programs and service programs in the QSYS file system. If you have an ILE C compiler on
your system, you can compile C code into modules and/or programs using the cc command. Qshell's cc is a wrapper for
CRTCMOD and CRTPGM. The UNIX a r command is given in Qshell as a wrapper for CRTSRVPGM and UPDSRVPGM. Also,
a complete and feature-rich version of UNIX m a ke is available.

Qshell without the regular utilities is almost useless as a UNIX-like shell, but the built-in utilities do include all of the common
JDK commands. The JDK commands are wrappers for the programs of the AS/400 Developer Kit for Java, which also must be
installed separately. It is possible to run very simple UNIX shell scripts with just the built-in utilities, but the functionality will
be extremely limited.

The interpreter component of Qshell has all of the familiar features of quoting, variables, parameter manipulation and
substitution, path name expansion, patterns, command pipelining, and conditional constructs. Even functions and command
groups are supported. Most of the useful I/O redirection operators are available. The mostly minor incompatibilities of the
interpreter are found in the features dealing with the operating system directly and are attributable to the differences between
OS/400 and UNIX.

Qshell command input is somewhat unusual in comparison to a standard UNIX command line. Figure 37.1 shows the
Command Entry screen of the STRQSH (or simply QSH) CL command. Here, the QSH command is being run in interactive
mode. The QSH command can also be used to run a single shell command or script.

F ig u re 37.1: The Qshell screen allows you to enter shell built-in utilities as well as Java commands.

The interactive Command Entry screen shows the command prompt, but rather than being placed immediately before the
command cursor, as in a standard UNIX shell, it floats in the text area above the command entry area at the bottom of the
screen. When a command produces standard output, it is presented on the line following the command prompt, just as it
would on a UNIX terminal. This arrangement isn't too confusing, but you soon realize that it precludes the use of full-screen
editing commands such as the popular v i or e m a cs text editors. There is one advantage to this scheme: Scrolling through
text output up and down across the screen edges is built in, so you don't need the UNIX m o re command.

Team-Fly
Team-Fly

C o m p atib ility
Externally, Qshell would appear to be useful in three possible areas. First, if you've built a UNIX shell script to do some
interesting thing, you may be able to use Qshell to do that same thing on an AS/400. Second, if you want to build and use
Java programs the way you were taught, but on the AS/400, you can use Qshell's built-in Java commands. Finally, if you have
a lot of experience in UNIX, you can leverage your experience with Qshell. All of these scenarios depend on the compatibility
of the shell and its associated command set.

To test Java and "open-source" compatibility, I chose a relatively simple, open-source Java server application and tried to do
the minimum amount of work possible to compile and run the application using Qshell. Similarly, to test UNIX script
compatibility, I chose some simple shell scripts and tried to run them as-is on Qshell. Note that these so-called tests were
not very scientific and that each individual's experience with Qshell will most likely be very different.

For the Java test, I selected the Muffin proxy server available from muffin.doit.org. This open-source software package can be
used on Internet firewalls to provide users on one side of the firewall access to Web sites on the other side. I downloaded the
current distribution release as a ZIP archive using a PC Web browser, then uploaded it to the AS/400. I then used the ja r
built-in utility to extract the package into an IFS directory; ja r extracted the 700 K compressed ZIP file perfectly.

Muffin's installation from source code uses a common UNIX open-source scheme for detecting the platform it is being
installed from. A shell script named co n fig u re is provided as a convenience to detect various things about the system and
then generate a m a ke file for compiling and installing. This script is designed to work as-is on the large majority of UNIX
systems, but, unfortunately, co n fig u re failed miserably when run under Qshell. The workaround involved hand- tuning Muffin's
generic m a ke file
file. Running Muffin turned out to be very simple. I ran the Java command specifying Muffin's main class as an
argument, as when using Java applications on most other platforms.

To make things very simple, I used Muffin's -n w option to disable the optional GUI. Muffin appeared to run flawlessly under
Qshell as a simple HTTP proxy server.

Team-Fly
Team-Fly

U n ix S crip t T e sts
Next, I ran a few scripts from the O'Reilly & Associates book UNIX Power Tools, Second Edition by Jerry Peek, Tim O'Reilly,
and Mike Loukides. These scripts are freely available on the Internet at ftp://ftp.ora.com/published/
oreilly/power_tools/UNIX/split. (You can also visit the O'Reilly & Associates Web site at www.oreilly.com.) I deliberately
avoided scripts that use commands not available in Qshell or that were specifically designed for shells other than the Bourne
shell. I ran into trouble with three of the five scripts, as you can see by the results in Table 37.2.

T a b le 37.2: U N IX S crip t T e st R e su lts

S crip t P e rfo rm a n ce
logerrs No problems.
count.it Error in expr command when difference between files is negative.
lookfor Output correct results but terminated with an error.
stree Variable substitution not recognized.
offset No problems.

The problems encountered were a result of incompatibility (as in the case of the stre e script) or possible implementation bugs
and inconsistencies. The problem in stre e turned out to be a simple variable substitution incompatibility that was easily fixed.
Each of the problems encountered could be easily remedied with simple changes to the script.

Team-Fly
Team-Fly

T h e C ase F o r Q sh e ll
Qshell is not a complete, full-featured UNIX shell. Rather, it is a very usable, familiar, UNIX-like shell environment for the
AS/400. Qshell provides UNIX users with the functions they have experience with. You might not have much luck getting a
given set of UNIX scripts to run or an open-source software package to compile as-is with Qshell, but it may be worth a small
effort to port those packages to the Qshell environment.

The JDK tools integration is very smooth. The built-in utilities for Java do look and feel just like their JDK 1.1 counterparts, and
this integration is Qshell's best feature. The m a ke command of the regular utilities is a good program that may find appeal
even beyond the UNIX crowd. Together, the built-in and regular utilities are sufficient for writing highly functional shell scripts
from scratch.

My Qshell enhancement wish list includes more compatibility with generic shell scripts, a few more important shell command
programs (especially p e rl and a w kk), and a full screen editor that runs within the shell. Some small bug fixes to the essential
commands would be nice, too.

Qshell comes along at a time when UNIX integration tools are increasingly popular. Even Microsoft has released its Services
for UNIX Add-on Pack for Windows NT, which includes a basic shell with scripting capability. What separates Qshell from the
others is its emphasis on being "UNIX-like" rather than "UNIX-interoperable." Qshell is a trade-off between the conflicting goals
of compatibility and efficiency. Its designers decided to allow UNIX users to be productive and efficient on AS/400s, rather
than on the most common UNIX platforms.

Team-Fly
Team-Fly

S ectio n V II: S erver


erver--S id e Java
C h ap te r L ist
Chapter 38: The "Little Web Server" Project

Chapter 39: Serving Up Host-Based Java Apps

Chapter 40: Javaserver Page Basics

Chapter 41: Servlets: The New Application Architecture

Chapter 42: Maintaining Session State With Java Servlets

Chapter 43: Send A Message With Javamail

Chapter 44: Synchronization Issues With Java Servlets

Chapter 45: Tomcat For AS/400: An Open-Source Web Application Server

Chapter 46: Jump-Start Servlets And JSPs With Websphere Version 3.0.2

P art O v e rv ie w
When Java was first introduced, its standard user interface was GUI. The GUI was delivered as either a thick-client, PC-based
application or a thin-client, browser-based Java applet. Truth be told, if it weren't for the advent of server-side Java, Java would
have died. In 1998, Sun Microsystems formally introduced Java servlets. Servlets are host-based Java programs that
dynamically construct HTML in response to browser requests. Even though the servlet specification is only a few years old, a
large percentage of Web applications use servlets.

It takes some time and understanding before an OS/400 programmer can become comfortable with the paradigm shift from
5250 green-screen applications to Web applications. I found it quite difficult myself, yet Web architectures really aren't all that
complex. In "The 'Little Web Server' Project," I explain Web architectures through the description of a computer science
college project on developing a Web server. The chapter describes how the server should handle requests for HTML and
requests for the invocation of Java servlets.

Programming with servlets is much easier for OS/400 programmers to become proficient in than Java GUI programming is,
and "Serving Up Host-based Java Apps" gets you started. Java servlets are now a pervasive technology, but, nevertheless,
servlet technology has a bit of a problem: Its user interface, HTML, is embedded to the business logic of the Java servlet, and
it's a difficult process to modify and enhance that user interface.

In 1999, Sun delivered specifications for JavaServer Pages (JSPs). JSPs are essentially HTML with embedded Java. You can
develop complete Web applications with JSPs, as "JavaServer Page Basics" covers, but you'd end up with the opposite
problem of servlet-centric applications. Instead of embedding HTML in your Java, you're embedding Java in your HTML. Alex
Garrison, in "Servlets: The New Application Architecture," describes how to marry these two technologies to develop quality
Web applications.

In Section VI, "Not Java," David Mayle describes how to maintain session state in "Using Cookies to Pass Parameters
Between Web Pages." Java servlets encapsulate the use of HTTP cookies, making session state management easy.
"Maintaining Session State with Java Servlets" provides a tutorial on Java servlets.

As you become comfortable with JSP and servlet technology, you'll want to begin to use some of the more sophisticated Java
technologies available today. Jeff Markham's "Send a Message with JavaMail" shows you how to manage email from a Java
servlet. Steve Njenga's "Synchronization Issues with Java Servlets" explains how to resolve concurrency issues that may
arise with heavily used servlet applications.

After reading the chapters in this section, you'll be ready to get started. To develop, test, and deploy servlets and JSPs, you'll
need a Web application server. IBM would lead you to believe there is only one option: WebSphere. But that's not true. There
are many options for Web application servers. This section provides tutorials on two: Apache's Tomcat and IBM's
WebSphere. You can run Tomcat on any platform you wish; I've run Tomcat on Windows 95/98/NT, Linux, Apple, and
OS/400. "Tomcat for AS/400: An Open-Source Web Application Server" introduces you to Tomcat and provides the
instructions and code necessary to install Tomcat on your AS/400. But if you want to go true blue, read Richard Shaler's
"Jump-start Servlets and JSPs with WebSphere Version 3.0.2."

Team-Fly
Team-Fly

C h ap ter 38: T h e "L ittle W eb S erver" P ro ject


O v e rv ie w
DON DENONCOURT

When I first began programming Java for the Internet, my efforts were dedicated to learning advanced Java techniques, while
sacrificing the time required to understand the basics of HTTP. At first, this seemed to be a good strategy because I was able
to develop some fairly interesting server-side applications. Soon, however, I realized the obvious: Sun Microsystems' Java
servlet package is an API for HTTP and HTTP is the protocol of the Web. After just a little research, I found that HTTP is really
quite a simple protocol. In this chapter, I will explain the basics of HTTP and the Java servlet API that provides encapsulated
access to HTTP.

The concepts behind HTTP are so simple that undergraduate computer scientists are often given the task of writing a Web
server as a class project. With that in mind, and for the scope of this chapter, put yourself in the student's place and think
about how you would code your own Web server. In doing so, you'll discover that this Web stuff isn't all that complicated.

Begin your own Little Web Server project by creating a program overview to describe the intent of your HTTP server. First,
your Little Web Server will use TCP/IP sockets to handle communications. The server will sit on an IP port (which you will
default to 80 unless otherwise specified) in a sockets wait state, ready to handle remote requests. When a remote user
connects to your system's IP address and the port number that your Web server program is waiting on, your server will
accept the connections and then read the HTTP packet that contains the request from the client. Based on the contents of
the HTTP request, your server will respond by sending down an HTTP packet that contains the response and then disconnect
the client. Disconnecting the client is a key point in the design of your HTTP server. HTTP is a stateless protocol in that your
Web server (which you are hypothetically coding) doesn't maintain a connection for the interactive processing with a client.
Each request is a completely new connection.

Team-Fly
Team-Fly

T h e R e q u e st
With the program overview aside, your next step is to figure out how to process the information contained in each HTTP
packet. Client HTTP requests come in two basic forms: a GET request and a POST request. A GET request is sent to the
server when a user keys a URL into the browser or clicks a hyperlink. The browser builds an HTTP packet that contains, at a
minimum, the request method or command type, the name of the object that the user is requesting, the HTTP version, the
product name of the browser, and the list of file types that the browser can handle:
GET /login.html HTTP/1.0
User-Agent: Mozilla/4.02 [en] (Win95; I)
Accept: image/gif, image/jpeg, text/html, */*

Meanwhile, the domain name (or IP address), the qualifier for the request object, and the user input parameter (if any) are
passed as what is known as the query string:
http://www.mc.com/servlet/login?user=don&pass=secret

The h ttp : portion of the URL says that it is using the Hypertext Transfer Protocol. The ////ww w w .m c.co m portion is the domain
name of the server (but it could also be an IP address). The /se rv le t portion is the qualifier for the requested object,
and /lo g in is the name of the requested object. The question mark (?) says that a query string is to follow, and the equal sign
(=) indicates a key/value pair for a user request parameter. The ampersand (&) then shows the start of a new key/value
parameter pair. In the example, the parameters are my user profile name with a value of d o n and my no-longer se cre t
password.

You might have noticed something odd about the URL in the example-it doesn't specify a port number. You might find this
omission confusing because the program summary given earlier said that the HTTP server sits on a specific IP port as it waits
for user requests. Remember, though, that I said that the default port for HTTP is 80, so when the request doesn't contain an
explicit port number, your TCP/IP server will pass HTTP requests to whatever program is lying in wait on port 80. To explicitly
identify the port, you would specify colon (:) 80 following the IP address or domain name:
http://200.199.99:80/html/index.html

Typically, so that users don't have to key a port number for your Web server, a domain name is registered so that it resolves
to not only the IP address but also the port number.

Team-Fly
Team-Fly

T h e R e sp o n se
If your computer science professor were nice, she'd limit your Web server to merely host static HTML. When a user requests
a static HTML page, the qualifier portion of the request is used as the path to the HTML file on the host. So, for example, if
the request was for http://200.199.99:80/html/HelloWorld.html, your server would simply open the file called H e llo W o rld .h tm l
in the directory called h tm l and then stuff the contents of that file into an HTTP response packet. That response packet, as
you can see in Figure 38.1, is fairly easy to build. The packet starts by specifying which version of HTTP it contains (in this
case, 1.0), followed by the HTTP status code. Status codes are used to tell the client (the browser) whether or not the
request was successfully filled. (A summary of HTTP status codes is shown in Table 38.1.)

F ig u re 38.1: An HTTP response packet contains basic information about the response and an embedded HTML
file.

T a b le 38.1: H T T P S ta tu s C o d e s

S ta tu s C o d e D e scrip tio n
1xx Informational, HTTP/1.0 does not define any but HTTP/1.1 does.
2xx Successful, request received, understood, and accepted.
3xx Redirection, server requests Web client to redirect to another URL
4xx Client error, request improperly formatted or cannot be fulfilled.
5xx Server error, valid request that server cannot fulfill.

You probably also noticed that the HTTP response packet in Figure 38.1 includes not only the complete contents of the
H e llo W o rld .h tm l file but also a few extra lines that further describe the contents of the response. Those extra lines contain
what are called HTTP headers. The Server header is used to tell the browser the name of the HTTP server that handled its
user's request. The Content-type header specifies that the embedded content that follows contains text-based HTML, and the
Content-length header indicates the total length of the file. Some additional HTTP headers are listed in Table 38.2.

T a b le 38.2: H T T P H e a d e rs

H TTP H eader D e scrip tio n


Allow Tells the client what HTTP methods are supported, such as GET, POST, and HEAD.
Expires The date that the HTML becomes invalid.
Pragma A general-purpose field commonly used to specify "no-cache."
If-modified-since Returns file to the client only if modified since a date.
Last-modified The date that the file was last modified.
Location The directory of the server-based file.
Referer The address of the file that linked to this file.
Set-cookie Application-specific information often used to maintain state across a stateless protocol.
User-agent Name and version of the HTTP client.

Team-Fly
Team-Fly

D y n am ic C o n te n t
Thus far, the scope of your Little Web Server project doesn't sound overly complex, but college professors never assign tasks
that are easy. My hypothetical computer science professor is going to expect your HTTP server to dynamically generate
content in response to user queries. User input comes from HTML forms such as the one shown in Figure 38.2, which simply
prompts for a person's last name.

F ig u re 38.2: Java servlets dynamically build content based on user input from an HTML form.

The HTML < F O R M > tag in the example contains an ACTION option with which you specify the name of the program that is
coded to process the form's input.Your Little Web Server will have to be extended to pass the user's form request on to a host
program. The host program will then dynamically build the HTTP response that it subsequently returns to your HTTP server. A
few years ago, HTTP servers were extended with CGI to respond to user requests with dynamically created HTML content,
but today the best option is to use Java servlets. Thus, you probably will decide to extend your Little Web Server to give
access to HTTP through servlets.

How will your Little Web Server know when to invoke a Java servlet instead of simply returning static HTML? You are going to
have to code your server to look for the string /se rv le t in its qualifier. If it's anything else, your server will use the qualifier as
the directory path for the HTML file. But when the qualifier contains /se rvle tt, your server will hand the request over to a Java
servlet for processing. By the way, should you really want your Web server to support CGI, you'd code the server to look for
the string /c g ii--b in and then pass the request on to a legacy program.

Team-Fly
Team-Fly

S e rv le t P ro ce ssin g
Believe it or not, the process of invoking a Java servlet is fairly simple, because Sun ships a set of Java classes that know
how to run a servlet. All your Web server has to do is pass the request to Sun's servlet handler and then be prepared to send
the servlet's response back to the client. When your Web server receives an HTTP packet that contains a /se rv le t qualifier
(as specified in the ACTION option of the HTML < F O R M > tag or as explicitly keyed in a URL), it calls the se rvice method of
the Java servlet that follows the /se rv le t qualifier. Your Web server passes to the servlet's se rvice method an
H ttp S e rvle tR e q u e st object and an H ttp S e rvle tR e sp o n se object.

Obviously, your Web server will have to instantiate these two objects before it can call the se rvice method of the servlet. And
here's where the beauty of Java servlets begins to show: The H ttp S e rvle tR e q u e st and H ttp S e rvle tR e sp o n se classes, as
their names suggest, encapsulate access to all information contained within an HTTP packet. All of the request header
information contained in an HTTP request is easily accessible from the methods of the H ttp S e rvle tR e q u e st object, and
request headers are easily added to an HTTP response with the methods of the H ttp S e rvle tR e sp o n se object; this is far
easier than with CGI programs. For instance, using cookies for the development of a Web application is easily done with the
a d d C o o kie method of H ttp S e rvle tR e sp o n se
se. Those application cookies are then easily retrieved with the g e tC o o kie s
method of H ttp S e rvle tR e q u e st. (For more information on HTTP cookies, see Chapter 34, "Using Cookies to Pass
Parameters Between Web Pages.")

Team-Fly
Team-Fly

H ow D o Y ou D o?
Now to get back to coding your Little Web Server. After your server creates the H ttp S e rvle tR e q u e st and
H ttp S e rvle tR e sp o n se objects, it calls the servlet's se rvice method, passing those two objects as parameters. Most
servlets, however, don't contain a se rvice method, so how's that going to work? Well, remember that this is object-oriented
programming (OOP), and you should know that the base class for a Java servlet contains a default se rvice method. The base
class's version of the se rvice method is coded to call the d o G e t method of its subclass whenever the HTTP packet's
METHOD option (see Figure 38.2) is GET; it calls the DOPOST method when the HTTP packet's METHOD option is POST. (I
apologize for my ambiguous use of the term method, but, unfortunately, the functions of Java classes and HTTP commands
are both called methods.) There are a few other HTTP methods (e.g., HEAD, PUT, and DELETE), but GET and POST are the
most commonly used ones, so your Little Web Server needn't provide for the others.

Team-Fly
Team-Fly

S n o o p y T h e S e rv le t
Most Web servers ship with an example servlet called S n o o p S e rvle t that shows an example use of the methods of the
H ttp S e rvle tR e q u e st class. When I request IBM's WebSphere version of S n o o p S e rvle t from Midrange Computing's AS/400,
it responds with the HTML form shown in Figure 38.3. You might assume that the Java coder who authored S n o o p S e rvle t
must have known about Internet programming and HTTP because of the depth of the information listed on its HTML response
page. But the code behind S n o o p S e rvle t is just basic Java; all the coder did was dump out information accessed with the
g e t methods of the H ttp S e rvle tR e q u e st class. The code behind WebSphere's S n o o p S e rvle t may be trivial, but what is not
trivial is the ease with which you can develop sophisticated Internet applications using the Java servlet HTTP API.

F ig u re 38.3: IBM's WebSphere version of SnoopServlet shows information contained in my HTTP request, including a
cookie.

You probably won't be coding your own Little Web Server, but the point of this chapter is to show the simplicity of HTTP and
the ease with which Java servlets can access and manipulate that information. Switching from the user interface paradigm of
the AS/400 5250 data stream to HTML requires that you become comfortable with HTTP. Even if you are using CGI RPG to
redeploy your legacy applications, HTTP knowledge is still vital. Java servlets, however, have a simple and direct API to HTTP,
the protocol of the Web, through the encapsulation facilities of OOP and Java.

Team-Fly
Team-Fly

C h ap ter 39: S ervin g U p H o st


st--B ased Java A p p s
O v e rv ie w
DON DENONCOURT

Anyone developing business applications in Java uses the servlets API. Even though Sun Microsystems introduced servlets
only as recently as the spring of 1998, servlets are already a pervasive technology. Keep an eye on the URLs at the top of
your browser for a few weeks. A URL containing a qualifier with the suffix nsf indicates that a Lotus Domino application is
driving the content. The directory name cgi-bin signifies that the application uses a legacy language with CGI. If "loading
Java…" appears at the bottom of your browser's screen, it doesn't really matter, because you're probably moving to another
site because you don't want to wait for the Java applet to download. The qualifier servlet is a sure sign that host-based Java
servlet technology is driving the application.

Team-Fly
Team-Fly

H o st-B ase d A p p s R u le
Java applets have fallen out of favor for Internet business applications. Applets were all the rage because they delivered client-
side business applications over the Web. Web designers began using applets because they presented a graphical interface
far superior to HTML, but they soon discovered that applets were fat clients because the code required to present that
"superior" interface leaned toward obesity. Java servlets, on the other hand, are host-based. Servlets keep business logic on
the server, and because the user interface for servlets is HTML, download speeds are not an issue. Some client-side logic
may be required, but, more often than not, you can implement that client-side processing via a scripting language such as
JavaScript or VBScript.

Dynamic generation of HTML with Java servlets is the same strategy CGI programmers have used for several years. CGI
allows you to associate a URL request with a host program that can be implemented using your language of choice. However,
on most platforms, each time a URL invokes a CGI program, that program is restarted, incurring normal expenses of security
checks, memory allocation, and file opens. Once the program completes the request by returning an HTML response
containing dynamically constructed information, that program instance is purged. Each subsequent invocation of the CGI
program imposes a program initialization penalty on the server. Java servlets, in contrast, are not purged; the servlet instance
remains available to the Web server for invocation by multiple clients.

Now, I must be honest. Earlier, I said "on most platforms" when noting the superiority of servlets over CGI, but the AS/400 is
not an ordinary platform. Using a combination of activation groups and the persistent CGI feature with V4R3, CGI application
performance on the AS/400 is far superior to CGI on most platforms. Application portability is the issue. With considerations
such as security, caching, and clustering, Web server configuration is complicated. Consequently, many Web sites have
multiple platforms that support a single application. For that reason, Web hosting needs to be portable. Servlets provide that
portability. The AS/400 may be the best platform for back-end business applications, but front-end Web applications may not
always be on the AS/400.

Team-Fly
Team-Fly

W e b L o g ic
When specifying a URL on your browser, the qualification is often to an HTML file within an explicit host directory:
http://yourDomain/home/level1/level2/ SomeHtml.html.

The host simply sends the HTML file from the location specified back to the client. Often, for simplicity and security, the host
configuration maps a "logical" directory name to the real directory name, decreasing the length of the URL and concealing the
real host directory name. CGI implementations also use the concept of a logical directory by mapping directory name cg ii--b in
to a library of host CGI programs. When the HTTP server sees cg ii--b inin, it executes the program name that follows the cg ii--b in
qualification. Web servers that support Java servlets, such as IBM's HTTP Server for AS/400, map directory name se rvle t to a
directory of Java servlets. In addition, as with CGI applications, the server invokes the Java servlet qualified by /se rv le tt. Java
servlets, like CGI programs, can be invoked from a URL request or as an action item on an HTML form. The page shown in
Figure 39.1, for instance, is qualified by the URL http://domainOrIP/servlet/ Seminar. Once configured to enable Java servlets,
your HTTP server of choice invokes the Java class S e m in a rr.

F ig u re 39.1: When a Web server sees the servlet qualification on a URL, it invokes the named Java
servlet.

The browser sends a URL request to the HTTP server in HTTP, which is the protocol of the Web. HTTP browser requests may
or may not include embedded HTML files, but they always provide request methods. When you enter a URL, the HTTP
request method is GET; an HTML form request uses the method POST. (For more information on HTTP, see Chapter 38, "The
'Little Web Server' Project.") When a Web server receives an HTTP GET request, the servlet engine invokes the d o G e t
method of the Java servlet qualified in the URL. When the server receives an HTTP POST request, such as the one sent from
the entry form shown in Figure 39.1, the servlet engine invokes the d o P o st method of the servlet qualified by the ACTION
parameter of the HTML < F O R M > tag. For example, notice the qualification of the S e m in a r servlet and the specification of a
POST request method in the HTML in Figure 39.2:
F ig u re 39.2: HTML forms can associate a Java servlet to process the user request.

<FORM ACTION="/serclet/Seminar" METHOD="POST">

Team-Fly
Team-Fly

T h e S e rv le t A P I
The example application in Figure 39.1 uses a Java servlet invoked by the URL request http://domainOrIP/servlet/Seminar.
The S e m in a r servlet dynamically builds the HTML response with the latest product information. That HTML response
includes a form whose action is handled by the same S e m in a r servlet (al- though it can be a different servlet). The S e m in a r
servlet is Java built atop the generic H ttp S e rvle t class. H ttp S e rvle t provides code implementations for common services, two
of which I've already mentioned: d o G e t and d o P o st. The H ttp S e rvle t code implementations for d o G e t and d o P o st do
nothing worthwhile. They're in H ttp S e rvle t as placeholders to assure the servlet engine that all servlets, if only by order of
object-oriented (OO) inheritance, have these methods. This is important because the servlet engine calls the d o G e t method
based on a URL request and calls the d o P o st method based on an HTML form action request. If your servlet is to process an
HTTP GET request from a URL, you must define a custom implementation of the H ttp S e rvle t class's d o G e t method, and if
your servlet is to process HTML forms, you must code a d o P o st.

H ttp S e rvle t also has a method called in it


it. The servlet engine invokes a servlet's in it method the first time that servlet is
requested, like an initialization subroutine in RPG. As you know from RPG programs, this initial processing can be handy.
For servlets, you might want to code your in it method to load a JDBC driver and initialize JDBC connections or, if you prefer
record-level access, open files as global fields declared in a Java class but not in a method of that class. Those JDBC
connections or record-level access file opens then become available to all remote requests, saving the time required to
connect to the database.

Team-Fly
Team-Fly

T h e E x am p le
The code for the S e m in a r Java servlet is given in Figure 39.3. At Label A, the S e m in a r class extends the H ttp S e rvle t class.
At Label B, the global fields of the S e m in a r class are declared. The values of these fields are accessible to all clients. The
in it method, at Label C, first calls its parent's implementation of in it
it. When you override the H ttp S e rvle t class's in it method,
you need to invoke the parent's version of in it because it does some important initial processing that you don't have to code
yourself. The S e m in a r class's custom version of the in it method then creates a vector (a dynamically sizable array) to hold
the registrants. This servlet is coded for simplicity, so pretend that the in it function has gone to DB2 for OS/400 to obtain the
latest seminar locations and counts. Otherwise, I may as well code this information in a static HTML file. That's the point of
servlets: to present dynamic information over the Internet.

F ig u re 39.3: The Seminar servlet creates a registration form in its doGet method and processes that form in its doPost
method.
Team-Fly
Team-Fly

A s G o o d A s It G e ts
The d o G e t method at Label D in Figure 39.3 has two parameters: H ttp S e rvle tR e q u e st and H ttp S e rvle tR e sp o n se
se. The first
parameter contains information about the request; the second contains the dynamically generated HTML response. (I suggest
you review the Java documentation for these two classes, because they have some powerful capabilities. Both of them, for
instance, have methods that make using HTTP cookies a breeze.) The request contains any parameter on the URL, but
because the S e m in a r application uses no URL parameters, its implementation of d o G e t ignores the request parameter. At
Label E, however, the response parameter is used. Think of H ttp S e rvle tR e sp o n se as a handle to an HTML file containing the
response to the user's request. At Label E, the document re sp .se tC o n te n tT yp e ("te x t/h tm l") tells HTTP that this file is to
be transferred to that browser as text-based HTML. The next line at Label E receives a handle to the output stream. It's like
setting a record format in an RPG screen program.

At Label F, the d o G e t method dynamically constructs an HTML file. All HTML files are enclosed by < H T M L > and < /H T M L >
tags. They also have a head tag, < H E A D >>, and body tag, < B O D Y >>, so these obligatory tags are inserted into the response
buffer. Label F then builds the body of the HTML file, inserting the .g if file for MC's coffee cup and listing the fall dates for my
Java seminars. Again, in a real application, this information comes from a database. At Label G, the input form is
constructed. The input form contains a drop-down selection list for the city of choice and a text field for the registrant's name.
The d o G e t code ends by closing the print writer, at which point the servlet engine sends the HTML response to the browser
(see Figure 39.2).

Team-Fly
Team-Fly

P o stag e D u e
Once the user selects a city, keys in a name, and clicks Register, the ACTION option of the HTML < F O R M > tag instructs
the S e m in a r servlet to process the HTTP POST request. The code for the d o P o st method is given at Label H of Figure 39.3.
The d o P o st method has the same two parameters as d o G e t. Again, the content type is set, and a handle to the output writer
is obtained. At Label I, the CITY and NAME parameters specified by the client are retrieved. Then, at Label J, after stuffing the
obligatory < H T M L >>, < H E A D >>, and < B O D Y > tags, the d o P o st code checks whether registration is full. If seats are still
available, d o P o st increments the array element of the global count field associated with the selected city. (A real application
would update a database at this point.) Figure 39.4 shows the dynamic HTML content generated by d o P o st when Billy Briggs
registers, and Figure 39.5 shows how it looks on Billy's browser.

F ig u re 39.4: The HTML response from a servlet contains dynamic information.

Team-Fly
Team-Fly

Y o u M u st P o o l Y o u r R e so u rce s
Obviously, Internet applications are more complex than my S e m in a r servlet, but industrial-strength servlets have more
requirements. They must have some form of transaction control to ensure data integrity. For performance, they should have
some form of database connection pooling. They also need a strategy to maintain state across the stateless HTTP.
Transaction control can be enabled with JDBC transactions, record-level access commitment control, or Enterprise
JavaBeans (EJB) transactions. You can code your own connection pool logic or use the connection pooling features included
with most Web application servers, including IBM's WebSphere. For things such as the Internet's popular shopping cart
metaphor, you can use either HTTP 1.1's session API or HTTP cookies. You can also add elegant state manage ment
features by employing EJB with your servlets.

F ig u re 39.5: Whether you use Java servlets or RPG CGI, the point is to interact with the user.

You may ask, "Isn't embedding HTML into a Java servlet the same thing as describing screens in RPG?" That is a problem.
It's always better to separate screen design from program design. It's even more important with Web applications because
HTML design is becoming a profession unto itself. Business programmers can easily present information logically with HTML
but don't often have the time or training to make it pretty with graphics. In the spring of 1999, Sun announced JavaServer
Pages (JSPs), which separate programming logic from screen presentation, and because JSPs are relatively new, it's
fortunate that WebSphere supports JSPs.

Team-Fly
Team-Fly

C h ap ter 40: JavaS erver P ag e B asics


O v e rv ie w
DON DENONCOURT

Java servlets have taken the Web by storm. In a period of about 12 months, Sun Microsystems' servlet technology became
widely adopted as a standard for host-based Internet applications. In Chapter 39, "Serving Up Host-based Java Apps," I
showed how Sun's servlet technology allows you to develop server-side Java applications that respond to browser requests by
dynamically constructing HTML from application data. But you might have noticed that there was an inherent design flaw in
my servlet example-it embeds the HTML code required for the user interface (UI). RPG programmers haven't embedded UI
code since externally defined files became available (and we say they're behind the times). That's where Sun's JavaServer
Page (JSP) technology enters. JSP effectively separates UI design from business programming logic. In this chapter, I'll
illustrate how I separated the HTML user interface from the Java code of my servlet example in Chapter 39 using JSP
technology.

Before I go into the rewrite of my servlet, I must first lay the groundwork for JSP. JSP is a server-side scripting language; it is
parsed on the host to dynamically construct the HTML. HTML scripting languages were initially used on the client (Web
browser) to do things such as edit entry fields or selectively use the latest HTML syntax supported by Microsoft Internet
Explorer or Netscape Navigator. The scripting language that was first available for HTML was Netscape LiveWire. Netscape
soon renamed LiveWire to JavaScript, and Microsoft quickly followed with a clone of JavaScript called JScript. Netscape then
had the idea to parse the JavaScript on the host rather than the client so that the host could dynamically construct HTML
before it was sent to the client. Microsoft followed suit with a much more powerful server-side scripting language called Active
Server Pages (ASP). Meanwhile, Sun, doing what it does best, took the best ideas from commonly accepted industry
standards and designed JSP technology.

Team-Fly
Team-Fly

M in im u m S tan d ard R e q u ire m e n ts


The best way to describe how JSP works is to show you a simple example. The following line of text contains the complete
HTML syntax from a file called M in im a l.h tm l:
<HTML><BODY>Minimal HTML file</BODY></HTML>

When a Web server receives a request from a browser for M in im a l.h tm l, it simply sends that text file down to the browser.
But if you rename M in im a l.h tm l (on the server machine, that is) to M in im a l.jsp
l.jsp, the process is entirely different. When a
browser requests the file called M in im a l.jsp
l.jsp, the JSP-enabled server (e.g., IBM's HTTP Server for AS/400 and IBM's
WebSphere) sees the jsp suffix and compiles the JSP file. That's right; the Web application server compiles the HTML text
contained within that file. This page-compile process converts the JSP into the Java servlet source file shown in Figure 40.1
and compiles that source into a Java class. The Web application server then executes the Java servlet, which simply creates
the same HTML shown earlier. The browser receives that HTML and presents "Minimal HTML file" in the browser window.

F ig u re 40.1: The servlet code automatically generated by the Web application server's page-compile process is
ugly.

Obviously, this compile process takes up a considerable amount of time (perhaps a few seconds). But the next time a client
requests that same JSP file, the server will simply execute the servlet created earlier. Meanwhile, if a Web developer modifies
the JSP file, the server will notice that the JSP has been changed, recreate the Java code, and compile a new servlet.

Team-Fly
Team-Fly

S crip tle ts
At this point, I have not shown any added value of JSP technology, so my next example uses some JSP scripting:
<HTML><BODY>
Today's date <%=(new java.util.Date()).toLocaleString() %>
</BODY></HTML>

This simple JSP example contains Java code within the JSP scripting tags of < % = and % >>. When this JSP page is
requested, the servlet automatically generated by the Web server will dynamically insert today's date into an HTML file. The
dynamically constructed HTML file is sent to the requesting browser and presented to the user in the following format:
Today's date Sep 8, 1999 8:14:29 PM

Any Java syntax can be used in a JSP file. Also, because a JSP file ultimately becomes a Java servlet, the parameters that
are sent to the standard functions of a servlet can be used in the JSP. The following example uses the H ttp S e rvle tR e q u e st
object variable called re q u e st to retrieve the name of the requesting Web browser:
<HTML><BODY>
<%= request.getHeader("User-Agent") %>
</HTML></BODY>

When I requested the JSP file that contained the preceding syntax from Internet Explorer, the browser displayed M o zilla /4.0
(co m p a tib le ; M S IE 4.0; W in d o w s 95), but when I requested the same JSP from Netscape Navigator, I saw M o zilla /4.06
[e n ] (W in 95; U ;N a v).

The H ttp S e rvle tR e q u e st class provides encapsulated object-oriented (OO) access to all the information that could ever
possibly be embedded to Web requests, such as HTTP cookies, HTTP headers, HTML form input parameters, and HTTP
query strings. A few of the methods at your disposal from the H ttp S e rvle tR e q u e st class are g e tC o o kie ss, g e tH e a d e rr,
g e tP a ra m e te rr, and g e tQ u e ryS trin gg. Three other object variables are also available in the Java code of your JSP file:
se, o u t, and in . The classes of the o u t and in object variables are from the ja va .io package (PP rin tW rite r and
re sp o n se
B u ffe re d R e a d e rr). The class of the re sp o n se object variable is H ttp S e rvle tR e sp o n sese. It's sort of the opposite of
H ttp S e rvle tR e q u e st, and, as you might guess, the H ttp S e rvle tR e sp o n se class encapsulates OO access to any of the
facilities available with an HTTP response that is to be sent back to the client. For instance, H ttp S e rve rR e sp o n se has
functions such as a d d C o o kie kie, se tH e a d e rr, and se n d R e d ire ct. Through the H ttp S e rvle tR e q u e st and H ttp S e rvle tR e sp o n se
classes, you will be able to do with ease what CGI programmers must struggle with.

When more than one line of Java code is contained within the < % and % > tags, that section of code is known as a scriptlet.
The Java syntax that can be inserted between the < % and % > tags of a JSP file can be as complex as you desire. But you
really don't want to have that much Java code in your JSP. Why? Because then you'd have the opposite problem of
embedding HTML code in a Java servlet-you'd have Java code embedded into what is basically an HTML file. Again, the idea
with JSP is to separate presentation from programming. There's a lot more cool stuff that you can do with JSP scriptlets, but I
want to move on to a much cleaner strategy of coding your UI with JSP without the use of complex Java code.

Team-Fly
Team-Fly

B e an s, B e an s
JavaServer Pages cleanly separate the UI from programming logic with JavaBeans, Sun's strategy for component-based
programming. A JavaBean is basically a Java class that conforms to a standard naming and coding strategy for functions. The
intent of JavaBeans is to provide a functional interface that is easy to use. In fact, a JavaBean should be so easy to use that a
Web designer with little or no Java training can use it through a JSP tag called bean. The following is the < jsp :u se B e a n >
tag's formal syntax:
<jsp:useBean
id="beanName"
scope="page|request|session|application"
class="className"
/>

The JavaBean is where the complex code belongs-not in the JSP file. To pull out the HTML that I had embedded in my servlet
example in Chapter 39, I created a simple JavaBean that I called S e m in a rB e a nn.

To understand how the S e m in a rB e a n JavaBean fits into my JSP example, you first need to look at its UI. The UI for my
example, as it appears in Internet Explorer, is shown in Figure 40.2, and the JSP code that generates that page is shown in
Figure 40.3. Notice the < jsp :u se B e a n > tag at the top of the JSP in Figure 40.3. It references the S e m in a rB e a n JavaBean
with the cla ss qualifier. The code for S e m in a rB e a n is shown in Figure 40.4. It's a trivial example in that its "dynamic" data
doesn't even come from DB2 for OS/400. For simplicity, I hard-coded the data as compile-time arrays. But the idea is that I've
encapsulated access to a business entity with some simple Java code. The JSP file of Figure 40.3 is able to use the
functions of that S e m in a rB e a n through the variable name "seminars" that I specified using the id qualifier in the
< jsp :u se B e a n > tag.

F ig u re 40.2: JavaServer Pages are processed on the host to dynamically generate HTML to be sent to Web
browsers.
F ig u re 40.3: The <jsp: useBean> tag references a JavaBean so that the JSP file can invoke the functions of that
JavaBean.

F ig u re 40.4: A JavaBean is a Java class that is coded to follow a simple but standard strategy for coding function
interfaces .

Team-Fly
Team-Fly

Ite ra tio n
To construct the HTML list of seminar dates shown in the browser graphic in Figure 40.2, the JSP repeatedly invokes the
g e tD a te function of the S e m in a rB e a nn. That "iteration" is enabled with a standard Java FOR loop. Note that the Java code of
the FOR loop is broken up so that the HTML list item tag () and a JSP expression (the < % = % > tag set) can add each
element from the date array:
for (int i=0; i<dates.length; i++)
{
%>
<%= dates[i] %>
<% } %>

As you can see, you can mix and match your Java and HTML code to create applications that are as complex as you want.

To construct the drop-down list for users to select the city where they wish to attend one of my Java seminars, I again used a
FOR loop, but this time, I invoke the g e tC itie s function of the S e m in a rB e a nn. My trivial S e m in a rB e a n has no functions
available to set its attributes, but if it did, I could easily invoke setter functions to update my seminar database from user input
to the HTML form. (Note, however, that because JSPs may be maintained by nonprogrammers, it is not a good idea to put
setter methods in Beans.) The form of my JSP, however, is sent for processing to a servlet called S e m in a rF o rJS P , as
identified in the ACTION option of the < F O R M > tag:
<FORM ACTION="/servlet/SeminarForJSP" METHOD="GET">

All the S e m in a rF o rJS P servlet does is read the parameter values for NAME and CITY, then send the HTML that
encapsulates the following note to the registrant:
Registration Confirmation
"Thank you, Don Denoncourt. Your registration is confirmed for San Antonio."

Team-Fly
Team-Fly

M o re S tu ff
There are a couple of other capabilities of JSPs that I want to mention. First is a JSP's ability to directly call a servlet with the
< S E R V L E T > tag. The second capability is that a servlet can call a JSP with the ca llP a g e function. In a typical scenario, a
standard HTML file presents a form to the user. A servlet is identified with the < F O R M > tag's ACTION option to handle the
user input. The servlet uses the full potential of the Java programming language, but instead of embedding an HTML response
to the user, the servlet creates a JavaBean that encapsulates the information and perhaps encapsulates the ability to
manipulate the state of that information. The servlet then calls a JSP with the ca llP a g e function. The < jsp :u se B e a n > tag
references the JavaBean created in the servlet.

Now, you should note that the developer of the servlet is a business programmer and the developer of the JSP is a Web
designer. The Web designer is able to easily retrieve information from the JavaBean and then do what she does best with that
information-design a well-crafted Web page. If the Web developer needs additional computing power, she may request that a
servlet be developed so that she can invoke it from her JSP with the < S E R V L E T > tag. The Web designer can even invoke
another JSP from within a JSP, thus allowing the design of a modular Web site. With the intelligent use of JSPs, servlets, and
JavaBeans, you can easily engineer the separation of presentation and programming.

Team-Fly
Team-Fly

F in d O u t M o re
For documentation, you can download the IBM Redbook Developing an E-Business Application for the IBM WebSphere
Application Server (SG24-5423-00) from www.redbook s.ibm.com. The "e-biz book," as I call it, provides a complete example
application called H o m e B a n k that uses JSP, servlets, and JavaBeans. Two valuable PDFs that are AS/400-specific are
available for download from IBM's Technical Studio site (www.as400.ibm.com/tstudio/websphere/docs/ doc.htm): "WebSphere
Application Server for AS/400 Documentation Center" and "Getting Started with WebSphere Application Server for AS/400."
You can also retrieve JSP specifications from Sun's Web site (www.java.sun.com/ products/jsp).

To run JSP from your AS/400, you need the HTTP Server for AS/400 (5769DG1) and WebSphere Application Server for
AS/400 (5769AS1) program products installed and configured (both of which are bundled with OS/400 since V4R3). For
information on installing and configuring WebSphere to your V4 machine, see Chapter 46, "Jump-start Servlets and JSPs with
WebSphere Version 3.0.2." But, beware: Installation of WebSphere is not straightforward, so I suggest you start with
Apache's Tomcat Web application server. It's free and it works just as well on your PC as it does on your AS/400. For more
on Tomcat, see Chapter 45, "Tomcat for AS/400: An Open-Source Web Application Server."

Team-Fly
Team-Fly

C o n sid e r Y o u rse lf S e rv e d
You've been served. You have now been presented with notice of the power of JavaServer Pages, so it's time to get started.
My example was necessarily simplistic in order to illustrate the relevant concepts. However, you should still be able to
envision the potential for combining JSP, servlets, and JavaBeans to separate the UI from the business logic. This logical
separation of tasks supports a collaborative work environment where Web designers can design Web pages and business
programmers can code business logic.

Team-Fly
Team-Fly

C h ap ter 41: S ervlets


ervlets--T h e N ew A p p licatio n A rch itectu re
O v e rv ie w
ALEX GARRISON

Like many of you, I have spent my professional programming career looking for ways IT can give my company an edge over
the competition. I have seen firsthand the benefits of cross-platform object-oriented (OO) programming. Unfortunately, I have
experienced problems with scalability, security, system complexity, and data integrity. I would like to find a system that is
easy to use, has an integrated database, can be accessed from the Internet, and supports a powerful OO language. As the
ad says, "…then that would change everything." With Java servlets, JavaServer Pages (JSPs), IBM's WebSphere, and the
AS/400, perhaps there is finally a winning combination.

Team-Fly
Team-Fly

W e b A p p licatio n S e rv e rs
When Java first came on the scene, it seemed to be a perfect fit for the AS/400. At last, maybe there was a worthy
successor to RPG. But would Java "play nice" on the AS/400? Could I leverage my company's investment in several million
lines of RPG code and a database developed over a period of years? Could I draw a line in the sand, stop developing in RPG,
and switch over to Java without skipping a beat? My initial experiences with Java answered that question with a firm "no," but,
after the completion of my most recent project, the answer is now "maybe."

Team-Fly
Team-Fly

T h e N e w A p p licatio n A rch ite ctu re


At this time, you have several practical ways to run Java programs on an AS/400. You can run them as batch programs (OK),
interactively from a command prompt using the Run Java (RUNJVA) command (slow), from within the Qshell environment
(slow), called from RPG or CL programs (if you like pain), or from a Web application server such as WebSphere (now we're
talking). WebSphere provides a Web-enabled environment that lets you focus on the applications and not the supporting
infrastructure. You don't want to spend time thinking about managing a user's connection to your system, and you don't want
to manage database connections. In the green-screen world, you didn't worry about this background stuff. When was the last
time you as a programmer worried about how the user obtained a sign-on screen? You need to concentrate on writing the
application to solve business problems, and the operating environment should handle all the background stuff.

One of the last remaining sore points I had against Java was that the code for the user interface was often embedded within
the business logic. In the GUI world, this can be incredibly time-consuming for the programmer. In the RPG world, you are
used to creating a display file with SDA and then being free to focus on the business logic in the RPG code. The addition of
JSPs brings this same freedom to the Java servlet world. JSPs handle the formatting of data for the user interface, and Java
servlets handle the management of the data. The combined use of JSP and servlets allows you to separate the business and
presentation logic.

Figure 41.1 shows the basic configuration I recommend. A typical scenario of an interactive session with a user would be as
follows:

F ig u re 41.1: The new application architecture uses HTML, Java servlets, JavaBeans, and JavaServer
Pages.

1. A user starts up his favorite Web browser.

2. The browser's URL references an AS/400-based Web site.

3. The AS/400's HTTP server services the user request by sending an initial HTML Web page to the browser (the initial
page is analogous to a 5250 menu).

4. The user clicks on a menu option of the Web page.

5. The browser sends the user's request to the AS/400-based site powered by WebSphere (or some other Web
application server that supports servlets).

6. The Web application server recognizes a request to run a servlet (like a green-screen menu trying to run an RPG
program). The Web application server starts up the servlet, creating a unique environment for this session, and passes
to the servlet the user's menu option request.

7. The Java servlet, as an application controller, responds to the user's request by accessing the database (either with
direct database calls, RPG/legacy program calls, or Enterprise JavaBeans). The servlet then crunches the retrieved
data with its business logic, and, finally, the servlet assembles that crunched data into the information required to
respond to the user.
8. The servlet puts all the acquired data into a JavaBean object (often called view Beans or smart parameters) and
forwards control to a JSP (kind of like an EXFMT in an RPG program).

9. The JSP formats the data contained in the passed view Bean into a Web page.

10. WebSphere passes the dynamically constructed Web page back to the browser so that the user can view the
response.

Not too bad, huh? This process is similar to that of your RPG programs and 5250 display files. You had to code only four
pieces: the initial HTML page, to contain a menu; the Java servlet, to contain the business logic; the JavaBean, to hold the
display data; and the JSP, which generates the user interface. One thing I can't convey in the simple diagram shown in Figure
41.1 is that, in real life, this setup, without adequate performance tuning, runs like a dog. The one- to two-second response
time you are used to in RPG may turn out to be several minutes with an improperly tuned Java application. Chapter 47, "A
Programmer's Notebook: Making Servlets Run Faster," lists a number of tips that you can use to make your server-side
applications as fast as your legacy RPG applications.

Team-Fly
Team-Fly

A n M V C C o d e E x am p le
[Editor's note: The new application architecture discussed by Alex Garrison sounds fairly complex, so I decided to create a
simple application that uses the Model-View-Controller (MVC) architecture.] The following tutorial demonstrates how easy it is
to build an MVC application. Figure 41.2 is the static HTML user input panel, and Figure 41.3 is the dynamically constructed
HTML response.

F ig u re 41.2: HTML files are used for initial prompting.

F ig u re 41.3: HTML is dynamically generated by a JavaServer Page using data from a JavaBean.

Figure 41.4 shows the HTML for Figure 41.2; it simply prompts the user for a customer number. The most important line of
the HTML code in that example is this < F O R M > tag:

F ig u re 41.4: When the input display is static, there is no need for a JSP.

<FORM ACTION="/servlet/GetCustomer" METHOD="GET">

The ACTION option of the < F O R M > tag qualifies a Java servlet called G e tC u sto m e r as the server-side application that is to
handle the user request. When the user clicks the Submit button, your Web application server will invoke the G e tC u sto m e r
program shown in Figure 41.5. The in it function (or method in OO parlance) of the G e tC u sto m e r class sets up a connection
to DB2 for OS/400, but it's the d o G e t method that does the work of responding to the user's HTML-based request. The d o G e t
method retrieves the customer number with the g e tP a ra m e te r method, uses that number to create a C u sto m e r JavaBean
(by invoking its g e tC u sto m e r method that uses SQL to retrieve the customer data), sets that JavaBean as an
attribute/parameter of the user request, and passes control to a JSP.

 
 

F ig u re 41.5: A Java servlet handles the Web browser user's request by retrieving data from the database, stuffing that
data into a JavaBean, and forwarding control to a JSP .

The C u sto m e r JavaBean, shown in Figure 41.6, is an example of what I call a "smart parameter," because essentially it is
simply a data structure, with functions, which is passed as a parameter to a JSP. The *ENTRY *PLIST of JSP, shown in
Figure 41.7, that references the "smart parameter" is the < jsp :u se B e a n > tag. The JSP retrieves values out of the JavaBean
with the g e tN a m e and g e tA d d re ss methods. Note that the Java code of the JSP is nested between pairs of < % and % > tags.
Otherwise, the JSP contains standard HTML.

F ig u re 41.6: A JavaBean is used to contain the information obtained by the Java servlet.

F ig u re 41.7: A JSP formats the information contained in a JavaBean using a combination of HTML and Java
syntax.

Team-Fly
Team-Fly

C h ap ter 42: M ain tain in g S essio n S tate W ith Java S ervlets


O v e rv ie w
DON DENONCOURT

The architectures of legacy AS/400 applications are completely different from Web applications. With a legacy application,
when a user comes into work in the morning, she quickly enters her profile name and password and then saunters off for her
morning coffee while the job starts. Then, as she invokes the various programs of that application, those program invocations
are hers-she owns them. Each program invocation has its own memory space, its file cursors are maintained during think/wait
time, and all its variables relate to the last action its owner (the user) took. Most client/server applications-from complex
business applications to FTP-also have a similar architecture in that the user logs in and a persistent connection is
maintained for that specific user.

Now consider the default application model for applications that use HTTP (e.g., Web applications). First, the user keys in a
URL or clicks a link that makes a request to an HTTP server. That request could be for an HTML file, a Java applet, or the
execution of a CGI, Java servlet, JavaServer Page, or, curse the proprietary thought, a Microsoft Active Server Page (ASP).
Second, a TCP/IP connection is made between the client (the Web browser) and the server (the Web host). Third, the server
responds with, typically, an HTML response, but it could be any file such as an applet, a PDF, an email, or HTML
dynamically created with a CGI program or Java servlet. Finally, and here's the significant point, the connection is closed.
That server completely forgets about the user. If the user makes a request again and says, "Hey, remember me? I was here
just three seconds ago," the server will respond with "No. But what can I do to help you?" You can't get upset with the Web
server and the host-based application program, though, because they may have handled requests from dozens of other users
in the 3,000 milliseconds that transpired since you last interacted with them.

Team-Fly
Team-Fly

S tate le ssn e ss
Because the state of an application is not maintained between client (the Web browser) and server (the Web host), HTTP
applications are called "stateless." In the beginning, when the Web was used for the dissemination of static information, this
statelessness wasn't a problem. But when companies began to design business applications for the Web, this stateless
behavior became an issue. Quickly, however, simple solutions to these problems were devised.

One solution that is still in use is to embed hidden variables into HTML forms to fake a persistent session-that is, a session
with state. I say fak e because the server would still close the connection after responding to a request. In an RPG CGI
program, for instance, the developer might use the values from hidden HTML input variables to reposition file cursors and then
stuff those hidden variables back in the form of an HTML response.

One problem with this strategy is the proliferation of hidden variables in HTML forms. (Another problem is the cost associated
with starting up a new RPG CGI job with each user request.) The number of these hidden variables can easily clutter up the
application code, thus making programming maintenance even more difficult. A similar but somewhat cleaner solution is to
use HTTP cookies to maintain state. (For more on cookies, see Chapter 34, "Using Cookies to Pass Parameters Between
Web Pages.") But HTTP cookies typically have a limitation of around 20 cookies per Web server, which is a number that is
easily exceeded when attempting to maintain state in a business application.

To help alleviate this problem, a facility called persistent CGI-which takes advantage of the unique architecture of OS/400
(specifically named activation groups)-was introduced in V4R2. However, persistent CGI is a costly solution in terms of main
memory because it involves isolating a specific RPG program instance for each user. Java servlets also have facilities to
maintain session state, but they are far more frugal with memory than persistent CGI. Servlets are able to make efficient use
of system resources because of the sophisticated capabilities of Java threads. In fact, a single Java servlet instance is able to
maintain session state for any number of remote users. So, if your Internet application needs to maintain session state, Java
servlets are the way to go.

Team-Fly
Team-Fly

S h o p p in g C arts
The shopping cart metaphor is an example in which the maintenance of session state is a requirement. The user is browsing
through your store selecting items that she might purchase. When she sees something she likes, she places it in her
shopping cart. Eventually, she either wheels up to the cash register and pays for the order or walks away and hops over to
another Internet store. Obviously, the items in that shopping cart are specific to one particular customer, so the shopping
cart's contents must be available from one request to the next.

My example application uses the same shopping cart metaphor. My little "store" (Figure 42.1) sells only two books: Java for
RPG Programmers (Figure 42.2) and Java Applications Strategies for the AS/400 (Figure 42.3). When a shopper adds two
copies of the first book to her order, the summary page shown in Figure 42.4 is presented. Then, after the shopper adds a
selection for five copies of the second book, the summary page will look like Figure 42.5. Because the application maintained
session state, or "remembered" the items that were in the shop- per's basket, it was able to present the order-total page for
confirmation.

F ig u re 42.1: The storefront for my simple application is a page with links to the two products.

F ig u re 42.2: Each of the items for sale in my application has a separate HTML file.
F ig u re 42.3: The HTML files for each of the items for sale contain forms that include hidden fields for the item price and
description.

F ig u re 42.4: After an item is added to the shopping cart, the order-total page lets the shopper confirm the order or
continue shopping.

F ig u re 42.5: When a shopper confirms an order by clicking on the Order button, the AddItem Java servlet is invoked by
the Web server.

Team-Fly
Team-Fly

S e ssio n s
My application was able to maintain state through a feature of Java servlets called sessions. But, first, let me briefly review
servlets. The d o G e t and d o P o st methods of a servlet are the "mainlines" of a servlet. The Web server automatically invokes
the doGet method when the HTML form specifies the HTTP GET method, but if the form specifies POST, then the doPost
method is invoked. Both the doGet and doPost methods have the same two parameters: an input parameter of
HttpServletRequest and an output parameter of HttpServletResponse. (For more on servlets, see Chapter 39, "Serving Up
Host-based Java Apps.")

The servlet API includes a class called HTTPSession. When a user adds his first item to the order, the servlet creates a new
session by instantiating an HttpSession object. The HttpSession class encapsulates access to application-specific objects
that are associated with one particular user session. Your servlet creates that ses sio n object by invoking the g e tS e ssio n
function of the H ttp S e rvle tR e q u e st object:
HttpSession session = request.getSession();

If a session already exists for the shopper, a reference to that session is returned; otherwise, the g e tS e ssio n method creates
and then returns a new se ssio n object.

In truth, this se ssio n object is nothing more than a unique number that is associated with each client. That number is then
passed back and forth between the Web browser and the Web server as an HTTP cookie. All subsequent requests from the
client pass that unique session number back to the server as an HTTP cookie. The g e tS e ssio n function simply returns
encapsulated access to this unique session. User-specific information is then associated with that se ssio n object with the
H ttp S e ssio n class's p u tV a lu e method. The p u tV a lu e method stores session information in a session by stuffing a key/value
pair in the se ssio n object:
session.putValue("Order", orderObject)

This puts a key with a name of "Order" in the session that stores an O rd e r object that contains an array of Ite m objects.
That O rd e r object can be retrieved from the se ssio n object in subsequent user requests by requesting the value by its key
name:
Order orderObject =
(Order)session.getValue("Order");

You don't need to store all the objects used in an application in the session. Usually, one object is what I call the "root"
object, because all other objects are associated with that object. In my little application, the O rd e r class has one or more
Ite m objects associated with it. The user has only one shopping cart (i.e., the O rd e r object) and because that O rd e r object
has references to the Ite m objects that it "contains," the servlet is able to retrieve them without use of the se ssio n object's
g e tV a lu ee.

Team-Fly
Team-Fly

The C ode
The Java classes that constitute my little storefront application are shown in Figure 42.6. The O rd e r and Ite m classes are
JavaBeans that encapsulate the business entities of a shopping cart. The A d d Ite m and P la ce O rd e r classes are the servlets
that control the order process. The application also uses three HTML files: Ja va B o o ks.h tm l, Ja va R P G .h tm l, and
Ja va S tra te g ie s.h tm l. These HTML files present the Web pages shown in Figures 42.1, 42.2, and 42.3, respectively. The
Ja va B o o ks.h tm l storefront has links to Ja va R P G .h tm l and Ja va S tra te g ie s.h tm l. Both of those HTML files contain a
< F O R M > tag, and the ACTION of that < F O R M > tag says that the A d d Ite m servlet is to process the user request:

F ig u re 42.6: The storefront application uses two business JavaBeans that encapsulate access to a database and two
Java servlets that

<FORM ACTION="/servlet/AddItem" METHOD="GET">

Note that, normally, the METHOD option of the < F O R M > tag is set to POST. (I used the Tomcat Web application server from
Apache.org so that I could test my servlets from my PC-based development platform. See Chapter 45, "Tomcat for AS/400:
An Open-Source Web Application Server," for more information on Tomcat.) Because the GET method was identified in the
< F O R M > tag, the URL sent to the host was the following:
http://127.0.0.1:8080/servlet/AddItem?item=Java+for+RPG+Programmers&
price=89.00&quantity=2&Add=Add

Please be aware that when you use the GET method, the form parameters are sent as a URL query string and the servlet's
d o G e t method is invoked by the Web server. When you use the POST method, the parameters are passed in the body of the
HTTP packet and, as such, are not easily viewable by hackers-especially when Secure Sockets Layer (SSL) is enabled.
Forms that have the POST method specified are processed by the servlet's d o P o st method. I suggest you use POST
whenever possible because, besides the security aspect, there is typically a 256-byte limitation to the query string of a URL,
which limits the number of input fields in your HTML form.

Team-Fly
Team-Fly

G o o d F o rm
The forms of my Ja va R P G .h tm l and Ja va S tra te g ie s.h tm l files contain hidden fields that uniquely specify item price and
description as well as an input field for the quantity:
<INPUT TYPE="HIDDEN" NAME="item"
VALUE="Java for RPG Programmers">
<INPUT TYPE="HIDDEN" NAME="price" VALUE="89.00">
<INPUT TYPE="TEXT" NAME="quantity" SIZE=5 MAXLENGTH=5>

When the Web server receives the HTML request from the Ja va R P G or Ja va S tra te g ie s form, it calls the d o G e t method of
the A d d Ite m servlet shown in Figure 42.7.

   

F ig u re 42.7: The doGet method of the AddItem servlet associates each user with a unique session
ID .

The d o G e t method begins by doing the obligatory set of the content type and retrieval of the P rin tW rite r object (which is
where the dynamic HTML output is placed). Then it acquires a session context for the application with a call to the
H ttp S e rvle tR e q u e st object's g e tS e ssio n method and attempts to retrieve an existing order that may be associated with this
particular customer with the se ssio n object's g e tV a lu e method.
HttpSession ssn = req.getSession();
Order order = (Order)ssn.getValue("order");
if (order == null) {
order = new Order();
}

Note that if an order does not exist, the application creates one. With the O rd e r object in hand, the application then retrieves
the form's input parameters with the H ttp S e rvle tR e q u e st object's g e tP a ra m e te r method:
String itemStr = req.getParameter("item");

Using those input values, the application has the information required to be able to create an instance of the Ite m class,
insert it into the O rd e r object, and then associate the O rd e r object with the session with the p u tV a lu e method:
order.addItem(item);
ssn.putValue("order", order);

Team-Fly
Team-Fly

P lacin g T h e O rd e r
The d o G e t method of the A d d Ite m servlet then builds an HTML response that contains the complete order and a form that
asks the shopper if she wants to confirm the order:
<FORM ACTION="/servlet/PlaceOrder" METHOD="GET">;
<INPUT TYPE="SUBMIT" NAME="Order" VALUE="Order">
</FORM>

But to allow the shopper to continue browsing, the HTML response also contains a link back to the main order page:
<a href="/examples/jsp/order/JavaBooks.html">

When the shopper is ready to confirm the order and click the Order button shown in Figure 42.5, the d o G e t method of the
P la ce O rd e r servlet shown in Figure 42.8 is invoked by the Web server.

 
F ig u re 42.8: The PlaceOrder servlet gets the user's order with the session object's getValue method and then invokes
the Order class's write method to put the order to the database.

Just like the A d d Ite m servlet, the P la ce O rd e r servlet retrieves the session and, from that, the O rd e r object:
HttpSession ssn = req.getSession(true);
Order order = (Order)ssn.getValue("order");

The application then invokes the w rite method of the O rd e r class to place the order and its items in the application
database: o rd e r.w rite ();
();. When you copy the code for the O rd e r and Ite m classes from the CD included with this book,
you'll notice that I didn't implement the writes to a database. The intent of this example is to show how to maintain session
state. You can easily implement RDB persistence with JDBC, record-level access, or even basic Java serialization to text
files.

One other very important method that the PlaceOrder servlet invokes is the invali d a te method. This method destroys the
se ssio n object. After the order is confirmed, there is no reason for it to consume memory, so the in va lid a te method frees up
those resources: ssn .in va lid a te ()
(). Your application should probably also have a Cancel button that allows the user to abort
the order, in which case, the in va lid a te method would also be invoked. Also note that, should the shopper leave your Web
site without confirming or canceling her order, the session stays around for a typical default period of 18 minutes before the
session is destroyed. This period is configurable by all Web servers that support servlets.

Team-Fly
Team-Fly

M ain tain in g O rd e r
Maintaining state with Java servlets is easy. First you get an H ttp S e ssio n object with the g e tS e ssio n method of the
H ttp S e rvle tR e q u e st object. Then you associate the O rd e r object (which I think of as the root object because, with the root
O rd e rr, you can pull the order detail) with the session with the H ttp S e ssio n object's p u tV a lu e method. Subsequent user
requests in this same and other servlets are able to retrieve that root object with the g e tV a lu e method of the H ttp S e ssio n
object. Finally, when the application is done with the session, you should release resources with the H ttp S e ssio n object's
in va lid a te method.

I think you will find it very easy to create stateful Web applications with Java servlets. Furthermore, I think the resulting
application code will be far easier for other programmers to understand and modify than the applications code of programs
that used some other means of maintaining state. Servlets are quickly becoming the standard way to develop server-side
Web applications on all business platforms.

Team-Fly
Team-Fly

C h ap ter 43: S en d A M essag e W ith Javam ail


O v e rv ie w
JEFF MARKHAM

If you were to ask the average person if there is anything to the Internet besides the Web and email, I'm sure you'd get "no"
for an answer. Most programmers know that Java's strength, besides the platform-independence thing, lies in its networking
capabilities. Knowing that, as well as knowing that email is such a huge part of everyday life, it's not a reach to assume that
Java has email capabilities. Java does have these capabilities in JavaMail. This chapter tells you how to use JavaMail to send
an email message and how to give Web applications a professional touch.

Everyone gets annoying email, like those messages from users who don't know how the Caps Lock button works-or who hit
the Reply to All button-or spam. Of course, email was never meant to be annoying; the early pioneers who built the Internet
intended it as a communications tool. One of those pioneers was Ray Tomlinson of the company Bolt, Beranek, and
Newman, which is now known as BBN Technologies and is part of GTE.

In 1971, right about the time Reggie Jackson hit his historic 520-foot home run off a Tiger Stadium light tower during the All-
Star game in Detroit, Tomlinson invented what is now known as email and sent the very first email message: "Testing 1-2-3."
He presented the first functional email program about a year later, in 1972, when Jackson was about to become the first
major-league baseball player with facial hair since 1914. But you already knew all that. Fast-forward 30 years: The novelty of
email has been replaced by its status as an everyday part of life. Not only do you use email clients all the time, but now, with
JavaMail, you can incorporate email into your Web applications as well.

Team-Fly
Team-Fly

Y o u 'v e G o t M ail
JavaMail Version 1.1.3 comes as an extension to the standard Java Development Kit (JDK), meaning that it is not included in
any JDK download and must be downloaded separately. JavaMail works with the JavaBeans Activation Framework (JAF),
which is also an extension of the JDK. This chapter presents a sample application that receives email via POP3. This means I
need POP3 support, for which I'll use Sun's free POP3 Provider.(Links to download these packages are listed in the
"References" section at the end of this chapter.)

The download files of these products include various demos and documentation, but what you'll need is three JAR files:
activation.jar, mail.jar, and pop3.jar. First, I'll clarify the ingredients of this chapter's example. The mail.jar file is JavaMail.
JavaMail requires the assistance of JAF, the activation.jar file, to handle the data content of the many different types of files
that can be sent across the Internet. The activation.jar file handles many low-level tasks required by JavaMail, and chances
are you'll never use the classes in this archive unless you want to add attachments when sending email.

To receive mail, there are two main protocols in use today: POP3 and Internet Mail Access Protocol (IMAP). IMAP support is
included in JavaMail and is superior to POP3 in virtually every way. The trouble is that POP3 is still much more widely used
than IMAP. This is why, to have POP3 support when using JavaMail, you must download the POP3 Provider, which is pure
Java but is not included in the Java family in any way, not even as an extension. Also, JavaMail is built with client-side email
in mind, and, as such, it cannot be used to build a mail server.

Team-Fly
Team-Fly

A ttach m e n t: S am p le C o d e
I'll outline some key classes in JavaMail by showing you an example of a servlet that reads and sends regular text email and
throws in a JavaServer Page (JSP) that acts as an error page, displaying exceptions and then sending a message to notify
the appropriate personnel about the error.

The example servlet begins with the simple HTML form shown in Figure 43.1 (the HTML code for which is shown in Figure
43.2) where a user enters values for his SMTP and POP3 servers, user name, and password. The user-name and password
values are used for the POP3 server. Typically, SMTP servers don't require a login.

F ig u re 43.1: A simple HTML form prompts for the information required by JavaMail.

F ig u re 43.2: The HTML input form qualifies ServletMail as the server-side Java class that is to respond to the user's
request.

The main servlet receives the parameters posted by the HTML form and creates a list of email messages that are available to
read (as shown in Figure 43.3).
F ig u re 43.3: This list of email messages is displayed upon logging in to a POP3 server.

Now I'll pick apart the code that gets you to this point. You first need to establish SMTP and POP3 services in the servlet
before you can do anything. The SMTP host is used by JavaMail in a simple yet specific manner. When JavaMail needs to
know the SMTP host name, it looks to the system Properties object for a property called smtp.mail.host. You must input the
property and the property's value. Setting up POP3 is a little more involved, but it's an easy three-step process:
1. Get a Session object.

2. Get a Store object.

3. Connect to the store.

Team-Fly
Team-Fly

E m ail S e ssio n s
A session in the vernacular of JavaMail should not be confused with an HttpSession of the API servlet. A JavaMail S e ssio n
doesn't maintain the status, or state, of a connection like an H ttp S e ssio n does. A Session object holds various user
configuration properties, such as the user's email address and host names. Once you have the Session object, you can get
the Store object by calling the session's g e tS to re () method.

The code snippets in Figure 43.4 detail the process of setting up SMTP and POP3 support. As you can see at Label A, you
supply the getStore() method with a string parameter, identifying what type of service you'll need; in this case, it's p o p 33.
Finally, when you get the Store object, you can connect to the resource, using the host name, user name, and password
supplied in the HTML form.

 
F ig u re 43.4: These are code snippets from both ServletMail.java and error.jsp .

In the unabridged version of the code shown in Figure 43.4, I put the Store object to the H ttp S e ssio n object so that I can use
it after I've logged on. If I didn't do this, I'd need some way of recreating the Store object so that I could retrieve new messages
during my H ttp S e ssio nn. Now that you're connected to a POP3 server, it's time to get the mail. Now you'll see the differences
between POP3 and IMAP and how JavaMail makes life easy no matter which provider you use.

To get your mail, you need to instantiate a Folder object, which tells JavaMail where your messages are located on the mail
server. Folders are a natural concept for IMAP, but POP3 has no such thing. Fortunately, the JavaMail specification requires
that POP3 providers implement a virtual folder called "INBOX." This way, when you create the Store object, using the method
described earlier, you only need to change the string from pop3 to imap (or whatever mail-retrieving protocol comes down the
pike).

After you create the folder, you can open it using-you guessed it-its open() method. The open() method takes an int as its
parameter, which tells JavaMail what mode the folder will be in or how you want to open the folder. Because this is an
example of getting email through your browser, you'll open the folder in read-only mode so that the messages stay on the
server. Figure 43.4, Label B, details the steps needed to retrieve email messages.

Team-Fly
Team-Fly

R e ce iv e A ll
After you've gone through all the steps to set up POP3 and SMTP services and you've opened a folder on the host, you're
ready to get the messages. Evoking the g e tM e ssa g e s() method of the folder will give you an array of Message objects that
you can use to create the message list. If you've ever used your favorite email client to view email source code, you know
there's a lot more to an email message than just the body of the message. JavaMail gives you several methods in the
M e ssa g e class to get at that information, and the example uses a few of those methods to create the message list-namely,
the ones that extract the date, sender, and subject of the message.

An important feature of JavaMail is that the Message class is "lightweight." In layman's terms, that means you don't get parts
of the message you haven't asked for. So, if your good buddy was gracious enough to send you an MPEG file of the entire
movie Caddyshack , you wouldn't have to wait a week for it to download if your email client used JavaMail.

As shown in Figure 43.5, viewing an individual message from the list is one of the more involved portions of the servlet, which
could get even more complicated quite easily. The details are in the read() method, where the message you want to view is
cast to, or changed into, a MimeMessage. Check the MimeMessage to see if it's HTML mail; if it is, just have the servlet
send the message out through its OutputStream. If it's regular text, the method formats the text a little, then sends it out to
the browser. If it's another type of MimeMessage called a M im e M u ltip a rt, that usually means there are attachments, and the
example simply prints out what kind of attachments they are (i.e., their Multipurpose Internet Mail Extension, or MIME, types
and their names).

F ig u re 43.5: This message is displayed after selecting a message from the list of emails.

Team-Fly
Team-Fly

S e n d A ll
Now that you have the lowdown on the key classes of retrieving and reading email, I'll get into what it takes to send email.
Sending email is a little easier, except, as I mentioned before, if you want to send attachments. I'll leave it up to you to figure
that one out.

Because the example doesn't send attachments, you get to use MimeMessage instead of MimeMultipart as the type of
message to send. Once an instance of M im e M e ssa g e is available to use, you can employ some simple methods to
construct the scary-looking email source I mentioned before. The example uses some of the methods of the M im e M e ssa g e
object to set the sender, recipient, subject, and body of the message. These parameters are retrieved from an HTML form that
the servlet itself puts out to a browser. After you've built the M im e M e ssa g ee, you use one of the few methods of the
T ra n sp o rt class called se n d () to-you guessed it again-send the message. The method takes the M im e M e ssa g e you created
earlier as its parameter. That's it for sending email. All the code for sending messages is shown in Figure 43.4 at Label C.

One of the features I put into the servlet is a JSP error page, the code for which is shown in Figure 43.6. Of course, there are
a million things that could go wrong when sending an email across the Internet. If something does go wrong, the error will be
captured and displayed along with some words that are meaningful to an actual user; the cryptic text of the error will be sent
as an email to somebody who can decipher its meaning (presumably to an IT person). Without going into lengthy detail about
how JSP error pages work, I'll point you to Figure 43.4, Label D, which shows the three lines of code you'll need to send
exceptions to a JSP error page.

 
F ig u re 43.6: A JSP error page itself sends an email to the person responsible for maintaining the Web
site .

Once the JSP has control of the application and has the Exception object, simply get the text of the Exception object (as
shown in Figure 43.4, Label E) and send it, using the same procedures I discussed for sending email.

Figure 43.7 shows what happens when I try to log on to my POP3 server using an invalid password. The error page displays a
brief message and explains that a message was sent to somebody who could do something about it. Figure 43.8 shows the
message sent by the JSP error page. To spice up the page a little, you could add several other items of interest to the email
such as query string parameters, cookie text, or headers.
F ig u re 43.7: This is the output of error.jsp after successfully sending an email about an error in
ServletMail.

F ig u re 43.8: This detailed error message is sent by error.jsp.

Team-Fly
Team-Fly

M o re E m ail Id e as
You've seen that using JavaMail in your Web applications is not difficult. In addition to being easy to use, JavaMail will give
your Web applications a nice touch.

There are several different applications of JavaMail. You could set up some email accounts to receive messages of a different
variety on your mail server. For example, you could use a servlet that reads a calendar file and sends an email to everyone in
your company, reminding them of the cutoff date for month-end or inventory processing. A servlet could also check inventory
files and send email to appropriate personnel when levels reach a certain strike level, either high or low. Brainstorm a while,
and you'll find there are many ways to employ JavaMail in your company.

Team-Fly
Team-Fly

R e fe re n ce s
 BBN Technologies Web site: www.gte.com/AboutGTE/gto/bbnt/index.html

 JavaBeans Activation Framework Web site: http://java.sun.com/beans/glasgow/jaf.html

 JavaMail API Web site (to download JavaMail and POP3 Provider): www.java.sun.com/products/javamail/index.html

Team-Fly
Team-Fly

C h ap ter 44: S yn ch ro n izatio n Issu es W ith Java S ervlets


O v e rv ie w
STEVE NJENGA

A servlet is a Java program that executes in a Java-enabled Web server. It runs entirely within the Java Virtual Machine (JVM),
and its purpose is to service requests from Web clients. The Web server then returns a response, typically in HTML, to the
client. Servlets are a powerful way to replace CGI programs written in various languages, such as C and Perl. Why should you
use servlets? Consider the following reasons:

P o rta b ility: Servlets are developed in Java, so that they can be moved to various operating systems without having to
recompile the source code, as is the case with CGI modules.

E fficie n cy: Servlets are loaded only once by the Web server. Each new request calls one of the servlet's se rvice methods; a
new CGI program, on the other hand, is loaded for each client request.

P e rsiste n ce : Servlets, once loaded by the Web server, reside in memory, allowing a state to be maintained between
requests. (An example of this is the shopping cart that is found on many Web sites.)

S e cu rity: Servlets run on the server in a Java "sandbox," which prevents them from disrupting the operating system or
breaching security. They can also take advantage of the Java Security Manager architecture.

Servlets are also robust and extensible, because they are developed in an object-oriented language.

Team-Fly
Team-Fly

T h e S e rv le t A rch ite ctu re


The servlet architecture consists of two Java packages: ja va x .se rvle t and ja va x .se rvle t.h ttp . The ja va x .se rvle t package
contains interfaces (classes that define methods but do not implement them) and classes that are extended and implemented
by all servlets. The ja va x .se rvle t.h ttp package contains classes that are extended by servlets that will handle HTTP
requests. Central to the servlet architecture is the ja va x .se rvle t.SS e rvle t interface class found in the ja va x .se rvle t package.
Servlets implement the methods within this class to handle communication with Web clients.

The following three methods are the most important: in it rvice, and d e stro yy. The in it method is called once by the Web
it, se rvice
server when loading the servlet. (The in it method typically establishes database connections.) The se rvice method receives,
handles, and responds to client requests. The d e stro y method performs cleanup functions (such as closing open database
connections or files and terminating long-running threads) when the servlet is explicitly unloaded or the Web server is shut
down.

The S im p le S e rvle t class, shown in Figure 44.1, is an example of the most basic of Java servlets; it has the in it
it, se rvice
rvice,
and d e stro y methods. S im p le S e rvle t merely responds to a Web-browsing client, via HTML, with the message "HELLO
WORLD!"

F ig u re 44.1: This simple servlet displays "HELLO WORLD!" on the browser.

Team-Fly
Team-Fly

T h e S e rv le t E n v iro n m e n t
Once initialized and loaded by the Web server, a servlet resides in memory, ready to handle client requests. The Web server
calls the servlet's se rvice method to handle these client requests. For example, the following URL request entered on a
browser will be routed to S im p le S e rvle t:
http://someHost/server/SimpleServlet

(Note that a servlet may also be called from an HTML form.) To communicate with the servlet, the Web server passes two
objects to the se rvice method: an H ttp S e rvle tR e q u e st, which encapsulates communication from the client to the server,
and an H ttp S e rvle tR e sp o n se
se, which encapsulates the communication from the servlet back to the client.
H ttp S e rvle tR e q u e st and H ttp S e rvle tR e sp o n se are interfaces defined by the ja va x .se rvle t package.

Team-Fly
Team-Fly

R e q u e st P ro ce ssin g A n d C o n cu rre n cy P ro b le m s
As I stated before, only one instance of S im p le S e rvle t will be initialized and loaded by the Web server. As shown in Figure
44.2, if several clients are accessing the Web server, the servlet's se rvice method will be called on by the Web server to
handle the multiple clients.

F ig u re 44.2: Multiple clients are handled by one servlet.

Technically, the servlet is running as a thread within the context of the Web server's JVM. The resulting implication is that the
calling clients will share the servlet's resources, such as its instance variables, database connections, or external files.

For example, in Figure 44.3 (with the import statements and the init and destroy methods omitted for space), SimpleServlet is
rewritten so that the service method saves the request object in the local variable clientRequest, then calls the
d isp la yW e lco m e M e ssa g e method, the purpose of which is to display the client's user name on the browser. The client's
user name and password are retrieved from the clie n tR e q u e st and stored in the u se rn a m e and p a ssw o rd String variables
before responding to the client with a welcome message.

F ig u re 44.3: This simple servlet displays the input user name back to the client browser.

All client calls will, however, share these variables, including the class variable clie n tR e q u e st. But, when written this way,
there is no telling what each client will see on the browser; client 1 may see the user name from client 3 or client 2, which is
unexpected behavior. Therefore, when developing servlets, you need to examine what might happen if multiple calls are made
to the se rvice method simultaneously. Specifically, you need to be aware of what happens to servlet instance variables and
how external resources are accessed in the se rvice method.

Team-Fly
Team-Fly

S e rv le t V ariab le s
A servlet's instance variables (i.e., variables defined outside the scope of a method) maintain a client-specific state. For
example, in Figure 44.3, the u se rn a m e and p a ssw o rd variables of S im p le S e rvle t hold the calling client's input.

The danger here is that the values of these class variables may end up in an unknown state. Consider the following scenario.
Client 1 calls the S im p le S e rvle t cla ss's se rvice method, sets the clie n tR e q u e st variable, and is preempted. Client 2 also
calls S im p le S e rvle t and sets clie n tR e q u e st. Meanwhile, client 1 is back and continues to execute the
d isp la yW e lco m e M e ssa g e method. The problem in this scenario is that, since the clients share the same instance variable,
clie n tR e q u e st, the values of u se rn a m e and p a ssw o rd displayed for client 1 are those sent by client 2.

There are several solutions to this problem. The first solution is to avoid declaring servlet variables at the instance level by
instead either passing objects from method to method or declaring variables local to a method. In Figure 44.4, for example,
the clie n tR e q u e st variable has been eliminated, and the u se rn a m e and p a ssw o rd variables are local to the
d isp la yW e lco m e M e ssa g e method.

F ig u re 44.4: Avoid instance variables at all costs.

The second solution is to develop the servlet so that it handles only one client request at a time. This solution is achieved by
implementing the S in g le T h re a d M o d e l, as well as extending the H ttp S e rvle t class, as shown in Figure 44.5. With this
implementation, each service call is handled serially by the Web server (i.e., the server makes sure that your servlet runs only
one se rvice method at a time). However, for the purpose of scalability and performance, the Web server should be capable of
spawning new instances of the servlet as well as supporting some kind of pooling mechanism to prevent blocked access to
the servlet. Otherwise, the user may experience degraded performance. If the servlet were to access external resources,
however, there is still the issue of handling concurrency problems (this is discussed in the "Accessing External Resources"
section).

F ig u re 44.5: The SingleThreadModel interface ensures that servlets run only one service method at a
time.

The third solution is to use Java threads and synchronize the methods or the specific block of code that is subject to
concurrency problems. Java threads and synchronization may be new concepts to you, so let me explain them.

Team-Fly
Team-Fly

A cce ssin g E x te rn al R e so u rce s


Typical external resources include files, data structures, or databases that are accessed from the servlet via JDBC or via the
Java Toolbox for AS/400's record-level access classes. (Note that the database connections are instance fields and are
typically constructed in the in it method.)

A single client should not monopolize a resource that it is not actively using. When a client acquires a resource and blocks
that resource while awaiting another resource (such as I/O), Java will allow a second client to access the resource. This
condition makes sense and is often desirable. However, the flow of events must be taken into account, because the first client
may not be done with its task and the second client may want to access the same resources, resulting in a deadlock.

Accessing external resources typically involves reading and writing to the resources (i.e., any number of threads should
execute read operations simultaneously but allow only one thread to write or to modify the resource at a time). For example,
with SimpleServlet, you might want to add code to validate the user name and password in the database as well as log the
date and time of the last access. This is done by adding the following methods to SimpleServlet:
public synchronized boolean ValidateUsernameAndPassword(…)
public synchronized void UpdateLoginDatetime(…)

With this approach, the database read and write operations of the va lid a te and u p d a te methods are synchronized by
including the keyword SYNCHRONIZED in their method declarations. The existence of the keyword SYNCHRONIZED causes
a lock to be created for each instance of the class. A thread that calls a synchronized method belonging to the object
instance must obtain this lock and automatically release it upon exiting. Any thread that attempts to execute
V a lid a te U se rn a m e A n d P a ssw o rd () or U p d a te L o g in D a te tim e () is forced to wait until the lock becomes available. This
effectively serializes all operations on the database. However, there is no scalability with this approach, and it results in very
poor performance if the number of clients grows too large.

Instead of synchronizing an entire method, you can synchronize blocks of code within the methods that modify the resource.
In the example shown in Figure 44.6, the code within the synchronized block can be executed only a single thread at a time.
When each thread enters the synchronized section, it obtains a lock for the object, or instance, represented by THIS. Again,
this technique ensures that only one process can use the update and read operations at a given time. In addition, "starvation"
may occur; a runaway thread may monopolize the resource within the modify block and effectively cause all other modify
threads to block or wait indefinitely.

F ig u re 44.6: Synchronizing a small block of code is more efficient than synchronizing a complete
method.

Synchronizing sections of code in a class, however, does not prevent simultaneous reading from and writing to a resource.
Two different instances of a class will have independent locks, each of which can be obtained by two separate threads. In one
instance, a thread may obtain a lock upon entering a synchronized update section of code, while, in the second instance,
another thread obtains a lock upon entering the read section. This may lead to unexpected results, such as data corruption.

Team-Fly
Team-Fly

Im p le m e n tin g T h e W ait A n d N o tify M e th o d s


The w a it and n o tify methods in conjunction with synchronization allow for the controlled acquisition and release of a lock.
The w a it method allows a thread to release its lock, to put itself in a wait state, and then to continue execution at the same
point when it is notified to do so. The n o tify method allows the thread that is running to inform the thread that is waiting that it
should resume and acquire the lock.

A thread in a wait state is, in effect, waiting for some external condition to become true; the lock is the mechanism that is
used to indicate this condition. When the thread is notified that the lock is available, the awaited condition has become true.
The code of Figure 44.7 illustrates how to use the w a it and n o tify methods. In this example, the P ro ce ssR e q u e st object
may be called from a servlet to read and modify a single external resource within the same operation. For example, a client
may retrieve a value from a column in a database table and then update that column before proceeding. Implementing the
w a it and n o tify methods in this way allows simultaneous reads, blocks reads if the resource is being modified, and allows
sequential writes (i.e., only one thread can write to the resource at a time, thus avoiding a race).

F ig u re 44.7: Ultimately, the use of wait and notify is the only way to ensure that a deadlock does not
occur.

Team-Fly
Team-Fly

T h e R ace T o R o b u st C o d e
Servlets provide a great architecture for Web applications, but Java coders must take care to manage resource contention.
Perhaps the best way to control contention is to simply code your servlets so that their threads will have no shared
resources, which is easily accomplished by using only local variables and refraining from the use of instance variables.
Another simple option is to use the single thread option—but only if you know that the servlet will have relatively few clients.
However, because instance variables are often a necessary evil— such as JDBC connections and record-level access file
opens—you will have to resort to the use of synchronized blocks. You should always try to synchronize the smallest block of
code possible to decrease the block time. The ultimate strategy for synchronization, because it removes any opportunity for
deadlock, is to use w a it and n o tify operations.

Team-Fly
Team-Fly

C h ap ter 45: T o m cat F o r A S /400: A n O p en


en--S o u rce W eb
A p p licatio n S erver
O v e rv ie w
DON DENONCOURT

OS/400 ships with WebSphere Standard Edition, which provides support for the server-side Java capabilities of JavaServer
Pages (JSPs) and servlets. But, I must admit, I haven't been faithful to IBM. I have to confess that I've been Tomcatting
around; I've been going out on WebSphere and fooling with other Web application servers. Why the disloyalty to IBM? Why
am I no longer "true" to "Blue"? For one thing, WebSphere 3.0 (the version that ships with OS/400 V4R4 and V4R5) is difficult
to install and difficult to configure. For another thing, although WebSphere is bundled with OS/400, it is a chargeable product
for most other platforms. Plus, I've found an open-source Web application server that will work on almost any computer that
runs on electricity.

What's the name of that open-source Web application server? Tomcat, from Apache.org. That's the same open-source
organization that provides the Web server used by 60 percent of all servers in the world (based on a December 2000 survey at
www.netcraft.com/survey/). Tomcat is quickly becoming a dominant player in the Web application server market. When
Tomcat first became available, it was thought of as merely a reference implementation of a Web application server (that is,
one to be used for proof-of-concept applications). But more and more mid- to high-end Web sites are beginning to use Tomcat
as their production Web application server. Webhelp.com, for instance, uses Tomcat to service more than 10 million
JSP/servlet transactions per day. Unless your site receives more hits than that, you might consider trying Tomcat. This
chapter covers how to install, configure, test, and performance tune Tomcat on your AS/400.

Team-Fly
Team-Fly

In stallin g T o m cat
To install Tomcat on your AS/400, first download ja ka rta -to m ca t.zip from jak arta.apache.org to your PC. You can use
WinZip to install Tomcat on your PC if you wish, but this chapter discusses Tomcat installation for the AS/400. So, you'll
need to upload ja ka rta -to m ca t.zip (using FTP or similar facilities) to a directory on your AS/400's IFS. To unzip Tomcat on
the AS/400, you'll need to use Java's ja r tool from the Qshell Command Entry screen. Therefore, start Qshell with the QSH
command, change your current directory to the IFS root, and invoke the ja r utility:
cd /
jar xf /where/ever/you/put/jakarta-tomcat.zip

The x option says to extract, and the f says that the compressed file name is to follow. Be sure to qualify the exact location
of the ja ka rta -to m ca t.zip file. Note that Qshell is thread-based, so its command screen is input-capable even while the
extraction process is running. The extraction process may take two or three minutes. You'll know it's complete when you see
a dollar sign ($) underneath the ja r command. The extraction process will create a directory called ja ka rta -to m ca t
underneath your working directory (which should be directly under the root if you change your directory, as noted earlier). To
quickly confirm that Tomcat has been installed, change the working directory to ja ka rta -to m ca t and list the files and
directories within using the ls command:
cd jakarta-tomcat
ls

You should see a list of six directories (bb in


in, co n f, d o cc, lib , src
src, and w e b a p p ss) and one file (LICENSE).

Tomcat requires no configuration unless its default port use of 8080 and 8007 is in conflict with one of your existing TCP/IP
server applications. The ports are set in a file called server.xml in Tomcat's conf directory. The easiest way to modify that file
is to use the Edit File (EDTF) command (which has been available only since V4R4):
EDTF '/jakarta-tomcat/conf/server.xml'

If you scan for the string "port," you'll find the two places the ports are set. Make the change, press F3 to exit, and your
Tomcat is configured for the new port.

Team-Fly
Team-Fly

S tartin g T o m cat
Although Tomcat ships with both UNIX- and Windows-style scripts, for the AS/400 you need to create an OS/400-specific
Qshell script file, such as the to m ca t400.sh file shown in Figure 45.1. The script begins by setting the
QIBM_MULTI_THREADED environment variable to TRUE so that it can appropriately "spawn" the Tomcat server application. It
then creates an environment variable to qualify Tomcat's home directory.

 
F ig u re 45.1: To run Tomcat on your AS/400, you'll need an AS/400-specific startup script .

Note that the -s option of the e x p o rt command says that the environment variable is available to subprocesses. The script
then saves the current CLASSPATH before it adds Tomcat's JAR files that contain the all-Java code that runs the server.
Next, the script adds application-specific JAR files. Almost all AS/400 sites will, at the very least, be adding the Java Toolbox
for AS/400 JAR file. Finally, Tomcat is started with the Java Virtual Machine (JVM) command ja va va. Note that the ampersand
(&) that trails the ja va command is required to start Tomcat as a thread-based subprocess.

Once you have your OS/400-specific Tomcat startup file ready, you can invoke it with the following Submit Job (SBMJOB)
command:
SBMJOB +
CMD(QSH CMD('/jakarta-tomcat/bin/tomcat400.sh')) +
JOB(tomcat)

Because Tomcat is a never-ending server application, it should not be run interactively. You also need to consider what
subsystem Tomcat should run under. When playing with Tomcat, you might just let it run as a low-priority batch job. Later,
however, you might want to run it with a much higher priority because, after all, Web applications are interactive.

With Tomcat successfully running, you should be able to access it from your Web browser by qualifying your AS/400's
domain name or IP address followed by a colon (:) and Tomcat's port number (8080 if you didn't change it in se rve r.x m l). You
should see Tomcat's home page (as shown in Figure 45.2). I encourage you to try the sample JSP and servlets (be sure to
check out their source code). If you want a quick way to try out your own JSPs and servlets, simply copy your JSP, HTML,
and image files to /ja ka rta -to m ca t/w e b a p p s/R o o t and then copy your servlets and JavaBeans to /ja ka rta -
to m ca t/w e b a p p s/R o o t/w e bb--in f/
f/classes.

F ig u re 45.2: Once you submit the Tomcat script to batch, you should be able to access it from your Web
browser.

All good things must come to an end and so too must your Tomcat job. So, to end Tomcat, you'll need to invoke a Qshell
script such as my e n d to m ca t400.sh file shown in Figure 45.3. This script will run quickly. Go ahead and run it interactively
from a command line:
QSH CMD(‘/jakarta-tomcat/bin/endtomcat400.sh’)

F ig u re 45.3: To end Tomcat, you should run a script that "gently" brings it down.

I considered writing a couple of OS/400-style commands that invoke my two Qshell scripts, but, if you don't have anyone in
your shop who knows how to write commands, you may as well just run Tomcat from Linux or NT.

Team-Fly
Team-Fly

P e rfo rm an ce T u n in g
Note that the first time you run any of the samples, you'll experience a lag time of a few minutes. That is the time that OS/400
must take to run the Create Java Program (CRTJVAPGM) command over Tomcat's JAR files. The problem with this automatic
process is that the CRTJVAPGM default optimization level is 10. Because optimization 10 is the slowest, I suggest you run
CRTJVAPGM manually and set optimization at 40 (that's what WebSphere's JAR files are automatically set to). The following
commands will properly optimize Tomcat:
CRTJVAPGM CLSF('/jakarta-tomcat/lib/servlet.jar') OPTIMIZE(40)
CRTJVAPGM CLSF('/jakarta-tomcat/lib/jasper.jar') OPTIMIZE(40)
CRTJVAPGM CLSF('/jakarta-tomcat/lib/webserver.jar') OPTIMIZE(40)
CRTJVAPGM CLSF('/jakarta-tomcat/lib/xml.jar') OPTIMIZE(40)

You might want to submit those CRTJVAPGM commands to batch because they could take five to 10 minutes each to
complete.

Team-Fly
Team-Fly

T h is M e an s W ar
The benefits of Tomcat go beyond price and robustness. Its benefits also include support for Sun's servlet API version 2.2 and
JSP 1.1. Few commercial Web application servers (including WebSphere) support the servlet 2.2 API. The best part of the 2.2
servlet API is Web Archive (WAR) files.

Remember that one of the biggest problems with Web applications is deployment. Quite often, the test and debug platform
and runtime environment is different from production. And every Web application server seems to handle deployment
differently. The servlet 2.2 API solves this dilemma with WAR files. WAR files are basically JAR files except that they contain
everything (JSP, servlets, HTML, XML configuration files, images, etc.) that is required to run an application. To deploy, all
you need to do is move the WAR file to the /ja ka rta
rta--to m ca t/w e b a p p s directory and modify Tomcat's configuration file to
qualify the new WAR and you're ready. You don't have to extract the WAR file; the application runs right out of the
compressed file.

Team-Fly
Team-Fly

D e b u g g in g Jsp s A n d S e rv le ts
Although IBM's VisualAge for Java Enterprise Edition (VAJ EE) provides a great debugging environment for JSPs and servlets,
VAJ EE is a costly product. Because Tomcat ships complete with its source code (it has to, it's open source), you can easily
set your entry-level Java integrated development environment (IDE) so that you can step through your Java servlets (which
also means you can step through the Java servlets code that is generated from a JSP). The two Web articles at the following
URLs show you how to set up Borland's JBuilder Foundation and IBM's VisualAge for Java for servlet and JSP debugging:
community.borland.com/article/0,1410,22057,00.html
www7.software.ibm.com/vad.nsf/Data/Document2390?OpenDocument

Basically, all these documents tell you is to add Tomcat's JAR files to your IDE's CLASSPATH. Then add the
o rg .a p a ch e .to m ca t.sta rtu p .T o m ca t class to your IDE's project. You'll also have to add a JVM parameter:
-Dtomcat.home=C:\where\ever\you\put\tomcat

Then add the servlet you wish to debug to your project and set breakpoints. Once that is done, you simply start the T o m ca t
class in debug mode from your IDE. I've set up a Tomcat test environment with JBuilder Professional 3.0, and you should be
able to do the same with your favorite IDE.

Team-Fly
Team-Fly

O p e n U p T o T o m cat
Yes, WebSphere probably scales better than Tomcat, but not so I could easily tell. I downloaded another open-source
product, called JMeter, from Apache.org. JMeter is an all-Java product that allows you to stress-test Web sites. A quick,
simplistic, and admittedly unscientific test showed that a couple of simple JSP data-access routines performed just as well
with Tomcat as they did with WebSphere (although that was before I "tuned" Tomcat's JARs).

Performance issues aside, Tomcat is very simple to install and configure. You don't have to worry about HTTP configuration
(Tomcat bundles its own HTTP server). You don't have to deal with WebSphere configuration from an oversized NT
workstation. And you have the latest and greatest of the servlet API and JSP standards.

Team-Fly
Team-Fly

C h ap ter 46: Ju m pp--S tart S ervlets A n d JS P s W ith W eb sp h ere


V ersio n 3.0.2
O v e rv ie w
RICHARD SHALER

OK, you have your WebSphere Application Server (WAS) Version 3.0.2 for AS/400. Now, how do you get it to execute one of
your cool JavaServer Pages (JSPs) or servlets? Even if you've had experience with WebSphere 2.0 for AS/400, you'll soon
discover that version 3.0.2 is a different beast. The installation and configuration of servlets and JSPs completely changed
between versions 2.0 and 3.0.2 of WebSphere. In this chapter, I'll show you how to get your server-side Java applications
running with WAS 3.0.2 with minimal configuration.

Team-Fly
Team-Fly

JS P S u p p o rt
If you have to use WAS, you should consider obtaining its latest version, which at the time of this writing is version 3.0.2; with
the latest PTFs, it actually becomes version 3.0.2.1. The main reason you should be using version 3.0.2 is that previous
versions only supported the JSP 0.91 specification—a specification that's rapidly becoming obsolete and being replaced with
JSP 1.0. Version 3.0.2 supports the JSP 1.0 specification. To start using WAS, you will need the following items installed
and configured appropriately:

 OS/400 V4R4 or later.

 One of the two available WAS licensed programs: 5733-WA2, the 56-bit encryption version, or 5733-WA3, the 128-bit
encryption version.

 TCP/IP Connectivity Utilities for AS/400, licensed program 5769TC1.

 IBM HTTP Server for AS/400, licensed program 5769DG1.

 Java Developer Kit for Java, licensed program 5769JV1.

 OS/400 cumulative PTF package C0049440 or later.

 The latest group PTFs:

 SF99026 WebServer (HTTP) Group.

 SF99028 WAS for AS/400 Group.

 SF99067 JAVA Group.

 SF99104 DB2 UDB for AS/400 (Database) Group.

 These individual PTFs:

 MF24700.

 SF62807.

 SF62809.

Team-Fly
Team-Fly

In stallatio n A n d C o n fig u ratio n


I'm going to provide only an overview of the installation and configuration process for WAS 3.0.2. You'll really need to go to the
manuals to get the job done, but this material will give you a good framework to work from. The best place to start with
configuration is at the WebSphere for AS/400 documentation site at
www.as400.ibm.com/products/WebSphere/docs/doc.htm. There you'll find links to various electronic manuals, including a
"Getting Started..." book for AS/400 that I found very helpful. To go to that manual directly, use the following URL:
www.as400.ibm.com/products/WebSphere/docs/as400v302/docs/getstart.pdf.

Installing WAS from the AS/400 version CD can be done from your AS/400 CD-ROM drive using the AS/400 Qshell
environment or from the CD drive of a connected PC. In addition to installing the server software, you must install the
WebSphere administration client software (kind of like the system console for WebSphere) on a Microsoft Windows NT
machine. To install the administration client, you must use the separate WebSphere for Windows NT CD. (I received the
Windows NT CD along with the AS/400 WebSphere CD.)

The administrative server listens for the administration client on default port 900. If you want to change this, you change the
admin.bootstrapPort property in the a d m in .p ro p e rtie s file found in IFS directory /Q IB M /P ro d D a ta /W e b A S A d v/p ro p e r
tie s/a d m in .p ro p e rtie ss.

The WAS process creates the QEJB library and two IFS directories: Q IB M /P ro d D a ta /W e b A S A d v and
Q IB M /U se rD a ta /W e b A S A d vv, with a number of subdirectories attached to them. I mention this because you'll use the
QEJBSBS subsystem in the QEJB library to start WAS (STRSBS QEJB/QEBJSBS), and you'll use the IFS directories to
store servlets, JSPs, and HTML files that you want WAS to process.

You will need to create a special HTTP server instance and configuration that will be used in conjunction with WAS. The
special HTTP configuration will need to be Java servlet and JSP-enabled. This is done by selecting a check box in the Java
servlet section of the HTTP configuration. You administer the AS/400 HTTP server instances and configurations from a
browser using port 2001 (e.g., http://<yourserver>:2001).

WAS's default location for servlets is the following: /QIBM/UserData/


WebASAdv/default/hosts/default_host/default_app/servlets/ <file_name>. Without any administration client configuration,
you can simply drop your servlet into this directory and it should run. However, by default, this application is not configured to
support JSP 1.0, only JSP 0.91. Fortunately, there is a Web application preconfigured with JSP 1.0 support. Its name is
s2. To use the e x a m p le s2 Web application, the JSP 1.0 code should be copied to this directory:
e x a m p le s2
/QIBM/UserData/WebASAdv/default/hosts/default_host/examples2/web/<file_name>

Now the trick is to create a P a ss directive in the HTTP server configuration for the HTTP instance used for your WAS. The
P a ss directive grants access to any .jsp file copied to the default servlet directory. It should look like this:
Pass /webapp/* /QIBM/UserData/WebASAdv/default/hosts/default_host/*

To run your JSP 1.0 application, you would use a URL like the following:
http://<your host>:<http server port if not 80>/webapp/examples2/myJSP.jsp

Because the JSP resides in a directory linked to a Web application that's configured for JSP 1.0 support, it should run. Figure
46.1 contains a screen capture of the WAS administration client application linked to Midrange Computing's AS/400. In the
left column, notice the JSP 1.0 Processor entry underneath the e x a m p le s2 Web application entry. This is what provides the
e x a m p le s2 Web application with JSP 1.0 support. Also notice that the Document Root for this application is as follows:
/QIBM/UserData/WebASAdv/default/hosts/default_host/examples2/web
F ig u re 46.1: The WebSphere Advanced Edition Administration Client is used to view the default JSP 1.0-enabled
examples2 Web application.

The Document Root is where you store documents for a Web application, and that's why I told you to copy your JSP to this
particular IFS directory. I knew the e x a m p le s2 application was configured to point to it.

Last, but definitely not the least, is classpaths. I say "not the least" because, when you have trouble determining the cause of
seemingly unexplainable problems with your Java application, it's often a problem with the classpath.

Some of your applications are going to need access to supplemental .class or .jar files located in various directories. For
example, a servlet that uses the AS/400 Java Toolbox will need to be able to find the jt400.jar file. In WAS, you can make the
classpath available two ways: to all Web application servers or to a specific Web application server.

To make a .class or .jar file available to all Web application servers configured in WAS Advanced Edition, you can modify the
admin.classpath statement in the U se rD a ta a d m in .p ro p e rtie s file
(/Q
/Q IB M /U se rD a ta /W e b A S A d v/d e fa u lt/p ro p e rtie s/a d m in .p ro p e rtie ss) and include the file name and its complete path. In
Figure 46.2, you can see I've added cla ssp a th five additional times to the a d m in .p ro p e rtie s file.

F ig u re 46.2: Add a classpath for all WebSphere Web application servers through the admin.properties
file.

Notice that I've used the equal sign, plus sign (=+) operator to append the new entry to the previous value of
th, and I've used a colon (:) to separate each entry.
a d m in .cla ssp a th

To make a .class or .jar file available to a specific application server, enter the file name and its complete path in the
Command line arguments property of the application server. For example, in Figure 46.3, I've added the AS/400 Java
Toolbox's .jar file to the classpath, so it will be available to all applications running on the Default Server (the only server
configured on MC's AS/400). If you need to add more than one classpath, separate them with a colon.
F ig u re 46.3: Add a classpath for a specific WebSphere Web application server through the Command line arguments
property.

Team-Fly
Team-Fly

W ish L ist
To me, one of the weaknesses of version 3.0.2 of WebSphere is that the administration client application uses a Java
application interface, which seems to have a certain degree of instability and kludginess. For example, when you perform
actions such as changing property values or stopping and starting servers or applications, you're forced to use a Refresh
button to reflect the change of value or status. Refreshing the application seems to take forever. I wish IBM had created an
HTML interface. If you've had any experience with Allaire's JRun 3.0 administration client, you'd quickly realize that an HTML
interface could be quicker and less problem prone. But to IBM's credit, it seems to be working hard to deliver fixes and
improvements to WebSphere. New PTFs are becoming available all the time. Be sure to check for the latest PTFs often.
Information about WebSphere for AS/400 PTFs can be found at www.as400.ibm.com/products/
WebSphere/services/service.htm.

There's also a generic WebSphere FixPacks and E-fixes Web page at www-4.ibm.com/software/webservers/appserv/efix.html
that contains a lot of detailed information about recent fixes.

Also, I wish the administration client would run on Windows 95/98 instead of only on NT. It would be so much easier for most
IT shops that want to begin using WebSphere if the administration client ran on Windows 95/98. It's not that fun to configure a
system with NT just to run the administration client. It doesn't seem that it would be that hard for IBM to do this.

Team-Fly
Team-Fly

O th e r P lay e rs
There are other Enterprise JavaBean (EJB)-capable Web application servers besides IBM's WebSphere, such as Allaire's
JRun 3.0, Bluestone Software's Sapphire/Web, and Sun's Forte for Java Enterprise Edition. Theoretically, these should run on
the AS/400. In fact, I've seen evidence that indicates that some users have at least one of these products running on the
AS/400. You will need to contact the vendors that produce these products to find out more information.

Team-Fly
Team-Fly

W as R e aso n in g
There are two advantages of moving to WebSphere 3.0.2. The first is support for the JSP 1.0 specification. The second is its
support for Enterprise JavaBeans (al- though it should be noted that, to use EJBs, you'll need the advanced edition of WAS,
which comes at a premium of $7,500 per processor). EJBs are what will make your Web applications truly manageable and
scalable. However, before you can run with EJBs, it is helpful to do a little walking with servlets and JSPs. With what you've
learned here, you can start making use of WebSphere Application Server Version 3.0.2 on your AS/400.

N o te  In the summer of 2000, IBM announced WebSphere Application Server Version 3.5 (standard and advanced
editions). Be sure to go to the AS/400 WebSphere home page to learn more about it.

Team-Fly
Team-Fly

R e fe re n ce s
 AS/400 WebSphere home page: www.as400.ibm.com/products/WebSphere/index.htm

 Building AS/400 Appls for WebSphere Advanced 3.0, Redbook (SG24-5691-00) at


www.redbook s.ibm.com/redpieces/pdfs/sg245691.pdf

 Documentation for Advanced Edition in HTML format:www.as400.ibm.com/products/WebSphere/docs/as400v302/docs/


index.html

 General FixPacks and E-fixes for All Platforms: www4.ibm.com/software/webservers/appserv/efix.html

 Newsgroup: ibm.software.WebSphere.application-server-as400

Team-Fly
Team-Fly

S e c tio n V III: Java P erfo rm an ce


C h ap te r L ist
Chapter 47: A Programmer's Notebook: Making Servlets Run Faster

Chapter 48: Java Performance Tuning

Chapter 49: Java Performance Tips

P art O v e rv ie w
Undoubtedly, after you've developed a large base of Java code, you'll have to do some performance tuning. Alex Garrison, in
"A Programmer's Notebook: Making Servlets Run Faster," provides plenty of tips and techniques on how to write Java code for
performance.

Sometimes, even the most well-written and beautiful code has to be tuned. You should never try to tune all your code. You
should tune by the old 80/20 rule: 20 percent of your code is used the most heavily, so you tune that 20 percent. So, how do
you find that 20 percent? OS/400 has an operating system component called Performance Explorer (PEX). In "Java
Performance Tuning," Paul Remtema shows you how to use PEX to find what sections of your code are performing poorly.
Paul also introduces an alphaWorks (www.alphawork s.ibm.com) tool called Performance Trace Data Visualizer (PTDV), which
presents Java performance data in a GUI.

There are times when even the most well-written code doesn't perform well. In "Java Performance Tips," Paul Remtema rips
apart my code introduced in "The Spartan Order System: An Exercise in Java Application Design" in Section XI. In a step-by-
step strategy, Paul uses my code to explain how to optimize existing Java applications.

Team-Fly
Team-Fly

C h ap ter 47: A P ro g ram m er's N o teb o o kk—


—M akin g S ervlets R u n
F aster
O v e rv ie w
ALEX GARRISON

For almost a year, I was part of a team of Java programmers that transformed the way my company does business by
completely rewriting its application using server-side Java. In this chapter, I offer some tips that have helped my team close
the final gap from a system that almost does what you need to a fully functional, productive alternative to the green-screen
world. Most of the lessons focus on the single biggest drawback to Java on the AS/400—poor performance. The opinions
offered are my own and reflect my pragmatic view that systems development should be an evolution, not a revolution. You will
have to judge for yourself whether any of these suggestions is right for you. All the members of my company's team of Java
programmers developed the tips that follow.

Team-Fly
Team-Fly

P ro filin g P e rfo rm an ce
In Chapter 41, "Servlets: The New Application Architecture," in Section VII, I give an overview of the basic configuration of a
server-side Java application. At the close of that chapter, I mention that an ill-tuned Java application can "run like a dog." Take
a look at some ways to make that application run like a racehorse. I think it is helpful to list the various pieces that have a
part in the typical server-side Java transaction outlined in "Servlets: The New Application Architecture." They are as follows:

 Network delays—When connecting over the Internet with a 56K modem, WebSphere may spend some time relaying your
HTML output from the JavaServer Page (JSP) to the browser. I try to plan on a user being able to support a 3 KBps
transfer rate. So, if my resultant HTML file is 30 KB, I can expect WebSphere to take 10 seconds just to transmit the file
from the AS/400 to the user's browser. Keep the HTML simple, clean, and attractive, and avoid animation or large
images.

 WebSphere delays—When WebSphere gets a request from the browser, it has to recognize that it should run a servlet,
start up the servlet, create a unique environment for the session, and pass the request to the servlet. The biggest
bottleneck is servlet startup. A decent-sized servlet may take several minutes to load the first time it is accessed. You
can eliminate most of this delay by configuring WebSphere to load your servlets when you start your Web server
subsystem.

 Servlet delays—Here is where your traditional programming skills come into play. Just as a poorly written RPG program
is slow, a poorly written Java program will be slow.

 Database access delays—Getting data to and from the database on the DASD takes time. Database I/O is the single
worst bottleneck I have seen. Keep database I/O to an absolute minimum. You may even want to denormalize (gasp!) the
database to help out this critical section.

 Environment delays—In the RPG world, you typically manage the environment with subsystems, priorities, classes, time
slices, and memory pools. WebSphere runs on the AS/400, so it too can be managed with these techniques. A
complicating factor, however, is the fact that the Java servlets run inside what is called a Java Virtual Machine (JVM).
Think of the JVM as a layer between your Java servlet and the operating system. The JVM manages its own memory and
has a number of properties you can set to affect performance.

For the user's experience to be as fast as possible, you first have to determine how the AS/400's time is being spent. This
means you have to profile the transaction and allocate a portion of the time to each of the categories that I listed. Start by
picking a time when you have the AS/400 pretty much to yourself. You want a level playing field without any outside
influences. Run the transaction from start to finish several times and record the total elapsed time from the time you click on
the browser to when the results are finally displayed on the browser. This is the overall perceived response time. The goal is
to make this as small as possible.

Next, take the resultant HTML that was displayed on the browser and save it to the hard disk of your PC. If you are using
Microsoft Internet Explorer, click on the File menu and select Save As. Set the Save As type to "Web page, HTML only."
After you have saved the file to your PC hard disk, take a look at the size of the file. Assuming the HTML doesn't include any
references to image files (.g
.g if or .jp e g ), the HTML's file size reflects how many bytes the JSP sent to the browser. Again,
assume the speed will be about 3 KBps over the Internet for dial-up modems, so divide the file size by 3 KB to estimate the
network delay.

Nailing down the WebSphere delay is a little trickier. If the servlet is already loaded, it typically takes WebSphere less than
100 milliseconds to fire off a thread and create the session environment. To nail this down more exactly, end your HTTP
server instance and restart it specifying this verbose option:
STRTCPSVR SERVER(*HTTP) HTTPSVR(myinstance '-vv')

As the server starts up, a spool file named QPZHBTRC will be created for user QTMHHTTP. You can look at the time stamps
in this spool file to see exactly how long it took for WebSphere to get a request to run a servlet, find that servlet, load the
servlet (if not yet loaded), and then pass the request information into the servlet. You can also see how many bytes were in
the response sent back to the browser. To end the traces, you will have to end the HTTP server and restart it normally
(without the -vv option). Again, this delay is not usually a problem. If you see delays of more than 100 milliseconds on a
servlet that is already loaded, contact IBM and get some help.

Servlet delays and database delays are best quantified by writing some time stamps to the WebSphere log file. All servlets
that are subclassed from ja va x .se rvle t.h ttp .H ttp S e rvle t can call the lo g (S trin g ) method and pass a string to be written to
the log file. Your WebSphere configuration controls the name and location of this log file. The log file is just a normal ASCII
text file, so you can look at it with Windows Notepad if you have mapped a drive to your AS/400. You can also use the
ADMIN Web site on your AS/400 to display the log file inside the browser (by default, it is www.myinstance.com:9090). Your
time stamps in the log file will tell you how long the servlet took to run once WebSphere started it up. Of course, this time
would include your database delays for any needed database I/O. Make sure your time stamps break out the database I/O by
writing entries to the log file specifying something like "now accessing database…" and "database access completed." If your
situation is like mine, database I/O will end up dominating your quest to improve performance.

Environment delays are very hard to quantify. The most likely cause I have seen is initial heap sizes being set too small. This
causes lots of extra garbage collection every time you hit the heap size limit and the JVM increases the heap (up to the
maximum heap size). These parameters are controlled by n cf.jvm .m x and n cf.jvm .m s in the jvm .p ro p e rtie s file. Assuming
you are running on an AS/400 dedicated to WebSphere, you want all the heap you can get, so set the minimum heap size to
be the same as the maximum heap size. I have heard general guidelines that the maximum heap size should be no more
than half the total main storage of the AS/400. You may have to play with that upper limit to see what works for you. Messing
with these parameters is not for the faint of heart. Make sure you record what the original values were so that you can recover
if you make a bad choice. You will have to end and restart the HTTP server for these changes to take effect. Again, I wouldn't
mess with the jvm .p ro p e rtie s file unless all other options have been exhausted.

Team-Fly
Team-Fly

P e rfo rm an ce T ip s
So far, you have profiled the transaction, and you know where the time is being spent. Now, you have to do something about
it. This section explores the tips that have helped me most.

R e co rd
rd--le v e l I/O Is F aste r th an S Q L I/O M o st o f th e T im e
If your performance profile is anything like mine, you will find that database I/O is the big performance killer in WebSphere. In
the best of circumstances, I have never seen the kind of I/O performance in Java that I have come to take for granted in RPG,
so that anything you can do to help here has a big payback. Getting SQL to run fast on an AS/400 is an art, not a science.
The bottom line is that you have to make the SQL optimizer happy every time. You may think you understand your SQL
statement and even think the optimizer will use the obvious index already built over the table in question. However, I have
learned from experience that the optimizer does not always make the obvious choices.

Sometimes, you may have so many indexes built over a table that the optimizer times out trying to pick the best approach.
Then, it may actually use the arrival sequence and build an index on the fly. If you are lucky enough to find an SQL statement
that makes the optimizer happy, you can "freeze" the optimization by putting the SQL statement in a stored procedure or a
prepared statement. Then, the optimizer will not try to reoptimize the SQL each time the procedure is executed. If you use
dynamic SQL, the optimizer will rerun every single time you execute the SQL. I have run internal benchmarks of dynamic
SQL, stored procedures with parameterized SQL, and other SQL techniques, and they usually don't come close to record-
level I/O using the IBM Java Toolbox for the AS/400. It is not uncommon to see performance increase by a factor of 12 for
record-level I/O over SQL.

I get a big payback using record-level I/O when I can make my initial record selection all from one table—that is, all my initial
selection fields are in a single table. Then, I can retrieve exactly the records of interest. Once I have these records, I can
selectively access other tables for supporting data. To do this, you may have to denormalize your tables somewhat. For
example, if you must select some records from the ORDER file within a given order date range and with customer names
starting with SM, you may have to put both the order date and customer name in the ORDER file (even if the customer name
is also in the CUSTOMER file). Record-level I/O using the toolbox allows you almost surgical control over database I/O; you
can reduce it down to just the absolute bare minimum.

On the other hand, there seems to be almost no difference between SQL and record-level I/O on small tables where you can
count on the optimizer to pick the right indexes. For example, if you have a state file with only 50 records keyed by state
code, SQL can find the record for Tennessee just as fast as record-level I/O can.

U se th e IB M C o n n e ctio n M an ag e r If U sin g JD B C
Starting up and closing connections to the database is very costly. The best way to avoid this delay is to let the WebSphere
IBM Connection Manager pool the database connections, keeping them open and ready for reuse. Using the Connection
Manager is a little beyond the scope of this chapter, but it is not as hard as you might think. Using a connection pool is not
much more trouble than managing the connection yourself. The big payback from connection pools comes when your servlets
release JDBC connections after each use. The Connection Manager will keep the connection open and put it in a pool where
this servlet and any other can reuse it.

Here's one word of caution: Always construct your code so that the Statement object's clo se method will always be called.
The Connection Manager will not release the SQL handle resources for you. If you forget to call the Statement clo se method,
you will slowly use up all the SQL handles available on the system. Eventually, SQL will just stop working altogether, and you
will have to restart the HTTP server.

L o ad A ll S e rv le ts at S tartu p
By default, WebSphere loads servlets only when they are requested. This means the first user to access a given servlet is
going to pay a big performance penalty while he waits (up to several minutes) for the servlet to load. You can easily use
WebSphere's administration facility to flag servlets to load at startup. It will take longer for the HTTP server to start up, but
your users won't see this long delay per servlet.

U se D ata P o o ls fo r S m all T ab le s
Data pools are an AS/400 feature that has been around for years and are not limited to WebSphere. You would be surprised
by how many AS/400 shops aren't aware of this nifty technique. You can basically force some tables or even just indexes to
stay resident in main storage all the time. There, they can be accessed at memory speeds instead of DASD speeds. Details
on how to configure data pools are beyond the scope of this chapter, but, in general, I like to set them up in a special
subsystem I create called DATAPOOL. Configure the subsystem to have a private pool big enough to hold the files or indexes
you want in main storage. You add an autostart job entry to the subsystem to run a little CL program. In the CL program, you
put something like the code shown in Figure 47.1.

F ig u re 47.1: Use this code to force tables or indexes to stay resident within a pool.

K e e p JS P O u tp u t S m all
It can take some time to send an HTML file across the Internet to a user who is on a dial-up connection. Take a look at the
HTML content sent back to the browser. You may be able to use Cascading Style Sheets (CSS) or other techniques to
reduce the amount of repeated information sent back to the browser. For example, you can set the default font and font size
for the whole page one time instead of constantly setting it in every paragraph. The opportunity is especially great for repeated
elements such as entries in a table or list. I was able to reduce the HTML size of one of my company's typical pages from
600 KB to about 40 KB. You can also easily detect the user's browser type from within the JSP. That gives you the
opportunity to take advantage of features unique to Netscape or Internet Explorer to further reduce the HTML content.

C o n v e rt D atab ase fro m E B C D IC to U n ico d e


If you change the coded character set ID (CCSID) of all character fields in your database to 13488, then your Java code will
not have to spend time converting all strings from EBCDIC to Unicode and vice versa. My company's team noted a
performance improvement of about 15 percent overall with this one simple change. Be aware, though, that this change will
require you to modify all other non-Java programs that access these tables. For example, since Unicode uses two bytes for
every character, your temporary variables in RPG programs need to be twice as big. You also will see a corresponding
increase in DASD use. If you are desperate for performance, 15 percent is nothing to overlook.

A v o id S e rv le t-to -S e rv le t C alls
Having one servlet call another often is expensive, just as calling one RPG program from another is time-consuming. You have
to decide where to draw the line, but try to make sure that any such calls make sense to your servlet architecture and that it
is never done in a loop. If you find that one servlet must make repeated calls to another servlet, reevaluate your design.

M isce llan e o u s
There are several tips I should mention that don't deserve a separate category of their own. For one, make sure you invoke the
Create Java Program (CRTJVAPGM) command over all your servlets, specifying optimization level 40. Also, make sure that
all .ja r files in your CLASSPATH are also compiled to optimization level 40. You will have to check this every time you load
PTFs that might possibly replace any of the .ja r files (as when you get that new PTF for the IBM Java Tool- box). You can
optimize IBM's Java Toolbox to level 40 with the following compile command:
CRTJVAPGM CLSF('/QIBM/ProdData/HTTP/Public/jt400/lib/jt400.jar') +
OPTIMIZE(40) LICOPT(NOPRERESOLVEEXTREF)

Another miscellaneous tip is to use the S trin g B u ffe r class instead of the S trin g class everywhere you can. I know this is
common sense, but you would be surprised how easy it is to forget. Also, create classes as final and static wherever
possible. A class in which all the methods and class variables are final and static can be used without creating an instance
reference, just as you can use S yste m .o u t.p rin tln (S trin g ) without first creating an object of type S yste m . The downside, of
course, is that such methods cannot be overloaded by future subclasses extending your classes.

Finally, if you are using the toolbox record I/O classes, make sure your A S 400 class object specifies the QTMHHTTP user
profile when connecting. If you don't, the toolbox will not use the native access methods IBM specifically added to help
toolbox performance; you will spend unnecessary time routing the data I/O through the TCP/IP stack.

Team-Fly
Team-Fly

F in al W o rd
The tips in this chapter have enabled my company to radically improve servlet performance on the AS/400. The programming
team still cannot approach the performance of RPG programs and green-screens, but it is able to create workable solutions.
IBM is constantly improving the speed of the components, so the situation will only improve over time. Space limitations keep
me from going into much depth on any one topic, so use these guidelines to go off and run your own benchmarks on your
own servlets. The benefits are definitely worth the trouble.

Team-Fly
Team-Fly

C h ap ter 48: Java P erfo rm an ce T u n in g


O v e rv ie w
PAUL REMTEMA

Several attributes of the Java language make performance tuning a bit more of a challenge than it is with typical procedural
languages like RPG or COBOL. However, none of these Java attributes are showstoppers. The Java language has seen
significant performance improvements on the AS/400 and other platforms since it was first introduced. It is fair to state,
however, that tuning Java for performance is more important than tuning RPG or COBOL. One reason for this is the extensive
nature of the Java runtime. Java 2 supports more than 5,000 classes. With such a large landscape, there are more chances
to hit "performance land mines."

Team-Fly
Team-Fly

T h e A rt O f P e rfo rm an ce T u n in g
Many components determine application performance. These include the language calculation performance, database,
network, and memory paging characteristics. With procedural languages such as RPG, the logic and calculations you code
in the program have less impact on performance than the other factors.

The Java language adds an additional challenge to what has historically been more of an art than a science. When you are
analyzing a Java application, you are measuring both the language that you coded and the runtime Java platform. Most of the
Java platform is implemented in Java. Compare this with RPG or COBOL, in which most language verbs make one direct call
into the operating system and one more call below the machine interface (MI) to complete the function. In Java, many classes
use other classes to complete the function.

One problem with all performance tools (including Java) is that they don't just summarize the results and make a simple
recommendation on what to change. The best any performance tool can do is tell you what is expensive relative to everything
else you have measured.

For example, in Java, there are many ways to complete a functional requirement. In the example in the "Collecting Object-
creation Events" section, string concatenation is relatively slow if you use the String object. Using the String buffer, however,
dramatically improves the results. Unfortunately, there are no performance tools that make such suggestions.

Team-Fly
Team-Fly

T h e N atu re O f Jav a
A large part of the Java runtime environment is written in Java. This layering approach has allowed significant improvements in
Java performance without affecting existing applications. Too much layering, however, can have a negative effect on
performance and can make performance tuning a challenge. This section focuses on some of the basic concepts that can
dramatically affect Java performance.

Java is more about objects than its complex parent, C++. Everything in Java, with the exception of a few primitive data types,
is a formal object. The time it takes to create a Java object depends primarily on the speed of the underlying operating
system heap management. Despite extensive research and tuning, Java applications are primarily influenced by the number
of objects created. In a server environment, each object created must eventually be collected through the garbage-collection
scheme, or you will run out of memory. Determining the number of objects created can be useful information when analyzing
Java application performance.

The Java language makes extensive use of synchronization locking. Java is a threaded language, meaning that every object
has the potential of being shared among multiple executing threads. To protect the data in the object, Java uses
synchronization locks. Synchronization locks are rather fast in Java and have been improved significantly since the early Java
Virtual Machines (JVMs). Synchronization locks don't exist, however, in a job-oriented RPG program. Often, Java objects are
locked by the JVM when the object will never be shared. Determining whether you are using Java classes that are making
unnecessary synchronization locks can help you improve application performance.

Object-oriented languages such as Java make extensive use of method calls. Since data is protected inside the boundaries of
an object, method calls are used to get and set every data item. Tracing method calls is the most common technique used in
tuning Java applications. Tracing Java method calls can produce tens of thousands of trace records in only a few seconds.
Locating performance problems often requires a sophisticated tool to reduce and summarize these trace records.

Extensive call activity combined with a large class library and hidden object- creation events are what make Java performance
tuning a unique challenge. The following section introduces tools that can help you face this unique challenge.

Team-Fly
Team-Fly

P e rfo rm an ce T o o ls
Performance Explorer (PEX) is an AS/400 operating system component. It has evolved over several releases, starting with the
RISC systems in V3R6. Today, PEX supports more than 170 different trace events. An industry-distinguishing feature of PEX
is its ability to trace many different types of system performance events in one measurement. For example, a PEX
measurement can include Java and RPG calls, low-level disk activity, and Java object-creation events.

PEX can be used to trace Java performance events. Analysis of the trace records can be simplified by limiting the collection
time and scope. I will demonstrate how to simplify the analysis by starting and stopping the collection at debug breakpoints.
Analysis of object creation and garbage collection can be accomplished by querying the trace records.

Analysis of method call traces requires tools that accumulate statistics from many trace records. Performance Trace Data
Visualizer (PTDV) is a tool that can be used to simplify the analysis of AS/400 Java performance events. PTDV is available
through the IBM alphaWorks Web site at www.alphawork s.ibm.com/ tech/ptdv. Java performance tools on platforms such as
Microsoft Windows NT and UNIX are driven by a profiling option built into the JVM. The Java platform defines standard trace
records produced when the profiling option is selected. The AS/400 JVM does not directly support this profiling option
because PEX trace records contain more information. To use a standard Java performance tool, you must convert the PEX
trace records to the standard Java format. The AS/400 JVM provides an application called the Java Performance Data
Converter (JPDC) that will convert PEX trace records to the Java industry standard format.

IBM provides a cross-platform Java performance tool called Jinsight that can process the output from the JPDC. The tool is
also available through the IBM alphaWorks Web site at www.alphawork s.ibm.com/tech.

Team-Fly
Team-Fly

P e rfo rm an ce E x p lo re r C o n ce p ts
There are several concepts associated with running Performance Explorer. These are illustrated in Figure 48.1. The Add
Performance Explorer Definition (ADDPEXDFN) command is used to define a measurement definition. The definition specifies
the performance events and determines whether the measurement is limited to specific jobs on the system.

F ig u re 48.1: This is the AS/400 Performance Explorer collection process.

The Start Performance Explorer (STRPEX) command starts a PEX session. The session monitors the JVM, recording trace
events in low-level memory below the MI. You can start the trace either before your Java application is started or during
certain critical steps in your application.

The End Performance Explorer (ENDPEX) command stops the trace activity and saves the trace data in a set of database
files. The files can be placed in any library you specify. Each file name starts with the letters QAYPE.

After performance data is collected, tools are required to analyze the results. The diagram in Figure 48.1 shows several
alternative tools that can be used.

Team-Fly
Team-Fly

Jav a P e rfo rm an ce E v e n ts
The ADDPEXDFN command supports 18 Java performance events. You can see all of the events by prompting on the
ADDPEXDFN command. These events are always monitored by the JVM. You can trace them on any Java application
whether it is written by you or purchased.

Java method call tracing requires a special hook that is compiled into the Java code through the Create Java Program
(CRTJVAPGM) command. Options on the ADDPEXDFN command determine whether you want to trace method calls.
Combining method call tracing with base Java performance events will produce a wealth of information.

Not all of the 18 performance events are performance critical. In writing this chapter, I discovered that some of the events are
not supported by IBM. Refer to Tables 48.1 through 48.3 for the list of events that you can use. The events that are most
useful are the object-creation (*OBJCRT) event and the garbage- collection (*GBGCOLSWEEP) event.

Method calls can be traced by specifying *JVAENTRY and *JVAEXIT. To activate these events, the Java program must be
created by specifying the Enable Performance Collection keyword (ENBPRFCOL(*ENTRYEXIT))onthe CRTJVAPGM
command.

The fields listed in Table 48.1 are in the trace index file (QAYPETIDX). There is one record for each trace event.

T a b le 48.1: T ra ce In d e x F ile (Q A Y P E T ID X ) R e co rd L a yo u t

F ie ld N a m e D e scrip tio n
QRECN Unique record number for every trace record. Use this to join to all other trace information
located in related trace files. For example: QAYPEJVA.QRECN = QAYPETIDX.QRECN
QTITY Event type. Always = 13 for Java. Refer to file QAYPEEVENT for a definition of each type.
QTISTY Event subtype. Based on the event you coded on ADDPEXDFN. For example: *OBJCRT is
subtype = 2. Refer to file QAYPEEVENT for a definition of each subtype.
QTIHO1 Performance Measurement Counter 1 (PMC1). A count by thread of CPU run cycles. This
counter will wrap quickly because it is only a binary 31 field. Unit is processor cycle speed.
Subtracting this field from any prior trace record on the same thread gives the CPU used
between the two trace events.
QTITSP Event time stamp.
QTIFTC Task count. This is a join field used to join this trace record to its owning task in the task
information file. For example: QAYPETASKI.QTSTCT = QAYPETIDX.QTIFTC
Source: Rochester Technology Center, Rochester, Minnesota.

Table 48.2 lists fields in the Java event file (QAYPEJVA). There is one record for each trace event. The fields listed are
generated by the object-creation (*OBJCRT) event and garbage-collection (*GBGCOLSWEEP) event.

T a b le 48.2: F ie ld s in th e Ja va E ve n t F ile (Q A Y P E JV A )

F ie ld N a m e D e scrip tio n
QRECN Unique record number for every trace record. Use this to join to all other trace information
located in related trace files. For example: QAYPEJVA.QRECN = QAYPETIDX.QRECN
QJVOBN The size of an object. Field is confusing because its documented name is object number.
Produced by *OBJCRT event.
QJVGST Garbage-collection start time stamp.
QJVOAC Garbage-collection object alive count. This is the number of objects not collected. It is a
measure of the number of in-use objects. The bigger the number, the bigger the application
and more memory required.
QJVODC Garbage-collection number of objects collected. A lot of trace records with a high count in this
field means you are creating and collecting many objects.
QJVBAL Java bytes allocated since last garbage collection. Measures the rate of new memory being
allocated and collected. In a steady state application, this value should remain relatively
constant. Value is in K bytes.
QJVBAT Java total bytes allocated. Current size of the Java heap. In a steady state application, this
value should remain relatively constant. Value is in K bytes.
QJVOCD Object create Delete indicator. Create is 1. Delete is 2.
Source: Rochester Technology Center, Rochester, Minnesota.

Table 48.3 lists fields in the task information file (QAYPETASKI). There is one record for each job, thread, and machine task.

T a b le 48.3: F ie ld s in th e T a sk In fo rm a tio n F ile (Q A Y P E T A S K I)

F ie ld N a m e D e scrip tio n
QTSTCT Task count. This is a join field used to join this trace record to other trace records. For
example: QAYPETASKI.QTSTCT = QAYPETIDX.QTIFTC
QTSJNM Job name for this task.
QTSJUS Job user name for this task.
QTSJNB Job number for this task.
QTSTHI Hex representation of the thread ID. This is the thread ID printed by PRTPEXRPT and shown
on WRKACTJOB.
QTSAP1 Accumulated run cycles. This is a 64-bit counter that holds the 31-bit PMC1 run cycles and
accounts for overflow. This is a running count of total CPU for this task (thread). Units are in
machine cycle speed.
Source: Rochester Technology Center, Rochester, Minnesota.

Team-Fly
Team-Fly

C o lle ctin g O b je ct
ct--C re atio n E v e n ts
To show how to use PEX on a Java program, I will run PEX on a simple Java program that concatenates two strings. String
objects implicitly create temporary objects behind the scenes; it's not obvious from looking at the Java code that this is
happening. This example demonstrates how PEX can be used to uncover what is happening in the JDK runtime. It proves
what is already common knowledge to Java performance gurus: Strings are expensive because they create lots of temporary
objects. Figure 48.2 shows a sample Java program that will be used to demonstrate PEX.

F ig u re 48.2: This is a sample Java application.

Team-Fly
Team-Fly

S am p le C o lle ctio n
To collect performance data with PEX, use the following steps:
1. Create a PEX definition to trace the object-creation events, as shown in Figure 48.3.

F ig u re 48.3: Create a Performance Explorer definition.

It's a good idea to specify the job name and user if you can determine the name before the test is run. In this case,
QJVACMDSRV is the name of the job created by the AS/400 JAVA or RUNJVA command. This name will be different
if you are using Java from Qshell or from a servlet within WebSphere. If you are testing on a system that you control,
you can specify *ALL for the JOB parameter and not worry about collecting too much data. On a busy development
system, you should narrow the scope of the collection by specifying a job name.

It's good practice to specify MAXSTG to some reasonable limit. This controls the amount of storage used for the trace
records. When the trace buffer is full, the trace automatically stops. This can prevent runaway traces from consuming
your system. A good value to specify is between 100 KB and 1000 KB.

The JVAEVT keyword is used to specify the Java performance events. In this case, *OBJCRT is the object-creation
event.

2. Start PEX. If you start it before your application is started, you will trace many Java events that are part of the startup
processing for the JVM. To avoid this, you can set a breakpoint in the Java program just before and after the section of
the program to be monitored. In the sample program (Figure 48.2), breakpoints were set just before and after the FOR
loop. You can start the Java application and enter debug mode by specifying OPTION(*DEBUG), as in Figure 48.4.
Once you reach the breakpoint, start PEX, as in the following:
STRPEX
SSNID(TESTONE)
DFN(CNTOBJCRT)

F ig u re 48.4: Run the WorldWideWait Java program.

3. Run the Java application. Simply use the resume key PF12 from the debug screen. When the section of code you are
measuring ends, you can end the collection by entering the command in Figure 48.5.

F ig u re 48.5: This is the command to end a Performance Explorer session.

The ENDPEX command stops the collection process. Trace records are moved from the trace buffer below the MI into
a set of files in the library specified by the DTALIB keyword. It may take a long time to process this command. The
DTAMBR holds the performance data. To simplify querying the files, you might want to store the performance data in
the first and only member of each file. ENDPEX will let you save data in any member of the trace files, but then you
have to enter overrides or copy the data before you can use SQL to analyze the results. Specifying RPLDTA(*YES)
saves time if you are repeating the test because it reuses the existing file and data member.

Team-Fly
Team-Fly

A n aly zin g A S /400 Jav a P e rfo rm an ce R e su lts


Analyzing the results means looking for those bottlenecks that you suspect might be occurring but are hard to locate. All of
the analysis starts with the information in the PEX database, in which there are 52 different files. The files are separated into
categories based on the type of performance collection. All of the files begin with QAYPE and are created the first time you
use the ENDPEX command on a new library.

Java performance events are placed in categories such as virtual machine events. Virtual machine events such as object
creation and garbage collection can usually be analyzed by querying the trace records. A special tool is not required, but you
need to understand the files and fields in the PEX database.

It is important to remember that analysis is easier if you limit the PEX definition to events and jobs that are most meaningful.
In some cases, a tool such as PTDV will give you sample definitions that work best for that tool. Remember that it is not
possible to analyze something you did not collect, and it is tedious and confusing to analyze too much data. Trying to find the
right combination of collection definition and analysis technique is somewhat of a trial-and-error process; be prepared to
repeat your experiment.

As an example of querying PEX data files, Figure 48.6 shows a query that counts the number of objects created and
computes the total amount of memory allocated for those objects in the sample program. The program shown in Figure 48.2
was called with a parameter of 100, using the definition shown in Figure 48.3.

F ig u re 48.6: This query counts the number of objects created by the WorldWideWait program.

The query shows that there were 300 objects created in the loop. Field QJVOBN in file QAYPEJVA contains the size of each
object. This query sums the values in this field for all of the created objects. This result means that the loop statement
m e ssa g e = first + la st; // cre a te s a n e w S trin g ! creates three objects and allocates about 50 bytes of memory for each
object.

To make use of the trace records, your tool uses the trace record fields in the QAYPE files. A complete layout of all trace
records is not possible, because some of the fields can be processed only by internal IBM tools. However, some useful fields
may be queried, as I have shown. Table 48.1, provided with assistance from IBM, documents the most useful fields.

Team-Fly
Team-Fly

Jav a P e rfo rm an ce T o o ls S u m m ary


For Java to grow beyond the experimental stages, serious performance tuning efforts will be necessary. The AS/400
Performance Explorer can be used to collect a myriad of performance data. Much of the challenge, however, is in reducing the
performance data to meaningful information.

Simple queries can be used to count events. The performance data files contain name-mapping information used to correlate
trace events with method and class file names. A more useful analysis would include grouping the events by method call and
attaching method and class file names to the analysis reports. One tool that does a good job of reducing the data and
matching performance events to method and class names is PTDV, which presents Java performance data in a GUI. It is not
a supported IBM product, but you can download PTDV from the IBM alphaWorks Web site.

PTDV presents data primarily in tabular formats, and cumulative statistics are provided. Java performance analysis requires
sophisticated tools. Knowledge of typical problem areas such as object creation and synchronization combined with tracing
tools will be required to improve application performance. The usability of the tools will determine whether the fine art of tuning
can be used by a wide range of application programmers. Current industry and AS/400 Java performance tools are not ready
for everyone. Ad hoc techniques and multiple tools are often required to resolve the problem. As tools improve, however, Java
application performance will improve as well.

Team-Fly
Team-Fly

C h ap ter 49: Java P erfo rm an ce T ip s


O v e rv ie w
PAUL REMTEMA

Chapter 48, "Java Performance Tuning," introduces the AS/400 Performance Explorer (PEX) tool. That chapter shows how to
collect Java performance events. In particular, object-creation and garbage-collection events are measured using standard
AS/400 PEX commands. This chapter adds specific tips that you can use to improve server Java performance. There are a
few basic system-tuning tips and a few basic language tips that everyone should know. Beyond these basics, you'll see how
to use PEX and a nifty tool called Performance Trace Data Visualizer. To add some excitement, I measure a simple Java
code fragment that creates a new order number (see Chapter 62, "The Spartan Order System: An Exercise in Java
Application Design" in Section XI). Then, I show how to improve the performance of that sample code using the tips in this
chapter.

Since Java was introduced, performance has improved significantly on the AS/400 as well as other platforms. In the early
days of Java, there were many performance horror stories. Valiant Java heroes spent long hours hand-tuning applications.
Under the covers, Java Virtual Machine (JVM) implementers used optimization techniques such as Just-In-Time (JIT)
compilers and the reimplementation of Java Development Kit (JDK) classes. The challenge you have today is that some Java
constructs seem elegant but are too slow. Unfortunately, you can't always see that. The approach I like to use is to construct
a controlled measurement around a set of primitive Java operations. Of course, you have to have some idea of where to look in
the first place. The tips in this chapter will help you determine where to begin. Once you think you have found a potential
problem, you need to have some idea of an alternate approach. There is no tool or process that can give you the best
alternative, but, if you use the techniques described in this chapter, you will soon develop a sense of how to improve your Java
code.

This chapter focuses on server Java performance. The tips apply to any release of Java on the AS/400, including JDK 1.1.4,
JDK 1.1.6, and JDK 1.1.7. Some of the tips may have less effect on the V4R4 JDK 1.2 environment because a JIT compiler
has been added to JDK 1.2. The measurement techniques shown in this chapter will work for any release, including JDK 1.2.

Before I start, it's important to configure your system for Java. Here are four of the most important system-tuning tips:

 Choose an AS/400 model that is designed for Java. Older AS/400 models are designed for RPG and COBOL
applications. Java applications require different memory, cache, and processor speeds than traditional RPG and COBOL
applications do. Newer models have larger caches and faster clock speeds. The best models for Java can be found in
AS/400 Performance Capabilities Reference—Version 4, Release 4, dated August 1999.

 Monitor storage pool page faults. Java applications require more memory than traditional applications. One way to
measure whether you are having memory pool problems is to look at the nondatabase page-fault rate in the storage pool
that is running your Java application. If you are using the JAVA command from the command line, this will usually be the
*BASE pool. Nondatabase page-fault rates should be less than 20. If the fault rate gets above 30, add more memory to
the storage pool. You can check page-fault rates with the Work with System Status (WRKSYSSTS) command.

 Use Create Java Program (CRTJVAPGM) whenever possible. The AS/400 CRTJVAPGM command transforms Java
class files into direct-execution RISC instructions. In most cases, you should specify optimization level 40. If you don't
use CRTJVAPGM, the AS/400 will automatically transform class files during runtime. The default optimization for this
automatic runtime transformation is optimization level 10. Transformation of Java archives (.zip
.zip and .ja r files) is
particularly important because optimizations can be made between class files contained in the .z ip or .ja r file. It is
especially important to run CRTJVAPGM over the jt4 0 0 .ja r file because the Java Toolbox for the AS/400 is contained in
this file and is not transformed during the install process.

 Monitor activity levels. The storage pool activity level determines the number of concurrent tasks that are allowed to run in
one pool. Each Java thread takes one activity level. If you are using a storage pool that was configured with a low activity
level, Java threads may have to wait. Often, this condition is difficult to detect and can significantly slow a threaded
application.

The system-tuning tips are the most important. Application-level tuning won't help you much if you haven't set up the system
properly.

The following tips are the most important programming tips for Java. Of course, there are many more tips, but I have found
these three to be the most significant (refer to the AS/400 Performance Capabilities Reference—Version 4, Release 4, dated
August 1999 for additional tips):

 Avoid implicit object creation. Certain Java classes create several small temporary objects to complete their work. The
worst cases I know about are the S trin g and B ig D e cim a l classes. As with any performance tip, S trin g and
B ig D e cim a l objects are a problem only if you create lots of them. One way to work around the S trin g problem is to use
S trin g B u ffe rr. Working around B ig D e cim a l is more difficult. Numerical primitives (such as ints or floats) can be used in
some cases. The reason why avoiding object creation is such an important tip is that object creation incurs a double
penalty: It takes time to create temporary objects, and then it takes time to "garbage-collect" them. In a steady-state
server application, all of the objects that are created must eventually be collected.

 Avoid unnecessary synchronization. Java synchronization is a locking technique used by the JVM to protect access to
objects in a multithreaded environment. A primary design goal should be to lock only objects (both Java and AS/400) that
must be shared and to lock them for only a short duration. Synchronization is usually specified with the syn ch ro n ize d
modifier on a Java method declaration. Many methods in the standard JDK library use the syn ch ro n ize d modifier. (A
scan of JDK 1.1.6 showed 790 cases.) The cases you should be most concerned about are frequent calls to short-
running functions. For example, the S trin g B u ffe r and V e cto r classes use synchronized methods. In extreme cases, it
might be necessary to write your own version of a Java class that avoids the synchronized call. Sun's Collections
package contains several alternatives to the V e cto r class, all of which perform well because they avoid using
synchronized calls. To determine whether developing your own unsynchronized classes is worth the effort, use the
Performance Trace Data Visualizer.

 Exploit method inlining. Method inlining is a classic optimization technique. The term refers to a compiler's ability to
eliminate call overhead by copying the entire called method (or procedure) into the calling location. The nice thing about
inlining is that it happens under the covers. You can keep simple abstracted object-oriented design that makes good use
of g e t and se t methods while relying on the compiler and translator to do the right thing. To make this work, however, you
need to be aware of a few structural rules. First, final static methods have a greater potential for being inlined, because
the system knows that they cannot be overridden. Second, the ja va c compiler provides an -O option that is worth trying.
(Note that this option can be set in all the major Java integrated development environments.) In some cases, the compiler
can inline methods before translation starts. Finally, packaging applications in a .ja r file will help. The translation of a .ja r
file can inline methods between classes because it has all of the classes available. In other words, always deploy Java
applications in .ja r files because your Java classes execute faster out of a .ja r than from directories.

Now that you have some of the basic tips, let me show you how to put this knowledge to work.

Team-Fly
Team-Fly

F ish in g F o r P e rfo rm an ce
There is an age-old adage that says, Give a man a fish, and you feed him for a day; teach him how to fish, and you feed him
for life. The tips I just provided can be viewed as big fish. To learn how to optimize Java programs better, you need to
understand how to measure the relative performance of primitive operations. There are just too many alternatives to learn all of
the tips. For example, is tool- box record I/O performance better than JDBC? What does it cost to invoke a servlet? What's
the performance difference between data queues and sockets? The list goes on and on.

The best way to teach others how to fish is by example. Figure 49.1 shows code that uses a data area to generate a unique
order number. It uses toolbox classes, reads the data area, converts the order number from B ig D e cim a l to integer, adds one,
converts the integer back to B ig D e cim a l, and saves the new result. In theory, other applications written in either Java or RPG
could access the same data area. The g e tN e x tO rd e rN o () method is used here. Let me see if I can improve the performance
of this code.

 
F ig u re 49.1: What looks like a well-crafted Java method will often perform poorly until tuned .

To measure this code, create a Performance Explorer definition suitable for Performance Trace Data Visualizer (PTDV). PTDV
(available from IBM's alphaWorks Web page at www.alphawork s.ibm.com) analyzes Java method call trace records. It collects
statistics such as inline instruction counts for all of the methods that have been "hooked" for performance. PTDV also
correlates Java object-creation (*OBJCRT) events and Java thread-state change (*THDSTTCHG) events with the methods that
are being measured. The object-creation events are important because they directly correlate to the tip to avoid implicit object
creation. The thread-state change events occur when a synchronized lock is waiting for an object; these correlate to the tip to
avoid unnecessary synchronization.

Figure 49.2 shows the PEX definition to use for PTDV. Note that it's very important to use the exact options shown here.
PTDV can handle only certain trace records, and there is no point in collecting data that can't be analyzed. Next, wrap the
code to be measured in a method called n e x tO rd e r(). Then, use CRTJVAPGM to add *ENTRY and *EXIT performance
"hooks" to the n e x tO rd e r() method. Finally, start PEX (STRPEX) and run the m a in method with a loop iteration of 100.

 
F ig u re 49.2: Object-creation and garbage-collection events were measured using the AS/400 Performance
Explorer

Figure 49.3 shows one output panel from PTDV. PTDV provides many different Java performance data views. One of the most
useful views is the Avg Inline Instruction count. Each RISC instruction represents a small unit of work. Primitive path-length
analysis amounts to counting instructions between points A and B in a code fragment. Instruction counting is useful because
it is invariant between AS/400 models. In this example, the number of average inline instructions is the cost of one call to the
n e x tO rd e r() method. Inline means all of the instructions I coded plus all of the system functions used by the JVM. Here's
one word of caution: The instructions are counted by thread. In the two examples I am comparing, everything is occurring on
the same thread. This may not be true in a more complex example.

F ig u re 49.3: Performance Trace Data Visualizer can be used to tune your Java applications.
Primitive analysis involves looking for the "relative" cost of two different approaches as measured by inline instructions. In this
example, PTDV indicates that each call to n e x tO rd e r() took about 535,349 RISC instructions (see row five). The object-
creation count is the total for 100 iterations, so the object-creation count for one call to n e x tO rd e r() is about 313 (see row
five). (Note that it is normal for instruction and object counts to vary slightly between calls.)

Team-Fly
Team-Fly

T u n in g Jav a C o d e
Here's how to improve the code. Because an order number is a simple integer, try using integers instead of B ig D e cim a l. Of
course, you should suspect that B ig D e cim a l might be a problem in the first place. The tips I've given should give you some
idea of where to start looking for problems. Closing the timing window is also important. The problem with the example in
Figure 49.1 is that the re a d and w rite of the data area may not be synchronized. Multiple concurrent jobs could generate
duplicate order numbers. (The V4R4 Toolbox documentation is not clear on whether the re a d () operation locks the data area.)
One way to correct this is to lock a database record for update. The record lock would lock the data between the re a d and
rite. It would also work from any RPG program so that both a new Java order-entry application and an old RPG order-entry
w rite
application could be running on the same system.

Figure 49.4 shows the code. It's not pretty; I'll admit that the data area approach is more readable. Java code is very elegant,
and you'll have to make trade-offs between readability and performance. In this example, I use the toolbox record I/O
functions. A physical database file was created with one record and one integer field. To improve the toolbox I/O, try using the
g e tC o n te n ts() method to move the entire buffer into a b yte [ ]a rra yy. Then, use the toolbox converter class to convert to and
from an integer. The n e x tO rd e r() method is shown here; the complete code can be found on the companion CD.

 
 

 
F ig u re 49.4: Java methods that are tuned may not be as readable as their cleanly coded counterparts, but they often
perform eight to 10 times faster .

Figure 49.5 shows the results of 100 calls to n e x tO rd e r(). The average inline instruction count is now 60,748, and the object-
creation count is 33. The results are dramatic: more than eight times better performance, more than nine times fewer objects
created, and better synchronization. Look back at the PTDV output from the data area test (Figure 49.3). You will notice that
the record I/O test (Figure 49.5) eliminated the garbage-collection thread and the creation of two worker threads. You'll have to
decide if this is worth the admittedly less readable code.

F ig u re 49.5: Using basic code optimization techniques, the example method had an eightfold improvement in
performance.

Java application performance is determined by many factors. One of the challenges you face is that some of the expensive
operations are somewhat hidden from view. In spite of this, it is now possible to build competitive, robust, scalable Java
applications. AS/400 Java performance analysis tools need improvement. PTDV does a good job, but it needs to include more
non-Java events. IBM should consider making PTDV a supported product. Building Performance Explorer collection definitions
involves too much trial and error. I also found some documented Java performance events that aren't supported. Finally, there
needs to be more documentation on how to put the measurements into a broader system perspective. You may be tuning
your Java only to find that the problem is the underlying database, communications, or network infrastructure.

Team-Fly
Team-Fly

S ectio n IX : E n terp rise Javab ean s


C h ap te r L ist
Chapter 50: E-Business By Design With Ejb

Chapter 51: Enterprise Javabeans: Show Me The Code!

Chapter 52: EJB: What's Going On Here

Chapter 53: Open-Source Enterprise Javabeans

Chapter 54: Distributed Java Computing With Rmi

P art O v e rv ie w
"Enterprise JavaBean [EJB] is only for large shops." "EJB is a complex technology that is hard to develop with." "Web
application servers that support EJB are expensive." All of these statements are common misconceptions about EJB. In my
opinion, I see two alternatives when using Java for AS/400 applications: one is to use RPG or COBOL for your business logic,
and the other is to use Enterprise JavaBeans. In either scenario, you'd use the technologies covered in Section VII, "Server-
side Java" (JavaServer Pages [JSPs] and servlets), to handle the Web interface.

The decision is whether or not you want to code your business logic in a legacy language or go all-Java. If you take the all-
Java route, the time and effort required to develop a robust application can be extremely prohibitive. I say "prohibitive" because
it takes a tremendous effort to code database persistence, transaction control, and scalability—unless, that is, you let the
architecture of EJB do it for you.

P e rsiste n ce
With RPG and COBOL, database files drive the processing. But the base Java language doesn't even know what a file is
without bringing in additional Java packages to support I/O. Furthermore, even after you access a record, the data from that
record is in EBCDIC, not the Unicode data types of Java. That means if you code your business logic in Java, your
programmers will have to tediously add additional code "fluff and stuff" data to and from the database. In other words, without
the benefit of EJB, they will have to code an architecture for data persistence.

T ran sactio n C o n tro l


One application transaction often spans the add, update, and delete of multiple records across several database files.
Programmers have to take great care to ensure that if something goes wrong with any one of the records, the updates to the
other database files of that same transaction are not committed. AS/400 RPG coders have handled this quite well with the file
locks of record-level access in their do-all monolithic programs. But in component-based development, you can potentially
have dozens of modules (or, in Java terms, classes and methods) that collaborate to perform one application transaction.
Without using EJB, your programmers will have to perform complex programming to ensure that transaction boundaries are
not crossed. But, when using EJB, your programmer will not have to do any coding to maintain database integrity. I don't have
enough space to explain why—just let me say that the transactional control features of EJB are easy to use yet very
sophisticated.

W o rk M an ag e m e n t
The slowest part of Java (and also the reason why Java apps take up so much main memory) is the creation of all those
objects. Senior Java developers know how to code their Java classes so that, once created, they can be used over and over
again rather than having to create new objects. But how many "senior" Java developers are there? EJB's standard architecture
allows servers (such as WebSphere Advanced Edition) to pool objects for optimal use. Coders think they are creating a new
object over and over again, but, behind the scenes, the EJB server continually reuses the same half-a-dozen or so enterprise
Beans. This "work management for Java," as I like to call it, is what allows EJB applications to scale well.

P ro to ty p e s, A rch ite ctu ral S tan d ard s, A n d R o le s


There are four other advantages of EJB—beyond EJB handling persistence, transaction control, and scalability—that I'd like to
cover. First, EJB applications are easy to prototype. The second advantage is that EJB's standard architecture promotes, and
all but forces, proper component-based development. You might not see that as an advantage unless you've used component-
based development. Each component of an EJB application—JSP user interface, Java servlet application controller, workflow
session Bean, and database entity Bean—is, by itself, simple. By looking briefly at an EJB component's interface, a
programmer is quickly able to understand not only how easy it is to use that component but also how easy it is to maintain.

The third advantage of EJB is separation of coding responsibilities. In the EJB applications that I've worked with, I see three
roles for the application developer: HTML developer (uses HTML and JSPs to develop and enhance the user interface), script
developer (uses Java in JSPs and servlets to interact with the business logic), and business logic developer (codes the EJB
components, typically using a tool such as VisualAge for Java Enterprise Edition) to handle the intricacies of the business
application. The fourth advantage of EJB is that you will find it easier to maintain your applications because of EJB's standard
architecture. One of the greatest advantages of the AS/400 is that you can hire anyone with AS/400 experience. The same
goes with EJB: Anyone with EJB experience will be able to maintain your EJB application.

Are you still confused about EJB? "E-business by Design with EJB" provides a detailed overview of EJB architecture. In
"Enterprise JavaBeans: Show Me the Code!" I take a different approach. Instead of covering the complexity of EJB, I cover
how easy it is for Java programmers to use entity Beans that are already available.

A good place to get started with EJB is by installing the examples provided with IBM's WebSphere Advanced Edition. "EJB:
What's Going on Here" explains how IBM's example code works. However, while WebSphere Standard Edition is bundled with
OS/400, the Enterprise Edition (which is required for EJB support) costs $7,500 per processor. It sounds like the use of EJB
technology is expensive. I say, "No, it's not"—not when you consider the cost of paying several Java programmers to code in
persistence, transaction control, and scalability. Furthermore, you don't have to pay for an EJB server. Several free EJB
servers are available. For instance, jBoss (www.ejboss.org) is a free all-Java EJB server. Recently, jBoss has been
downloaded at a rate of 1,000 per day. Three more free EJB servers are JOnAS (Java Open Application Server) at
www.openmaster.com/ejb/index.html ; Enhydra Enterprise Alpha 2 at www.enhydra.org/; and Dasein EJS Application Server at
www.imaginary.com/Java/Dasein/.

Jeff Markham introduces jBoss and JOnAS in "Open-Source Enterprise JavaBeans." If you are going to go "whole hog" with
Java, use Enterprise JavaBeans—you can't afford not to. You can't afford to code persistence, transaction control, and
scalability. You can't afford to "invent" your own strategy for coding real-world business applications with Java. Let the
architecture of EJB take care of all that for you, and reap the rewards of EJB's standardized component-based development
architecture and sophisticated runtime environment. If you are going to go "whole hog" with Java, use EJB.

Underneath the wrappers, EJB uses Remote Method Invocation (RMI) for the object distribution protocol. In truth, you can
develop distributed applications without the benefit of an EJB server. "Distributed Java Computing with RMI" provides a tutorial
on the use of RMI.

Programming with distributed objects can become a daunting task. Handling database transactions with JDBC often turns
into a complex and unmanageable process. Adding all the necessary code for relational database updates becomes repetitive
and time-consuming. And, finally, refactoring your Java application for performance all but requires you to be a computer
scientist rather than a business programmer. Enterprise JavaBeans relieve the use of these complexities and let you do your
job—code applications that allow your company to be more competitive in the new Internet economy. This section provides
you with an overview on the proper architectures for your new, all-Java applications.

Team-Fly
Team-Fly

C h ap ter 50: E -B u sin ess B y D esig n W ith E JB


O v e rv ie w
DON DENONCOURT

Enterprise JavaBean (EJB) is a fancy name, so let me break it down for you. The Enterprise part tells you that EJB is for
business applications, and a JavaBean is simply a software component. Moreover, because Java is the language of the
Internet, EJBs must be software components for e-business. JavaBeans (without the Enterprise) have been around for a
couple of years but were only GUI components; you still had to develop business back-ends for JavaBean-based GUI
applications. To support online transaction processing, you need business components more than you need fancy GUI
components, and you need e-commerce applications developed with business components that scale well and are easy to
use and portable to other platforms.

Three other business component strategies have also been available for some time: CORBA, Distributed Common Object
Model (DCOM), and Remote Method Invocation (RMI). However, CORBA is too complex, DCOM is too Microsoft-centric, and
RMI has poor scalability and no inherent transaction processing. Optionally, without component architectures, you can
develop your business back-ends by using CGI and RPG, but CGI is too kludgy, and CGI applications developed with RPG
are too platform-centric.

Such problems with those older business component architectures are the reasons many companies now build e-commerce
applications using EJB. EJB was designed to provide a standard architecture for object-oriented (OO) business applications
that are easy to develop and deploy. EJB was intended to let computer scientists do their systems programming and let
business programmers develop their business applications. In this chapter, I show you the basics of EJB architecture and
explain how that architecture makes developing robust e-commerce applications easy.

Team-Fly
Team-Fly

A p is, B e an s, an d C o n tain e rs
EJB has four fundamental elements: the remote interface, home interface, enterprise Bean itself, and container (see Figure
50.1). The first element, the remote interface, is a list of functions that a client may invoke to manipulate the state of a
business entity. Think of the remote interface as the client application's view of a host-based business entity. The remote
interface works seamlessly through a proxy service hosted by a Web application server such as BEA Systems' WebLogic,
IBM's WebSphere, or Bluestone Software's Sapphire/Web.

F ig u re 50.1: EJB architecture revolves around the remote interface, home interface, enterprise Bean, and
container.

The second element of EJB is the home interface, which is a sort of "entity factory." The client uses the home interface to
create new entities or retrieve an existing entity or set of entities. For most EJB servers, the state of an entity Bean is
maintained in a relational database, such as DB2 for OS/400. When a client application uses the home interface's cre a te
method, a record representing that entity is inserted in DB2/400. When a client application uses one of the home interface's
entity-specific fin d methods, enterprise Beans materialize from existing DB2/400 records based on various selection criteria.
(For more information on remote and home interfaces, see Chapter 51, "Enterprise JavaBeans: Show Me the Code!")

The third element of EJB is the enterprise Bean itself. The enterprise Bean implements the host-based Java code for all the
business methods of the remote interface and for the cre a te and fin d methods of the home interface. The client application
accesses these methods of the enterprise Bean through the remote and home interfaces via proxy services of an EJB-
enabled Web application server. The enterprise Bean also has many important methods that are inaccessible to the client,
such as its life-cycle methods: e jb L o a dd, e jb S to re te, and e jb R e m o ve
re, e jb C re a te ve. These four methods, respectively, are
invoked by the container at the appropriate time to read, update, write, and delete records from DB2/400.

That brings me to the container, the final element of EJB. The container provides a host-based environment for the enterprise
Bean. The client application programmer doesn't need to know anything about the container; its use is transparent to the
client. Like a Java applet, an enterprise Bean doesn't define the complete application; it defines only custom parts of that
application. However, whereas an applet is hosted by a browser, an enterprise Bean is hosted by a Web application server
with the help of the container. The container provides a safe environment for EJB and also supports standard services for it.

Those standard services provided by the container show how the EJB architecture really shines. The container manages
system and application resources such as memory, connection pools, and thread pools. The costliest processes on the
AS/400 are job starts and file opens. EJB containers manage resource pools of Java threads and SQL connections. Java
threads are analogous to AS/400 jobs, and SQL connections are hooks into DB2/400. Containers also provide other important
features such as caching, security, data persistence, and transaction management. (Data persistence is discussed in "Four
Beans" and transaction management is discussed in "Commitment Control," but you should note that it is the combination of
all the features of EJB that make EJB architecture perfect for Web applications.)

Team-Fly
Team-Fly

F o u r B e an s
There are four types of enterprise Beans. The stateless and stateful enterprise Beans are collectively known as session
Beans, and the Bean-managed persistence and container-managed persistence enterprise Beans are collectively known as
entity Beans. Stateless session Beans are host-based components that do not maintain any user or entity states between
client method invocations. In contrast, stateful session Beans maintain client states and have one-to-one relationships with
clients. Stateful session Beans are essentially application jobs.

Whereas stateful session Beans represent user jobs, entity Beans represent business entities. For EJB applications hosted
by an AS/400, an entity Bean has a one-to-one relationship with a DB2/400 record. Think of DB2/400 as your preferred data
persistence engine that manages your application's data. In reality, not only can entity Beans use any relational database for
persistent storage, but they can also use OO databases and flat-file systems. The entity Bean provides an OO Java class
wrapper for your business data.

As I mentioned earlier, the two types of entity Beans are Bean-managed persistence and container-managed persistence.
With Bean-managed persistence, the entity Bean programmer explicitly codes the four life-cycle methods of an enterprise
Bean (ee jb L o a dd, e jb S to re te, and e jb R e m o ve
re, e jb C re a te ve). Legacy programmers have been writing that type of code every day
for the last several years, so the process doesn't seem like a big deal, but it is. That code takes a lot of effort, but container-
managed persistence relieves the programmer of all the read/write responsibility. To use container-managed persistence,
simply specify the entity Bean name, file name, and mapping of the Java class attributes to relational data in a special EJB
file called a deployment descriptor (see Figure 50.2). You must still code into the entity Bean business methods such as
d e p o sit and w ith d ra w methods of an account entity Bean, but you don't need to code the four life-cycle methods or the fin d
methods.

F ig u re 50.2: The EJB 1.1 specification uses XML for deployment descriptors, but EJB 1.0 implementations use product-
specific syntax such as this BEA WebLogic deployment descriptor.

Team-Fly
Team-Fly

R e co rd L o ckin g
There is a problem with EJB. It's not a new problem, just a new twist to an old one. An entity Bean represents a business
entity. Now, suppose you deploy an EJB application, and clients Bill, Bob, and Jane are all using entity Bean InvoiceBean. All
three happen to be working with invoice number 6753 and access the same enterprise Bean in main memory. If Bill's client
application invokes a method that changes an attribute of InvoiceBean 6753, the other client applications access that change
even if Bill is not done modifying the invoice or if Jane modifies it before Bill posts his final change. This problem is nothing
new to AS/400 programmers. What is new is that, to solve this problem, you must use the record-locking facilities of SQL
instead of those of RPG and COBOL. Had Bill used a typical RPG, the program would have locked the record because he got
to the record first and read it for update. However, EJB implementations do not use dynamic record access; they use SQL
access. SQL records do not lock on reads. To prevent update anomalies when developing SQL-based applications, you must
use the transaction semantics of commitment control. Again, EJB containers do most of the transaction management for
you.

Team-Fly
Team-Fly

D irty P h an to m s
To resolve update anomalies that occur when Bill, Bob, and Jane access the same entity Bean requires only a little work
setting up the EJB. To do that, you need to know about SQL isolation levels and EJB transaction attributes, but before I go
into that, let me categorize update anomalies into three types: dirty reads, nonrepeatable reads, and phantom reads. A dirty
read occurs when a record read by one client is modified by another client but not yet committed. A nonrepeatable read
occurs when one client reads a record a second time after another client has changed that record since it was first read. A
phantom read occurs when a client rereads a group of records based on a selection criterion and another client has
subsequently added a record that fits that selection predicate.

The setup work required to resolve EJB update anomalies involves specifying an isolation level (Table 50.1) and transaction
attribute (Table 50.2) to be associated with your enterprise Bean in its deployment descriptor (Figure 50.2). The isolation level
table in Table 50.1 shows that each option provides different levels of locking, from the loose locking of
TRANSACTION_READ_UNCOMMITTED to the tight locking of TRANSACTION_SERIALIZABLE. You must remember that, as
you tighten the isolation level, you impose a performance penalty on your application.

T a b le 50.1: S Q L Iso la tio n L e ve ls

Iso la tio n L e ve l D e scrip tio n


TRANSACTION_READ_UNCOMMITTED Data changes immediately available, even without
commit; loosest isolation level.
TRANSACTION_SERIALIZABLE Locks data until commit; tightest isolation level.
TRANSACTION_READ_COMMITTED Prevents dirty reads but allows nonrepeatable and
phantom reads.
TRANSACTION_REPEATABLE_READ Prevents dirty and nonrepeatable reads but allows
phantom reads.
TRANSACTION_NONE Transactions not supported.

T a b le 50.2: E JB T ra n sa ctio n A ttrib u te s

A ttrib u te D e scrip tio n


TX_NOT_SUPPORTED Suspends existing transaction during method call.
TX_BEAN_MANAGED User-controlled transaction.
TX_REQUIRED Uses transaction if it exists; otherwise, it creates one.
TX_SUPPORTS Uses existing transaction but, otherwise, doesn't create one.
TX_REQUIRES_NEW Creates new transactions and commits transactions before returning.
TX_MANDATORY Throws an exception if no transaction exists.

Team-Fly
Team-Fly

C o m m itm e n t C o n tro l
Your selection of an isolation level defines the type of locking you want for your enterprise Bean, but, to lock your record or
records, you must use what is known as a commitment control boundary,or transaction. Transaction management can be
messy to work with, but EJB architecture was designed to handle it for you. Without EJB transaction management, you
would have to start a commitment control boundary, process the records, and, at the appropriate time, commit or roll back
the changes. To allow EJB to manage transactions, either specify one of the transaction attributes shown in Table 50.2 for all
the methods of an entity Bean or specify different transaction attributes for each method of the entity Bean.

You now have an entity Bean that has a one-to-one relationship with a DB2/400 record. You also have an isolation level and
transaction attribute associated with that entity Bean. That entity Bean may have a dozen different methods, all of which
manipulate the state of the entity. Because you've delegated transaction management to EJB, you don't have to set up
transaction boundaries. The entity Bean container automatically starts a transaction boundary when the method of that Bean
is invoked. That transaction boundary is known as a transaction context.

If you look over the transaction attributes in Table 50.2, you see that, sometimes, existing transaction contexts are used for
method invocations and, other times, new transaction contexts are created. At any rate, at some point, an enterprise Bean
method starts a new transaction context that may then be used in the invocation of other methods. That transaction context
is even used in the invocation of methods of other enterprise Beans. The point is that, upon return of the method that started
the transaction context, the transaction is automatically committed, and if the method invocation incurs a Java exception, the
transaction is automatically rolled back. When an application has a complex relationship between files (as all business
applications do), a single transaction boundary ensures integrity of the database modifications to your n-tier, EJB-based e-
commerce application.

Team-Fly
Team-Fly

M e th o d C o m m itm e n t
I must admit that, even after much research into EJB, I still didn't "get" EJB transaction attributes. It seemed to me that there
was a hole in the logic behind EJB transaction management. An enterprise Bean method must start a transaction context,
and when the method that started the context returns, the transaction is committed. I'm repeating myself, but my point is
that, when you apply the most basic standard OO encapsulation techniques to an entity Bean, little mini transactions fire off
all over the place. For instance, you would have a bunch of setter methods for a customer entity Bean. If I develop a client
application that uses that customer Bean and a user wants to modify several of a customer's attributes, that client application
would cause the EJB container to create and commit a new transaction for each invocation of a setter function. That doesn't
solve update anomalies; it's just a performance glut.

However, after pounding my head against my desk and reading a few hundred more pages of EJB documentation, I discovered
how to plug the hole I thought I'd found in EJB transaction management. I could associate transaction attributes to entity
Bean methods so that the EJB container could start transaction boundaries and subsequently commit database changes.
However, until I did further research, I didn't realize that stateful session Beans could also have transaction attributes
associated with their methods. I knew that an entity Bean normally has a one-to-one relationship with a database record and
that a stateful session Bean has a one-to-one relationship with a client application. The obvious plug for that hole was to use
the methods of stateful session Beans as macros for the invocation of entity Beans. You design session Beans with coarse-
grained methods that coordinate the fine-grained encapsulated methods of entity Beans. Therefore, session Beans prove the
overall control of transactions across invocations of methods in the same EJB class or in different EJB classes.

Team-Fly
Team-Fly

W h e re D o e s E JB F it In ?
EJB clients can be Java applets running from a Web browser, Java applications running over TCP/IP, or servlets. Servlets are
often used with EJB for two reasons. The first reason is that servlets simplify the user interface to HTML. The second reason
is that many Internet firewalls do not support the low-level protocol of EJB. Servlets effectively convert that protocol to one that
all firewalls understand: HTTP. Believe it or not, EJB clients can also be non-Java clients that use Microsoft DCOM clients or
OMG's CORBA, because many Web application servers can provide DCOM and CORBA proxy services for EJB components.

Will EJB architecture catch on? I think so. I think EJB will become a prevalent strategy for advanced e-commerce applications
because the industry is ready for a standard cross-platform architecture for business components that scales well and is
easy to use. Initially, you may find industrial-strength Web application servers that support EJB to be cost-prohibitive. I believe
the reason for this high cost is that the top Web application servers support a variety of architectures in addition to EJB.
Increasingly, however, new Web application servers that enter the market provide a limited number of services but specialize
in EJB hosting. In addition, because these servers are implemented in 100% Pure Java, they run on the AS/400. The beauty
of the EJB architecture is that you can use a lightweight EJB server (on your AS/400 or your desktop) to launch a proof-of-
concept application. Then, when management buys into this hot new technology, you can buy your industrial-strength
application server, with which your EJB business components are completely plug-compatible.

Team-Fly
Team-Fly

C h ap ter 51: E n terp rise Javab ean ss—


—S h o w M e T h e C o d e!
O v e rv ie w
DON DENONCOURT

I can only listen to so much hype about a new technology before I finally have to shout, "Let me see some code!" I've been
hearing about Enterprise JavaBeans (EJBs) for some time now, and I have been responsible for spreading some of that EJB
hype around myself. For instance, in the March 1999 issue of Midrange Computing, which focused on Java (and of which I
was the editor), IBM's Keith Rutledge said, "EJB is a standard computing model that works across computing platforms from
different vendors…. EJB makes it easier to write application logic and applications by handling the low-level infrastructure
tasks—such things as threading, state management, resource pooling, and the like."

Enough already. It's time to look under the hood of an EJB application. The beauty of EJB is that the client Java application
programmers don't have to deal with the complexity of the host Java classes. The code presented in this chapter focuses on
the client developer's view. I overview server-side EJB development without presenting its code—the client programmer doesn't
need to "know" about it anyway.

Team-Fly
Team-Fly

S e ssio n B e an s A n d E n tity B e an s
There are two basic types of EJBs: session Beans and entity Beans. Examples of session Beans are a shopping cart or a
grocery list of an e-commerce site. But ignore session Beans for now; you won't be using them until you begin the
development of advanced e-commerce applications. This chapter's focus is on entity Beans. Entity Beans are essentially Java
wrappers for persistent data, and for Java application programmers, the persistent data store is DB2 for OS/400. Typically,
you will have an entity Bean for each record format for the database files that make up your e-commerce applications.

Team-Fly
Team-Fly

W rap p in g Y o u r O rd e r: P ap e r O r P lastic?
Remember that this is object-oriented (OO) programming. An entity Bean not only provides methods that access the
information of a relational database (RDB) file, it also provides business methods that modify that information, as well as
methods that collaborate with other EJBs. The example Bean in this chapter is an OO wrapper for the information that is
contained in an RDB file called Order. The Order file has the simple format of order number (which is also the primary key),
customer number, and due date.

There are four basic components to any EJB: two interfaces (a home interface and a remote interface) and two classes (the
entity Bean itself and a primary key class). An interface is simply a list of methods that some Java class must later
implement, similar to a set of RPG IV D-specs that contains function and procedure prototypes. A Bean's home interface
provides the CRUD—that is, the EJB life-cycle methods for the creation, retrieval, update, and deletion of an entity Bean.
Figure 51.1 shows the O rd e rH o m e interface with the declaration of the cre a te and fin d B yP rim a ryK e y methods—in other
words, the creation and retrieval of CRUD. So, where are the U and D? The deletion is provided for with the declaration of the
re m o ve method in the base interface of O rd e rH o m ee, E JB H o m e (see Figure 51.2). An update method is not a required
interface for the client because the entity Bean on the server makes the state of a modified entity persistent by updating the
database at the appropriate times (using a function called e jb S to re re).

F ig u re 51.1: The OrderHome interface provides the life-cycle methods for an entity Bean.

F ig u re 51.2: EJBHome, the base interface of OrderHome, provides the methods required for the deletion of an
entity.

The O rd e r interface, the second of the two interfaces, is in Figure 51.3. It simply provides two methods: g e tD u e D a te and
g e tC u stN oo. For a more complete example, I'd also have numerous other methods (e.g., methods that modify the entity's
attributes or provide collaboration with other associated entity Beans). In the O rd e r example, I probably would have
g e tC u sto m e rr, a d d L in e Ite m , and g e tL in e Ite m methods.

 
F ig u re 51.3: The Order interface provides business methods for the manipulation of a business entity .

The two classes are the primary key class and the entity Bean. The primary key class is simply a class in which the data
members represent the full key of the entity. For the order entity, the order number is the full key, so the O rd e rP K class in
Figure 51.4 is composed of only one attribute: an Integer order number. The entity Bean class, O rd e rB e a nn, is where the
code for the O rd e r and O rd e rH o m e interfaces is implemented. Figure 51.5 lists the methods of the O rd e rB e a n class minus
their code implementations (which are beyond the scope of this chapter).

F ig u re 51.4: The attributes of the OrderPK class correspond to the full key of the RDB Order file.
 
F ig u re 51.5: The OrderBean class provides code implementations for all the methods of the OrderHome and Order
interfaces (shown in Figures 51.1-51.3) .

It is important to note that the client programmer will not be using the entity Bean—not directly, that is. The client
programmer uses the entity Bean through what is known as the remote interface. The remote interface is composed of the
business methods of the entity Bean. The Order Bean's remote interface is shown in Figure 51.3. The entity Bean is the Java
class that provides the code implementation for the home and remote interfaces.

Team-Fly
Team-Fly

B e an M an ag e d V s. C o n tain e r M an ag e d
The entity Bean itself or its container can manage the persistent storage of an entity Bean's attributes. Persistence
management by the entity Bean is easier for us legacy programmers to understand because we are used to being
responsible for implementing the code to create, read, update, and delete the DB2/400 records. In the documentation for EJB,
it is almost expected that you'll use JDBC for database management, but it's up to you. You could use IBM's Java Toolbox for
the AS/400's record-level access classes or an OO database management system.

An EJB strategy that may not be as easy to understand is container-managed persistence. Sun Microsystems' preliminary
EJB 2.0 specification includes strategies for the automation of RDB access for entity Beans. That means you don't have to
write any CRUD code; all you have to do is specify in a control file, known as the deployment descriptor, the persistent
storage type of JDBC and the file name followed by a table that maps the database field names with the entity Bean's
attributes. Figure 51.6 shows an example deployment descriptor that you could use with BEA's WebLogic for the
specification of container-managed persistence for my Order entity Bean.

F ig u re 51.6: The Client application uses an EJB remote interface to access the methods of a host-based entity
Bean.

Team-Fly
Team-Fly

C lie n t C o d e
Regardless of which strategy I use to manage persistence, the client code required to access the Order entity Bean (shown
in Figure 51.7) remains the same. The Java class, appropriately called C lie n tt, begins by qualifying itself as part of Midrange
Computing's EJB client package before it imports all of Midrange Computing's EJB interface classes:
package com.midrangecomputing.ejb.client;
import com.midrangecomputing.ejb.interfaces.*;

F ig u re 51.7: The EJB client obtains a reference to the remote Bean through the Java Naming and Directory
Interface.

The C lie n t class then imports the Java packages required for the remote access of EJB. The first method of the C lie n t class
is called g e tIn itia lC o n te x t. The code for this method is typical of EJB clients; it specifies the properties of the EJB host,
such as the URL of the host and its socket number as well as the user name and the user's password.

This particular EJB client application uses a hard-coded order number to retrieve a remote reference to an entity Bean. If the
order is not found, the application creates one using a hard-coded customer number and due date. All this processing is done
in the method called m a in
in. The m a in method begins by creating the object variables that contain the hard-coded values for
the order number, customer number, and due date. The m a in method then creates an instance of the O rd e rP K class and
then sets its order number attribute to be the Integer object that contains the hard-coded order number:
OrderPK orderKey = new OrderPK();
orderKey.ordNo = ordNo;

At this point, the client application is ready to retrieve a remote reference to a server instance of the Order entity Bean:
Context ctx = getInitialContext();

The client first invokes the g e tIn itia lC o n te x t method, which specifies to whom it is communicating. Then, it uses the lo o ku p
method of the C o n te x t class to enable a connection with the server's implementation of the O rd e rH o m e interface.
Remember that the home interface provides the life-cycle methods of an entity Bean; it is with the variable called h o m e that
the client application will retrieve or create an order entity.
OrderHome home = (OrderHome) ctx.lookup("ejb.OrderHome");

The client then creates a variable whose type is the Order entity Bean's remote interface. Remember that the remote interface
specifies the business methods for an entity Bean:
Order remoteOrder = null;

Next, the client attempts to retrieve a remote reference to the Order entity Bean with the fin d B yP rim a ryK e y method of the
O rd e rH o m e interface:
remoteOrder = (Order) home.findByPrimaryKey(orderKey);

But if a reference to the remote order could not be had, the client application creates a new one using the cre a te method of
the O rd e rH o m e interface:
remoteOrder = home.create(ordNo, custNo, dueDate);

Either way, whether found by primary key or newly constructed, the re m o te O rd e r variable contains a remote reference to the
Order entity Bean, which means the client application can invoke the methods of the remote interface:
System.out.println("Order......: " + ordNo +
" Customer..: " + remoteOrder.getCustNo() +
" Due Date..: " + remoteOrder.getDueDate());

The use of the remote invocation of the server-based entity Bean for system output may seem overly trivial, but it nonetheless
suggests the power of EJB. In a robust EJB application, the remote interface will contain business methods that the client is
able to invoke to perform the complex tasks associated with that entity.

Team-Fly
Team-Fly

N e e d fu l T h in g s
If the techniques shown in this order-processing example were all that EJB provides, there'd be no reason to use this
technology. And there'd be no reason to pay thousands, or tens of thousands, of dollars for an EJB server. The code that I've
shown for the client side is simply a slight variation of Java's Remote Method Invocation (RMI). So why not just use RMI,
which is free? An Internet application that uses the object distribution strategies of RMI will work fine when 10 clients are
accessing it. It will probably work fine when you have 20 clients attached, but when you have 100 or 1,000 clients…? RMI
applications don't scale well without complex systems programming. We are not systems programmers; we are business
programmers. EJB applications scale well because the EJB servers handle performance, using such features as caching,
resource pooling, and least recently used (LRU) algorithms for memory management. Furthermore, EJB has sophisticated
mechanisms for the management of transactions and commitment control—something all complex e-commerce applications
will require.

Team-Fly
Team-Fly

T h e E jb In te rface
The development of EJB applications can become quite complex, but the use of entity Beans in client applications is simple.
You use the home interface, O rd e rH o m e in my example, to control the life cycle of an entity Bean. You use the remote
interface, O rd e r in my example, to invoke the business methods of an entity Bean. You can manage the persistence of entity
Beans yourself, or you can delegate that responsibility to the container-managed persistence provided by the EJB server. By
the beginning of 2001, we began to see EJB Internet applications from independent software vendors that run great on the
AS/400. The use of the Enterprise JavaBeans specification will become pervasive because it provides the technologies
required for robust Internet e-commerce applications.

Team-Fly
Team-Fly

C h ap ter 52: E JB —W h at's G o in g O n H ere


O v e rv ie w
DON DENONCOURT

Everything has changed. The whole model for business programming has changed. It used to be that when you acquired new
AS/400 software, you looked at the database, perused a few thousand lines of RPG code, and had an understanding of what
was up. Now, with all this Java stuff, it's a lot easier to understand new systems. With the advances in modular programming,
component-based programming, and Enterprise JavaBeans (EJBs), learning new application software is easier than it ever
was with legacy RPG applications. With the availability of WebSphere 3.0 for the AS/400 comes IBM's implementation of an
EJB engine. EJB applications work entirely differently than what you are comfortable with, but, if you follow along with me in
this chapter, I think you'll agree that the new application design model is an improvement.

In this chapter, I'll give an overview of the architecture of the example EJB application that ships with WebSphere 3.0. The
example application revolves around two simple components: an Account entity Bean and a Transfer entity Bean. The Java
classes and interfaces that make up those two components are shown in Figure 52.1. The Account entity Bean has an
interface called, well, A cco u n t; an interface called A cco u n tH o m e ; a class called A cco u n tK e y; and another class called
A cco u n tB e a nn.

F ig u re 52.1: An entity Bean has four components: an entity interface, a home interface, a primary key class, and the
actual class that implements the methods of the interfaces.

All those classes and interfaces seem a little overwhelming, but each has its own specialized purpose, and, as you'll see, the
code for them is really quite simple. Let me break the construction of those classes down so that you can see what I mean
when I say "simple." The real McCoy of the Account classes and interfaces is the A cco u n tB e a n class; that's where all the
real-world business methods are implemented. Yet, paradoxically, clients are not allowed to directly access the
A cco u n tB e a n class. EJB clients access the A cco u n tB e a n class indirectly through the A cco u n t and A cco u n tH o m e
interfaces. This is standard EJB stuff here; all entity Beans have two such interfaces. For instance, Java client applications
access the T ra n sfe rB e a n class, which is also shown in Figure 52.1, through the T ra n sfe r and T ra n sfe rH o m e interfaces.

Team-Fly
Team-Fly

The C ode
As you probably already know, Java interfaces contain no code; they are only a list of methods. If you look closely at Figure
52.1, you'll see that the four methods of the A cco u n t interface (aa d dd, g e tB a la n ce ce, and su b tra ct) are also in the
ce, se tB a la n ce
A cco u n tB e a n class. The A cco u n tB e a n class is where the Java code implementation for the methods of the A cco u n t and
A cco u n tH o m e interfaces actually exists. Clients are able to remotely invoke the A cco u n tB e a n methods through a variable
whose data type is of the A cco u n t interface. But before the client application can invoke those methods, it has to get a
remote reference to a specific account entity through one of the methods of the A cco u n tH o m e interface. You can think of the
A cco u n tH o m e interface as a factory for creating and retrieving accounts. The A cco u n tH o m e interface has a method called
fin d B yP rim a ryK e yy, which is used to retrieve a specific entity, and two cre a te methods, which are used to create entirely
new business entities (the result of which is new records in the database).

There is one other class that I haven't covered yet—the A cco u n tK e y class. The A cco u n tK e y class is really nothing more
than a key list; it is a class that encapsulates access to the full key of an entity Bean. In the case of an Account object, the
full key is merely an account ID stored as a long integer. Earlier, I said that it is through the methods of the A cco u n tH o m e
interface that you are able to retrieve accounts. The fin d B yP rim a ryK e y method of A cco u n tH o m e returns a reference to a
specific Account object. If you look at the code listing in Figure 52.2, you can see that the fin d B yP rim a ryK e y method takes
an A cco u n tK e y as a parameter. That should make sense, because the fin d B yP rim a ryK e y method is essentially a read-by-
key operation, except you don't get a database record returned; instead, you get an entity Bean returned that wrappers
access to the business entity stored in the relational database.

 
F ig u re 52.2: The code for an entity Bean is fairly trivial because much of the responsibility for maintaining business
entities is handled by the EJB engine .

The four methods of the A cco u n t interface and the three methods of the A cco u n tH o m e interface aren't the whole story. If you
look at the code for the Account interface that is shown in Figure 52.2, you can see that it extends an interface called
E JB O b je ct. So, by order of Java inheritance, the A cco u n t interface has five other important and powerful methods:
le, isId e n tica ll, and re m o ve
g e tE JB H o m ee, g e tP rim a ryK e yy, g e tH a n d le ve. The g e tE JB H o m e method is used to retrieve a
reference to an A cco u n tH o m e object. The g e tP rim a ryK e y method is used to retrieve a key list object. The g e tH a n d le
method returns an object that is roughly comparable to a remote entity Bean reference except that the handle object is
guaranteed to uniquely identify an entity Bean. The isId e n tica l method is used to check if two entity Bean variables reference
the same entity. And, finally, the re m o ve method is used to delete an entity from DB2/400 (or whatever relational database
your EJBs are associated with).

The A cco u n tH o m e interface, as you can see from its code in Figure 52.2, extends the E JB H o m e interface. Therefore, all of
those home factory interfaces contain the three methods inherited from E JB H o m ee: two re m o ve methods, one of which
deletes an entity by a handle and the other of which deletes by a key list object, and the g e tE JB M e ta D a ta method, which
retrieves descriptive information about an entity Bean.
Team-Fly
Team-Fly

C lie n t A cce ss T o E n tity B e an s


Before I go into detail about the implementation for the A cco u n tB e a n class, I'd like to cover how a client application can
access the Account entity Bean. The WebSphere example application includes two Java servlets: C re a te A cco u n tJS P and
T ra n sfe rF u n d sJS P . The C re a te A cco u n tJS P servlet responds to an HTML form request to create a new account and then
passes control to a Java Server Page (JSP) to build the HTML response. The T ra n sfe rF u n d sJS P is used not only to transfer
funds from one account to another but also to list summaries of various accounts.

The code required to access an entity Bean from a client application is fairly simple to implement. First, you need to import
the appropriate packages:
import java.rmi.*;
import javax.naming.*;
import javax.ejb.*;
import javax.rmi.PortableRemoteObject;

The mechanism that EJB uses to transport objects across the Internet is Java's standard Remote Method Invocation (RMI),
the classes of which are contained in the ja va .rm i package. Entity Beans are requested from what is known as a naming
service, hence the ja va x .n a m in g package. (The x refers to extensions to the standard Java packages.) As you might guess,
the ja va x .e jb package is required to access the basic EJB classes. The ja va x .rm i.P o rta b le R e m o te O b je ct class is
imported to provide what is often referred to as an Object Request Broker (ORB). An ORB, like a travel broker, handles the
travel plans for objects across the Internet.

Team-Fly
Team-Fly

C re ate A cco u n t C lie n t


The C re a te A cco u n tJS P servlet obtains a reference to an A cco u n tH o m e object in its in it method. The servlet's in it method
begins by creating a C o n te x t object (which is basically the hook to an EJB server):
Context context = new InitialContext(env);

The e n v variable that was passed to the In itia lC o n te x t constructor contains soft-coded configuration values such as the URL
of the EJB server. Through the use of the EJB server context, the in it method of C re a te A cco u n tJS P is able to get a remote
reference to a specific entity Bean's home interface:
Object homeObject = ctx.lookup("account");
AccountHome accountHome =
(AccountHome)javax.rmi.PortableRemoteObject.narrow(
homeObject, AccountHome.class );

There's a lot going on in the two preceding statements. The lo o ku p method pulls the remote reference, but the object type
that is returned is what I consider to be the ultimate in Java ambiguity—an O b je ct object. That object variable, h o m e O b je ct,
truly is, at runtime, not merely a reference to an object of the class O b je ct but a reference to an object of the class
A cco u n tH o m ee. The second statement, therefore, is used to "narrow" (as the method is called) the reference to the
A cco u n tH o m e class. Remember that entity Beans are created, retrieved, and removed from the entity Bean's home interface
so that the A cco u n tH o m e object variable can then be used to create, remove, or retrieve specific Account objects.

The a cco u n tH o m e object instantiated in the in it method of C re a te A cco u n tJS P is used in its d o G e t method. When a
servlet-enabled Web server responds to a Web-browsing user's HTML form request, it invokes the d o G e t method of the
servlet specified in the ACTION option of the HTML < F O R M > tag. The C re a te A cco u n tJS P servlet's d o G e t method begins by
pulling the values entered by the user in the HTML form with the g e tP a ra m e te r method. Then, from the values retrieved from
the form, the d o G e t method creates an A cco u n tK e y key list object:
String accountNo = req.getParameter("account");
AccountKey kList = new AccountKey(Long.parseLong(accountNo));

With the k L ist object in hand, the d o G e t method is able to create a new A cco u n t object through the cre a te method of the
a cco u n tH o m e "factory" object:
Account account = accountHome.create(key, typeAcct, initialBalance);

Team-Fly
Team-Fly

T ran sfe r F u n d s C lie n t


WebSphere's example T ra n sfe rF u n d sJS P servlet processes much the same as C re a te A cco u n tJS P does. The in it method
of T ra n sfe rF u n d sJS P also obtains a context to WebSphere's EJB server. But, to prove that WebSphere supports not only
EJB as a distributed objects protocol but also CORBA, a remote reference to T ra n sfe rH o m e is retrieved using the facilities of
CORBA:
TransferHome transferHome =
(TransferHome)javax.rmi.PortableRemoteObject.narrow(
(org.omg.CORBA.Object)homeObject, TransferHome.class);

The d o G e t method of T ra n sfe rF u n d sJS P begins by creating a T ra n sfe r object:


Transfer transfer = transferHome.create();

Note that the T ra n sfe r class, as you can see in Figure 52.1, has no key list object. That makes sense, because a transfer is
transactional in nature and a unique or primary key is not required to represent transactions. Once the T ra n sfe r object is
created, the d o G e t method is able to invoke the g e tB a la n ce or tra n sfe rF u n d s method based on the user's request:
if (request == 1) transfer.transferFunds(fromKey, toKey, amountFloat);
else if (request == 2) transfer.getBalance(fromKey);
else if (request == 3) transfer.getBalance(toKey);

Team-Fly
Team-Fly

W h e re 's T h e C o d e ?
Now that I've covered the interface to the A cco u n tB e a n and T ra n sfe rB e a n classes, it's time to look at the actual code
implementation. Figure 52.3 shows the complete code for the A cco u n tB e a n class. But wait a minute. Where's the relational
database access? Where's the transaction control? And why do some of the methods have code implementations with no
code?

 
F ig u re 52.3: The AccountBean provides code for the business methods and "callbacks" for the seven life-cycle methods
of an entity Bean.

Years ago, when I was a data processing manager, my supervisor was the controller. He was a very bright guy, but he called
what I did "voodoo." Well, there's a lot of voodoo going on with the EJB engine. It is the EJB engine that reads and writes to
the database. It is the EJB engine that handles transaction and commitment control. And it is the EJB engine that provides
the "real" code implementation for the methods of the A cco u n tB e a n class that are implemented with two braces and no
code.

Seven of the methods of A cco u n tB e a n are special e jb methods: e jb A ctiva tete, e jb C re a te


te, e jb L o a dd, e jb P a ssiva te
te,
e jb P o stC re a te ve, and e jb S to re
te, e jb R e m o ve re. These seven methods are known as the "life-cycle" methods of an entity Bean.
The two e jb C re a te methods of A cco u n tB e a n are mapped by the EJB server to the A cco u n tH o m e interface's cre a te
methods. You'd expect to see an explicit write to the database in their methods but, trust me, EJB handles it for you in its
own hidden implementation of the e jb C re a te methods.

When an EJB client, like the C re a te A cco u n tJS P and T ra n sfe rF u n d sJS P servlets, invokes the cre a te method of
A cco u n tH o m ee, the EJB first invokes its own version of e jb C re a te to insert a record into your relational database. Then the
EJB engine invokes the A cco u n tB e a n version of e jb C re a te
te. The only thing that the A cco u n tB e a n version of e jb C re a te is
responsible for is setting the value of the entity Bean's attributes (class fields, properties, or whatever you want to call them):
accountId = key.accountId;
this.type = type;
balance = initialBalance;

You can consider the seven special e jb methods as callbacks, because the EJB engine calls them after it invokes its own
version of those methods. The hidden version of e jb L o a d is implemented to read from a relational database. The hidden
version of e jb S to re is implemented to write to the relational database. The hidden versions of e jb A ctiva te and e jb P a ssiva te
are implemented with the complex code required to "page" objects out of main memory to secondary storage for improved
performance—sort of like standard AS/400 work management. After the EJB engine calls its hidden version of any of the
seven special e jb methods, it calls the A cco u n tB e a n version. It's up to the EJB developer to decide if there is anything to do
after the EJB engine has done its stuff. On an e jb L o a dd, for instance, you might want to perform some calculations to build an
attribute of an entity field that is not stored persistently in the database, such as an order total.

An important point is that nowhere will you see calls to any of the e jb C re a te te, e jb L o a dd, e jb P a ssiva te
te, e jb A ctiva te
te,
e jb P o stC re a te ve, and e jb S to re methods (except, as Figure 52.3 shows with e jb C re a te
te, e jb R e m o ve te, when one e jb method
calls an overloaded version of the same method). The EJB engine decides when to invoke the life-cycle methods of an entity
Bean.

Team-Fly
Team-Fly

B u sin e ss P ro g ram m in g
The Enterprise JavaBeans specification clearly states that its intent is to "let business programmers do their job." EJB
removes the responsibility of accessing data from a database. It relieves the responsibility of managing complex transactions.
It relieves the responsibility of managing memory use. What is left to the business programmer is to write the business
methods that manipulate the state of business entities.

For the EJB engine to be able to do all that voodoo mentioned earlier, the EJB business programmer has to follow some fairly
structured steps to deploy entity Beans. Each Web application server has different deployment methods, but each
subsequent release of Sun's EJB specification makes deployment more and more standard.

Team-Fly
Team-Fly

C h ap ter 53: O p en
en--S o u rce E n terp rise Javab ean s
O v e rv ie w
JEFF MARKHAM

Whether you have been developing in Java for a few years now or are just starting out, there is no doubt you've become
acquainted with Enterprise JavaBeans (EJBs). As an AS/400 professional, you might be resigned to the idea that you'll have
to use IBM's WebSphere to take advantage of EJBs. There is an alternative, however; open-source options can now be
downloaded free for use with your AS/400. First, I'll discuss some fundamental EJB concepts, and then I will walk through an
example that can be applied to either of the two open-source EJB containers (container being the proper term for an EJB
server) covered in this chapter: JOnAS and jBoss.

Team-Fly
Team-Fly

E JB B asics
To create an EJB, you'll need to create at least two interfaces and one class. One of the interfaces is the remote interface,
which defines the Bean's business methods. Business methods are those methods that you'll use in client code to
manipulate the Bean. For example, if you have methods to get or set variable values of the Bean, those methods will be
defined in the remote interface. The other interface is called the home interface, and it is responsible for what is known as the
Bean's life cycle. The home interface defines methods to create, remove, and find Beans. These two interfaces and their
methods are used by the client code to interact with the Bean itself.

The actual Bean class must have methods identical to those defined in the remote interface, and it must also have methods
corresponding to some of the methods of the home interface. Client code doesn't actually instantiate an object of the Bean
class. (This may seem redundant or somewhat confusing, but it will become quite clear as you continue your EJB
development efforts.) An optional class used only for entity Beans is called a primary key class, which is quite simple and
provides access to a database record via a primary key.

There are basically two types of EJBs: session Beans and entity Beans. Session Beans can be categorized as either stateful
or stateless and, as a rule, represent some sort of business logic. For example, if your Bean design called for an EJB that did
nothing but calculate sales tax based on the geographical location of a customer, a session Bean would be a good candidate
to perform that work. The two types of entity Beans are Bean-managed persistent Beans (BMP Beans) and container-
managed persistent Beans (CMP Beans). Entity Beans are typically used to represent database records. If you choose in
your entity Bean to take care of the database communication yourself using SQLj, JDBC, or the AS/400 Tool- box for Java's
record-level access classes, your Bean will be a BMP Bean. If you choose to have the EJB container take care of the
communication between your entity Bean and a database, you will have created a CMP Bean.

Team-Fly
Team-Fly

S o p h isticate d B e an s
A mention of CMP Beans usually brings the question "How does an EJB container handle the database inserts, updates, and
deletes for me?" The sophistication of EJB containers allows them to provide much more than a space for EJBs to run. As I
mentioned, an EJB container can handle database operations in entity Beans. Virtually every container on the market today
does so through the JDBC driver of the database your CMP Bean will use. In the case of the AS/400, this means that if you
want to get at the data in your AS/400 files, you'll configure your EJB container to use the JDBC driver found in the AS/400
Toolbox for Java. Fields in a CMP Bean are then mapped to specific fields in a specific table in a specific database. Because
the EJB 1.1 specification isn't crystal clear on how these mappings are to be implemented, the method to perform the
mappings is container-specific. The example in this chapter details how to instruct your EJB container to make a particular
CMP Bean aware of its corresponding database file.

In dealing with databases, EJB containers also provide client code with transaction management. The Java Transaction API is
used by the container to give client code a high-level transaction service, thereby relieving the client code developer of worries
about transaction management and coordination.

Team-Fly
Team-Fly

S e cu rity , P le ase
Another feature of EJB containers is their ability to perform security functions. The EJB 1.1 and the Servlets 2.2 specifications
define standards and rules for containers to follow to accomplish the goal of cross-platform security. Until recently, security
for any server-side Java application was platform-specific. In the case of the AS/400, this meant learning validation list APIs or
using HTTP basic authentication for a user and then devising your own system of access.

EJB containers also manage resources, including database connections, threads, and socket connections. Container support
can allow multiple clients to access Beans, which frees the developer from worrying about how Beans are accessed or what
happens when a Bean is on the receiving end of a deluge of client requests. The container does this by creating as many or
as few instances of the Bean object as necessary within the container and by routing client requests to appropriate instances
of the Bean. Fundamentally, however, the EJB container creates a distributed, networked application out of components (the
interfaces and classes constituting a single EJB) that are written essentially as stand-alone objects. This, of course, is no
small thing.

To recap the benefits of EJBs and EJB containers, the EJB model allows developers to partition their efforts cleanly between
session Beans and entity Beans. In using these Beans, the developer is freed from low-level database transaction knowledge.
The developer will also be able to use cross-platform security and avoid coding to a platform-specific security API. The
developer may choose to bypass coding database operations and have the container perform those tasks. The developer is
thereby freed from the worry of threads or providing resources such as database connections. The developer is relieved of
having to figure out how to handle multiple clients of the Bean. And, possibly most significant, the Bean developer is able to
develop networked, distributed components without coding or knowing how those components will become networked and
distributed. RPG developers can understand the importance of EJBs and EJB containers, because most of their benefits are
similar to those that OS/400 provides for an RPG program. With all these advantages, it's no wonder that EJB development is
of great interest to business application developers.

Team-Fly
Team-Fly

D e p lo y in g T h e B e an
Rather than coding for many of these EJB features, they can be implemented by declaring them in what's known as the
deployment descriptor. Figure 53.1 shows a portion of a required deployment descriptor of an EJB called e jb -ja r.x m l. As you
can see by the file name, this is an XML file with tags to define the Bean, the Bean's remote and home interfaces, primary
key class (if any), and other descriptions to assist the EJB container in deploying the Bean. Note that the example is of a
CMP Bean corresponding to the familiar sample file of each AS/400, QIWS/QCUSTCDT. The deployment descriptor declares
that the Bean's persistence is managed by the container, and then it declares fields in the Bean that the container will have to
map to the correct fields in the correct file. The e jb -ja r.x m l file can be quite lengthy and has many tags to use and
remember. Typically, EJB containers come with tools to create these deployment descriptors. Even with these tools,
however, it's a good idea to become familiar with the more common, required tags by going to Sun Microsystems' EJB site at
www.java.sun.com/ products/ejb.

 
F ig u re 53.1: The ejb-jar.xml file has tags to help the EJB container deploy the Bean .

As I mentioned, a container that is EJB 1.1-compliant will offer support for CMP; in EJB 1.0-compliant containers, CMP
support is only optional. However, there are no clear instructions for EJB containers on how to implement this functionality,
and it is left to the container vendor to figure out how to do CMP support. In the case of JOnAS, CMP support comes in the
form of another XML deployment descriptor called jo n a ss--e jb
jb--ja r.x m l, a portion of which is shown in Figure 53.2.

F ig u re 53.3: Use the XML deployment descriptor to do CMP support in JOnAS.

One of the functions of an EJB container that I mentioned is the capacity to manage resources, including database
connections. In the jo n a ss--e jb
jb--ja r.x m l deployment descriptor, there is the Java Naming and Directory Interface (JNDI) name
of the database connection resource called A S 400 400. Setup of this resource is included in the configuration files of the entire
example. The table name is defined here (QCUSTCDT), and the CMP Bean's fields are mapped to the actual physical file
fields. Also, you can see declarations on how to implement what are known as finder methods. Finder methods are defined in
the Bean's home interface and are meant to put a wrapper around SQL SELECT statements. Container-specific deployment
descriptors will vary slightly in their descriptions of Bean field to database field mappings and finder methods.

The example on the companion CD is a simple CMP Bean with a client class that simply gets a reference to the EJB and
performs a few methods on that Bean. The output is shown in Figure 53.3.
 
F ig u re 53.3: The output of a simple CMP Bean shows data for a client class .

Team-Fly
Team-Fly

W h ich Is B e tte rr—


—JO n A S O r jB o ss?
I'd like to talk a bit about the two open-source containers mentioned in the beginning of the chapter, JOnAS and jBoss. As
open-source products, both are freely available to download and use in production immediately. I'll give you my take on both
products based on my experience. Both are all-Java products, meaning that they can run on any machine that has a Java
Virtual Machine (JVM). Typically, the installation procedure for Java products, including these, is to simply download a .z ip
file and extract it to wherever you like on your disk. One of the first things to do is configure the container to create a data
source for whatever database you'll be using. For me, it was easier to configure an AS/400 data source for JOnAS than jBoss.
Documentation for this procedure was clearer for JOnAS, and the process was much more straightforward. Also, it was easier
to configure a CMP Bean for use with JOnAS than with jBoss.

Because all deployment descriptors in EJB 1.1 containers are XML files, it would make sense that one would be able to use a
favorite XML editor to construct these files. With jBoss, however, it doesn't seem to be enough that the deployment
descriptors are both well formed and valid. It appears to be hit-and-miss as to whether jBoss will choke on deploying your
EJBs, depending on whether you used its supplied deployment descriptor generator (EJX) or not. For example, I was able to
use the XML features in the integrated development environment Forte (a free download from Sun) to create my e jb -ja r.x m l
file, check and validate the XML, and have JOnAS recognize it. I could not get jBoss to recognize that deployment descriptor
or the jBoss-specific CMP deployment descriptor, ja w s.x m l. JBoss's mailbox is littered with messages from users
complaining about the behavior of EJX and jBoss's inability to consistently recognize deployment descriptors regardless of
how they're created.

Despite jBoss's difficulties with creating data sources and deployment descriptors, I believe that jBoss is the superior of the
two containers for a couple of key reasons. First is jBoss's ability to hot-deploy a Bean. EJBs are packaged in JAR files; with
jBoss, deployment of the JAR file is as simple as dropping the JAR file into a directory that jBoss constantly monitors for new
Beans. This means no restarting the container when there are new Beans to deploy, an extremely significant feature for any
production-quality software. Second, there has been significant work in this project to integrate Tomcat as tightly as possible.
Tomcat is the open-source JSP/servlet container from the Apache Software Foundation, makers of the ever-popular Apache
HTTP Server. Tomcat's origins are in Sun's reference implementation of its JSP/servlet specification. Sun handed over the
code for that reference implementation to the Apache group, and Tomcat is the resulting production-quality JSP/servlet
container. Both JOnAS and jBoss can receive security information (such as roles and users) from Tomcat, creating a
seamless security environment for JSPs, servlets, and EJBs. Where jBoss shines, though, is not in the project's work to run
the two products within the same JVM but in its focus on communication speed between the two.

Another great aspect of jBoss is that you don't need to compile stubs and skeletons. If you're familiar with Remote Method
Invocation (RMI), you'll know that RMI uses intermediary objects called stubs and skeletons to communicate across the
network. JOnAS comes with a tool called GenIC, which reads the classes and interfaces of your Beans, creates the source
for classes required by JOnAS (stubs and skeletons), and then compiles the source. The resulting class files must be
packaged in the same JAR file as the Bean class files and then deployed. The reason for this step is that EJB uses some
features of RMI to perform communication between objects across the network. In any case, not having to carry out this task
when using jBoss is a definite plus.

Team-Fly
Team-Fly

T h e JV M
Of course, the AS/400 has a JVM, and IBM made version 1.3 available on the iSeries platform within months of Sun's
announcement of JDK 1.3. Having said that, even with the help of other AS/400 professionals, I was unable to get either of
these containers to run on IBM's AS/400 JVM. After running these containers on Windows 98, Windows NT, Red Hat's Linux,
and even Sun's Solaris, my suspicion turns to the AS/400 JVM. Without concrete proof, I'm unable to lambaste the AS/400
JVM, but I, along with MC senior technical editor Don Denoncourt, will be sure not to let this issue die, so as to deliver to the
AS/400 community two production-quality open-source EJB containers.

For most, EJBs on the AS/400 means WebSphere. WebSphere costs big bucks: about $7,500. For the sake of argument,
take the worst-case scenario concerning running either JOnAS or jBoss, that they'll never be able to run in the AS/400's JVM.
Spending a few grand on an Intel server running Linux used only for Apache/Tomcat/jBoss–JOnAS would still be less costly
than a copy of WebSphere. On top of that, you'd be able to take advantage of the latest Java 2 Enterprise Edition
specifications instead of waiting for WebSphere to bring itself up to still a couple versions behind the current specifications for
JDBC, servlets, and JSPs. Download both JOnAS and jBoss, spend some time developing EJBs, and soon you'll be ready to
use them in production.

Team-Fly
Team-Fly

C h ap ter 54: D istrib u ted Java C o m p u tin g W ith R M I


O v e rv ie w
DON DENONCOURT

Remote Method Invocation (RMI) sounds like a rather fancy and perhaps even intimidating kind of technology, but it really
isn't. If you break the term down, you can infer that remote refers to networking capabilities in a client/server strategy.
Invocation is a well-known synonym for a program call. What you might not know is that in object-oriented (OO)
nomenclature, a method is another word for a class function. Therefore, Remote Method Invocation suggests the ability to call
host Java functions from a remote site. This in itself is not too exciting. Most client/server languages directly support the
invocation of host programs from a remote site. Chapter 24, "Calling RPG from Java," explains how to use IBM's AS/400 Java
Toolbox to make AS/400 program calls. But the RMI facilities of Java 1.1 deliver far more than just the ability to call programs
remotely. RMI is an easy-to-program architecture that allows local Java objects to access remote Java objects as if they were
on the same machine. In essence, RMI is a simple, yet elegant, OO approach to distributed computing that is easy to write
and easy to maintain.

Consider for a moment the design of an AS/400 Java application that is composed of a group of classes. Once you create
those Java classes that make up the Java application, you can make runtime instances of the application's classes (more
appropriately called objects) accessible across a network. Without RMI, you would have to make remote calls to host AS/400
programs that return a stream of data bytes back to the client. Your Java code would then have to repackage that data back
into the object's format. With RMI, you simply access the objects as if they were local.

RMI is so easy to use, I almost find it disheartening. You see, I have done a significant amount of programming in C and C++
using both TCP/IP and SNA protocols to dynamically handle the remote transfer of data. With TCP/IP, I had to deal with
sockets or Remote Procedure Calls (RPCs). My network programs had to manipulate data packets and handle the
marshaling and demarshaling of data. (Marshaling is the process of converting data into a network protocol before transfer,
and demarshaling refers to the conversion of data back from the network into the desired application format.) Working directly
with TCP/IP and SNA required studying several books and a significant learning curve. (Note that Java has made sockets
programming easier by providing an excellent implementation of sockets programming classes.) Distributed computing using
Java's RMI, on the other hand, requires only reading a short tutorial and playing with a set of example RMI classes. This
chapter provides both.

Team-Fly
Team-Fly

A n E x am p le R M I A p p licatio n
I am going to work through a simple example that will illuminate how an RMI implementation works. I had originally hoped to
create an RMI application in which the client RMI class resides on an AS/400 with the beta port of Java 1.1.1 installed. I
planned to set up the class to make requests from a PC-based server RMI class to create an Abstract Window Toolkit (AWT)
window frame. Interesting concept, executing a graphical application from an AS/400. Unfortunately, the beta AS/400 Java
1.1.1 port had some problems in its RMI implementation at the time, so I simply designed the RMI application to use the
same PC as both the host and the remote site. Having both the host and the remote site as the same machine also makes
things easier for you to play around with RMI. When the AS/400 Java port is stable, you can modify a few lines of the
example and the application will work as originally intended.

Team-Fly
Team-Fly

E ig h t S te p s T o R m i
Developing RMI Java classes, no matter what the complexity, requires that you follow eight simple steps.
1. Define the remote interface.

2. Develop the server class by implementing the remote interface.

3. Develop the client class to use the remote interface.

4. Compile the Java source.

5. Generate the client stub class and server skeleton class.

6. Start the RMI Registry on the server machine.

7. Execute the server class.

8. Execute the client class.

S te p O n e : T h e R e m o te In te rface
The cornerstone of RMI programming is the development and deployment of a Java interface that comprises the functions that
you wish to access remotely. An interface is a construct that defines functions, similar to a class but without providing
implementations for those functions. You can think of an interface as the class API to be accessed remotely. Figure 54.1
shows the interface, named R e m o te A W TT, for the example RMI application. You want the RMI server class to create an AWT
window frame at the request of a remote site's client class. The R e m o te A W T interface, as with all RMI interfaces, extends
the R e m o te interface imported from the ja va .rm i package. Also notice the required R e m o te E x ce p tio n declaration. All
functions in your interface must include this throw exception statement. Network communications are prone to errors, and
RMI was designed to force implementations to prepare for those remote exceptions.

F ig u re 54.1: The Java interface called RemoteAWT has one method, createAWTFrame.

S te p T w o : Im p le m e n tin g T h e R e m o te In te rface
At this point, you are halfway done with the development of an RMI application. I know I have only covered the first of eight
steps, but setting up the interface makes up most of the work. The second step is to develop the server class by
implementing the remote interface. Figure 54.2 shows the definition for the A W T S e rve r class.
 
F ig u re 54.2: The server RMI class (AWTServer.java) implements the RemoteAWT interface .

A W T S e rve r extends, as all RMI server class implementations must, the U n ica stR e m o te O b je ct imported from the ja va .rm i
package. A W T S e rve r also implements the R e m o te A W T interface shown in Figure 54.1. A server class must do the
following four things, as referenced in Figure 54.2 with the associated letter identifier:
A. Define a constructor that throws ja va .rm i.R e m o te E x ce p tio nn.

B. Instantiate with the new operator a local server class object.

C. Invoke the N a m in g .re b in d () function, passing a reference to the local server object.

D. Provide implementations for each of the functions declared in the remote interface.

S te p T h re e : T h e C lie n t
Without going into too much explanation yet as to the purpose of the curious N a m in g .re b in d () function call, let me first
describe the A W T C lie n t remote class implementation shown in Figure 54.3. The m a in () function of the A W T C lie n t begins
by setting up a security manager. Because a client site may load an untrusted object, it should have a security manager
installed to prevent a malicious or buggy object from wreaking havoc on your local machine. Java's default security manager,
R M IS e cu rityM a n a g e rr, should suffice, but you can plug in a third-party or homegrown security manager.

F ig u re 54.3: The AWTClient RMI class uses a remote reference to the AWTServer class.

Before an A W T C lie n t object can invoke a method from its associated remote A W T S e rve r object, it first has to obtain a
reference to the A W T S e rve r object that was instantiated on the host machine. To do this, you use the RMI N a m in g class
again, but this time, rather than invoking re b in d ()
(), you invoke the lo o ku p () function. The version of A W T C lie n t in Figure 54.3
was written to run on the same machine as the server, so the parameter to the N a m in g .lo o ku p () function is different than it
would be when connecting to another machine over the Internet. When the AS/400 port of Java 1.1.1 is solid, you will need to
insert your AS/400's URL address as the parameter to the N a m in g .lo o ku p () function.

The R e m o te A W T class name contained within parentheses and preceding the N a m in g .lo o ku p () call is what is known to C,
Java, and C++ programmers as a cast. The return parameter from N a m in g .lo o ku p () returns an ambiguous object type that is
then dynamically typecast, or has its object type converted by the compiler, to the R e m o te A W T interface class. As you can
now see, A W T C lie n t uses your big RMI hook—the R e m o te A W T interface.

Notice in Figure 54.3 that the receipt and use of the R e m o te A W T interface class is enclosed within a TRY block. A TRY
block is similar to a MONMSG statement in a CL program. The CATCH block following the TRY block is like the DO portion of
that MONMSG statement. If communication errors occur during the execution of the code within the TRY block, the CATCH
block's code will execute.

S te p F o u r: C o m p ilatio n
I have been deliberately vague in my description of the N a m in g class calls to its re b in d () and lo o ku p () functions thus far, but
I will clarify things in a minute. For the time being, and now that the example RMI classes are fleshed out, it is time to
compile them. (The three Java sources are available on this book's companion CD.) Set your current directory to wherever you
downloaded the RMI example class definitions and change your CLASSPATH to include the path to that same directory. The
following DOS calls to the Java compiler will then create the Java class files:
javac.exe -d . RemoteAWT.java
javac.exe -d . AWTServer.java
javac.exe -d . AWTClient.java

The hyphen, letter d, space, and period tell the Java compiler to generate the classes relative to the current directory. Note
that because of the package statement in the Java source files, the class files will be generated in a subdirectory in the
current directory with the same name as the package. For instance, if your current directory is C :\Ja va \rm ico d ee, then, after
compilation, the A W T S e rve r class of the package d e n o n co u rt will be under a directory called
C :\Ja va \rm ico d e \d e n o n co u rt.

S te p F iv e : S tu b s A n d S ke le to n s
Once the RMI application class files are created, the next step is to use the Remote Method Interface Compiler (RMIC) utility
(rm
rm ic.e x e for Windows and UNIX and the RMIC command on the AS/400) to generate stub and skeleton classes. Stubs and
skeletons sounds like a vaudeville act, but they are actually utility classes that are magically generated by the RMIC utility to
provide the complex implementation of marshaling, demarshaling, and transmittal of objects. All you need to know is how to
run the RMIC utility over the server RMI class. All the time and effort I put into learning TCP sockets and RPC network
programming goes out the window; RMI now does it all for me with the following simple command:
rmic.exe -d . denoncourt.AWTServer

This Java command, as executed from within a DOS window, generates an A W T S e rve r_S ke l.cla ss and an
A W T S e rve r_S tu b .cla ss in the d e n o n co u rt subdirectory. The stub class is for use by the remote client site (in this case,
your PC masquerading as the AS/400), and the skeleton class is for use by the host server site (again, your PC). You never
explicitly reference these classes; that is done internally by the RMI Registry, RMI's real engine.

S te p S ix : T h e R M I R e g istry
At this point, you have all the code necessary to execute your RMI application. All the TCP sockets code required to do the
communications between the remote and server sites is done for you through a Java utility known as the RMI Registry. This
registry is started with sta rt rm ire g istry in Windows, rm ire g istry & in UNIX, and the RMIRGSTY command on your AS/400.
Note that in Windows, the RMI Registry is started in a separate DOS window, which is minimized and left alone. In UNIX, the
ampersand (&) makes the RMI Registry run as a background task, and on the AS/400, the RMI Registry submits itself to run
as a batch job.

Once started, the server-based RMI Registry handles requests from remote sites to start and coordinate distributed OO
computing. Remember the call to N a m in g .re b in d () in the A W T S e rve r class and the call to N a m in g .lo o ku p () in the
A W T C lie n t class? The A W T S e rve r class's call to N a m in g .re b in d ("/A W T S e rve r", a w t) tells the RMI Registry to add the
instantiation of the A W T S e rve r class, referenced with the object a w t, to a list of class objects available for remote
invocation. The A W T S e rve r class is accessed by requests based on the string /A W T S e rve rr. Requests for access to the
host A W T S e rve r class come in the following form:
Naming.lookup("//hostURL/AWTServer")

The A W T C lie n t class was implemented as a Java application to run outside of a Web browser. An applet version would have
invoked the following N a m in g .lo o ku p () function to get the URL based on the location of the host code from where the
executing class, perhaps called A W T C lie n tA p p le t, was downloaded:
Naming.lookup("//"+getCodeBase()+getHost()+"/AWTServer");

S te p S e v e n : S e rv ice W ith C lass


Everything is set up and ready. An RMI interface has been developed and implemented as a server class. You've coded a
client class to retrieve a reference to the RMI server class. You've compiled the Java code to create classes and created
stubs and skeletons with the RMIC utility. The RMI Registry is running on the host machine. Nothing is left to do but run the
application. An RMI application is enabled by first starting the server class on the host computer with the following code:
java denoncourt.AWTServer

Don't forget to set up your CLASSPATH to point to the directory that contains the RMI classes. Remember that you must
also set your CLASSPATH for each new DOS window. The call to the Java program invokes the public m a in () function of the
A W T S e rve r class. Remember that the m a in () function of A W T S e rve r is coded to call N a m in g .re b in d () and pass its own
instance of the A W T S e rve r object. This tells the RMI Registry to await requests for A W T S e rve r object method invocations.
The DOS window will be dedicated to the Java execution of the A W T S e rve r class (see Figure 54.4).
F ig u re 54.4: Before a client can remotely access an RMI object, a server must instantiate it.

S te p E ig h t: C lassy C lie n te le
Finally, you invoke your RMI application by starting the client class in another DOS window with the following code:
java denoncourt.AWTClient

This call to the Java program invokes the public m a in () function of the A W T C lie n t class. Again, remember that the m a in ()
function of A W T C lie n t is coded to retrieve a reference to a R e m o te A W T object from a call to N a m in g .lo o ku p () with the two
parameters: the address of the host machine and the name of the RMI server class (AA W T S e rve rr). N a m in g .lo o ku p (),
working behind the scenes, invokes the stub class, which then requests the RMI Registry running on the host machine to
search for a reference to the host RMI object. The remote object reference that is returned from N a m in g .lo o ku p () and stored
in the class object variable a w t may then be used for RMI. In Figure 54.3, the statement S trin g m e ssa g e =
a w t.cre a te A W T F ra m e (); asks the host server to create an AWT window frame, the result of which is shown in Figure 54.5,
and retrieve a S trin g object sent back from the host.

F ig u re 54.5: As a curiosity, my RMI test remotely invokes an AWT Frame.

When the client RMI object runs from your AS/400 as I originally intended, this example will be even cooler. When you close
the frame, the A W T S e rve r class sends a notification to the A W T S e rve rL iste n e r class (Figure 54.2) that was instantiated
and registered as a window listener in the m a in () function of A W T S e rve rr.

Team-Fly
Team-Fly

R M I D e p lo y m e n t C o n sid e ratio n s
There you have it—RMI in eight steps. For simplicity's sake, this RMI implementation did not define any functions that
returned complex objects. Keep in mind that the ability to perform distributed OO applications is a major feature of RMI. Also,
be aware that, for an object to be transmittable via RMI, it must be serializable. Serialization is the Java mechanism that
enables an object to save itself to a file or transmit itself across a network. Fortunately, all basic Java classes are already
serializable, and making your own classes serializable is a straightforward process.

Team-Fly
Team-Fly

R u n n in g T h e R M I S e rv e r A s A B atch P ro ce ss
Since rm ire g istry is a server process that produces no output, it would be ideal to be able to run this command in batch
mode instead of from the Qshell command line. I asked Walter Goodwin how this was possible, and the information in this
section is his response.

Using a Qshell script, it is possible to start your RMI service with a single Submit Job (SBMJOB) command. First, add the
following Qshell script code to a file in your AS/400 IFS "home" directory (I've saved mine to /h o m e /w a lte r/ru n re g .sh
.sh):
#!/usr/bin/sh
export CLASSPATH=.:/qibm/ProdData/HTTP/Public/jt400/lib/jt400.jar:
export QIBM_MULTI_THREADED=Y
rmiregistry 1099 &

The e x p o rt command causes the QIBM_MULTI_THREADED environment variable to be used in processes subsequently
started by the script. This variable must be set to the value Y in order to run Java programs. The next line invokes the
rm ire g istry command. The trailing ampersand on this command tells Qshell to run the command asynchronously and, in
effect, causes it to create a new process that uses the environment variable just set.

You can now invoke this command from a CL command line like this:
STRQSH CMD('/home/walter/runreg.sh')

This step will start the server, but, unfortunately, it will hang your interactive session. It gets hung up because Qshell waits
patiently for the rm ire g istry command to end. Because it is a server process, however, rm ire g istry does not end without
being forcefully interrupted. S ysR e q 2 will end the command and give you your CL command line back. You should submit
the command to batch with a SBMJOB command similar to the following:
SBMJOB CMD(STRQSH CMD('/home/walter/runreg.sh')) JOB(RMIREGSTRY)

Here, I've named the batch job something familiar with the JOB parameter, so I'll be able to find it in a Work with Active Job
(WRKACTJOB) display later. If I want to end the server later, I'll simply do an ENDJOB. Note, however, that since rm ire g istry
is a Java program, it may create other "thread" jobs. When ending the server, these thread jobs need to be forcefully removed
with ENDJOB as well.

Team-Fly
Team-Fly

R e aso n s T o U se R M I
There are a number of reasons to use RMI-speed, security, object distribution, and support for legacy applications are the first
that come to mind. For Web applications, in which classes are continually being downloaded to the remote sites, the
download time for complex Java objects can become unacceptable. By converting the application to RMI, much of the
complexity of the object model can remain on the host. The client classes that are downloaded via RMI are then considerably
smaller because the code implementation of functions invoked from the remote sites now resides on the host machine. By
leaving application code on the host site, you also improve security by removing the possibility that the class's Java byte code
might be disassembled by unscrupulous programmers.

When you are considering object distribution strategies, take into account that RMI has advantages over other RPC systems
such as Distributed Computing Environment (DCE), Distributed Component Object Model (DCOM), and CORBA because they
cannot download and execute implementations. This limitation stems from the fact that they cannot pass real objects as
arguments, only data. Finally, because it is a Java-to-Java implementation, RMI is often dismissed as a solution for the
integration with legacy host applications. This is a mistake, because RMI has direct support for the connection to legacy
applications with Java Native Interface (JNI). You can write Java RMI classes, the functions of which are implemented with JNI-
compliant ILE/C calls to your legacy application programs. JNI is available on the AS/400 port of Java 1.1.

Java has advanced far beyond being a tool used simply to jazz up Web sites. Java 1.1 brought many new features, not the
least of which is RMI. With RMI, Java enables the seamless distribution of Java objects across intranets and the Internet. RMI
does compete with technologies such as CORBA, but for basic Java-to-Java applications, RMI is the clear winner because of
its ease of use and seamless object distribution.

Team-Fly
Team-Fly

S ectio n X : O d d s A n d E n d s
C h ap te r L ist
Chapter 55: Soft-Coding Values For Java Applications

Chapter 56: Java Source Level Debugger For The As/400

Chapter 57: Deliver Your Programs With Java Message Service

Chapter 58: How To Build Opsnav Java Plug-Ins

Chapter 59: Java Packaging

P art O v e rv ie w
There are a number of Java technologies that didn't cleanly fit into any of the other sections in this book yet are important
enough for inclusion. In the chapters in Section III, "JDBC: SQL for Java," it was mentioned that the JDBC driver name should
be soft-coded. How do you soft-code anything in a Java application? The answer is Java p ro p e rtie s files. In my real-world
business applications, I use Java p ro p e rtie s files extensively. But in code developed for articles and books, I leave out the
use of p ro p e rtie s files because their code obfuscates the purpose of the code that provides a tutorial on a specific Java
technology. But in "Soft-coding Values for Java Applications," the specific Java technology is Java p ro p e rtie s files.

I rarely compile, much less debug, my Java applications on the AS/400. I use an integrated development environment (IDE) on
NT or Linux for compilation, testing, and debugging. Then, once the application works on my PC, I transfer the Java class
code to the AS/400. Sometimes, what works on the PC doesn't work on the AS/400, and you need to know how to debug
Java from OS/400. This is covered in "Java Source Level Debugger for the AS/400."

Section V, "Legacy Interoperability," provides instructions for invoking RPG and COBOL using a variety of methods: data
queues, Java Native Interface, program calls, and stored procedures. Data queues are an example of what is known as
message-oriented middleware (MOM). Data queues are decidedly OS/400-specific, and if you want to write completely cross-
platform code, then you need to consider Sun's MOM strategy that Jeff Markham covers in "Deliver Your Programs with Java
Message Service."

I no longer teach Java GUI programming at Java seminars unless coerced. That's because the use of a GUI adds 20 to 60
percent more complexity to your application when compared with the simple HTML interface of server-side Java. Plus, the
screen I/O of server-side Java is analogous to green-screen I/O, thus easier for OS/400 programmers to get started with.
Shannon O'Donnell, however, disagrees with me. He feels there is a big requirement for Java GUIs. Perhaps Shannon is right,
but then he is an expert on OS/400's Operations Navigator. Shannon has written numerous GUIs for Operations Navigator
using the techniques he explains in "How to Build OpsNav Java Plug-ins."

The last technology covered in this section is Java packages. The biggest problem OS/400 programmers have with testing
Java applications is setting their CLASSPATH. You see, your Java applications use packages of Java classes that exist on
various directories, and, at runtime, those packages have to be in your Java Virtual Machine's CLASSPATH environment
variable for their classes to be accessible. Galen Tucker takes some of the mystery out of the CLASSPATH and Java
packages with "Java Packaging."

Team-Fly
Team-Fly

C h ap ter 55: S o ft
ft--C o d in g V alu es F o r Java A p p licatio n s
O v e rv ie w
DON DENONCOURT

The Java seminar that I teach for Midrange Computing includes a hands-on lab that requires attendees to load a PC-based
relational database onto their laptops, create and populate a file, and then write a JDBC application to list the contents of their
database file. Later, they load Sun's JavaServer Web Development Kit (JSWDK) and then write a Java servlet that, once
again, lists the contents of their database file, but this time via HTML as delivered from a Web server to a Web browser.

The seminar attendees enjoy the exercise, but they don't get too excited until I take one of the attendee's servlets, copy it to
the AS/400, copy their database file to DB2 for OS/400, and then access the PC-developed (but now AS/400-based) Java
servlet from a Web browser. Do they get excited because they see a program that was developed and tested on a PC run on
the AS/400 without modification or recompilation ? Well, almost. You see, I always have to modify the attendee's Java servlet
to change the registration of the JDBC driver name and the open of an SQL connection from
DriverManager.registerDriver(
new com.imaginary.sql.msql.MsqlDriver());
Connection con = DriverManager.getConnection (
"jdbc:msql://127.0.0.1:1114/denoncourt");

to the following:
DriverManager.registerDriver(
new com.ibm.as400.access.AS400JDBCDriver());
Connection con = DriverManager.getConnection (
"jdbc:as400://207.212.90.55");

Those manual code changes are certainly not exemplary of cross-platform programming. The proper way to write cross-
platform Java code is to soft-code the JDBC driver name and the SQL server's URL through the use of a standard Java class
called P ro p e rtie ss. In a moment, I'm going to show you how to use the P ro p e rtie s class, but, before I do that, I need to show
you an alternative method of registering the JDBC driver. You see, the D rive rM a n a g e r class's re g iste rD rive r method all but
forces you to hard-code the name of a JDBC driver. The "better" way of registering the driver is to pass the name of the JDBC
driver to the C la ss class's fo rN a m e method:
try {
Class.forName("com.ibm.as400.access.AS400JDBCDriver ");
} catch( ClassNotFoundException e) {
System.out.println(e);
}

And because the fo rN a m e method takes a String, you can soft-code the driver name. Note that the fo rN a m e method must
be enclosed in a TRY/CATCH block to monitor and handle the C la ssN o tF o u n d E x ce p tio nn.

Team-Fly
Team-Fly

IN I F ile s
With Microsoft Windows, when you want to soft-code properties for an application, you use .in i files. Most of you are
probably familiar with the infamous w in .in i and syste m .in i files. The structure of Microsoft's .in i files is simple: Properties are
set as textual name/value pairs. For instance, the following line from my syste m .in i file sets my display driver to a specific
device:
display.drv=NeoMagic MagicGraph 128XD

Java has something comparable to Microsoft's .in i files: p ro p e rtie s files. WebSphere, for instance, has a p ro p e rtie s file
called jvm .p ro p e rtie ss. In that file, you set the value of the n cf.jvm .cla ssp a th property with a Java CLASSPATH that includes
the Java archives required by your applications.

But back to my JDBC driver problem. Java p ro p e rtie s files work great for soft-coding things such as JDBC driver names and
SQL server URLs. Figure 55.1 shows a p ro p e rtie s file that I use to soft-code the name of the AS/400's native JDBC driver.
Notice that it also soft-codes a few other properties such as the user profile name, password, and even a library list (which
should always be soft-coded).

F ig u re 55.1: Java's alternative to Microsoft .ini files are properties files.

Team-Fly
Team-Fly

Jav a IN I F ile s
So, how does a Java class read values from these p ro p e rtie s files? With the use of Java's P ro p e rtie s class. The P ro p e rtie s
class has a method called g e tP ro p e rty that allows your Java application to pull the value out of a p ro p e rtie s file based on
the name of a property as specified in the name/value pair. For instance, to pull the name of the JDBC driver specified in my
p ro p e rtie s file, I use the following statement:
String jdbcDriver = jdbcProps.getProperty("JDBCDriver");

But before I could pull that value, I had to create the jd b cP ro p s P ro p e rtie s object:
Properties jdbcProps = new Properties();

Then I had to associate the P ro p e rtie s object with an external file using the F ile In p u tS tre a m from the ja va .io package:
FileInputStream input = new FileInputStream("JDBC.properties");

The P ro p e rtie s object (as referenced with the variable called jd b cP ro p ss) will then be able to read all the name/value pairs
stored in the p ro p e rtie s text file with its load method:
jdbcProps.load(input);

Team-Fly
Team-Fly

S tan d ard JD B C P ro p e rtie s


My example Java application, U sin g JD B C P ro p e rtie ss, shown in Figure 55.2, opens a JDBC connection to whatever system is
specified as the property called ip in the file called JD B C .p ro p e rtie ss. The U sin g JD B C P ro p e rtie s class's m a in method
creates a P ro p e rtie s object, associates it with the JD B C .p ro p e rtie s file, and then invokes the application's constructor to
load the JDBC driver that is soft-coded in the p ro p e rtie s file. Finally, the U sin g JD B C P ro p e rtie s class lists all the records in
the QCUSTCDT file with a call to the listQ C U S T C D T method (the results of which are shown in Figure 55.3).

   

F ig u re 55.2: JDBC applications should be made cross-platform by soft-coding their JDBC driver names and the SQL
server's subprotocol and IP .
F ig u re 55.3: The UsingJDBCProperties class uses two different JDBC drivers that were soft-coded to a properties file and
a custom Properties class.

Soft-coding JDBC drivers requires more than just specifying the driver name. Each JDBC driver requires a specific subprotocol
in the SQL server's URL. The subprotocol is soft-coded in my p ro p e rtie s file along with the IP, user, password, block size,
and library list. You could stuff all those JDBC property settings into the URL string, but there is an easier way. The
D rive rM a n a g e r class has an overloaded g e tC o n n e ctio n method that accepts two parameters: a S trin g object that is to
contain the URL of the SQL server and a P ro p e rtie s object, which is used to specify JDBC property settings. The P ro p e rtie s
object can contain values for a number of standard properties such as user, password, prompt, libraries, and block size. The
following statement shows how the constructor method of U sin g JD B C P ro p e rtie s sets its soft-coded subprotocol and IP in
the URL S trin g object parameter and then the user, password, library list, and block size in the P ro p e rtie s object parameter:
DriverManager.getConnection (
"jdbc:" + subprotocol + ":" + ip, jdbcProps);

Team-Fly
Team-Fly

P u re V s. N ativ e D riv e rs
If you look at the m a in method of my U sin g JD B C P ro p e rtie s application, you will notice that, after it lists the Customer
database file once, it lists the contents of the Customer file a second time. However, with this second pass, it constructs the
U sin g JD B C P ro p e rtie s object in a completely different strategy:
UsingJDBCProperties testAgain =
new UsingJDBCProperties(new JDBCProperties());

This iteration of the constructor, however, does not use a P ro p e rtie s object that loads property values from a text file.
Instead, it is passed an object of the custom P ro p e rtie s class called JD B C P ro p e rtie ss, the code for which is shown in Figure
55.4. I created the JD B C P ro p e rtie s class to illustrate another strategy for soft-coding application configuration settings. The
class simply uses the p u t method inherited from the ja va .u til.P ro p e rtie s class to set the values for my application's JDBC
driver, SQL server IP, and the other JDBC properties. No text file is required.

F ig u re 55.4: Custom Properties classes can be shipped as a part of an application's .jar file to soft-code its
configuration.

Team-Fly
Team-Fly

100 P e rce n t C ro ss
ss--P latfo rm
There are a lot of reasons for soft-coding application configuration information. One of the biggest reasons is to make your
Java code truly cross-platform. Take a look again at the property setting for the JDBC driver in Figure 55.1 and Figure 55.4.
Notice that the driver in the p ro p e rtie s file of Figure 55.1 is called co m .ib m .d b 2.jd b c.a p p .D B 2D rive r and the driver in the
P ro p e rtie s class of Figure 55.4 is called co m .ib m .a s400.a cce ss.A S 400JD B C D rive r.

The first driver is called a native JDBC driver because it was optimized for the host platform (and it is not implemented all in
Java). The second driver is known as a pure driver because it is certified as 100% Pure Java. The long and the short of these
two AS/400 JDBC drivers is that, for performance, you should use the native driver when your Java application is running on an
AS/400 and use the pure Java driver when you are on any other platform. And to soft-code the JDBC driver, you should use
Java's P ro p e rtie s class and p ro p e rtie s files.

Team-Fly
Team-Fly

N o te p ad /400
Editing text files-such as Java p ro p e rtie s files-that are located on the AS/400 IFS can be problematic. For the longest time, I
was editing my AS/400 IFS files with Windows Notepad. But for Notepad to be able to open the file, it must be downloaded to
my PC. The AS/400 has been shipping with the source for an ASCII text editor called EDTF for several releases. The problem,
though, is that you need a C compiler to create the EDTF utility. But with V4R4, EDTF began shipping in a compiled and
runnable form. To test the EDTF command, I selected an HTML file:
edtf '/html/HelloWorld.html'

The user interface of Edit File's 5250 display panel (shown in Figure 55.5) will remind PC DOS programmers of the old EDLIN
utility. The prompt column to the left of the text supports options such as add, move, and delete. Text can also be directly
updated on the screen.

F ig u re 55.5: OS/400's Edit File command allows you to edit an ASCII IFS-based file on your AS/400.

EDTF can be used on any of the ASCII files located in the AS/400 IFS. I've found EDTF to be a useful utility for displaying and
modifying the WebSphere's configuration parameters that are stored in text-based (.in
.in ii-like) p ro p e rtie s files.

Team-Fly
Team-Fly

M y P ro p e rty Is Y o u r P ro p e rty
From now on in my Java seminars, I plan to first modify my attendees' Java code to use a p ro p e rtie s file before I take their
JDBC application and move it to the AS/400. Then, I'll rerun the Java application, again from the PC, to access the same local
relational database. Next, I'll copy the .c la ss file, unmodified, to Midrange Computing's AS/400 along with the p ro p e rtie s file.
But, once the p ro p e rtie s file is on the AS/400, I'll modify its IP address, JDBC driver name, subprotocol, user name, and
password. Finally, I'll run the unmodified .c la ss file and woo my Java seminar attendees with the elegance and simplicity of
cross-platform Java programming.

Team-Fly
Team-Fly

C h ap ter 56: Java S o u rce L evel D eb u g g er F o r T h e A S /400


O v e rv ie w
DON DENONCOURT

I do most of my debugging from a PC. Because my Java classes run just as well on a PC as they do on an AS/400, I'd rather
debug using the integrated debugger of one of my Java integrated development environments (IDEs). Sometimes, however,
you just have to see what's gone awry with Java code that, for some inexplicable reason, runs well on a PC but not on an
AS/400. Thankfully, the same AS/400's Integrated Source Level Debugger (ISDB) that you use to debug your RPG programs
can also be used to debug your Java classes. The AS/400's ISDB has long supported multiple languages.

A few years ago, I produced a video for Midrange Computing called "Interactive ILE Debugging" (mc-store.com/mc-
store/iniledeb.html). In that video, I show how you can debug not just RPG but also COBOL, CL, and even C programs. The
fact that ISDB supports the complexity of a free-format pointer-based language such as C suggests why IBM was able to
easily tweak it to support Java.

Team-Fly
Team-Fly

C ro ss
ss--P latfo rm C o m p ile r O p tio n s
Figure 56.1 shows the source for a Java application called U sin g JD B C P ro p e rtie s (which I covered in detail in Chapter 55,
"Soft-coding Values for Java Applications"). The figure shows the application at a breakpoint at line number 17. Also note that
the contents of the String object variable called jd b cD rive r are displayed at the bottom of the screen.

F ig u re 56.1: The same source level debugger that you use on RPG can be used to debug your Java
applications.

Figure 56.1 shows where you want to get, so how do you get there? Here's a summary: Compile your Java with the DEBUG
option, make sure the Java source is in the same directory as the Java class, and use the RUNJVA command specifying the
option to debug:
RUNJVA CLASS('UsingJDBCProperties') OPTION(*DEBUG)

But before you can debug a Java class from ISDB, you need to be sure that the Java class was compiled with debugging
information. The Java Development Kit's compiler command, ja va cc, has a -g option that forces the Java compiler to generate
debugging information:
javac -g UsingJDBCProperties.java

When this option is not selected, the compiler generates tighter code, much as the AS/400's RPG compiler does.

The first time I debugged a Java class from the AS/400, I thought that I had to perform the Java compile from the AS/400 in
the Qshell environment. Not true. I was amazed to find that, as long as the Java class was created with the -g option,
regardless of the platform and environment that it was created on, you could debug that class from within the AS/400's ISDB.
Note that all IDEs provide some sort of a compiler options panel where you can set the DEBUG option on. In fact, I compiled
the example application on Windows 95 using Symantec's Visual Café and then copied the .c la ss and .ja va files to the
AS/400 IFS, at which time I was able to immediately debug the application.

Team-Fly
Team-Fly

S tart T h e In te g rate d S o u rce L e v e l D e b u g g e r


Unlike with RPG applications, you don't use the Start Integrated Source Level Debugger (STRISDB) command to debug a
Java app. Instead, you use the Run Java (RUNJVA) command specifying the OPTION(*DEBUG) and the name of the Java
class you wish to debug:
RUNJVA CLASS('UsingJDBCProperties') OPTION(*DEBUG)

The RUNJVA command sets up the debugging environment and then pops your Java source up in the Display Module Source
panel, as shown in Figure 56.1. Note that you need to be sure that the Java class is available in the classpath specified in the
CLASSPATH option of the RUNJVA command or that it is in the current AS/400 IFS directory. When your Java code appears
in the Display Module Source panel, you can scroll through the source and set breakpoints. Remember, breakpoints can be
set by positioning the cursor over a statement and pressing F6 or by keying in the BREAK (or the abbreviation BR) command
from the Debug prompt followed by the statement number. Statements that have been set as breakpoints have their
statement number highlighted in the Display Module Source panel.

To execute your application, use the F12 key. Don't be alarmed when the panel that shows your Java source code disappears
as the Qshell execution environment pops up. Your Java application's source will pop back up when it hits one of the
breakpoints that you set. Once a break is hit, the source will be positioned to display the appropriate section of code and the
statement at breakpoint will be highlighted. From there, you can display program variables either by positioning the cursor to
a variable and pressing F11 or by keying in EVAL (or EV for short) and the variable name on the Debug command line.

I always opt to debug my Java from one of the powerful GUI-based integrated development environments available on my PC.
(I have IBM's VisualAge for Java, Symantec's Visual Café, and Borland's JBuilder, all of which are equally good at debugging.)
Sometimes, however, I have to see why something isn't working on the AS/400 that works fine from my PC. At those times,
I'm more than happy to work with the character-based user interface of the AS/400's Integrated Source Level Debugger.

Team-Fly
Team-Fly

C h ap ter 57: D eliver Y o u r P ro g ram s W ith Java M essag e S ervice


O v e rv ie w
JEFF MARKHAM

Chances are, if you've ever been part of a project that involved two or more widely different systems, you've at least done
some homework on messaging systems. Products that provide messaging services to your applications are also known as
message-oriented middleware (MOM). Ideally, these products allow applications of different pedigrees to communicate with
each other regardless of operating system, database, or development language. With this cross-platform purpose in mind, it's
no wonder that Java has its answer for messaging: Java Message Service (JMS). This chapter looks under the JMS hood to
see what it has to offer developers.

First of all, some of you might be wondering, if Java is a cross-platform development language, why wouldn't a developer
simply rewrite an RPG or COBOL application rather than slap some Java component onto it with JMS? The answer,
grasshopper, is that for larger shops with a heavy investment in ERP software or other purchased and homegrown software of
advanced nature, there isn't a need to throw the baby out with the bathwater. You don't have to rewrite your applications just
because they aren't written in Java.

Team-Fly
Team-Fly

L e g acy In te ro p e rab ility


One of the things I run into quite often these days is that people automatically assume that if an application is written in RPG,
it can't possibly be full-featured or advanced enough for today's needs. I know if you're reading this book, I'm probably
preaching to the choir, but that thinking is, of course, simply wrong. Even if you do decide that rewriting an application in Java
is the way to go, chances are that, in today's networked environment, you'll have to tie together files and programs across a
complex network. And networks fail from time to time. If and when they do, incorporating messaging into your applications will
ease the pain of those failures. Lastly, messaging products assist in balancing the load of system requirements in a
networked application. If, for example, your JDBC- powered servlet has a hard time keeping up with demand during peak
processing times, an option would be to queue some of those SQL transactions as XML documents in a message queue to
be processed later rather than synchronously.

So, what if you do actually have applications that work quite well on your AS/400 and are mulling over the many different ways
that will let your native applications work in the networked world of e-commerce? You could take the poor man's route and buy
a browser plug-in or an applet that would act as a screen-scraper. But if you don't want to look like a legacy shop trying to
play Internet, you'll probably scrap that idea. You could rewrite everything even though your existing software works just like
you want it to. But if you don't have the budget of OPEC and the patience of Job, you'll probably scrap that idea too. A happy
medium to consider is tying that software with Java Web components such as servlets and JavaServer Pages using JMS.

Team-Fly
Team-Fly

M O M S ay s S u b scrib e T o JM S
JMS is one of the several server-side technologies that make up the Java 2 Enterprise Edition (J2EE) platform. JMS, like
JDBC, is a specification, not a product. That means that Sun Microsystems sets forth the rules governing what products must
feature if they are to be considered as implementing JMS. Like all MOM products, JMS exchanges messages of defined
format between applications. These messages are not meant to be used by you or me; they're meant for the use of the
applications that are tied together by the MOM. Messages in JMS are asynchronous in nature and represent virtually any
programmatic event you can imagine, like signaling the end of a batch program or encapsulating data entry information.

JMS defines two basic types of messaging: point-to-point and publish/subscribe. For those of you with data queue
experience, point-to-point won't be too hard to grasp. Simply put, it means that the JMS provider sends messages to
message queues. Clients then pick up their messages at their specified message queue. Publish/subscribe is a little harder
to explain with words but an easy concept to grasp. Clients dynamically send or receive messages to a predetermined logical
node called a topic, and the JMS provider handles the distribution to all interested parties. A classic example of this is a chat
room. Everybody publishes their comments, and everybody else immediately sees those comments.

Team-Fly
Team-Fly

D isse ctio n O f A M e ssag e


According to the JMS specification, messages are made up of three different parts: the header, user-supplied properties, and
the body. In addition, there are provisions for five different types of message bodies:

 Bytes.

 Map.

 Object.

 Stream.

 Text.

B y te s
A bytes message is a message of bytes that, presumably, you the developer have encoded yourself (probably with the help of
Java's ability to encode data into various formats such as ASCII or EBCDIC). Most of you will probably never use this
message type, but it exists for those who like to roll their own encoding and decoding in their programs.

M ap
A message with a map body is similar to a Java hash table in that the body contains name/value pairs. The name is a Java
string, and the value is a primitive type (e.g., an int, double, or long).

O b je ct an d S tre am
An object message body is simply a message with any serializable Java object, and a stream body type contains a stream of
Java primitive types that are accessed sequentially, unlike the map message.

Text
The text message represents an interesting capability of JMS. A text message is capable of encapsulating XML-formatted
data because a text message contains the value of a Java string. XML is to data what Java is to programming: It provides a
cross-platform manner in which to represent your data. The documentation for JMS even says that the text message was
created with the idea that developers would use it to transport data formatted in XML, thereby creating a conduit between
dissimilar systems by moving portable data across those systems.

Team-Fly
Team-Fly

G e t T h e M e ssag e
I'll show you an example of how JMS and XML can be used in your Web applications. (The entire example is available on this
book's companion CD. Follow the instructions in the accompanying re a d m e .d o c file to see the example in action.) The heart
of the example is two servlets: one that sends XML-formatted text messages to a JMS-compliant messaging product and
another that receives the message, parses it out into parameters of a JDBC prepared statement, and performs the database
update. The example uses ye olde QIWS/QCUSTCDT file (available on most AS/400s), so that you can try this out in your
spare time.

The static HTML page in Figure 57.1 displays a form for a user to enter information about a new customer. When the user
presses the Submit button, the information in the form is posted to the S e n d N e w C u sto m e r servlet. I had that servlet mapped
to e b iz/se n d C u sto m e r while testing it out, which is why that mapped name is the ACTION of the POST.

F ig u re 57.1: This form includes input data to be transformed into an XML- formatted message.

If the servlet engine isn't configured to start this particular servlet when the engine starts, the servlet will start when the first
request for its services is made, meaning the first time somebody enters a new customer. Remembering what you've learned
about servlets, you know that when a servlet starts, the in it() method of the servlet is called by the servlet engine. It's good
practice to place code that you'd like to execute only once inside this method. In the case of the example, this is where you'll
want to connect to a JMS provider.

Team-Fly
Team-Fly

M e ssag e G e n e sis
Figure 57.2, Label A, shows the code needed to get that connection. The first thing that you need to do is get a Java Naming
and Directory Interface (JNDI) C o n te x t. In a nutshell, JNDI provides a way to look up services in a network. Using my
example, you need to get a messaging service. I've used some properties that are specific to the JMS-compliant product I
used to test the example with (see the "Closed and Open-source Choices" section for more information on vendor-specific
properties). I use JNDI not only to find a messaging service on a network but also to find a Q u e u e (in the case of point-to-
point messaging) and something called a Q u e u e C o n n e ctio n F a cto ry ry. Take a look at the code. Once you get past the long
names for everything, you'll see that setting things up to send messages to a Q u e u e is quite simple. Using Old Testament-
speak (I'm writing this on a Sunday), Q u e u e C o n n e ctio n F a cto ry begat q u e u e S e ssio nn, which begat q u e u e S e n d e rr. When
the q u e u e S e n d e r object is instantiated, you use its sta rt() method to finalize the steps needed to set up sending a
message.

 
F ig u re 57.2: These are code snippets of the example on the CD .

Figure 57.3 shows what the XML would look like if you used the message for human-readable purposes. As many of you
know by now, XML is platform- neutral data, which melds quite nicely not only with the concept of Java but with messaging in
general. To get this type of message from HTML input, I used the packages available in the reference implementation of Java
APIs for XML Parsing (JAXP) from Sun. I also used additional XML parsing APIs from Sun called Project X.

F ig u re 57.3: This example XML describes both the structure of the data contained therein and the content of a specific
customer.

If you're familiar with handling XML with Java, you know that there is a cornucopia of tools available for a developer working
with XML. Apache's Xerces, IBM's XML4J, and JDOM are just a few. These days, everywhere you turn, somebody is claiming
a better way to programmatically manipulate XML documents.

After transforming the XML document you've generated from the HTML input into a String object, you simply instantiate a new
T e x tM e ssa g e object, set its text as the previously transformed string, and use the se n d () method of the q u e u e S e n d e r with
the String object as the parameter.

Team-Fly
Team-Fly

M e ssag e D e liv e ry
When your messages arrive in the messaging service, the messaging service delivers those messages to the interested
parties-in this case, whoever is listening for messages on your predetermined queue. The messaging product stores your
message in memory or to disk, depending on how you've asked the messaging service to handle your messages. By
specifying that the message be sent as persistent, the messaging service will physically store the message to disk, making
disk failure the only way your messages will not be delivered to their intended parties.

Setting up a servlet to listen for messages on a queue is almost identical to the way you set up a servlet to send messages
to a queue. The biggest difference is shown in Figure 57.2, at Label B, where the servlet implements the M e ssa g e L iste n e r
interface. Recalling Java fundamentals, you know that if you implement an interface, you must declare the methods of that
interface whether you actually use them or not. Since the M e ssa g e L iste n e r interface defines only one method, it doesn't turn
out to be such a chore. The method is the o n M e ssa g e () method, also shown at Label B. The M e ssa g e L iste n e r interface and
the o n M e ssa g e method are basically conveniences that allow a developer to write event-driven code when a message is
received-much the same way a developer writing Swing applications will use A ctio n L iste n e r to know when a user presses a
button on a GUI.

Looking at the code snippet, you instantiate a q u e u e R e ce ive r object rather than a q u e u e S e n d e r object, and you register
the servlet itself as the M e ssa g e L iste n e r using the q u e u e R e ce ive r.se tM e ssa g e L iste n e r() method. The servlet doesn't take
any POST or GET requests or any other client request for that matter. It acts as a background job waiting patiently for
messages to process. It takes in the messages, recreates an XML document, takes out the values between the tags to put
into a JDBC prepared statement, and then inserts a record into the physical file.

If you take the time to run this example, it doesn't matter which servlet you start first or when you start the servlets at all. To
see the concepts behind asynchronous messaging, fire up the S e n d N e w C u sto m e r servlet and add customers to your
heart's content. Then fire up the R e ce ive N e w C u sto m e r servlet and watch the physical file being populated with new records.
The only real requirement is that your messaging service be started before any of this.

Team-Fly
Team-Fly

C lo se d A n d O p e nn--S o u rce C h o ice s


I said I'd talk about vendor-specific properties and now's a good time for that. In running the example, you'll need a product
that implements the JMS specification, now at version 1.0.2. I chose a product called SwiftMQ, which is not an open-source
product but is freely available. I also tried jBoss's SpyderMQ, Progress Software's SonicMQ, and Sun's Java Message Queue.
For this example, you'll want to get up and running as quickly as possible and not fiddle around with arcane configuration
settings. SwiftMQ will give you just that. It has both a GUI and a command line interface. It's pure Java and purports to run on
any platform that supports Java 2, which means that you may even run it on an AS/400, although I did not when I was testing
the example. (SpyderMQ is another pure Java product that also needs the Java 2 platform and therefore could possibly run on
an AS/400.) Also, SwiftMQ implements its own protocol, SMQP, meaning that doing JNDI lookups is much easier than trying
to set up Lightweight Directory Access Protocol, RMI, or other transport services supported by JNDI.

By now, you may be wondering where MQSeries fits in to all of this. If you are, there's good news and bad news. The good
news is that, as a Java developer, you're able to develop applications for MQSeries for the AS/400. The bad news is that you
can't use JMS. As a matter of fact, of the 39 platforms that the MQSeries Web site says it runs on, the AS/400 is the only
platform on which JMS is not supported. Though not compatible with JMS, Java support for MQSeries on the AS/400 comes
in the form of a software package called MQSeries classes for Java. The availability of these classes come as an MQSeries
SupportPac download for version 5.1.

Team-Fly
Team-Fly

M e ssag e S u m m ary
I've touched on a few of the many features of JMS and messaging in general. In my example, I received an XML-formatted
message and parsed the elements into a JDBC prepared statement in order to update a physical file. Those elements could
have been used as parameters to a program call or even sent to another messaging service. In the beginning of the chapter, I
mentioned a few reasons why you'd consider messaging. I'm sure if you spent some time thinking about it, you'd find specific
problems in your shop that could be solved with messaging and JMS.

Team-Fly
Team-Fly

R e fe re n ce s
 IIT GmbH's SwiftMQ Web site: www.swift.com

 jBoss Organization's SpyderMQ Web site: www.ejboss.org

 MQSeries Classes for Java and Java Message Service Web site: www-
4.ibm.com/software/ts/mqseries/txppacs/ma88.html

 MQSeries Messaging Platforms Web site: www-4.ibm.com/software/ts/mqseries/platforms/#mqseries

 Progress Software's SonicMQ Web site: www.progress.com

 Sun Microsystems' Java Message Queue Web site: www.sun.com/forte/jmq/

Team-Fly
Team-Fly

C h ap ter 58: H o w T o B u ild O p sn av Java P lu gg--In s


O v e rv ie w
SHANNON O'DONNELL

Client Access's Operations Navigator (OpsNav) is IBM's graphical interface operations manager to the AS/400 that enables its
users to perform a variety of work management functions such as application administration, database management, and
security configuration. In fact, there's very little in the way of work management on the AS/400 that you can do with a green-
screen interface but cannot do with OpsNav. You can open up OpsNav even further through the use of plug-ins. A plug-in is a
self-contained module that performs a specific function, which you "plug into" the OpsNav GUI. IBM has enabled plug-in
development by building all the hooks to the Windows-based program for you, leaving you the comparatively simple task of
just developing code for your plug-in and attaching it to those hooks.

I'm going to detail the process you need to go through to develop your own plug-in using Java. To use this information, you
need V4R4 of both OS/400 and Client Access Express, and you need modification 2 of the AS/400 Toolbox for Java. (This
version of the toolbox comes standard with V4R4 of OS/400.) You also need the sample plug-in code available from IBM's
Web site at www.as400.ibm.com/clientaccess/toolk it/java.htm.

Team-Fly
Team-Fly

G e ttin g S tarte d
The easiest way to learn how to build your own plug-in is to take an example and modify it to see how it works. IBM has
provided three examples of OpsNav plug-ins in its sample file. When you download the file containing the plug-in sample,
install it to the root (CC :\
:\) directory on your PC.

The downloaded file contains several folders and subfolders, beginning with the parent folder, JV O P N A V . Drill down through
the C :\JV O P N A V folder until you get to the C :\JV O P N A V \C O M \IB M \A S 400\O P N A V \ subfolder. In this subfolder, you'll find
three additional folders labeled M e ssa g e Q u e u e S a m p le 11, M e ssa g e Q u e u e S a m p le 22, and M e ssa g e Q u e u e S a m p le 33. Each
of these folders contains Java code for a particular plug-in sample.

There are several steps to go through to create your own plug-in, and, when you're first learning, they can seem quite
daunting. Hang in there. You'll find that, as you become familiar with all the pieces, they'll soon make sense.

To make things as painless as possible, though, I'll step through the process in a somewhat logical order. I'll first look at the
basic OpsNav interface and then identify the components required for a plug-in. After that, I'll provide the steps to modify the
sample code. To keep things simple, I'll use only the first sample provided by IBM, M e ssa g e Q u e u e S a m p le 11, shown in
Figure 58.1. This plug-in displays a list of messages for the AS/400 user profile logged in with OpsNav and lets you add new
messages to and delete messages from that user's message queue.

F ig u re 58.1: The MessageQueueSample1 plug-in displays message text and the date and time the messages were
created.

Team-Fly
Team-Fly

T h e O p sN av T re e
If you look at the OpsNav GUI, you'll see that it has a treelike interface. The left-hand pane displays all the branches of the
tree. When you click one of these branches to expand it, you can see the leaves of the tree. Clicking a node either displays
additional leaves or displays a list of objects in the right-hand pane of the GUI. All the functions available through the OpsNav
client behave in exactly the same manner.

Every plug-in you create must also conform to this basic framework of the OpsNav GUI. This means that the plug-in must
provide a branch on the OpsNav tree with an icon and a description to identify itself. When the user clicks the icon with the
mouse pointer, it must either expand to display leaves underneath or build a list of objects in the right-hand pane. If a user
right-clicks your plug-in node on the OpsNav tree, it must have the capability of displaying a context menu and then acting on
the user-selected options found there.

Team-Fly
Team-Fly

Id e n tify in g T h e Jav a P ie ce s
To ensure that each of these steps is followed, all plug-ins are broken down into various components. When using Java to
create your plug-in, you have four basic Java classes:

 List Manager-manages the list (i.e., causes a list to be built or rebuilt as items are added or deleted).

 Actions Manager-handles context menu actions, such as adding or deleting.

 Object Details-extracts individual item details.

 Object List Interface-contains logic that builds the list (which is called from the List Manager).

If your particular plug-in requires more functionality, such as the ability to add an item to the list, you'll need to create a Java
class for those functions as well.

In the sample, the components are named M q M e ssa g e sL istM a n a g e r.ja va va, M q A ctio n sM a n a g e r.ja va , M q M e ssa g e .ja va
va,
and M q M e ssa g e Q u e u e .ja va
va. Two additional components are used to add and delete messages:
M q N e w M e ssa g e B e a n .ja va and M q D e le te M e ssa g e B e a n .ja va
va.

Team-Fly
Team-Fly

G U I B u ild e r
In addition to the aforementioned object classes, the sample plug-in contains a couple of Java GUI panels: one to add new
messages to the list and another to confirm the deletion of messages from the list. These interface panels were designed and
generated as PDML files from IBM's GUI Builder utility. Many Java programmers are familiar with PCML, which is a language
defined in XML that was created to ease the difficulty of interfacing with legacy data and applications. Well, PDML is designed
to ease the pain of developing and using Java GUIs.

GUI Builder is a set of Java classes that comes free with modification 2 of the AS/400 Toolbox for Java. Using GUI Builder,
you can design a Java user interface very quickly. Your interface can contain text fields, list windows, trees, buttons, and, in
fact, pretty much any type of GUI component you can think of. After you have developed your GUI panels, GUI Builder
generates PDML source files and (optionally) skeleton Java code and HTML documentation.

Team-Fly
Team-Fly

R e g iste rin g Y o u r P lu gg--In


In addition to Java classes and PDML files, you will find a couple of *.R E G files in each S a m p le s directory. A *.R E G file is a
type of file that adds keys to the Windows Registry. When you create your own plug-in, you copy these *.R E G files and
modify them to suit your requirements. The M sg Q u e u e S a m p le 1.re g file contains registration information for registering the
Java plug-in to Windows when that plug-in resides on the PC's hard drive itself. You also have the option, with Client Access
Express, of distributing your plug-in from the AS/400 IFS on your AS/400.

It works like this. You load all the pieces of your plug-in code (Java classes, PDML panels, and the *.D L L files and icons
used by your plug-in) into a directory in the AS/400 IFS. When the user installs Client Access Express (either for the first
time or using the Selective install option), the user sees your plug-in as an installable module under OpsNav and has the
option of installing it from there, making distribution of your plug-in a snap. The M sg Q u e u e S a m p le 1In sta ll.re g file contains
the registration set you need to install the plug-in from the AS/400.

Team-Fly
Team-Fly

M o d ify in g T h e S am p le P lu gg--In
As mentioned, the first sample plug-in displays a list of messages from the AS/400 message queue of the person signed on
through OpsNav. The plug-in displays the text of the message as well as the date and time it was received. What you're going
to do is modify the basic Java code to display the message ID and message type. This is a pretty simple modification, but it
gives you a good idea of how the pieces fit together.

For this modification, you need to change only two source files: M e ssa g e Q u e u e G U I.p d m l and
va. You change the first one using GUI Builder, and you change the other using a Java editor.
M q M e ssa g e sL istM a n a g e r.ja va
IBM has been kind enough to add into the other Java classes many extra methods that enable you to extract much more of
the message detail information than you're going after here. If you want to expand on what you're doing here, look at the
M q M e ssa g e .ja va source file. You can see all the methods available for you to access.

Team-Fly
Team-Fly

M o d ify in g T h e P D M L F ile
The first thing you need to do is start GUI Builder. There isn't enough room in this chapter to take you on a step-by-step tour
of GUI Builder and how to use it. However, Chapter 20, "GUI Builder Makes Java GUI Development Easy," covers PDML in
detail, and you can find a very good tutorial on GUI Builder in the AS/400 Toolbox for Java documentation at
www.as400.ibm.com/toolbox.

When GUI Builder starts, open the M e ssa g e Q u e u e G U I.p d m l file. For the modification, the only thing you need to change is
the String Table entry, so double- click this node to open it for editing. A string table in PDML is nothing more than a set of
character strings you can use to display error or informational text. You're going to use these strings as column headings.

Add to the string table two entries to be used as new column headings for your plug-in. The first entry is for the message ID;
the second is for the message type. When you open your sample string table, you can see two entries, co lu m n .m sg .co l1
and co lu m n .m sg .co l2
l2. Add two more entries to this sequence by clicking the Add String icon. Add the entry
co lu m n .m sg .co l3 with the text Message ID and the entry co lu m n .m sg .co l4 with the text Message Type. When you're done,
your sample should look like the one in Figure 58.2.

F ig u re 58.2: You modify the string table entries used by the plug-in using the GUI Builder utility.

Now close the String Table panel, save your file, and close GUI Builder. When you do this, GUI Builder recompiles the
M e ssa g e Q u e u e G U I.p d m l file for you.

Now you need to modify the M q M e ssa g e sL istM a n a g e r.ja va source file to use these new strings and retrieve values to
display under them for each message in the user's message queue.

Team-Fly
Team-Fly

M o d ify in g T h e Jav a P ro g ram


Since this isn't a tutorial on how to program in Java, I won't go into the various tools and requirements for programming in Java
on your PC. I'll assume that you know how to edit and compile a Java source file. If you're not familiar with these processes,
check the references at the end of this chapter for some great resources to get you started.

Once you've opened the M q M e ssa g e sL istM a n a g e r.ja va source file, scroll through the source until you get to the method
named C o lu m n D e scrip to rr. In this method, you identify to the List Manager how many columns of data your plug-in has. In
the sample program, two columns are identified for you, but you need to add two more columns. To do this, you need to
increase the number of elements in the array named d e scrip to rs rs. Look for this line:
ColumnDescriptor[] descriptors = new ColumnDescriptor[2]

Change the value in the last instance of C o lu m n D e scrip to r in this line from 2 to 44. Just underneath this line, you'll see a
couple of lines that set the value for the elements in the d e scrip to rs array. Add the following two lines to the source file, just
under the last line that sets the d e scrip to rs element values:
descriptors[2] =
new ColumnDescriptor(m_loader.getString("column.msg.col3"), 30, 3);
descriptors[3] =
new ColumnDescriptor(m_loader.getString("column.msg.col4"), 35, 4);

Doing this adds the two new columns to the class. Notice that the values in these columns are the same as the entries you
made in the M e ssa g e Q u e u e G U I.p d m l file in GUI Builder.

Now scroll down until you find the method named g e tC o lu m n D a ta


ta. Look for the following line:
sData = "";

Just underneath it, add this line:


sDataint = 0;

This variable is used to hold the numeric value of the message ID.

The last thing you need to do is retrieve the values for the message ID and message type. Search for the sw itch control block
in the g e tC o lu m n D a ta method. You need to add two more ca se statements to this block to get the required data. Under the
last ca se block but before the d e fa u lt block, add the code shown in Figure 58.3 to your source file.

 
F ig u re 58.3: Add these lines of code to the getColumnData method .

The m sg .g e tID () method in the M q M e ssa g e Java class retrieves the message ID from the message object on the AS/400.
The m sg .g e tT yp e ()method in M q M e ssa g e retrieves the message type from the message object on the AS/400. That's it;
now you can compile the M q M e ssa g e sL istM a n a g e r.ja va source file and create the Java class.

Team-Fly
Team-Fly

M o d ify in g T h e W in d o w s R e g istry
The last thing you should be familiar with is the *.R E G files. If you installed the sample source files to the C :\JV O P N A V
directory on your PC, you don't need to modify anything in this file. However, when you begin to create your own plug-ins, you
need to copy these files to your new plug-in folder and modify them to fit your needs. The *.R E G files can be edited with any
text editor, and they contain some pretty good instructions on how to use them.

The final step in modifying the sample plug-in code is to register the plug-in to Windows. Double-click the
M sg Q u e u e S a m p le 1.re g file. You'll be asked whether or not you want to add a key to the Windows Registry. Click the Yes
box, and you're done!

Team-Fly
Team-Fly

T h e M o m e n t O f T ru th
Now that you've modified the GUI and Java source file and compiled everything, it's time to see whether it all works. Open an
OpsNav session on your PC and connect to your AS/400. Each time you start OpsNav, it will "scan" your AS/400 and the
Windows Registry to see whether or not any new plug-ins have been added. It should find your new sample plug-in. Double-
click the Java Message Queue Sample 1 node in the OpsNav GUI to display the message on the AS/400 associated with the
user ID currently logged on. To see the new columns you added, scroll to the right in the right-hand pane of the resulting list.
Cool, huh?

Team-Fly
Team-Fly

T h e N asty P art
So far, you've worked with some pieces that any AS/400 green-screen programmer with a little Java experience should be
able to handle. As new functionality and new plug-ins are developed, you may want to brush up a bit more on your Java skills,
since the code can get complex very quickly. Relatively speaking, all of what you've done is fairly easy to do. If you don't have
a PC programming background, however, the next part may make you quail.

Every plug-in must have a DLL file defined for it. At this point, your only choice for creating this DLL is to use either C++ or
Visual Basic. Windows uses the DLL to find things such as the icons used by your plug-in as well as to determine version
number and other relevant data. For the sample programs, you could get by with the DLL file that resides in the
C :\JV O P N A V \W IN 32\M R I\ folder, but, when you create your own plug-in, you have to use either C++ or Visual Basic to
create all the unique icons and DLL files for that plug-in.

Team-Fly
Team-Fly

F in al T h o u g h ts
The changes you've made to the sample plug-in are pretty minor, but they should give you a feel for how all these pieces fit
together to create a plug-in. The best way to learn more about developing plug-ins is just to do it. For more information, visit
the IBM AS/400 Information Center at www.as400.ibm.com/infocenter.

There's no limit to what you can do with a plug-in. Creating plug-ins for the OpsNav client isn't for the faint of heart, but, if you
stick with it, you can provide your users some rather unique functionality.

Team-Fly
Team-Fly

R e fe re n ce s
 IBM AS/400 Information Center Web site: www.as400.ibm.com/infocenter

 IBM AS/400 Toolbox for Java and JTOpen Web site: www.as400.ibm.com/toolbox

 Zappie home page: www.zappie.net

Team-Fly
Team-Fly

C h ap ter 59: Java P ackag in g


O v e rv ie w
GALEN TUCKER

Java is becoming the language of choice for new development. The advantages of developing in Java (not the least of which
are code reuse and Write Once, Run Anywhere cross-platform support) are well documented, and judging from the amount of
new development in Java, it seems these advantages are not being overlooked. However, once the decision to develop in Java
is made, programming staff members are faced with wading through all the information on Java in order to make Java work for
their organizations. The truth is, to use Java, you need to understand only a few key concepts relevant to the part(s) of Java
you are using at the time.

A good grounding in object-oriented programming (OOP) is the basic foundation for understanding Java. Because of the
building block nature of the component- based programming enabled with the Java language, you will be able to construct
powerful applications by using Java classes provided by Sun Microsystems, IBM, third-party software vendors, and even the
other programmer teams within your own company. The Java classes of these various sources are bundled into functional
groups using a Java construct (conceptually similar to AS/400 libraries) called pack ages.

Team-Fly
Team-Fly

P ackag e Y o u r W o rld
Packaging is one of those Java tools that helps the developer organize projects, classes, and even full systems. Simply put,
a package is a collection of class files much like an AS/400 library is a collection of programs. The main purpose of
packaging is to make development and maintenance easier. Packaging allows for a natural layout of projects that builds on
the ease of maintenance established by using OOP. For organizational purposes, you would not normally put random classes
in a single package, just as you would not want to put random RPG programs in an AS/400 library.

The base Java language itself is extended by a core set of packages: ja va .m a thth, ja va .la n gg, and so forth. When you first
create a class file with no IMPORT statements, Java has little functionality. In order to do anything useful with Java, you must
first import the packages that contain the classes that provide the functionality you're looking for.

Basically, many of the classes that you need to do things such as advanced math, graphics, and communications are found
in packages supplied by Sun. Sun's Java Foundation Classes (JFCs), for example, provide advanced GUI components such
as tabbed dialogs, trees, and a subfilelike component call JT a b le
le. Other companies such as IBM, Microsoft, Hewlett-
Packard, and a host of third-party companies also provide packaged extensions to Java. Often, the Java packages developed
by various companies use the same class name. For instance, Sun's ja va .m a th package contains a class called
B ig D e cim a l, and IBM also produces a package that has a class called B ig D e cim a l. The difference is the package name
and how they operate. The package name provides what is known as a name space, which cleanly identifies classes of the
same name because they are isolated in the qualified name space of the package name.

When you develop Java applications for your own company, you will be creating packages of classes that are specific to your
business. When you create a Java source file, the first Java statement should be the PACKAGE statement.

(Otherwise, that class will not be cleanly bundled with other application-related classes in a Java package.) The PACKAGE
statement is normally followed by a set of IMPORT statements. By including other packages via the IMPORT statement in a
class, the application gains the functionality of the classes of those other packages. For example, you create a package to
calculate a mortgage over n years, then someone else begins developing a project that will use a calculated mortgage
payment, a person's income, and other bills to determine if an applicant should be awarded a loan. That person could import
your package and use your public classes and methods to arrive at a major portion of her project without having to design and
code the same thing again. She could also code her package to execute or extend your package and classes and use the
results, thereby saving GUI design time, file creation, and so on.

Team-Fly
Team-Fly

P u ttin g Y o u r P ackag e T o g e th e r
Package organization allows for an easier understanding of system layout and improves maintenance time. You may decide
to group all your file access classes in a single package and then use that package exclusively throughout your development.
That way, any required changes to data access can be done in one package for all your projects. You can use packages not
only to separate large projects and systems, such as the various financial systems (accounts receivable, accounts payable,
and general ledger), but also to break up the various pieces of the entire system into more manageable parts. The decision on
how to group your classes into particular packages is similar to deciding what classes to define.

A high-level breakdown of the system you are developing is the first step in creating your package hierarchy. Breaking a
financial system into A/R, A/P, G/L, and so on, is the way that developers do things, but in the procedural programming
world, that is often as far as the breakdown goes. Some of the better planned procedural systems include general-purpose
systems to handle generic calculations such as date format.

One of OOP's main advantages over procedural application programming is reuse. By using packages, the developer extends
OOP and groups even further. Grouping all file access classes in one package, for example, allows various systems to use
the information provided by the classes of that package while being oblivious to the source of that information. This information
encapsulation provides a single point for file access administration. Maintenance becomes easier because the developer
knows that, if any system has a problem or requires maintenance regarding file access, it is in one central location.
Packaging can be applied to any application area such as communications (email, printers, or faxes) or common business
logic. As you can see, further identifying different components of your project and marking them for their own package can
have tremendous benefits. Careful consideration in determining your package name and contents should not be
underestimated.

That is not to say that you can't rename a package or its contents, but doing so has been known to cause problems.
Sometimes, changing package names can clear up confusion; other times, it creates it. For instance, take the name change
of the Swing package-Sun's lightweight GUI components. Sun changed the name of the Swing package from
co m .su n .ja va .sw in g to ja va x .sw in g to clearly show that Swing is an extension to Java as opposed to a part of the core
Java classes. This also created a standard package name for Sun to release future Java extensions. Although this name
change was the best move to clarify the package intent, it has caused as much confusion as it cleared up, especially among
developers who are unfamiliar with Java's packaging setup. This package name change alone represents the majority of
incompatibilities between Java Development Kit (JDK) 1.1.x and JDK 1.2.x (Java 2).

Another major reason for using packages is the secure interclass communication they provide. The security comes primarily
from the keyword PROTECTED. The protected access allows for greater flexibility in how classes interact, preventing classes
outside of your package from accessing restricted methods. Particular accounting function methods, for example, may be
accessible throughout the general ledger package but are not something that you would want the purchase order system to
be able to access by simply extending or creating an instance of your class.

Team-Fly
Team-Fly

Jav a N am e G am e s
Packages follow a standard naming convention set by Sun: the reverse of your company's Web address in all lowercase
letters extended by the specific package name. IBM's AS/400 access classes, for instance, are in a package called
ss, with w w w .a s400.ib m .co m being the valid domain name. This naming strategy is merely a
co m .ib m .a s400.a cce ss
convention; it is not a requirement of Java but, rather, a standard that is generally adhered to. For that matter, Java does not
require the use of packages at all, but all the development tools I've seen create a package each time you start a new
development.

Packages can also be layered. For example, your company's complete package might be co m .m yco m p a n yy, and the
accounts receivable package might be co m .m yco m p a n y.a cco u n tsre ce iva b le le. The package name also represents the
directory in which your Java source and class files are stored. If your package is co m .m yco m p a n yy, then you must set up a
directory structure co m \m yco m p a n y to contain your source and class files. An account class in the accounts receivable
package would be kept in co m \m yco m p a n y\a cco u n tsre ce iva b le \a cco u n t.cla ss
ss. The package name also affects how you
must execute your Java source.

Team-Fly
Team-Fly

C o m p ilin g A n d E x e cu tin g Y o u r N e w P ackag e


To compile Java source that is not part of a package, you simply need to execute the ja va c command in the directory where
the source is kept. The same is true when you create a package. However, you need to specify the full package name when
executing the class. If you were to compile the account class in the previous example, you would need to type ja va c
a cco u n t.ja va in the co m \m yco m p a n y\a cco u n tsre ce iva b le \ directory.

That being said, when you first begin developing with Java, you may encounter compile errors of the "file not found" variety
when you attempt to execute a class file that is part of a package. The reason for this error is simple once you understand
the package principles. The period-separated words in a Java package name correspond to directories. In order to execute a
class file that is part of a package, you must be in the directory where the package directory starts. For example, if your
a cco u n t.ja va file is part of the package co m .m yco m p a n yy, then your package directory (in DOS) looks like this:
C :\co m \m yco m p a n y\. To compile the a cco u n t.ja va file, you would need to be in the directory where the source is kept
(CC :\co m \m yco m p a n y\). When executing your class, you need to be at the root (CC :\:\). The full command to compile your
a cco u n t.ja va file looks like this:
C:\com\mycompany\ javac account.java

To execute the class file, the command changes to


C:\java com.mycompany.account

As with all Java programs, you don't specify the .c la ss extension. The reason for this is packaging; so m e file .cla ss causes
the Java Virtual Machine to search for the class cla ss in the package (i.e., directory) so m e file
file.

Team-Fly
Team-Fly

P u ttin g It A ll T o g e th e r In A JA R
A JAR is a Java archive file similar to a PC .z ip file or a UNIX TAR file. In fact, you can view the contents of a JAR file using
WinZip, as shown in Figure 59.1. As you can see, the JAR file contains all the class files, image files, and so forth that make
up your project. You can create a JAR file for a single class or package, but if you're going to distribute the package, a good
practice would be to include all required files, including all external classes used by your package, any image files, and
anything else your package needs to execute. The JAR file in the example shows that the developer included all the required
classes.

F ig u re 59.1: A JAR file can contain any type of file, just like a .zip file. This AS/400 Toolbox for Java JAR file contains .gif
image and class files.

While you are in the process of creating your project, an uncompressed format is probably best. When it comes time to
distribute your creation, JAR files have a number of advantages, particularly speed. Java has the ability to read directly from
compressed files. In fact, Java can access files faster from a JAR file than from an uncompressed directory. Couple this fact
with combining all the necessary classes for your project to run into one JAR file, and you get even better performance.

If you include all the required parts of your application in one JAR file, installation may be as simple as saving the JAR and
executing the proper command. Anyone who has had to set up a client computer with all the necessary CLASSPATH
commands can probably attest to the convenience of a single JAR. Space is not generally a consideration in today's
programming world where clients have anywhere from 1 to 37 GB worth of hard drive space, but your JAR will certainly win
brownie points with anyone who has to download your application across the Internet. You'll also make a few friends with the
technical staff who may have to download your JAR from the network server to a couple of hundred or even thousand
computers.

Team-Fly
Team-Fly

T o tal P ackag e
The name-spacing feature of packages was included in the Java language, like many of Java's features, to make developing
easier. All of the development I've done in Java, from a single class to full systems, has been done using the package feature.
I may not need a package for what I'm creating today, especially if it's only one class, but by grouping classes, single or not,
in their own package, things become clearer.

Just like with using OO methods, practice will make designing packages easier. I would recommend that anyone doing
serious Java development use packaging in their design and implementation.

Team-Fly
Team-Fly

S ectio n X I: S am p le A p p licatio n s
C h ap te r L ist
Chapter 60: A Java GUI For DSPFFD

Chapter 61: Spool File To PDF, PDQ

Chapter 62: The Spartan Order System: An Exercise In Java Application Design

Chapter 63: Tracking AS/400 Vital Signs With Sysstats

Chapter 64: Free And Easy With WebSQL

P art O v e rv ie w
Most of the chapters in this book provide examples of Java code. But most of them are overly trivial to clearly show a single
point. This section provides real-world examples of Java applications.

Alex Garrison's "A Java GUI for DSPFFD" provides a useful example application that gives you a utility that most OS/400s
need: a visual display of the Display File Field Description. Joe Pluta and I, in "Spool File to PDF, PDQ," provide you with the
code and the know-how to convert OS/400 spooled files to Adobe's PDF. It's easy to convert spool files to HTML, but HTML
has limited viewing capabilities, especially for 132 and 198 character printouts. PDF, on the other hand, gives the Web-
browsing reader of your spool files converted to PDF much more control on viewing and searching.

The chapters in Section IV, "Java GUI Programming," explain how to create a graphical interface, and Section II, "AS/400
Toolbox for Java," explains how to use record-level access to get at your data. You'll have to combine these technologies to
create a complete application. I wrote "The Spartan Order System: An Exercise in Java Application Design" as an example
application (albeit without much real-world error handling and complexity) to show how to integrate Java technologies to
develop an application.

For those of you interested in sophisticated GUI development, you'll have to look at the implementation that Alex Garrison
used in "Tracking AS/400 Vital Signs with SysStats." Alex spared no complexity to make this application work well.

While Alex's "Tracking AS/400 Vital Signs with SysStats" spared no complexity, I spared no simplicity in "Free and Easy
with WebSQL." In about 120 lines of Java code and a dozen or so lines of HTML, I created a Web-based interactive SQL
Command Entry screen. The W e b S Q L servlet dynamically constructs HTML tables (subfiles) for SQL SELECT statements
but appropriately runs inserts, updates, and deletes to the database.

Team-Fly
Team-Fly

C h ap ter 60: A Java G U I F o r D S P F F D


O v e rv ie w
ALEX GARRISON

Almost every AS/400 shop uses a utility to display the field attributes of a DB2 for OS/400 record format or, at a minimum,
uses the Display File Field Description (DSPFFD) command. AS/400 programmers need to know the names and attributes of
the fields in a record format to code RPG or COBOL programs or to build SQL statements. DSPFFD, however, does not
display information in a useful format. As a result, programmers often create a custom utility to present the information in a
5250 subfile. My version of such a utility is called D isp la yR e co rd F o rm a t, a Java client application that presents file field
names and attributes in a GUI table format. Using the AS/400 Toolbox for Java, the user connects to an AS/400 and selects
any file of interest. Multiple record formats are supported, and the utility will search the user's library list for the file.

D isp la yR e co rd F o rm a t was written to provide an example of a full-blown Java application with many of the niceties expected
in a modern GUI:

 Mnemonics (e.g., Alt+F for the File menu).

 Keyboard accelerators (e.g., Ctrl+X to exit the program).

 Conditional menu options (i.e., menu options disabled or renamed when not appropriate).

 Status bar at the bottom of the application.

 Use of an .in i file to remember connection information.

The appearance of the D isp la yR e co rd F o rm a t GUI on your computer screen will vary depending on the operating system,
look and feel selected, and other screen customizations. Figure 60.1 shows sample output on my system using the Windows
look and feel.

F ig u re 60.1: This is a sample DisplayRecordFormat GUI with the Windows look and feel.

Due to space limitations, I won't list the source here. The entire application, including source, is available on the CD included
with this book.

Team-Fly
Team-Fly

T u to rial
D isp la yR e co rd F o rm a t is written totally in Java, so that you should be able to run the application from any client computer
that has a Java Virtual Machine installed (see the "Requirements" subsection).

In stallatio n /R u n
The following are the steps to install the application on a Windows platform:
1. Copy the d rf.z ip file from this book's CD.

2. Unzip the file to any directory. The Java source and class files are contained in two .ja r files. The d rf.ja r file contains
most of the application, and In iF ile .ja r is a JavaBean available free from IBM alphaWorks
(www.alphaWork s.ibm.com/Home/). The .g if files are used in the status bar to show the connection status of the
AS/400.

3. Ensure that the path to IBM's AS/400 Toolbox for Java (jt4
jt4 0 0 .ja rr) is in your CLASSPATH environment variable and that
you are using Java 2 (JDK 1.2 or 1.3). On my system, my CLASSPATH is initially set in my a u to e x e c.b a t file with
the following DOS command:
SET CLASSPATH=%CLASSPATH%D:\java\jt400\lib\jt400.jar;

4. Execute the d rf.b a t file. The d rf.b a t file will append d rf.ja r and In iF ile .ja r to your CLASSPATH and run the Java
program. There is no need to edit the .in i file prior to running the program. The information will automatically be saved
when you exit.

Provided you meet the requirements discussed in the next section, you should see a screen similar to Figure 60.1. If
you get a "class not found" error, most likely d rf.b a t was unable to append to your CLASSPATH environment variable.
Try extending the size of your environment space in co n fig .sys with the following DOS command:
shell=c:\command.com /p /e:8192

Alternatively, you can run d rf.b a t from another DOS batch file with the following DOS command:
command /e:8192 /c drf.bat

R e q u ire m e n ts
The only requirement on the AS/400 is to have TCP/IP active (with host servers on-STRHOSTSVR *ALL). No special CL,
RPG, or other programs are required on the host. You will get all the information you need from system API calls.

On the client computer, you will need a Java Development Kit (JDK) with Swing support and jt4 0 0 .z ip (AS/400 Toolbox for
Java class files). Swing is now a standard part of Java 2 (JDK 1.2 and 1.3) with the Java Foundation Classes. The application
has been tested on JDK 1.2.2 and JDK 1.3. D isp la yR e co rd F o rm a t has been tested on Windows 95 and Windows NT 4.0.

P ro g ram O p e ratio n
Once you have the program up and running, connect to an AS/400 by selecting Connection/Configuration from the menu. You
will be prompted for the name of the AS/400, your user profile, and your password, as shown in Figure 60.2.

F ig u re 60.2: The DSPFFD application maintains your connection information in its .ini file.

Click on the Connect button to start communicating with the AS/400. Once a TCP/IP port has been opened up and you pass
the security verification, the computer icon on the status bar will indicate your connection status, as shown at the bottom of
Figure 60.3.
F ig u re 60.3: The Display Record Format panel lets you know when you've successfully connected.

Now that you can talk to the AS/400, choose a file to display by selecting File/Open from the menu. The prompt shown in
Figure 60.4 will be displayed. Select a file, click on OK, and you are off and running. The status bar will indicate the progress
in obtaining the information from the AS/400. Should you have an error (e.g., a typo in the file name), an error dialog listing the
full contents of the A S 400M e ssa g e object array will be displayed. This is an interesting exercise just to see what kind of error
information is available from the AS/400 Toolbox for Java's classes.

F ig u re 60.4: The Open AS/400 File panel allows you to key a file name and a library qualifier for that
file.

Team-Fly
Team-Fly

A rch ite ctu re


The basic design requirements for the D isp la yR e co rd F o rm a t tool are quite simple:
1. The application should run on a client computer with no programs or extra code required on the AS/400 server.

2. The GUI output should replicate as far as possible the DSPFFD information when directed to an outfile.

Im p le m e n tatio n
With these two simple rules in mind, I examined the possible ways of retrieving the information. The AS/400 Toolbox for Java
has a full suite of classes to retrieve file information; A S 400F ile R e co rd D e scrip tio nn, R e co rd F o rm a t, F ie ld D e scrip tio nn, and
A S 400JD B C R e su ltS e tM e ta D a ta are the most useful. These classes, however, only provide a subset of the information
actually available in a file. A careful comparison of the DSPFFD command output and the AS/400 Tool- box for Java output
shows the toolbox classes that return record and field descriptions omit the following information:

Field Descriptions

 The g e tC o lH d g method returns a single string of the first column heading field (there are three column heading fields in a
physical file).

 Date format and date separator information on a per-field basis.

 Coded character set ID (CCSID) values for the text description, column heading, data, and EDTWRD.

 Variable length indicator.

 I/O attribute (i,o,b).

Reord Formats

 Record length.

 Record description CCSID.

 Variable length fields indicator, graphic fields indicator, date/time fields indicator, and null-capable fields indicator.

If you used the system APIs, however, you could get at all of this information. Besides, using AS/400 API calls in a Java
program would be interesting, especially since you also get to play with user spaces.

Figures 60.5 and 60.6 show the main classes in the implementation. The central application class is D isp la yR e co rd F o rm a t.
Because communication with the AS/400 is relatively time-consuming, a separate thread was used to handle I/O with the
host. To hide the thread complexities from the rest of the application, the daemon communication thread was wrapped in the
F m tR e a d e r class.

F ig u re 60.5: This is a UML diagram for the DisplayRecordFormat application.


F ig u re 60.6: This is another UML diagram for the DisplayRecordFormat application.

The F m tR e a d e r class makes calls to the following AS/400 APIs:

 QUSROBJD-verify the file exists and qualify the library name (qq u a lL ib N a m e method).

 QUSCRTUS-create user space in QTEMP (cre


cre a te U se rS p a ce method).

 QUSRTVUS-retrieve user space data (gg e tR e cF m tL ist, g e tU se rS p a ce G e n H d rr, and g e tU S F ld L ist methods).

 QUSRUSAT-retrieve user space attributes (gg e tU se rS p a ce A ttr method).

 QUSLFLD-list fields (lo


lo a d U S F ld L ist method).

 QUSLRCD-list record formats (lo


lo a d U S R e cF m tL ist method).

Everyone has a favorite way to handle thread-thread communication. A simple and fairly reliable method for daemon threads
to communicate with the main thread is to use custom events in which the data is an integral part of the event. The daemon
thread creates the event, loads data into the event object, and posts the event to the application event queue. The system
then delivers the event to the main thread (which is a registered listener) automatically. This approach is very fast and allows
you to do without a lot of pesky synchronization statements.

The most challenging aspect of the GUI are the JT a b le components, which display the field information in a format much like
a spreadsheet. (See chapter 11 of Kim Topley's CORE Java Foundation Classes for the best JT a b le information I have found
anywhere.) You want the GUI display to lock the first column of the table so that the field names are always shown, even
when the user scrolls to the right. I accomplished this by using two JT a b le ss: fld T a b le L o ck for the field name column and
fld T a b le for all the other columns. The fld T a b le is embedded in the body of a JS cro llP a n ee, and fld T a b le L o ck is inserted
into the row header of the JS cro llP a n ee. The whole procedure is pretty straightforward once you get used to the
JS cro llP a n ee, but you have to add some code to coordinate the view sizes of the row header and main body to account for
changes in the table sizes. The result looks like one (mostly) seamless table.

Through the magic of Model-View-Controller (see Chapter 41, "Servlets: The New Application Architecture," in Section VII, for
an in-depth discussion of MVC), both tables are able to use the same data model. Although beyond the scope of this chapter,
the bottom line is that the data can be changed in one place and both tables immediately reflect the changes.

A nice feature of many client programs is the use of an .in i file to store state information from one invocation to another. The
In iF ile JavaBean from IBM alphaWorks was used to provide quick access to a traditional .in i file. The JavaBean is free from
IBM and allows the application to read and write information from an .in i file with a few simple method calls. Using this Bean,
the name of the server and the user profile are loaded by the constructor for D isp la yR e co rd F o rm a t and are saved when the
application exits using the d isp o se method.

A point that I would like to make regarding the d isp o se method is that Java does allow you to specify a fin a liz e method to
any class that is guaranteed to be called sometime by the garbage collector. (See page 143 of Cay S. Horstmann and Gary
Cornell's Core Java 1.1: Volume I-Fundamentals for a discussion on why you might not want to rely on this method.) While
you could certainly use the fin a liz e method when exiting the whole application, I have gotten into the habit of always
providing my own method and controlling exactly when cleanup is done.

Both the custom events and the In iF ile Bean are great for applications, but they are not suited for applets. Applets are not
allowed access to the system event queue (which is bad news for custom events), and most browsers will not allow applets
to access the client file system (which is bad news for the In iF ile JavaBean).

Dialog boxes that gather information from the user (CC o n C fg D ia lo g and O p e n F ile D ia lo gg) use the time-honored technique of
transfer objects (CC o n C fg In fo and O p e n F ile In fo
fo) to send user input back to the main thread. A transfer object is especially
useful in Java where you cannot pass information back directly as method parameters.

Team-Fly
Team-Fly

E v o lu tio n : A W T T o S w in g
The first version of D isp la yR e co rd F o rm a t used the Abstract Window Toolkit (AWT) for the GUI. The AWT-only version was
fast, but it suffered from AWT's lack of a robust set of GUI components. The table was implemented using a modified
M u ltiC o lu m n L istB o x from Taligent (www.taligent.com). (IBM's Redbook Accessing the AS/400 System with Java uses
Taligent's M u ltiC o lu m n L istB o x for all of the examples that presented tables.) Although my initial AWT version of
D isp la yR e co rd F o rm a t that used Taligent's M u ltiC o lu m n L istB o x worked fine, the Java world seems to be moving to Swing
(which includes IBM), so I converted the application to Swing. The M u ltiC o lu m n L istB o x is gone; it has been replaced by two
JT a b le s and a JS cro llP a n ee. As with most Swing applications, the converted product is prettier, slower, and much more
complicated. Drop me an email at AGarrison@dotlogix.com if you are interested in the AWT version.

Team-Fly
Team-Fly

L e sso n s L e arn e d
Unlike the AWT, Swing is not threadsafe. All code that accesses Swing components should be in the AWT event thread. This
will be the main thread of your application for most components. (Modal JD ia lo g boxes get their own AWT thread.) The
implication for D isp la yR e co rd F o rm a t is that I could not have a method in the F m tR e a d e r thread call a
D isp la yR e co rd F o rm a t method in the main thread to modify the model of the JT a b le or the contents of the Jco m b o B o x
even with synchronized blocks. (For a thorough discussion of Swing and multithreading, see Appendix B of Kim Topley's
CORE Java Foundation Classes.)

Don't mix AWT and Swing components. For example, don't have B u tto n and JL a b e l components in the same application. I
know it is technically possible to do so, but you don't want to try.

Swing is slower than the AWT. Don't let anyone tell you otherwise. One can only hope that performance will improve over
time. Once you get a taste of the extra functionality and start using all the new Swing components, you are hooked; there is
no going back to AWT. Take some advice given to me recently by an IBMer, "So, Java is slow? Just buy a bigger box."

Exception handling is a good thing. When you are dealing with client/server communications using the AS/400 Toolbox for
Java, most activities must be enclosed in TRY/CATCH blocks. Try to use these blocks to provide a more fault- tolerant
application to the user.

The AS/400 Toolbox for Java access classes are easy to use. With a few samples and a little experimentation, you too can
call programs on the AS/400, manipulate user spaces, and process returned data. In fact, with the AS/400 Toolbox for Java,
you will find that coding these actions in Java is just as easy as in RPG-maybe easier.

Team-Fly
Team-Fly

R e fe re n ce s
 AS/400 System API Reference V3R7 (SC41-4801-01)

 Core Java 1.1: Volume I-Fundamentals. Cay S. Horstmann and Gary Cornell. Mountain View, California: Sun
Microsystems, 1997. See www.horstmann.com.

 Core Java 1.1: Volume II-Advanced Features. Cay S. Horstmann and Gary Cornell. Mountain View, California: Sun
Microsystems, 1998. See www.horstmann.com.

 CORE Java Foundation Classes. Kim Topley. Upper Saddle River, New Jersey: Prentice-Hall, 1998. See
www.topley.demon.co.uk /corejfc.html.

 OS/400 File APIs V3R7 (SC41-4857-01)

 OS/400 Object APIs V3R7 (SC41-4865-01)

Team-Fly
Team-Fly

C h ap ter 61: S p o o l F ile T o P D F , P D Q


O v e rv ie w
JOE PLUTA AND DON DENONCOURT

I'm tired of hype. Things never live up to expectations. It always seems that, if enough people buy just one of something
based on hype, whoever sold it to them gets to retire comfortably while the consumers try to figure out how to get their money
back.

Software is no stranger to this trend. Everyone has seen overzealous expectations turn to disappointment. For example, hype
surrounding Java as the "one true language" has been enormous. Reams of paper have been devoted to the wonders of Java,
all of them in future tense, so it's no wonder people have their doubts about Java. "Write Once, Run Anywhere" is becoming
as overused as "scalable," and it hasn't helped that Java has grown so rapidly, evolving from a nice Web page enabler to,
arguably, the first true cross-platform, open-specification language.

Team-Fly
Team-Fly

C P Y S P L F P D F : C ro ss
ss--P latfo rm C o m e s O f A g e
Well, the hype stops here! This chapter provides an example application that takes advantage of Java's strengths.

Recently, Don Denoncourt came to me with an interesting idea. He had found a public domain Java package that allowed an
application to create PDF documents relatively easily. PDF documents are very complex, but this package simplified things
considerably. One of Java's important strengths is its ability to encapsulate complex programming logic, making it easy to
use by other applications. The logic involved in creating PDF documents was a natural candidate for this kind of
encapsulation.

There was one problem, however: The package was developed for UNIX machines (Etymon Systems, www.etymon.com). We
thought about that and realized that it didn't matter. If Java were truly a cross-platform product, we should be able to use the
S p lf2P d f class on the AS/400, and that was exactly the case. Don wrote the Copy Spool File to Portable Document File
(CPYSPLFPDF) command and the CL program it calls. That CL program invokes a Java application I wrote, which, in turn,
uses UNIX Java classes. The result is a simple AS/400 command that converts AS/400 spool files into PDF documents you
can then download to your PC (or Macintosh or UNIX workstation) and display or print using the Adobe Acrobat Reader.

Team-Fly
Team-Fly

W h at's A P o rtab le D o cu m e n t?
A portable document is one that doesn't rely on either the hardware or the software used to print it. It uses a standard
structure to define elements of a printed document. In 1985, Adobe (www.adobe.com) introduced PostScript, which rapidly
became an industry standard, so much so that it was actually embedded in the firmware of many printers. If you sent a raw
PostScript document to a PostScript-enabled printer, you could be assured that it would look exactly as the original author
intended (within the physical limitations of color, page size, and resolution), even if the author had used completely different
hardware.

The next step in the portable document technology was the introduction of PDF. PDF was designed from the ground up to
allow the display, navigation, and electronic exchange of printed documents electronically. More than just a standard for
printed material, PDF allows users to view a printed report on their terminal, to provide sophisticated hyperlinks in documents,
and many other benefits. In this chapter, I won't be taking advantage of the more sophisticated features; I'm just going to
convert a simple text document. But once I do, you'll be able to use the Adobe Acrobat Reader to page back and forth
through the document with ease.

D o cu m e n t S tru ctu re
Even a basic PDF document requires quite a bit of information. See Figure 61.1 for a minimal PDF document. This document
doesn't even print anything; it just provides the framework for PDF objects to be printed. However, much of the complexity of
the PDF document is encapsulated in the co m .e tym o n .p j package, making your life quite a bit easier.

 
F ig u re 61.1: The content of even the most minimal PDF file can be quite confusing .

P ag e S tru ctu re
PDF documents are defined by page. Each page can have text and graphics written on it. Each page has an XY coordinate
system that is used to place individual objects. It's easy to intersperse portrait- and landscape-oriented pages, because each
page is a separate entity. The tricky part is that you have to keep track of the X and Y positions of every piece of text; there is
no such thing as a "newline" character in the PDF world. This S p l2P d f.ja va application handles the conversion of line and
column to X and Y coordinates.

O b je cts
Objects can be text, graphics, or images. S p l2P d f uses only text objects, so the conversion is very straightforward. Graphics
are simple lines and geometric shapes, while images are actual bit-mapped images. Images require a bit more forethought
when placing them on a page.

Team-Fly
Team-Fly

W h ich W ay D o Y o u G o ?
There are actually several steps to be taken and several routes to get where you want to go. You need to extract the data
from the spooled file. You also need to convert the row and column information into page number and XY coordinates. You
have to move the file from the QSYS file system to the AS/400 IFS file system. Finally, you need to convert the data from
EBCDIC to ASCII. When should each step be executed? First, I'll review the options.

R e ad S p o o l F ile D ire ctly


You can directly extract the data from the spooled file using the QPGETSP API. However, if you've used the APIs, you know
the complexity involved. Even if you're well versed in API programming, there is a significant amount of work required to get
data this way.

C o p y S p o o l F ile to A S /400 F ile


The simplest way, then, is to copy the spool file to a database file using the Copy Spool File (CPYSPLF) command. The
CPYSPLF command is quite easy to use and has a number of options. The most important keyword for this chapter is the
CTLCHAR keyword. There are three options for CTLCHAR (not counting the *S36FMT option, which is definitely not what you
want). *NONE simply copies records out, losing the spacing between lines. *FCFC and *PRTCTL both include spacing
information, but *FCFC uses a special American National Standards Institute (ANSI) standard technique that is, to my mind,
a bit more complex than the simpler *PRTCTL. For *PRTCTL, the first four characters contain either a three-digit line number
to skip to or a single-digit number of lines to space (0 means overwrite, 1 means print on the next line, 2 means skip a line).
Having selected the *PRTCTL format, you next need to decide how to transfer the file.

You could read the AS/400 database file directly using the A S 400F ile object from IBM's AS/400 Toolbox for Java. However,
you'd still have to deal with EBCDIC-ASCII conversion at some point, as well as using record techniques. That's quite a bit to
cover in a single Java application, and besides, I always believe in letting the system do the work if possible.

So, instead, you examine the Copy to Stream File (CPYTOSTMF) command. With it, you can let OS/400 move the file from a
QSYS file to an AS/400 IFS file while performing the ASCII-EBCDIC conversion for you. Then, you can use the IF S F ile object
from the toolbox to allow you to easily access the data using standard streaming file techniques.

Team-Fly
Team-Fly

T h e C o n v e rsio n
Now that you have a plan for converting the spooled file to an AS/400 IFS stream file, you can put together the high-level
design of the utility. Here you see yet another reason to use OS/400 commands as much as possible. Since you're not using
any high-level language (HLL) programs, you simply execute the OS/400 commands using the C o m m a n d C a ll class in Java.

T h e S p lf2P d f A p p licatio n
The S p lf2P d f application is a very simple application that will convert a specific spooled file into a specific AS/400 IFS file in
PDF. You, the user, need to know the names of both the source spooled file and the target PDF file. The target file should not
exist, but the directory must. The entire procedure is a Java application, so it can be run from the Java interpreter command
line. There are six steps that the S p lf2P d f Java application performs:
1. Create AS/400 File-a simple call to CRTPF using the C o m m a n d C a ll object.

2. Copy Spool File to AS/400 File-a call to CPYSPLF.

3. Copy AS/400 File to Stream File-a call to CPYTOSTMF.

4. Convert Stream File to PDF File-the actual PDF conversion. I've written a class called S p l2P d f (note the different
spelling), which converts a spooled data stream (with *PRTCTL characters) to a PDF data stream. Convert Spooled
Data Stream to PDF Stream uses the third- party routines from Etymon to do the conversion, so the logic is actually
pretty simple. The source for that class is in the .ja r file, along with the source for the S p lf2P d f application. S p lf2P d f
simply has to open the stream file created above for input and open the file specified in the second parameter for
output. S p l2P d f does the rest.

5. Delete Stream File-a call to RMVLNK.

6. Delete AS/400 File-a call to DLTF.

Team-Fly
Team-Fly

In stallin g T h e S p lf2p d f P ro g ram


Now, I'll go through the processes of installing and running the S p lf2P d f program step by step. I'm going to show you how it
works on my machine, but you might have to tweak the procedures slightly for them to work in your environment.

To load the CPYSPLFPDF command, you need to follow several steps:


1. Create holding areas on the AS/400:
CRTLIB LIB(PBDPRODLIB)
CRTSAVF FILE(PBDPRODLIB/CPYSPLFPDF)
MKDIR DIR('/java')
MKDIR DIR('/java/Splf2Pdf')

2. Unzip C P Y S P L F P D F .zip into a directory (for example, C :\C P Y S P L F P D FF).

3. Execute the commands shown in the FTP session of Figure 61.2 to transfer files to the AS/400.

F ig u re 61.2: This is a sample FTP session used to send the Splf2Pdf.jar to your AS/400.

4. Restore the CPYSPLFPDF library:


RSTLIB SAVLIB(CPYSPLFPDF) DEV(*SAVF) +
SAVF(CPYSPLFPDF/PBDPRODLIB)

5. Finally, compile the .ja r file on the AS/400:


CRTJVAPGM CLSF('/java/Splf2Pdf/Splf2Pdf.jar') +
OPTIMIZE(40)

Team-Fly
Team-Fly

R u n n in g T h e C P Y S P L F P D F C o m m an d
Now, with the command and Java classes installed, you can actually convert a spooled file. The CPYSPLFPDF command
requires as parameters the spooled file name; the destination PDF file name; and the spool file's job name, user ID, job
number, and, finally, spool file number. The PDF file name uses the AS/400 IFS file system format. For example, to create
the file m yo u tp u t.p d f in the AS/400 IFS directory you created earlier, you would use the
name /ja va /S p lf2P d f/m yo u tp u t.p d f.

Figure 61.3 shows an example execution of the CPYSPLFPDF command. Now, you can FTP this file back down to the PC
and view it with Adobe Acrobat. Figure 61.4 shows the file as it looks in the Adobe Acrobat Reader.

F ig u re 61.3: The CPYSPLFPDF command requires the qualification of the spool file's location and the IFS location of
where the PDF file should be created.

F ig u re 61.4: Congratulations! Your AS/400 spooled file now can be read by just about any PC in the
world.

Team-Fly
Team-Fly

The C ode
Figure 61.5 shows the CPYSPLFPDF command source, and Figure 61.6 shows the SPLFPDFCPP source of the command
processing program. The command source is fairly straightforward, so it requires no further discussion. The command
processing program, however, does some fairly odd things that anyone who is considering developing AS/400 Java
applications should take note of.

F ig u re 61.5: The CPYSPLFPDF command has an intuitive interface that AS/400 programmers have come to
expect.

 
F ig u re 61.6: The command processing program, SPLFPDFCPP, for the CPYSPLFPDF command does a couple of
tricks to prevent the Qshell command interface from popping up .

The input parameters are straightforward CL code, as are the working variables. (I almost keyed the comment work ing
variables as Work ing Storage, but I was afraid you'd then know I was once a COBOL programmer.) The first section of code,
however, is not so straightforward. It creates a fresh version of a file called STDOUT in QTEMP. It turns out that the file name
STDOUT is significant for running Java applications. All Java applications, much to Joe Pluta's displeasure, run from the
Qshell environment. The Qshell uses a simple I/O strategy for "standard" output borrowed from other UNIX-like shell
environments and the C and C++ computer languages. In the Qshell environment, there are three standard I/O files: standard
input, standard output, and standard error. You can think of "standard" as "default," and note that the standard/default output
is the Qshell command screen. The standard/default input and error file is also the Qshell command screen. Simple read and
write I/O statements in C, C++, or Java automatically go to the standard input, output, and error files. But if you execute a C,
C++, or Java application from batch, the standard output is the job log. (Any application request for input, by the way, will
result in an error unless you redirect the input file.)

Team-Fly
Team-Fly

P ro b le m s A n d S o lu tio n s
Java applications on the AS/400 can be executed from the RUNJVA command or from the Qshell environment. But wait-the
RUNJVA command turns around and passes control to the Qshell environment anyway, so that you get the same standard
I/O behavior regardless of which Java application invocation you use. When you want to run a Java application interactively,
you are thrown into the Qshell environment so those standard input, output, and error files are available. The problem is that,
when your Java application completes, you are left in the Qshell environment until you press Enter. I can see it now: Your
nighttime computer operator calls you at 2:00 in the morning and says, "I get this weird screen every time I try to run your
new PDF thingy and I didn't know what to do."

The workaround for this Qshell snafu is to redirect the standard output to a file rather than the default of the Qshell command
environment. Now, you are back to that QTEMP/STDOUT file. Notice that just before the SPLFPDFCPP program invokes the
QSH command to run Joe's S p lf2P d f Java application, the standard output file is redirected (specifically, it's overridden with
the Override Database File [OVRDBF] command) to the QTEMP/STDOUT file. That little trick prevents the Qshell command
prompt from being presented. The only thing to be aware of is that any informational messages go into the QTEMP/STDOUT
file. If your Java application doesn't execute properly, the informational messages that may tell you what went wrong will be in
that database file, whereas you are used to them being in the job log. An improvement to the SPLFPDFCPP program might
be to spin through that file just after the Java application completes to read the standard output information and write it to the
job log.

Team-Fly
Team-Fly

T ricks
So that's why the QTEMP/STDOUT file is refreshed at the beginning of the SPLFPDFCPP program. The next section of the
program simply sets up the job name, user, and job number variables. The Change Spool File Attributes (CHGSPLFA)
command, I must add, is invoked merely to see if the spool file, in fact, exists.

The very last command invoked in the SPLFPDFCPP program is the QSH command. QSH normally starts the Qshell
environment unless there is a command in the CMD prompt. The & JA V A variable contains the full command specification
required to run Joe's S p lf2P d f Java application complete with the spool file name, qualified job name, and the AS/400 IFS
output file. Note that I used the -cla ssp a th option of the Java utility rather than the Add Environment Variable (ADDENVVAR)
command. Be sure to either place the S p lf2P d f.ja r file in the AS/400 IFS directory called Ja va /S p lf2P d f, as Joe suggested,
or modify the cla ssp a th in your SPLFPDFCPP source. I also always like to point out that the AS/400's implementation of
Java uses a colon (:) rather than a semicolon (;) as the separator of paths in the cla ssp a th th. The jt4 0 0 .ja r location that follows
the S p lf2P d f.ja r path is standard for all AS/400s. When you install the free AS/400 Developer Kit for Java license program
(5769-JV1), the jt4 0 0 .ja r file is placed in the /QQ IB M /P ro d D a ta /H T T P /P u b lic/jt400/lib / directory.

Team-Fly
Team-Fly

P e rfo rm an ce
The CPYSPLFPDF command seems to execute slowly for a small spool file, but the problem isn't the utility. The performance
problem is the Java Virtual Machine startup time. When the spool file is significantly larger, the conversion does not take a
noticeably longer time to execute. Joe suggested that one improvement to his S p lf2P d f Java package would be to make it a
server application. The S p lf2P d f server would be started after a system IPL, or perhaps daily, and then sit as an
asynchronous job waiting for conversion requests.

A L ittle B o n u s
Here's an added bonus of the Spool File to PDF conversion utility. Because you used IBM's AS/400 Toolbox for Java (certified
as 100% Pure Java), this is a truly cross-platform utility. The utility can be used to get data directly from an AS/400 onto your
PC without ever using a green-screen. If you have been using the toolbox locally on your workstation and already have it in
your CLASSPATH, extract the Java code from the CD to some directory on your PC (such as C :/te m pp) and execute the
following command:
C:\TEMP>SET CLASSPATH=%CLASSPATH%;.\Splf2Pdf.jar

This command will put the S p lf2P d f.ja r file in your CLASSPATH. Now, you can run the S p lf2P d f application just like you did
on the AS/400, with one slight change: The target file name should use workstation syntax-for example,
c:\te m p \q p su p rtf.p d f-instead of AS/400 IFS syntax. So, to convert the same spooled file you just converted on the AS/400
into a file on the workstation, enter the following command:
java Splf2Pdf.Splf2Pdf 212228/pluta/qpadev0008/qpsuprtf/1
c:\temp\qpsuprtf.pdf

The application will display a login panel allowing you to enter the system name, user ID, and password. If you enter it
correctly, the file will be converted just as you saw before, then converted into a PDF file on the workstation. This is not
magic; it's simply a byproduct of IBM's toolbox classes.

Team-Fly
Team-Fly

R e p o rts T o U se rs W ith P D F Is P D Q
In this little utility, you can see both the strengths and the weaknesses of Java on the AS/400. The primary strength of Java is
the ability to use third-party routines from anywhere, including the UNIX world, on the AS/400. Back in the days when IBM
and UNIX were mortal enemies, nobody would have thought this possible. Even with the advent of the RS/6000, the truce was
uneasy at best. But Java byte code bridges that gulf, making truly portable utilities a possibility. In fact, you could even run
this utility on a UNIX workstation to directly convert AS/400 spooled files to PDF files.

The second strength is the incredible work done by IBM in putting together the AS/400 Toolbox for Java. By making nearly
every facet of the AS/400 available to Java programmers, IBM has opened up the AS/400 to a whole new world of capabilities.
As the toolbox matures, so will the AS/400 as a world-class player in the distributed processing community.

Team-Fly
Team-Fly

C h ap ter 62: T h e S p artan O rd er S ystem -A n E xercise In Java


A p p licatio n D esig n
O v e rv ie w
DON DENONCOURT

I developed the Spartan Order System to be a complete, if trivial, Java application that has a GUI interface for two DB2 for
OS/400 database files: the ORDER file and the ORDDTL file. Access to these two files is encapsulated through object-
oriented (OO) Java classes. The system does no validation. It doesn't integrate with other systems. In fact, it lacks any
sophisticated features. But the Spartan Order System exemplifies the basics of design strategies for AS/400 Java
applications (although, because it was developed in 1998, there is no Web interface).

By studying the Spartan Order System's implementation of Java technologies, you will learn how to use data areas,
encapsulation techniques, and the basics of simple GUI design. Furthermore, you will gain utility classes that simplify
connecting to the AS/400 and using commitment control for record-level access. Should you choose to procure the Spartan
Order System (i.e., its Java source code), you can do so by copying it from this book's companion CD. How much would a
grandiose order-processing system such as SOS cost you? Well, for you, it's free!

The Spartan Order System's database is an order file and an order-detail file. The attributes of these two files are shown in the
SQL CREATE TABLE statements shown in Figure 62.1. For your convenience, I have created a utility class called
G e n O rd e rT a b le s that generates the tables and starts journaling and commitment control over the database files. (For more
information, see Chapter 5, "Commitment Control for Record-level Access," in Section II.)

F ig u re 62.1: The Spartan Order System is made up of two files and two indexes.

Team-Fly
Team-Fly

O rd e r E n try O v e rv ie w
The GUI interface to the Spartan Order System is made up of two window frames: an Order frame (Figure 62.2) and an Order
Detail frame (Figure 62.3). When the user enters her customer number and an or der due date into the initial order panel, an
object of the O rd e r class is instantiated. The O rd e r class encapsulates access to the DB2/400 ORDER file. The O rd e r
class's a d d method inserts a new record into the ORDER file using a unique order number that was generated using a Java
interface to an AS/400 data area.

F ig u re 62.2: The OrderGUI class uses a BorderLayout to neatly arrange the components within the application
frame.

The Spartan Order System pops up the Order Detail window frame after the order header is created. As the user adds line
items to the Order Detail panel, objects of the O rd e rD e ta il class are created. Using the same strategy as the O rd e r class,
the a d d method of the O rd e rD e ta il class inserts records into the ORDDTL file. As line items are added to DB2/400, they are
also added to the list box at the bottom half of the Order Detail panel in Figure 62.3. When the user is satisfied with the order,
she can click the Commit button, or if she wants to drop the whole thing, she can click the Cancel button.

F ig u re 62.3: The OrderDetailGUI puts two panels that are set to BorderLayout into its frame that is set to the
FlowLayout.

As you probably have already guessed, the event handling attached to the Commit and Cancel buttons uses commitment
control to either commit or roll back the database changes. One transaction cycle or "boundary" for the Spartan Order
System is the addition of one order and its associated line items. An alternative to using commitment control would be to hold
off writing those order and order-detail records to DB2/400 until the order was "committed" by the user. Consider, however, a
more complex order-processing system that uses many other database files and programs. Often, those supporting programs
require records to be in the database file to calculate things such as discounts, transportation charges, and estimated
delivery dates. The more complex the application, the more difficult it is to buffer the database updates. Also realize that
Internet applications are more volatile than good old 5250 apps, so that even with the buffered approach, there is still a chance
of having incomplete updates during times of communication failure.

Team-Fly
Team-Fly

The G U I
The Spartan Order System's GUI was implemented using Java's Abstract Window Toolkit (AWT). Its interface would have
been better had I used Java Foundation Classes (JFCs), but, remember, this system was created with simplicity in mind. The
O rd e rG U I class extends AWT's F ra m e class. It does not manually size and align components into the GUI frame; instead, it
delegates that responsibility to Java layout managers. Layout managers manage the sizing and placement of components
into the frame in what I think is a brilliant strategy. (Thanks, Sun.) The Spartan Order System uses three of the five layout
managers bundled with AWT: B o rd e rL a yo u t, F lo w L a yo u t, and G rid L a yo u t. B o rd e rL a yo u t aligns components along
northern, southern, eastern, and western boundaries of a panel as well as to the center of a panel. F lo w L a yo u t simply
places components left to right and top to bottom in the order the components are added to the panel. G rid L a yo u t neatly
aligns component in rows and columns. Most GUIs are designed with panels stacked inside of each other-sort of like the
game "Tetris"-with each panel using whatever layout manager best aligns the components placed in that panel.

The layout manager for the O rd e rG U I frame is set to the B o rd e rL a yo u t. I added a panel to the northern portion of the Order
frame. That panel has a layout manager of F lo w L a yo u t. It is into that northern panel that I placed the input-capable
components (AWT T e x tF ie ld components) for customer number and due date along with their associated prompts (AWT's
L a b e l component). The O rd e rG U I then had another panel added to its southern border. It was in that southernmost panel
that I placed the Add and Clear AWT B u tto n components.

To handle the click events for the Add and Clear buttons, the O rd e rG U I class implements the A ctio n L iste n e r interface.
B u tto n components generate A ctio n E ve n t objects when a user clicks them. The A ctio n L iste n e r interface has a single
method called a ctio n P e rfo rm e d that has an A ctio n E ve n t object as a parameter. When you say your GUI class implements
an interface, your class must then provide code implementations for the methods of that interface. The O rd e rG U I
implementation of the required a ctio n P e rfo rm e d method shown in Figure 62.4 is coded to handle events from both the Clear
and Add buttons. The code for the a ctio n P e rfo rm e d method finds out which button generated the click event (AA ctio n E ve n t)
with the g e tA ctio n C o m m a n d method (which returns the button's label). When the A ctio n E ve n t is generated from the Clear
button, the a ctio n P e rfo rm e d method simply clears the text fields. When the A ctio n E ve n t is from the Add button, the
a ctio n P e rfo rm e d method of the O rd e rG U I class creates an O rd e r object (which, remember, inserts a record into the
DB2/400 ORDER file). The a ctio n P e rfo rm e d method then invokes the Order Detail GUI by creating an O rd e rD e ta ilG U I
object and subsequently calls the sh o w method of O rd e rD e ta ilG U I to slap the application window up on the screen.

F ig u re 62.4: The actionPerformed method of the OrderGUI class handles the events generated by both the Add and Clear
buttons.

One last but very important step for Java event handling is that the O rd e rG U I has to register itself to be notified when the user
clicks the Add or the Clear button. It registers itself by invoking the a d d A ctio n L iste n e r method over both of the button
objects. Note that the Java reserved word THIS specifies that the same object that is invoking the a d d A ctio n L iste n e r method
is the one that is to be notified when the A ctio n E ve n t occurs. When that event does occur, the Java Virtual Machine will
automatically notify (call) the a ctio n P e rfo rm e d method of the registered object. That's event-driven programming for Java in a
nutshell.

Team-Fly
Team-Fly

O rd e r D e tail G U I Im p le m e n tatio n
The Order Detail GUI features two main panels. Both of the layout managers for those main panels are set to B o rd e rL a yo u t.
The main panel that is at the top of the frame has another panel placed in its center. The layout manager of that centered
panel is set to G rid L a yo u t. As you can see in Figure 62.3, that grid has two columns and five rows; it is used as a data entry
form for order-detail records. The first column of the grid has prompts for the input components in the second column. To the
southern border of the topmost main panel, I have added another panel that houses the Add and Clear buttons using the
F lo w L a yo u t.

The bottom half of the O rd e rD e ta ilG U I frame presents the other main panel (which, remember, also uses B o rd e rL a yo u t). In
the northern portion of that bottom panel, I placed the "Line Items" prompt (as an AWT L a b e l component) to identify the
elements contained in the list box that follows. The list box is placed at the center of the bottom panel; it displays line items
that have been added to the order. To the southern border of the bottom panel, I added another button panel that houses the
Commit and Cancel AWT buttons.

The user adds line items with the top half of the Order Detail GUI, and then, when he is satisfied with the order shown in the
list box at the bottom half of the frame, he commits the DB2/400 ORDER and ORDDTL writes with the Commit button. Just
like the O rd e rG U I, the O rd e rD e ta ilG U I implements the A ctio n L iste n e r interface, which means that O rd e rD e ta ilG U I must
provide code for an a ctio n P e rfo rm e d method. Each of the four buttons of the O rd e rD e ta ilG U I (aa d d D e ta il, cle a rr, co m m it,
and ca n ce l) specifies that the a ctio n P e rfo rm e d method of the O rd e rD e ta ilG U I object is to handle the action events by
invoking the a d d A ctio n L iste n e r method:
addDetail.addActionListener(this);
clear.addActionListener(this);
commit.addActionListener(this);
cancel.addActionListener(this);

The a ctio n P e rfo rm e d method of the O rd e rD e ta ilG U I object again uses the g e tA ctio n C o m m a n d to find out which button
the user has selected. If it is the Clear button, the values of the T e x tF ie ld components are cleared. If it is the Commit button,
the ORDER and ORDDTL writes are committed using record-level access's co m m it method, the O rd e rD e ta ilG U I window is
disposed, and control is returned to the O rd e rG U I window. If the button clicked is the Add button, an O rd e rD e ta il object is
created and its a d d method is invoked, which creates a new record in the ORDDTL file. Finally, if the button selected is the
Cancel button, the ORDER and ORDDTL writes are rolled back (with a call to the ro llb a ck method) and control is returned to
the O rd e rG U I.

When you copy the Java source code, you may find it curious that the O rd e rD e ta ilG U I has a m a in method. It's curious
because the m a in method of the O rd e rD e ta ilG U I is not invoked with normal processing. However, it is good coding practice
to put unit-testing code in the m a in method of all of your classes. That way, you can easily test each class. The m a in
method of O rd e rD e ta ilG U I simply instantiates an O rd e r object (which is required by the O rd e rD e ta ilG U I constructor) and
bootstraps the O rd e rD e ta ilG U I application by instantiating an O rd e rD e ta ilG U I object and then invoking its sh o w method.

Team-Fly
Team-Fly

D atab ase E n cap su latio n


The GUI access to the DB2/400 ORDER and ORDDTL files was through the O rd e r and O rd e rD e ta il classes. The OO
interface to the database is quite simple. A record is created in the ORDER file with the a d d method of the O rd e r object, and
records are added to the ORDDTL file from the a d d method of the O rd e rD e ta il object. But full encapsulation requires more
than just inserting records; it requires read capabilities as well as deletion and modification. The Spartan Order System GUI
did not use these features. The O rd e r and the O rd e rD e ta il classes did, however, provide implementations for these required
features.

Figure 62.5 shows the list of methods for the O rd e r class. Notice that the class interface has a d dd, u p d a te
te, and d e le te
methods. Order records are read when instantiating an O rd e r object using the constructor method that accepts the full key
(the order number) for the database record. The O rd e r class also provides getter and setter methods for each of its (two)
fields. It is standard encapsulation strategy to make the fields (a.k.a. attributes) of a class private and then make getter and
setter methods to retrieve and modify the values of those fields. Setter methods should provide some form of validation. When
you want to modify the values of a record's fields, you use the various setter methods and then the u p d a te method to post
your changes to the database. I find these semantics easier to understand and use than READE, CHAIN, and other RPG
operation codes. Access to business entities should be through the methods of a business class that represents the entity
rather than through direct access to files. The O rd e r class also provides a getter method that returns an array of the
O rd e rD e ta il objects associated with an order.

F ig u re 62.5: The interface of the Order class was designed to encapsulate access business methods associated with
the order entity and hide the complexities of DB2/400 file processing.

The O rd e r class has three constructors. The first has no parameters; it is used when you want to create a new order record.
The second constructor has an order number parameter; as mentioned earlier, it is used to retrieve the order record values
based on the key value. The third constructor requires both the order number and a Boolean value to specify whether you
want the record locked. The default behavior, as you have come to expect from RPG when reading a record from a file opened
for update, is to lock the record. To support a strategy similar to RPG's "read with no lock" op code, this third constructor
option of the O rd e r class allows you to specify that you do not want to lock the record.

The O rd e rD e ta il class was implemented using the same strategy as the O rd e r class. Figure 62.6 shows the O rd e rD e ta il
list of public methods. When you copy the O rd e r and O rd e rD e ta il Java source, you might notice that there is an awful lot of
duplicate code between these two classes. They both use the same file open strategy, and they both use similar a d dd,
te, and d e le te code. Code duplication is bad. Whenever you start to feel déjà vu when coding in Java, consider creating
u p d a te
a base class. That's exactly what I prescribe in Java Applications Strategies for the AS/400, but I don't have the space in this
chapter or the desire to cover the complexity of the design required to code a base class for record-level access.
F ig u re 62.6: Because the interface of the OrderDetail class uses many of the same methods of the Order class, it
warrants the use of a base class.

The complexity of my particular implementation of the O rd e r class doesn't really matter; it is the usability of the interface of
the O rd e r class that should be your only concern. The interface for both the O rd e r and the O rd e rD e ta il classes is trivial.
Also note that the code for the O rd e rG U I and O rd e rD e ta ilG U I did not open and directly process any files; that responsibility
was delegated to the O rd e r and O rd e rD e ta il classes. The point that I want to make here is that database access to one file
is isolated to the Java class that wraps access to the records of that file. This component-based programming strategy
decreases the complexity of programming Java applications.

This process of encapsulation is known as object-to-relational wrappering, and there are many tools on the market that
automate the encapsulation process. IBM's VisualAge for Java Enterprise Edition, for instance, comes with a feature called
Data Access Builder (DAX). Another well-known product (which is not AS/400-specific but works well with DB2/400) is The
Object People's TOPLink for Java (www.objectpeople.com)). And now that the technology of Enterprise JavaBeans (EJBs) is
gaining momentum, it is also important for me to note that most Web application servers that support EJB (such as BEA's
WebLogic, www.bea.com) come with an object-to-relational wrappering tool.

Team-Fly
Team-Fly

S ta tic E le c tric ity


The O rd e r and O rd e rD e ta il classes are both wrappers around database files. One potential problem with encapsulating
database access to a Java class is that each object of that class requires access to a file open. When you consider that a
single order may have multiple line items, you can immediately see that there would be a performance problem if there were a
separate file open for each object (which encapsulates access to one database record). My O rd e r and O rd e rD e ta il classes
neatly circumvent this problem by making the file open variable sta tic tic. The following statement is used in the O rd e r class to
declare the object variable o rd e rF ile
ile, which is to hold the file open for keyed access to the ORDER file:
private static KeyedFile orderFile;

The sta tic modifier makes the o rd e rF ile object variable a class field. Because the o rd e rF ile field is declared as sta tic
tic, the
file open is shared among all object instances of the O rd e r class. The constructor methods of the Spartan Order System's
O rd e r class check to see if the ORDER file has been opened. Thus, the first time an O rd e r object is created, the o rd e rF ile
object is instanced as a K e ye d F ile object:
if (orderFile == null) {
orderFile =
new KeyedFile(system,
"/QSYS.LIB/DENONCOURT.LIB/ORDER01.FILE");
}

All subsequent object instances of the Order class use the same sta tic file open.

Team-Fly
Team-Fly

G o o d C o n n e ctio n s
Even more of a performance concern are connections to the AS/400. AS/400 connections are enabled with the IBM Java
Toolbox for the AS/400's A S 400 class. Your Java application should instance one of these classes. One way to do this is to
create an A S 400 connection object and then pass it to the constructor methods of all the classes in your application. That
can get a little messy, so I use a simple yet powerful technique known as the singleton design pattern in my P ro file class,
as shown in Figure 62.7. A singleton is simply a class that has fields that are all static. The first time the P ro file class is
referred, the funny little method with no name is invoked.

F ig u re 62.7: This Profile class uses the singleton design pattern.

This method is known as the static method, and I guarantee that it will be invoked once and only once and that it will not be
used until some other class's method refers to one of its static fields. Whenever I need an A S 400 connection object, I simply
refer to the P ro file class's static A S 400 field. The O rd e r class's constructor, for instance, uses the following code to set its
A S 400 connection object field:
system = Profile.as400;

I use my P ro file class in many of my Java applications to be sure that I use only one A S 400 connection. In this case, the
one A S 400 connection object is doubly important because the files opened in the Spartan Order System must be opened
through the same A S 400 connection object.

Team-Fly
Team-Fly

U sin g A S /400 D ata A re as W ith Jav a


During my initial testing of the Spartan Order System, the first problem that I had was the uniqueness of the order number. In
legacy applications, you solve this problem with a data area. Any program that needs a unique order number accesses the
last-used number from the data area, increases it by one, and then updates the data area. OS/400 V4R4's version of the
AS/400 Toolbox for Java added Java classes for accessing data areas. The toolbox has four data area classes: D a ta A re aa,
C h a ra cte rD a ta A re aa, D e cim a lD a ta A re aa, and L o ca lD a ta A re aa. The Spartan Order System uses the D e cim a lD a ta A re a to
access the last order data area that I created with the following AS/400 command:
CRTDTAARA DTAARA(DENONCOURT/LASTORDNO) TYPE(*DEC) LEN( 6 0)

The data area classes are so easy to use that I saw little reason to encapsulate access to the last order data area with a
utility class. Essentially, a data area is like a file open, so I made the D e cim a lD a ta A re a field of the O b je ct class a sta tic
field so that it could be shared among all instances of the O rd e r class just like the o rd e rF ile file open:
private static DecimalDataArea lastOrderNoDtaara;

Then, in the O rd e r class's constructor, I instanced the la stO rd e rN o D ta a ra object (that is, if it hasn't been created already):
if (lastOrderNoDtaara == null) {
lastOrderNoDtaara =
new DecimalDataArea(system,
"/QSYS.LIB/DENONCOURT.LIB/LASTORDNO.DTAARA");
}

When the O rd e r class needs a unique order number, it uses its private utility method called g e tN e x tO rd e rN oo. The
g e tN e x tO rd e rN o method retrieves the last order number used with the following code:
BigDecimal dtaara = lastOrderNoDtaara.read();
int lastOrderNo = dtaara.intValue();

The re a d method of the D e cim a lD a ta A re a class automatically converts the zoned decimal EBCDIC value of the
LASTORDNO data area to a Java B ig D e cim a l object. Order numbers have no decimals, so I converted the B ig D e cim a l
object into the simple integer data value. I then increased the last order number value by one (using the funny Java plus plus
[++] operator rather than la stO rd e rN o = la stO rd e rN o + 1;) and updated the data area with the D e cim a lD a ta A re a class's
w rite method:
lastOrderNo++;
lastOrderNoDtaara.write(
new BigDecimal(lastOrderNo));

Notice that I created a B ig D e cim a l object on the fly to be passed as the parameter to the D e cim a lD a ta A re a class's w rite
method. (Chapter 49, "Java Performance Tips," provides an alternative strategy to using data areas with Java.)

Team-Fly
Team-Fly

P lace Y o u r O rd e r
The Spartan Order System is doomed to be replaced by more sophisticated Java applications. But it accomplishes this goal:
It gives you a simple implementation of a Java application that takes advantage of the unique features of the AS/400. It uses
data areas, record-level access, and commitment control-all AS/400-specific technologies. The Spartan Order System uses
the simple yet powerful feature of Java's sta tic modifier on class fields and class methods. It also presents basic
encapsulation techniques. Take advantage of this simple application and incorporate its techniques into your own Java
application design strategies.

Team-Fly
Team-Fly

C h ap ter 63: T rackin g A S /400 V ital S ig n s W ith S ysS tats


O v e rv ie w
ALEX GARRISON

I have always been intrigued by the various monitor gadgets you see in a hospital emergency room. In particular, the heart
monitor seems ideally designed for its task. You can see the current state of the heart both in amplitude and frequency of
beats, and you can see some history over the past couple of seconds. Well, you know that keeping your AS/400 healthy and
operating smoothly is no easy task. Performance tuning and capacity planning are tricky even on a static system. If you start
adding or deleting users, applications, or peripherals, the challenge increases exponentially. S ysS ta ts is a simple graphical
Java tool that was developed with the same two benefits as a heart monitor: It provides real-time information and shows
system trends.

Figure 63.1 shows S ysS ta ts in action for two AS/400s. The figure displays strip chart graphs of CPU utilization, DASD
utilization, and the number of interactive jobs, as well as the contents of the QSYSOPR message queue and some Simple
Network Management Protocol (SNMP) information. (SNMP has been available on the AS/400 since V3R2. See the
"Implementation" section for further details.) The strip chart graphs use my S lid in g G ra p h JavaBean.

F ig u re 63.1: The SysStats performance monitor dynamically displays output from multiple AS/400s.

Although the tool does perform useful work, the main purpose of S ysS ta ts is to provide Java programmers with real-world
examples of specific advanced programming techniques. Reading about a technique in a book is good; seeing working
examples in the context of a complete application is even better.

Team-Fly
Team-Fly

P ro g ram O p e ratio n
S ysS ta ts is a Java application meant to run on any client platform that has a Java Virtual Machine (JVM), IBM's AS/400
Toolbox for Java Modification 2, and TCP/IP connectivity to one or more AS/400s. The application has been tested on Java
Development Kit (JDK) 1.1.7 with Swing 1.1.1 Beta 2 and JDK 1.2 using the Windows 95, 98, and NT client platforms. Your
CLASSPATH should already include the JDK and the AS/400 Toolbox for Java. No special code is required on the AS/400,
and S ysS ta ts works correctly with systems running V3R2, V3R7, and V4R3. Other releases may work as well but have not
been tested. In general, the AS/400 Toolbox for Java is not designed to work with V3R2, but I've had no problem with the
limited classes used by S ysS ta tsts.

The Java source and class files are included on this book's companion CD with three .ja r files. In iF ile .ja r and
S N M P P ro to co l.ja r are JavaBeans available for free from IBM alphaWorks (www.alphawork s.ibm.com); S ysS ta ts.ja r contains
the bulk of the application. Check the re a d m e .tx t file for any last-minute instructions.

To run the tool, simply execute the S ysS ta ts.b a t file. The .b a t file adds the three .ja r files to your CLASSPATH and executes
the application. You should see a screen similar to Figure 63.1. If you execute SYSSTATS.BAT from the command line, you
may also supply up to two parameters: NOMSGQ and SIM.

NOMSGQ disables the message queue facility in S ysS ta tsts. SIM causes S ysS ta ts to only simulate connection to an AS/400.
The application displays random data points as if they were obtained from the AS/400. This option is useful if you are
modifying the application and don't have an AS/400 handy. With this option, you still must add an AS/400 and connect to the
system.

If you run the application multiple times in the same DOS box or VisualAge for Java (VAJ) integrated development
environment (IDE) session, you get a "Could not open Trap Socket on Port 162" exception from the SNMP JavaBean. A bug
in the SNMP JavaBean does not properly close the TCP/IP resources when the application terminates. Opening a new DOS
box or restarting VAJ solves this problem.

Team-Fly
Team-Fly

C o n n e ctin g T o A n A S /400
Once the application is up and running, you must tell S ysS ta ts which AS/400s are of interest and connect to each system.
To add a new AS/400, select Connection/Add System or use Ctrl+S. A dialog similar to that in Figure 63.2 appears. You may
enter the system name as an IP address or as the TCP/IP name of your system. Enter your AS/400 user profile and
password along with a refresh rate in seconds. Choose a different graph color for each system. All three graphs and the
QSYSOPR message queue display use color to differentiate between systems. Once the systems have been entered, you
can start the connection to each by selecting the Connect submenu option from each system in the Connection menu, or you
can connect all systems at once by selecting Connection/Connect All or using Ctrl+A. You can always go back and change
the refresh interval or graph color.

F ig u re 63.2: SysStats allows you to configure the display to refresh at qualified intervals.

The status bar at the bottom of the application displays overall connection status and any error messages encountered during
the connection. You may also look at the icon associated with each AS/400 in the Connection menu. A red circle with a
slash means the system is not connected; a lightning bolt means the system is connected successfully. If you have a typo in
the system name, the application does not give you a connection error until the AS/400 Toolbox for Java has timed out from
trying to connect to the nonexistent system.

The name of each AS/400 appears on the legend below each graph, using the color that you select. The numbers in
parentheses by the system name on each graph display the most recent data point received from the given system (see
Figure 63.1). The first number is the time received (in seconds) since the application was started, and the second number is
the value. The vertical axis of each graph automatically adjusts to fit the range of data points received.

The application has been configured to display 100 data points per system on each graph. Once 100 data points have been
displayed, new points are added to the right of the graph as old data points are removed from the left. The result is a sliding
window that always displays the 100 most recent data points per system. For example, to display 24 hours of information,
you set the refresh interval to 864 seconds. You can also change the S ysS ta ts constructor to allow more or fewer points.

Team-Fly
Team-Fly

C u sto m izin g Y o u r V ie w
The View option allows you to select just those panels you wish to display. The remaining panels automatically resize
themselves to take up the available space. At this time, you cannot move the panels around or manually resize them.
However, moving and resizing panels would be possible with some straightforward modifications to the layout manager. I'm
leaving these modifications as exercises for you (or for a later version of S ysS ta ts
ts).

Team-Fly
Team-Fly

S h u ttin g D o w n
You close the application in the normal ways you have come to expect from GUIs. Either select the X in the top right corner of
the application or select File/Exit or Ctrl+X. The File menu gives you the option to save your settings upon exit and the option
to save your AS/400 passwords upon exit. Both options are on by default, so remember to uncheck the password option if
you don't want the S ysS ta ts.in i file to show your passwords. If you don't save this information, you will have to reenter it in the
connection Properties dialog the next time you start the application (see Figure 63.2). In addition to your connection
information, S ysS ta ts also saves the panels you have selected to view and the size and position of the application frame on
the desktop.

If you try to shut down the application during a connection attempt for any AS/400, you'll see a dialog warning that continuing
to exit will not allow your settings to be saved. You can either wait for the connection to complete (or time out) or continue to
exit. Continuing to exit at this point does not save your settings, because the connecting thread has a lock on the connection
parameter object for the given system.

Team-Fly
Team-Fly

T ro u b le sh o o tin g
S ysS ta ts requires AS/400 Toolbox for Java Modification 2 or later. If the data points in your graphs are all zero, you're
probably running Modification 1. Otherwise, make sure that your PATH includes the JDK or Java Runtime Environment (JRE)
and that the CLASSPATH already includes the JDK (and 1.1.1 sw in g a ll.ja r if running prior to JDK 1.2).

If the CLASSPATH and PATH are set correctly and you still get a "class not found" error, S ysS ta ts.b a t may have run out of
environment space when adding the .ja r files to your CLASSPATH. Try extending the size of your environment space in
co n fig .sys or running S ysS ta ts.b a t from another .b a t file with something like co m m a n d /e :8192 /c S ysS ta ts.b a t. If you can
bring up the application but get some other error not covered here, select Help/Program Environment from the S ysS ta ts menu.
This option shows all your Java environment variables. Email me that list (at AGarrison@dotlogix.com), and I'll get back to you
with a solution.

Team-Fly
Team-Fly

Im p le m e n tatio n
Because Java is mostly object-oriented (OO), you can reuse many of these classes in your own applications. I can't provide a
thorough discussion of the application architecture here because of space limitations. The following, however, is a summary of
the primary Java classes:

 S ysS ta ts is the central class. S ysS ta ts provides the GUI and most of the program logic.

 H o st is derived from the AS/400 Toolbox for Java's A S 400 connection class; it controls all communication with the host
except for SNMP.

 S N M P R e a d e r queries the AS/400 and walks the SNMP tree until a complete message is put together.

 S lid in g G ra p h is a JavaBean encapsulating all the graph functions.

 S N M P R e a d e rE ve n t and H o stE ve n t are transfer objects carrying data broadcast to all registered S N M P R e a d e r and
H o st listeners.

Allow me to climb onto my soapbox for a minute. OO programmers tend to think of the world as composed of objects that
communicate with each other synchronously and asynchronously by messages. Allowing an object to call a member method
of another object is not OO in my book. When you want to cause action on some object, you send a message saying "delete
yourself" or "print yourself."

When you want to communicate information between objects, you encapsulate this information in a transfer object and send
it in a message. Unfortunately, you can't write a complex program in Java using this model because of performance. You will,
however, see transfer objects used in my code for communication between main classes. Drawing a line in the sand at
appropriate boundaries preserves some of the OO benefits while allowing the application to run in a timely fashion.

Team-Fly
Team-Fly

M u ltith re ad in g
In Swing, the preferred way for threads to send information back to GUI objects is to encapsulate the information inside
objects that implement the R u n n a b le interface and send the objects to the Abstract Window Toolkit (AWT) event queue
thread as messages. The S w in g U tilitie s.in vo ke L a te r() method is used to put the R u n n a b le object on the AWT event
queue and continue on with business. (You could, of course, use in vo ke A n d W a it() if you want the thread to sit and wait until
the AWT event queue has processed your R u n n a b le object.) This approach ensures that only one thread at a time (always
the AWT event queue thread in this case) can modify GUI elements. Once you get used to the idea, you will find that this
approach eliminates many possible race conditions and deadlocks.

All interaction with the user occurs in the AWT event queue thread. Consequently, you must keep activities in this thread as
short as possible. Otherwise, the GUI will appear to freeze until the thread has time to check the event queue again.
Whenever you want to do some time-consuming activity (like initiate a connection to an AS/400), you should spin off a
daemon thread to do the work in the background. S ysS ta ts enforces this design principle by using a recursion technique. The
S ysS ta ts.co n n e ctS yste m (h o st) method, for example, can be called directly from any thread, including the AWT event queue
thread. The method checks to see if it is running in a daemon thread. If not, it creates a new thread, which then calls
co n n e ctS yste m (h o st), thus ensuring that the connection to an AS/400 is always done from a daemon thread. The user of
this method can then call this method from anywhere with the assurance that the GUI will not freeze while the connection is
taking place.

Team-Fly
Team-Fly

S lid in g G rap h Jav aB e an


The S lid in g G ra p h JavaBean does all the strip chart graph activity. This graphical Bean provides a sliding window along the X
axis to provide strip chart functionality. As new data points are added to the right, old data points are removed from the left.
Any number of data sets can be displayed on a single graph. Each data set is a separate object maintained by the
S lid in g G ra p h Bean. By means of accessor methods such as S lid in g G ra p h .g e tD a ta S e t(S trin g ), the user can then
manipulate data set properties (e.g., color, legend) and even add points directly to the data set. Convenience methods for
adding points to data sets are also provided in the S lid in g G ra p h class.

The Y and X axes are also objects within the S lid in g G ra p h Bean. With the use of accessor methods, users can retrieve a
given axis and then set various axis properties (e.g., insets, the axis color, display axis yes/no, and display tick marks
yes/no).

The X axis will float up and down on the Y axis to always reflect the actual zero point on the Y axis. Y values may go positive
or negative, but successive X values must always increase (within a given data set). This X-axis restriction is consistent with
the strip chart nature of the graph. Usually, the X axis represents time, and successive measurements only increase in time.

The graph title is actually a Java Foundation Class (JFC) JL a b e l, so that the user has full control over the font, size, color,
and other text attributes. Also, the graph legend can be toggled on and off. If displayed, the legend will show the name of
each data set. If tick marks are also enabled, the value of the most recent data point for each data set is also displayed in the
legend. S ysS ta ts uses the S lid in g G ra p h extensively and is a good place to look for help on how to get started with this
useful Bean.

Team-Fly
Team-Fly

C ircu lar T e x t B u ffe r


The T e x tB u ffe r class uses a JT e x tP a n e and the new Swing document model to create a circular buffer of text lines. Once
the buffer is full, new lines are added to the bottom as old lines are removed from the top of the pane. A side benefit from
using a JT e x tP a n e is that you have full control over the attributes of the text such as font and color. If JT e x tA re a had been
used, all the text would be the same color and font.

Team-Fly
Team-Fly

A S /400 A P Is
The H o st class of S ysS ta ts uses a private inner class (often referred to as a helper class) called S ta tsR e a d e r to retrieve
system information from an AS/400. The S ta tsR e a d e r class has two different techniques available for accessing the
information on the AS/400.

The first technique uses the toolbox to call the QWCRSSTS API on the AS/400 directly. S ta tsR e a d e r has to call this API
three times whenever a reading is desired. The first call gets information available using the SSTS0100 format. The second
call gets information using the SSTS0200 format. A third call is then made using the SSTS0200 format to reset the averaging
interval on the AS/400 (equivalent to pressing F10 from the WRKSYSSTS screen). The S ta tsR e a d e r class also provides a
co n ve rtT im e sta m p method that uses the toolbox to call the QWCCVTDT API to convert the AS/400 time information to a
more useful format.

The second technique uses the toolbox S yste m S ta tu s class to get the same information I was manually retrieving from the
QWCRSSTS API. The S yste m S ta tu s class is much easier to use, and it would be great if you could reset the averaging
interval. Unfortunately, the toolbox designers neglected to put in this one critical feature. Hence, repeated calls to the
S yste m S ta tu s.g e tP e rce n tP ro ce ssin g U n itU se d () method will average the CPU utilization from the point of the first call
forward (like pressing F5 from the WRKSYSSTS screen). Deleting and recreating a S yste m S ta tu s object has no effect. You
must end and restart the connection to the AS/400.

Team-Fly
Team-Fly

C u sto m L ay o u t M an ag e rs
Often when using the layout managers provided by Swing, you can't find one layout that really does everything you need.
Most programmers use nested containers to get the desired effect. For example, you might add some objects to a JP a n e l
using a F lo w L a yo u t and then embed the JP a n e l in another JP a n e l that uses a G rid B a g L a yo u t. Sometimes, this nested
approach really starts to be cumbersome and difficult to maintain. (This approach also sometimes causes erratic behavior in
layout and repainting.) You can create your own layout manager to simplify your code and add some elegance and sanity
back to the application. S ysS ta ts uses a custom layout manager called M u ltiR o w L a yo u tF ill.

M u ltiR o w L a yo u tF ill allows you to assign objects to a given row. The layout manager will then always divide the display area
evenly between the number of rows vertically and evenly between the objects in the row horizontally. Objects in each row are
resized to evenly fill all the available room. No matter how the frame is resized, the objects will stay in their assigned row
(unlike F lo w L a yo u t, which can wrap objects to another row). Adding two objects to row zero then becomes simple:
myPanel = new JPanel();
myPanel.setLayout(new MultiRowLayoutFill());
myPanel.add("0", myObjectA);
myPanel.add("0", myObjectB);

To further simplify matters, S ysS ta ts uses a F illP a n e l class. This class is derived from JP a n e l. When the panel has only
one component, the component is always sized to fill the container. This feature overcomes some pesky problems with JDK
1.1 layout managers.

A second custom layout manager called R o w L a yo u t is provided as a bonus in the S ysS ta ts package but is unused.
R o w L a yo u t expands David Geary's (author of Graphic Java Mastering the AWT, 2nd ed., Sun Microsystems Press Java
Series) class by adding V_FILL and H_FILL options as well as demonstrating Sun's recommended implementation of
enumerations. (Enumerations are frequently used in C++ but are lacking in the Java spec.)

Team-Fly
Team-Fly

A lp h aw o rks Jav aB e an s
IBM alphaWorks consistently puts out high-quality, free JavaBeans available to everyone. S ysS ta ts uses two alphaWorks
JavaBeans: In iF ile and S N M P P ro to co l.

In iF ile is a standard in most of my applications. This JavaBean provides very simple access to a text .ini file familiar from
Windows 3.1. You should be aware, however, that a significant bug exists in the documentation for the In iF ile .g e tP ro p e rty
method. If a property does not exist, this method returns a S trin g object containing n u ll ll, not a true Java null. Tests for if
(x x x .g e tP ro p e rty (S trin g ,S trin g ) = = n u ll) will never return true. You must instead test for if(x x x .g e tP ro p e rty
(S trin g ,S trin g ).e q u a ls("n u ll"))
ll")).

S N M P P ro to co l is a JavaBean that handles the socket I/O and low-level communication with any SNMP manager (not just
the AS/400). SNMP was developed to provide a standard way to gather network management information from all devices in a
TCP/IP network. Provided the device has an SNMP manager, you can easily write applications to discover what devices are
running on your network, what their characteristics are, stats such as number of octets in and out of the device, and much
more information. The limits of this protocol are really just bounded by your imagination. For example, you could write a
simple application to routinely query all the devices in your network and alert when some device doesn't respond. To give you
a small taste of the power of this protocol, S ysS ta ts uses S N M P R e a d e r to routinely gather some octet count information for
each network interface in a given AS/400.

S ysS ta ts is also capable of receiving unsolicited SNMP trap messages from your AS/400. You do have to configure the
SNMP manager on your AS/400 to enable traps on the "public" community and to have the IP address of the station running
SysStats. To test if traps are working, end and restart the SNMP manager on the AS/400. You should get trap messages on
S ysS ta ts recording the stop and start.

S N M P P ro to co l does have one very noticeable bug, however. The designers of the class intended for users to use the
Im m u ta b le class to specify parameters on the calls to the various S N M P P ro to co l methods. However, the Im m u ta b le class
was not made public, so users of the S N M P P ro to co l class have no access to the Im m u ta b le class. The IBM alphaWorks
forum has acknowledged this bug and may issue a fix later. In the meantime, S ysS ta ts has to use the actual constant values.

Team-Fly
Team-Fly

C lo sin g S tatu s
S ysS ta ts provides a nice demonstration platform for many Java design techniques. Programmers can easily extract these
classes for use in their own applications. System administrators can take the base functionality of S ysS ta ts and expand it to
provide a robust AS/400 system management tool.

Writing S ysS ta ts has taught me that multithreading under Swing is much safer and simpler than under the old AWT model.
By sending R u n n a b le objects as messages, Java is coming ever closer to a pure OO language. I expect the future to bring
even more such advances.

The folks at IBM have also continued to show commitment to Java and integrating Java clients to the AS/400 with the AS/400
Toolbox for Java Modification 2 and the great JavaBeans from alphaWorks. Their work has made the AS/400 a useful server in
the Java world.

Team-Fly
Team-Fly

C h ap ter 64: F ree A n d E asy W ith W eb S Q L


O v e rv ie w
DON DENONCOURT

I am often amazed by how easily Internet applications can be developed using Java. Recently, I sat down to write a Web-
based interactive SQL utility. What I wanted was a replacement for SQL/400. I often used SQL/400 to create and maintain
DB2 for OS/400 files, but I was getting tired of starting a 5250 session only to enter one or two simple SQL statements and
then log off. What I wanted was a Java servlet that would allow me to enter SQL statements from a Web browser. I had been
thinking about developing this servlet for a few months, but, after reviewing the SQL hooks available with IBM's Java Toolbox
for the AS/400 Modification 2, I knew I could create my Web-based SQL processor quickly. In fact, it took me less than an
hour and only about a hundred lines of Java code. I called the resulting Java-based SQL server WebSQL.

The purpose of this chapter is twofold: to provide a freeware, Web-based interactive SQL product and to demonstrate how
easy it is to develop Web applications with Java. Figure 64.1 shows the Web page that prompts you for your SQL statement.
When you key in a SELECT statement (be sure to use the dot operator, not the AS/400 slash, for the library qualifier-e.g.,
DENONCOURT.CUSTMAST), WebSQL responds with a "subfile" (actually, it's an HTML table). Figure 64.2 provides an
example of such a subfile. Key in a CREATE, INSERT, UPDATE, DELETE, or DROP command, and the SQL database
maintenance statement executes. If anything goes awry, you get an HTML page that tells you what was wrong with your
SQL. For example, when I keyed in SELECT * FROM MYLIB.BOGUS, I received the following message on an error page:
"java.sql.SQLException: [SQL0204] BOGUS in MYLIB type *FILE not found."

F ig u re 64.1: The Submit button of an HTML input form functions like the Enter key of a 5250 screen, and the Reset
button works like F5=Refresh.

F ig u re 64.2: HTML tables are basically subfiles for the Internet.

Team-Fly
Team-Fly

The C ode
It would seem that coding WebSQL was complex, but it was really quite simple. All I did was use a few JDBC calls to invoke
the SQL statements and delegate the responsibility of formatting query results to a couple of the classes in IBM's
jt400S e rvle t.ja r from Modification 3 of IBM's Java Toolbox for the AS/400 (JT400). Figure 64.3 shows the HTML code for the
WebSQL prompt. All it contains is a simple HTML form (which is, basically, like a display file input record format) that is
composed of a single field called SQL. When the user clicks the Submit button, the value entered in the SQL text area input
field is sent to the WebSQL servlet to process the SQL request on the AS/400. If the user clicks the Reset button, the input
in the SQL text area is simply cleared.

F ig u re 64.3: The DDS for the WebSQL HTML file contains one "record format" (HTML form) and one input
field.

Team-Fly
Team-Fly

S e rv in g S Q L W ith Jav a
Figure 64.4 shows the complete code for my WebSQL Java servlet. It imports packages of Java classes that perform such
things as SQL execution and standard I/O. It also imports the Java extension classes for servlet processing. The servlet then
imports two Java packages that come with JT400 Mod 3: one that encapsulates access to HTML and one that builds Web
pages from JDBC result sets.

   

 
F ig u re 64.4: The AS/400's Web server invokes the doGet function of the WebSQL Java servlet when a user clicks the
Submit button on the HTML form .

The function called in it it, which is the initialization subroutine of a Java servlet, loads the JDBC driver (with a call to the
C la ss.fo rN a m e function) and establishes a TCP/IP connection to the AS/400 (with a call to
D rive rM a n a g e r.g e tC o n n e ctio nn). As with an RPG initialization subroutine, the in it function is invoked only once, so that all
remote users of WebSQL will use the same SQL connection. The Web server invokes the function called d o G e t when a user
clicks the Submit button of the HTML form shown in Figure 64.1. The d o G e t function of WebSQL, after setting the content
type and obtaining an output stream for the HTML, retrieves the values of the SQL input parameter SQL. If SQL is a SELECT
statement, d o G e t invokes the b u ild T a b le function; otherwise, d o G e t invokes the ru n U p d a te function.

The b u ild T a b le function uses JDBC's executeQuery function to retrieve the SQL SELECT statement's result set. If JDBC is
unable to run the SQL, b u ild T a b le calls the itD id n tW o rk function to dump the SQL error into a Web page. But if all goes
well, b u ild T a b le uses a JT400 Mod 3 class called H T M L T a b le C o n ve rte r to construct an HTML table from the SQL result
set. However, before H T M L T a b le C o n ve rte r can do its stuff, the user must wrapper the SQL result set with
S Q L R e su ltS e tR o w D a ta and set the format of an HTML table with the H T M L T a b le class. Once the user has created the
S Q L R e su ltS e tR o w D a ta object and constructed the H T M L T a b le
le, he invokes the co n ve rtT o T a b le s function of the
H T M L T a b le C o n ve rte r object to build a table such as the one shown in Figure 64.2. Finally, the user dumps the table to the
HTML output with the call to o u t.p rin tln (h tm lT a b le [0]).

When a user keys an SQL statement that is not a SELECT statement, the d o G e t function of WebSQL calls ru n U p d a te te. The
ru n U p d a te function simply invokes JDBC's e x e cu te Q u e ry function, passing to it the SQL statement that the user entered. If
the SQL statement doesn't run properly, the itD id n tW o rk function notifies the Web browser user of the error.

Team-Fly
Team-Fly

P o te n tial
I now have Web-based interactive SQL, and, on this book's CD, so do you. WebSQL begs for improvements and
enhancements. For one thing, you might want to shore up security for WebSQL. You might have noticed that all users of
WebSQL, as it is written today, use the same profile. One easy way to add a layer of security is to add a password/profile
HTML prompt to enable the AS/400's object-based security. Another suggested enhancement is to store the last 10 or so
SQL statements executed by a user in a cookie. Then, using JavaScript in the WebSQL.html file, you can display the last 10
SQL statements so that the user can cut and paste them into the SQL statement's text area.

The real focus of this chapter is not Web-based interactive SQL but the potential for Java-based Internet applications. If you
understand the architecture for my quickly coded yet powerful WebSQL application, then you will begin consideration for
crafting business applications for Internet deployment.

Team-Fly
Team-Fly

A p p en d ix: S o ftw are L o ad in g In stru ctio n s


The CD-ROM you receive with iSeries and AS/400 Java at Work contains all of the source code presented in the book. To
install this code, you'll need a PC with Sun's Java Development Kit 1.2.2 (JDK 1.2.2), Sun's Swing set of advanced GUI
components, and IBM's Java Toolbox for the AS/400 (JT400). However, a Java integrated development environment (IDE) such
as IBM's VisualAge for Java, Borland's JBuilder, or Symantec's Visual Café would be a superior development environment to
the JDK.

Jav a D e v e lo p m e n t K it
You can download Sun's JDK from java.sun.com/products/jdk /1.2/index.html. When the page is presented, select Java 2
SDK v 1.2.2 Windows 95/98/2000/NT Production Release. The downloaded file, which is a PC executable install program,
prompts you for the drive and directory name to which you intend to install the JDK. For this purpose, consider creating a
main directory called Ja va and a subdirectory called jd k1.2.2
k1.2.2. Later, if you opt to install the latest JDK (JDK 1.3), you can
install that JDK in a directory called jd k1.3
k1.3. Note that the examples in this book were tested with Java 1.2, but they should
work fine with Java 1.3. Actually, Java 1.3 provides significant improvements in the performance of the Java Foundation
Classes' (JFC) GUI components.

Team-Fly
Team-Fly

S w in g /JF C
If you use a Java IDE that doesn't yet support Java 1.2, you will need to download the Swing/JFC package from Sun's Java
Developer Connection site at java.sun.com/products/jfc/. Select "JFC 1.1 with Swing 1.1.1" and, once downloaded, make
sure to add sw in g a ll.ja r to your Java CLASSPATH.

Team-Fly
Team-Fly

A S /400 T o o lb o x F o r Jav a
You can download the latest IBM AS/400 Toolbox for Java to your PC from one of two places: the Integrated File System
(IFS) of your AS/400 (if it's V4R2 or later) or IBM's Java Toolbox for the AS/400 page. The IFS directory that contains the
jt4 0 0 .ja r file is /Q IB M /P ro d D a ta /H T T P /P u b lic/jt400/lib
lic/jt400/lib, and you'll find IBM's Java Toolbox for the AS/400 page at
www.as400.ibm.com/toolbox/downloads.htm. This book's companion CD contains the six .ja r files from the JT400
Modification 2 that are listed in Table A.1. Of these six files, the jt4 0 0 .ja r file contains the bulk of the AS/400 access
classes.

T a b le A .1: IB M 's JT 400 M o d ifica tio n 2's S ix JA R F ile s

N am e C o n te n ts
jt400.jar AS/400 access classes.
uitools.jar AS/400-specific GUI tools.
jui400.jar AS/400-specific GUI classes.
x4j400.jar XML parser.
data400.jar PCML classes.
util400.jar UI utility classes.

The jt4 0 0 .ja r file is required for DB2 for OS/400 record-level access, JDBC SQL access, program call, and command call.
The x 4j400.ja r archive file contains the Java XML processor code, and the d a ta 400.ja r archive file contains the
P ro g ra m C a llD o cu m e n t class and its associated classes (it's about 57 KB in size).

IBM's JT400 Modification 2 classes are available for free with OS/400 V4R4. Although the jt400.jar is included on the CD, a
beta for OS/400 V4R4 will work fine with V4R2 and V4R3. I suggest that you obtain the full set of downloads for the Java
Toolbox for the AS/400 so that you have the complete documentation available on your system.

OS/400 V4R5 ships with Java Toolbox for the AS/400 Modification 3. Modification 3 has some nice enhancements as well as
speed improvements. But if you don't want to load V4R5 on your AS/400 just yet, you can download the Modification 3
classes from IBM's JTOpen Web site. JTOpen is IBM's open-source version of the Java Toolbox. As of mid-2000, JTOpen
matched the Modification 3 level of Java Toolbox for the AS/400. If you go to www.as400.ibm.com/toolbox/ and follow the
JTOpen links, you can download the .jar files. The idea behind the JTOpen project is to provide a superset of functionality over
the Modification 3 license program product offering (5769JC1). Not only will fixes to the toolbox get to JTOpen faster than the
official PTFs, but JTOpen will have additional classes submitted by power AS/400 Java programmers.

Team-Fly
Team-Fly

C o m p ilatio n In stru ctio n s


The Java source files contained on the companion CD are in directories that correspond to the sections and chapters of this
book that contain code examples. You'll need to copy all of the C o d e directory, along with all of its subdirectories, to your
PC's hard drive. Each directory has a DOS batch file called M a ke .b a t that will perform the Java compiles required for
examples from that chapter. All of the required .ja r files (e.g., jt4 0 0 .ja r and R d b 2O b j.ja rr) are in the main C o d e directory. The
batch files, when required, have the CLASSPATH hard-coded in the make file.

The relational-to-objects frameworks .jar file (Rdb2Obj.jar) can be created with the following statement, which is contained in
the Make.bat batch file:
jar cvf Rdb2Obj.jar *.java *.class \
com/midrangecomputing/ObjectToRelational/*.java \
com/midrangecomputing/ObjectToRelational/*.class \
com/midrangecomputing/ObjectToRelational/*.htm \

If you are using a Java IDE, be sure the CLASSPATH required for your Java compiles is specified with project options.

The –classpath option of the JDK's javac compiler, by the way, would not be required if you create an environment variable
called CLASSPATH. If the javac compile command doesn't contain a –classpath option, the compiler looks for an environment
variable called—you guessed it—CLASSPATH. The following two statements, for instance, are in my autoexec.bat file:
SET CLASSPATH=%CLASSPATH%D:\java\jt00\lib\jt400.jar;
SET CLASSPATH=%CLASSPATH%D:\java\Swing\swing-1.1beta2\swingall.jar;

Team-Fly
Team-Fly

E x e cu tio n
Once the Java source files (.ja
.ja va suffix) are compiled into executable Java byte code (.cla
.cla ss suffix), those class files that
contain a m a in function may be executed. But before the m a in function can be executed, the DOS PATH and CLASSPATH
environment variables must be set. The PATH environment variable qualifies the location of the ja va .e x e file that starts the
Java Virtual Machine (JVM), which then executes the Java class specified as a parameter.

The JVM uses the CLASSPATH environment variable to find the packages specified in the IMPORT statements of the various
classes used in a Java application. To be able to test the HTML, servlet, and JavaServer Page examples from Section VII, you
can load the HTTP Server for AS/400 and WebSphere onto your AS/400. But, for a PC-based test environment for your server-
side Java applications, I suggest you use Sun's JavaServer Web Development Kit (JSWDK).

Team-Fly
Team-Fly

D e p re catio n E rro rs
You will notice that some of the make batch files will generate Java deprecation warnings or warnings that are issued when
you use functions of classes that have been flagged as obsolete. In some circumstances, the classes of this book use such
"obsolete" functions because they made the code easier to read and understand. For instance, Java's ja va .u til.D a te class
has now been effectively replaced with the ja va .u til.C a le n d a r class. Although the calendar class's implementation is far
superior to that of the date class, it's more difficult to use and understand.

I leave it as an exercise to you, the reader, to replace the deprecated functions used in this book with the new recommended
functions. To find the recommended replacement strategy, review the HTML documentation for the class that contains the
deprecated function. That document will suggest a replacement function or class.

Team-Fly
Team-Fly

In d ex
A
Abstract Window Toolkit (AWT), 53, 155, 157, 602, 674, 713, 717
Java Foundation Classes (JFC) and, 159, 159t, 160t, 165, 188
Spartan Order System Application example of, 696-697
Swing and, 674
accelerator keys, Java Foundation Classes (JFC), 188-191, 190
accept function, sockets programming, 286, 303, 311
Access, 398, 407
activation.jar files, 478
Active Server Page (ASP), 366, 377, 409, 446
ActiveX, 409-411
activity level monitoring, 545
Add Environment Variable (ADDENVVAR), 84, 86-87, 150
Add Link (ADDLNK) command, 151
Add Performance Explorer Definition (ADDPEXDFN), 534
Add Service Table Entry (ADDSRVTBLE), 299
Add TCP/IP Port Restriction (ADDTCPPORT), 299
addition, 34
addressing, in sockets programming, 297, 302-303, 308
Adobe Acrobat (See PDF files)
AIX, 6
ALL option, commitment control, 69
Allaire, 517
alphaWorks, 403, 519, 534, 548, 716-717
AND, 35
ANSI standards, PDF, 681
Apache, 403
applets, xxx, 8, 13-23, 27, 46, 49, 425, 435-436, 561, 673
applications vs., 19-20, 19t
attributes for, 16-18
design model for, 22-23
download time of, 103, 111-112, 111
Enterprise JavaBeans (EJBs) and, 567
HTML tag for, 14-17, 27
main method in, 20
methods for (init, start, stop, destroy), 14-16, 19, 20
paint, repaint, and update methods for, 16
proxy classes and, 46, 103-112
running, 16-18
security and, 26
servlet communication, 107
structure of, 14-16
threading and, 197
uses for, 21-22
Application Program Interfaces (APIs), 73, 417, 434, 672
sockets, 286, 286t, 288t
applications in Java, 13-23, 27, 39, 49
applets vs., 19-20, 19t
minimum requirements of, 59-59
proxy classes and, 111
uses for, vs. applets, 21-22
Enterprise JavaBeans (EJBs) and, 567
soft-coded values for (See soft-coded values for Java applications)
arithmetic operators, 34
arrays, 35-36
error, 383-384, 384
Java Foundation Classes (JFC), 169
JavaScript, 371
AS/400 and Java (See business case for Java)
AS/400 Client Access Express for Windows, 407
AS/400 Toolbox for Java (JT400), xxix, 11, 12, 23, 45-46, 48, 58, 73-75, 103, 259, 149
calling RPG from Java using, 269-270
CD-ROM companion disk, loading instructions, 728-729
classes in, 61
conversion classes in, 273-274, 274t
debugging and use of, 59-60
Modification 3 (Mod3), 89, 91
PTFs for, 60
Qshell and, 81-89
servers for, 59
Start Host Servers (STRHOSTSVR) command and, 59
ASCII, 296, 303, 334, 337, 633, 682
ASNA Visual RPG (AVR), 409, 411
assignment operations, 35
asterisk comment delimiters, 28-29, 41
asynchronous communication, xxxi
ATTRIBUTE property, GUI Builder, 222-223
attributes, class, 207
attributes, HTML, 344
AutoCommit, 146
awk shell program, 424

Team-Fly
Team-Fly

In d ex
B
Barnes, Jim, 229, 285, 327
base classes, 701
Bean-managed persistence EJBs, 562, 573-574, 578, 592
Beans, JavaBeans (See also Enterprise JavaBeans), 449-452, 457
interaction of, with servlets, JSP, WebSphere, 456-458, 458
servlet calls from, 453
servlets and, 460-462
setter methods for, 452
Berners–Lee, Tim, 343
BigDecimal, 273-274, 545-546, 547-553, 656, 705
bind function, sockets, 286
binding, Java Native Interface (JNI), 331
binding directories, sockets programming, 304
bitwise operations, 34-35
blocks of records, JDBC, 153
Bluestone Software, 517
boolean literals, 38
boolean operators, 35
bootstrapping, Java Foundation Classes (JFC), 166
Borland (See JBuilder)
Bourne shell, 418, 423
braces as statement block delimiters, 32-33
browser support, 27, 64-65
cookies, 388
Java Foundation Classes (JFC), 188
JavaScript, 369-370, 372, 376, 384-385
JavaServer Pages (JSP), 446-448
servlets, 437-438
XML, 402, 403, 404
XSL, 411
business case for Java, 47-48, 57-58, 72, 229, 257-267, 455-456
Business Planning and Control System (BPCS), 78, 79
79, 242
buttons (JButton), in GUI, 171, 176-177, 194, 263-266
byte code, 26, 27, 50, 53
bytes messages, 633

Team-Fly
Team-Fly

In d ex
C
C, 43, 228, 491, 602, 627
C++, xxviii, xxx, 6, 26, 41, 43, 220, 228, 532, 602
caching, 436, 544
CallableStatement, 123, 128, 278-284
calling objects using objects, 712-713
calling RPG from Java (See also Remote Method invocation), 114, 229, 236, 269-276, 533, 535
AS/400 toolbox for Java in, 269-270
CallableStatement for, 278-284
connection information for, 271
conversion classes for, 273-274, 274t
converting parameter values in, 275
data translation in, 334, 337
example program for, 270-274
exceptions and errors in, 284
Java Native Interface (JNI), 230, 327-339
binding in, 331
code for, 332-334
Create Service Program (CRTSRVPGM) values in, 338
data translation in, 334, 337
documentation bug in, 337-338
shell for wrapping RPG IV, 330-332
threading in, 333, 338
wrapper creation for, 334-337
JDBC for, 277-284
CallableStatement for, 278-284
classes used in, 281-282
JDBCCallableStatement in, 283-284
language used in, 280
parameter identification in, 281-282
retrieving (get) parameter values in, 282-283
stored procedure (Java.sql) for, 277, 278-281
parameter identification in, 281-282
parameter passing in, 269
path information for, 271
Program Call Generator in, 270
ProgramCall object for, 270, 273-277, 284
ProgramParameter object for, 270, 273, 274
Remote Method Invocation (RMI) and, 610-613
retrieving parameter values in, 275, 282
separating business rules from interface, 250
SmartGuide (wizard) for, in VAJ, 275-276, 275275, 276
steps in, 270
stored procedures for, 278-281
TRY block in, 271
URL and passwords for, 271
VAJ for, 269, 271
wrapper creation for, 334-337
Canvas class, GUI development, 218-219
Cascading Style Sheets (CSS), 415, 527
case sensitivity
JDBC, 150
Qshell, 85
CATCH, 54, 122, 211, 618, 675
cc command, Qshell, 420
CD-ROM companion disk, loading instructions, 727-731
CERN, 343
CGI coding, 232, 234-235, 343, 366, 377, 393, 431, 434, 435, 437, 491, 560
dynamic content in, 436
persistent, 465
stateless applications and, 464-465
CHAIN, 46, 75, 76
Change Network Attributes (CHGNETA), 60
CHANGE option, commitment control, 69
Change User Profile (CHGUSRPRF), 85
Channel Definition Format (CDF) in, 407
character literals, 38
check boxes, 348, 353
CL, 627
classes, 39, 50, 556, 602, 655-656
abstract window toolkit (AWT), 53
attributes of, 207
base, 701
constructors and, 161, 166, 700
creation of, 62
extending, 50, 76
final and static, 528
frameworks and, 77
helper, 715
inheritance in, 76
inner, 163
Java Foundation (See Java Foundation Classes), 155-156
JDBC, 118
naming, 658-659
packages of (See packages for Java)
private, 699
proxy classes (See proxy classes)
serialization and, 611
servlet, 96-102
sockets programming, 313
source files and, 53
static, 528, 702-703, 706
Window Foundation Classes (WFC), 157
wrappers for, 91-92, 92t
inheritance, 50
naming, 50
CLASSPATH, 58-59, 84-89, 129, 616
Add Link (ADDLNK) command for, 151
CD-ROM companion disk programs and, 730
for Display File Field Description (DSPFFD) utility, 667-668
for GUI Builder, 220-221
for JDBC, 150, 151
packages for Java classes and, 661
performance and, 528
proxy classes and, 110
for Remote Method Invocation (RMI), 608, 610
for SysStats Tracking Utility, 709, 711-712
for WebSphere Application Server, 515-516, 516
Clear Physical File (CLRPFM), 147
click events (See also event handling), Java Foundation Classes (JFC), 171
client/server, 8, 10, 22-23, 229, 257-258, 267, 329, 463, 601
separating business rules from interface, 242-244
client-side programming, 9, 21, 229, 263-266
JavaScript data input validation in, 376-382
close function, socket programming, 298, 304
clustering, 436
COBOL, xviii, xxviii, xxix, xxx, 26, 45, 61, 114, 142, 148, 228, 257, 365, 531, 532, 555, 615, 627, 631, 665
coded character set ID (CCSID), 527-528, 670
com.ibm.AS/400.util.html (See servlets)
com.ibm.AS/400.util.servlet (See servlets)
command line execution of Java app, 58
comments, 28-29, 41
commit method, 68, 69, 143, 146, 147
commitment /transaction control, 45, 61-70, 113-114, 141-148, 443, 694, 695, 698-699, 705
ALL option for, 69
AutoCommit in, 146
CHANGE option for, 69
commit method in, 68, 69, 143, 146, 147
CURSOR STABILITY option for, 69
DEFAULT option for, 70
dirty reads in, 142, 564
Enterprise JavaBeans (EJBs) and, 556, 564-566, 593-594
example application in JDBC (JDBCTransactions), 143-146
example application of, GenOrderTables, 62-68
files affected by, 69
isolation levels for, 143-146, 145t , 213, 564-565, 565t, 566
JDBC, 141-148
journaling for, 68-69, 145-146, 694
keyed file class for, 61-62
locking records and, 62, 69-70, 146-147, 564, 565
NONE option for, 70
nonrepeatable reads in, 142, 564
phantom reads in, 142, 564
READ operations and, 62
record-level access and, 148
rollback method in, 65-68, 69, 147, 699
sequential file class for, 61-62
sharing, 70
transaction attributes and, EJB, 564-567, 565t
transaction boundaries in, 142, 556, 565, 566, 695
transaction context in, 566
transactional integrity in, 147
communications
overhead of, 111-112, 111
remote, 107
compare operators, 35
compiling, 11, 26-27, 58, 615
CD-ROM companion disk programs, 729-730
encapsulation and, 74
JDBC program, 129
just-in-time (JIT), 26-27, 544
packages for Java classes, 659-660
Remote Method Interface Compiler (RMIC) for, 608
Remote Method Invocation (RMI), 603, 607-608
concatenation, 36
concurrency, 318
conditional statements, 29-32
connect function, sockets programming, 286, 303
Connection class, JDBC, 118-121, 126-134, 150, 151, 152, 195-197, 278
connection management, 54, 64-65, 74, 703-704
Connection Manager for, 526
dynamic menu example for, 181-186, 182
Enterprise JavaBeans (EJBs) and, 561
JDBC (See Connection class, JDBC)
pooling, 443, 526
SysStats Tracking Utility for, 709-710
Connection Manager use, 526
connection pools, 526
constants, 37
constructor methods, 53, 54, 161, 166, 700
containers, EJB, 560-562, 573-574, 578, 592-593, 592
container-managed persistence EJBs, 562, 573-574, 578, 592
containers, EJB, 595, EJB, 597-598
contention, servlet, 500-501
conversion classes, calling RPG from Java, 273-274, 274t
cookies, 341, 342, 387-395, 391
391, 426, 432, 443, 469
browser support for, 388
cookie function in, 388
creating, 388-391, 391
expiration date setting for, 391, 395
HttpServletRequest in, 395
HttpServletResponse in, 395
JavaScript and, 393
maintaining application state using, 392-395
programming for, 392
retrieveCookie function in, 388, 391-392
security and, 388
servlets and, 393, 394-395
setCookie function in, 388, 391
shopping cart applications and, 393
stateless applications and, 464-465
text for, 391
Copy Spool File (CPYSPLF), 681
Copy Spool File to Portable Document File
(CPYSPLFPDF) (See also Spool File to PDF
Conversion), 678
Copy to Stream File (CPYTOSTMF), 682
CORBA, 107, 559, 567, 585, 613
CPU utilization, SysStats Tracking Utility, 707
CREATE INDEX, SQL, 62, 116
Create Java Program (CRTJVAPGM), 83, 508, 528
performance and, 535, 545
Create Journal (CRTJRN), 69, 146
Create Journal Receiver (CRTJRNRCV), 69, 146
CREATE PROCEDURE, SQL, 278, 280
Create Service Program (CRTSRVPGM), 338
CREATE TABLE, SQL, 62, 116, 694
CREATE, SQL, 720
creation, retrieval, update, delete (CRUD) cycle, EJB, 570-573, 584, 592
cross-platform features of Java, 3-4, 26, 655
soft-coded values for Java applications, 617-626, 617
CURSOR STABILITY option, commitment
control, 69

Team-Fly
Team-Fly

In d ex
D
DASD utilization, 528, 707
Data Access Builder (DAX), 207, 702
data areas, 704-705
DATA CLASS property, GUI Builder, 222-223
data pools, 526-527
Data Queue Messaging (DQM) APIs, separating
business rules from interface, 254-255
data queues, 48, 329, 615, 616
legacy code transfer using, 235-236
data source names, JDBC, 118-119, 128
data types, 33, 56, 273-274, 339, 556
database
encapsulation in, 600-702
Java Naming and Directory Interface (JNDI) and, 595
performance and, 522, 524, 527-528
using XML, 398-399
database management systems (DBMS), 127, 197
DB2 for OS/400, 113, 125, 141
DDL files, Operations Navigator Java plug-ins, 652
DDS, 50, 262-263
deadlocks, 498, 501, 498, 713
debugging, xxxi, 615, 627-630
Integrated Source Level Debugger (ISDB) for, 627-630, 628
Tomcat for, 509-510
declaration statements, 29
declaring variables, 33-34
decrement, 34-35
DEFAULT option, commitment control, 70
Delete File (DLTF), 147
DELETE, SQL, 46, 117, 118, 122, 138, 720
Delphi, xxx
demarshaling, 602
Denoncourt, Don, 61, 81, 91, 115, 135, 141, 149, 201, 277, 365, 397, 427, 435, 445, 463, 503, 559, 569, 579, 627, 677, 693
deploying Java apps, 4-5
deployment descriptor, EJB, 562-563, 574, 594-595, 597
deployment descriptor generator (EJX), 598
deprecation errors, CD-ROM companion disk, 730-731
destroy method, 14-16, 19, 20, 492, 494
directories for Java, 81-82
home directories, 85-86
Java Naming and Directory Interface (JNDI) for, 635-636, 640, 595
Operations Navigator, 644-645, 645
profile and .profile files, Qshell, 86, 87-89, 88
dirty reads, 142, 564
Display File field Description (DSPFFD) utility, xxxi, 663, 665-675
display file programming
Java Blockmode User Interface (JBUI) package and, 76-77
XSL and, 410-411
Display Library Utility, socket programming example, 290-304
Display Network Attributes (DSPNETA), 60
dispose method, 673
distributed applications, Enterprise JavaBeans (EJBs) and, 558
Distributed Common Object Model (DCOM), 559, 567, 613
Distributed Computing Environment (DCE), 613
Distributed Data Management (DDM) server, 60
division, 34
DO, 30
Document Root, WebSphere, 514
document type definitions (DTDs), XML, 405-406
documentation, 41-43
documents, HTML, 345
doGet method, 95, 98-99, 310, 394-395, 438, 439, 442, 460, 468, 470-474, 585, 722
dollar sign ($), environment variable indicator, 85
doPost method, 394-395, 438, 439, 442, 443, 468, 471
download times, applets, 103
DQMCEXIT, 255
DQMCINIT, 255
DQMCRCV, 255
DQMCSND, 255
DQMSSND, 255
DriverManager class, JDBC, 118, 120-121, 126-129, 153, 195, 618, 623
drivers, JDBC, 114, 116, 118, 127, 149-151, 195, 277, 592-593, 618, 619
DROP, SQL, 720
drop-down lists, 378-380, 380
DROP PROCEDURE, SQL, 280
DROP TABLE, SQL, 117
dynamic content, 436, 440, 459
JavaServer Pages (JSP) and, 448, 450-452, 450
dynamic menus, 156, 181-186, 182

Team-Fly
Team-Fly

In d ex
E
EBCDIC, 277, 296, 334, 337, 527, 556, 633, 682
echo command, Qshell, 85
ECMAScript (See also JavaScript), 375
Edit File (EDTF), 88-89, 625, 625
editors
Edit File command, 88-89, 625, 625
Notepad/400 for, 624-625
XSL, 412
EDTF text editor, 625
ejb life-cycle methods for, 587-588
Electronic Data Interchange (EDI), 406-407, 415
elements, XSL, 411, 414
email (See JavaMail)
encapsulation, 46, 54, 71-80, 434, 699-702, 658, 694, 702, 713
file formats and, using JDB/400, 76
frameworks in, 77
interfaces and, 78
JAO/400 package for, 77
Java Blockmode User Interface (JBUI) package and, 76-77
JavaServer Pages (JSP), 449
JDB/400 package for, 75-76
record-level access and, 76
sample of, 74
servlets use of, 95, 102
subfile programming, 203, 207-208
End Performance Explorer (ENDPEX), 535
Enterprise JavaBeans (EJBs), xxx, xxxi, 256, 517, 555-568, 702
architectural standards for, 557, 560-562, 560
Bean-managed persistence, 562, 573-574, 578, 592
CGI vs., 560
client access to, 567, 580, 574-577, 583-584, 593-594
code for, Account management example, 581-588
commitment /transaction control in, 556, 564-566, 565t, 593-594
connection management and, 561
container-managed persistence, 562, 573-574, 578, 592
container-managed persistence, 573-574, 573
containers for, 560-562, 573-574, 578, 592-593, 595, 597-598
CORBA vs., 559, 567, 585
cost of, 558, 567-568, 567
creation, retrieval, update, delete (CRUD) cycle for, 570-573, 584, 592
DCOM vs., 559, 567
deployment descriptor for, 562-563, 574, 594-598
distributed applications and, 558
e-business design using, 559-568, 559
ejb life-cycle methods for, 587-588
enterprise Bean component of, 560-562
entity, 562, 567, 570, 572, 578, 592, 593
finder methods in, 595
firewalls and, 567
hidden methods of, 588
home interface for, 560-562, 570, 576, 578, 580-584, 580
580, 592
HTML and, 557, 567, 583
HTTP and, 567, 598
isolation levels in, 566
Java Archive (JAR) file deployment of, 598
Java Naming and Directory Interface (JNDI) and, 595
"JavaBean" defined for, 559
jBoss server for, 558, 591, 597-599
JDBC and, 558, 592-593
JOnAS server for, 558, 591, 595, 597-599
JSP and, 557, 583
JVM and, 599
legacy code and, 555
life-cycle methods for, 570-573, 584, 587-588, 592
locking records and, 563-565
method commitment in, 566-567
open source, 591-599
persistence and, 555-556, 562, 570, 573-574, 578, 592, 594
primary key class for, 570, 572, 576-577, 580-583, 580
580, 592
prototypes for, 557
remote interface for, 560-562, 570, 573, 574-577, 580-583, 580
580, 591-592
Remote Method Invocation (RMI) and, 558, 559, 577, 598-599, 601-613
roles of, 557
security and, 593-594, 598
separating business rules and interface using, 557
server-side programming and, 555, 569-578
servers for, 567-568, 558, 591-599
session, 562, 567, 570, 592, 593
skeleton classes for, 598-599
SQL and, 592
stateful, 562, 567, 592
stateless, 562, 592
stub classes for, 598-599
threading, Java threads and, 561
Tomcat and, 598
transaction attributes for, 564-567, 565t
transaction boundary in, 565, 566
transaction context in, 566
types of, 562-563
Web server and, 560
WebSphere and, 518, 557, 579-589, 591, 599
work management and, 556
wrapper function of, 570-573, 581
entity Beans, 562, 567, 570, 572, 578, 592, 593
entry fields, 260
enumerations, 716
environment of Java, 532-533
environment variables, 85
error arrays, 383-384, 384
Etymon, 678
European Computer Manufacturers Association (ECMA), 372, 376
event handling, 56-57, 57
Java Foundation Classes (JFC) and GUIs, 165, 171-172, 177, 185-186, 191, 263-266, 696-698
JavaScript, 369-370, 377
events, 56, 57
exception and error handling, 213
calling RPG from Java, 271, 284
GUIs, 260
JavaScript, 370-371, 383-384, 384
JDBC, 122
packages for Java classes, 659
separating business rules from interface, 246-247, 246 249, 251-252, 253, 254
246--249
sockets programming, 304
subfile processing, 206, 211-212, 212
212, 246-247, 246
246--249
TRY/CATCH, 54, 122, 211, 271, 618, 675
executable applications in Java, size of, 26
executable Java apps, 39, 81
EXFMT, 363
export command, Qshell, 83, 84-85, 87
extending a class, 50, 76
Extensible Markup Language (XML), xxx, 397-407, 632, 637-638, 646
browser support for, 402, 403, 404
Cascading Style Sheets (CSS) in, 415
Channel Definition Format (CDF) in, 407
content, structure, and presentation in, 399-405
databases using, 398-399
development of, 406
document type definitions (DTDs) for, 405-406
electronic data interchange (EDI) and, 406-407
Extensible Stylesheet Language (XSL) and, 403, 410, 411, 412
generating HTML using, 404-405, 404
GUI Builder and, 220
Java APIs for XML Parsing (JAXP), 637
Java Message Service (JMS) and, 637-638
Online Transaction Processing (OTP) and, 407
Open Financial Exchange (OFX) in, 407
POXML sample program for, 401-402
rules for, 405-406
tags, 399-400
uses for, 406-407
Extensible Stylesheet Language (XSL), xxx,
xxxi, 341, 342, 403, 409-415
ActiveX and, 409-411
attributes of elements in, 414
browser support for, 411
Cascading Style Sheets (CSS) in, 415
display file programming and, 410-411
editors for, 412
Electronic Data Interchange (EDI) and, 415
elements in, 411, 414
HTML and, 410, 411, 412-415, 414
nodes in, 411, 414
root node in, 414
separating business rules from interface using, 410-411
syntax of, 412-415
translations in, 411
treelike structure of, 411-412
XML and, 410, 411, 412

Team-Fly
Team-Fly

In d ex
F
false, 38
fat client, 436
FETCH, 128, 153
5250 and HMTL, 355-363
file names, 54-55
files, directories for, 81-82
final classes, 528
finalize, 673
finder methods, EJB, 595
firewalls
Enterprise JavaBeans (EJBs) and, 567
proxy classes and, 104, 106
flow layout manager, 715
FOR, 30-31, 139, 452
forking, 317
form ( ) HTML elements, 346-354, 361, 362, 431, 432, 438, 442, 452, 453, 459, 460, 470, 585
formatting HTML tags, 345
forms, HTML, 97, 342, 346-354, 347 347, 361, 362
arrays and JavaScript validation in, 371
check boxes in, 348, 353
client side validation using, 376-382
date validation in, 371, 378, 383
drop-down lists in, 378-380, 380
dynamic content in, 431-432
GET method and, 350
hidden fields in, 471
JavaMail, 479-481, 479479, 481
JavaScript for, 365-373, 375-385
list boxes in, 351-352
onKeyPress event in, 377
POST method and, 350
radio buttons in, 348, 354
regular expressions and, 382-383
selection lists in, 347-348
servlet for, 97-102, 100
100,
SnoopServlet example for, 433-434, 434
Submit button in, 348, 369-370, 377
text input fields in, 348, 353-354, 378-380
validating and verifying data input, using JavaScript, 366-368, 366
366, 376-382
Forte, 598
frames, in GUI, 160-163, 160
frameworks, 77
FTP, 316
fully qualified names, 152
function keys, 260

Team-Fly
Team-Fly

In d ex
G
garbage collection, 11, 524, 532, 533, 535, 541, 673
Garrison, Alex, 181, 426, 455, 519, 521, 664, 665, 707
Generalized Markup Language (GML), 406
GenIC, 598
GenOrderTables sample application, 62-68
GET method, 350, 428-429, 433, 438, 470
getter methods, 207, 699
in calling RPG from Java, 282-283
JDBC, 120, 129, 138-139, 198, 282-283
TRY/CATCH, 211
Goldfarb, Charles, 406
Goodwin, Walter, 46, 342, 417, 611
Grant Object Authority (GRTOBJAUT), 60
graphical user interface (See Java Foundation Classes [JFC] and GUI development)
green-screen UI, 259-260, 267, 616
CGI coding for, 232, 234-235
HTML emulation for, 356-357, 357
357, 363
JFC emulation for,260-262, 261
subfile programming and, 358-359, 358
358, 359
Workstation Gateway Server (WGS) for, 232, 234-235
grid bag layout manager, 194, 208, 211, 219, 715
GUI (See Java Foundation Classes [JFC] and GUI development)
GUI Builder, 215-226
appearance of, 221
ATTRIBUTE property in, 222-223
CLASSPATH setting for, 220-221
configuring and running, 220-221
converting Windows Resource files to XML for, 220
DATA CLASS property in, 222-223
displaying GUI in, 224-225
downloading latest version of, 220
help files, 223
HTML in, 223
JDK for, 221
New Panel in, 221, 222
Operations Navigator Java plug-ins and, 646
Panel Definition Markup Language (PDML), 220, 223-225, 646, 647-649
skeleton code creation for, 222-223
starting, 221
traditional design vs., 216-219, 216
tutorial on, 225
XML and, 220
GUI Programming application, 663

Team-Fly
Team-Fly

In d ex
H
header files, 41, 230
Header specification, in RPG, 39
headers, HTTP, 430, 430-431t
heap size, 524, 532
Hello World sample application, 39-40
help, 260
GUI Builder, 223
helper classes, 715
hidden fields, 471
hidden files, 89
hidden methods, EJB, 588
high-level languages (HLL), xxvii, 126
Holt, Ted, 125
home directories, 85-86, 85
home interface, EJB, 560-562, 570, 576, 578, 580-584, 580
580, 592
HTML (See H yp e rte x t Markup Language)
HTTP (See H yp e rte x t Transfer Protocol)
HttpServletRequest, 310, 395, 432, 433, 442, 448-449, 468, 476, 493
HttpServletResponse for, 310, 395, 432, 433, 442, 449, 493
Hypertext Markup Language (HTML) (See also forms, HTML; Spool File to PDF Conversion Utility), xxx, xxxi, 46, 91, 200,
319, 326, 341, 342-363, 399, 406, 409, 425, 426, 445-446, 491, 616, 637-638
applets and, 14-17, 27
attributes in, 344
check boxes in, 348, 353
class wrappers for, 91-92, 92t
classes in, 46
cookies and (See cookies)
documentation and Javadoc, 41
documents in, 345
dynamic content and, 431-432, 436, 440, 448, 450-452, 450450, 459
Enterprise JavaBeans (EJBs) and, 557, 567, 583
5250 emulation using, 356-357, 357 357, 363
form ( ) elements in, 346-354, 361, 362, 431, 432, 438, 442, 452, 453, 459, 460, 470, 585
form in, using servlet, 97-102, 100
formatting tags in, 345
GET method and, 350
GUI Builder and, 223
HTTP and, 356
JAR files and, 200
Java Message Service (JMS) and, 637-638
JavaScript and (See JavaScript)
JavaServer Pages (JSP) and (See JavaServer Pages)
list boxes in, 351-352
LotusXSL utility to generate, 404-405, 404
Panel Definition Markup Language (PDML) and, 220, 223-225, 646-649
performance and, 522, 523, 527
POST method and, 350
radio buttons in, 348, 354
tag for JavaScript, 369-370, 372, 378
selection lists in, 347-348
servlets and, 91-102, 432, 436, 443-444, 460, 493
SnoopServlet example for, 433-434, 434
stateless applications and, 387, 464-465
structural tags in, 345
subfile programming and, 358-362, 358358, 359
Submit button in, 348
tables in, 346, 361, 362, 720, 720
tables in, using servlets, 92-96, 93
93, 97-102, 100
tags in, 92, 93
93, 98, 344, 345-346, 361, 399
text input fields in, 348, 353-354
URLs in, 436-437, 437
utility packages for, 91-92
WebSQL Application, 664, 719-725
XSL and, 410, 411, 412-415, 414
Hypertext Transfer Protocol (HTTP) (See also Web servers), 23, 324, 326, 341, 342, 426, 457
CGI and, 437
cookies in (See cookies)
dynamic content in, 431-432
Enterprise JavaBeans (EJBs) and, 567, 598
GET method and, 350, 428-429, 433, 438, 470
headers, 430, 430-431t
HTML and, 343, 356
HttpServletRequest object in, 310, 395, 432, 433, 442, 448-449, 468, 476, 493
HttpServletResponse object in, 310, 395, 432, 433, 442, 449, 493
JavaServer Pages (JSP) and, server requirements for, 454
methods in, 433
port assignment in, 106, 428, 429
POST method and, 350, 428-429, 433, 438, 470
proxy server for, 422
request in, 428-429
response in, 429-431
servlets and, 324, 326, 492
SnoopServlet example for, 433-434, 434
stateless applications and, 393-395, 463-465
status codes for, 429, 430t
tunneling, 326
URLs in, 428-429, 436-437, 437
437,
WebSphere Application Server and, 513-514

Team-Fly
Team-Fly

In d ex
I
IF, 29
ILE C compiler, 417
import method, servlet, 308, 494
increment, 34-35
indexes, SQL, 116
inheritance, 50, 76
ini files, 667, 673
soft-coded values for Java applications, 618-620
IniFile JavaBean,716-717, 716
init method, 14-16, 19, 20, 492, 494
initialization of objects, 53
inlining methods, 546-547, 549
inner classes, 163
input inhibitor indicator, Qshell, 87
INSERT, SQL, 117, 122, 138, 143, 720
instance variables, 495-497, 528
integer literals, 38
integrated development environment (IDE), 25, 81-82, 215-216, 269-270, 417, 509, 615, 627, 709
Integrated Source Level Debugger (ISDB), 627-630, 628
interactive processing, SysStats Tracking Utility, 707
interfaces, encapsulation and, 78
International Organization for Standardization (IOS), 406
Internet, 228
Internet Explorer (See browser support)
Internet Mail Access Protocol (IMAP), 478-479
interpreted JDBC processing, SQL and, 122-123
IP addresses, 119, 285-287, 302-303
isolation levels, 143-146, 145t, 213, 564-566, 565t

Team-Fly
Team-Fly

In d ex
J
JAO/400 package, encapsulation, 77
Java APIs for XML Parsing (JAXP), 637
Java Archive (JAR) files, 20-21, 129, 198, 200, 546
download time of, 103-104, 111-112, 111
Enterprise JavaBeans (EJBs), deployment of, 598
packages for Java classes, 660-661, 660
proxy classes and, 103-112
Java Blockmode User Interface (JBUI) package, 76-77
JAVA command, 221, 312
Java Compatible, 5
Java Compiler (JAVAC) command, 58
Java Database Connectivity (JDBC), 61, 113-153, 229, 497, 632
AutoCommit in, 146
blocks of records, record buffer/record blocking in, 153
browsing through database in, 193-200
CallableStatement in, 123, 128, 278-284
calling RPG from Java using (See calling RPG from Java)
case sensitivity in, 150
classes in, 118
CLASSPATH setting for, 150, 151
commit method in, 143, 146, 147
commitment control in, 141-148
compiling example program in, 129-130
components of, 126
Connection class for, 118, 119, 120-121, 126-134, 150, 151, 152, 195-197, 278
Connection Manager for, 526
connection pools and, 526
data modifications using UPDATE, INSERT, DELETE, 122, 138, 143
data source names for, 118-119, 128
dirty reads in, 142
DriverManager class for, 118, 120-121, 126-129, 153, 195, 618, 623
drivers for, 116, 118, 127, 149-151, 195, 277, 592-593, 618, 619
Enterprise JavaBeans (EJBs) and, 558, 592-593
error handling, 122
getter methods in, 120, 129, 138-139, 198, 282-283
interpreted processing and, with SQL, 122-123
isolation levels for, 143-146, 145t
JAR files and, 198, 200
JDBCCallableStatement in, 283-284
journaling in, 145-146
labels (JLabel) in, 198
library lists for, 151-152
locking records and, 142, 146-147
metadata and, 130-134
native drivers for, 116, 149, 150, 151, 623-624
next method in, 128-129
nonrepeatable reads in, 142
ODBC drivers for, 150
100% Pure Java driver for, 116, 118-119, 149, 150, 623-624
open database connectivity (ODBC) and, 115-116
performance of, 135-140
phantom reads in, 142
platform support for, 125, 149
portability of, 134
prefetch setting, 153
PreparedStatement in, 123, 128, 135-140
properties files and, 619, 626
properties of, standard, 620-623, 622
pseudocompiles in, 135-136, 139
query execution in, 119, 128, 136, 138
record-level access and, 134, 148
ResultSet class for, 118, 119, 120-121, 126-129, 130-134, 138-139, 197-198
rollback method in, 147
RPG calls and, 236
running a program for, 129-130
server support for, 134
servlets and, 96
set processing in, 120-121
setter methods in, 139
soft-coded driver values for, 118, 150, 617-625
SQL and, 115-118, 125-126, 135-136, 141-142, 197
Statement class for, 118, 119, 120-123, 126-129, 135, 139-140, 197-198
stored procedures and, 128
synchronization and, 500
tables (JTable) in, 198-200
transaction boundaries in, 142
transactional integrity in, 147
user name and password for, 119, 128
Java Development Kit (JDK), 10, 11, 16, 25, 43, 49, 58, 59, 81, 116, 129, 150, 198, 658, 668
CD-ROM companion disk, loading instructions, 727-728
documentation bug in, 337-338
GUI Builder and, 221
JavaMail and, 478
performance, 544
Qshell and, 417-420, 424
SysStats Tracking Utility and, 708, 711
Java Event File (QAYPEJVA), 536, 537t
Java Foundation Classes (JFC) and GUI
development (See also separating business
rules from interface), xxx, xxxi, 21, 155-156,
157-164, 165-180, 258, 425, 695, 714
Abstract Window Toolkit (AWT) and, 155, 157, 159, 159t, 160t, 165, 188, 696-697
accelerator keys in, 188-191, 190
adding components to topmost panel in, 162-164, 219
arrays in, 169
bootstrapping in, 166
browser support and, 188
buttons (JButton) in, 171, 176-177, 194, 263-266
Canvas class in, 218-219
CD-ROM companion disk, loading instructions, 728
click events in, 171
closing a window in, 162-163, 166
components of, 159, 159t, 160t
cross platform support for, 158
DDS and, 262-263
Display File Field Description (DSPFFD) utility, 668
display file program and XSL, 410-411
dynamic menus in, 156, 181-186, 182
entry fields in, 260
error handling in, 260
event handling (Java.awt.event) in, 165, 171-172, 177, 185-186, 263-266, 696-697, 698
example application using, 160-162, 160
frame creation in, 160-163, 160
160, 165-166
function keys in, 260
green-screen interface and, 259-262, 261
grid bag layout manager for, 194, 208, 211, 219
GUI Builder for (See GUI Builder)
GUI Programming application, 663
inner classes in, 163
integrated development environment (IDE) for, 215-216
Java Blockmode User Interface (JBUI) package and, 76-77
labels (JLabels) in, 170-171, 193, 198
layout managers for, 170, 194, 219, 696, 698, 715-716
list boxes in, 698
list processing in, 171-172
listeners for, 185, 219, 263-266
lists in, 164, 167-170, 169
menu items added to menu in, 176-177
menus in, 163-164, 163163, 174-176, 175
175, 188-191
mnemonic pointers to menus in, for power users, 177-180, 178
multirow layout fill manager, 716
multithreading and, 713, 717
nested panes in, 715-716
output fields in, 260
Panel Definition Markup Language (PDML) in, 156, 220, 223-225, 646, 647-649
row layout manager, 716
scrollable panes in, 170
single vs. multipane inquiry and entry in, 259
SlidingGraph JavaBean, 714
Spartan Order System Application example of, 663, 693-706
status bar in, 156, 186-187
subfiles (See subfile programming)
Swing (Javax.swing) component of, 158, 165
tabbed dialogs in, 155, 157, 158, 164, 172-174, 172
tables (JTable) in, 155-158, 193, 194
194, 198-200, 201-213, 201
templates for, 165-180
text buffers in, 714-715
text fields in, 171
tool tips in, 177-180, 178
topmost panel in, 162, 166, 208
trees in, 155, 157, 158, 164
User Interface Manager (UIM) for, 158, 194
vectors in, 169-170, 172
Window Foundation Classes (WFC) and, 157
Java Message Queue, 639
Java Message Service (JMS), xxxi, 631-641
bytes messages in, 633
clients in, 633
delivery of messages in, 638-639
generating messages in, 635-638
HTML, 637-638, 637
Java APIs for XML Parsing (JAXP) in, 637
Java Naming and Directory Interface (JNDI) for, 635-636, 640
legacy interoperability and, 632
listener for, 638-639
map messages in, 634
message components in, 633-634
message oriented middleware (MOM) and, 632-633
object messages in, 634
persistence in, 638
point-to-point messaging in, 633
publish/subscribe messaging in, 633
queues for, 636
sending and receiving messages in, servlet example for, 634-639, 635
sources for, closed vs. open, 639-640
stream messages in, 634
text messages in, 634
topics for, 633
XML and, 637-638
Java Naming and Directory Interface (JNDI) and, 595, 635-636, 640
Java Native Interface (JNI), xxx, 21, 230, 327-329, 615
AS/400 toolbox for Java vs., 328-329
binding in, 331
calling RPG using (See calling RPG from Java)
code for, 332-334
data translation in, 334, 337
data types and, 339
documentation bug in, 337-338
functionality of, 339
legacy code reengineering in, 329
QJVAJNI service program for, in QSYS, 328, 336, 338
Remote Method Invocation (RMI) and, 613
shell for wrapping RPG iv, 330-332
Technology Independent Machine Interface (TIMI) and, 328
threading in, 333, 338
Java Performance Data Converter (JPDC), 534
Java Runtime Environment (JRE), 275, 711
Java Security Manager, 492
Java Transformer, 10, 11
Java Virtual Machine (JVM), xxviii, 10, 11, 13-14, 21, 23, 26, 27, 48, 49, 50, 106, 141, 150, 157, 318, 327, 491, 533, 534, 597-
598, 616, 708
CD-ROM companion disk programs and, 730
Enterprise JavaBeans (EJBs) and, 599
performance and, 522, 543
Tomcat and, 506
java.lang, 656
java.math, 656
JavaBeans, 7, 449-452, 559
JavaBeans Activation Framework (JAF), 478
Javadoc, 41
JavaMail, 426, 477-489
activation.jar files for, 478
error/used as error page for JSP, 479, 486-488, 488
488, 489
folder for "inbox" and incoming mail, 483
HTML form for servlet in, 479-481, 479
479, 481
Internet Mail Access Protocol (IMAP) for, 478-479
JavaBeans Activation Framework (JAF), 478
JDK and, 478
mail.jar files for, 478
Multipurpose Internet Mail Extension (MIME) and, 484, 485
POP3 and, 478-479, 481-483,
pop3.jar files for, 478
receiving messages using getMessage in, 483-484, 485
sending mail in, 485-488
servlet to read and send mail using, 479-481, 479
479, 481
sessions in, 481-483
Simple Mail Transfer Protocol (SMTP) servers for, 479, 481-483
uses for, 489
JAVAP command, 131
JavaScript, xxx, xxxi, 341, 342, 348, 354, 363, 365-373, 375-385, 436, 446
arrays in, 371
browser support for, 369-370, 372, 376, 384-385
client side validation using, 376-382
cookies and, 393
date validation in, 371, 378, 383
debugging, 371
development of, 376-376
drop-down lists validation in, 380-381, 380
error handling in, 370-371, 383-384, 384
extensions to, 372
Java vs., 365
Jscript vs., 376
modular programming and, 371-372
onKeyPress event, 377
onSubmit event, 369-370, 377
regular expressions and, 382-383
tag for, 369-370, 372, 378
validate function in, 370-371
validating and verifying data using, 366-368, 366
366, 376-382
JavaServer Pages (JSP), 91, 343, 359-362, 426, 444, 445-454, 455, 456, 503, 730
browser support, 446-448
compiling, 446-448
documentation for, 453-454
dynamic content and, 448, 450-452, 450
encapsulation in, 449
Enterprise JavaBeans (EJBs) and, 557, 583
error page for, using JavaMail, 479, 486-488, 488
488, 489
HTTP Server for AS/400 required for, 454
HttpServletRequest object and, 448-449
HttpServletResponse object and, 449
interaction of, with servlets, Beans, WebSphere, 456-458, 458
JavaBeans and, 449-452
parameter passed to, 461
performance and, 522
scriptlets in, 448-449
servlets and, direct calls to, 453
setter methods in, for Beans, 452
subfile programming and, 359-362
syntax of, 446-448
Tomcat and, 509-510
WebSphere Application Server and, 454, 511-512, 514, 515
JavaServer Web Development Kit (JSWDK), 617, 730
javax.servlet package, 492, 493
javax.servlet.http package, 492
javax.swing (See also Java Foundation Classes), 158, 165, 658
jBoss EJB server, 558, 591, 597-599, 639
JBuilder, 11, 23, 25, 49, 509, 630
JDB/400 package, 71, 75-76
JDBC (See Java Database Connectivity)
JDBCCallableStatement, 283-284
JDOM, 638
JOnAS EJB server, 558, 591, 595, 597-599
journaling, 68-69, 145-146, 694
JPanel, 715
JRun, 517
JScript, 376, 446
JScrollPane, 674
JTable, 656, 672, 674
just-in-time (JIT) compilation, 26-27, 544

Team-Fly
Team-Fly

In d ex
K
keyboard mnemonics (See menus; mnemonic pointers)
keyed files, commitment control and, 61-62

Team-Fly
Team-Fly

In d ex
L
labels (JLabel) in, 170-171, 193, 198
layout managers, 170, 194, 219, 696, 698, 715-716
learning curve for Java, 4, 6, 71, 141-142, 156
legacy systems and Java, xxx, 72, 227-230, 615-616
calling RPG from Java in, 269-276
CGI coding for, 232, 234-235
client/server and, 242
copying applications and modifying in, two versions of code, 232
data areas and, 704-705
data queues for, 235-236
direct use of green-screen UI on web site, Workstation Gateway Server (WGS) for, 232, 234-235
Enterprise JavaBeans (EJBs) and, 555
green-screen UI emulation in, 260-262, 261
Java Message Service (JMS) and, 632
Java Native Interface (JNI) and, 329
leveraging existing code and coding skills in, 256
MQSeries for, 235
Remote Method Invocation (RMI) and, 613
rewriting legacy code in Java, 232
RPG calls and, 236
sockets programming and, 236, 304-305
library lists, JDBC and, 151-152
life-cycle methods for EJBs, 570-573, 584, 587-588, 592
Lightweight Directory Access Protocol (LDAP), 640
Linux, 341, 599, 615
list boxes, 351-352, 698
listen function, sockets, 286
listeners, 56-57, 57
57, 263-266
for dynamic menus, 185
in GUI development, 219
for Java Message Service (JMS), 638-639
for Remote Method Invocation (RMI), 611
for subfile programming, 206-207
lists
display of, 77-78
in Java Foundation Classes (JFC), 164, 167-170, 169
169, 171-172
split-panel display of, 78, 79
literals, 38
LiveScript (See also JavaScript), 365
LiveWire, 446
locking records, 62, 146-147, 533, 550, 556, 564, 565, 700-701
block synchronization in, 498-499
commitment control and, 69-70
Enterprise JavaBeans (EJBs) and, 563-564
JDBC and, 142
synchronization and, 498
logical views, 116
loopback addresses, 119
looping, 30, 139
LotusXSL, 403, 411

Team-Fly
Team-Fly

In d ex
M
machine interface (MI), 532
mail.jar files, 478
main method in Java application, 18-19, 20, 39, 699
make command, 424
map messages, 634
Mark ham, Jeff, 103, 156, 193, 229, 315, 342, 375, 426, 477, 558, 591, 616, 631
markup languages, 344, 397, 406
marshaling, 602
mathematical operators, 40
Mayle, David, 342, 387, 426
memory use, 9, 21-22, 522, 544
menus, 163-164, 163
accelerator keys in, 188-191, 190
add items to, 176-177
dynamic, 156, 181-186, 182
Java Foundation Classes (JFC), 163-164, 163
163, 174-176, 175
175, 188-191
listeners for dynamic action in, 185
mnemonic pointers to, for power users, 177-180, 178
message oriented middleware (MOM), 616, 631, 632-633
messaging (See also Java Message Service)
calling RPG from Java, between client and server in, 253-255
MQSeries for, 235
metadata, JDBC and, 130-134
method calls, 535
method inlining, 546-547, 549
methods, 10, 41, 54-55, 533, 556, 601
static, 704, 706
middleware, in separating business rules from
interface, 253-255
mnemonic pointers to menus in, for power
users, 177-180, 178
Model View Controller (MVC), 458-462, 459
459, 673
modular programming, 371-372
modularization for legacy code (See also separating business rules from interface), 229, 231-240
benefits of, 234-236
data queues for, 235-236
MQSeries for, 235
Receive Data Queue (QRCVDTAQ) API in, 237, 239
RPG calls and, 236
RPG typical program structure, 233-234
Send Data Queue (QSNDDTAQ) API in, 237, 239
in separating business rules from interface, 231-234, 237-239
sockets programming for, 236
Monitor Message (MONMSG), 54
monolithic code (See also separating business rules from interface), 241-242
Mortgage Calculation sample application, 40
MQSeries, 235, 640
Muffin, as Qshell performance test, 422-425
multipane inquiry and entry, 259
multiplication, 34
Multipurpose Internet Mail Extension (MIME), 484, 485
multirow layout fill manager, 716
multithreading, 318, 713, 717

Team-Fly
Team-Fly

In d ex
N
name spaces, packages for Java classes, 656, 661
native call support, 48
native drivers, JDBC, 114, 116, 149, 150, 151, 623-624
negation, 34-35
nested panes in GUI, 715-716
Net.Data, 343
Netscape Navigator (See browser support)
network and Java, 7-9, 22-23
NEW keyword, 53, 54
next method, JDBC, 128-129
Njenga, Steve, 426, 491
nodes, XSL, 411, 414
NONE option, commitment control, 70
nonrepeatable reads, 142, 564
Notepad/400 for, 624-625
notify method, synchronization 499-500, 501
numeric literals, 38

Team-Fly
Team-Fly

In d ex
O
object-creation events, performance and, 535, 538, 541, 545-546, 547-553
object messages, 634
object-oriented (OO) programming, xxviii, 4, 12, 26, 47, 49-54, 57-58, 49, 62, 72, 203, 244, 256, 257, 418, 434, 449, 455, 532,
560, 570, 601, 655, 693
Object People, 702
object-to-relational wrappering, 702
objects, 60, 602
constructor and, 53
creation of, 55
initialization of, 53
serialization of, 106, 107
THIS keyword and, 55-56
O'Donnell, Shannon, 156, 215, 616, 643
100% Pure Java, 5, 11, 114, 568
JDBCdriver for, 116, 118-118, 149, 150, 623-624
Online Transaction Processing (OTP), 407
Open Database Connectivity (ODBC) (See also Java Database Connectivity), 115-116, 150
Open Financial Exchange (OFX), 407
Operations Navigator, xxxi, 616
Operations Navigator Java plug-ins, 643-653
Actions Manager class for, 645
classes for, 645-646
DDL file for, 652
GUI Builder and, 646
JVOPNAV folder for, 644
List Manager class for, 645
modifications to Java program, 649-651
modifications to sample, 647
Object Details class for, 646
Object List Interface class for, 646
Panel Definition Markup Language (PDML) in, 646, 647-649
"plug-in" defined for, 643
registering, 646-647, 651
requirements for, 643-644
samples of, IBM provided, 644
source files for, 647
string table in, 648-649, 648
testing, 652
tree structure of OpsNav and, 644-645, 645
optimizer, 525
OR, 35
OS/2, 5, 27, 258
OS/400, 10, 45, 341
output fields, 260

Team-Fly
Team-Fly

In d ex
P
PACKAGE statement, 656-657
packages for Java, 616, 655-661
CLASSPATH and, 661
compiling and executing a new package in, 659-660
core packages in, 656
creation of, 656-658
encapsulation and, 658
errors in, 659
Java Archive (JAR) files and, 660-661, 660
Java Foundation Classes (JFC) (See also), 656
java.lang, 656
java.math, 656
layered, 659
name spaces of, 656, 661
names of, 656, 658-659
PACKAGE statement for, 656-657
security and, 658
Swing, 658
packed decimal data, 273-274
page faults, 544
paint method, applets, 16
Panel Definition Markup Language (PDML) in, 156, 220, 223-225, 646, 647-649
parameter passing, 269
Pass directive, WebSphere Application Server, 514
passwords
AS/400 toolbox for Java and, 59
in calling RPG from Java, 271
in JDBC, 119, 128
as servlet instance variables, 495
path (See also CLASSPATH), 54-55, 54
PDF (See Portable Document File)
Pelk ie, Teresa, 341, 343
performance, 519, 543-553
activity level monitoring for, 545
analyzing results of tests in, 540-542
BigDecimal and, 545-546, 547-553
calculating, 531-532
CGI, 436
CLASSPATH settings and, 528
coded character set ID (CCSID) and, 527-528
collecting data for, using PEX, 538-540
Connection Manager use and, 526
Create Java Program (CRTJVAPGM) and, 528, 535, 545
data pools and, 526-527
database, 522, 524, 527-528
example of application tuning for, using BigDecimal, 547-553, 553
garbage collection and, 524, 532, 533, 535, 541
heap size and, 524, 532
HTML and, 522, 523, 527
Java Archive (JAR) files and, 546
Java Development Kit (JDK) and, 544
Java Event File (QAYPEJVA) and, 536, 537t
Java Native Interface (JNI), 328-329
Java Performance Data Converter (JPDC) and, 534
Java Server Pages (JSP) and, 522
Java Virtual Machine (JVM) and, 522, 543
locking records and, 550
method inlining and, 546-547, 549
object-creation events and, 535, 538, 541, 545-546, 547-553
optimizer and, 525
performance events to measure, 535-537
Performance Explorer (PEX), 519, 534-542, 534
534, 548
Performance Trace Data Visualizer (PTDV), 519, 534, 541, 542, 543, 546, 548-550,553
proxy classes and, 111-112, 111
Qshell, 422-425
QTMHHTTP and, 529
record-level access and, 525-526
servlet-to-servlet calls vs., 528
servlets and, 519, 521-529
SQL and, 525
storage pool page faults and, 544
StringBuffer and, 528, 545-546
synchronization and, 533, 546
system requirements and, 544
Task Information File (QAYPETASKI) and, 537, 537t
threading and, 533, 545, 549
tips for improving, 524-529
Tomcat, 508-509, 510
tracing, 533-536, 536t
Tracking AS/400 Vital Signs with SyStats Application for, 664, 707-718
tuning, 519
virtual machine events and, 541
Web server and, 436, 523
WebSphere and, 522, 523, 525
Performance Explorer (PEX), 519, 533-542, 534
534, 543, 548
Performance Trace Data Visualizer (PTDV), 519, 534, 541, 542, 543, 546, 548-550, 553
Perl, 393, 491
perl shell program, 424
persistence, 492
in Enterprise JavaBeans (EJBs), 555-556, 562, 570, 573-574, 578, 592, 594
in Java Message Service (JMS), 638
persistent CGI, 465
phantom reads, 142, 564
Phone servlet example application, 319-325
PING, 316
plug-ins (See Operations Navigator Java plug-ins)
Pluta, Joe, 45-46, 71, 229, 241, 257, 355, 663, 677
point-to-point messaging, 633
Polutta, Michael, 269
pools, data, 526-527
POP3, 478-479, 481-483
pop3.jar files, 478
portability of Java, 5-6, 9, 11, 50, 134, 491
portable document files (PDF), Spool File to PDF Conversion utility, xxviii, xxxi, 663, 677-691
ports
Add TCP/IP Port Restriction (ADDTCPPORT, 299
Display File Field Description (DSPFFD) utility, 668
proxy classes and, 104, 106
reviewing, using GO CFGTCP, 299
sockets and, 286-287, 297, 299, 302, 308, 316
threading and, 316
Tomcat, 505, 506
Web server programming, 428, 429
WebSphere Application Server, 513
well-known, 316
POSIX, 417, 418
POST method, 350, 428-429, 433, 438, 470
predicate in selection criteria for, SQL, 117
prefetch setting, JDBC, 153
PreparedStatement, 113, 123, 128, 135-140
primary key class, EJB, 570, 572, 576-577, 580-583, 580
580, 592
private classes, 699
productivity and Java, 6-7, 12
profile and .profile files, Qshell, 86, 87-89, 88
Program Call Generator, 270
program calls, 616
program temporary fix (PTF), 60
AS/400 toolbox for Java and, 60
WebSphere Application Server, 512, 517
ProgramCall object, 270, 273, 274-276, 277, 284
ProgramParameter object, 270, 273, 274
Progress Software, 639
Properties class, soft-coded values for Java
applications, 619-620
properties files, 615, 619, 626
proxy classes, 46, 103-112
classes supported by, 104
CLASSPATH for, 110
download times and, 103-104, 111-112, 111
firewalls vs., 104, 106
JAR file downloads using, 103-104
performance of, 111-112, 111
port to listen for, 104, 106
Qshell and, 110
servers and, 109-110
system property settings for, 106, 110
proxy servers, 46, 109-110, 422
pseudocompiles, JDBC, 135-136, 139
publish/subscribe messaging, 633

Team-Fly
Team-Fly

In d ex
Q
QCMD command interpreter, 418
QCMDEXC, 298
QCMN subsystem, record-level access, 60
QDCXLATE, 298, 303
QEJB library, WebSphere Application Server and, 513
QJVAJNI service program, in QSYS, 328, 336, 338
QSH commands (See also Qshell), 420-421
Qshell, 46, 81-89, 342, 417-424, 456
awk shell program, 424
Bourne shell design of, 418, 423
built-in utilities component of, 418-419, 419t, 422
calling RPG from Java using, 330-332
case sensitivity of, 85
cc command in, 420
command input in, 420-421, 421
commands for, 83, 83t
compatibility of, 421-422
components of, 418-421
current directory and cd function for, 87
documentation for, 418
echo command in, for CLASSPATH viewing, 85
editing of commands in, 421
export command in, 83, 84-85, 87
help for command use in, 83, 84
hidden files and, 89
home directories in, 85-86
input inhibitor indicator for, 87
Integrated File System (IFS) and, 81-82
interpreter component of, 420
Java Development Kit (JDK) and, 417-419, 420, 424
list (ls) command in, 89
make command in, 424
PATH and CLASSPATH setting for, 84-89
perl shell program, 424
POSIX and X/Open compatibility of, 418
profile and .profile files in, 86, 87-89, 88
proxy classes and, 110
QSH commands in, 420-421
Qstartup program, 86
regular utilities component of, 418-421, 420t
Remote Method Invocation (RMI) and, 612
Run Java (RUNJVA) command and CLASSPATH in, 86-87
shell programs defined for, 418
system command in, 83
threading in, 87
Tomcat and, 508
UNIX commands in, 419-420, 421
UNIX script test of, 423, 423t
wrappers in, 420
Qstartup program, Qshell, 86
QSYS library, 81, 304
QSYSINC, socket functions in, 287
QSYSOPR, SysStats Tracking Utility and, 707, 710
QTMHHTTP, 529
QUASPIBD, 304
queries, JDBC, 119, 128, 130-134, 136, 138
QUSCRTUS, 672
QUSER user profile, AS/400 toolbox for Java and, 59
QUSLFLD, 672
QUSLRCD, 672
QUSROBJD, 672
QUSRTVUS, 672
QUSRUSAT, 672
QWCCVTDT, 715
QWCRSSTS, 715

Team-Fly
Team-Fly

In d ex
R
race conditions, 713
radio buttons, 348, 354
READ operations, 62, 72
read/write functions, sockets, 286-287, 298, 303, 304
Receive Data Queue (QRCVDTAQ) API, 237, 239
record buffer/record blocking, JDBC, 153
record-level access, 45-60, 73, 269, 705
Application example for, 663
commitment control in, 61-70, 148
Distributed Data Management (DDM) server for, 60
encapsulation and, 76
JDBC and, 134, 148
network attributes setting for, 60
OBJAUT setting for, 60
performance and, 525-526
QCMN subsystem for, 60
sample application showing, 48-49
servlets and, 96
setup for, 60
Start TCP Server (STRTCPSVR) command and, 60
synchronization and, 500
user profiles for, 60
records, 55
Registry
plug-ins and, 646-647, 651
RMI, 603, 609, 609, 612
regular expressions, JavaScript and, 382-383
relational databases (RDBs), 115
relational operators, 35
remote interface
Enterprise JavaBeans (EJBs), 560-562, 570, 573, 574-577, 580-583, 580
580, 591-592
Remote Method Invocation (RMI), 603-606, 603
Remote Method Interface Compiler (RMIC), 608
Remote Method Invocation (RMI), 107, 558, 559, 610-613,640
batch process deployment of, 611-612
benefits of, 613
class development for, 603, 609-610
CLASSPATH for, 608, 610
client creation for, 603, 606-607
compilation for, 603, 607-608
CORBA vs., 613
deployment of, 611
Distributed Component Object Model (DCOM) vs., 613
Distributed Computing Environment (DCE) vs., 613
eight steps to, 603
Enterprise JavaBeans (EJBs) and, 577, 598-599
instantiation of object for, 610, 610
invoking, 603, 610-611
Java Native Interface (JNI) and, 613
legacy systems and, 613
listener for, 611
Qshell for, 612
remote interface development for, 603-604
remote interface implementation for, 604-606
Remote Method Interface Compiler (RMIC) for, 608
RMI Registry for, 603, 609, 612
sample application and code for, 602-603
serialization and, 611
skeleton classes for, 603, 608-609
stub classes for, 603, 608-609
threading and, 612
Remote Procedure Calls (RPC), 602
Remtema, Paul, 519, 531, 543
repaint method, applets, 16
ResultSet class, JDBC, 118, 119, 120-121, 126, 130-134, 138-139, 197-198
retrieveCookie function, 388, 391-392
reusability of code (See also Write Once, Run Anywhere), 5-7, 72, 76, 256, 258-259, 655, 657
rewriting legacy code in Java, 232
RMI Registry for, 603, 609, 609, 612
rollback method, 65-68, 69, 147, 695, 699
root node, XSL, 414
Ross, Eduardo, 342, 409
row layout manager, 716
RPG, xxvii, xxix, xxx, 45, 61, 71, 72, 114, 142,
148, 228, 230, 257, 285, 307, 365, 445, 456,
531, 532, 555, 560, 615, 627, 631, 665
calling from Java (See calling RPG from Java)
servlet client role for, 319-325
wrapper for, 334-337
RPG II/III, xxviii, 73
RPG IV, xxviii, 285, 73
Run Java (RUNJVA) command, 86-87, 312, 456
runaway threads, 498
Runnable objects, 713, 717
Rutledge, Keith, xxix, 1, 3, 13, 569

Team-Fly
Team-Fly

In d ex
S
Sample Applications, 662-726
Display File field Description (DSPFFD) utility, 663, 665-675, 666
666, 668
668, 669
669, 671
GUI Programming application, 663
Record Level Access Application, 663
Spartan Order System Application example, 663, 693-706
Spool File to PDF Conversion utility, 663, 677-691
Tracking AS/400 Vital Signs with SyStats Application, 664, 707-718
WebSQL Application, 664, 719-725
"sandbox" (See also security), 492
SanFrancisco project, 5, 11
Sapphire/Web, 517
scalability of Java, 9, 11
screen I/O, 229
tag for JavaScript, 369-370, 372, 378
scriptlets, 448-449
scrollable panes, Java Foundation Classes (JFC), 170
security, 8, 10, 23, 26, 436
cookies and, 388
Enterprise JavaBeans (EJBs), 593-594, 598
packages for Java classes and, 658
servlets and, 492
SELECT
in JDBC, 62
in RPG, 31
in SQL, 98-99, 117, 119, 120, 128, 135-136, 138, 142, 153, 197, 595, 664, 719, 720, 722
selection lists, 347-348
Send Data Queue (QSNDDTAQ) API, 237, 239
Send Socket Request (SNDSKTRQS), 299
separating business rules and interface, 557, 657
separating business rules from interface, 8-9, 229, 231-234, 237-239, 241-256, 454
benefits of, 234-236
calls in, 250
client/server and, 242-244
client side of, 249
Data Queue Messaging (DQM) APIs in, 254-255
exception and error handling in, 246-247, 246 249, 251-252, 253, 254
246--249
increased coding in, 255
JavaServer Pages (JSP) and, 449
messaging between client and server in, 253-255
middleware for, 253-255
object oriented approach to, 244
original program structure example for, 245-248
screen appearance in, 255
server client and, 243-244
server-side of, 252-253
structural changes to program required for, 249-251
XSL, 410-411
sequential files, commitment control and, 61-62
serialization, 106, 107, 611
server/client, 243-244, 267
server-side programming, 8, 9, 21, 229, 259, 341, 425-426, 445, 616
Enterprise JavaBeans (EJBs) and, 555, 569-578
servers (See also Web servers), 4, 8, 9, 259
AS/400 toolbox for Java and, 59
Enterprise JavaBeans (EJBs), 558, 567-568, 591-599
HTTP servers and, 109-110
JDBC support, 134
ports and, 316-317
proxy classes and, 109-110
proxy and, 109-110, 422
sockets programming and, 291-298
Web (See Web server)
service method (See also servlets), 491, 492, 493, 494
service table entries, sockets programming, 299
servlet engines, 318, 635
servlets, 62, 91-102, 229, 343, 425, 426, 435-444, 445, 455-462
accessing external resources for, 497-499
applet communication, 107
architecture of, 492
Beans and, 460-462
Beans, direct calls from, 453
browser support for, 437-438
calling servlets using, 528
classes of, 96-102
concurrency and, 494-495, 494
contention in, 500-501
cookies and, 393, 394-395
delays in processing of, 522
destroy method for, 492, 494
doGet method and, 95, 98-99, 310, 438, 439, 442, 460, 468, 470, 471-474, 585, 722
doPost method in, 438, 439, 442, 443, 468, 471
dynamic content in, 436, 440
encapsulation in, 95, 102
Enterprise JavaBeans (EJBs) and, 567
environment for, 493
Hello World example (SimpleServlet), 492-493
HTML and, 432, 436, 443-444, 460, 493
HTML class wrappers for, 91-92, 92t
HTML form example of, 97-102, 100
HTML table example of, 92-96, 9393, 97-102, 100
HTML utility packages for, 91-92
HTTP and, 324, 326, 492
HttpServletRequest object in, 310, 395, 432, 433, 442, 448-449, 468, 476, 493
HttpServletResponse for, 310, 395, 432, 433, 442, 449, 493
import statement in, 308, 494
init method for, 492, 494
instance variables in, 495-497
interaction of, with JSP, Beans, and WebSphere, 456-458, 458
Java Message Service (JMS), example, 634-639, 635
635, 634
JavaMail, read and send mail, 479-481, 479
479, 481
JavaServer Pages (JSP) (See also JavaServer Pages), 445, 453
javax.servlet package for, 492, 493
javax.servlet.http package for, 492
legacy systems and, 456-458
loading all at startup, to improve
performance, 526
Model View Controller (MVC) architecture example of, 458-462, 459
performance issues in, 519, 521-529
persistence in, 492
persistent CGI and, 465
Phone servlet example application, 319-325
portability of, 491
request processing in, 494-495, 494
RPG as client for, 319-325
sample of, for Web sever, 439-444
security in, 492
serial processing of, 497
server-side programming for, 326
service method for, 491, 492, 493, 494
servlet engines and, 318, 635
sessions in, 468-476
shopping carts and, 465-467, 466, 467, 468, 469-476, 470,
SnoopServlet example for, 433-434, 434
sockets programming and, 308-311, 315-326
statefulness and, 463-476
synchronization issues and (See synchronization issues)
threading in, 494, 496-497
Tomcat and, debugging, 509-510
URLs and, 318, 436-437, 437
uses for, 491-492
vectors and, 440
Web server programming and, 432, 436
WebSphere Application Server and, 318, 513-514
WebSQL Application and, 664, 719-725
session Beans, 562, 567, 570, 592, 593
session, in JavaMail, 481-483
sessions, 468-476
set processing, JDBC, 120-121
setCookie function, 388, 391
SETLL, 46
setsockopt function, sockets, 286
setter methods, 207, 213, 699
Beans, 452
JDBC, 139
Shaler, Richard, xxix, 1, 25, 45, 47, 426, 511
shared commitment control, 70
shell programming (See also Qshell), 341, 342, 418
shopping carts applications, 465-467, 466
466, 467 , 468
468, 469-476, 470
cookies and, 393
sign-on dialog box, 54
Simple Mail Transfer Protocol (SMTP), 316, 479, 481-483
Simple Network Management Protocol
(SNMP), SysStats, 707-708, 716-717
single- vs. multipane inquiry and entry, 259
singleton design, 203, 205
205, 703-704
64-bit computing, 9, 11
skeleton classes, 598-599, 603, 608-609
slash comment delimiters, 28-29, 41
SlidingGraph JavaBean, 714
Smalltalk, 26
smart parameters, 457, 461
SmartGuide (wizard), calling RPG from Java, 275-276, 275
275, 276
SNA, 602
SNADS, 316
SNMPProtocol JavaBean, 716-717
sockets programming, 7, 229, 236, 285-305, 307-313, 315-326, 329, 602, 608, 609
accept function in, 286, 303, 311
address for, 297, 302-303, 308
Application Program Interfaces (APIs) for, 286, 286t, 288t
bind function in, 286
binding, 287-290, 296, 297, 299, 304, 311
client in, 299-303
close function in, 298, 304
compiling sample program for, 303-304
connect function in, 286, 303
connecting to, 297-299, 311
creation of, 296-297
data translation in (ASCII to EBCDIC), 296, 298, 303
example use of, Display Library Utility program, 290-304
exception and error handling, 304
finding, in QSYSINC library, 287-290
function prototypes for, 287, 288t
host class for, 311-312
HttpServletRequest for, 310
HttpServletResponse for, 310
Java classes for, 313
legacy systems and, 304-305
listen function in, 286
number or descriptor for, 286, 298
port for, 286, 297, 299, 302, 308, 316
portability of sockets in, 308
read/write functions in, 286-287, 298, 303, 304
Send Socket Request (SNDSKTRQS) in, 299
server in, 291-298
service table entry for, 299
servlet using, 308-311, 315-326
setsockopt function in, 286
socket function in, 286, 296-297, 302
"sockets" defined in, 285-287
speed of, 308
toServer/fromServer objects for, 310-311
URL for, 312, 312
Web server programming and, 428
soft-coded values for Java applications, 615, 617-626
editing and editors for, 624-625
ini files and, 618-620
JDBC drivers and, 118, 150, 618, 619
Notepad/400 for, 624-625
Properties class in, 619-620
properties files and, 619, 626
standard JDBC properties and, 620-623, 622
Solaris, 599
SonicMQ, 639
source files, 50, 53
Integrated File System (IFS) and, 81
Operations Navigator Java plug-ins, 647
source objects, 56, 57
Spartan Order System Application example, 663, 693-706
spawning, 317
special characters, 38, 39
split-panel display, 78, 79
Spool File to PDF Conversion utility, xxviii, xxxi, 663, 677-691, 677
SpyderMQ, 639-640, 639
SQL, xxx-xxxi, 45, 48, 61, 114, 115-118, 125-126, 141, 229, 632
commitment control for, 143-148
connection and EJBs, 561
CREATE in, 720
CREATE INDEX in, 116
CREATE PROCEDURE in, 278, 280
CREATE TABLE in, 116, 694
DELETE in, 117, 118, 138, 720
DROP in, 720
DROP PROCEDURE in, 280
DROP TABLE in, 117
Enterprise JavaBeans (EJBs) and, 592
indexes in, 116
INSERT in, 117, 138, 143, 720
interpreted JDBC processing and, 122-123
JDBC and, 116-118, 125-126, 135-136, 141-142, 197
logical views in, 116
performance and, 525
predicate in selection criteria for, 117
rollback method in, 147
SELECT in, 117, 119, 120, 128, 135-136, 138, 142, 153, 197, 595, 664, 719, 720, 722
stored procedures in, 278-281, 525
tables in, 116, 145
UPDATE in, 117, 138, 143, 720
WebSQL Application and, 664, 719-725
WHERE clause in, 117, 118, 119
Standard Generalized Markup Language (SGML), 406
Start Host Servers (STRHOSTSVR) command, 59
start method, applet, 14-16, 19, 20
Start Performance Explorer (STRPEX), 535, 548
Start TCP Server (STRTCPSVR) command, 60
"starvation" of processing, 498
stateful applications, 387
cookies and, 392-395
Enterprise JavaBeans (EJBs) and, 562, 567, 592
servlets and, 463-476
stateless applications, 342, 387
cookies and, 392-395
Enterprise JavaBeans (EJBs) and, 562, 592
persistent CGI and, 465
servlets and, instance variables and, 463-476, 495-497
sessions and, 468-476
shopping carts vs., 465-467, 466
466, 467
467, 468
468,469-476, 470
solutions to, 464-465
statement blocks, 32-33
Statement class, JDBC, 118, 119, 120-123, 126-129, 135, 139-140, JDBC, 197-198
statements, 28-29
static classes, 528, 702-703, 706
static methods, 704, 706
status bars, 156, 186-187
status codes, HTTP, 429, 430t
stop method, applet, 14-16, 19, 20
storage pool page faults, 544
stored procedures, 229, 525, 616
Callable Statement and, 128
in calling RPG from Java, 278-281
JDBC and, 128
stream messages, 634
string table, PDML, 648-649, 648
StringBuffer, 528, 545-546
strings, 36-37, 39-40
STRJRNPF, 69, 146
structural HTML tags, 345
stub classes, 598-599, 603, 608-609
stylesheets (See Extensible Stylesheet Language)
subfile programming, 156, 201-213, 260, 358-359, 358
358, 359
Customer Update example in, 208-211
design tips for, 213
encapsulation in, 203, 207-208
error handling in, 206, 211-212, 212
212, 246-247, 246-249
HTML and, 358-359, 358358, 359
JavaServer Pages (JSP) and, 359-362
listeners for, 206-207
singleton design in, 203, 205
table creation for, 202-205, 202
tables (JTable) for, 201-213
WebSQL Application, 664, 719-725
Submit button, 348, 369-370, 377
Submit Job (SBMJOB), 312
subprocesses (See threading)
subtraction, 34
Sun, 6, 11, 49
SwiftMQ, 639-640
Swing (See also Java Foundation Classes [JFC] and GUI development), 158, 658, 674
SWITCH, 29, 31-32
symmetric multiprocessing (SMP), 9
synchronization, 426, 491-501, 533
block method for, 498-499
contention vs., 500-501
deadlocks and, 498, 501, 498
external resource access and, 497-499
locking records and, 498
notify method for, 499-500, 501
performance and, 546
threading and, 497
wait method for, 499-500, 501
syntax of Java, 1
SysStats, 664, 707-718
system command, Qshell, 83
system-managed storage, 10

Team-Fly
Team-Fly

In d ex
T
tabbed dialogs, 155, 157, 158, 164, 172-174, 172
tables, HTML, using servlets, 92-96, 93, 97-102, 100, 346, 361, 362, 720, 720
tables (JTable), 155-158, 193, 194, 198-200, 201-213, 202
adding components to, 212-213
Customer Update example of, 203-205, 203
203, 208-211
encapsulation in, 203, 207-208
error handling, 206, 211-212, 212
listeners and, 206-207
singleton design in, 203, 205
tables, in SQL, 116, 145
tags, HTML, 92, 93
93, 98, 344, 345, 361, 399
tags, XML, 399-400
TAR files, 660
Task Information File (QAYPETASKI), 537, 537t
TCP/IP, 4, 7-9, 23, 54, 58, 61, 65, 74, 142, 228, 229, 316, 602
Add TCP/IP Port Restriction (ADDTCPPORT), 299
HTTP and (See HTTP)
ports and, 316-317
sockets (See sockets programming)
SysStats Tracking Utility, 708
Tomcat and, 505
Web server programming and, 428
Work with TCP/IP Network Status (WRKTCPSTS), 299
Technology Independent Machine Interface (TIMI), 10, 11, 328
text buffers, 714-715
text input fields, in GUI, 171, 348, 353-354
text messages, 634
thick client, 425
thin client, 425
THIS keyword, 171
THIS keyword, 55-56, 171
threading, 197, 316, 317, 333, 338, 533, 672
block synchronization in, 498-499
contention and, 500-501
deadlocks and, 498
in Display File Field Description (DSPFFD) utility, 670
Enterprise JavaBeans in, 561
locking records and, 498
multi-, 713, 717
notify method synchronization in, 499-500, 501
performance and, 545, 549
Qshell, 87
Remote Method Invocation (RMI) and, 612
runaway, 498
servlet, 318, 494, 496-497
spawning or forking in, 317
"starvation" in, 498
status bar for, 188
synchronization and, 497-499
wait method synchronization in, 499-500, 501
Together/J UML tool, 202
Tomcat, 426, 454, 470, 503-510
Create Java Program (CRTJVAPGM) and, 508
debugging JSPs and servlets using, 509-510
Enterprise JavaBeans (EJBs) and, 598
home page of, 507
installing, 504-505
interactive running prohibited in, 506
JSP and, 509
JVM and, 506
performance tuning in, 508-509, 510
ports for, 505, 506
Qshell script for, 508
starting, 505-508
stopping/ending, 507-508
Web Archive (WAR) files and, 509
tool tips, in GUI, 177-180, 178
TOPlink, 207, 702
trace index file (QAYPETIDX), 535-536, 536t
tracing performance, 533-534, 535-536, 536t
Tracking AS/400 Vital Signs with SyStats Application for, 664, 707-718
transaction attributes, EJB, 564-567, 565t
transaction boundaries, 142, 556, 565-566, 695
transaction context, 566
transaction control (See commitment control)
transactional integrity, 147
transfer objects, 673, 713
translations, XSL, 411
trees, in GUI, 155, 157, 158, 164
true, 38
TRY, 54, 122, 211, 271, 618, 675
Tuck er, Galen, 616, 655
tunneling, HTTP, 326

Team-Fly
Team-Fly

In d ex
U
UCS Transformation Format 8 (UTF 8), 334, 339
unary operators, 34-35, 34
Unicode values, 38, 39
39, 339, 527, 556
Uniform Resource Locators (URLs), 7, 119, 127-128, 428-429, 435, 436-437, 437
437, 457
in calling RPG from Java, 271
in servlets, 318
in sockets programming, 312, 312
Universal Database, 398
Universal Multiple Octet Coded Character Set 2 (UCS 2), 337
UNIX (See also Qshell; sockets programming), 5, 85, 228, 305, 341, 342, 343, 382, 417-424, 534, 608, 660, 678
UPDAT, 75
update method, applets, 16
UPDATE, SQL, 117, 122, 138, 143, 720
User Interface Manager (UIM), 158, 194
user name/ID
in JDBC and, 119, 128
as servlet instance variables, 495

Team-Fly
Team-Fly

In d ex
V
validation, 207
Vandever, Kevin, 229, 231, 307
variables
declaration of, 33-34
servlets and, instance, 495-497
VBScript, 436
vectors, 106, 169-170, 172, 440, 546
view Beans, 457
virtual machine events, 541
Visual Age for Java (VAJ), 7, 11, 12, 23, 25, 49, 207, 215, 509, 557, 630, 702, 709
in calling RPG from Java, 269, 271
SmartGuide (wizard) in, 275-276, 275
275, 276
Visual Basic, xxx, 115, 411
Visual Café, 25, 630

Team-Fly
Team-Fly

In d ex
W
wait method, synchronization, 499-500, 501
Web Archive (WAR) files, 509
Web servers (See also HTTP; Tomcat; WebSphere Application Server), 425, 427-444, 455-456
CGI and, 436, 437
commitment/transaction control in, 443
connection pools for, 443, 526
cookies and, 432
dynamic content and, 431-432, 436, 440, 448, 450-452, 450
450, 450
Enterprise JavaBeans (EJBs) and, 443, 560
GET and POST requests in, 428-429, 433, 438, 470
headers in, HTTP, 430, 430-431 t
HTTP and, 427-44
HttpServletRequest object in, 432, 433, 442, 448-449, 468, 476, 493
HttpServletResponse object in, 432, 433, 442, 449, 493
JavaServer Pages (JSP) (See JavaServer Pages)
performance issues in, 436, 523
port assignment in, 428, 429
record-level access and, 443
request processing in, 428-429, 494-495, 494
response processing in, 429-431
servlet API example for, 439-444
servlets and, 432, 436, 491, 526
SnoopServlet example for, 433-434, 434
sockets programming in, 428
stateless applications and, 463-465
status codes for, in HTTP, 429, 430t
TCP/IP and, 428
Tomcat for, 503-510
URLs in, 428-429, 436-437, 437
Web site and Java, 4, 7-9
WebLogic, 574, 702
WebSphere Application Server, 317, 343, 426, 454, 455, 456, 457, 511-518
classpath settings for .class and .jar files in, 515-516, 516
competition for, 517
configuring, 512-516
data pools and, 526-527
Document Root for, 514
Enterprise JavaBean (EJB) support in, 518, 557, 579-589, 591, 599
FixPacks and E fixes for, 517
HTTP server instancing and configuration for, 513-514
installing, 512-516
interaction of, with servlets, Beans, JSP, 456-458, 458
JavaServer Pages (JSP) and, requirements of, 444, 454
JSP and, 511-512, 514, 515
Pass directive for access in, 514
performance and, 522, 523, 525
port for, 513
QEJB library and directories for, 513
required programs and PTFs for, 512, 517
RPG as servlet client in, 319-325, 319
server-side programming in, 326
servlets and, 318, 513-514
SnoopServlet example for, 433-434, 434
Tomcat vs., 503-510
Windows use of, 517
WebSQL Application, 664, 719-725
well-known ports, 106, 316
WHERE clause, SQL, 117, 118, 119
WHILE, 29, 30, 55, 120
Window Foundation Classes (WFC), 157
Windows, 5, 6, 228, 343, 534, 599, 615
WinZip (See Java Archive files)
work management, Enterprise JavaBeans (EJBs) and, 556
Work with Object Links (WRKLNK), 81
Work with Objects (WRKOBJ), 60
Work with System Status (WRKSYSSTS), 544
Work with TCP/IP Network Status (WRKTCPSTS), 299
Workstation Gateway Server (WGS), 232, 234-235
World Wide Web Consortium (W3C), 403, 411-412
wrappers, 73, 702
Enterprise JavaBeans (EJBs) as, 570-573, 581
HTML, 91-92, 92t
JNI functions, 334-337
object to relational, 702
Qshell, 420
WRITE, 75
Write Once, Run Anywhere (WORA) concepts, 5-6, 9, 12, 13, 47, 256, 258-259, 655

Team-Fly
Team-Fly

In d ex
X
X/Open, 418
xalan, 403
Xerces, 637
XML4J, 638
XSL (See Extensible Stylesheet Language)

Team-Fly
Team-Fly

In d ex
Z
zip files (See Java Archive Files)

Team-Fly
Team-Fly

L ist o f S id eb ars
C h ap te r 29: U sin g T h e JN I T o C all R P G F ro m Jav a
A source at IBM reported the following:

Team-Fly
Team-Fly

L ist o f F ig u res
C h ap te r 2: A p p le ts an d A p p licatio n s
Figure 2.1: An applet has four milestone methods: init, start, stop, and destroy .

Figure 2.2: HTML has a tag that allows you to embed a Java applet inside a Web page.

Figure 2.3: The applet tag qualifies the name of the applet and the size and location of the Java window with the Web
page.

Figure 2.4: The main method is the entry point of a Java application; it is automatically called when you invoke the JAVA
command and the application's class name from a command line.

Figure 2.5: The JAR command is similar to the Zip utility in that it has options that allow you to create a file that contains
compressed files and then to decompress those files.

C h ap te r 3: A n A S /400 P ro g ram m e r's F irst L o o k A t Jav a


Figure 3.1: The applet tag qualifies the name of the applet and the size and location of the Java window with the Web
page.

Figure 3.2: Java's SWITCH statement is similar to RPG's SELECT statement.

Figure 3.3: A behavior of Java's SWITCH statement that you need to be aware of is that without BREAK statements,
control logic continues to drop through the CASE clauses.

Figure 3.4: Blocks of code within IF/THEN/ELSE clauses are demarcated with braces.

Figure 3.5: Java has eight basic data types.

Figure 3.6: Variables can be declared and initialized with the same statement.

Figure 3.7: A Java application's main method is the entry point to the class.

Figure 3.8: Special characters can be inserted into a Java string using special values.

Figure 3.9: The syntax required for creating a Java "Hello World" program is quite simple.

Figure 3.10: The System.out.println method is an easy way to create simple screen output.

Figure 3.11: Mathematical operations are easily performed on Java's basic data types (int, double, long, and float).

Figure 3.12: This code is a self-documenting Java class.

Figure 3.13: The screen shows a sample HTML page generated with javadoc.exe.

C h ap te r 4: R e co rd
rd--L e v e l A cce ss W ith T h e A S /400
Figure 4.1: If you construct an object of the AS400 class without specifying system, user ID, and password, a Java sign-
on dialog will prompt the user for that information.

Figure 4.2: The ListCustomers application used the JT400's record-level access classes to list all the records of OS/400's
sample QCUSTCDT file located in the QIWS library.

Figure 4.3: Java GUI application classes normally extend the Abstract Window Toolkit's Frame class .

Figure 4.4: The ListWindowListener handles the window-closing event by terminating the application.

Figure 4.5: Event-driven programming with Java requires three objects: source, event, and listener.

C h ap te r 5: C o m m itm e n t C o n tro l F o r R e co rd
rd--L e v e l A cce ss
Figure 5.1: The GenOrderTables Java application creates the order header file, order- detail file, and unique indexes, and
starts journaling .

Figure 5.2: The OrderProcess Java application adds two orders, but the second order is not committed to DB2/400—it's
rolled back.

Figure 5.3: An SQL view of the order-detail file shows that records that are added to DB2/400 are available even before a
commit or rollback operation.

Figure 5.4: The rollback method retracts all operations made to the database within the most recent transaction context.

C h ap te r 6: E n cap su latio n : Jav a P o w e r W ith R P G S im p licity


Figure 6.1. This is a simple program fragment to read a source file.

Figure 6.2: This is the same code in Java, using only the classes in the JT400 .

Figure 6.3: This is the same code using the JDB/400 package .

Figure 6.4: This Jao400Split panel has been extended to display the Shop Order file from System Software Associates'
BPCS.

Figure 6.5: This is the entire code for the FSOSplit application.

C h ap te r 7: Q sh e ll A n d IB M 's Jav a T o o lb o x F o r T h e A S /400


Figure 7.1: Using the Work with Object Links panel is an excellent way to become comfortable with the IFS.

Figure 7.2: Java files are stored in directories within the IFS.

Figure 7.3: To display help for a command, simply issue it without parameters.

Figure 7.4: The special .profile script is executed each time you go into Qshell.

Figure 7.5: You can create an initial program for Qshell by putting a .profile script in your home directory.

C h ap te r 8: Jav a S e rv le t P ro g ram m in g F o r T h e H T M LL--C h alle n g e d


Figure 8.1: HTML tables are the "subfiles" of the Internet.

Figure 8.2: The HTML tags required to generate an HTML table manually are somewhat terse.

Figure 8.3: The com.ibm.as400.util.html allows you to generate an HTML table using the meaningful methods of object-
oriented classes rather than cryptic HTML tags.

Figure 8.4: The getNextRow method, with minimal lines of code, builds a new row for your HTML "subfile."

Figure 8.5: The ServletClasses servlet uses JT400's com.ibm.as400.util.servlet classes to list rows from the
QIWS/QCUSTCDT file in an HTML form .

Figure 8.6: The HTMLTableConverter class has the smarts to create a complete HTML table from an SQL result set.

Figure 8.7: It is handy to be able to quickly generate an HTML table from an SQL result set with minimal coding.

Figure 8.8: The HTMLTableConverter object does all the work of transforming data from an SQL result set into an HTML
table .

C h ap te r 9: R e d u cin g A p p le t C o d e S ize W ith P ro x y C lasse s


Figure 9.1: Java applets deployed in a business scenario often require the presentation of information retrieved from
complex relational database files.

Figure 9.2: The DBServlet servlet acts as a mediator between applets and DB2/400; it performs database retrieval from
DB2/400 and passes the result back to the applet as a serialized (text) file .

Figure 9.3: Each of the five applet configurations has a progressively smaller JAR file size.

C h ap te r 10: JD B C B asics
Figure 10.1: Most JDBC applications use the DriverManager, Connection, Statement, and ResultSet classes to access
relational data .

C h ap te r 11: G e ttin g T o K n o w JD B C
Figure 11.1: Java applications that use JDBC for data access are not tightly coupled to the AS/400 .
Figure 11.2: Relational data is available to your Java applications via JDBC.

Figure 11.3: Both the JDBC Connection and ResultSet objects contain metadata .

Figure 11.4: The metadata from the Connection and ResultSet objects can be used to dynamically set display attributes
such as column headers and entry lengths .

C h ap te r 12: P re p are Y o u r JD B C A p p licatio n s F o r P e rfo rm an ce


Figure 12.1: The main method of this example iteratively invokes the getCustomer method, which uses the
PreparedStatement object that was created in the application's constructor .

Figure 12.2: The setter methods of the PreparedStatement class are used to set the values of SQL statement
parameters.

Figure 12.3: The JDBCPreparedStatement class's main method lists all customers that have key values between 1 and
10.

C h ap te r 13: U sin g C o m m itm e n t C o n tro l W ith JD B C


Figure 13.1: The JDBCTransactions class is an example application that shows how to use commitment control to
ensure database integrity .

Figure 13.2: The invoice and invoice-detail files can be built with two simple SQL CREATE TABLE statements.

Figure 13.3: To be able to use commitment control with JDBC, the files must be journaled.

C h ap te r 15: Jav a F o u n d atio n C lasse s B asics


Figure 15.1: The JFrame component is a top-level application window that features a title and, optionally, a menu bar.

Figure 15.2: Most of your JFC GUI applications will use similar code to set up the window frame .

Figure 15.3: JFC components are added to the topmost panel of your application's GUI.

C h ap te r 16: JF C D e v e lo p m e n t W ith T e m p late s


Figure 16.1: The minimal JFC application extends JFrame, bootstraps the application in main, and sets a topmost panel
in its constructor.

Figure 16.2: A minimal JFC application has a window frame and code that handles the window-closing event.

Figure 16.3: To handle the events generated from the application's GUI components, the simplest JFC applications
extend ActionListener and implement the actionPerformed method .

Figure 16.4: JFC's JList list box component has a different behavior than its AWT predecessor, List.

Figure 16.5: A JTabbedPane component is a container for one or more JPanels.

Figure 16.6: The FrameWithTabbedDialog application adds three JPanel objects to a JTabbedPane (part 1 of 2).

Figure 16.7: The various panels of a tabbed dialog can each contain completely different components.

Figure 16.8: Panels are added to a tabbed dialog with the addTab method of the JTabbedPane class.

Figure 16.9: Adding a menu to the window frame is a straightforward process.

Figure 16.10: The FrameWithMenuV1 class shows how easy it is to add a menu to a window frame .

Figure 16.11: The GUI events generated with menu selection and button clicks are handled with the actionPerformed
method.

Figure 16.12: Version 2 of the frame with a menu application handles the menu selection events and provides tool tips
and keyboard

Figure 16.13: The FrameWithMenuV2 class adds tool tips to help user neophytes and keyboard mnemonics to appease
user experts.

C h ap te r 17: C h ro m ee--P late Y o u r Jav a G u i W ith D y n am ic M e n u s A n d A S tatu s B ar


Figure 17.1: The menus of GUI applications should reflect the current state of the application by enabling, disabling,
adding, or removing menu options.

Figure 17.2: The DynamicMenu Java application can be used as a skeleton from which you can develop your own
dynamic menus .

Figure 17.3: The StatusBar class manages the presentation of an application's status at the southern border of the
window frame .

Figure 17.4: Accelerator keys save you the time of selecting items from menus.

Figure 17.5: The Java source for AWTMenu shows just how easy it is to assign accelerator keys to menu options .

C h ap te r 18: Ju st B ro w sin g W ith JD B C


Figure 18.1: The Inquiry applet displays a custom JTable "subfile" after the user fills in the customer and order number.

Figure 18.2: The Form class loads the JDBC driver, establishes a connection, and creates the GUI components of the
applet .

Figure 18.3: The Detail class subclasses Java Foundation Classes' JTable "subfile" class to create a custom multicolumn
view .

C h ap te r 19: C h e ap Jav a S u b file P ro g ram m in g T ricks


Figure 19.1: Users of the customer update application click on the row of a customer to modify that customer's record.

Figure 19.2: The Update Customer Master Record window allows the user to update the customer selected from the
Customer subfile.

Figure 19.3: The UML object model of the customer update application graphically displays the collaboration of Java
objects to host an application.

Figure 19.4: The CustomerTable class uses the AS/400 Toolbox for Java's SQLResultSetTablePane to create a subfile
with one Java statement .

Figure 19.5: The SQLConnect class is an example of the singleton design pattern, which is used to ensure that only one
SQL connection is used in the application.

Figure 19.6: The CustomerUpdate class uses a JFC JPanel set to the GridLayout layout manager to prompt the user to
update customer fields .

Figure 19.7: The InvalidLengthException class is an example of how easy it is to create application exception messages.

Figure 19.8: The JFC's JOptionDialog is easily used to present an error dialog.

C h ap te r 20: G U I B u ild e r M ake s Jav a G U I D e v e lo p m e n t E asy


Figure 20.1: Here's a very simple Java GUI.

Figure 20.2: This is the traditional method of coding a Java GUI .

Figure 20.3: GUI Builder lets you develop Java GUIs very rapidly.

Figure 20.4: Here's the PDML file generated by GUI Builder for the example.

Figure 20.5: Contrast this Java code with that shown in Figure 20.2. Both display the same GUI.

C h ap te r 21: A p p licatio n M o d u larizatio nn—


—S e p aratin g P re se n tatio n A n d
P ro g ram m in g L o g ic
Figure 21.1: User interface and business logic are traditionally linked together in this way .

Figure 21.2: This is what the screen looks like when you run it after a request is entered.

Figure 21.3: Separating out the user interface from the business logic gives green-screen users the UI they are
accustomed to .

Figure 21.4: The new version of the business-logic program uses data queues to communicate with the UI. .

C h ap te r 22: B re akin g A p art T h e M o n o lith


Figure 22.1: The pseudocode for the original, monolithic program is straightforward. .

Figure 22.2: The item select program allows the user to enter an item number and select the action to perform.

Figure 22.3: In View mode, all entry fields are protected.

Figure 22.4: While in Modify mode, only the key fields are protected.

Figure 22.5: If errors are encountered, the invalid fields are highlighted and the messages are displayed in a message
subfile.

Figure 22.6: To break apart your monolith, you must separate your business logic from the display logic.

Figure 22.7: It is the responsibility of the client to relay messages to the user.

Figure 22.8: The structure of the maintenance program is very modular.

C h ap te r 23: T h e B u sin e ss o f Jav a


Figure 23.1: The item select program allows the user to enter an item number and select the action to perform.

Figure 23.2: In View mode, all entry fields are protected.

Figure 23.3: While in Revise mode, only the key fields are protected.

Figure 23.4: If errors are encountered, the invalid fields are highlighted and the messages are displayed in a drop-down
list.

Figure 23.5: ItemMaintainer, at less than 100 lines, replaces the ITMSEL program (and its DDS) on the AS/400. (part 1 of
2)

Figure 23.6: It's easy to configure a completely different entry panel using the base classes EntryField,
VerticalEntryFieldPanel, and ButtonPanel.

C h ap te r 24: C allin g R P G F ro m Jav a


Figure 24.1: The XMPCALR3 RPG program accepts two parameters: packed and character.

Figure 24.2: The ExampleProgramCall constructor encapsulates the implementation to call PROGRAMLIB/XMPCALR3.

Figure 24.3: VAJ's SmartGuide for creating a ProgramCall object prompts for the class name to create and the name and
location of the AS/400 program.

Figure 24.4: VAJ's ProgramCall SmartGuide makes it easy to specify AS/400 program parameters and their associated
Java data types.

C h ap te r 25: In v o kin g R P G V ia JD B C
Figure 25.1: JDBC's CallableStatement class can be used to invoke AS/400 RPG programs .

Figure 25.2: The INV001 RPG program has zoned, packed, and character parameters.

Figure 25.3: The CallableStatement class inherited its setter methods from its parent class, PreparedStatement.

Figure 25.4: Return values from your RPG program are retrieved from calls to the CallableStatement object's getter
methods.

Figure 25.5: You should create a Java class that is an object-oriented wrapper to your legacy program using standard
encapsulation techniques so that the class can be used over and over.

C h ap te r 26: T C P /IP S o cke ts P ro g ram m in g


Figure 26.1: The C APIs are available from RPG given the appropriate set of RPG prototypes.

Figure 26.2: RPG socket clients need to copy the socket prototypes.

Figure 26.3: RPG socket clients also use the same C APIs .

C h ap te r 27: U sin g Jav a S o cke ts P ro g ram m in g


Figure 27.1: Servlets dynamically construct HTML to communicate with Web users and can communicate with legacy
applications through Java's simple sockets API .

Figure 27.2: A servlet responds to remote requests from URLs and HTML form submissions.

C h ap te r 28: S e rv le ts, S o cke ts, A n d R P G


Figure 28.1: With TCP/IP, RPG can be a client to a Java servlet .

Figure 28.2: A Java client can speak to the servlet and receive data back just as the RPG client in Figure 28.1 does.

C h ap te r 29: U sin g T h e JN I T o C all R P G F ro m Jav a


Figure 29.1: Java applications can benefit from legacy "native" application code.

Figure 29.2: You can use RPG subprocedures to provide code implementations for Java methods .

Figure 29.3: Modularized back-office RPG code can be used by both Java and RPG front-ends .

Figure 29.4: Each RPG subprocedure requires a wrapper to convert EBCDIC to Java data types.

Figure 29.5: To use the JNI environment, you'll need access to a copy book of data structures.

C h ap te r 30: H T M L B asics
Figure 30.1: The Query Options form accepts several types of user inputs.

Figure 30.2: Form elements, the most important HTML elements for Web programming, accept user inputs .

C h ap te r 31: H T M L : T h e N e w 5250
Figure 31.1: A typical 5250 maintenance screen presents a panel that the user fills in. After the user presses Enter or
one of the 24 function keys, the contents of its record format are sent to a program for processing.

Figure 31.2: A Web-based maintenance screen functions much like its 5250 ancestor.

Figure 31.3: Any competent AS/400 programmer knows how to effectively code 5250 subfiles.

Figure 31.4: AS/400 programmers who become Web programmers will need a strategy that is equivalent to 5250 subfiles.

Figure 31.5: This is the source code for a JavaServer Page designed to support the subfile browser panel in Figure 31.4 .

C h ap te r 32: H T M L F o rm V alid atio n W ith Jav ascrip t


Figure 32.1: Basic editing of dates, codes, and mandatory fill fields should be performed on the client, not on the server.

Figure 32.2: JavaScript is embedded into HTML. It is parsed and interpreted by the Web browser, not the Web server .

Figure 32.3: You should use modular programming techniques with JavaScript.

C h ap te r 33: A d v an ce d H T M L F o rm V alid atio n W ith Jav ascrip t


Figure 33.1: The HTML input form contains input fields that should be validated on the client .

Figure 33.2: This form will be validated with JavaScript.

Figure 33.3: This code is used to validate that the user has selected a value from the drop-down list other than the first
value.

Figure 33.4: Display as many error messages as you can in a single dialog box.

C h ap te r 34: U sin g C o o kie s T o P ass P aram e te rs B e tw e e n W e b P ag e s


Figure 34.1: With a few lines of JavaScript (which work in both Netscape and Internet Explorer), you can maintain user
state with cookies .

Figure 34.2: This simple cookie JavaScript application informs the browsing user how often he has visited this page.

Figure 34.3: This Web application, called CookiesServlet, lists all the cookies sent from the Web browser.
C h ap te r 35: X M L : T h e U b iq u ito u s L an g u ag e O f T h e In te rn e t
Figure 35.1: Using the AS/400's DDS, you can define the structure for a database file.

Figure 35.2: SQL can be used to list the contents of related files.

Figure 35.3: DDS field names can be used as XML tags to define the structure of an XML document.

Figure 35.4: Internet Explorer 4.0 ships with a Java applet that can be used to present XML data in an HTML file.

Figure 35.5: HTML's applet tag is used to invoke Microsoft's XMLDSO Java class that retrieves content from an XML
document for HTML presentation .

Figure 35.6: HTML can be generated using one of the several available, free XSL processors.

Figure 35.7: Lotus's LotusXSL is an XSL processor that converts XML to HTML .

Figure 35.8: Document type definitions are where you specify rules that an XML document must conform with to be a
valid document for that specific implementation of an XML language.

C h ap te r 36: X S L S ty le sh e e ts: D isp lay F ile s O f T h e W e b


Figure 36.1: This is the XML article listing to be transformed into HTML.

Figure 36.2: A single template in this XSL stylesheet is used to transform the list of articles into a displayable HTML
table.

Figure 36.3: The transformation from XSL to HTML gives this browser display.

C h ap te r 37: U n ix D e v e lo p e rs F in d A H o m e In Q sh e ll
Figure 37.1: The Qshell screen allows you to enter shell built-in utilities as well as Java commands.

C h ap te r 38: T h e "L ittle W e b S e rv e r" P ro je ct


Figure 38.1: An HTTP response packet contains basic information about the response and an embedded HTML file.

Figure 38.2: Java servlets dynamically build content based on user input from an HTML form.

Figure 38.3: IBM's WebSphere version of SnoopServlet shows information contained in my HTTP request, including a
cookie.

C h ap te r 39: S e rv in g U p H o st-B ase d Jav a A p p s


Figure 39.1: When a Web server sees the servlet qualification on a URL, it invokes the named Java servlet.

Figure 39.2: HTML forms can associate a Java servlet to process the user request.

Figure 39.3: The Seminar servlet creates a registration form in its doGet method and processes that form in its doPost
method.

Figure 39.4: The HTML response from a servlet contains dynamic information.

Figure 39.5: Whether you use Java servlets or RPG CGI, the point is to interact with the user.

C h ap te r 40: Jav aS e rv e r P ag e B asics


Figure 40.1: The servlet code automatically generated by the Web application server's page-compile process is ugly.

Figure 40.2: JavaServer Pages are processed on the host to dynamically generate HTML to be sent to Web browsers.

Figure 40.3: The <jsp: useBean> tag references a JavaBean so that the JSP file can invoke the functions of that
JavaBean.

Figure 40.4: A JavaBean is a Java class that is coded to follow a simple but standard strategy for coding function
interfaces .

C h ap te r 41: S e rv le ts
ts——T h e N e w A p p licatio n A rch ite ctu re
Figure 41.1: The new application architecture uses HTML, Java servlets, JavaBeans, and JavaServer Pages.
Figure 41.2: HTML files are used for initial prompting.

Figure 41.3: HTML is dynamically generated by a JavaServer Page using data from a JavaBean.

Figure 41.4: When the input display is static, there is no need for a JSP.

Figure 41.5: A Java servlet handles the Web browser user's request by retrieving data from the database, stuffing that
data into a JavaBean, and forwarding control to a JSP .

Figure 41.6: A JavaBean is used to contain the information obtained by the Java servlet.

Figure 41.7: A JSP formats the information contained in a JavaBean using a combination of HTML and Java syntax.

C h ap te r 42: M ain tain in g S e ssio n S tate W ith Jav a S e rv le ts


Figure 42.1: The storefront for my simple application is a page with links to the two products.

Figure 42.2: Each of the items for sale in my application has a separate HTML file.

Figure 42.3: The HTML files for each of the items for sale contain forms that include hidden fields for the item price and
description.

Figure 42.4: After an item is added to the shopping cart, the order-total page lets the shopper confirm the order or
continue shopping.

Figure 42.5: When a shopper confirms an order by clicking on the Order button, the AddItem Java servlet is invoked by
the Web server.

Figure 42.6: The storefront application uses two business JavaBeans that encapsulate access to a database and two
Java servlets that

Figure 42.7: The doGet method of the AddItem servlet associates each user with a unique session ID .

Figure 42.8: The PlaceOrder servlet gets the user's order with the session object's getValue method and then invokes the
Order class's write method to put the order to the database.

C h ap te r 43: S e n d A M e ssag e W ith Jav am ail


Figure 43.1: A simple HTML form prompts for the information required by JavaMail.

Figure 43.2: The HTML input form qualifies ServletMail as the server-side Java class that is to respond to the user's
request.

Figure 43.3: This list of email messages is displayed upon logging in to a POP3 server.

Figure 43.4: These are code snippets from both ServletMail.java and error.jsp .

Figure 43.5: This message is displayed after selecting a message from the list of emails.

Figure 43.6: A JSP error page itself sends an email to the person responsible for maintaining the Web site .

Figure 43.7: This is the output of error.jsp after successfully sending an email about an error in ServletMail.

Figure 43.8: This detailed error message is sent by error.jsp.

C h ap te r 44: S y n ch ro n izatio n Issu e s W ith Jav a S e rv le ts


Figure 44.1: This simple servlet displays "HELLO WORLD!" on the browser.

Figure 44.2: Multiple clients are handled by one servlet.

Figure 44.3: This simple servlet displays the input user name back to the client browser.

Figure 44.4: Avoid instance variables at all costs.

Figure 44.5: The SingleThreadModel interface ensures that servlets run only one service method at a time.

Figure 44.6: Synchronizing a small block of code is more efficient than synchronizing a complete method.

Figure 44.7: Ultimately, the use of wait and notify is the only way to ensure that a deadlock does not occur.

C h ap te r 45: T o m cat F o r A S /400: A n O p e nn--S o u rce W e b A p p licatio n S e rv e r


Figure 45.1: To run Tomcat on your AS/400, you'll need an AS/400-specific startup script .

Figure 45.2: Once you submit the Tomcat script to batch, you should be able to access it from your Web browser.

Figure 45.3: To end Tomcat, you should run a script that "gently" brings it down.

C h ap te r 46: Ju m pp--S tart S e rv le ts A n d JS P s W ith W e b sp h e re V e rsio n 3.0.2


Figure 46.1: The WebSphere Advanced Edition Administration Client is used to view the default JSP 1.0-enabled
examples2 Web application.

Figure 46.2: Add a classpath for all WebSphere Web application servers through the admin.properties file.

Figure 46.3: Add a classpath for a specific WebSphere Web application server through the Command line arguments
property.

C h ap te r 47: A P ro g ram m e r's N o te b o o kk—


—M akin g S e rv le ts R u n F aste r
Figure 47.1: Use this code to force tables or indexes to stay resident within a pool.

C h ap te r 48: Jav a P e rfo rm an ce T u n in g


Figure 48.1: This is the AS/400 Performance Explorer collection process.

Figure 48.2: This is a sample Java application.

Figure 48.3: Create a Performance Explorer definition.

Figure 48.4: Run the WorldWideWait Java program.

Figure 48.5: This is the command to end a Performance Explorer session.

Figure 48.6: This query counts the number of objects created by the WorldWideWait program.

C h ap te r 49: Jav a P e rfo rm an ce T ip s


Figure 49.1: What looks like a well-crafted Java method will often perform poorly until tuned .

Figure 49.2: Object-creation and garbage-collection events were measured using the AS/400 Performance Explorer

Figure 49.3: Performance Trace Data Visualizer can be used to tune your Java applications.

Figure 49.4: Java methods that are tuned may not be as readable as their cleanly coded counterparts, but they often
perform eight to 10 times faster .

Figure 49.5: Using basic code optimization techniques, the example method had an eightfold improvement in
performance.

C h ap te r 50: E -B u sin e ss B y D e sig n W ith E JB


Figure 50.1: EJB architecture revolves around the remote interface, home interface, enterprise Bean, and container.

Figure 50.2: The EJB 1.1 specification uses XML for deployment descriptors, but EJB 1.0 implementations use product-
specific syntax such as this BEA WebLogic deployment descriptor.

C h ap te r 51: E n te rp rise Jav ab e an ss—


—S h o w M e T h e C o d e !
Figure 51.1: The OrderHome interface provides the life-cycle methods for an entity Bean.

Figure 51.2: EJBHome, the base interface of OrderHome, provides the methods required for the deletion of an entity.

Figure 51.3: The Order interface provides business methods for the manipulation of a business entity .

Figure 51.4: The attributes of the OrderPK class correspond to the full key of the RDB Order file.

Figure 51.5: The OrderBean class provides code implementations for all the methods of the OrderHome and Order
interfaces (shown in Figures 51.1-51.3) .

Figure 51.6: The Client application uses an EJB remote interface to access the methods of a host-based entity Bean.

Figure 51.7: The EJB client obtains a reference to the remote Bean through the Java Naming and Directory Interface.
C h ap te r 52: E JB —W h at's G o in g O n H e re
Figure 52.1: An entity Bean has four components: an entity interface, a home interface, a primary key class, and the
actual class that implements the methods of the interfaces.

Figure 52.2: The code for an entity Bean is fairly trivial because much of the responsibility for maintaining business
entities is handled by the EJB engine .

Figure 52.3: The AccountBean provides code for the business methods and "callbacks" for the seven life-cycle methods
of an entity Bean.

C h ap te r 53: O p e nn--S o u rce E n te rp rise Jav ab e an s


Figure 53.1: The ejb-jar.xml file has tags to help the EJB container deploy the Bean .

Figure 53.3: Use the XML deployment descriptor to do CMP support in JOnAS.

Figure 53.3: The output of a simple CMP Bean shows data for a client class .

C h ap te r 54: D istrib u te d Jav a C o m p u tin g W ith R M I


Figure 54.1: The Java interface called RemoteAWT has one method, createAWTFrame.

Figure 54.2: The server RMI class (AWTServer.java) implements the RemoteAWT interface .

Figure 54.3: The AWTClient RMI class uses a remote reference to the AWTServer class.

Figure 54.4: Before a client can remotely access an RMI object, a server must instantiate it.

Figure 54.5: As a curiosity, my RMI test remotely invokes an AWT Frame.

C h ap te r 55: S o ft
ft--C o d in g V alu e s F o r Jav a A p p licatio n s
Figure 55.1: Java's alternative to Microsoft .ini files are properties files.

Figure 55.2: JDBC applications should be made cross-platform by soft-coding their JDBC driver names and the SQL
server's subprotocol and IP .

Figure 55.3: The UsingJDBCProperties class uses two different JDBC drivers that were soft-coded to a properties file and
a custom Properties class.

Figure 55.4: Custom Properties classes can be shipped as a part of an application's .jar file to soft-code its configuration.

Figure 55.5: OS/400's Edit File command allows you to edit an ASCII IFS-based file on your AS/400.

C h ap te r 56: Jav a S o u rce L e v e l D e b u g g e r F o r T h e A S /400


Figure 56.1: The same source level debugger that you use on RPG can be used to debug your Java applications.

C h ap te r 57: D e liv e r Y o u r P ro g ram s W ith Jav a M e ssag e S e rv ice


Figure 57.1: This form includes input data to be transformed into an XML- formatted message.

Figure 57.2: These are code snippets of the example on the CD .

Figure 57.3: This example XML describes both the structure of the data contained therein and the content of a specific
customer.

C h ap te r 58: H o w T o B u ild O p sn av Jav a P lu gg--In s


Figure 58.1: The MessageQueueSample1 plug-in displays message text and the date and time the messages were
created.

Figure 58.2: You modify the string table entries used by the plug-in using the GUI Builder utility.

Figure 58.3: Add these lines of code to the getColumnData method .

C h ap te r 59: Jav a P ackag in g


Figure 59.1: A JAR file can contain any type of file, just like a .zip file. This AS/400 Toolbox for Java JAR file contains .gif
image and class files.

C h ap te r 60: A Jav a G U I F o r D S P F F D
Figure 60.1: This is a sample DisplayRecordFormat GUI with the Windows look and feel.

Figure 60.2: The DSPFFD application maintains your connection information in its .ini file.

Figure 60.3: The Display Record Format panel lets you know when you've successfully connected.

Figure 60.4: The Open AS/400 File panel allows you to key a file name and a library qualifier for that file.

Figure 60.5: This is a UML diagram for the DisplayRecordFormat application.

Figure 60.6: This is another UML diagram for the DisplayRecordFormat application.

C h ap te r 61: S p o o l F ile T o P D F , P D Q
Figure 61.1: The content of even the most minimal PDF file can be quite confusing .

Figure 61.2: This is a sample FTP session used to send the Splf2Pdf.jar to your AS/400.

Figure 61.3: The CPYSPLFPDF command requires the qualification of the spool file's location and the IFS location of
where the PDF file should be created.

Figure 61.4: Congratulations! Your AS/400 spooled file now can be read by just about any PC in the world.

Figure 61.5: The CPYSPLFPDF command has an intuitive interface that AS/400 programmers have come to expect.

Figure 61.6: The command processing program, SPLFPDFCPP, for the CPYSPLFPDF command does a couple of tricks
to prevent the Qshell command interface from popping up .

C h ap te r 62: T h e S p artan O rd e r S y ste m —A n E x e rcise In Jav a A p p licatio n D e sig n


Figure 62.1: The Spartan Order System is made up of two files and two indexes.

Figure 62.2: The OrderGUI class uses a BorderLayout to neatly arrange the components within the application frame.

Figure 62.3: The OrderDetailGUI puts two panels that are set to BorderLayout into its frame that is set to the FlowLayout.

Figure 62.4: The actionPerformed method of the OrderGUI class handles the events generated by both the Add and Clear
buttons.

Figure 62.5: The interface of the Order class was designed to encapsulate access business methods associated with the
order entity and hide the complexities of DB2/400 file processing.

Figure 62.6: Because the interface of the OrderDetail class uses many of the same methods of the Order class, it
warrants the use of a base class.

Figure 62.7: This Profile class uses the singleton design pattern.

C h ap te r 63: T rackin g A S /400 V ital S ig n s W ith S y sS tats


Figure 63.1: The SysStats performance monitor dynamically displays output from multiple AS/400s.

Figure 63.2: SysStats allows you to configure the display to refresh at qualified intervals.

C h ap te r 64: F re e A n d E asy W ith W e b S Q L


Figure 64.1: The Submit button of an HTML input form functions like the Enter key of a 5250 screen, and the Reset button
works like F5=Refresh.

Figure 64.2: HTML tables are basically subfiles for the Internet.

Figure 64.3: The DDS for the WebSQL HTML file contains one "record format" (HTML form) and one input field.

Figure 64.4: The AS/400's Web server invokes the doGet function of the WebSQL Java servlet when a user clicks the
Submit button on the HTML form .
Team-Fly
Team-Fly

L ist o f T ab les
C h ap te r 2: A p p le ts an d A p p licatio n s
Table 2.1: Applets vs. Applications

C h ap te r 4: R e co rd
rd--L e v e l A cce ss W ith T h e A S /400
Table 4.1: AS/400 Data Types to Java Classes

C h ap te r 7: Q sh e ll A n d IB M 's Jav a T o o lb o x F o r T h e A S /400


Table 7.1: Basic Qshell Commands

C h ap te r 8: Jav a S e rv le t P ro g ram m in g F o r T h e H T M LL--C h alle n g e d


Table 8.1: Java Class Wrappers for HTML

Table 8.2: The AS/400 Servlet Utility Classes

C h ap te r 13: U sin g C o m m itm e n t C o n tro l W ith JD B C


Table 13.1: Isolation Levels of JDBC

C h ap te r 15: Jav a F o u n d atio n C lasse s B asics


Table 15.1: JFC to AWT Component Comparison

Table 15.2: JFC's Most Interesting Components

C h ap te r 24: C allin g R P G F ro m Jav a


Table 24.1: Conversion Class Description

C h ap te r 26: T C P /IP S o cke ts P ro g ram m in g


Table 26.1: Socket APIs

Table 26.2: Socket API Prototypes

C h ap te r 37: U n ix D e v e lo p e rs F in d A H o m e In Q sh e ll
Table 37.1: Built-in Qshell Commands

Table 37.2: UNIX Script Test Results

C h ap te r 38: T h e "L ittle W e b S e rv e r" P ro je ct


Table 38.1: HTTP Status Codes

Table 38.2: HTTP Headers

C h ap te r 48: Jav a P e rfo rm an ce T u n in g


Table 48.1: Trace Index File (QAYPETIDX) Record Layout

Table 48.2: Fields in the Java Event File (QAYPEJVA)

Table 48.3: Fields in the Task Information File (QAYPETASKI)


C h ap te r 50: E -B u sin e ss B y D e sig n W ith E JB
Table 50.1: SQL Isolation Levels

Table 50.2: EJB Transaction Attributes

A p p e n d ix : S o ftw are L o ad in g In stru ctio n s


Table A.1: IBM's JT400 Modification 2's Six JAR Files

Team-Fly

You might also like