Beruflich Dokumente
Kultur Dokumente
SG24-5296-00
IBML
SG24-5296-00
Take Note!
Before using this information and the product it supports, be sure to read the general information in
Chapter 7, Special Notices on page 289.
Contents
Figures
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Preface
. . . . . . . . . . . . . . . .
The Team That Wrote This Redbook
. . . . . . . .
Comments Welcome
. . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . .
Chapter 1. Overview
. . . . . . . . . . . . . . . . . . . . . . . . . . .
1.1 Developing Applications in the Network Computing Framework
. . . . . . . . . . . . . . . . . . . . . .
1.1.1 An Overview of NCF
1.1.2 Designing NCF Applications . . . . . . . . . . . . . . . . . .
1.1.3 Some Design Alternatives . . . . . . . . . . . . . . . . . . .
1.2 Java Is the Foundation . . . . . . . . . . . . . . . . . . . . . . . .
. . . .
1.3 Universal Support for the Servlet Programming Model
Chapter 2. Servlets . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
2.1 Overview of Java Servlets
2.1.1 Advantages of Servlets . . . . . . . . . . . . . . .
2.1.2 Servlets and CGI-BINs . . . . . . . . . . . . . . .
. . . . . . . . . . . . . .
2.1.3 The Hello World Servlet
. . . . . . . . . . .
2.2 Structure of the Java Servlet API
2.2.1 Interface javax.servlet.Servlet . . . . . . . . . . .
2.2.2 Interface javax.servlet.ServletConfig . . . . . . .
2.2.3 Interface javax.servlet.ServletContext . . . . . .
2.2.4 Interface javax.servlet.ServletRequest . . . . . .
2.2.5 Interface javax.servlet.ServletResponse . . . . .
2.2.6 Interface javax.servlet.http.HttpServletRequest
2.2.7 Interface javax.servlet.http.HttpServletResponse
2.2.8 Class javax.servlet.GenericServlet . . . . . . . .
2.2.9 Class javax.servlet.ServletInputStream . . . . .
. . .
2.2.10 Class javax.servlet.ServletOutputStream
2.2.11 Class javax.servlet.http.HttpServlet . . . . . . .
. . . . . . . .
2.2.12 Class javax.servlet.http.HttpUtils
. . .
2.2.13 Exception javax.servlet.ServletException
2.2.14 Exception javax.servlet.UnavailableException .
. . . . . . . . . . . . . . . . . . . . .
2.3 Servlet Structure
2.3.1 The init(), service() and destroy() Methods . . .
2.3.2 Parameters Passed by the Server . . . . . . . .
2.3.3 Servlet Life Cycle . . . . . . . . . . . . . . . . . .
2.4 Extending Lotus Domino Go Webserver with Servlets
. . . . . . . . . . . . .
2.4.1 Document Root Directory
. . . . . . . . . . . . . . . . . .
2.4.2 Servlet Directory
2.4.3 Other Configurations . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
2.5 Creating a Servlet
2.5.1 Compiling and Installing a Servlet . . . . . . . .
2.5.2 Invoking a Servlet . . . . . . . . . . . . . . . . . .
. . . . . . . . .
2.5.3 Debugging and Testing Servlets
2.6 Advantages of Servlets over CGI-BIN . . . . . . . . .
. . . . . . . .
2.6.1 CGI-BIN Processing HTML Forms
2.6.2 Java Servlets Processing Forms . . . . . . . . .
2.6.3 GET and POST HTML Methods . . . . . . . . . .
2.6.4 Multithreading . . . . . . . . . . . . . . . . . . . .
. . . . . . .
. . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
v
xi
xi
xii
1
1
2
2
4
9
10
11
11
12
14
15
16
17
17
18
19
19
19
19
20
20
20
21
21
21
22
22
22
25
26
28
29
29
30
33
33
36
38
38
38
44
49
62
iii
3. Connectors . . . . . . .
. . .
Role of a Connector
CICS Applications . . . . .
CICS Internet Gateway . .
CICS Gateway for Java . .
MQSeries Internet Gateway
MQSeries Client for Java
eNetwork Host On-Demand
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
. . .
. . .
. . .
. .
113
113
114
116
133
154
173
184
197
197
208
209
216
229
229
232
232
240
245
258
. . . . . . . . . . . . .
265
266
276
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
289
. . . . . . . . . . . . .
. . . . . . . . .
. . . . . . . .
. . . . . . . . .
. . . . . . . . .
291
291
291
291
. . . . . . . . . . . . . . . . . . .
293
293
294
295
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
297
iv
. . .
. . . . . . . . . . . .
Index
. . .
. . .
67
68
73
77
83
87
96
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
299
Figures
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
.
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
.
. .
.
. .
. .
2
5
6
8
10
12
15
16
18
20
23
27
28
30
31
32
34
35
35
36
37
39
39
41
42
44
45
45
46
47
48
49
50
51
51
52
53
54
55
57
58
59
59
60
61
61
62
63
65
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
vi
66
67
. 68
. 70
. 73
. 74
. 75
. 76
. 77
. 78
. 79
. 80
. 81
. 82
. 83
. 83
. 84
. 84
. 85
. 86
. 86
. 89
. 90
. 91
. 92
. 93
. 94
. 95
. 96
. 98
100
101
103
104
105
105
106
107
108
108
109
109
. .
. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
110
110
114
116
117
120
120
121
122
126
127
127
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
128
130
131
132
132
132
134
135
136
137
137
138
139
140
141
142
143
144
147
154
155
157
158
159
160
161
162
163
164
165
166
167
Figures
vii
169
173
176
177
178
180
180
181
182
185
186
186
187
189
190
191
192
193
194
196
197
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
viii
198
198
199
199
200
201
201
202
202
203
203
204
204
205
205
206
206
207
207
208
209
211
213
213
214
214
215
215
216
216
217
218
219
220
221
221
222
223
227
230
233
234
234
235
235
236
236
237
237
238
238
239
239
240
241
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
Retrieve.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . .
The Application Is Terminated If No URL Is Passed
Output Generated by the Retrieve JDBC Application . . . . . . . . . . .
. . .
The Flow of the JDBC Client/Server Scenario Using Java Beans
. . . . . . .
The JDBC Select Bean Placed onto the BeanBox Window
SelectCustomizer Panel When an SQLException Is Thrown . . . . . . .
MS-DOS BeanBox Window When an SQLException Is Thrown . . . . .
. . . . . . . . . . . . . . .
The SelectCustomizer Panel Correctly Filled
. . . . . . . . . . . . . . .
Available Tables for the SAMPLE1 Database
The SelectCustomizer Panel after Some Columns Have Been Selected
The MS-DOS BeanBox Window Registers All Our Choices . . . . . . .
The JDBC Select Bean Displays All Requested Data . . . . . . . . . . .
Properties Window for the JDBC Select Bean . . . . . . . . . . . . . . .
. .
Flow of the JDBC Three-Tier Model Scenario Using Java Servlets
The File RetrieveForm.html . . . . . . . . . . . . . . . . . . . . . . . . . .
The Form Contained in the RetrieveFrom.html Page . . . . . . . . . . .
. . . . . . . . . .
The Clients Browser Displays the Retrieved Results
The RetrieveServlet.java File . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
The Scenarios Environment
The Index for the CICS Demos . . . . . . . . . . . . . . . . . . . . . . . .
Source for CICS Demos . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Customized cigstart
The NCF Home Page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
NCFSTART - Sample Operations . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
Surfing on CICS Transaction
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
CICS Signon Screen
. . . . . . . . . . . . . . . . . . . . . . . . .
The Tech Demo Transaction
The Tech Demo Transaction - Inquiry Panel . . . . . . . . . . . . . . . .
. . . . . . . . .
The Tech Demo Transaction - Inquiry Response Panel
Logical Representation of the Scenario Involving CICS and Servlets .
CicsServlet.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Directory Tree Necessary to Make the CicsServlet Run . . . . . . . . .
. . . . . . . . .
The ncfcxserv.htm HTML File Invoking the CicsServlet
How to Start the CXNT120 CICS Region for NTNCF120 . . . . . . . . . .
IBM Transaction Server - Start CICS Region . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
CXNT120 CICS Region Busy
CXNT120 CICS Region Started . . . . . . . . . . . . . . . . . . . . . . . .
CICSTERM - CICS Server Selection Window . . . . . . . . . . . . . . . .
. . . . . . .
CICSTERM - CICS Client 3270 Terminal Emulator Window
. . . . . . . . . . . .
The CICS Client 3270 Terminal Emulator Is Active
CICS Java Gateway Icon . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . .
The IBM CICS Gateway for Java Has Been Correctly Activated
. . . . . . . . . . . . . . . . . . .
Applications Running in This Scenario
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Query Connector
Entering User ID and Password in the CICS Client Messages Window
The Response Is Displayed On the Clients Browser . . . . . . . . . . .
The CICS Gateway Window Registers the Client Has Connected and
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Disconnected
259. The Transaction Count Field for the commarea String Has Been
Updated . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Figures
242
243
245
246
248
250
251
252
253
255
256
257
257
259
260
261
262
263
266
267
268
270
273
273
274
274
275
275
276
277
278
280
281
281
282
282
283
283
284
284
284
285
285
286
286
287
287
288
ix
Preface
This redbook provides an overview of the recently announced Network
Computing Framework (NCF), as well as specific implementation examples to
help explain the different pieces in the framework. For example, there are
scenarios that show how to use the various connectors that are available, as
well as how to implement database calls using Net.Data and also using JDBC.
In addition, there are many examples of how to use and implement servlet
support within the Network Computing Framework. This book is a subset of a
more in-depth redbook, which has an order number of SG24-2119.
While it provides a broad understanding of this new architecture, this book also
gets very specific about how to install components that are used in the
framework. In addition, examples of servlets and beans are provided to give you
a better understanding of the technologies that are involved.
xi
Thanks to the following people for their invaluable contributions to this project:
Mike Conner, Bill Lawton
IBM Austin
Mark Fisher, Ernest Evans, Ken McCauley, John Shin
IBM RTP
Nino Lusardi
IBM Italy
Comments Welcome
Your comments are important to us!
We want our redbooks to be as helpful as possible. Please send us your
comments about this or other redbooks in one of the following ways:
Fax the evaluation form found in ITSO Redbook Evaluation on page 299 to
the fax number shown on the form.
Use the electronic evaluation form found on the Redbooks Web sites:
For Internet users
For IBM Intranet users
redbook@vnet.ibm.com
xii
http://www.redbooks.ibm.com
http://w3.itso.ibm.com
Chapter 1. Overview
The Networking Computer Framework (NCF) supplies the underlying services
needed by network applications, while providing an open, standards-based
framework within which developers can integrate products from a variety of
vendors. It provides a unified programming model based on Java and
JavaBeans technology. Client-side and server-side functions are enhanced by
JavaBeans that provide access to all services. Its modular approach makes it
very flexible. What starts as a simple online application can grow quickly and
easily. As a developer you can leverage JavaBean components and
object-oriented technologies to quickly build applications and systems.
By following the NCF model of building network computing solutions, developers
can:
A set of clients that exploit just in time components such as Kona Beans
In this example, one might start with designing a JavaBean that wraps access to
the companys directory application. This bean would be a pure Java class
definition with properties that allow it to be configured. For example, it might
have a property for the domain name of the server where the directory
application runs and it might have several properties that control how name
matching is to be done or that set the default company location. It would likely
have a property for the lookup name pattern and other access qualifiers such as
location or department. It would also be likely to have a read only property that
contains the result of a lookup, say in the form of a two dimensional array of
strings where each row is one directory entry and each column is a different
aspect of the directory information such as first name or employee ID.
It would probably support a method to look up directory information based on its
current property settings. It might also support a number of event listener
interfaces to make it more usable in traditional graphical user interfaces, but this
is not necessary in our example where it will only be used by a servlet (a Java
class derived from javax.servlet.GenericServlet).
This bean could be developed and tested without concern for HTML, or servlets,
or other Web issues. Once the bean was developed, one could design a servlet
that uses the bean to look up directory information and then format the
information into an HTML table of the results. One way to design this servlet
would be to define a method, say lookup, that takes appropriate parameters,
does the lookup, and writes the HTML table to an output stream that was passed
in as a parameter. This method could be called from the servlets service
method, which would extract the required parameters (including the output
stream) from the HTTP request and then call lookup to do the actual work. The
advantage of this design is that one could add a main method so that the servlet
class also could be used as a Java application for testing purposes. The main
method could take command-line arguments for the lookup parameters and then
cause the output to go to System.out. This allows much of the servlets logic,
including the production of the HTML output, to be tested outside of a Web
server and without use of a Web client. Once the servlet was working in this
mode, it could be installed into the Web server (as little as putting it in the right
place in the Web servers file system and possibly involving setting up an alias
and/or access controls).
Once the servlet is finished, it would be necessary to design a Web page to
invoke the servlet. This page would contain a form similar to the one shown in
Figure 2. However, in this design example we chose to have our servlet produce
only an HTML table with the results of the directory lookup. We still need to
provide a way to generate an entire HTML page to send back to the client. There
are a number of choices here. A wrapper servlet can be defined that writes the
rest of the page with a call to the lookup servlet made at the appropriate point.
(Servlets can invoke other servlets by just calling their service methods and
forwarding the calling servlets service method parameters to the called servlet.)
Another alternative would be to use a ServletEmbed in an HTML page.
ServletEmbeds are described in more detail later in this section. Briefly, they
are HTML syntax that can be embedded into an HTML page. The ServletEmbed
expression in the HTML page is replaced with the output of the called servlet
while the Web server is sending the page to the client, so the client Web
browser never sees the ServletEmbed, just the HTML that is produced by the
called servlet.
Chapter 1. O v e r v i e w
Content: Content refers to MIME data that is sent to a client system to provide
the user interface to an NCF application. NCF applications produce MIME data of
various types, such as: HTML, GIF, TIF or JPEG. An NCF applications content
can come from:
Dynamic files: HTML files that contain references to Java servlets called
ServletEmbeds that run as the file is being sent to the client and dynamically
provide part of the files content. (These are discussed in more detail
below.)
Servlets that run in response to HTTP requests and generate MIME data.
The only restriction on the MIME data produced by an NCF application is that it
must be processable by the client. NCF is open with respect to client systems.
However, to fully leverage the NCF features and infrastructure, a client system
should support both HTML and Java programs called applets that run in the
client system. Clients are expected to fully support at least the features of Java
1.02, and some of the advanced client support in NCF requires that the client
support Java 1.1.
NCF provides tools including NetObjects Fusion, Lotus BeanMachine, and
VisualAge Java that can be used to construct content, especially applets.
However, NCF leverages standard content types; therefore, there are many
third-party tools that can also be used, especially in the generation of HTML or
images.
Servlets: At the center of every NCF application is one or more Java servlets.
Servlets are very similar to CGI-BIN programs and Web server plugins
(programs written to Web server plugin APIs such as NSAPI, ISAPI, or ICAPI),
except that they are written in Java and run in a Java Virtual Machine managed
by the Web server. These servlets coordinate the steps of the application and
provide most of its function. Servlets are Java classes that support the
javax.servlet.Servlet interface.
Essentially, a servlets job is to process a request (usually an HTTP or HTTPS
request) and produce MIME data (usually HTML). Servlets are registered with the
Web server and can be named in URLs in HTML forms or even in simple HTML
Chapter 1. O v e r v i e w
links. When the form is submitted or the link is followed, the Web browser will
construct an appropriate HTTP or HTTPS request including parameters, and/or a
query string as specified in the HTML. The Web server will receive this request
and direct it to the appropriate servlets service [ 1 ] method, first creating an
instance of the servlet if necessary. The servlets service method is passed two
parameters, a javax.servlet.Request and a javax.servlet.Response. The request
parameter gives the servlet convenient access to information in the HTTP
request including:
The URL of the request, including the query parameters, and the query string
The identity of the remote user and how the user was authenticated
The response parameter provides methods that allow the servlet to respond to
the HTTP request. In particular, the response provides a stream to which the
servlet can write. The stream also delivers anything that the servlet writes (for
example, HTML) to the Web browser as the content of the HTTP response.
The details of the Java servlet interfaces and classes are defined in the standard
Java packages javax.servlet and javax.servlet.http. JavaSoft provides the Java
Servlet Toolkit which you can download from the JavaSoft Web site at
www.javasoft.com. This toolkit contains the interfaces and classes related to
servlets. JavaSoft has also produced a white paper on servlets that can be
found on the JavaSoft Web site. This JavaSoft white paper provides a good
introduction to what servlets are and how to work with them.
<servlet name=Lookup
<param name=foo1 value=bar>
<param name=foo2 value=baz>
</servlet>
Figure 3. ServletEmbed Syntax for Lookup
This would call the servlet registered under the name Lookup. The two named
parameters are passed to the servlet just like form data parameters are passed.
Other forms of the ServletEmbed syntax allow the class of the servlet to be
specified and initialization parameters to be passed. In all cases, when the
servlet is called, it receives the HTTP context of the page, so it can inquire about
the remote user and such, just like a top-level servlet.
Client/Server Communication: NCF provides both client and server support for
HTTP, HTTPS, and IIOP. HTTP is the standard protocol for client/server
communication on the Web. However, it is fairly inefficient and insecure. HTTPS
is an industry-standard extension to HTTP that adds security based on SSL
Version 3. This is a public-key/private-key based protocol that allows an
untrusting client to set up a secure session with an untrusting server. In this
session the server knows the clients identity and the client knows the server s
identity. In addition, data is sent encrypted and incorruptible.
NCF also supports the Object Management Group s CORBA IIOP standard for
remote method call support. With this support an applet running in the client can
establish a connection to a servlet running in the Web server and pass method
calls back and forth. NCF supports IIOP in both a standard mode that allows
interoperability with other IIOP clients and servers and an enhanced mode that
allows IIOP requests to be carried over HTTP sessions (therefore leveraging
HTTP session setup) and to carry object parameters by value as well as
reference (the norm). When objects are passed by value, a new object is created
in the target process with a copy of the calling process objects value. This
allows the target process to call methods on the object without incurring the
overhead of a remote method call as would be required if the object was passed
by reference. The NCF support of IIOP allows programmers to use either Java or
CORBA IDL to define object interfaces for use with the IIOP support.
Figure 4 on page 8 illustrates the two primary forms of client/server
communication supported by NCF. Note that the IIOP form uses a standard
NCF-provided servlet to receive IIOP requests. This servlet dispatches IIOP
requests to Java objects that the application designer has defined. The
application supports the dispatch process by implementing a simple interface
that maps object keys to objects, and objects to object keys. The IIOP servlet
uses this interface to marshal and demarshal object references.
Chapter 1. O v e r v i e w
IMS
CICS
MQSeries
Lotus Notes
The NCF Java-based programming model will be supported in all the major
Web servers and on all the major system platforms, including IBMs high-end
server platforms. This is only possible because of the unique portability of
Java.
Secure operation.
Java is unique among mainstream programming languages in its support for
secure operation. Only Java is practical for Web downloads. Relying on code
signing alone is just not enough given the fine-grained nature of Web
downloads.
Strong typing
No pointer errors
No array errors
10
Chapter 2. Servlets
This chapter shows:
The servlet builds a response and passes it to the server. That response is
dynamically built and the contents of the response usually depends on the
clients request.
11
Servlets look like ordinary Java programs. The servlets import particular Java
packages that belong to the Java servlet API. Since servlets are object
bytecodes that can be dynamically loaded off the Net, we could say that servlets
are to the server what applets are to the client. But, since servlets run inside
servers, they do not need a graphical user interface (GUI). In this sense servlets
are also called faceless objects.
12
With a servlet approach, the server can grant full access to local facilities,
such as databases, and trust that the servlet itself will control the amount
and precise nature of access that is effectively afforded to external users.
So, for example, the Java servlet API provides all the methods to monitor
and verify the origin of all requests (see the example shown in Figure 39 on
page 55 and discussed in the following pages). Moreover, on the Internet
Connection Secure Server, servlets cannot be loaded from the network.
They must reside on the local system. As a consequence, if a proprietary
algorithm is built into a servlet, the code never passes beyond the
boundaries of the server; only the results that it produces do. If the code is
not passed to the client, it cannot be saved or disassembled.
Servlets can be client programs of other services, for example, when they
are used in distributed application systems. We discuss this important way
to use servlets in 3.1.6.3, Servlets and IBM Connectors on page 194 and in
5.5, JDBC Client/Server Database Server Scenario Using Java Servlets on
page 258.
It is possible to invoke them from a local or remote disk across the network.
All the examples that are described in this chapter demonstrate this.
Servlets can be chained. This means that one servlet can call another
servlet, thus becoming its client. It can also call several servlets in
sequence.
They can be dynamically called from within HTML pages, using the servlet
tag technique as shown in 2.8, Servlet Tag Technique on page 87.
Like all Java programs, servlets can use all the capabilities of the
object-oriented Java language:
Memory access violations are not possible, so faulty servlets will not
crash servers.
Chapter 2. Servlets
13
14
Chapter 2. Servlets
15
import
java.io.*
import javax.servlet.*;
This servlet only contains a single life cycle method, service(), that displays on
the clients browser the phrase Hello World!. To obtain this, you must compile
the Java source code of the servlet, copy the generated class file in a specific
directory called servlet and then invoke the servlet by pointing to its URL with
your browser.
javax.servlet
javax.servlet.http
These two packages contain seven interfaces, five classes and two exceptions.
Before going on with this chapter, it is helpful to have a visual idea of the
structure of the Java servlet API. The following table should help.
16
Interfaces
Classes
Exceptions
javax.servlet.http
Servlet
ServletConfig
ServletContext
ServletRequest
ServletResponse
GenericServlet
ServletInputStream
ServletOutputStream
HttpServletRequest
HttpServletResponse
HttpServlet
HttpUtils
ServletException
Unavailable Exception
Note
Generally speaking, a Java class is composed of two things: variables and
methods. In addition, all Java variables and methods must be a member of a
class. Instance variables are what describes an object and typically, in pure
object-oriented languages such as Java, they are encapsulated; which means
that only the objects themselves can change these variables. To do this,
objects use functions called methods.
As you can see, the amount of material introduced by the Java servlet API is not
too big. Nevertheless, these few interfaces, classes and exceptions are able to
make a Java server very powerful.
Table 1 shows fourteen items. It would be good to have a general description of
each of them before moving onto the next section.
Note: The description of the Java Servlet API provided here is based upon the
official information located at: http://www.javasoft.com.
Chapter 2. Servlets
17
Using the public interface ServletConfig provides access to the servlets context
with a single call to the method getServletContext().
getAttribute() returns the value of the named attribute of the network service
or the value null if the attribute does not exist.
getMimeType() returns the mime type of the specified file or null if not
known.
getRealPath() applies alias rules to the specified virtual path and returns the
corresponding real path.
getServerInfo() returns the name and version of the network service under
which the servlet is running.
getServlet() returns the servlet of the specified name or null if not found.
18
Chapter 2. Servlets
19
ServletOutputStream
out = response.getOutputStream();
response.setContentType(text/html ) ;
out.println(How to use the interface HttpServletResponse ) ;
out.close();
Note
If you are writing a servlet that interacts with HTML Web pages containing
forms, you will probably create your servlet by subclassing HttpServlet. For
all other servlets you will probably start by subclassing GenericServlet.
20
Chapter 2. Servlets
21
init()
start()
stop()
destroy()
paint()
repaint()
Servlets look like ordinary Java programs. How do you recognize them? First of
all they must implement the servlet interface, usually by extending either the
GenericServlet class (see 2.2.8, Class javax.servlet.GenericServlet on page 20)
or the HttpServlet class (see 2.2.11, Class javax.servlet.http.HttpServlet on
page 21). Both the GenericServlet and the HttpServlet classes contain three
methods, which they take by inheritance from the servlet interface:
1. init()
22
2. service()
3. destroy()
These methods are used by the servlet to communicate with the server. As we
already said (see 2.2.1, Interface javax.servlet.Servlet on page 17), these three
methods are called life cycle methods. You will work with these three methods
in a slightly different way, depending on whether you are extending the
GenericServlet class or the HttpServlet class.
However, the simplest possible servlet defines the single service() life cycle
method. In other words, the service() method is required and the others are
optional.
import java.io.*
import javax.servlet.*;
public class SimplestServlet extends GenericServlet
{
public void service(ServletRequest request, ServletResponse response)
throws ServletException, IOException
{
PrintStream out = new PrintStream(res.getOutputStream());
out.println(Hello World! ) ;
}
public String getServletInfo()
{
return This servlet defines the single service() life cycle method ;
}
}
Figure 11. The Simplest Possible Servlet Contains a Single Life Cycle Method, service()
The init() method is run only once when the server loads the servlet and the
servlet is started. It is guaranteed to finish before any service() requests are
accepted. The servlet can be activated when the server starts or when the
first client accesses the servlet. The biggest advantage is that the init()
method is called only once, without considering how many clients access the
servlet. As we see (Figure 30 on page 47) the default init() method logs the
servlet initialization and it is possible to configure it in order to save other
information.
The default init() method can usually be accepted as it is, without the need to
override it, because it is not abstract. Servlet developers may, if they want,
provide their own implementation of this method, overriding it and creating a
custom init(). A custom init() is typically used to perform setup of
servlet-wide resources only once, rather than once per request (see
Chapter 2. Servlets
23
Figure 79 on page 98). For example, you might want to write a custom init()
to load GIF images one time only, where the servlet returns the images
multiple times in response to multiple client requests to the servlet. Further
examples may be initializing sessions with other network services or getting
access to their persistent data (stored in a database or in a file).
For example, the custom init() method of the EmployeeSearch servlet that we
show in 2.7, A Sample Servlet on page 67 reads a database file name as
an initial parameter, tries to open the database text file, calls another
method, named readDB(), to build a Hashtable and throws a
ServletException object if an error occurred.
Note
When you write your own code overriding:
The destroy() method is run only once when the server stops the servlet and
unloads it. The servlet-log file gives information about all the initialized and
destroyed methods (Figure 30 on page 47) and this is a way to see if, for
example, a servlet is unloaded. Moreover the servlet-log file offers a good
way to debug, as we show in 2.7.4, Debugging and Testing the Servlet on
page 83.
Usually, the servlets are unloaded when the server is shut down. The
default destroy() method also can be accepted as is, without the need to
override it, because it is not abstract like the init() method. Servlet writers
may, if they wish, override the destroy call, providing their own custom
destroy() method. A custom destroy() method is often used in the
management of servlet-wide resources. For example, the server might
accumulate data when it is running and you might want to save this data to a
file when the servlet is stopped (see for example Figure 79 on page 98).
The service() method is the heart of the servlet. In fact, as we said, the simplest
possible servlet defines only the service() method. Unlike the init() and destroy()
methods, it is called for each client request, and not only once in the life cycle of
the servlet. Moreover, it must be handled differently when it is based on the
GenericServlet class or in the HttpServlet class.
If the servlet is based on the GenericServlet class, the service method is
abstract, so you must override it. The service() method obtains information
about the client request, prepares the response and returns this response to the
client. You should also consider that multiple clients might have access to the
service() method at the same time, so you also have to include threads and
synchronized code (see 2.6.4, Multithreading on page 62).
If the servlet is based on the HttpServlet class, the service method is not
abstract. Therefore, you can accept it if you are supporting the HTTP 1.0
protocol. The service() method determines whether the information entered onto
24
the form on the clients browser is provided by GET or POST. If the answer is
GET, the service() method calls the doGet() method of the HttpServlet class. If
the answer is POST, the service() method calls the doPost() method of the
HttpServlet class. It is up to the servlet developer to override the doGet() or
doPost() methods in order to accept the clients request and give a response
back to it, as appropriate. If you are supporting the HTTP 1.1 protocol, then you
will probably override the service() method to support HTML 1.1 extensions
(OPTIONS, PUT, DELETE and TRACE). Calling super.service() from within the
overridden service method provides the default handling on the other methods
(such as GET and POST).
Note: When writing your servlets, you can write your own code overriding the
following servlet class methods:
init()
service()
destroy()
getServletInfo()
doGet()
doPost()
All other Java servlet API methods are implemented by the Domino Lotus
Go Webserver for its processing. You should make sure that you do not
override any other Java servlet API methods or you will be overriding the
servers code.
In addition you should never call the java.lang.System.exit() method,
because it terminates the JVM currently running and servlets will no
longer run until your Java-enabled Web server is restarted.
If the servlet is based on the GenericServlet class, the two objects are
instances of:
ServletRequest
ServletResponse
If the servlet is based on the HttpServlet class, the two objects are instances
of:
HttpServletRequest
HttpServletResponse
These objects, lets call them request and response for convenience,
encapsulate the data sent by the client, providing access to parameters and
allowing the servlets to report status including errors if they occurred. You can
decide to write to System.out and System.err using the println() method and you
can decide to write in the servlet-log file using the log() method. An example of
the above is described in 2.7.4, Debugging and Testing the Servlet on page 83.
Chapter 2. Servlets
25
The server creates an instance for the request and response objects and passes
them to the servlet. Both these objects are used by the server to exchange data
with the servlet.
The servlet invokes methods from the request object in order to discover
information about the client environment, the server environment and all the
information provided by the client, for example, all the data entered on a form on
the clients browser and set by the GET and POST methods. The specific
methods of the request object that the servlet uses to retrieve information from
the client are:
getParameterNames()
getParameter()
getParameterValues()
The exact way the servlet discovers all this information is fully explained in the
example described in Figure 39 on page 55. The method getInputStream()
returns a ServletInputStream object by reading the request body (see Figure 11
on page 23). An additional method, getQueryString() is available for
HttpServletRequest objects only.
The servlet invokes methods for the response object to send the response that it
has already prepared back to the client. The primary method of the response
object that the servlet uses to send the response back to the client is the
getOutputStream() method. This method returns a ServletOutputStream object
(see Figure 11 on page 23) and you may use the print() and println() methods of
this object for writing the servlet response back to the client (see Figure 29 on
page 46).
The input stream that the servlet gets using the getInputStream() method and the
output stream that the servlet gets using the getOutputStream() method may be
used with data in whatever format is appropriate. For example, HTML and
several image formats may be valid data formats.
26
A client request arrives at the server 1. A client request is already at the
server if the client request initiated the servlet load.
The server invokes the servlet service() method 6, passing the request 7
and response 8 objects as parameters.
The service() method gets information about the request object and
processes the request accessing the other resources 9 and getting the
necessary information 10.
Chapter 2. Servlets
27
The service() method uses methods of the response object to pass the
response 11 back to the server 12 and then to the client 13. The
service() method may invoke other methods to process the request, such as
doGet() or doPost() or new methods that the servlet developer wrote.
For additional client requests, the server creates new request and responses
objects, again invokes the service() method of the servlet and passes to it
those two objects as parameters. Therefore, this loop is repeated, but
without the need to re-call the init() method. The servlet, in general, is
initialized only once.
When the server no longer needs the servlets (typically when the server is
shut down), the server invokes the servlet destroy() method.
28
Chapter 2. Servlets
29
The Java classpath variable has more then just the servlets directory. It also
has to point to the servlet JVMs classpaths that are the paths to the files
classes.zip and icsclass.zip. In addition, the path to the servlet class files must
be appended to the two classpaths in the Java classpath variable.
30
Chapter 2. Servlets
31
The list shows all the servlets for which you have defined initialization
parameters. (The list in Figure 16 is empty and shows only an example.) These
are the parameters the servlet init() method will use to initialize the servlet.
To define the initialization parameters for a particular servlet:
1. Specify the name of the servlet instance.
2. Specify the name of the servlet class.
3. Specify the servlet initialization parameters. Parm_name = Parm_value is
the format for the parameters. For multiple parameters, put each parameter
on a separate line.
4. Click on Add.
5. Click on Apply to update the server with your new settings or click Reset to
return to the values that were onto the form before you made the changes.
To remove a servlets initialization parameters:
1. Select the index of the servlet shown in the list.
2. Click on Remove.
3. Click on Apply to update the server with your new settings or click on Reset
to reset the values to what they were before you started to modify the
current screen.
32
/usr/lpp/internet/server_root/java/lib/classes.zip:
/usr/lpp/internet/server_root/cgi-bin/icsclass.zip:
/usr/lpp/internet/server_root/servlets/public
For Windows NT you would use:
C:\WWW\Bin\Java\lib\classes.zip;
C:\WWW\CGI-Bin\icsclass.zip;
C:\WWW\Servlets\Public
You can also decide to set CLASSPATH as an environment variable on the
platform you are using. If you do that, when you compile the SimplestServlet
servlet, you simply enter: javac SimplestServlet.java (see 2.4.2, Servlet
Directory on page 29).
Now you have to copy the new servlet class file SimplestServlet.class into the
servlet directory (see 2.4.2, Servlet Directory on page 29). You should also put
any HTML files associated with your servlet in the document root directory (see
2.4.1, Document Root Directory on page 29). If your servlet needs to read
some initialization parameters, you have two choices:
1. If your servlet is invoked from within an HTML file using the < s e r v l e t > tag,
the initialization parameters will be specified inside the <servlet> tag itself
(see 2.5.2, Invoking a Servlet on page 36).
2. If you invoke your server by pointing directly to its URL, then you must
specify its initialization parameters directly in the configuration file or fill out
the Servlet Configuration section of the Administration and Configuration
Chapter 2. Servlets
33
34
On Windows NT, you can also enter the following commands to stop and start
the Lotus Domino Go Webserver:
1. net stop lotus go Webserver
2. net start lotus go Webserver
In most cases, it is enough that Lotus Domino Go Webserver is restarted to read
the new configuration. On Windows NT, you can simply maximize the Lotus
Domino Go Webserver window, open the File menu and select Restart, as shown
in the following screen:
Chapter 2. Servlets
35
This will force Lotus Domino Go Webserver to read the new configuration without
completely shutting down.
Now you can reinvoke your servlet from the browser.
36
In general you can always invoke a servlet from a browser, pointing directly to
its URL, but you must be sure that the servlet does not require any initialization
parameters. When you write a Java servlet, you should initialize all of the
parameters that you dont want the client to have to set up (for example, the
name of a file that the servlet must open). If the servlet does require
initialization parameters, you can set them to their initial values following the
procedure that we described in 2.4.3.3, Servlet Initialization Parameters on
page 31 and that we see in 2.7.2, Compiling and Installing the Servlet on
page 73.
Moreover, it may be possible that the servlet you are invoking needs to set other
parameters. All the others are simply called parameters and usually their
values are dynamically generated by clients by filling out the fields of a form. If
you want, you can pass these parameters to the servlet by appending a query
string (a URL-encoded string) to the servlets URL, after a question mark ?. For
example:
http://server s IP address/servlet/MyServlet?firstname=Marco&lastname=Pistoia
Where MyServlet is the generic name of one servlet.
We discuss this technique in 2.6.2, Java Servlets Processing Forms on
page 44. We also show another way to call a servlet from the <form> tag of
an HTML form, using either the GET or the POST methods. The correct syntax is
one of the following:
Servlets can handle both the GET and the POST method in a very simple way.
When you invoke a servlet from a form that uses the GET method a question
mark ? is implicitly added after the servlets URL. The ? gets appended to a
query string that encodes the information you have requested. Unfortunately,
there is a chance that the query string will get truncated, so, if it is very long,
you should use the POST method. If you use the POST method, the information
supplied by the user is not appended to the servlets URL but it is submitted as a
Chapter 2. Servlets
37
separate stream. The information is still URL-encoded but this time there is no
danger that it will get truncated.
If you want, you can also invoke a servlet from within an HTML file. The output
of a servlet is usually an entire HTML page, but with this technique you divide
your page in two sections. The first is static and it is the same for all clients that
will have access to your servlet. The second is dynamic and it is automatically
created dependent upon what the clients requests are. The static portion of the
HTML page contains the two tags <servlet> and </servlet>, and every thing
between these two tags and the two tags themselves will be dynamically
overwritten by the dynamic portion of the HTML file. Moreover this technique
allows you to pass to the servlet all the parameters it needs, including the
initialization parameters from within the HTML page. Of course, the Web server
must be able to recognize the presence of the two tags <servlet> and
</servlet>, invoke the appropriate servlet, pass it the right parameters and
send the complete HTML page, composed by the dynamic and the static
sections, back to the client. Lotus Domino Go Webserver 4.6 has this ability and
we dedicate an entire section to the servlet tag technique in 2.8, Servlet Tag
Technique on page 87.
38
The form shown in Figure 22 was generated with the HTML code
CGIServlet.html, stored in the Marco subdirectory of the document root directory.
<html>
<head>
<title>This HTML page invokes the CGIServlet CGI Perl Script</title>
</head>
<body>
<h1>This HTML page invokes<br>the CGIServlet CGI Perl script</h1>
<form method=GET action= / cgi-bin/CGIServlet.pl>
<pre>
First Name: <input type=text name=firstname>
Last Name: <input type=text name =lastname>
<input type=submit> <input type=reset>
</pre>
</form>
</body>
</html>
This form is processed by the CGI Perl script CGIServlet.pl, stored in the CGI-BIN
subdirectory based off of the INSTALL_DIRECTORY. The INSTALL_DIRECTORY
is just a variable that points to the actual directory. On AIX, you have to set the
file mode of the CGI Perl script to executable. To do this, let
INSTALL_DIRECTORY/cgi-bin be the current directory and then enter the
following command:
chmod +x CGIServlet.pl
Chapter 2. Servlets
39
The input to a CGI script is called an HTTP request and the output is called an
HTTP response. The HTML page containing the form passes the input request to
the server when the user clicks on the Submit Query button. The CGI script
reads the input data as key-value pairs or name-value pairs, processes the data
and generates an output response that the server passes back to the client
(browser) that submitted the form.
The HTML code that generated the form used the GET method of passing data to
the CGI script:
http://aixncf10/cgi-bin/CGIServlet.pl?firstname=Marco&lastname=Pistoia
40
Notes:
1. The equal symbol ( = ) separates each input field name from its value.
2. An ampersand (&) separates individual name-value pairs.
3. The parameter data follows the question mark (?).
4. The location of the script is relative to the INSTALL_DIRECTORY.
The part of the URL following the question mark (?) is the value assigned to the
environment variable QUERY_STRING.
The Perl CGI script to be invoked uses the form tag:
Chapter 2. Servlets
41
#!/usr/local/bin/perl
print <<EOM;
Content-type: text/html
<html>
<head>
<title>
HTML Page Dynamically Generated by the CGIServlet CGI Perl Script
</title>
</head>
<body>
<h1>HTML Page Dynamically Generated<br>
by the CGIServlet CGI Perl Script</h1>
<pre>
EOM
$query_string = $ENV{ QUERY_STRING } ;
$query_string = s/%([\dA-Fa-f][\dA-Fa-f])/pack (C, hex ($1))/eg;
$query_string = s/\+/ /g;
@pairs = split (/&/, $query_string);
foreach $pair (@pairs) {
($key, $value) = split (/=/, $pair);
$form_data{$key} = $value;
}
$firstname = $form_data{firstname};
$lastname = $form_data{lastname};
print \n<h2>Data received</h2>\n ;
print Hello, $firstname $lastname. Thank you for your visit!\n\n ;
print <<EOM;
</pre>
</body>
</html>
EOM
close OUT;
Figure 25. CGI Perl Script Processing the HTML Form
Anything appearing after a pound sign (#) on a line is a comment. The first line
(#!/usr/local/bin/perl) is a special comment, because it forces the script file to be
interpreted by the Perl interpreter, located in the /usr/local/bin directory. The
Perl interpreter must have its file mode set to executable.
Everything between print <<EOM; and EOM is printed to the standard output of
the CGI script, which is the dynamically generated page. You will notice that in
the CGI Perl script there are two blocks delimited by two special tags (EOM).
The first block is similar to a standard HTML header:
42
print <<EOM;
Content-type: text/html
<html>
<head>
<title>
HTML Page Dynamically Generated by the CGIServlet CGI Perl Script
</title>
</head>
The second block is similar to the end of an HTML page:
print <<EOM;
</pre>
</body>
</html>
The central part of the script provides the dynamic generation of the HTML code.
It is dynamic because it depends upon the CGI input parameters.
The content of the QUERY_STRING environment variable can be retrieved using
the following instruction:
[0] firstname=Marco
[1] lastname=Pistoia
Each element of the array is split into key and value components, with the equal
sign in each string as a field delimiter:
Chapter 2. Servlets
43
$form_data{$key} = $value
This Hashtable allows you to retrieve the values by using the name as a key:
$firstname = $form_data{firstname};
$lastname = $form_data{lastname};
The dynamic content portion of the page can be generated with:
Figure 26. HTML Page Dynamically Generated by the CGIServlet CGI Perl Script
44
This HTML form is very similar to that shown in Figure 22 on page 39. It was
generated by the following HTML file, called ServletCGI.html and stored in the
subdirectory Marco in INSTALL_LOCATION:
<html>
<head>
<title>This HTML Page Invokes the ServletCGI Servlet</title>
</head>
<body>
<h1>This HTML Page Invokes<br>the ServletCGI Servlet</h1>
<form method=GET action=/servlet/ServletCGI>
<pre>
First Name: <input type=text name=firstname>
Last Name: <input type=text name =lastname>
<input type=submit> <input type=reset>
</pre>
</form>
</body>
</html>
Figure 28. HTML Code Generating the HTML Form
Chapter 2. Servlets
45
You can see that the only difference between this code and the code shown in
Figure 23 on page 39, besides the title, is the value of the action parameter. In
this case it calls the ServletCGI servlet. As we explained in 2.4.2, Servlet
Directory on page 29, the compiled class of every servlet must be stored in the
servlet directory that is identified by the symbolic name servlet, in order to be
recognized by the Web server.
The source code of the ServletCGI servlet is very simple, as you can see in the
following figure:
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class ServletCGI extends HttpServlet
{
public void init(ServletConfig config) throws ServletException
{
super.init(config);
log( ServletCGI has been initialized ) ;
}
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
ServletOutputStream out = response.getOutputStream();
response.setContentType ( text/html ) ;
out.println(<title>HTML Page Dynamically Generated by the ServletCGI Servlet</title> ) ;
out.println(<h1>HTML Page Dynamically Generated<br>by the ServletCGI Servlet</h1> ) ;
String firstname = request.getParameter( firstname ) ;
String lastname = request.getParameter( lastname ) ;
out.println(<h2>Data received</h2> ) ;
out.println( Hello, + firstname + + lastname + . ) ;
out.println( Thank you for your visit! ) ;
out.close();
}
}
The name of this file is ServletCGI.java. It is required that the Java source file,
whose extension is .java, and the relative compiled file, whose extension is
.class, have the same name. The .java file also is stored in the servlet directory.
This is convenient but not necessary.
You can immediately see that the Java servlet source code is much simpler than
the corresponding CGI Perl script.
We needed to import the three packages: javax.servlet, javax.servlet.http and
java.io. The class defining the servlet extends the HttpServlet class rather than
the GenericServlet class, since this servlet must interact with an HTML form.
The two life cycle methods that are implemented are: init() and service().
The init() method is invoked when the servlet is first loaded. This occurs on the
first request for the service only. At that point, the servlet remains in memory
until the server is shut down. This is different from CGI-BINs, which do not
remain in memory. This can be easily demonstrated. After you have compiled
and installed the servlet in the servlet directory, you can modify the source code
of the servlet, recompile it and reinstall it in the servlet directory. This will
overwrite the old version. You will see that what the client s browser display is
updated with the new version of the servlet only when the Web server is stopped
and restarted. This can be done by entering, in an AIX platform, the two
following commands:
46
1. stopsrc -s httpd
2. startsrc -s httpd
In this example, the init() method is passed on to the superclass HttpServlet. The
default init() method initializes the servlet and logs the initialization in the
servlet-log file in the logs directory below INSTALL_LOCATION. The default
string written by the init() method in the servlet-log file consists of the name of
the servlet class followed by : init, as well as the destroy() method. The
destroy() method, which is usually invoked when the server is shut down, writes
in the servlet-log file the name of the servlet class followed by : destroy. The
servlet-log file can give us information about initialized and destroyed servlets.
It is possible to customize both the init() and destroy() methods so that more
than the default amount of information is stored. For example, in this case we
asked the init() method to log the following string into the servlet-log file:
As you can see, the servlet-log file gives information about all the servlets that
have been initialized and destroyed.
We have just seen a way to verify that servlets remain in memory until the
server is shut down. Another advantage of servlets over CGI-BINs is that
generating dynamic content is much simpler. You can retrieve the parameter
values that you want from the request argument of the service() method and
then you print them:
47
The first thing to do is to set the content type of the response. This is done
through the setContentType() method of the HttpServletResponse interface:
response.setContentType(text/html ) ;
It is important to note that this operation is not done through the output stream.
Only the HTML code and actual content are written directly to the output stream.
Moreover, the output stream must be closed before exiting, to make sure that
the stream buffer is flushed. This is done with the following method: out.close();.
It is worth noting that the Java servlet overrides the service() method. An option
is leaving the service() method intact and instead overriding doGet() or doPost(),
depending on the HTTP method parameter specified in the HTML file. In that
case we would override the doGet() method.
We now see what happens when we fill out the form shown in Figure 27 on
page 45, for example, setting the first field to Marco and the second field to
Pistoia.
We submit the form by clicking on Submit Query. The following screen shows
that the URL is automatically set to:
http://aixncf10/servlet/ServletCGI?firstname=Marco&lastname=Pistoia
It also shows that the dynamic HTML page is sent to the clients browser:
48
Figure 32. HTML Page Dynamically Generated by the ServletCGI Java Servlet
Notice that decoding the form parameter data that is passed to the servlet is not
required with servlets as it was with CGI scripts. Basic functions inherited from
the HttpServlet class handles the decoding automatically. Therefore, you can
access the key-value pairs created and encoded by the client browser directly
inside the servlet service() method. The decoded key-value pairs can be
retrieved directly from the first argument of the service() method of the
HttpServlet class.
Chapter 2. Servlets
49
<html>
<head>
<title>This HTML Page Invokes the ServletCGI Servlet</title>
</head>
<body>
<h1>This HTML Page Invokes<br>the ServletCGI Servlet</h1>
<form method=POST action=/servlet/ServletCGI>
<pre>
First Name: <input type=text name=firstname>
Last Name: <input type=text name =lastname>
<input type=submit> <input type=reset>
</pre>
</form>
</body>
</html>
Figure 33. HTML Code Invoking the ServletCGI Servlet with the POST Method
The HTML page generated by this file is identical to that shown in Figure 27 on
page 45. Filling out the form with the First Name field set to Marco and the Last
Name field set to Pistoia and submitting the form will create the correct
ServletCGI servlet. A screen similar to Figure 32 on page 49 is displayed on the
clients browser.
Every time you use the POST method, the Security Information window is
displayed. This occurs before the data that was entered by the client is
submitted to the server.
The user must click the Continue button to go on.
50
Figure 34. A Security Information Window Is Displayed with the POST Method
Next we try the same process with a Perl CGI script and replace GET with POST
as follows:
<html>
<head>
<title>This HTML page invokes the CGIServlet CGI Perl Script</title>
</head>
<body>
<h1>This HTML page invokes<br>the CGIServlet CGI Perl script</h1>
<form method=POST action= / cgi-bin/CGIServlet.pl>
<pre>
First Name: <input type=text name=firstname>
Last Name: <input type=text name =lastname>
<input type=submit> <input type=reset>
</pre>
</form>
</body>
</html>
Figure 35. HTML Code Invoking the CGIServlet Perl CGI Script with the POST Method
Chapter 2. Servlets
51
Figure 36. HTML Page Not Correctly Generated by the CGI Perl Script
We can conclude that the same servlet can handle both GET and POST methods
when receiving parameters from a clients browser request, but if you wanted to
handle both GET and POST methods by submitting a form and using normal CGI
scripts, you would need two different scripts or two different code branches with
some conditional logic. With servlets you can switch between GET and POST
methods while requesting pages without altering any code in the servlet that
handles and responds to the request.
The next example shows how a servlet can discover information about the
server, the client environment and all the data sent by the client. It also
describes loops of a typical structure in servlets (see Figure 40 on page 57).
The HTML form shown in the following window is generated by the HTML file
named FormInfo.html.
52
Chapter 2. Servlets
53
<html>
<head>
<title>Form Info HTML Page</title>
</head>
<body>
<h1>Form Info HTML Page</h1>
<form method= GET action=/servlet/FormInfo>
<P>
Your age: <input type= text Name= age size=2><br>
Your gender:
<input type= radio name= gender value= M>Male
<input type= radio Name= gender value= F>Female<br>
Your favourite foods:
<input type= checkbox name= ItalianFood>Italian
<input type= checkbox name= ChineseFood>Chinese
<input type= checkbox name= MexicanFood>Mexican
<input type= checkbox name= FrenchFood>French<br>
The country where you would spend your holydays:
<select name= CountryHolydays>
<option>USA
<option selected>Italy
<option>Taiwan
<option>Canada
<option>Spain
<option>Great Britain
<option>China
<option>Japan
<option>France
<option>Greece
<option>Germany
<option><i>None of the above</i>
</select><br>
What of these cities have you already visited?
<select name= VisitedCity multiple size=3>
<option value= American>New York
<option value= Italian>Rome
<option value= Canadian>Montreal
<option value= French>Paris
<option value= Italian>Venice
<option value= English>London
<option value= Russian>Moscow
<option value= Mexican>Mexico City
</select><br>
Enter your comments:
<textarea name= Comments rows=2 cols=40></textarea><br>
When you are done with the above responses, please submit this form:
<input type= submit value= Submit this form>
<input type= reset value= Reset this form>
</form>
<p>
Thank you!
</body>
</html>
Figure 38. HTML Code Generating the Form Info HTML Page
This HTML form invokes the Java servlet FormInfo.class using the HTML GET
method. The following figure shows the Java code for this servlet:
54
import
import
import
import
java.io.*;
java.util.*;
javax.servlet.*;
javax.servlet.http.*;
}
}
out.close();
}
}
Chapter 2. Servlets
55
getServletPath() returns the part of the request URI that refers to the servlet
being invoked.
getQueryString() returns the query string part of the servlet URI or null if
none.
getContentType() returns the Internet media type of the request entity data or
null if not known.
getServerName() returns the host name of the server that received the
request.
getServerPort() returns the port number of the port on which the request was
received.
getRemoteUser() returns the name of the user making the request or null if
not known.
getRemoteAddr() returns the IP address of the agent that sent the request.
getRemoteHost() returns the fully qualified host name of the agent that sent
the request.
There is one more piece of code not yet explained. This piece of code was not
necessary in the example in Figure 29 on page 46 because we knew all of the
names of the parameters we were expecting to send. The example we describe
now is more general, because it can be used to test forms that have names of
parameters that we dont know in advance. This is the reason why we parse all
the parameters with an enumeration:
56
We can now use the hasMoreElements() method to test for the end of the
parameter list:
while (names.hasMoreElements())
{
...
}
Inside the while cycle, we can retrieve the next parameter name or key from the
nextElement() method of enumeration:
value = request.getParameter(key);
Now we can do whatever processing or output we like with key and value:
while (names.hasMoreElements())
{
String key, value;
key = (String)names.nextElement();
value = request.getParameter(key);
out.println(KEY: + key + VALUE: + value + <br> ) ;
}
Figure 40. Loops of a Typical Structure in Servlets
Your age: 28
Your favorite foods: Italian and Chinese (Multiple selections are allowed.)
The country where you would spend your holidays: USA (A single selection is
allowed.)
Chapter 2. Servlets
57
When the Submit this form button is selected, the FormInfo servlet will generate
an HTML page with all the requested information. Moving the scroll bar, we
show the dynamic HTML content divided into three windows:
1. The request information window:
58
Figure 42. HTML Page Generated Using the GET Method - Request Information
Figure 43. HTML Page Generated Using the GET Method - Request Headers
Chapter 2. Servlets
59
Figure 44. HTML Page Generated Using the GET Method - Servlet Parameters
Notice that the value of the URL and the query string variables is encoded. (The
part of the string not visible in the window is readable in the URL.)
If we now replace GET with POST in the HTML code:
60
Figure 45. HTML Page Generated Using the POST Method - Request Information
Figure 46. HTML Page Generated Using the POST Method - Request Headers
Chapter 2. Servlets
61
Figure 47. HTML Page Generated Using the POST Method - Servlet Parameters
2.6.4 Multithreading
CGI scripts are completely platform-dependent. While the language with which
they are written can vary, they cant be transported from a Windows machine to
a Macintosh.
Servlets are platform-independent since they are written in Java. They can be
moved between machines with ease and without recompiling. Servlets can also
take advantage of clever Java threading mechanisms and provide fast
turnaround and efficient processing of data. In addition, there is some work
under way to improve Java performance with Just in Time (JIT) compilers.
A servlet can continue to run in the background after it has finished processing a
request, so that it is ready to process the next request without incurring
additional start up costs (memory and CPU). On an active server, the overhead
of starting CGI programs is significant. Furthermore, a servlet can use threads
to process simultaneous requests more efficiently.
The following example is a counter servlet that tells the reader how many times
a page has been accessed since the servlet started running. This servlet does
not need to process an InputStream or read any parameters.
The following window shows the code for the servlet:
62
import java.io.*;
import java.util.*;
import javax.servlet.*;
public class CounterServlet extends GenericServlet
{
static int count = 0;
static Date today = new Date();
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException
{
ServletOutputStream out = res.getOutputStream();
res.setContentType(text/html ) ;
out.println(<html><head><title>Access Counter</title></head> ) ;
out.println(<body><h1>Access Counter</h1> ) ;
Date now;
synchronized(this)
{
++count;
now = new Date();
}
out.println(At the moment, it is <h2> + now + </h2> ) ;
out.println(This servlet has been accessed<h2>+count+</h2> ) ;
out.println(times since<h3>+today+</h3> ) ;
out.println(</body></html> ) ;
out.close();
}
}
The static int count field holds the number of times this servlet was invoked.
The static Date today field holds the time when the servlet was first
constructed.
There is one trick in this servlet that is worth noting. By their nature, Web
servers are multithreaded. Only one copy of the servlet is loaded, but it is likely
that multiple threads from multiple client requests can access the servlet
concurrently. Multiple concurrent access by multiple threads can cause
problems if the servlet is not made thread safe . It is therefore extremely
important for servlets to pay attention to synchronization issues. In this servlet,
you must synchronize access to the count field. The Date variable, today, is
read-only after the servlet is first constructed, so access to it does not need to
be synchronized. We also introduced another Date variable, now . Access to
now is synchronized, so that today holds the time this servlet was first invoked
and this value does not change until the servlet is unloaded, while the value of
now is updated every time the servlet is accessed.
Chapter 2. Servlets
63
Note
How do we synchronize access to the count and now fields? We do this by
indicating the block of code where we have access to count and now as
synchronized, inside the service() method:
synchronized (this)
{
++count;
now = new Date();
}
The object name in the parentheses after the synchronized modifier generally
indicates which lock the block of code should wait to acquire. In this case,
we used the this object, referring to the class itself.
class ClassName
{
void method()
{
...
synchronized (this)
{
...
// synchronized code
}
...
}
}
By using the synchronized modifier in this way, the method only requires the
use of the lock for the minimum amount of time necessary, allowing it to be
used by other threads.
Servlets like this are useful because they can be invoked either as independent
servlets or otherwise using the servlet tag technique. When used with the
servlet tag technique, their outputs are inserted into the HTML files sent to the
clients. We can now invoke CounterServlet directly as an independent servlet
entering its URL: http://aixncf10/servlet/CounterServlet, where aixncf10 is the
host name of our server. The result is shown in the following window:
64
After clicking the Reload button on the Netscape window, the servlet is reloaded
and the count and now variables are updated, while today does not change its
value, as shown in the following screen:
Chapter 2. Servlets
65
You get the same results accessing the servlet from another client. For
example, you can open a new window running Netscape and recall the
CounterServlet:
66
In order to have a real update of the count and now variables, be sure that you
have reset the history of your browser (selecting the Clear History button in the
Preferences window) and both the memory and the disk caches. (Clicking both
the Clear Memory Cache and Clear Disk Cache buttons in the Cache window.
They can be accessed from the Advanced Preferences window.)
67
import
import
import
import
java.io.*;
java.util.*;
javax.servlet.*;
javax.servlet.http.*;
68
Chapter 2. Servlets
69
if (key != null)
out.print(key);
out.println( \><p> ) ;
out.println(<input type=\ submit\ value=\ SUBMIT\><p></form><hr> ) ;
if (key != null && key.length() != 0)
{
key = key.toUpperCase();
String values = (String) employeeInfo.get(key);
if (values != null)
{
int tab = values.indexOf( & ) ;
out.println(<table width=\35%\ border=\3\ > ) ;
out.println(<tr><th>Name</th> ) ;
out.println(<td> + key + < / td></tr> ) ;
out.println(<tr><th>Electronic Address</th> ) ;
out.println(<td> + values.substring(0, tab) + < / td></tr> ) ;
out.println(<tr><th>Phone</th> ) ;
out.println(<td> + values.substring(tab+1, values.length()));
out.println( < / td></tr></table> ) ;
}
else
{
out.println(key + not found ) ;
}
}
out.println(<p></body></html> ) ;
out.close();
}
The database containing all the information about IBM employees is a text file
called employee.txt. It contains the name, electronic address and telephone
number for all the IBM employees. It is assumed that each line of the text file is
divided into three fields separated by an ampersand ( &). There is a line for each
employee. The first field has the employees name. The second field has the
employees electronic address. The third field stores the employees telephone
number. Employees records are stored in alphabetical order in our example.
Our database is simple as shown in the following figure:
BECHARD CLAUDE&WTSCPOK(BECHARD)&352-4539
LIU THOMAS&WTSCPOK(LIU)&352-4543
NUSBAUM BARRY&WTSCPOK(BARRY)&352-4542
This line is wrong
PISTOIA MARCO&WTSCPOK(PISTOIA)&352-3514
ROCHESTER GIANCARLO&WTSCPOK(GROCHEST)&352-4541
Figure 53. Database Text File
Notice that one of the lines of the database is not formatted the same way as the
others:
70
When the servlet reads the database, it stores all the information in
employeeInfo, which is an instance of the Hashtable class:
employeeFile = getInitParameter(dbfile ) ;
2. Tries to open the database text file:
Chapter 2. Servlets
71
if ((tab=raw.indexOf(&))<0)
{
...
raw = buffread.readLine();
continue;
}
3. Splits each line into two string components. The first component is the
employees name converted to all uppercase and the second one is a string
having both the employees electronic address and telephone number, still
separated by an ampersand ( &):
employeeInfo.put(name, values);
5. Throws an IOException if an input/output error occurred:
throw e;
Also the readDB() method, like the init() method, logs all these operations in the
servlet-log file using the log() method of the GenericServlet class.
The service() method of the EmployeeSearch servlet builds an HTML form and
sends it to the client. The form contains a text input field where the user can
write the name of the employee whose electronic address and telephone number
were requested. The form is built in a very simple way:
http://aixncf10/servlet/EmployeeSearch?key=Pistoia+Marco
then the name Marco Pistoia is also automatically written in the text input field.
Otherwise, if the user simply invokes the servlet without specifying any
parameter, the text input field is empty.
The following statement creates a Submit button:
72
key = key.toUpperCase();
String values = (String) employeeInfo.get(key);
For each employee an electronic address and telephone number had been
saved in the same string component of the Hashtable, separated by an
ampersand. The following step retrieves both these parameters, creates an
HTML table containing all the information that the user requested and sends it
back to the client.
If the name entered by the user does not match any key in the hashtable, an
error message is sent back to the client:
out.println(<p></body></html> ) ;
In addition, it closes the output stream before exiting, to make sure that the
buffer stream is flushed:
out.close();
The destroy() method of the EmployeeSearch servlet is very simple. When the
Web server is shut down, the destroy() method destroys the servlet and logs this
operation in the servlet-log file:
javac EmployeeSearch.java
The EmployeeSearch.class file must be stored in the servlet directory (see 2.4.2,
Servlet Directory on page 29). The EmployeeSearch servlet reads a database
text file, which we called employee.txt. We can place that file anywhere, but we
need to let the servlet know where it will be located. The database text file
name is an initial parameter for the servlet (see 1 on page 71), so we have to
follow the procedure indicated in 2.4.3.3, Servlet Initialization Parameters on
Chapter 2. Servlets
73
dbfile=/usr/lpp/internet/server_root/database/employee.txt .
The init() method of the EmployeeSearch servlet forces the servlet to read the
value of the dbfile initial parameter:
74
displayed on the screen so you can reread all of the configuration information.
In that screen capture we only showed the section relative to the
EmployeeSearch servlet configuration:
Configuration Page
Restart Server
We click on Restart Server. This causes the server to read the updated
configuration file and restart without fully shutting down.
The Security Information window reappears on the screen and we click on the
Continue button. The last step is the Restart Confirmation page:
Chapter 2. Servlets
75
This page confirms that the server has been successfully restarted. You can
click on the Configuration Page button to continue with further configurations.
We should also remember that if we modify the Java source code of the servlet
and compile the modified source code, we have to stop the Lotus Domino Go
Webserver and restart it by entering:
1. stopsrc -s httpd
2. startsrc -s httpd
Now our servlet is completely installed and its configuration will be present in
the Servlet Initialization Parameters window:
76
Chapter 2. Servlets
77
We can fill out the input text file setting the employees name to PISTOIA
MARCO.
78
Figure 60. Insert the Name of the Employee You A r e Searching For
Clicking the SUBMIT button causes the servlet to give us the following dynamic
response:
Chapter 2. Servlets
79
http://server s IP address/servlet/EmployeeSearch?key=PISTOIA+MARCO
We already pointed out that the EmployeeSearch servlet is written in order to
dynamically fill out the text input field with the employee s name. For example,
the following window is shown when we enter the following URL:
http://servers IP address/servlet/EmployeeSearch?key=Pistoia+Marco
80
We obtain the table with the requested information and the text input field is
automatically updated.
Chapter 2. Servlets
81
Notice that it is not necessary to use all capital letters in the input text field, even
if all employees names are written in capital letters in the database text file (see
Figure 53 on page 70). The servlet automatically converts the string to
uppercase to see if it matches one of the items in the database text file. You
can see this if you compare Figure 63 and Figure 61 on page 80.
If you type the name of a person who is not included in the database (for
example, Smith John), you will get an error message:
82
EmployeeSearch:
EmployeeSearch:
EmployeeSearch:
EmployeeSearch:
EmployeeSearch:
EmployeeSearch:
EmployeeSearch:
init
The EmployeeSearch servlet has been correctly activated.
DB file / usr/lpp/internet/server_root/database/employee.txt .
Uncorrect employee database file at line 4.
EmployeeSearch has read 6 lines.
EmployeeSearch Hashtable has 5 entries.
Servlet EmployeeSearch working
Chapter 2. Servlets
83
That debugging information was extracted from the following figure. The other
lines are relative to other life cycles of the servlet.
Notice in particular that the servlet logs information indicating that the fourth line
of the database text file is incorrect. This causes the two messages that follow
about the database text file having six lines but the Hashtable that the servlet
has created has only five entries. This matches Figure 53 on page 70.
If the Lotus Domino Go Webserver is shut down after a client has initialized the
servlet, we see a new line in the servlet-log file as shown in:
Figure 67. servlet-log File after the destroy() Method Has Been Called
Lets restart the Web server and try another experiment. We renamed the
database text file, entering the following command when
/usr/lpp/internet/server_root/database is the current directory:
84
mv employee.txt employee1.txt
If we do not update the Servlet Configuration form, we can still invoke the servlet
by pointing to its URL, because no error message is displayed on the client s
browser, as the following window demonstrates:
We then try to search for an employee and we enter Pistoia Marco into the input
text field. When we try to submit this form, the URL is modified, but no response
is displayed:
Chapter 2. Servlets
85
The servlet didnt work and we didnt get any indication as to why it didnt work.
This is the reason our servlet logs all operations it performs including all errors
that occurred in the servlet-log file.
86
The last five lines of this text screen show what the servlet has logged. They
show that:
1. The servlet has been correctly initialized, as we understood by looking at the
client s browser:
EmployeeSearch: init
EmployeeSearch: The EmployeeSearch servlet has been correctly activated.
2. The servlet read into the configuration file the exact database file name and
the path to it:
...
Chapter 2. Servlets
87
When the Web server sees the .shtml extension for the HTML file, it
automatically looks for the <servlet> and </servlet> tags inside the
document and tries to build the dynamic HTML portion. The format of the
< s e r v l e t > t a g i s s i m i l a r t o t h e < a p p l e t > t a g . The servlet does not have a
user interface at the client. T h e r e f o r e , a < s e r v l e t > t a g , u n l i k e a n < a p p l e t >
tag, does not require and in fact cannot have a width or height parameter and in
its minimum form looks like this:
<servlet name=ServletName>
...
</servlet>
ServletName specifies a symbolic name for the servlet. Usually it could be the
class name of the servlet without the .class extension. If you wish, the class
name may also be specified in the <servlet> tag as the value of the code
attribute as follows:
<servlet code=ServletCode.class>
...
</servlet>
Please, note that the class name always requires the .class extension.
Moreover, both name and class name for the <servlet> tag may be specified,
so a more complete example for the <servlet> tag is the following:
City=Raleigh
Country=USA
88
Company=IBM
Employee=Marco
<html>
<head>
<title>Experiment SHTML Page</title>
</head>
<body>
<h1>Experiment SHTML Page</h1><hr>
<servlet code=Experiment.class City=Raleigh Country=USA>
<param name=Company value=IBM>
<param name=Employee value=Marco>
</servlet>
<hr>
</body>
</html>
Figure 71. HTML Code of the Experiment.shtml File
This shtml page has very little static content and provides dynamic content by
invoking the Experiment.class servlet. The Experiment.java file is shown in the
following figure:
Chapter 2. Servlets
89
import
import
import
import
javax.servlet.*;
javax.servlet.http.*;
java.io.*;
java.util.*;
Invoking the servlet with the servlet tag technique is very simple. All you have
to do is point the clients browser to the HTML file having an .shtml extension
and call the servlet from within the <servlet> tag. In our case, we entered the
location of the Experiment.shtml file. The result is shown in the following figure:
90
The Experiment.java servlet is very simple but it is also very useful for checking
if your Web server is able to handle the servlet tag technique. Reading the Java
source code of the Experiment servlet (see Figure 72 on page 90), we see some
Chapter 2. Servlets
91
of the techniques that we already knew. For example, to retrieve the initial
parameters, we first use the getInitParametersNames() method of the
GenericServlet class, which returns the names of the servlets initialization
parameters as an enumeration of strings or an empty enumeration if there are
no initialization parameters. Secondly we use the getInitParameter() method
iterating over all the initialization parameters, following a similar procedure as
indicated in Figure 40 on page 57. The way we retrieve the normal parameters
is not different, but we used the getParameterNames() and the getParameter()
methods of the ServletRequest class.
Looking at the HTML source code in Figure 71 on page 89 and the result
displayed on the clients browser in Figure 73 on page 91, it is interesting to
note how everything between the two tags <servlet> and </servlet>,
including the tags themselves, has been dynamically overwritten and has been
completely replaced by the dynamic portion of the HTML file produced by the
servlet. This replacement takes place at the server-side. This is the reason why
the servlet tag technique is also known as server-side inclusion. A
demonstration of what we are stating can be obtained from the clients browser
itself, while it is displaying the Experiment.shtml page. Clicking on the View
menu of the Netscape window (see Figure 73 on page 91) and then selecting
Page Source, we can see that there is no more trace of the <servlet> and
</servlet> tags and the dynamic portion of the HTML dependent upon all the
parameters passed to the servlet has completely replaced it:
Figure 74. HTML Source Code after the Dynamic Portion Has Been Embedded
Moreover, this demonstrates that the Java code of the servlet is not accessible
from the client-side.
Additional information can be retrieved using the log() method of the
GenericServlet class. We had indicated that the server calls the init() method
92
only once when the first client requests the servlet. This could not be completely
true if the servlet is invoked from within the <servlet> tag of an HTML page.
Our tests demonstrated the following:
1. The first time you invoke the servlet from within the < s e r v l e t > tag of an
HTML page, you must specify the code attribute, plus all the initialization
parameters.
2. If you specify the name attribute too, you will be able to, from that point,
invoke the servlet only with the name parameter.
3. In this case the servlet is not reinitialized and the initialization parameters
passed to the servlet the first time survive.
4. If the code attribute is specified without the name attribute, the server is
forced to reload the servlet, even if you are using the same identical
configuration (the same code, the same initialization parameters). Multiple
instances of the same servlet are created and they are simultaneously
destroyed when the destroy() method for the servlet is invoked, typically
when the Web server is shut down.
5. If you specify only the name attribute, the server is not forced to reload the
servlet and so initialization parameters passed to the servlet the first time
survive, even if you try to change them by specifying new values.
For example, we can consider the Experiment servlet. It is invoked by the
Experiment.shtml file, from within the <servlet> tag, using the code attribute.
We can see that the server calls the init() method for the Experiment servlet
every time a client requests an HTML file that invokes that servlet from within
the <servlet> tag using the code attribute.
This can be demonstrated by restarting the Lotus Domino Go Webserver,
pointing the browser to the URL of the Experiment.shtml page and reloading the
page a specific number of times. Before reloading the HTML page, we should
be sure to clear the history, the memory cache and the disk cache of our
browser, as indicated at the end of 2.6.4, Multithreading on page 62. Our
servlet logs its initialization and the servlet-log file shows that the Web server
has invoked the init() method each time we reloaded it.
Why has the Web server initialized the servlet five times? When a servlet is
invoked from within the <servlet> tag of an HTML file and the code attribute is
specified, the servlet dynamically receives its initialization parameters. These
parameters are no longer passed to the servlet statically, using the Servlet
Configuration form. We want to have the option to use a different HTML file to
Chapter 2. Servlets
93
invoke the same servlet from within a <servlet> tag, passing it different
initialization parameters. That is the reason why the Web server, when the code
attribute also is specified, calls the init() method of the servlet and passes the
initialization parameters to the servlet.
Finally we want to try another test. The Experiment servlet can be invoked
directly by pointing to its URL and without interacting with an HTML page only if
we are able to pass it all the parameters it needs. Its parameters are divided
into two classes:
1. Initialization parameters can be passed to the servlet also by filling out and
submitting the Servlet Configuration form (see 2.4.3.3, Servlet Initialization
Parameters on page 31). Following the same steps we used to install the
EmployeeSearch servlet (see 2.7.2, Compiling and Installing the Servlet on
page 73), we fill out the Servlet Configuration form by setting:
Parameters to:
City=Raleigh
Country=USA
You should then click on Apply, as shown in the following screen:
Figure 76. Filling Out the Servlet Configuration Form for the Experiment Servlet
94
After restarting the Web server, you can invoke the servlet by simply pointing
to its URL, but you still have to communicate its normal parameters to it.
2. Normal parameters can be communicated to the servlet by appending to its
URL a question mark (?) followed by the query string of the requested
parameters, for example:
http://server s IP address/servlet/Experiment/Company=IBM&Employee=Marco
(See 2.5.2, Invoking a Servlet on page 36.)
The following figure shows the result:
This time the HTML page is completely dynamic, because the Experiment servlet
has not been invoked from within a <servlet> tag of any HTML page.
If the servlet is directly invoked in this way, the Web server calls the init()
method only once, when the first client browser points to the servlets URL. In
fact, in this case, when initialization parameters are specified from within the
Servlet Configuration form they cant change.
We can obtain a very simple demonstration of this if we clear history, memory
cache and disk cache from our browser and we call the servlet a number of
Chapter 2. Servlets
95
times. The servlet-log file indicates that the servlet is initialized only the first
time:
Figure 78. The init() Method Is Called Only the First Time the Servlet Is Invoked
set CLASSPATH=C:\WWW\Bin\Java\lib\classes.zip;
C:-WWW-CGI-Bin-icsclass.zip;C:-WWW-Servlets-Public
After making that change you should reboot your system.
The servlet we built to show the servlet tag technique is called IncludedCounter.
It is not supposed to be invoked directly by pointing to its URL, but it is invoked
from within the <servlet> tag on HTML pages that have a .shtml extension. Its
purpose is to produce a counter that can be dynamically embedded inside an
HTML file that carries the .shtml extension. It counts how many times that HTML
page has been accessed by a particular client machine. Instead of counting how
many times the HTML file has been requested in general by all clients, it holds
different counters for different clients. The output of this servlet is simply an
integer, which is dynamically embedded inside the HTML page by using the
servlet tag technique.
In addition, it is also possible that different HTML pages invoke this servlet,
provided that they call it with different instance names, using the name attribute
o f t h e < s e r v l e t > t a g . In this way, there is an instance for each HTML page and
each instance counts the number of times its related HTML page has been
invoked.
Each instance of the IncludedCounter servlet uses a Hashtable object to register
all the necessary information related to the HTML page invoking that instance.
As we know, the java.util.Hashtable class implements a Hashtable, which maps
keys to values. In this case, when a client machine requests the HTML page
96
Chapter 2. Servlets
97
import
import
import
import
java.util.*;
java.io.*;
javax.servlet.*;
javax.servlet.http.*;
98
Chapter 2. Servlets
99
Of course, it is necessary to also show the Java source code for the StoredData
class used to wrap all the counters. The following figure shows the
StoredData.java file:
import java.io.*;
public class StoredData implements Serializable
{
int number;
public StoredData(int value)
{
number = value;
}
public int increment()
{
++number;
return number;
}
}
Figure 80. StoredData.java
100
<HTML>
<HEAD>
<TITLE>PAGE 1</TITLE>
</HEAD>
<BODY>
<H1>PAGE 1</H1>
This is the <B>first</B> example of a SHTML page invoking the IncludedCounter servlet
<HR>
The file containing the stored data is <B>Page1.obj</B>.
<HR>
<CENTER>
<H2>
You have invoked this page
<H1>
<SERVLET
code=IncludedCounter.class
name=IncludedCounter1
filename= C:\\Objects\\Page1.obj>
</SERVLET>
</H1>
times
</H2>
</CENTER>
</BODY>
</HTML>
When the clients browser requests the Page1.shtml file, the .shtml extension
forces the Web server to search the pair of tags (<servlet> and </servlet>)
within the HTML code. Everything between these two tags, plus the tags
themselves, is replaced by the dynamic output of the IncludedCounter servlet.
Notice that this HTML page invokes the IncludedCounter servlet, so that the Web
server automatically creates an instance of that servlet. This instance is called
IncludedCounter1, according to the value of the name attribute within the
< s e r v l e t > t a g . This instance is related to the Page1.shtml file. The filename
initialization paramenter is passed to the servlet with the value
C:\Objects\Page1.obj. This means that the Hashtable object related to the
Page1.shtml file (used to register all the clients that have access to the
Page1.shtml page and the number of the accesses) will be saved in the
Page1.obj file.
In order for the Web server to be able to create the IncludedCounter1 servlet
instance, the init() method is called. This method is used by the servlet to
discover the value of the filename initialization parameter and to retrieve the
Hastable object, named table, from the file. Of course, before running the
servlet, it is necessary to create the empty file Page1.obj inside the directory
C:\Objects, otherwise a FileNotFoundException exception is thrown. Notice that
the first time the servlet is run, the Page1.obj file will be empty and no Hashtable
object will be retrieved. This situation is handled by simply catching an
IOException exception.
The service() method works according to a very simple mechanism. First of all it
retrieves the IP address of the client machine from where the Page1.shtml page
was requested. This function is accomplished by the getRemoteAddr() method
for the HttpServletRequest object, called req and passed to the service() method.
Chapter 2. Servlets
101
Then the service() method creates a StoredData object named counter, used to
retrieve the number of accesses to the Page1.shtml file from the client machine.
Also, the counter.increment() method is invoked to update the counter field.
If that client machine is accessing the Page1.shtml file for the first time, no
counter object can be created starting from the table, so the counter s
constructor is invoked, passing it the int value 1. In this case the table object
must be updated with the IP address of the new client that accessed the
Page1.shtml file and its relative StoredData object.
Finally the service() method produces the dynamic HTML portion to embed
inside the Page1.shtml file.
The destroy() method is invoked only when the Web server is shut down. It is
used to store the table object inside the Page1.obj file.
Notice that accesses to the table objects need to be synchronized in order to
avoid multiple threads from multiple client requests causing problems when
accessing the servlet concurrently.
Now that we have described how the IncludedCounter servlet works, we can
experiment with it. First of all the Page1.obj file must be created, placing it
inside the directory C:\Objects as is required by the Page1.shtml file. To create
this file, it is enough to open and save an empty text file with the MS-DOS editor.
We should be sure that the file we created has the right read and write
permissions.
Before experimenting with the IncludedCounter servlet, it is a good idea to open
the Preferences window for the Netscape browser and to set to 0 the number of
days after which pages in history expire. The Preferences window can be
accessed from the Edit menu. You can also select Advanced and then Cache in
the Preferences window and set Memory Cache and Disk Cache to 0 KB. In this
way, you do not have to clear history, memory cache and disk cache for your
browser each time you request the Page1.shtml file to experiment with the
counter.
If you place the Page1.shtml file in a subdirectory of your Web server below
C:\WWW\HTML, point your browser to its location and then click two times on the
Reload button of the Netscape browser window, you can immediately see how
the IncludedCounter works. The dynamic portion embedded inside the
Page1.shtml file is automatically updated and you can read that you have
effectively invoked that page three times, as shown in the following figure:
102
Figure 82. The Page1.shtml File Has Been Reloaded Three Times
You can see that the counter, which is the dynamic portion of the HTML page, is
automatically increased each time you reload that page.
After each experiment, we want to immediately check the servlet-log file, placed
inside the directory C:\WWW\Logs. Comparing the servlet-log file with the Java
source code of the IncludedCounter servlet, we can see useful information about
how the servlet really works. In the last release of the Lotus Domino Go
Webserver 4.6, the output of the log() method is saved inside a file called
servlet-log that carries the extension of the current date. This gives you a
servlet-log file for each day your Web server has invoked a servlet. The
following window shows the servlet-log file after we reloaded the Page1.shtml
file three times:
Chapter 2. Servlets
103
Even if the servlet has been invoked three times, notice that it has been loaded
only once. In fact the init() method has been called only once, while the
service() method has been invoked three times. Also notice that the servlet has
been able to find the Page1.obj file, otherwise we would have read that a
FileNotFoundException exception had been caught. Nevertheless an IOException
exception has been caught, because the Page1.obj file was empty and it was not
possible to retrieve any Hashtable object from it.
Another interesting experiment we can try is to invoke the Page1.shtml file from
a different client machine. We see that the IncludedCounter servlet holds two
separate counters for the two different client machines. The following figure
shows the Netscape 2.02 browser for OS/2 after having invoked the Page1.shtml
file:
104
Figure 84. The Page1.shtml File Loaded from a Different Client Machine
Opening the servlet-log file again, we see that this operation has simply caused
a new call to the service() method:
Chapter 2. Servlets
105
These tests demonstrate that only one instance of the IncludedCounter servlet
has been loaded, according to the only value given to the name parameter
within the <servlet> tag.
We want to now try a new experiment with a new HTML file, called Page2.shtml.
The HTML code for this file is shown in the following figure:
<HTML>
<HEAD>
<TITLE>PAGE 2</TITLE>
</HEAD>
<BODY>
<H1>PAGE 2</H1>
This is the <B>second</B> example of a SHTML page invoking the IncludedCounter servlet
<HR>
The file containing the stored data is <B>Page2.obj</B>.
<HR>
<CENTER>
<H2>
You have invoked this page
<H1>
<SERVLET
code=IncludedCounter.class
name=IncludedCounter2
filename= C:\\Objects\\Page2.obj>
</SERVLET>
</H1>
times
</H2>
</CENTER>
</BODY>
</HTML>
The most important things that we must notice in this second file are the
following:
It forces the Web server to create a second instance for the IncludedCounter
servlet, called IncludedCounter2.
The Hashtable object related to this second instance will be stored into the
Page2.obj file.
Of course we must create the Page2.obj file in the directory C:\Objects before
loading the Page2.shtml file, otherwise a FileNotFoundException exception will
be caught by the init() method.
Pointing our browser to the Page2.shtml file and selecting the Reload button one
time in the Netscape browser, we see a screen similar to the following:
106
Figure 87. The Page2.shtml File Has Been Loaded by the Client s Browser
This picture demonstrates that even if the client machine is the same one that
requested the Page1.shtml file, the Web server has created a new servlet
instance that holds a separate counter for the Page2.shtml file.
It is worth looking back at the servlet-log file now. It shows an example of a new
instance that has been created for the IncludedCounter servlet, as shown in the
following figure:
Chapter 2. Servlets
107
Notice that for this second instance an IOException exception has been caught,
because the Page2.obj file that we created is empty.
Before restarting the Web server, we want to check the status of the two files
Page1.obj and Page2.obj, which will be used to store the two Hashtable objects
held by the two instances IncludedCounter1 and IncludedCounter2. The
following figure shows that they are still empty, even if the two instances have
already been created:
Figure 89. Both the Files Page1.obj and Page2.obj A r e Still Empty
In fact it is the destroy() method that will definitively store the two objects inside
these two files. The destroy() method is called by the Web server itself when it
is shut down. After restarting the Web server, we can see that the two files are
no longer empty, as shown in the following figure:
108
Figure 90. Both the Files Page1.obj and Page2.obj A r e No Longer Empty
The servlet-log file is now very interesting, because it shows that both the
IncludedCounter1 and IncludedCounter2 instances have been destroyed as soon
as the Web server has been restarted:
The next experiment shows the init() method functions. We wrote a custom init()
that should now be able to retrieve the Hashtable objects stored inside the
Page1.obj and Page2.obj files. If we open our browser, which last time had
invoked Page1.shtml three times, and we point it to the Page1.shtml file, the
dynamic counter informs us that this is the fourth time we have access to that
page, as shown in the following figure:
Chapter 2. Servlets
109
Figure 92. The Page1.shtml File Has Been Loaded after the Web Server Was Restarted
Since the Page1.obj file effectively contained a Hashtable object stored inside it,
no IOException exception has been caught this time and the servlet-log file
simply indicates that both the init() and the servlet() method have been called a
single time:
Other tests could be done modifying the configurations within the <servlet>
tag. For example we demonstrated the following:
110
If we specify only the code attribute within the servlet tag and we do not
specify any value for the name attribute, the Web server creates new
instances for the servlet each time we click the Reload button of the
Netscape browser window. Each one of these instances reads the same
Hashtable object from the same file, so we see that the counter field is
updated only the first time. All these instances are destroyed when the Web
server is shut down. This demonstrates that it is necessary to specify a
value for the name attribute, in order to create only one instance of the
servlet for each HTML page and to get the counter really updated.
It is also possible to avoid the creation of the file with the extension .obj,
before the HTML file is invoked. The servlet automatically creates the file
when the destroy() method is called and stores the Hashtable object inside
it.
If the value for the name attribute is also specified, the initialization
parameter specified at the moment the servlet instance was created survives
even if we try to change it by modifying it within the <servlet> tag of the
HTML page.
Chapter 2. Servlets
111
112
Chapter 3. Connectors
This chapter describes all the connectors that we use on AIX and Windows NT
and shows how to set them up.
IMS Connectors
MQSeries
CICS
DCE servers
To download and test the IBM NCF connectors you can link to
http://www.ics.raleigh.ibm.com/ibmconnectors as shown in Figure 94 on
page 114.
Copyright IBM Corp. 1998
113
114
Presentation Logic
Business Logic
All of these parts may be included in a single program or can be split into two or
more programs linked through the CICS API: EXEC CICS LINK. In the past, the
most common programming methodology was to include all three components
inside a single module where the presentation logic was generally based on
3270 screens. More recently, applications started to be written in a client/server
style where the presentation logic (3270 or graphical user interface), could call
the business logic using a CICS LINK, passing and receiving data through the
COMMAREA. CICS provides the ability to invoke a local program, inside the
same CICS region where the calling program runs, or a remote program, in a
different region where the calling program runs across the network. In a
distributed CICS environment you can call a program using the following
functions:
Distributed program link (DPL) is the ability to call a remote CICS program
between CICS servers. The CICS API used is EXEC CICS LINK where the
called program location can be explicitly included into the API command or
you can use the CICS program definition. Using the program definition is the
recommended way since you do not have to recompile the program if you
change the called program location, just update the program definition.
External call interface (ECI) is the ability to call a CICS server program from
a CICS client.
To invoke a CICS program that includes all three components (3270 presentation,
business and data access logic), you have to present the request the same way
that a 3270 device does. CICS allows this by using:
Chapter 3. Connectors
115
116
memory. This happens when the user starts his or her first transaction. The
state information includes a session identifier that is placed in a hidden field on
every HTML page sent to the browser and the terminal identifier obtained during
the first request sent to the CICS server. It is used in all subsequent EPI
requests. A browser session will terminate, and all resources will be deleted,
when:
Chapter 3. Connectors
117
3.1.2.1 Installation
The CICS Internet Gateway solution is distributed with CICS client products and
the installation steps are documented in Network Computing Framework
Component Guide , SG24-2119. You can download the CICS client from:
http://www.hursley.ibm.com/cics/clients or from: http://service.software.ibm.com
for free if you already have a license for any CICS transaction server.
The CICS gateway may be installed when the CICS client is installed, or at any
time afterwards by running the CICS Client Installation utility program and
selecting the CICS Internet Gateway as an additional component to install. The
CICS gateway is installed into the cig directory under the main CICS client
directory.
The installation step when completed successfully modifies your system
environment. This depends upon the platform you are using. For example, in
Windows NT two keys are added to the Windows NT registry.
All the documentation that you need is provided in HTML format. You can
retrieve it using your Web browser and opening the file
file:///c:/cicscli/cig/html/Index.htm after you have installed the code.
3.1.2.2 Customization
CICS Internet Gateway requires two actions:
1. Configuring the CICS gateway
The CICS gateway has a configuration file called CIGD.INI located in the
c:\CICSCLI\CIG\BIN directory on Windows NT and OS/2, or CIGD.ENV located
in /usr/lpp/cig/bin/ on AIX. You have to verify that the following paths were
set correctly.
For Windows NT and OS/2
Trace = c:\cicscli\cig\admin\cigtrace.log
Error = c:\cicscli\cig\admin\cigerror.log
Info
= c:\cicscli\cig\admin\ciginfo.log
Header = c:\cicscli\cig\html\headtext.htm
Trailer = c:\cicscli\cig\html\tailtext.htm
ExitPage = c:\cig\cigstart.htm
For AIX
Trace = /tmp/cigtrace.log
Error = /tmp/cigerror.log
Info
= /tmp/ciginfo.log
Header = /usr/lpp/cig/html/prime/headtext.htm
Trailer = /usr/lpp/cig/html/prime/tailtext.htm
ExitPage = /cig/cigstart.htm
As you can see in Figure 100 on page 122 the configuration file has two
sections:
118
Default section - Defines features that can not be overridden when the
request to start a transaction is submitted.
TimeOutCICS - How long the gateway will wait for CICS to respond
to a user request. When that interval expires the gateway will free
up all resources associated with that browser session.
Chapter 3. Connectors
119
120
You can provide your header and trailer logo images or use what is
provided by IBM. Just modify the Header and Trailer path in the CICS
Gateway configuration file.
The parameters described in the override section could be used to
customize solutions as we show in 3.1.2.6, How to Use CICS Internet
Gateway on page 129.
Chapter 3. Connectors
121
Figure 100 (Part 1 of 3). CICS Internet Gateway - CIGD.INI File for Windows NT
122
[Default]
Trace = C:\CICSCLI\cig\admin\cigtrace.log
Error = C:\CICSCLI\cig\admin\cigerror.log
Info = C:\CICSCLI\cig\admin\ciginfo.log
Cursor = 0x23
MaxUsers = 15
TimeOutCICS = 60
TimeOutInternet = 600
TimeOutGateway= 60
;----------------------------------------------------------------------; Override section - This section defines features which can be
;
overridden with start tran.
;
;Header
- This specifies the fully qualified path name to a
;
piece of HTML that will be imbedded at the top of
;
every page.
;
This will default to no header.
;Trailer
- This specifies the fully qualified path name to a
;
piece of HTML that will be imbedded at the bottom of
;
every page.
;
This will default to no trailer.
;ExitPage
- This specifies the URL of the exit page that will be
;
displayed at the end of the session. This can either
;
be local ( eg. /cig/cigstart.htm )
;
or remote ( eg. http://saints/cig/cigstart.htm )
;
NB. A local URL will be faster.
;
It can also be the URL of a cgi script to call on exit
;
( eg. /cig-bin/cleanup )
;
This will default to /cig/cigstart.htm
;ExitAid
- In some cases it will be necessary to back out of a
;
transaction. This parameter specifies the name of the
;
key which will be entered to exit. This value should
;
be specified in Hex. e.g. 0x33 for PF3 .
;
This will default to 0x00 (i.e. don t attempt to
;
cleanly exit a transaction when an error occurs).
;
Note: This could mean that the terminal cannot be
;
be deleted because the EPI still believes that the
;
transaction is still active
;PFKey24
- In some CICS applications 24 PF keys are required.
;
This option allows you to specify whether you would
;
like these PF 13 to 24 keys to be displayed. A value of
;
On will enable displaying of these PF keys.
;
Note: Loading these extra graphics will be slower.
;
This will default to Off.
;PAKeys
- In some CICS applications the 3 PA keys are required.
;
This option allows you to specify whether you would
;
like these extra PA keys to be displayed. A value of
;
On will enable displaying of these PA keys.
;
Note: Loading these extra graphics will be slower.
;
This will default to Off.
Figure 100 (Part 2 of 3). CICS Internet Gateway - CIGD.INI File for Windows NT
Chapter 3. Connectors
123
;GraphicKeys
;
;
;
;
;
;AutoExit
;
;
;
;
;ImbedHTML
;
;
;
;
;
;
;AppendEXE
;
;
;
;
;
;
[Override]
Header = C:\CICSCLI\cig\html\headtext.htm
Trailer = C:\CICSCLI\cig\html\tailtext.htm
ExitPage = /cig/cigstart.htm
ExitAid = 0x00
PFKey24 = Off
PAKeys = Off
GraphicKeys = Off
AutoExit = Off
ImbedHTML = Off
AppendEXE = Off
Figure 100 (Part 3 of 3). CICS Internet Gateway - CIGD.INI File for Windows NT
124
LotusGo Webserver Windows NT file: WINNT\HTTPD.CNF
Exec
Exec
Pass
/cig-bin/*
/cig-admin/*
/cig/*
c:\cicscli\cig\cgi\*
c:\cicscli\cig\admin\*
c:\cicscli\cig\html\*
The above entries must be placed before the generic Pass directive
below, which already exist in the file.
Pass
/*
c:\www\html\*
file: /etc/httpd.conf
Exec
Exec
Pass
/usr/lpp/cig/cgi/*
/usr/lpp/cig/admin/*
/usr/lpp/cig/html/prime/*
/cig-bin/*
/cig-admin/*
/cig/*
Where prime is the name of your locale. The above entries must be
placed before the generic Pass directive below, which already exist
in the file.
Pass
/*
/usr/lpp/internet/server_root/pub/*
You can protect the directory cig-admin so that requests for access to it will
require a user ID and password. For a simple setup, where the Web server
administrator and the CICS Gateway administrator are the same person, the
cig-admin directory may be protected by replicating and changing the
existing administrators protection in the Web server configuration file:
LotusGo Web Server Windows NT file: WINNT\HTTPD.CNF
Protect /admin-bin/*
Protect /cig-admin/*
PROT-ADMIN
PROT-ADMIN
/* an existing line */
/* inserting line */
file: /etc/httpd.conf
Protect /cig-admin/* {
ServerId
Private_Authorization
AuthType
Basic
GetMask
A11@(*)
PutMask
A11@(*)
PostMask
A11@(*)
Mask
A11@(*)
PasswdFile
/usr/lpp/internet/server_root/Admin/Webadmin.passwd
Windows NT
The CICS gateway runs as a Windows NT service. To start it, open the
Window NT Control Panel application and click on the Services program.
Select IBM CICS Internet Gateway and click on the Start button. If you wish
to start it automatically every time that the machine is started, you have to
select Startup and change Startup Type to Automatic (shown in Figure 101
on page 126).
Chapter 3. Connectors
125
AIX
The CICS gateway has to run as a user in the same primary group as the
Lotus Domino Go Webserver, not just a group set. (A group is a collection of
users than can share access authority to protect resources; a group set
specifies the groups in which the user is a member.)
Make sure that the LANG environment variable is exported to a suitable
value (for example, LANG=en_US) to have messages in the language that
you want.
To start it, enter: /usr/lpp/cig/bin/cigd &. Alternatively, you can add the
following entry to your /etc/inittab file after the Web server and DCE entries:
126
Figure 103. CICS Internet Gateway: Customized Header and Trailer HTMLs
3.1.2.4 Configuration
The CICS Internet Gateway requires the CICS client to send and receive its EPI
requests to a CICS server. The configuration that you set up should consist of a
Web server, CICS Internet Gateway and CICS client connected to the CICS
application servers.
If your CICS server does not support the CICS Client EPI (for example, the CICS
EPI function is available starting with CICS/ESA 4.1 in MVS/ESA or OS/390
operating system), you can bypass this problem with the following configuration:
Chapter 3. Connectors
127
Web server, CICS Internet Gateway, CICS Client and CICS server, on the same
machine as shown in Figure 104 on page 128. The client is connected to the
CICS application using the CICS Inter System Communication (ISC). The EPI
requests are sent from the CICS client to the CICS server installed in the same
system. It will then get routed to the other CICS servers using the CICS
transaction routing function. This requires a remote transaction definition.
Please refer to 3.1.2.5, Security for security considerations.
If the CICS application server does not support a TCP/IP connection with CICS
clients or another CICS server, you have to provide a Systems Network
Architecture (SNA) connection and SNA support on the Web server system.
3.1.2.5 Security
CICS Internet Gateway allows you to use your existing CICS security
environment generally based on an external security manager. An example of
this would be the IBM RACF product. CICS has its own built-in security. It uses
a sign-on table (SNT). The user has to invoke the CICS sign-on transaction
(CESN) at the first request, complete the security procedure and then they can
have access to the authorized CICS resources. If you implemented a CICS
server on the same machine that the CICS Internet Gateway and the CICS client
are installed, you should be aware that the sign-on requests will be processed
by that CICS server. This means that you have to download security profiles
from the CICS application servers and put them on the CICS server that has the
Web server. However, you have to define as remote transactions only the
transactions that you want to be accessed over the Web. The list of transactions
can be a subset of all your applications. In this case, the transactions that are
not defined as remote could not be executed. This could be considered a
security block that can reduce the effort to download all security profiles used in
the CICS application environment.
You may also want to use encryption for passwords and sensitive data. That
service is provided by the SSL function on the Web server.
If you are providing an Internet or extranet solution, you may also want to place
your Web server and CICS Internet Gateway outside your firewall.
128
Minor customization
It is possible to provide an easy way to start new CICS transactions or add
hyperlinks to existing applications with some minor customization. This will
help extend the functions of an application. The way you do this is:
Chapter 3. Connectors
129
In 1 and 2(see Figure 105), you can see that the CICS system name
CICSTCP and the name of the transaction CESN, are hidden and
provided using the value parameter. The user can just click on the
Submit button to start the transaction 3.
130
***************************************************************
* cicssda DDW1IT -- July 1996 Test Internet
***************************************************************
DDW1IT DFHMSD TYPE=&SYSPARM,MODE=INOUT,LANG=COBOL,STORAGE=AUTO, X
DSATTS=(COLOR,HILIGHT),MAPATTS=(COLOR,HILIGHT),
X
TIOAPFX=YES,COLOR=GREEN,HILIGHT=OFF
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
SUR3
DFHMDF POS=(5,44),LENGTH=15,JUSTIFY=(LEFT,ZERO),
ATTRB=(PROT,NORM)
DFHMDF POS=(5,60),LENGTH=1,JUSTIFY=(LEFT,ZERO),
ATTRB=(PROT,NORM)
DFHMDF POS=(6,07),LENGTH=72,JUSTIFY=(LEFT,ZERO),
ATTRB=(PROT,DRK),
INITIAL=<A HREF=http://ntncf120/Stories.html>
Employ Story</a>
X
X
X
DFHMDF POS=(07,20),LENGTH=11,JUSTIFY=(LEFT,ZERO),
ATTRB=(PROT,NORM),INITIAL= First name:
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
DDW1IT DFHMSD TYPE=FINAL
Figure 106. CICS Internet Gateway - HTML Tags Added on CICS Map
Single transaction
A single transaction can provide the function that is required. An
example of this is if you have an inquiry or an order entry transaction
where the user has to insert a CICS transaction code and the data.
When it ends, the browse session could terminate. Another situation
where you can apply this solution is when a CICS application issues an
EXEC CICS RETURN without specifying the next transaction code. This
would always occur with pseudo-conversational transactions.
It is very simple to provide a multimedia menu that can start the
transaction directly without knowing every CICS transaction code and
how to complete the transactions. Using a Web browser lets you
potentially have one click of the mouse to get a result.
You can provide this service by setting the AutoExit parameter to ON and
setting the ExitPage parameter to permit the user to navigate between
CICS transactions without knowing transaction codes. In the screen
below we show the HTML form used to test the AutoExit parameter. The
results are shown in Figure 107 on page 132 and Figure 108 on
page 132. Clicking on the Please click here to continue link will retrieve
the default ExitPage shown in Figure 109 on page 132.
<p>
Chapter 3. Connectors
131
Figure 107. CICS Internet Gateway: Click on to Start Your CICS Transaction
132
Java classes
They run on the users computer and support ECI and EPI requests from a
local Java applet or application and they are dynamically downloaded at the
users request.
The gateway Java classes are:
GatewayRequest - Is the root class that all the different types of gateway
requests are built from. A user program cant create a GatewayRequest
object.
The first three classes are used to establish communication with the long
running gateway process using Javas socket protocol. ECIRequest and
EPIRequest are used to specify the CICS ECI and EPI calls that are sent to
the gateway.
Gateway
The CICS Gateway for Java is a long running process that must reside on
the same processor as the Web server (a Java security feature) and
supports multiple concurrent ECI or EPI requests from the Java client. The
gateway channels ECI and EPI calls through a CICS client to selected CICS
server applications. It is able to manage many communication links to the
connected browsers or network computers and controls asynchronous
conversations to the CICS server systems.
The gateway can communicate with CICS servers either on the same
processor or across a TCP/IP or SNA communication link provided by the
CICS client.
Since the CICS gateway is written in the Java programming language it can run
on any server platform that is Java-enabled and that supports the CICS client
interface. It is available on AIX, Windows NT, OS/2 and Sun Solaris and it will
soon be available on the S/390 platform.
Chapter 3. Connectors
133
3.1.3.1 Installation
Before you download the IBM CICS Gateway for Java you have to check if your
environment has the minimum level of Java Development Toolkit (JDK) installed:
When you download CICS Gateway for Java, you obtain a compressed file that
will be a zip file for OS/2 and NT or a tar file for AIX and Solaris. You can place
this file anywhere, but all of the documentation refers to the JGATE directory as
134
being the root directory. When you expand it you will get a directory structure
similar to the one in Figure 111 on page 135.
In the JGATE directory you will find a readme.txt file where you will find the
following important information:
Note: Unfortunately, a restriction has been discovered with the CICS client,
which effects the CICS Gateway for Java. In order to run concurrent ECI
and EPI requests via the CICS Gateway for Java you will need to open
two CICS gateways listening on different TCP/IP ports. You should then
make all ECI requests via one CICS gateway and all EPI requests via the
other CICS gateway. To specify the CICS gateway port use the -port
command line option as described in the product documentation. This
restriction applies on all supported platforms.
All documentation is provided in HTML form and includes:
135
Web Server
Pass
/jgate/*
e:\jgate\*
Setting
Classpath
c:\set classpath
CLASSPATH=c:\jdk1.1.3\lib\classes.zip;e:\jgate;e:\jgate\classes;
Figure 112. CICS Gateway for Java: Start with the Default Options
136
Figure 113. CICS Gateway for Java: Start with the User Options
Figure 114. CICS Gateway for Java: Get Help on the Startup Options
You can store your start command in a file and associate it with an icon or
shortcut to avoid typing it in often, as shown in Figure 115 on page 138.
Chapter 3. Connectors
137
Figure 115. CICS Gateway for Java: Start Command Using an Icon
To stop your CICS Gateway for Java you have to select its console session. Then
type Q and press Enter. This is possible if you have started the gateway with the
default option or if you did not select the -noinput option. If you selected the
-noinput option, this disables the CICS Gateway for Java application from
reading any input from the console. You have to choose another method. For
example:
138
To test your entire environment, including CICS client and CICS server
components, you have to select Read the CICS Gateway for Java Programming
Guide from jgate/html/doc/index.html. This section explains how to write a Java
applet that includes the gateway classes and two sample programs: TestECI and
TestEPI.
TestECI is a sample program that allows you to test the functions of the CICS
Gateway for Java by sending one or more ECI requests to a CICS server. Be
aware that TestECI does not pass the CICS COMMAREA to the called program,
so you have to modify it to display the COMMAREA data in output report. The
source for TestECI is provided in the directory jgate/java/ibm/cics/jgate/test.
To run the sample you can use your Java-enabled browser or start it as an
application. The parameters that you need to pass to the TestECI program
Chapter 3. Connectors
139
depends on how you plan to implement it. The parameters that you can set for
the program are shown in the screen below:
<applet code=TestECI
<param name=jgate
<param name=jgateport
<param name=server
<param name=userid
<param name=password
<param name=prog0..9
<param name=status
<param name=trace
</applet>
You can see the output of EciTest run as an application and the parameters used
in Figure 117. The same process that was run in a browser session is shown in
Figure 118 on page 141 with the HTML page source in Figure 119 on page 142.
Figure 117. CICS Gateway for Java: TestECI Program Running As an Application
140
Figure 118. CICS Gateway for Java: TestECI Program Running in a Browser
Chapter 3. Connectors
141
Figure 119. CICS Gateway for Java: HTML Used to Run TestECI Program
TestEPI is a sample that allows you to test one or more EPI requests with a CICS
server. The source of TestEPI and the classes that it invokes, RequestDetails
and EPIStrings, are available in the jgate/java/ibm/cics/jgate/test directory where
you can also find the sample HTML page, testepi.html.
You can run TestEPI from your browser or from an appletviewer using the same
testepi.html file. It presents a panel where you have to provide some
information:
Java Gateway Name - The TCP/IP address or the host name where your
CICS Gateway for Java runs.
Java Gateway Port - TestEPI starts port 2006 (the default port used by the
gateway). You can override this default with the port that you have defined.
If it is wrong, you will receive the following error message when you try to
connect:
142
CICS Server Name - If it is not provided, the default CICS server that is
defined in the CICSCLI.INI configuration file will be used. If it is provided,
this must be a CICS server that your CICS client can connect to.
After you have provided all the input fields you can select one of the two
following options:
When you click the Execute EPI request button, the TestEPI program will start a
new thread that will show you the results of any actions that the program made.
You can see the an example of TestEPI using the appletviewer command
appletviewer testepi.html in Figure 120.
Figure 120. CICS Gateway for Java: TestEPI Program Running in an Appletviewer
Chapter 3. Connectors
143
The program then sends the request to the CICS Gateway for Java using the
flow method of the Java object. 3
The Java program checks the return code of the flow operation to verify if
the request was successful. 4
The Java program closes the JavaGateway object using the close method of
JavaGateway class. 5
/************************************************************************/
/*
*/
/* STATEMENT
Licensed Materials - Property of IBM
*/
/*
(C) Copyright IBM Corporation 1996
*/
/*
See Copyright instructions.
*/
/*
All rights reserved.
*/
/*
U.S. Government Users Restricted Rights - use, */
/*
duplication or disclosure restricted by GSA
*/
/*
ADP Schedule Contract with IBM Corp.
*/
/*
*/
/*
NOTICE TO USERS OF THE SOURCE CODE EXAMPLES
*/
/*
*/
/* AUTHOR
Andrew R. Dean
*/
/* STATUS
Version 1.0
*/
/* NOTES
This is a general sample to demonstrate the basic */
/*
functions of the CICS Gateway for Java
*/
/*
*/
/************************************************************************/
package ibm.cics.jgate.test;
import ibm.cics.jgate.client.*;
import
import
import
import
java.net.*;
java.io.*;
java.awt.*;
java.applet.*;
/*
* Create a new JavaGateway to use
*/
Figure 121 (Part 1 of 3). CICS Gateway for Java: TestECI Java Source Sample
144
2
eciRequest =
new ECIRequest(strServerName, // CICS Server
strUserId,
// UserId, null for none
strPassword, // Password, null for none
null,
// Program name
null,
// Commarea, null for none
ECIRequest.ECI_NO_EXTEND,
ECIRequest.ECI_LUW_NEW);
for (int iCallLoop = 0; iCallLoop < iNoOfProgNames;
iCallLoop++)
{
eciRequest.Cics_Rc = 0;
/*
* Set the program name in the eciRequest
*/
eciRequest.Program = astrProgNames[iCallLoop];
/*
* Set ECI_NO_EXTEND on the last call only, otherwise
* set ECI_EXTENDED
*/
eciRequest.Extend_Mode =
(iCallLoop == (iNoOfProgNames - 1)) ?
ECIRequest.ECI_NO_EXTEND :
ECIRequest.ECI_EXTENDED;
/*
* Flow the request via the JGate to CICS
*/
displayMsg(About to call : + eciRequest.Program);
displayMsg( Extend_Mode : + eciRequest.Extend_Mode);
displayMsg( Luw_Token : + eciRequest.Luw_Token);
3
jgaConnection.flow(eciRequest);
displayMsg(Return code
displayMsg(Abend code
: + eciRequest.Cics_Rc);
: + eciRequest.Abend_Code);
}
}
}
Figure 121 (Part 2 of 3). CICS Gateway for Java: TestECI Java Source Sample
finally
{
try
{
if (jgaConnection != null)
{
jgaConnection.close();
displayMsg(Successfully closed JavaGateway ) ;
}
}
catch (IOException eClose)
{
displayMsg(Exception during close : + eClose);
}
5
}
}
Figure 121 (Part 3 of 3). CICS Gateway for Java: TestECI Java Source Sample
To integrate a 3270 CICS existing application we have to use an EPI call and the
Java applet acts like a terminal to CICS. This requires you to be aware of the
Chapter 3. Connectors
145
3270 data streams that may flow from CICS and the 3270 data streams that the
CICS application expects to receive. It also important to be aware of the rules
that govern native CICS client EPI programming and the differences that exist
when you invoke a CICS transaction on different platforms. When getting events
from CICS it is recommended that you use the EPI_WAIT option, and ensure that
the EPIRequest objects field size is set to the maximum size of the 3270 data
stream that CICS may return.
An EPI program written using the CICS Gateway for Java generally follows the
steps outlined in Figure 122 on page 147. The steps are:
1. Open a connection to the gateway. 1
2. Add a terminal. 2
3. Start a transaction. 3
4. Get events until either the event received is an end transaction, a converse,
or a severe error. 4
5. If the event received is a converse, then send the reply and return to the get
event loop. 5
6. If the event received is an end transaction, delete the terminal and one more
get event to obtain the end terminal event. 6
7. Close the connection to the gateway. 7
146
/************************************************************************/
/*
*/
/* STATEMENT
Licensed Materials - Property of IBM
*/
/*
(C) Copyright IBM Corporation 1996
*/
/*
See Copyright instructions.
*/
/*
All rights reserved.
*/
/*
U.S. Government Users Restricted Rights - use, */
/*
duplication or disclosure restricted by GSA
*/
/*
ADP Schedule Contract with IBM Corp.
*/
/*
*/
/*
NOTICE TO USERS OF THE SOURCE CODE EXAMPLES
*/
/*
*/
/* AUTHOR
Emma Eldergill
*/
/* STATUS
Version 1.1.1
*/
/* NOTES
This is a general sample to demonstrate the EPI */
/*
class of the CICS Gateway for Java
*/
/*
*/
/************************************************************************/
package ibm.cics.jgate.test;
import ibm.cics.jgate.client.*;
import
import
import
import
import
java.net.*;
java.io.IOException;
java.awt.*;
java.util.Vector;
java.applet.*;
Figure 122 (Part 1 of 7). CICS Gateway for Java: TestEPI Java Source Sample
Chapter 3. Connectors
147
/*
* Flow the addTerminal request
*/
jgaTest.flow(epiReq);
strRC = EPIStrings.getStringRC(epiReq.Cics_Rc);
strMessage = strStatus + Thread.currentThread().getName() +
: addTerminal() RC = + strRC + , termIndex =
+ epiReq.termIndex + \n ;
displayMsg(strMessage);
/*
* If RC = OK
*
Flow the startTran request
*/
3
if (epiReq.Cics_Rc == EPIRequest.EPI_NORMAL)
{
epiReq.startTran(strTransid,abytData,iSize);
jgaTest.flow(epiReq);
strRC = EPIStrings.getStringRC(epiReq.Cics_Rc);
strMessage = strStatus + Thread.currentThread().getName() +
: startTran() RC = + strRC + , termIndex =
+ epiReq.termIndex + \n ;
displayMsg(strMessage);
}
else
{
bLoop
= false;
bDelTerm = false;
}
/*
* Note: the startTran() Cics_Rc may be EPI_NORMAL but the transid
* not recognised, therefore it may be necessary to scan the next
* getEvent() data to see whether
* it says that the transaction id was not recognized.
*/
/*
* Create loop getting events until get to END_TRAN event
* CECI is a conversational task on OS/2.
*/
while (bLoop)
{
if ( epiReq.Cics_Rc
|| epiReq.Cics_Rc
|| epiReq.Cics_Rc
|| epiReq.Cics_Rc
{
==
==
==
==
EPIRequest.EPI_NORMAL
EPIRequest.EPI_ERR_MORE_DATA
EPIRequest.EPI_ERR_MORE_EVENTS
EPIRequest.EPI_ERR_NO_EVENT)
Figure 122 (Part 2 of 7). CICS Gateway for Java: TestEPI Java Source Sample
148
4
getNextEvent(jgaTest,epiReq);
if (epiReq.event == EPIRequest.EPI_EVENT_END_TRAN)
{
bLoop = false;
if (epiReq.Transid != null)
{
if ( ! (epiReq.Transid.equals(
)) )
{
strMessage = strStatus
+ Thread.currentThread().getName()
+ : Pseudoconversation, next Transid =
+ epiReq.Transid + \n ;
displayMsg(strMessage);
}
}
}
else if (epiReq.event == EPIRequest.EPI_EVENT_CONVERSE)
{
replyFlow(jgaTest,epiReq);
}
}
else
{
bLoop = false;
}
5
}
}
catch (IOException exIO)
{
strMessage = strStatus + Thread.currentThread().getName() +
: Error: IOException\n ;
displayMsg(strMessage);
strMessage = strStatus + Thread.currentThread().getName() +
: Error details: + exIO.getMessage() + \n ;
displayMsg(strMessage);
}
finally
{
/*
* If we are not in the middle of a transaction then we can delete
* the terminal.
* Flow the delTerminal request
* Close the connection
*/
Figure 122 (Part 3 of 7). CICS Gateway for Java: TestEPI Java Source Sample
Chapter 3. Connectors
149
try
{
if (jgaTest != null)
{
if (bDelTerm)
{
strMessage = strStatus + Thread.currentThread().getName() +
: about to delete Terminal \n ;
displayMsg(strMessage);
6
epiReq.delTerminal();
jgaTest.flow(epiReq);
strRC = EPIStrings.getStringRC(epiReq.Cics_Rc);
strMessage = strStatus + Thread.currentThread().getName() +
: delTerminal() RC = + strRC + \n ;
displayMsg(strMessage);
/*
* Get the EPI_EVENT_END_TERM event or the termIndex
* value will keep incrementing
*/
getNextEvent(jgaTest,epiReq);
if (epiReq.event == EPIRequest.EPI_EVENT_END_TERM)
{
strMessage = strStatus + Thread.currentThread().getName()
+ : received END_TERM event\n ;
displayMsg(strMessage);
}
else
{
strMessage = strStatus + Thread.currentThread().getName()
+ : Error, did not receive END_TERM event\n ;
displayMsg(strMessage);
epiReq.Cics_Rc = 99;
}
if (epiReq.Cics_Rc == 0)
{
bOK = true;
}
}
Figure 122 (Part 4 of 7). CICS Gateway for Java: TestEPI Java Source Sample
150
7
jgaTest.close();
strMessage = strStatus + Thread.currentThread().getName() +
: closed JavaGateway connection\n ;
displayMsg(strMessage);
}
}
catch (IOException exIO)
{
strMessage = strStatus + Thread.currentThread().getName() +
: Error during cleanup: IOException\n ;
displayMsg(strMessage);
strMessage = strStatus + Thread.currentThread().getName() +
: Error during cleanup details: + exIO.getMessage() + \n ;
displayMsg(strMessage);
}
}
return bOK;
}
/*-----------------------------------------------------------------/*
Method : getNextEvent
/** Invoke EPIRequest s getEvent method, and flow() this request
*/---------------------------------------------------------------public void getNextEvent(JavaGateway jgaTest, EPIRequest epiRequest)
throws IOException
{
String strMessage;
String strRC;
String strEvent;
int iWaitState = EPIRequest.EPI_WAIT;
int iSize
= 2000;
try
{
epiRequest.getEvent(iWaitState,iSize);
jgaTest.flow(epiRequest);
/*
* If the event is a SEND or CONVERSE
*
then there may be data with it
*
(check the size to see there is)
*/
if ( epiRequest.event == EPIRequest.EPI_EVENT_SEND
|| epiRequest.event == EPIRequest.EPI_EVENT_CONVERSE )
{
Figure 122 (Part 5 of 7). CICS Gateway for Java: TestEPI Java Source Sample
Chapter 3. Connectors
151
strRC
= EPIStrings.getStringRC(epiRequest.Cics_Rc);
strEvent = EPIStrings.getStringEvent(epiRequest.event);
strMessage = strStatus + Thread.currentThread().getName() +
: getEvent() RC = + strRC + , event = + strEvent +
, size of datastream returned = + epiRequest.size + \n ;
displayMsg(strMessage);
GatewayTrace.hexDump(epiRequest.data, datastream array ) ;
}
else
{
strRC
= EPIStrings.getStringRC(epiRequest.Cics_Rc);
strEvent = EPIStrings.getStringEvent(epiRequest.event);
strMessage = strStatus + Thread.currentThread().getName() +
: getEvent() RC = + strRC + , event = + strEvent + \n ;
displayMsg(strMessage);
}
}
catch (IOException exIO)
{
throw exIO;
}
}
//------------------------------------------------------------------------/*
Method : replyFlow
/** Invoke EPIRequest s sendReply method, and flow() this request
*///----------------------------------------------------------------------public void replyFlow(JavaGateway jgaTest, EPIRequest epiRequest)
throws IOException
{
String strMessage;
String strRC;
/* byte array for 3270 data stream (in ASCII) */
byte[] abytData = new byte[3];
int iSize
= 3;
Figure 122 (Part 6 of 7). CICS Gateway for Java: TestEPI Java Source Sample
152
/*
* Flow the sendReply (to exit the task)
*/
try
{
epiRequest.sendReply(abytData,iSize);
jgaTest.flow(epiRequest);
strRC = EPIStrings.getStringRC(epiRequest.Cics_Rc);
strMessage = strStatus + Thread.currentThread().getName() +
: sendReply() RC = + strRC + , termIndex =
+ epiRequest.termIndex + \n ;
displayMsg(strMessage);
}
catch (IOException exIO)
{
throw exIO;
}
}
Figure 122 (Part 7 of 7). CICS Gateway for Java: TestEPI Java Source Sample
153
This is discussed further in 3.1.2, CICS Internet Gateway on page 116. The
CICS Gateway for Java offers scalable solutions. It is possible to use multiple
gateways as a front-end to single or multiple application servers as shown in
Figure 123 on page 154.
The Java architecture guarantees the portability of applets across all platforms
and browsers that support Java. This also applies to the CICS Java classes.
CICS Gateway for Java requires you to develop applets that will manage the
presentation logic and will make ECI and EPI calls to the existing applications.
Java offers powerful GUI support and application development tools. VisualAge
for Java includes support to CICS Java classes.
Figure 123. CICS Gateway for Java: Scalability and Access to Multiple Systems
154
The MQSeries Internet Gateway can be installed on systems that are running
MVS, AIX, OS/400, Sun Solaris, OS/2 or Windows NT, and support the CGI, ICAPI
and NSAPI Web server interfaces.
For more information about MQSeries architecture, products and solutions you
can go to http://www.hursley.ibm.com/mqseries. Figure 124 shows a typical
MQSeries Internet scenario.
Windows NT
1. Shut down the Web server that you want to use with the MQSeries
Internet Gateway.
2. Unpack the mqignt.zip file that you have downloaded. This will create a
directory called mqignt, which contains the files needed to install the
gateway code.
3. Run the setup.exe program in the mqignt directory. A set of panels will
guide you through the installation procedures. At the end the MQSeries
Internet Gateway is installed into the dmqgate directory.
AIX
1. Shut down your Web server before starting the installation procedure
using the command: stopsrc -s httpd.
2. Unpack the mqigaix.tar file that you have downloaded using: tar -xvf
mqigaix.tar. The result will be a dmqgate100.img file extracted into the
current directory.
3. To install the gateway files on your Web machine you have to use the
smitty command.
Chapter 3. Connectors
155
Log in as root.
Run smitty.
Accept the default options and press Enter to start the installation.
4. To enable the Web server to access MQ resources, its user name must
be included in the mqm group. You can use a name that already exists
in your mqm group or you can create a new one dedicated to your Web
server and add it to the group. You have to stop and start your queue
manager using that user.
At this point you have to configure your Web server. This procedure depends
upon which Web server you are using. We show you how to configure a Lotus
Domino Go Webserver product. You can find the same type of information for
Netscape and Microsoft Internet Information Server in the user s guide in:
file:/// [ dmqgate disk ] /dmqgate/doc/index.htm
LotusGo Webserver Windows NT
Exec
Pass
/dmq-bin/*
/dmq/*
file: WINNT\HTTPD.CNF
c:\dmqgate\bin\*
c:\dmqgate\doc\*
The above entries must be placed before the generic Pass directive
below, which already exist in the file.
Pass
/*
LotusGo Webserver
c:\www\html\*
Exec
Pass
AIX
/dmq-bin/*
/doc/*
file:
/etc/httpd.conf
/usr/lpp/dmqgate/bin/*
/usr/lpp/dmqgate/doc/*
Where prime is the name of your locale. The above entries must be
placed before the generic Pass directive below, which already exist
in the file.
Pass
/*
/usr/lpp/internet/server_root/pub/*
Now you can restart your Web server.
156
29H1019,5697-177 (C) Copyright IBM Corp. 1994, 1995. ALL RIGHTS RESERVED.
Starting MQSeries Commands.
: ********************************************************************/
: *
*/
: * Program name: DMQSAMP.TST
*/
: *
*/
: ********************************************************************/
:
1 :
DEFINE QLOCAL( DMQGATEWAY ) REPLACE +
:
DESCR( Gateway Queue )
AMQ8006: MQSeries queue created.
:
2 :
DEFINE QLOCAL( DMQSAMP1 ) REPLACE +
:
DESCR( Queue for sample Serving Application 1 - wrap )
AMQ8006: MQSeries queue created.
:
: ********************************************************************/
: *
*/
: * END OF DMQSAMP.TST
*/
: *
*/
: ********************************************************************/
2 MQSC commands read.
0 commands have a syntax error.
0 commands cannot be processed.
Figure 125. MQSeries Internet Gateway: Defining MQ Resources for the Sample
Now you are ready to test your environment. Start the Web browser and:
There is a sample written for the CGI, ICAPI and NSAPI Web server interface.
The sample lets you fill in a form that will be sent to the MQSeries queue
DMQSAMP1. That is read by a back-end program DMQSAMP1. You can find the
back-end program in the c:\dmqgate\samples directory. To start it you have to
enter the following command:
Chapter 3. Connectors
157
The back-end program reads data coming from the Web and writes a response
to a reply queue using MQSeries API calls. The message sent back to the
browser contains all of the HTTP parameters and data used in this sample. This
is shown in Figure 127 on page 159, Figure 128 on page 160 and Figure 129 on
page 161.
158
Chapter 3. Connectors
159
160
Chapter 3. Connectors
161
Figure 130. MQ Internet Gateway: DQSAMP1 Process Output Form without Context
162
Chapter 3. Connectors
163
164
MQIGwQueue - Is the queue name where the Internet Gateway writes the
messages using the MQI MQPUT call.
MQIGwWaitInterval - Is the time that the Internet Gateway should wait for a
reply.
MQIGwIniFile - Is the name of the INI file used to hold the parameter s
values.
MQIGwReplayQueue = DMQGATEWAY
MQIGwContext = All
The MQSeries Internet Gateway searches the values using the following order:
1. HTML form
2. Configuration file defined using the MQIGwIniFile keyword
3. dmq.ini file
Only one keyword can be set for the values listed above. To avoid unpredictable
results, only set one of the values.
<HEAD>
<TITLE>NCF MQSeries Internet Gateway CGI Sample</TITLE>
</HEAD>
<HR>
<H3>Sample Form</H3>
<P>Click on <b>Submit</b> to run the CGI sample.</P>
<center><h3>Example Survey of Internet Browsers</h3></center>
<FORM ACTION= / dmq-bin/dmqcgi METHOD=POST>
<INPUT NAME=MQIGwQueue TYPE=hidden VALUE=DMQSAMP1>
<INPUT NAME=MQIGwWaitInterval TYPE=hidden VALUE=10000>
<INPUT NAME=MQIGwIniFile TYPE=hidden value=ncfdmq.ini>
<INPUT NAME=MQIGwWaitInterval TYPE=hidden value=ncftime.htm>
</FORM>
</BODY>
</HTML>
Figure 133. MQ Internet Gateway: Sample Form with Provided Keywords
When the keyword MQIGwWaitInterval is set, you have to provide a reply retry
form that will be displayed when the wait interval expires. If you dont supply
your own form, the sample timedout.htm form will be used. It is stored in the
[ dmqgatedisk ] /dmqgate/bin directory. If you write your own reply form, you can
use any style but you must include the following FORM tag:
Chapter 3. Connectors
165
<FORM
The ACTION attribute on the FORM tag to match the Web server interface
that you are using as shown in the following table.
ACTION
CGI
/dmq-bin/dmqcgi
ICAPI
/dmq-bin/dmqicapi
NSAPI
/dmq-bin/dmqnsapi
ISAPI
/dmq-bin/dmqisapi
Figure 134 shows the result of a customized reply retry form and Figure 135 on
page 167 shows the source used:
166
<HTML>
<HEAD>
<TITLE>MQSeries Internet Gateway Status</TITLE>
</HEAD>
<body bgcolor=#ffffff background= / doc/dmqdg08.gif>
<!-- beginning of message area -->
<table>
<tr><th>
<td>
<h1>SunShine</h1>
</td>
<td>
<img src= / cig/smile.gif alt=Smile>
</td>
<td>
<h1>NCF Enterprise</h1>
</td>
</table>
<HR ALIGN=center SIZE=4>
<p>This is a sample timed-out form that is sent if the Wait Interval has
been exceeded.
<P>To check if your reply is available press <b>Retry</b>
(and wait again).
<center>
<!-- end of message area -->
<FORM ACTION= / dmq-bin/dmqcgi METHOD=POST>
<i><INPUT TYPE=submit NAME=dmqretry VALUE= Retry ></i>
</FORM>
</center>
<!-- beginning of footage area -->
<hr>
<p>
<h3>
<p>We are terrible sorry that this was happen. If you wish send a claim,
please click on SunShine General Manager Mail link.
</h3>
<center>
<img src= . . / dmq/shark.gif alt=Shark>
<hr>
<B><A HREF= . . / dmq/ncfcgi1.htm>Back to the input form</A></B>
<B><A HREF= . . / dmq/ncfboss.htm>SunShine General Manager</A>
</B>
<!-- end of footer area -->
</BODY>
</HTML>
Figure 135. MQ Internet Gateway: Customized Reply Retry Form Source File
Chapter 3. Connectors
167
queue is defined as local. This network computing solution can take advantage
of MQSeries-specific functions such as:
Message priority - Messages are processed in fifo order into the same
message priority. The priority can be set by the application.
As you can see when you run the DMQSAMP1 sample, as shown in Figure 127
on page 159 through Figure 129 on page 161, the MQ message coming from the
HTML pages can include all the HTML form input data and user data or only the
user data as shown in Figure 130 on page 162. This depends upon the
MQIGwContext keyword value. However, the application has to provide the
response in a special format to let the MQSeries Internet Gateway repackage it
into an HTML file and to send it to the Web browser for display. The application
program that will get the message and send back the answer is described as
Web-aware.
Web-aware MQ applications do not use any new or specific MQ calls, but they
need to be written in a specific manner. You can refer to the source of
DMQSAMP1 program in the dmqgate\samples directory to see the format of data
that the MQSeries Internet Gateway uses to write the message and the format
that the Web-aware application uses to build the return message. Figure 136 on
page 169 shows the three parts of the DMQSAMP1 program:
ParseString is used to parse the incoming data from the MQSeries Internet
Gateway.
168
URLDecode is used to remove + symbols with spaces and convert the next
two characters following the % symbol.
/**************************************************************************/
/*
*/
/* Local function definitions
*/
/*
*/
/**************************************************************************/
void ReturnMsgData( MQHCONN Hconn, char *pBuffer,
MQLONG BufferLength );
void GetMsgData( MQHCONN Hconn, char *pBuffer,
PMQLONG pBufferLength );
void BuildHTTP( char *pHTTPBuffer );
void ParseString( char *pString );
char *GetValue( char *pName );
int URLDecode(char *string_to_decode);
BuildHTTP( mBuffer);
/**************************************************************************/
/*
*/
/* BuildHTTP
*/
/* Convert response data to HTML(Hypertext Markup Language) format so
*/
/* it can be displayed on a Web browser.
*/
/* This function creates a table of name values pairs.
*/
/*
*/
/**************************************************************************/
void BuildHTTP( char *pHTTPBuffer )
{
int i=0;
/*
* specify that the
*/
strcpy(pHTTPBuffer,
strcat(pHTTPBuffer,
strcat(pHTTPBuffer,
strcat(pHTTPBuffer,
strcat(pHTTPBuffer,
strcat(pHTTPBuffer,
strcat(pHTTPBuffer,
strcat(pHTTPBuffer,
strcat(pHTTPBuffer,
strcat(pHTTPBuffer,
Figure 136 (Part 1 of 4). MQ Internet Gateway: DMQSAMP1 BuildHTTP and ParseString
Routines
Chapter 3. Connectors
169
/*
* specify table format and headings
*/
strcat(pHTTPBuffer, <TABLE BORDER=1 CELLPADDING=4>\n ) ;
strcat(pHTTPBuffer, <TR> ) ;
strcat(pHTTPBuffer, <TD ALIGN=CENTER><FONT COLOR=RED> ) ;
strcat(pHTTPBuffer, Variable</FONT></TD> ) ;
strcat(pHTTPBuffer, <TD ALIGN=CENTER><FONT COLOR=RED> ) ;
strcat(pHTTPBuffer, Value</FONT></TD></TR>\n ) ;
/*
* add each name value pair to the table
*/
for (i=0;i<VarCount;i++ )
{
strcat(pHTTPBuffer, <TR><TD ALIGN=right><B> ) ;
strcat(pHTTPBuffer, pVar[i][NAME]);
strcat(pHTTPBuffer, < / B></TD><TD> ) ;
if ( strlen(pVar[i][VALUE]) > 0)
{
strcat(pHTTPBuffer, pVar[i][VALUE]);
}
else
{
strcat(pHTTPBuffer, <I>none</I> ) ;
}
strcat(pHTTPBuffer, < / TD></TR>\n ) ;
}
/*
* end the table and document
*/
strcat(pHTTPBuffer,
strcat(pHTTPBuffer,
strcat(pHTTPBuffer,
strcat(pHTTPBuffer,
< / TABLE>\n ) ;
< / CENTER> ) ;
< / body>\n ) ;
< / html>\n ) ;
Figure 136 (Part 2 of 4). MQ Internet Gateway: DMQSAMP1 BuildHTTP and ParseString
Routines
170
/**************************************************************************/
/*
*/
/* ParseString
*/
/* Data from the Web consists of a series of names and their respective
*/
/* values. Name value pairs are separated by the & character and
*/
/* a name is separated from a value by the = character.
*/
/* This function parses request data by replacing = and &
*/
/* characters by a null terminator.
*/
/* This function also calls function URLdecode which decodes each name
*/
/* and value. The decoded name value pairs are then printed.
*/
/*
*/
/**************************************************************************/
void ParseString( char *pString )
{
int i;
char *p;
i=strlen(pString);
pVar[VarCount][NAME] = pString;
printf( Parsing request data...\n ) ;
for (p=pString; i ;p++,i-- )
{
if ( *p == & )
{
*p = \0 ;
pVar[VarCount][NAME] = p+1;
}
else if ( *p == = )
{
*p = \0 ;
pVar[VarCount][VALUE] = p+1;
VarCount++;
}
}
for (i=0;i<VarCount;i++ )
{
URLDecode( pVar[i][NAME] );
URLDecode( pVar[i][VALUE] );
printf( \tName <%s> Value<%s>\n ,
pVar[i][NAME],
pVar[i][VALUE]) ;
}
}
Figure 136 (Part 3 of 4). MQ Internet Gateway: DMQSAMP1 BuildHTTP and ParseString
Routines
Chapter 3. Connectors
171
/**************************************************************************/
/* URLDecode
*/
/* Each name and value are decoded by replacing plus signs with spaces
*/
/* and then replacing characters that were encoded as a per cent sign
*/
/* followed by a hexadecimal number by the actual characters.
*/
/**************************************************************************/
int URLDecode(char *string_to_decode)
{
char c1, c2;
/* holders for hex digits of escape sequence */
int len;
/* length of original string */
int j;
/* index for reading from encoded string */
int k;
/* index for writing to decoded string */
len=strlen(string_to_decode);
/*
Run down the length of the encoded string, examining each
character. If it s a +, we write a space to the decoded string.
If it s a %, we discard it, read in the next two characters,
convert their hex value to a char, and write that. Anything
else, we just copy over.
*/
for (j=0, k=0;j<len;j++, k++) {
switch(string_to_decode[j]) {
case + :
string_to_decode[k]= ;
break;
case % :
c1=tolower(string_to_decode[++j]);
if (isdigit(c1)) {
c1-= 0 ;
} else {
c1=c1- a+10;
}
c2=tolower(string_to_decode[++j]);
if (isdigit(c2)) {
c2-= 0 ;
} else {
c2=c2- a+10;
}
string_to_decode[k]=c1*16+c2;
break;
default:
string_to_decode[k]=string_to_decode[j];
break;
}
}
string_to_decode[k]= \0 ;
return(k);
}
Figure 136 (Part 4 of 4). MQ Internet Gateway: DMQSAMP1 BuildHTTP and ParseString
Routines
You can provide one or more Web-aware applications that can receive the
message from the MQ Internet Gateway. It processes the messages and sends
them to one or more MQSeries application across the MQSeries network as
shown in Figure 137 on page 173. MQI correlates each request message with
the relative response message using the message identifier (msgid) and/or the
correlation identifier (correlid). In this way you can provide a strong integration
with all existing MQSeries applications with the Web and you can split a single
request and re-join the responses. Another useful way to use msgid and
correlid is to split the Web-aware application into two programs:
One receives data from the Web and sends it to the non-Web-aware
application.
The other receives the response from the non-aware application and
repackages it into an HTML file.
In this way you do not have to wait to complete a single request/response loop
before processing the subsequent incoming request.
172
Application developers can create applets and applications that can run on any
platform that supports the Java run-time environment. They can provide
presentation and business logic that can use MQSeries MQI to exchange data
and process with the existing applications across the Web. This solution lets you
Chapter 3. Connectors
173
write an application once and run it anywhere. It reduces the development time
for multiplatform applications and the cost of distributing and maintaining
software.
readme.txt
You need to copy the mqc4jdoc.zip file into a directory and unzip it to have all
the documentation you need for this task. Then you can proceed with the type of
installation that you want to implement:
Pass
/mqjava/*
c:\mqjava\*
After it is installed you can verify your installation by using an applet called
mqjavac.html that can run from a Web browser or with an appletviewer.
We assume that you are working on the Web system where you have installed
MQSeries Client for Java, MQSeries queue manager and the Web server.
Considerations about which queue manager the MQSeries Client for Java can
connect to are discussed in 3.1.5.2, How to Use MQSeries Client for Java on
page 178.
In order to verify your installation you have to provide a channel definition in
your MQSeries environment:
1. Start your queue manager with the strmqm command.
2. Type runmqsc to start the runmqsc program.
3. Define a sample channel called JAVA.CHANNEL by typing:
174
MQSeries
1414/tcp
2. Edit the file /etc/inetd.conf. If you do not have the following line in that file,
add it as shown:
Chapter 3. Connectors
175
Figure 138. MQ Client for Java: Web Browser Running the Verification Program
176
Figure 139. MQ Client for Java: Appletviewer Running the Verification Program
You can use this installation verification applet to allow your users to verify their
access to your queue manager. mqjavac.html includes a set of optional
parameters that allow you to modify the applet to suit your specific
Chapter 3. Connectors
177
requirements. You need to remove the ! from the parameters since that makes
it a comment line, and insert your values. In addition to the parameters that you
used during the installation verification test, you also have:
trace - The client will write a trace log. The value could be 1 to 5, and the
trace will be written on the Java console. In Figure 140 you can see part of
a trace activated with trace=1.
Figure 140. MQ Client for Java: Trace Written into the Java Console
178
using Microsoft Internet Explorer, the Java applet can connect only to the MQ
queue manager present on the local host.
The following table summarizes the MQ queue manager locations that can be
accessed from each environment.
Table 3. Accessible MQ Queue Manager Locations
Installation Location
Browser
Local Disk
Web Server
Netscape Navigator
any
Web server
localhost
Web server
appletviewer
any
any
Send/Receive - This means that the applet uses MQPUT to send messages
and MQGET with the wait option to retrieve the response message.
It is possible to insert a queue name. If you dont select one, then a default will
be used as the correlation ID. In this sample, the correlation ID is used to
retrieve a specific message from the queue. This could be useful if you have a
queue that receives messages from many users and needs to correlate the
response messages to each users request.
Chapter 3. Connectors
179
180
Figure 144 on page 182 has a piece of the code from the sample just to show
you how to code MQSeries calls using the MQ Java Client. The full API
documentation is available in the MQSeries Java Programmer s Guide distributed
with the product in HTML format.
The program is divided into three different sections, based upon the action types
reported in Figure 141 on page 180 (send/receive, receive and send). A
description of key components in the program follows:
1. You need to import the MQ classes 1.
2. Set some variables, such as the host name, the MQ channel used and the
name of queue manager 2. We need to use them in the MQEnvironment
3.
3. Before you open the queue you have to set the options such as the ones at
4 for input and output.
4. The name of the queue can be retrieved from the screen or you can use the
default name 5. You can define a different queue name for the send and
receive flows, but not for send/receive itself.
5. To make an MQPUT call we need to set up MQPutMessageOptions and
MQGetMessageOptions 6. For an individual send operation we used the
Chapter 3. Connectors
181
import com.ibm.mq.*;
import DemoMq;
1
2
4
5
}
MQMessage output = new MQMessage();
6
output.writeString( req.chiave.getText() );
MQPutMessageOptions pmo = new MQPutMessageOptions();
if ( (!(req.corrid.getText().equals( ) ) ) )
{
System.out.println(put + req.corrid.getText() );
req.corrid.getText().getBytes( 0,
req.corrid.getText().length(),
output.correlationId,
0 );
}
output.format = MQC.MQFMT_STRING;
local_queue.put( output, pmo );
7
Figure 144 (Part 1 of 3). MQ Client for Java: Example Source Code
182
MQEnvironment.hostname = hostname;
3
MQEnvironment.channel = channel;
System.out.println( new MQQueueManegr\n ) ;
qMgr = new MQQueueManager( qManager );
openOptions = MQC.MQOO_INPUT_AS_Q_DEF + MQC.MQOO_FAIL_IF_QUIESCING; 4
local_queue = qMgr.accessQueue(MQJAVA.LOCAL.CODA1 , 5
openOptions,
null,
null,
null );
MQMessage input = new MQMessage();
MQGetMessageOptions gmo = new MQGetMessageOptions(); 6
}
public void flussoRpc( DemoMq req ) throws MQException, java.io.IOException
{
try
{
int openOptions;
if ( req.start == 0 )
{
MQEnvironment.hostname = hostname;
3
MQEnvironment.channel = channel;
System.out.println( new MQQueueManegr\n ) ;
qMgr = new MQQueueManager( qManager );
openOptions = MQC.MQOO_OUTPUT + MQC.MQOO_FAIL_IF_QUIESCING; 4
if ( req.nomecoda.getText().equals() )
local_queue = qMgr.accessQueue(MQJAVA.LOCAL.CODA3 , 5
openOptions,
null,
null,
null );
openOptions = MQC.MQOO_INPUT_SHARED + MQC.MQOO_FAIL_IF_QUIESCING; 4
reply_local_queue = qMgr.accessQueue(MQJAVA.LOCAL.REPLY ,
5
openOptions,
null,
null,
null );
MQMessage output = new MQMessage();
output.writeString( req.chiave.getText() );
MQPutMessageOptions pmo = new MQPutMessageOptions();
Figure 144 (Part 2 of 3). MQ Client for Java: Example Source Code
Chapter 3. Connectors
183
if ( (!(req.corrid.getText().equals( ) ) ) )
{
System.out.println(put + req.corrid.getText() );
req.corrid.getText().getBytes( 0,
req.corrid.getText().length(),
output.correlationId,
0 );
}
output.messageType = MQC.MQMT_REQUEST;
8
output.format = MQC.MQFMT_STRING ;
7
output.replyToQueueName = new String(MQJAVA.LOCAL.REPLY ) ;
output.report = MQC.MQRO_EXCEPTION_WITH_DATA;
local_queue.put( output, pmo );
MQMessage input = new MQMessage();
MQGetMessageOptions gmo = new MQGetMessageOptions();
6
gmo.options = MQC.MQGMO_WAIT | MQC.MQGMO_ACCEPT_TRUNCATED_MSG;
gmo.waitInterval = 30000;
input.correlationId = output.correlationId; 9
reply_local_queue.get( input, gmo );
String msgText = input.readLine();
req.risultato.setText( msgText );
}
Figure 144 (Part 3 of 3). MQ Client for Java: Example Source Code
184
IBM Communication Server for AIX 4.2 or later (with IBM SNA Client Access
for AIX 1.2 or later)
3.1.6.1 Installation
You can download Host On-Demand from the IBM Web site and install it in the
same system where the Web and IBM Communications server are running. For
Windows NT server, the Host On-Demand is also packaged with the IBM
Communications Server for NT V5, as shown in Figure 146 on page 186. The
installation is very simple; you can just follow the window prompts, choosing the
disk drive (Figure 147 on page 186), and the program folder where you want to
install the product (Figure 148 on page 187). The only thing that it requires is an
IBM Communication Server installed and configured on your system.
Chapter 3. Connectors
185
186
The customization is very simple. You just have to read the information in the
Host On-Demand readme file in the IBM Communication Server folder. It uses
TCP/IP port number 23. If you want to change it, you have to edit the
c:\IBMCS\hd3270\he3270en.htm file and change the following statement to your
new TCP/IP port number:
<param
name=TN3270E_SERVER_PORT value=23>
To provide a browser link to Host On-Demand, you have to insert the following
statement into your Web server configuration file:
Pass
/hod/*
c:\IBMCS\HD3270\*
The documentation is provided in HTML form and you can retrieve it using the
link Webserver/hod/readme.htm link. There are two samples:
Webserver/hod/sample1.htm
This sample explains how the administrator can implement his or her own
Web page to link Host On-Demand, using a customized style. The
suggestion is to maintain some hyperlinks that provides help information for
your user.
Webserver/hod/sample2.htm
This example shows you how it is possible to invoke Host On-Demand with
the auto-connect option. You have to set the HTML parameter in the
following way:
Chapter 3. Connectors
187
<applet archive=he3270ap.zip code=he3270ap.class width=480
heigth=360 align=center>
<param name=CABBASE value=he3270ap.cab>
<param name=AUTO_CONNECT value=YES>
<param name=SEPARATE_WINDOW VALUE=NO>
</APPLET>
188
Chapter 3. Connectors
189
190
Figure 151. eNetwork Host On-Demand: How to Use the Keyboard Screen
Chapter 3. Connectors
191
Emulator functions
As mentioned before, it is the solution for SNA application access through a
standard Java-enabled desktop or Web browser. It provides emulator
functions on-demand by downloading a Java TN3270 to your computer. The
download time is reduced because only the functions needed are sent.
Java implementation
The Java implementation offers advantages not usually found in similar
solutions that use HTML mappers to provide access to the host. It provides
a persistent connection to the server. This allows you to eliminate the
interruptions due to connecting and reconnecting sessions as well as
providing less overhead and better performance. Persistent sessions also
improve network security by denying unauthorized connections to authorized
sessions.
In addition Host On-Demand lets you use the keyboard and PF keys. You
can also use the PF key icons by using your mouse. The TN3270 Java applet
includes: a default windows setting, a menu bar and the support of the
keyboard and mouse.
192
Multiple sessions
Host On-Demand provides multiple session support and lets you access
multiple 3270 applications at the same time. The current version (V1) of Host
On-Demand supports two sessions. The new version (V2) will increase that.
Clients
Host On-Demand supports any Java-enabled client platform. It can be
invoked not only from a Web browser but also from groupware clients such
as Lotus Client (4.5 or later), appletviewer or any operating systems that
support a Java virtual machine (at least JDK 1.02).
Chapter 3. Connectors
193
194
It requires you to develop Java programs that will be downloaded to the Web
browser to provide a user interface. Java programming is more complicated
than building HTML pages and in most cases, the user interface provided by
Internet or intranet solutions increase the number of potential users that can
access your application and its data. You will need to prepare for this
increased workload, as well as provide help or training for the users of the
applications.
As Java technology is rapidly evolving, new versions of the Java language
can offer more functions and services to build new powerful and robust
applications. This requires you to upgrade the Java Virtual Machine present
in the client operating systems or download new browser versions. It also
requires more CPU processing power as well as additional disk and
memory.
Using servlets and IBM connectors in the Web server system can solve some of
the above problems:
A servlet is a Java program that runs on the Web server. For this reason it
does not have a graphical user interface and can provide high performance
because it is a long running process able to manage simultaneous requests
using a multithreaded process. (Servlets start at the first client request and
stay active all the time that the Web server is active or until a destroy()
method for that servlet is invoked.)
It can be invoked:
From within the <SERVLET> tag of an HTML page with extension .shtml
This means that the user has to download only an HTML page to have a user
interface and to obtain application services. This solves the problem of not
having sufficient network bandwidth and for upgrading the clients software
and hardware to run new Java applets or new versions of Java. Of course
you can still provide Java applet solutions for a specific solution, but with a
servlet environment you only need to maintain your Web servers.
With the servlet approach, the Java classes necessary to invoke the
application server do not need to be downloaded to the clients browser. It
is enough that they are placed into a well-defined location inside the Web
server and are imported by the servlet interfacing to the application server.
Then the client does not connect to the application server directly, but
passes through the servlet.
Portable from any server system that supports a Java Virtual Machine
Chapter 3. Connectors
195
CICS and the MQSeries provide the Java classes that servlets can use to invoke:
CICS programs
MQSeries applications
This way the servlet processes requests coming from the user in HTML pages
and invokes existing application via CICS Java classes and a CICS client or via
MQ Java classes and MQSeries. In Figure 155 you can see an overview of this
architecture.
196
197
We want to point out that the macro subdirectory is the place where Net.Data
macro files are located. In addition, the installation process for Net.Data will
create a file called db2www.ini under \WWW\Html as shown in the following
figure:
198
the DB2PATH field blank, the system considers the next word INCLUDE_PATH to
be the value of DB2PATH and this caused an error. Therefore, we had to modify
it. This was due to using beta code and should be fixed in the production
version of the code. The original file is shown in Figure 159, and the modified
one is shown in Figure 160.
The next application that we show is DB2 CAE. It enables the DB2 client to
access data from a remote DB2 server through the network. It is easy to install
but there are some things that you need to be aware of.
You have to first start the Client Configuration Assistant from the DB2 for
Windows NT folder. You will then see a dialog pop up to tell you to add a
database connection. Click on the Add database button as shown in the
following figure:
199
This will bring you to the Add Database SmartGuide. Select Search the network
to search the server that you want to connect to. Then click on Next on the
bottom of the screen as shown in the following figure:
200
The Add Database SmartGuide will show you the system that you want to
connect to (see Figure 163). In this case, double-click on the item Known
Systems to see the systems that you can connect to. Youll see output similar to
Figure 164 on page 202. There are two servers in this case: NTNCF21 and
NTNCF22.
201
202
Highlight the database called SAMPLE and click on the Add System button as
shown in the following:
After you click on Add System there will be a dialog pop-up asking you the
protocol of the network as well as the server that you want to connect to. In this
case we chose TCP/IP for the transport protocol and NTNCF22 for the server
(see Figure 167).
203
If everything is okay, a message box will appear telling you that the system was
found in the list, as shown in Figure 168 on page 204.
We then highlighted the database SAMPLE and clicked on the tab Alias at the
top to make this an alias on our system. In this case we called it SAMPLE1 (see
Figure 169 and Figure 170 on page 205).
204
Figure 170. Specify the Local Name for the Target DB2 Database
After you create the alias choose the tab Target Database on the top and click on
the button Done (see Figure 171).
You will get a confirmation message box from the system. It informs you that
the configuration connection for SAMPLE1 was added successfully. You can test
205
the connection by clicking on the Test Connection button (see Figure 172 on
page 206).
When the system wants to build the connection it needs to know the user ID and
password for that database. You have to provide that in the dialog box as shown
in the following figure:
206
Go back to the Client Configuration Assistant window and you will see that there
is one entry for the database SAMPLE1 that you just connected to from the DB2
server NTNCF22 (see Figure 175).
To try another test from the DB2 command window we issued a command to
connect to database SAMPLE1:
207
Now that you know how to connect to a remote database server by using the
Client Configuration Assistant we go into our scenario and show you how
Net.Data works with the DB2 server over the network.
208
Figure 177. Use Control Center to Show You the Details of Database
We wanted to connect to the database called SAMPLE and try to use the tables
in the database. We show you how to do this with Net.Data. You can see this in
Figure 178 on page 211.
First you could have an HTML section to receive the user input from the client.
This section is called HTML(INPUT) as you can see in 7. That is exactly the
URL that the user should browse. The URL for this one is:
http://ntncf99/cgi-bin/db2www/test0.mac/input.
Input for this URL means that you go to the HTML input section first to enter
some data for the macro file. There is also a form contained in this section at
8. Inside the form there is a text field called querytext. That is the data we get
from the user (see 9), which is followed by a Submit button.
Lets now look back to the first part of this file at 1. This is the definition
section. You should define the database name, login ID and the password here
Chapter 4. Net.Data Database Scenario
209
so that Net.Data can use them to open the database that you want. You can also
define other variables that you need in this section. The second part is the SQL
section. This is the section where you issue your SQL command. You may have
more than one SQL section in a macro file. In this example, we have two SQL
sections. As you can see in 2 the SQL section is called get_row(). It counts
how many rows there are that come back from the SQL query. In the first line
youll see the variable $(querytext). In Net.Data, if you want to refer to the
variable, you should use a $ in front of it. querytext is the parameter that we
receive from the client. It is shown at 9. It means that we replace the variable
$(querytext) with the data that the user enters.
In the report section of this SQL, youll see a variable called $(ROW_NUM). It is
a system variable. It will be automatically filled right after the SQL command is
executed. This is so you will know how many rows there are that match your
SQL command. Another part of the SQL section is the message section. It
receives the SQL return code from your SQL statement and does something with
it. If the code is positive, it means it is just a warning. If it is negative, it means
there is an error. In this case we only care about a code of 100. This indicates
no data found.
The next SQL section, go_sql() at 3, performs the SQL statement and shows
the result. Youll see there is no report section for this one. It just lists them in
the way that they come back from DB2.
At 4we see an HTML report section called query(). It is called from 8 when
the user chooses the Submit button on the form. In this section, we plan how we
want to lay out the page. We could put any HTML tag here. Besides that, we
call the SQL sections here, as you can see in 5 and 6. We call get_row()
first, and then go_sql(). The output will go in this sequence and print out the
total number of rows first and then the details. The variable called $(SQL_CODE)
is also a system variable. It contains the SQL return code from the most
recently SQL command.
210
1%define {
DATABASE=sample
LOGIN=liu
PASSWORD=xxxxxxx
%}
2%Function(DTW_SQL) get_row() {
$(querytext)
%report{
<h4>There are $(ROW_NUM) rows selected.</h4>
%}
%message{
100:{
<center>
<h3>No data found!</h3>
</center>
%}
%}
%}
3%Function(DTW_SQL) go_sql() {
$(querytext)
%message{
100:{
<center>
<h3>No data found!</h3>
</center>
%}
%}
%}
4%HTML(query){
<HTML>
<HEAD><TITLE>Create Table</title></head>
<BODY>
<H2>Result...</h2>
5@get_row()
<hr>
6@go_sql()
SQL_CODE for this query is $(SQL_CODE)
Figure 178 (Part 1 of 2). The Macro File to Access Database Sample
211
<hr>
</body>
</html>
%}
7%HTML(INPUT){
<head>
<title>SQL Query.</title>
</head>
<body bgcolor=#FFFFFF>
<center>
<p>
<font color=#800000 size=5><strong>SQL Query...</strong></font>
</p>
8 <form action= / cgi-bin/db2www/test0.mac/query method=POST>
<p>
9 <input type=text name=querytext size=80 maxlength=256>
</p>
<p>
<input type=submit name=Submit value=GoSQL!>
</p>
</form>
</center>
</body>
%}
Figure 178 (Part 2 of 2). The Macro File to Access Database Sample
Now lets try our example. First you have to enter the URL for the macro file and
the HTML input section as you can see in Figure 179 on page 213. Then enter
the SQL command that you want and click on the button GoSQL!.
212
The result from the remote database should look like the following:
There are 35 rows selected by the SQL command. We can also check this by
using the DB2 Command window. The results are shown in Figure 181 on
page 214 thru Figure 183 on page 215.
213
214
Now we try to select another table from the database. We selected the
employee table. The results are shown in Figure 184, Figure 185 on page 216
and Figure 186 on page 216.
215
216
categories based upon their salary. The first category range is from 0 to $13000,
the second is from $13000 to $16000, the third is from $16000 to $19000 and the
last will be from $19000 to $22000. The details on table staff are shown in the
following figure:
217
Then we input select ID, NAME, SALARY from staff for the SQL query command
field, 13000 for Level1, 16000 for Level2, 19000 for Level3 and 22000 for Level4.
This means that the client can enter dynamic values for their analysis. After we
enter all of the fields we click on the GoSQL! button. The result is shown in
Figure 189 on page 219. It comes from an applet, which is shown in Figure 190
on page 220.
218
219
We did some more testing to see some other results. In Figure 191 on page 221
we changed the ranges that we wanted to check for.
220
You can see that the pie chart in Figure 193 on page 222 is a little different than
the one in Figure 190 on page 220 since we selected a different set of ranges.
221
Now that you have seen the results we show you the source code for the macro
file and the applet and explain the code in detail. The source code for the macro
file is shown in Figure 194 on page 223 and the source code for the applet is
shown in Figure 195 on page 227.
222
%define {
DATABASE=sample
LOGIN=liu
PASSWORD=xxxxxxx
1netdata1.codebase={http://ntncf99:80%}
upperbound=
lowerbound=
%}
%Function(DTW_SQL) go_sql() {
$(querytext)
%message{
100:{
<center>
<h3>No data found!</h3>
</center>
%}
%}
%}
%Function(DTW_SQL) get_row() {
$(querytext)
%report{
<h4>There are $(ROW_NUM) rows selected.</h4>
%}
%message{
100:{
<center>
<h3>No data found!</h3>
</center>
%}
%}
%}
2%Function(DTW_SQL) get_amount() {
SELECT * FROM staff
WHERE SALARY > $(lowerbound) AND SALARY <= $(upperbound)
%REPORT{
@DTW_ASSIGN(temp, ROW_NUM)
%}
Figure 194 (Part 1 of 3). The Macro File test.mac That Contains an Applet
223
%message{
100:{
<center>
<h3>No data found!</h3>
</center>
%}
%}
%}
224
@DTW_ASSIGN(lowerbound,level3)
@DTW_ASSIGN(upperbound,level4)
@get_amount()
@DTW_ASSIGN(amount4, temp)
5@DTWA_netdata1(netdata1.codebase,
level1, amount1,
level2, amount2,
level3, amount3,
level4, amount4)
</body>
</html>
%}
%HTML(INPUT){
<head>
<title>SQL Query.</title>
</head>
<body bgcolor=#FFFFFF>
<center>
<p>
<font color=#800000 size=5><strong>SQL Query...</strong></font>
</p>
<form action= / cgi-bin/db2www/test.mac/query method=POST>
<p>
<input type=text name=querytext size=80 maxlength=256>
</p>6
Level1 : <input type=text name=level1 size=10 maxlength=10>
Level2 : <input type=text name=level2 size=10 maxlength=10>
Level3 : <input type=text name=level3 size=10 maxlength=10>
Level4 : <input type=text name=level4 size=10 maxlength=10>
<p>
<input type=submit name=Submit value=GoSQL!>
</p>
</form>
</center>
</body>
%}
Figure 194 (Part 3 of 3). The Macro File test.mac That Contains an Applet
This macro file is based on the one in Figure 178 on page 211. We just made
some modifications to the applet part. All we want to do is to get the input data
from the HTML input section and pass these as parameters to the applet. In
order to communicate with the applet, we had to set up the environment for it.
For example, for the code base path at 1, we defined the code base for the
applet that included the host name and the port number. In this example, the
host name is ntncf99 and the port number is 80. The netdata1.class is placed in
the default directory for HTML files: c:\www\Html:.
At 3 we declare the prototype of the applet. It includes the applet name as
well as the parameters to be passed. In this case, the name of applet is
225
netdata1 and we pass eight parameters to it. We have to remember the names
of these parameters, because in the applet we get the values of these
parameters by using the exact same names.
In this example, we created a new SQL section called get_amount(). You can
see it at 2. It is designed to get the row number that fits the dynamic condition
in the where clause. There are two variables that are used in this case. One is
upperbound and the other is lowerbound. These two variables will be generated
before we call this SQL section. When this SQL section is executed, it gets the
row number that fits the condition and sets the value in variable temp. We do
this by issuing the command @DTW_ASSIGN(temp, ROW_NUM).
Look at 6, which is in the HTML input section. We have four text fields in the
page. They represent the four salary levels. Each of them has a name and we
will use these names to refer to the values later in the HTML report section.
In the HTML report section %HTML(query), we call get_row() and go_sql() as
shown in Figure 178 on page 211. The differences are shown at 4 and 5. At
4 we assign values to lower-bound and upper-bound. Then we call the SQL
function get_amount(). As we discussed before, these two variables are for the
dynamic condition in the where clause. Right after the function is called, well
have the row number that fits the range in variable temp so we can assign the
value of temp to amount1. The same procedure is applied to amount2, amount3
and amount4.
At 5, we call the applet at this time by issuing the command:
@DTWA_netdata1(netdata1.codebase,
level1, amount1,
level2, amount2,
level3, amount3,
level4, amount4)
Remember the name following @DTWA_ must be the name of the class. The
first parameter should be the code base of the applet. This is just a rule that
you have to follow.
You have seen how to call an applet inside the macro file and also how to pass
parameters to applets. Now, it is very easy for you to develop an applet. In this
example, we design a pie chart to show the percentage for each category. The
source code is shown in Figure 195 on page 227.
226
import java.applet.Applet;
import java.awt.*;
import java.lang.*;
class ShapeFrame extends Frame
{
String
level1, level2, level3, level4;
int
amount1, amount2, amount3, amount4;
int
total_amount;
2 public ShapeFrame(String l1, int a1, String l2, int a2,
String l3, int a3, String l4, int a4)
{
super(Salary Range ) ;
setBackground(Color.white);
resize(500, 500);
level1 = l1;
amount1 = a1;
level2 = l2;
amount2 = a2;
level3 = l3;
amount3 = a3;
level4 = l4;
amount4 = a4;
3
}
total_amount = a1 + a2 + a3 + a4;
g.setColor(Color.red);
g.fillArc(130, 80, width, height,
0, amount1*360/total_amount);
g.drawString(Below + $ + level1, 125, 330);
g.setColor(Color.blue);
g.fillArc(130, 80, width, height,
amount1*360/total_amount, amount2*360/total_amount);
g.drawString($ + level1 + -- + $ + level2, 110, 370);
g.setColor(Color.black);
g.fillArc(130, 80, width, height,
(amount1+amount2)*360/total_amount,
amount3*360/total_amount);
g.drawString($ + level2 + -- + $ + level3, 110, 410);
227
g.setColor(Color.green);
g.fillArc(130, 80, width, height,
(amount1+amount2+amount3)*360/total_amount,
amount4*360/total_amount);
g.drawString($ + level3 + -- + $ + level4, 105, 450);
}
public boolean handleEvent(Event evt)
{
if (evt.id == Event.WINDOW_DESTROY)
{
dispose();
return true;
}
return super.handleEvent(evt);
}
}
public class
{
ShapeFrame
String
int
In this applet there are two classes: one is netdata1 and the other is
ShapeFrame. netdata1 is the main class in this file. It receives the parameters
that are passed by the Net.Data macro. ShapeFrame takes care of drawing the
pie chart. At 1 youll see how to get parameters by using the function
getParameter(). The parameters are passed to class ShapeFrame as you can
see at 2.
Then we get the total number of staff at 3 and the drawing function will be
done by function paint(). At 4 we used fillArc() to draw a filled arc for each
category of all levels in different color, so you can easily see the percentage for
each one.
228
229
The JDBC APIs are included in the JDK 1.1, so using the JDBC does not require
any product installation besides the JDK 1.1. But, for some specific product
functions, there are add-on pieces from database vendors (for example, Oracle
and Sybase).
230
This chapter shows examples for both these models and demonstrates the
capability to integrate the new JavaBeans technology in a database
environment.
The typical flow that a JDBC application follows to interact with a database is
described with the following four steps:
1. The application loads a driver to interface with the database.
2. The application connects to the database using the driver.
3. The application creates and executes SQL statements.
4. The application processes the results.
Looking back to Figure 196 on page 230, there are four important entities that
help database developers to write the appropriate Java programs performing
these functions:
1. The public class DriverManager extends Objects class is responsible for
loading the appropriate JDBC driver and handling the database connection.
2. The public interface Connection interface is responsible for connecting to the
database.
3. The public interface Statement interface is responsible for handling SQL
statements on a connection.
4. The public interface ResultSet is responsible for allowing access to the
results of an executed statement.
We examine the flow followed by a JDBC application in the following sections.
231
232
Then the Source section for the Add Database SmartGuide window was brought
up and we had to select how we wanted to set up a connection. Since our
database was located in the local network, we selected Search the Network, as
shown in the following figure.
233
Figure 198. Selecting the Source in the Add Database SmartGuide Window
Figure 199. Target Database Section for the Add Database SmartGuide Window
234
We expanded the Known Systems field by clicking the plus sign ( + ) next to it.
The NTNCF100 machine was automatically found and displayed.
We continued expanding the object tree and the Client Configuration Assistant
found three DB2 databases for the NTNCF100 machine. We selected SAMPLE, as
shown in the following figure.
235
We then clicked on the Add System... button and the following window was
displayed in order for us to select the protocol we wanted to use to find the DB2
server.
We set the Protocol text field to TCP/IP and the Hostname text field to NTNCF100,
which was the name of the machine where we installed the DB2 UDB and where
we had created the SAMPLE database. The following DB2 Message window
came up to confirm that our operation was successful.
Then we clicked on SAMPLE as indicated in Figure 201 on page 235 and we also
clicked on the Alias tab on the top of the Add Database SmartGuide window.
That was to give an alias, for example SAMPLE1, to the target database in our
local workstation, as indicated in the following screen.
236
Figure 204. Giving an Alias to the Target Database in the Local Workstation
At that point we chose the Done button at the bottom of the window and the
following Confirmation window was displayed by the Client Configuration
Assistant to confirm that the connection configuration for SAMPLE1 was added
correctly.
We could then test the connection by selecting the Test Connection button. In
order for us to connect to the DB2 database whose alias is SAMPLE1, we had to
enter a user ID and password for that database. Then we had to click the OK
button, accepting the Connection mode set by default to Share, as shown in the
following window.
237
We chose the OK button and then the Close button on the Confirmation window
shown in Figure 205 on page 237. We could see that the SAMPLE database on
the NTNCF100 DB2 server machine had become available to the DB2 client
workstation with the alias name set to SAMPLE1, as shown below:
238
Figure 208. Available DB2 Databases in the Client Configuration Assistant Window
Another test that confirmed that the connection was successful was done by
using the command line processor for DB2 CAE. This tool can be launched by
selecting the Command Line Processor item from the DB2 for Windows NT menu.
At the db2 => prompt, we entered the following command:
Figure 209. Using the DB2 Command Line Processor for Testing the Connection
The output confirmed that the connection was successful, giving us all the
database connection information.
239
Figure 210. DB2 Connection Information Using the DB2 Command Line Processor
240
Database URL
Database user ID
Database password
Selected table
Selected columns
3. The DB2 CAE connects to the DB2 UDB located on the server machine and
passes to it the table and the columns requested.
4. The DB2 server sends the response back to the DB2 CAE on the client
machine. The DB2 CAE passes the response back to the client application
using the JDBC-ODBC Bridge Driver.
We called this application Retrieve, because its function is to retrieve data from
the SAMPLE1 database. The source code for the Retrieve JDBC application is
shown in the following figure.
241
import java.sql.*;
class Retrieve
{
public static void main(String argv[])
{
if (argv.length == 0)
{
System.err.println(No URL passed ) ;
System.exit(1);
}
try
{
Class.forName(sun.jdbc.odbc.JdbcOdbcDriver ) ;
String url = argv[0];
String userid, passwd;
if (argv.length > 1)
userid = argv[1];
else
userid = ;
if (argv.length > 2)
passwd = argv[2];
else
passwd = ;
Connection con = DriverManager.getConnection(url, userid, passwd);
Statement stat = con.createStatement();
ResultSet rs = stat.executeQuery(SELECT FIRSTNME, LASTNAME FROM PISTOIA.EMPLOYEE ) ;
System.out.println();
System.out.println(FIRST NAME and LAST NAME ) ;
System.out.println(________________________);
System.out.println();
while (rs.next())
{
String firstnme = rs.getString(FIRSTNME ) ;
String lastname = rs.getString(LASTNAME ) ;
System.out.println(firstnme + + lastname);
}
stat.close();
con.close();
}
catch(Exception e)
{
System.out.println(e.getMessage());
e.printStackTrace();
}
}
}
We can see that writing an application using the JDBC API is not very difficult.
We examine the source code of the Retrieve.java application in order to show
how it works.
First of all, notice that it is assumed that the user on the client machine passes
the JDBC database URL, the user ID and the password when the application is
invoked by the java command. The database URL is a critical piece of
information that must be passed to the JDBC application. If no URL is passed,
the application is terminated by calling the exit() method, java.lang.System. An
242
example of this is shown in the following MS-DOS window, where the Retrieve
application has been invoked without passing it the required URL.
Note
We have seen that you need to specify the JDBC URL for the database. What
exactly is a JDBC URL? It is an address that is necessary to identify a
database so that the appropriate driver is able to recognize the database and
to establish a connection with it. A JDBC URL must follow a well-defined
standard syntax, such as:
protocol:subprotocol:subname
A JDBC URL is composed of three different parts separated by colons.
These three parts are defined in the following list:
1. protocol is always jdbc.
2. subprotocol specifies the subprotocol that interfaces with JDBC. For
example, if we want to connect to a database using the JDBC-ODBC
Bridge Driver, this part of the URL will be odbc.
3. subname specifies the data source, which is the way we identify the
database. Of course this part of the JDBC URL can vary, because it
strictly depends on the subprotocol used.
In our scenarios, the JDBC URL is simply:
jdbc:odbc:sample1
243
required, and the application provides an empty string if they are not
communicated on the command line.
Another important thing that we must notice in the source code of that
application is that the Class.forName() method is invoked, passing to it the string
sun.jdbc.odbc.JdbcOdbcDriver as a parameter. In this way the forName()
method locates, loads and links the class JdbcOdbcDriver in the package
sun.jdbc.odbc, which is the JDBC-ODBC Bridge Driver.
The following steps are very simple and they involve the four most important
entities of the java.sql JDBC API package (see 5.1, What Is JDBC? on
page 229):
1. The DriverManager class is used to load the appropriate JDBC driver.
2. Using the DriverManager.getConnection() method with the URL, user ID and
password as parameters, a connection object is created for connecting to the
appropriate database.
3. Using the Connection.createStatement() method, a statement object is
created for executing an SQL statement and obtaining the results produced
by it.
4. Using the Statement.executeQuery() method with the following SQL
statement as a parameter, a ResultSet object is created for allowing access
to the results of the executed statement:
javac Retrieve.java
In fact, the two packages, java.sql JDBC API and sun.jdbc.odbc JDBC-ODBC
Bridge Driver, come with all the classes of JDK 1.1, so Retrieve.java can be
treated as a regular Java file.
Once you have compiled it, you launch it by typing in the following in the same
directory where the file Retrieve.class is stored:
244
245
Figure 215. The Flow of the JDBC Client/Server Scenario Using Java Beans
import java.sql.*;
In addition, as indicated by Figure 215, it interfaces with the DB2 CAE present on
the database client machine using the JDBC-ODBC Bridge Driver. The following
lines of code demonstrate this:
246
static
{
status.setText(Connecting to + url);
try
{
Class.forName(sun.jdbc.odbc.JdbcOdbcDriver ) ;
}
catch (Exception ex)
{
status.setText(Couldn t load JDBC-ODBC bridge driver ) ;
System.err.println(Caught Exception: + ex);
ex.printStackTrace();
return null;
}
...
Building this JDBC client/server scenario using the JDBC Select bean is very
simple. After you launch the BeanBox application, you must pick the JDBC
Select bean from the ToolBox window and place it onto the BeanBox window, as
shown in the following figure:
247
Figure 216. The JDBC Select Bean Placed onto the BeanBox Window
248
from the BeanBox window. As soon as you select this item, you will see the
Customize panel appear on the screen. You have three text fields to fill in:
1. JDBC URL, by default set to jdbc:odbc:SQLSERVER:.
2. User, by default set to guest.
3. Password, by default set to guest.
This is shown in the following three lines of code:
private
Of course you cant connect to the SAMPLE1 database on the DB2 server
machine using these default values. A java.sql.SQLException would be thrown
since it is the wrong database. This would be immediately registered at the
bottom of the Customizer panel, as shown in the following figure:
249
The MS-DOS window associated with the BeanBox application also would show
this exception, as we can see in the following figure:
250
For this reason, you must fill in those text fields with the proper values. In our
scenario these rules should be respected:
1. JDBC URL must be set to jdbc:odbc:sample1.
2. User must be set to pistoia.
3. Password must be set to xxxxxxx.
After this operation has been performed, the SelectCustomizer panel should
appear similar to the following figure:
251
Then you can click the User Tables button for the SelectCustomizer panel without
an SQLException being thrown and the customizer will then display the nine
available tables for the SAMPLE1 database, as shown in the following screen:
252
Notice that you can select the Back button at the bottom of the SelectCustomizer
panel to go back to the last menu.
You can select a table by simply highlighting it with your mouse. For example,
we selected PISTOIA.EMPLOYEE and the list of all the available columns for that
table was immediately displayed. The top of the SelectCustomizer window
summarizes the content of the panel:
Database: jdbc:odbc:sample1
Table: PISTOIA.EMPLOYEE
Number of columns: 14
You can then choose the columns you want in SQL SELECT. For example, we
selected:
Chapter 5. JDBC Database Scenario
253
1. EMPNO
2. FIRSTNME
3. MIDINIT
4. LASTNAME
5. WORKDEPT
6. JOB
7. BIRTHDATE
8. SALARY
The following window shows the SelectCustomizer panel after those selections
were done:
254
Figure 221. The SelectCustomizer Panel after Some Columns Have Been Selected
255
The BeanBox window dynamically updates the displayed data while we are
making our choices. After all the selections are done, it will appear similar to
the following:
256
Notice that the Properties window for the JDBC Select bean also dynamically
registers all the choices that we made on the SelectCustomizer panel, including
the final SQL statement, as shown in the following window:
257
The Customizer panel provides a GUI that allows the user to enter the SQL
statements in an interactive way. This would have been impossible simply using
the Properties window. Without a customizer, the user could type the SQL
statement relative to the particular data they want to retrieve. That is the reason
why the JDBC Select bean comes with its own customizer.
You can choose the Back button for the SelectCustomizer panel, in order to
select other tables or to connect to different databases or you can choose the
Done button.
This section has demonstrated in a simple way that Java beans can be easily
integrated in a client/server database scenario, with very attractive advantages.
Java beans add code reusability to the Java portability. Moreover, using visible
Java beans inside JavaBeans-aware visual builder tools lets you obtain nice
graphical results.
258
Figure 225. Flow of the JDBC Three-Tier Model Scenario Using Java Servlets
259
This scenario is based upon two files that must be written by the developer:
The HTML file containing the HTML form. This file is called
RetrieveForm.html.
The Java servlet that is invoked using the GET HTTP method from within the
H T M L < f o r m > t a g . This Java file is called RetrieveServlet.java.
The file Retrieve.html is very simple and is shown in the following figure:
<HTML>
<HEAD>
<TITLE>RetriveForm</TITLE>
</HEAD>
<BODY>
<H1>Retrieve Data From the DB2 Database</H1>
<HR>
<FORM Method=GET Action= / servlet/RetrieveServlet>
<P>
Please, fill out this form.
<P>
JDBC URL
<BR>
<SELECT>
<OPTION>jdbc:odbc:sample1
</SELECT>
<P>
User ID
<BR>
<INPUT Type=text Name=userid Size=8>
<P>
Password
<BR>
<INPUT Type=password Name=passwd Size=8>
<P>
Please, submit this form.
<BR>
<INPUT Type=Submit Value=Submit>
<INPUT Type=Reset Value=Reset>
</FORM>
<P>
Thank you!
<HR>
</BODY>
</HTML>
Figure 226. The File RetrieveForm.html
After we save this file in the HTML directory of our Web server, we can invoke it
by pointing to its URL. The Web server sends the HTML file containing the HTML
260
form back to the clients browser and the user can fill out the form by setting
User ID to pistoia and Password to xxxxxx, as shown in the following figure:
Notice that the JDBC URL appears inside a selection menu, without the option to
select different items. This is only a demonstration application, but it would be
easy to include in the selection list new items, corresponding to different
databases.
261
As soon as the user at the clients machine clicks on the Submit button, the
JDBC servlet is invoked. It interacts with the DB2 database and retrieves the
requested data that is displayed on the client s browser, as the following screen
demonstrates:
262
Notice that the servlet has been invoked within the <form> tag of the HTML
page using the GET HTTP method. You can see a simple example of this by
reading the URL after the servlet has been invoked.
This JDBC servlet connects to the same database, SAMPLE1, that we saw in
previous examples. It simply retrieves the two columns FIRSTNME and
LASTNAME from the table PISTOIA.EMPLOYEE, just like the Retrieve JDBC
application did (see 5.3, JDBC Client/Server Scenario on page 240). In effect
the source code for this RetreiveServlet servlet class is obtained in a very
simple way from the Retrieve.java file, as we can see comparing the lines of
code shown in Figure 212 on page 242 with those shown in the following figure:
import
import
import
import
java.sql.*;
javax.servlet.*;
javax.servlet.http.*;
java.io.*;
263
You can see that the main body of code for the Retrieve.java file has not
changed. The most significant statements are in the service() method of
RetrieveServlet. The two methods init() and destroy() do not do anything but log
their activations. The init() method would be more important if it had to retrieve
initialization parameters. Also, the destroy() method would be more significant if
it were used to store some information into a permanent file before killing the
servlet. This scenario does not require these operations, so the service()
methods reuse the more important procedures done by the Retrieve JDBC
application.
There are a few differences:
264
The response that the application sends back to the client machine is
formatted in an appropriate HTML form, in order to be displayed by the
clients browser.
Since, in this case it does not make sense to enter parameters on the
command line, the user ID and password are communicated within the HTML
form and then their values must be retrieved by using the getParameter()
method for the HttpServletRequest class.
Client
In our scenario the client is a Web browser located on a Windows NT 4.0
system. We used Netscape Communicator 4.01, Netscape Navigator Gold
3.02 and Microsoft Internet Explorer 3.02. Since we needed to be able to use
Java programs, the only requirement was a Java-enabled browser.
Application Server
The applications ran on the S/390 using CICS/ESA V3.3.
The IBM connectors may all be on the same system if you choose and they can
each provide different solutions, to different users. We used the IBM Transaction
Server for Windows NT because CICS/ESA V3.3 didnt have the EPI CICS client
support. The next release, CICS/ESA V4.1 or IBM Transaction Server for OS/390
does have EPI CICS client support. We used IBM SNA Communication Server V5
to make the SNA connection between CICS/ESA and the Transaction Server for
Windows NT. Figure 230 on page 266 represents the environment and the links
that we used between the three different systems.
For more information on connectors, see Chapter 3, Connectors on page 113.
265
Pass /ncf/*
c:\www\ncfral\*
We built the examples based on the CICS Internet Gateway and on CICS
Gateway for Java as shown in the main index of the Web page in Figure 231 on
page 267.
266
267
The CICS index page allows you to surf through the CICS applications and show
some of the characteristics of the CICS Internet Gateway and CICS Gateway for
Java. You can build your own index by inserting the transactions or the
programs that you want to access from an Internet or intranet.
We modified the CIGD.INI file in c:cicscli\bin, by placing a personalized header,
trailer and exit page in it. The CICS Internet Gateway will insert our header and
trailer for the 3270 emulator screens, as shown in Figure 235 on page 273. It
will use the specified ExitPage every time that the user closes the session or a
time-out value expires.
268
cicscli\bin\cigd.ini modified
Header = C:\CICSCLI\cig\html\ncftext.htm
Trailer = C:\CICSCLI\cig\html\ncftail.htm
ExitPage = /cig/ncfcics.htm
ExitAid = 0x00
PFKey24 = Off
PAKeys = Off
GraphicKeys = Off
AutoExit = Off
ImbedHTML = Off
AppendEXE = Off
<table>
<tr><th>
<td>
<h1>Welcome to the SunShine</h1>
</td>
<td>
<img src= / cig/smile.gif alt=Smile>
</td>
<td>
<h1>NCF Enterprise</h1>
</td>
</table>
<HR ALIGN=center SIZE=4>
The first topic in the index is called CICS Internet Gateway: sample operations.
It links to a customized cigstart HTML page, distributed with the CICS Internet
Gateway, called ncfstart, as shown in Figure 233 on page 270.
269
270
<!-- This function lists the available CICS servers by querying the EPI
-->
<!-- and building a list to present to the user, and allows selection
-->
<!-- of a system from the list
-->
<form method= post action= / cig-bin/ciginfo/List>
<input type= submit value= Click here to list the cics servers.>
</form>
<p>
<hr>
<!**********************************************************************>
<p>
<h3>
<a name = Tran>Different ways to start a transaction</a>
</h3>
<p>
<!-- with a predetermined system and transaction
-->
<p>
<ol>
<li>
A predetermined system and transaction
<p>
<form method= post action= / cig-bin/cigcgi/StartTran>
<input type= hidden name= SystemName size=8 maxlength=8 value= CICSTCP>
<input type= hidden name= TranName size=25 maxlength=99 value= CESN>
<input type= submit value= Click here to perform transaction CESN on
system NTNCF120>
<!-- Note that TranData need not be specified, transaction name and data
-->
<!-- can be specified in TranName
-->
</form>
<hr>
<li>
A predetermined system and transaction but with variable data
<p>
<form method= post action= / cig-bin/cigcgi/StartTran>
<input type= hidden name= SystemName size=25 maxlength=99 value= CICSTCP>
<input type= hidden name= TranName size=25 maxlength=99 value= CECI>
Specify data for CECI transaction
<input type= input name= TranData size=25 maxlength=99
value= INQUIRE TRAN ><br>
<input type= submit
value= Click here to perform transaction CECI on system NTNCF120 >
</form>
<hr>
<li>
271
272
Figure 235 through Figure 240 on page 276 show examples of how to use your
Web browser as the interface to CICS for typical transactions instead of using a
real 3270-type device.
273
274
275
276
8. The gateway receives the request, unpacks it and makes the corresponding
ECI calls to the CICS client.
9. The CICS client passes the ECI calls to the CICS server.
10. The CICS server sends the requested data back to the CICS client.
11. The CICS client sends the requested data back to the CICS gateway.
12. The CICS gateway packs these results and passes them to the Java servlet
running inside the Java-enabled Web server.
13. The Java servlet uses the ServletResponse object to send the requested
data back to the Web server.
14. The Web server sends the response back to the client.
The following screen is a logical (not physical) representation of the above flow:
Figure 241. Logical Representation of the Scenario Involving CICS and Servlets
The source code for the Java servlet, named CicsServlet.java, is shown in the
following figure:
277
import
import
import
import
java.io.*;
ibm.cics.jgate.client.*;
javax.servlet.*;
javax.servlet.http.*;
278
As you can see, this servlet sends back to the client a piece of information, the
commarea String object. This is a sample servlet and its purpose is to show the
ability of a servlet to invoke a CICS server. A servlet like this is considered a
client for the CICS server.
Notice that the response dynamically sent by the Web server back to the client is
unique for each request the Web server receives.
Chapter 6. Transaction Server Scenario (NT and S/390)
279
The CicsServlet.java file must be copied and compiled into the servlet directory
WWW\Servlets\Public. It imports the two packages javax.servlet and
javax.servlet.http. Of course it also needs to import the package
ibm.cics.jgate.client, which contains the IBM CICS Gateway for Java classes:
ibm.cics.jgate.client.JavaGateway
ibm.cics.jgate.client.ECIRequest
ibm.cics.jgate.client.EPIRequest
ibm.cics.jgate.client.Callbackable
ibm.cics.jgate.client.GatewayRequest
ibm.cics.jgate.client.GatewayTrace
280
<HTML>
<HEAD>
<TITLE>NCFCXSERV.HTM</TITLE>
</HEAD>
<BODY>
<H2><I>Servlet and IBM Connectors</I></h2>
<FORM METHOD=GET ACTION=/servlet/CicsServlet>
<INPUT TYPE=SUBMIT>
</FORM>
</BODY>
</HTML>
Figure 244. The ncfcxserv.htm HTML File Invoking the CicsServlet
This file resides in the Web server and can be called by the client browser
simply by pointing to its URL. We now describe all the steps that are necessary
to make the scenario work.
The first thing that has to be done is to start up the CICS Server for Windows NT.
This can be done by choosing the Start button, selecting Programs and then IBM
CICS Server for Windows NT. After that you need to click on the Administration
Utility item in the IBM CICS Server for Windows NT menu. That brings you to the
IBM Transaction Server Administration Window. From the Subsystem menu you
can select Start... to start CXNT120, which was the CICS region for our NTNCF120
machine, as shown in the following screen:
Figure 245. How to Start the CXNT120 CICS Region for NTNCF120
281
The IBM Transaction Server - Start CICS Region window is brought up and we
simply click the OK button while the Start type is set to Auto, as the following
figure indicates:
The status of the CXNT120 CICS Region will change from Stopped to Busy as
shown in the following window:
282
We also need to start a local terminal for the IBM CICS Server. To do this we
open the IBM CICS Server for Windows NT menu and select the Start Local
Terminal option. The CICSTERM - CICS server selection window is automatically
displayed. Select the item CXNT120 Named Piped Support for local client and
then choose the OK button, as shown in the following window:
As soon as the CICSTERM - CICS client 3270 Terminal Emulator window came up
we typed TTEE and saw a window similar to the following:
283
We then pressed the Ctrl key on our keyboard and the Terminal Emulator
indicated that it was active.
In order to make the scenario run we had to start the IBM CICS Gateway for
Java. All you need to do to start it is to double-click on the CICS Java Gateway
icon on the desktop. That icon is graphically represented by the following figure:
284
If everything is configured correctly, the CICS Gateway for Java window will
appear indicating that the CICS Gateway for Java has been correctly activated
and that the initial connection and worker threads have been successfully
created. The Lotus Domino Go Webserver must also be up so that the Netscape
Web browser can invoke the ncfcxserv.htm HTML page.
Figure 253. The I B M CICS Gateway for Java Has Been Correctly Activated
Since the scenario was built to work with all the components on the same
system, our Windows NT 4 machine had all the following applications running
simultaneously:
Netscape
As soon as the clients browser points to the ncfcxserv.htm HTML file, the
following page is displayed:
285
This simple HTML page only requires the user to click the Submit Query button.
The next stop would be to enter the user ID and password for the CICS server.
The CICS Client Messages window is displayed requesting that information:
Figure 256. Entering User ID and Password in the CICS Client Messages Window
Select the OK button. This operation initiates the entire scenario that we just
described so that a response similar to the following is displayed at the client s
browser:
286
Notice that the ncfcxserv.htm page has automatically invoked the CicsServlet
servlet by using the GET HTTP method, as you can see by reading the URL
displayed in the clients browser.
The CICS Java Gateway for Java will automatically register that the client has
connected and then disconnected, as we can see in the following window:
Figure 258. The CICS Gateway Window Registers the Client Has Connected and
Disconnected
The dynamic response that we obtained is the commarea string object for our
transaction. It is really a dynamic response, because the next time the user
clicks the Submit Query button in the HTML form while the ncfcxserv.htm page is
displayed or clicks the Reload button in the Netscape window they will get a new
transaction count. This is shown in the following window:
287
Figure 259. The Transaction Count Field for the commarea String Has Been Updated
288
Licensees of this program who wish to have information about it for the purpose
of enabling: (i) the exchange of information between independently created
programs and other programs (including this one) and (ii) the mutual use of the
information which has been exchanged, should contact IBM Corporation, Dept.
600A, Mail Drop 1329, Somers, NY 10589 USA.
Such information may be available, subject to appropriate terms and conditions,
including in some cases, payment of a fee.
The information contained in this document has not been submitted to any
formal IBM test and is distributed AS IS. The use of this information or the
implementation of any of these techniques is a customer responsibility and
depends on the customers ability to evaluate and integrate them into the
customers operational environment. While each item may have been reviewed
by IBM for accuracy in a specific situation, there is no guarantee that the same
or similar results will be obtained elsewhere. Customers attempting to adapt
these techniques to their own environments do so at their own risk.
Any pointers in this publication to external Web sites are provided for
convenience only and do not in any manner serve as an endorsement of these
Web sites.
Reference to PTF numbers that have not been released through the normal
distribution process does not imply general availability. The purpose of
including these reference numbers is to alert IBM customers to specific
information relative to the implementation of the PTF when it becomes available
to each customer according to the normal IBM PTF distribution process.
289
AS/400
CICS/ESA
DB2
DB2 Universal Database
DRDA
IMS
MQSeries
Net.Data
OS/2
OS/400
RS/6000
SAA
SystemView
VTAM
290
Subscription
Number
SBOF-7201
SBOF-7370
SBOF-7240
SBOF-7270
SBOF-7230
SBOF-7205
SBOF-7290
SBOF-7250
Collection Kit
Number
SK2T-2177
SK2T-6022
SK2T-8038
SK2T-2849
SK2T-8040
SK2T-8041
SK2T-8037
SK2T-8042
Web Gateways Tools - Connecting IBM and Lotus Application to the Web ,
SR23-7862
291
292
http://w3.itso.ibm.com/
Tools Disks
To get LIST3820s of redbooks, type one of the following commands:
TOOLCAT REDPRINT
TOOLS SENDTO EHONE4 TOOLS2 REDPRINT GET SG24xxxx PACKAGE
TOOLS SENDTO CANVM2 TOOLS REDPRINT GET SG24xxxx PACKAGE (Canadian users only)
To get BookManager BOOKs of redbooks, type the following command:
TOOLCAT REDBOOKS
To get lists of redbooks, type the following command:
For information so current it is still in the process of being written, look at Redpieces on the Redbooks Web
Site ( http://www.redbooks.ibm.com/redpieces.html). Redpieces are redbooks in progress; not all redbooks
become redpieces, and sometimes just a few chapters will be published this way. The intent is to get the
information out much quicker than the formal publishing process allows.
293
In United States:
I n Canada:
Outside North America:
1-800-879-2755
1-800-IBM-4YOU
(long
(+45)
(+45)
(+45)
(+45)
(+45)
Internet
usib6fpl@ibmmail.com
lmannix@vnet.ibm.com
bookshop@dk.ibm.com
Telephone Orders
I B M Publications
Publications Customer Support
P.O. Box 29570
Raleigh, NC 27626-0570
USA
IBMMAIL
usib6fpl at ibmmail
caibmbkz at ibmmail
dkibmbsh at ibmmail
1-800-445-9269
1-403-267-4455
(+45) 48 14 2207 (long distance charge)
1-800-IBM-4FAX (United States) or USA International Access Code -408-256-5422 (Outside USA) ask for:
Index # 4421 Abstracts of new redbooks
Index # 4422 IBM redbooks
Index # 4420 Redbooks for last six months
http://www.redbooks.ibm.com/
http://www.elink.ibmlink.ibm.com/pbl/pbl
Redpieces
For information so current it is still in the process of being written, look at Redpieces on the Redbooks Web
Site ( http://www.redbooks.ibm.com/redpieces.html). Redpieces are redbooks in progress; not all redbooks
become redpieces, and sometimes just a few chapters will be published this way. The intent is to get the
information out much quicker than the formal publishing process allows.
294
First name
Order Number
Quantity
Last name
Company
Address
City
Postal code
Telephone number
Telefax number
Card issued to
Country
VAT number
Signature
We accept American Express, Diners, Eurocard, Master Card, and Visa. Payment by credit card not
available in all countries. Signature mandatory for credit card payment.
295
296
Index
Special Characters
.shtml extension
HTML table 3
HTTP request 3
HttpServlet class 17, 21, 22
HttpServletResponse object 259
B
BeanInfo
bibliography
291
C
certificates 4
CGI-BIN 5, 14, 46
CGI-BIN processing 38
CGI, sample 157
CICS
Internet Gateway 113, 116
CICS Gateway for Java 113, 133, 276
applets 154
downloading 134
connectors 8
conversational transaction 114
CORBA IIOP 7
creating, SQL Query Tool 209
D
destroy() method 20, 22, 23, 24, 73, 93, 102
doGet() method 28
doPost() method 28
downloading, CICS Gateway for Java 134
dynamic 38
content 7, 44, 47
generation 43
response 287
Web content 11
E
e-business solutions 1
ECI call 143
ECI requests 133, 139, 153
EPI requests 127, 133, 153
J
Java
applet 4, 216
servlet 44, 232, 276
servlet API 12, 25, 28
java.io 46
JavaBean
component standard 2
interfaces 9
technology 1
javac 33
javax.servlet 6, 16, 46, 96
javax.servlet.http 6, 16, 46, 96, 264
javax.servlet.Request 6
javax.servlet.Response 6
javax.servlet.Servlet interface 5
JDBC 229, 231, 232
JDBC APIs 230
JDBC application 240, 241
JDBC Select bean 258
JDBC-ODBC Bridge Driver 231, 240, 241, 244
JDK shared libraries 30
Just in Time (JIT) compilers 62
F
FormInfo.class
I
IBM Connectors 195
ibm.cics.jgate.client.ECIRequest object 144
ibm.cics.jgate.client.JavaGateway object 143
ICAPI, sample 157
IIOP session 4
init() method 20, 22, 93, 109
invoking, Java servlet 44
ISAPI 5
54
G
GenericServlet class 17, 20, 22
GET 21, 26, 37, 49, 52
M
MQSeries Client for Java
173, 178
297
N
NetObjects Fusion
NSAPI 5, 157
4, 5
P
paint() method 22
POST 21, 26, 37, 49, 52
R
repaint() method
22
S
service() method 19, 23, 24, 72, 102
servlet 3, 4, 5, 54, 232, 259
classes 29
directory 29, 33
programming model 10
tag technique 87
using in the Web server system 195
servlet-log file 103, 107, 109
SNA application access 192
SQL Query Tool, creating 209
start() method 22
stop() method 22
sun.jdbc.odbc 244
T
TestECI
139
U
using, Java applets
216
V
VisualAge for Java
4, 5, 9
W
wrapper servlet
298
__IBM employee
Please rate your overall satisfaction with this book using the scale:
(1 = very good, 2 = good, 3 = average, 4 = poor, 5 = very poor)
Overall Satisfaction
____________
Yes____ No____
Comments/Suggestions:
(THANK YOU FOR YOUR FEEDBACK!)
_____________________________________________________________________________________________________
_____________________________________________________________________________________________________
_____________________________________________________________________________________________________
_____________________________________________________________________________________________________
_____________________________________________________________________________________________________
299
SG24-5296-00
IBML
SG24-5296-00
Printed in the U.S.A.