Web Enabling System/390 Applications Using WebSphere for OS/390, Java, and MQSeries

advertisement
Web Enabling System/390 Applications Using
WebSphere for OS/390, Java, and MQSeries
Tony Newling
Senior Information Technology Specialist
IBM Australia Limited
newlingt@au1.ibm.com
February 2000
Abstract
This paper describes a technique for making existing computer applications available to users
from a standard Web browser, over the Internet or a private intranet. It describes an
infrastructure for Web serving based on WebSphere for OS/390, Java for OS/390, and
MQSeries for OS/390. It also describes the design and implementation of programs to
connect the Web browser user to any application, regardless of where the application resides.
Finally, the paper describes the advantages of implementing such an infrastructure on
OS/390.
The techniques described in this paper have been successfully implemented as a proof of
concept at a large Australian compan y.
Pre-requisite Knowledge
This paper is designed for readers who are broadly familiar with the following topics:
[1] The architecture and purpose of System/390 and OS/390
[2] The architecture and purpose of OS/390 UNIX System Services
[3] The architecture and purpose of CICS Transaction Server for OS/390
[4] The architecture and purpose of MQSeries for OS/390
[5] The architecture and purpose of Java
Specifically, the paper will be useful for OS/390 System Programmers, Technical Managers,
Application Designers and Programmers, and System Architects .
Purpose of this Paper
Organizations that use System/390 and OS/390 “mainframe” computers typically have large
collections of application software that:
1. Have been developed over many years (in some cases, over a period of 30 years).
2. Continue to fulfill the needs of the organization.
3. May run on OS/390 or other computing systems/platforms.
4. Could be effectively made available to new users (such as customers, business partners,
and others) using Internet technologies.
© Copyright IBM Corporation 2000
Page 1 of 23
This paper describes a tactical approach to make such applications available to Web browser
users. The approach described requires more effort than a “screen-scraping” approach (for
example using Host on Demand or Host Publisher), but less effort than development of a new
application architecture based on components (for example using Enterprise Java Beans or
Component Broker). The approach requires that the application be able to exchange an
MQSeries message with the WebSphere Application Server. Applications might require some
modification if they cannot currently exchange MQSeries messages. The example application
used in this paper is a CICS application, written in COBOL, which is callable using Distributed
Program Link (DPL).
Overview of the Architecture
The components of the Web enablement architecture described in this paper are illustrated in
the following diagram, with explanatory notes following the diagram .
Web Browser
MQSeries
MQSeries
WebSphere Application Server
CICS
Appl.
Java 1.1.x
WAN
vbg
IBM HTTP Server
TCP/IP
LAN
OS/390 2.5
Logical Partition
LAN connect
LPAR
System/390 Processor
These notes describe the components of the Web enablement architecture, starting with the
application and working back to the end-user.
CICS (Application)
The example application described in this paper is a CICS application. The CICS
application is callable using EXEC CICS LINK. Any application that can exchange
messages using MQSeries is a candidate application for this architecture.
In this case, the application resides on a different OS/390 system than the Web server.
This illustrates that the target application need only have an MQSeries client or server
available to send and retrieve messages. It also illustrates a technique for isolating your
production system from your “Web system” if that is required.
The sample application uses the CICS/MQSeries bridge. This bridge allows CICS
programs to be invoked automatically when messages for those programs are received on
© Copyright IBM Corporation 2000
Page 2 of 23
the production system by MQSeries. The CICS/MQSeries bridge is available with
MQSeries Version 1 Release 2 for MVS/ESA, or from the MQSeries SupportPacs Web
site.
MQSeries
MQSeries is installed on both the OS/390 “ Web system” (the system where
WebSphere Application Server runs) and the system running the application
program (this might be OS/390, or some other system). Messages are passed
between the MQSeries systems in the two computer systems.
WebSphere Application Server
Websphere is a component of OS/390 releases after (and including) OS/390 Version 2
Release 5. Recent releases have WebSphere included in the ServerPac. If you do not
have WebSphere installed, it can be downloaded from the IBM software Web site.
WebSphere runs on the IBM HTTP Server and provides a servlet engine for OS/390.
WebSphere has a pre-requisite of Java for OS/390. The Java Developer’s Kit (levels
1.1.8 and 1.1.6) can be downloaded from the IBM System/390 Web site.
For the architecture described in this paper, the MQSeries Bindings for Java are required.
These are a set of Java class libraries which allow Java programs to put and get
messages from MQSeries queues on the same OS/390 system as the bindings are
installed (the “Web” system).
IBM HTTP Server
This is a Web server for OS/390, and is a component of OS/390. All releases of OS/390
after Version 1 Release 3 have included a Web server, although they have had different
names. The most recent releases of OS/390 include the IBM HTTP Server. The
WebSphere Web site specifies which levels of Web server are required to run
WebSphere.
TCP/IP
Provides the communications transport between the W eb server and the Web browser.
TCP/IP is a component of the OS/390 Communications Server.
OS/390
An operating system designed for business users of the System/390 computing
architecture, OS/390 p rovides the operating environment for the Web server, WebSphere,
Java, and MQSeries, among other things. A minimum level of OS/390 Version 2 Release
5 is required to run WebSphere. Note that your production system may be at a lower level
of OS/390, you only need this level in your “Web” system. You can connect to down-level
OS/390 systems using MQSeries.
Logical Partition
System/390 processors from IBM provide a facility to logically partition a single computer
into up to 15 logical systems. Many IBM customers use this LPAR facility to run
production, development, and testing systems all on a single computer. An example use
of LPAR is illustrated in the diagram.
LAN Connect
Some mechanism for connecting the System/390 computer to a local area network is
required in order to use this architecture. IBM S/390 computers include the Open
Systems Adapter (OSA) which can provide Ethernet (up to Gigabit speeds), Token Ring,
ATM, and FDDI connections to LANs. Alternatively, you can use channel-attached
devices to connect to a network.
© Copyright IBM Corporation 2000
Page 3 of 23
System/390 Processor
This is the computer that runs OS/390. There are no specific considerations for the
computer in this architecture. You can use your existing processor for this architecture.
Client Web Browser
User station which provides the user interface to the e-business applications. There are
no specific considerations for the client Web browser in this document, although a
reasonably recent level of browser is required.
Overview of the Application Flows
Having reviewed the overall Web enablement architecture, an analysis of the flow of data
through this architecture completes the overview.
The flow illustrated in the above diagram is further described as follows:
MQSeries
WAS
Web Browser
JSP
Application
System
with
MQSeries
Request Queue
Reply Queue
Extract data
Build msg
Send
Wait for response
Get message
Parse data
Return
H
T
T
P
S
e
r
v
e
r
T
C
P
/
I
P
Get home page (index.html)
Click on link in page to get
first application page
Fill out form in retrieved page.
Form fields reflect data
required by application.
Some fields can be hidden.
Display results
Results page could be
another form, which
could invoke another
program.
Iterate as appropriate
"Web" Logical Partition
Phase 1: HTML Static Pages Retrieved by Client
Before any of the processing to access the application can take place, an HTML page
which includes a form to initiate the application call must be retrieved by the client. For
example, a Web client may enter http://your.server.name/ to retrieve the server’s home
page. This is a standard HTTP request and it is processed by the IBM HTTP server
according to the rules you have defined for the server. Retrieval of static HTML
documents is not described in this paper. If you need more details, please refer to
OS/390 e-business Infrastructure: IBM HTTP Server 5.1 - Customization & Usage ,
SG24-5603, available from the IBM Redbooks Web site at http://www.redbooks.ibm.com
© Copyright IBM Corporation 2000
Page 4 of 23
Your home page may then have a link to the application page, which in turn contains a
form which collects the information needed by the application and invokes the application
when the submit button is pressed.
Phase 2: User Clicks on Button to Invoke Application Processing
The user fills out the application form, entering the data required by the application. For
example, if the application requires the user’s name, address, and property valuation in
order to provide an insurance quotation, the HTML form would have fields to collect that
information. Once the form is completed, the user presses a submit button (which might
be labelled as “Obtain Quotation”) which causes the browser to request a Java Server
Page file from the server.
Phase 3: Web Server Processes Request
The Web server receives the request for the JSP file and begins analysis to determine
how to processes the request, in the normal way. The client user ID is checked, then the
request is parsed. The server has a mapping rule which maps *.jsp to a location in the
UNIX System Services hierarchical file system (usually
/usr/lpp/WebSphere/AppServer/lib/libadpter.so:AdapterService ). This is
the WebSphere DLL program which invokes Java processing.
The client user ID is then validated and checked to see whether it has authority to retrieve
the requested file (or in this case run the WebSphere program). Assuming it has, the
plug-in program is invoked to compile the JSP if appropriate (if it is already compiled and
no changes have been made since it was compiled, the compiled page will be loaded).
The compiled JSP is a Java servlet. The servlet runs on a thread within the Web server
address space.
Phase 4: Servlet Processing Begins
The Java servlet program starts and performs the following actions:
1. Parse the data provided by the user in the HTML form which called the JSP/servlet.
2. Call a Java bean, passing it the data from the form in an appropriate format.
3. The Java bean formats an MQSeries message and puts it on an appropriate queue.
This message includes the name of the application program to be invoked on the
application system, and appropriate data for that program.
4. The Java bean issues an MQSeries get message to an appropriate queue. It waits for
a message or a timeout interval.
Phase 5: MQSeries Processing
The message placed on the MQSeries “outbound” queue is routed by MQSeries to an
“inbound” queue on an appropriate system. This is “business as usual” processing for
MQSeries, and your MQSeries administrator can set up the system to arrange for the
appropriate message routing.
On the system running the application being Web-enabled, the MQSeries/CICS bridge
program is invoked when the message sent by the JSP/servlet arrives on its “inbound”
queue. The bridge determines the name of the CICS program to be invoked from the first
eight bytes of the message. It extracts the remainder of the message, builds a
COMMAREA (data area), and calls the CICS program with EXEC CICS LINK.
When the CICS program completes, it returns to the bridge program with an updated
COMMAREA. This COMMAREA is sent as a message to the “reply-to” queue specified
by the calling program (the JSP/servlet).
© Copyright IBM Corporation 2000
Page 5 of 23
Phase 6: Servlet Processing Completes
The JSP/servlet program has been waiting for an MQSeries message to be returned from
the original call. When the message arrives, the following actions are taken:
1. Extract the message from the queue.
2. Parse the message according to the standards for the application.
3. Insert data into appropriate fields in the HTML that is part of the JSP.
4. Return the output to the user as HTML.
In the case of Java Server Pages, the servlet replaces data returned by CICS into the
specified fields in the JSP page.
The output HTML could include another form to invoke further CICS processing.
This concludes our overview of the architecture of the Web-enabled application. The
following sections discuss particular components of the architecture in greater detail.
© Copyright IBM Corporation 2000
Page 6 of 23
What Is Needed to Use the Architecture?
The following components are required to use the architecture described in this paper:
w “Web” system - the system running the WebSphere Application Server
é A System/390 processor, with a LAN connection
é OS/390 Version 2 Release 5 or later, with
ë UNIX System Services fully enabled
ë TCP/IP services of OS/390 Communications Server enabled
ë IBM HTTP Server (or an earlier, compatible equivalent) installed and operating
ë Java 1.1.x for OS/390 installed and operating
ë WebSphere Application Server 1.1 or 1.2 installed and operating
ë MQSeries installed and operating
ë MQSeries Bindings for Java installed and operating
w “Application” system - the system running the application you wish to Web enable
é An MQSeries client or server
é The application, capable of exchanging messages with MQSeries
é Network connectivity to the OS/390 system, using TCP/IP or SNA
The references section of this paper provides pointers to information about each of these
topics.
What is a Java Server Page?
Increasingly, Internet technologies are moving from a client orientation to a server orientation.
That is, the server controls the content which is provided to the client. Java servlets are
programs, written in the Java programming language, which run on a server and allow access
to server systems such as files, databases, and transaction systems. You can use a servlet
on OS/390 to provide access to DB2 databases, CICS transactions, and MQSeries queues,
among others. Using servlets rather than other techniques (such as Common Gateway
Interface programs) is attractive because servlets can be moved with recompilation to
different server platforms that implement the Java servlet standard as provided by SUN
Microsystems.
Therefore, it is possible to write a servlet which connects to CICS and displays the results in
an HTML page. There are a number of significant problems with this approach, however:
w Variable data, such as the CICS application program name, and the MQ queue names
you wish to use need to be hard-coded in the servlet (or you have to carefully architect the
servlet to accept this information as parameters in some way). To change these, the
servlet must be edited and recompiled.
w The presentation logic (the HTML produced) is hard-coded, and you have to recompile the
servlet if you want to change it.
w Because the HTML is embedded in Java code, it is difficult to use an HTML builder tool to
make HTML that looks attractive.
Java Server Pages solve this problem by turning everything around. With a servlet, you write
the Java code and include the HTML. With Java Server Pages, you write the HTML (usually
with an HTML building tool) and include the Java code in the HTML page. WebSphere then
compiles the entire JSP into a servlet dynamically when the JSP is called. The JSP is
compiled by WebSphere only when it is changed. A compiled version is kept in the file
© Copyright IBM Corporation 2000
Page 7 of 23
system (usually in /usr/lpp/WebSphere/AppServer/servlets/pagecompile ) for use
when no changes have been made.
A standard for JSPs has also been produced by SUN Microsystems, and therefore JSPs can
be moved among systems that implement the standard. WebSphere is an example of a
server that has implemented the standard. Be cautious, however, at the time of writing
WebSphere on OS/390 has implemented JSP 0.91, while the current level of the standard is
1.1.
A JSP Example
A sample JSP is instructive to understand the concepts. The following sample has
explanatory notes below it. Large amounts of the JSP have been removed so that I can
illustrate the salient points. Items of interest in the HTML code are marked as [x] , where x is
a cross reference to the notes that f ollow.
<html>
<head>
<title>MQTest Output</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="#FFFFFF" background="images/bground.gif">
<BEAN NAME="mqb" TYPE="MQSeries.RSAMessage" SCOPE="REQUEST" INTROSPECT="NO">
</BEAN>
[1]
<%
String
String
String
String
String
mqmgr = (String) request.getParameterValues("mqmgr")[0];
[2]
outputqueue = (String) request.getParameterValues("outputqueue")[0]; [2]
inputqueue = (String) request.getParameterValues("inputqueue")[0]; [2]
message = (String) request.getParameterValues("message")[0];
[2]
timeout = (String) request.getParameterValues("mqtimeout")[0];
[2]
String outdata = new String();
mqb.setQueuemanager(mqmgr);
[3]
mqb.setOutputqueue(outputqueue);
[3]
mqb.setInputqueue(inputqueue);
[3]
mqb.setOutputmessage(message);
[3]
mqb.setGettimeout(timeout);
[3]
mqb.putMessage();
[4]
mqb.getMessage();
[5]
%>
<table width="81%" border="0" cellpadding="0" cellspacing="0">
<tr>
<td width="45%"><font face="Arial, Helvetica, sans-serif">The queue manager
you used was:</font></td>
<td width="55%"><font face="Arial, Helvetica, sans-serif"
color="#00FF00"><%=mqb.getQueuemanager() %></font></td>
[6]
</tr>
<tr>
<td width="45%"><font face="Arial, Helvetica, sans-serif">The output queue
was:</font></td>
<td width="55%"><font face="Arial, Helvetica, sans-serif"
color="#FF00FF"><%=mqb.getOutputqueue() %></font></td>
</tr>
<tr>
<td width="45%"><font face="Arial, Helvetica, sans-serif">The input queue
was:</font></td>
© Copyright IBM Corporation 2000
Page 8 of 23
<td width="55%"><font face="Arial, Helvetica, sans-serif"
color="#3399FF"><%=mqb.getInputqueue() %></font></td>
</tr>
</table>
<br>
<table width="81%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td><font face="Arial, Helvetica, sans-serif">
<%
[7]
boolean err = false;
if (mqb.getErrorMessage() == "")
{
%>
Your message text is:
<%
outdata = mqb.getOutputmessage();
} else
{
%>
An error occurred, the error text is:
<%
outdata = mqb.getErrorMessage();
err = true;
}
%>
[8]
</font></td>
</tr>
<tr>
<td>
<%
if (!err)
{
%>
<font face=’Arial, Helvetica, sans-serif’ color=’#000099’>
<%
} else
{
%>
<font face=’Arial, Helvetica, sans-serif’ color=’#993300’>
<%
}
%> <%=outdata %></font></td>
[9]
</tr>
</table>
<p> </p>
</body>
</html>
Some points to note from this source:
w A JSP looks like a standard HTML file, containing some JavaScript. The HTML file can be
built using any standard HTML tool. NetObjects Fusion (http://www.netobjects.com/) is
a good example of an HTML building tool. WebSphere Studio also has good tools for
building JSP files.
w The <bean> tag [1] references Java compiled programs which provide services to this
JSP. The mqb bean (source code provided on page 11) provides services to construct a
message for MQSeries, put the message on a queue, and retrieve a message from a
queue. It is my practise to build a generic Java bean which can provide services to any
JSP, and then put the information unique to each application in the Java code within the
JSP.
© Copyright IBM Corporation 2000
Page 9 of 23
w JavaScript code is encapsulated within <% and %> delimiters. I have had problems when
w
I put code on the same line as a delimiter (eg <% int index=0); and this may be a function
of the level of JSP (0.91) implemented in WebSphere for OS/390. For scripts, put
delimiters on their own line and you won’t have a problem.
After the first script delimiter, there are a series of lines that extract the data from the form
that called this JSP [2]. Lines of the form
String mqmgr = (String) request.getParameterValues("mqmgr")[0];
extract the field name from the form and assign the value to a variable (in this case with
the same name) within the servlet.
w The next step in the JSP is to take the fields from the form and use them to set initial
values for the bean [3]. In this case we are using the values set up in the lines marked
[2].
w The message constructed by the bean is put on an output MQSeries message queue in
line [4].
w The JSP then waits for a reply message (line [5]).
w To display the contents of a Java variable created within the JSP, use HTML of the form
<%= variablename %> (example in line [6]). Make sure in particular you use <%= with no
spaces in between, or you will end up with an error (in the WebSphere ncf.log) like
/usr/lpp/WebSphere/AppServer/servlets/pagecompile/_StaffMember_xjsp.java:49: ’;’
expected.
data[0].writeChars(0, 314, out);
and usually a response on the Web browser like
Unable to compile
/usr/lpp/ServletExpress//servlets/pagecompile/_test2_xjsp.java
w If you wish to produce HTML within a loop (for example, while) or within any Java
conditional logic (for example, if) you must close the Java block beginning the conditional
construct, then include the HTML you want produced, and then place another Java block
closing the conditional or loop block. An example is shown between markers [7] and [8] in
the code above. In other words, the JavaScript code cannot contain HTML elements.
Line [9] is an example of variable output – if the call to MQSeries is successful, the output
message is displayed. If the call is not successful, the MQSeries return code is displayed.
w JSPs fail if <%= variablename %> is evaluated at run time to a null value. Often, these
variables contain Java strings, so a null string would be “”. Nulls are quite common in
databases, so good practise would be to initialise all variables to non-null values in your
database access code (don’t change the database!). Your beans which access the
database should do this. A good practise would be for your bean’s getter methods (the
functions which get the data) to test the result they are sending. If the value to be
returned is null, the getter method should change the value to a non-null (for example, a
null string is converted to a single space).
Use of Compiled Java Code
As you can see from the above JSP extract, control of the application and display of the
results is done using JavaScript code. Note that this JavaScript is processed on the server,
not on the client, so you should not have security concerns about using JavaScript in this
instance. The end user only sees HTML, the JSP is a development entity; remember that it is
compiled into a servlet at run time, and the servlet produces HTML for the end user.
When designing applications that use JSPs, you will quickly notice that each JSP you develop
shares a set of common Java code. For example, for the sample application using CICS,
common routines are required, among other things, to:
© Copyright IBM Corporation 2000
Page 10 of 23
w
w
w
w
w
Construct an MQSeries message.
Put a message on an MQSeries queue.
Get a message from an MQSeries queue.
Parse an MQSeries message.
Handle error conditions signalled by MQSeries.
This common code should be compiled into a Java bean. The bean can be a Java class file,
which provides services to the JSP as Java methods. By way of illustration, the source for the
bean used in the JSP described earlier is listed following. Notes are included within the code
as comments, and where appropriate following the code.
mqb Bean
This bean (RSAMessage.class) must be placed somewhere in the WebSphere class path, in
an MQSeries subdirectory (since it has been defined as being part of the MQSeries package).
package MQSeries;
import com.ibm.mq.*; // This is a reference to the MQSeries bindings for Java
package,
// available from the MQSeries SupportPacs web site
import java.util.Hashtable;
/**
* This type was created in VisualAge.
* VisualAge for Java was used to build this bean. One significant advantage of VAJ
* for building such code is that on defining an attribute, VAJ can automatically
* build getter and setter methods for you, significantly reducing your coding
effort.
* Incremental compilation is another significant advantage.
* No use of VAJ connectors was made when building this code.
*/
public class RSAMessage {
private String outputqueue = "Output queue name is not set";
private String inputqueue = "Input queue name is not set";
private String queuemanager = "Queue manager name is not set";
private String inputmessage = "Input message is not set";
private String outputmessage = "Output message is not set";
private String errormessage = "";
// The above attributes are set up with default values.
// This is done in case a value is not properly set by the JSP, in
// which case the default value will be displayed on the output web page,
// making diagnosis of JSP coding errors simpler.
private byte messageID[]; // required by MQ Bindings for Java
private int gettimeoutms = 60000; // default MQ timeout is 60 seconds
/**
* RSAMessage constructor comment.
*/
public RSAMessage() {
super();
}
/**
* This method was created in VisualAge.
* @param newValue java.lang.String
*/
public void appendErrorMessage(String newValue) {
this.errormessage += newValue;
}
/**
© Copyright IBM Corporation 2000
Page 11 of 23
* This method was created in VisualAge.
* @return java.lang.String
*/
public String getErrorMessage() {
return errormessage;
}
/**
* This method was created in VisualAge.
* @return int
*/
public int getGettimeoutms() {
return gettimeoutms;
}
/**
* This method was created in VisualAge.
* @return java.lang.String
*/
public String getInputmessage() {
return inputmessage;
}
/**
* This method was created in VisualAge.
* @return java.lang.String
*/
public String getInputqueue() {
return inputqueue;
}
/**
* This method was created in VisualAge.
*/
public void getMessage() {
// This method assumes that the following methods have been run:
// 1. PutMessage()
// It is used to get an expected message from a reply queue
try
{
// Create a connection to the queue manager
MQQueueManager qmgr = new MQQueueManager(this.getQueuemanager());
// Set up options for the call
int openOptions = MQC.MQOO_INPUT_AS_Q_DEF ;
// Define the queue to place the message on
MQQueue q = qmgr.accessQueue(this.getInputqueue(),
openOptions, null, null, null);
// Define the message to be sent
MQMessage msg = new MQMessage();
// and set the message ID to be that originally sent
msg.messageId = getMessageID();
// Set up options for the get as default
MQGetMessageOptions gmo = new MQGetMessageOptions();
// Set up to wait for a message
gmo.options = MQC.MQGMO_WAIT;
gmo.waitInterval = 1;
// Now get the message
q.get(msg,gmo);
// and put it in our message container
setInputmessage(msg.readString(msg.getMessageLength()));
// Now disconnect
© Copyright IBM Corporation 2000
Page 12 of 23
q.close();
qmgr.disconnect();
}
catch (MQException ex)
{
appendErrorMessage("An MQSeries error occurred : Completion code " +
ex.completionCode + " Reason code " + ex.reasonCode);
}
// Was it a Java buffer space error?
catch (java.io.IOException ex)
{
appendErrorMessage("An error occurred whilst writing to the message buffer:
" + ex);
}
}
/**
* This method was created in VisualAge.
* @return byte
*/
public byte[] getMessageID() {
return messageID;
}
/**
* This method was created in VisualAge.
* @return java.lang.String
*/
public String getOutputmessage() {
return outputmessage;
}
/**
* This method was created in VisualAge.
* @return java.lang.String
*/
public String getOutputqueue() {
return outputqueue;
}
/**
* This method was created in VisualAge.
* @return java.lang.String
*/
public String getQueuemanager() {
return queuemanager;
}
/**
* Starts the application.
* @param args an array of command-line arguments
*/
public static void main(java.lang.String[] args) {
// A main method means this bean can be called from a shell environment
// for testing.
RSAMessage m = new RSAMessage();
System.out.println("Starting application...");
m.setQueuemanager("CSQ6");
m.setOutputqueue("CSQ5.LOOP.QUEUE");
m.setInputqueue("CSQ6.LOCAL.QUEUE");
m.setOutputmessage("This is my test message 1234567890");
m.setGettimeout("120000");
System.out.println("Putting output message...");
m.putMessage();
System.out.println("Finished putting output message...");
System.out.println("Getting input message...");
m.getMessage();
System.out.println("Finished getting input message...");
© Copyright IBM Corporation 2000
Page 13 of 23
System.out.println("Retrieved message is...");
System.out.println("");
System.out.println(m.getInputmessage());
System.out.println("");
System.out.println("Error messages are...");
System.out.println("");
System.out.println(m.getErrorMessage());
}
/**
* This method was created in VisualAge.
*/
public void putMessage() {
// This method assumes that the following methods have been run:
// 1. setQueuemanager(String)
// 2. setOutputqueue(String)
// 3. SetOutputmessage(String)
// It is used to put a message on an outbound queue.
try
{
// Create a connection to the queue manager
MQQueueManager qmgr = new MQQueueManager(this.getQueuemanager());
// Set up options for the call
int openOptions = MQC.MQOO_OUTPUT;
// Define the queue to place the message on
MQQueue q = qmgr.accessQueue(this.getOutputqueue(),
openOptions, null, null, null);
// Define the message to be sent
MQMessage msg = new MQMessage();
// Set up message ID to default -queue manager will assign a unique message
ID
msg.messageId = MQC.MQMI_NONE;
// Set up correlation ID to required for new sessions
msg.correlationId = MQC.MQCI_NEW_SESSION;
// Set up format
msg.format = MQC.MQFMT_STRING;
// Set up reply queue
msg.replyToQueueName = inputqueue;
// and put the message in it
msg.writeString(outputmessage);
// Set up options for the put as default
MQPutMessageOptions pmo = new MQPutMessageOptions();
// Now put the message
q.put(msg,pmo);
// Remember the message id for later
setMessageID(msg.messageId);
// Now disconnect
q.close();
qmgr.disconnect();
}
catch (MQException ex)
{
appendErrorMessage("An MQSeries error occurred : Completion code " +
ex.completionCode + " Reason code " + ex.reasonCode);
}
// Was it a Java buffer space error?
catch (java.io.IOException ex)
{
© Copyright IBM Corporation 2000
Page 14 of 23
appendErrorMessage("An error occurred whilst writing to the message buffer: " +
ex);
}
}
/**
* This method was created in VisualAge.
* @param newValue java.lang.String
*/
public void setErrorMessage(String newValue) {
this.errormessage = newValue;
}
/**
* This method was created in VisualAge.
* @param input java.lang.String
*/
public void setGettimeout(String input) {
// this method takes a string and sets the MQ message get
// timeout value to the integer value derived from the String
try
{
Integer toms = new Integer(input);
this.gettimeoutms = toms.intValue();
} catch (NumberFormatException ne)
{
// do nothing, just take the default timeout set in the constructor
}
}
/**
* This method was created in VisualAge.
* @param newValue int
*/
public void setGettimeoutms(int newValue) {
this.gettimeoutms = newValue;
}
/**
* This method was created in VisualAge.
* @param newValue java.lang.String
*/
public void setInputmessage(String newValue) {
this.inputmessage = newValue;
}
/**
* This method was created in VisualAge.
* @param newValue java.lang.String
*/
public void setInputqueue(String newValue) {
this.inputqueue = newValue;
}
/**
* This method was created in VisualAge.
* @param newValue byte
*/
public void setMessageID(byte[] newValue) {
this.messageID = newValue;
}
/**
* This method was created in VisualAge.
* @param newValue java.lang.String
*/
public void setOutputmessage(String newValue) {
this.outputmessage = newValue;
}
/**
* This method was created in VisualAge.
* @param newValue java.lang.String
*/
© Copyright IBM Corporation 2000
Page 15 of 23
public void setOutputqueue(String newValue) {
this.outputqueue = newValue;
}
/**
* This method was created in VisualAge.
* @param newValue java.lang.String
*/
public void setQueuemanager(String newValue) {
this.queuemanager = newValue;
}
}
Notes from the Java bean source code:
w This code was built for a proof-of-concept. It was not engineered to be production ready.
You are free to use the code, but must do so at your own risk. To be made production
ready, a significant amount of work needs to be done on error checking and handling. In
addition, no parser is provided. For the proof-of-concept, I wrote a parser in JavaScript
within the JSP file.
w XML is ideally suited to describing the message that passes between WebSphere and the
application. This would be a good subject for another paper.
Creating JSPs
I use NetObjects Fusion (http://www.netobjects.com) to create my Web pages and JSPs; you
of course can use any tool you consider appropriate. Here are a few tricks I have developed
to build JSPs using an HTML builder:
w Build your HTML as normal.
w For JSPs, make sure you change the extension of the file produced by the tool to .jsp.
w If you require tabular output, where one row of HTML is produced for each row returned
from an application, the best way I have found is:
1. Lay out the table with two rows, one for the header and one as a model for the
results.
2. In the results row, enter the variable names to be evaluated in the appropriate
columns. Set up the fonts and colours you wish to use. However, you probably
cannot code <%= variablename %> because the tool will most likely change the < to
< and > to > (URL escapes) because these characters are reserved for HTML.
Web browsers translate these characters back to < and >, but you want them
evaluated by the server (servlet), not the browser. I therefore use a trick like
ZZvariablenameYY, and on the OS/390 system edit the file and change all ZZ to
‘<%= ‘ and all YY to ‘ %>’. If anyone can find a better way (or stop the tool from
URL escaping these characters, please let me know.
3. Position the cursor in the body of the document (not in the layout region or margins)
and click the HTML button to insert your bean tags after the body tag.
4. Use the tool ROW HTML button to:
a. Insert the Java code for the beans call and loop opening BEFORE the row tag.
b. Insert the Java code to close the loop and increment the counter AFTER the
row tag.
© Copyright IBM Corporation 2000
Page 16 of 23
Proof of Concept Application
The proof of concept CICS application is a quoting application for building or motor insurance.
This is a simple application that requires only specification of the type of insurance, postcode,
and sum insured to generate a quote.
An HTML page is used to collect this information from the client. A fragment from such a page
is shown following:
Clicking “Request Quote” on this page makes a call to the JSP listed following:
<html>
<head>
<title>CICSTest Output</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="#FFFFFF" background="images/bground.gif">
<BEAN NAME="mqb" TYPE="MQSeries.RSAMessage" SCOPE="REQUEST" INTROSPECT="NO">
</BEAN>
[1]
<%
// get system values from the form. Note that these are provided
// in hidden fields in the input HTML form for this Proof of Concept
String mqmgr = (String) request.getParameterValues("mqmgr")[0];
[2]
String outputqueue = (String) request.getParameterValues("outputqueue")[0];
String inputqueue = (String) request.getParameterValues("inputqueue")[0];
String timeout = (String) request.getParameterValues("mqtimeout")[0];
String program = (String) request.getParameterValues("program")[0];
// application values:
String operator = (String) request.getParameterValues("operator")[0];
[3]
String typeoi = (String) request.getParameterValues("type")[0];
String postcode = (String) request.getParameterValues("postcode")[0];
String suminsured = (String) request.getParameterValues("suminsured")[0];
String
String
String
String
String
outdata = new String();
message = new String();
omessage = new String();
blah = new String();
toi = new String();
// test the length of the program name to be called - provided by the form
program.trim();
© Copyright IBM Corporation 2000
Page 17 of 23
if (program.length() != 8)
{
// this is an ugly solution and needs to be fixed properly
// concatenate blanks to the provided program name
blah = program.concat("
");
// then substring to 8 characters
omessage = blah.substring(0,8);
}
// pad suminsured with 0’s if length is not 6.
String sum = "000000";
String outsum = new String();
int sumlength = suminsured.length();
if (sumlength != 6)
{
outsum = sum.substring(0, (6 - sumlength));
outsum += suminsured;
} else
{
outsum += suminsured;
}
message += operator += typeoi += postcode += outsum;
message += "
";
omessage += message;
[5]
[4]
mqb.setQueuemanager(mqmgr);
[6]
mqb.setOutputqueue(outputqueue);
[6]
mqb.setInputqueue(inputqueue);
[6]
mqb.setOutputmessage(omessage);
[6]
mqb.setGettimeout(timeout);
[6]
mqb.putMessage();
[7]
mqb.getMessage();
[8]
boolean err = false;
outdata = mqb.getInputmessage();
String errormessage = new String();
// look for a comma, if we get one the data is real, otherwise it is
// an error message
[9]
if (outdata.indexOf(",") == -1)
{
err = true;
errormessage = outdata;
}
if (mqb.getErrorMessage() != "")
{
err = true;
errormessage = mqb.getErrorMessage();
}
String
String
String
String
String
String
outbasicpremium = " ";
[10]
outtaxes = " ";
[10]
outtotalpremium = " ";
[10]
outpostcode = " ";
[10]
outsuminsured = " ";
[10]
testit = new String();
© Copyright IBM Corporation 2000
Page 18 of 23
if (!err)
{
[11]
int counterc = outdata.indexOf(",");
int counterm = outdata.indexOf(",", counterc+1);
outbasicpremium = outdata.substring(counterc+1, counterm);
counterc = counterm;
counterm = outdata.indexOf(",", counterc+1);
outtaxes = outdata.substring(counterc+1, counterm);
counterc = counterm;
counterm = outdata.indexOf(",", counterc+1);
outtotalpremium = outdata.substring(counterc+1, counterm);
counterc = counterm;
counterm = outdata.indexOf(",", counterc+1);
outpostcode = outdata.substring(counterc+1, counterm);
counterc = counterm;
counterm = outdata.indexOf(",", counterc+1);
outsuminsured = outdata.substring(counterc+1, counterm);
// set up type of insurance text
testit = typeoi.substring(0,3);
if (testit.compareTo("001") == 0)
{
toi = "building";
} else
{
toi = "contents";
}
}
%>
<table width="91%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td width="0%"><img src="images/title.gif" width="406" height="68"></td>
<td width="73%"> </td>
<td width="27%"><img src="images/logo.gif" width="170" height="58"></td>
</tr>
<tr>
<td width="0%"> </td>
<td width="73%"> </td>
<td width="27%"> </td>
</tr>
<%
// if we get a valid result, print the following
if (!err)
[12]
{
%>
<tr>
<td width="100%" colspan="3">
<h2>CICS Quoting Application</h2>
<p><font face="Arial, Helvetica, sans-serif">Thank you for your interest
in insuring your <b><%=toi %></b> with us. Your quote is:</font></p>
[13]
</td>
</tr>
</table>
© Copyright IBM Corporation 2000
Page 19 of 23
<br>
<table width="293" border="0" cellpadding="0" cellspacing="0">
<tr>
<td width="68%"><font face="Arial, Helvetica, sans-serif">For postcode:</font></td>
<td width="32%"><font face="Arial, Helvetica, sans-serif"
color="#00FF00"><%=outpostcode%></font></td>
[13]
</tr>
<tr>
<td width="68%"><font face="Arial, Helvetica, sans-serif">and for sum
insured:</font></td>
<td width="32%"><font face="Arial, Helvetica, sans-serif"
color="#00FF00">$<%=outsuminsured%></font></td>
[13]
</tr>
<tr>
<td width="68%"> </td>
<td width="32%"> </td>
</tr>
<tr>
<td width="68%"><font face="Arial, Helvetica, sans-serif">Basic Premium</font></td>
<td width="32%" align="right"><font face="Arial, Helvetica, sans-serif"
color="#3399FF">$<%=outbasicpremium%></font></td>
[13]
</tr>
<tr>
<td width="68%"><font face="Arial, Helvetica, sans-serif">Taxes and
Charges</font></td>
<td width="32%" align="right"><font face="Arial, Helvetica, sans-serif"
color="#3399FF">$<%=outtaxes%></font></td>
[13]
</tr>
<tr bgcolor="#00CCFF">
<td width="68%"><b><font face="Arial, Helvetica, sans-serif">Total
Premium</font></b></td>
<td width="32%" align="right"><b><font face="Arial, Helvetica, sans-serif"
color="#0000FF">$<%=outtotalpremium%></font></b></td>
[13]
</tr>
</table>
<p> </p>
<%
// else if message not OK, print this
} else
[14]
{
%>
<!table width="75%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td><font face="Arial, Helvetica, sans-serif">Sorry, we were unable to generate
a quote. Please try again later.</font></td>
</tr>
<tr>
<td><font face="Arial, Helvetica, sans-serif">Error message is : <%=errormessage %>
[15]
</font></td>
</tr>
<p> </p>
<%
// end if
}
%>
</body>
</html>
[16]
Notes from the JSP:
[1] Once again, we use the Java bean explained earlier.
© Copyright IBM Corporation 2000
Page 20 of 23
[2] System values such as MQSeries queue manager name, and input and output queues,
are provided to the JSP in hidden fields from the form which invokes the JSP. This is not
a secure solution, a more engineered solution would probably use servlet properties files
or initialization files to specify site specific information.
[3] Application values are retrieved from the form here.
[4] The MQSeries message is constructed, to the format required by the application being
called. This has been agreed in advance with the owner of the application.
[5] The MQSeries/CICS bridge requires the CICS program name, with length of eight bytes,
followed by the COMMAREA data to be passed to the CICS program.
[6] These lines set up important data for the Java bean, which determine which MQSeries
queues to be used and so on.
[7] The message is placed on the outbound queue, and the JSP waits for a response on the
inbound queue [8].
[9] The response from the application should be comma delimited. This has been agreed
with the application owner. The code following this comment checks for a valid response
message.
[10] These lines initialize the strings which will be used for output. Since JSPs fail if null
values are output, the strings are initialized to a single space to ensure the JSP will not
fail due to nulls.
[11] The if block commencing here parses the data by scanning for commas (as agreed with
the application owner. The order of variable values has also been agreed. This is a very
simple design, and a production application would use a more robust design, perhaps
using something like XML to describe the message contents.
[12] As in the earlier JSP, there is an if block which produces the following HTML if there is no
error. Note that the JavaScript must be ended (even though the logic has not ended)
before HTML code is included.
[13] These lines are examples of outputting data parsed from the MQSeries message.
[14] This else block is associated with the if in line [12].
[15] In case of an error, an apology is produced along with the MQSeries message.
[16] The end of the JavaScript if block.
The output of the JSP is shown following (fragment of HTML page):
JSPs allow you to present your application in an attractive way, making use of graphics,
colours, and fonts (along with any other HTML or browser feature you wish to use).
© Copyright IBM Corporation 2000
Page 21 of 23
Why Use OS/390
There are a number of documents that describe the advantages of using OS/390 as a Web
server/concentrator. These include the OS/390 e-business Infrastructure books listed in the
references.
However, there are a number of reasons OS/390 was chosen as the server for the
proof-of-concept project which generated this paper. These were:
w Response time. Experiences with access to CICS applications using MQSeries from NT
servers provided a benchmark for response times, which typically were in the order of a
few seconds. Without any tuning or other special work, a response time in the order of
one second was achieved for the architecture described in this paper.
w Capacity. OS/390 has the capability to run more work than most other commercial
w
servers.
Security. Users can be validated using OS/390 Security Server, to ensure that have
authority to access the resources they are asking for.
© Copyright IBM Corporation 2000
Page 22 of 23
References
Web Server
IBM HTTP Server for OS/390 Planning, Installing, and Using , SC31-8690.
IBM HTTP Server for OS/390 Web Programming Guide , SC34-4743-01.
These documents are available from the software Web site,
http://www.ibm.com/software/webservers/httpservers/doc51.html.
OS/390 e-business Infrastructure: IBM HTTP Server 5.1- Customization & Usage ,
SG24-5603-00 (check http://www.redbooks.ibm.com for availability).
WebSphere Application Server
WebSphere Application Server for OS/390 Program Directory , GI10-6780, available from
http://www.ibm.com/software/webservers/appserv/
(follow the links to WebSphere for OS/390).
WebSphere Application Server for OS/390 Planning, Installing, and Using , available from
http://www.ibm.com/software/webservers/appserv/
(follow the links to WebSphere for OS/390).
A trouble shooting guide is also available from this location.
OS/390 e-business Infrastructure: IBM WebSphere Application Server 1.1 - Customization &
Usage, SG24-5604-00 (check http://www.redbooks.ibm.com for availability).
Java for OS/390
Check the Web site, http://www.s390.ibm.com/java
e-business Application Solutions on OS/390 Using Java: Volume I , SG24-5342-00 (check
http://www.redbooks.ibm.com for availability).
Java Programming Guide for OS/390, SG24-5619 (check http://www.redbooks.ibm.com for
availability).
MQSeries
Check the Web site for information about MQSeries, MQSeries bindings for Java, and the
MQSeries/CICS bridge - http://www.ibm.com/software/ts/mqseries/
© Copyright IBM Corporation 2000
Page 23 of 23
Download