April 2006
This document contains
information that will help you use the development tools in this release of
WSIT for OpenVMS.
Software Version
Web Services Integration Toolkit Version 1.1
Hewlett-Packard
Company
© 2006
Hewlett-Packard Development Company, L.P.
Intel, Intel Inside, and
Itanium are trademarks of Intel Corporation in the
Microsoft, Windows,
Windows XP, Visual Basic, Visual C++, and Win32 are trademarks of Microsoft
Corporation in the
Java and all Java-based
marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the
All other product names
mentioned herein may be trademarks of their respective companies.
Confidential computer
software. Valid license from HP and/or its subsidiaries required for
possession, use, or copying. Consistent with FAR 12.211 and 12.212, Commercial
Computer Software, Computer Software Documentation, and Technical Data for
Commercial Items are licensed to the U.S. Government under vendor’s standard
commercial license.
Neither HP nor any of its
subsidiaries shall be liable for technical or editorial errors or omissions
contained herein. The information in this document is provided “as is” without
warranty of any kind and is subject to change without notice. The warranties
for HP products are set forth in the express limited warranty statements
accompanying such products. Nothing herein should be construed as constituting
an additional warranty.
C O N T E N T S
INTRODUCTORY
INFORMATION – FOR ALL USERS
1. USING THE WEB
SERVICES INTEGRATION TOOLKIT FOR OPENVMS
1.1 Overview
1.2 Preparing the Original (Legacy) Application
1.3 Exposing an OpenVMS 3GL Application: Typical Development Steps
1.4 Wrapping a 3GL
Application: C Sample
1.4.1 Server/Application Build Procedure
1.4.2 Customizing the Build Environment
1.5 Wrapping an ACMS
Application: ACMS Sample
1.6 Generating Sample Clients
1.7 Using ANT with the Web
Services Integration Toolkit
1.7.1 Ant Setup
1.7.2 Configuring the
wsit-ant-user.properties File
1.7.3 Using the
wsit-ant-userbuild.xml Build File
1.7.4 Ant Property Descriptions
1.7.5 Ant Target Descriptions
1.7.6 Custom Ant Tasks
1.8 Using Distributed NetBeans with the Web Services Integration
Toolkit
1.8.1 WSIT Build Templates
1.8.2 Using the WSIT-Supplied Ant
Version
1.9 Security Considerations
1.9.1 Server Process Security
1.9.2 Per User Security
2.1
Types of OpenVMS Applications
2.3.1 Sessions
2.3.2 Application
Reusability
2.3.3 Using Multiple
Processes to Scale Applications
2.3.4 Specifying Out-of-Process Deployment Options
2.3.4.1 Out-of-Process
Account Preparation and Requirements
2.4 Web Services Integration
Toolkit Interfaces
2.4.1 Application Interfaces (User Supplied)
2.4.2 OpenVMS Datatypes Supported
by WSIT
2.4.3 Passing Mechanisms
2.4.4 JavaBean Interface
(Generated by WSIT)
2.4.5 Datatype Mapping
2.4.6 Parameter Usages
2.5 Design Restrictions for
Wrapped Applications
2.5.1 Pointer Types Not Supported
2.5.2 Instantiated WSIT JavaBeans
Cannot Be Shared Among Clients
2.5.3 Languages Tested with Web
Services Integration Toolkit
2.5.4 Tips and Hints for Supported
Languages
2.5.5 Tips and Hints for OpenVMS
Alpha Users
ADVANCED
INFORMATION – FOR EXPERIENCED USERS
3. ADVANCED
OUT-OF-PROCESS CONFIGURATION
3.2
Case B: Sequentially
Reusable
3.3
Case C: Concurrently Reusable
3.4 Case D: Concurrently Reusable with Multiple
Threads
4. USING
TEMPLATES TO GENERATE CODE
4.1
Modifying Velocity Templates
4.2
Generating Code with IDL2CODE.JAR
4.3
Example 1: Writing a New Template
4.4
Example 2: Modifying an Existing Template
B. Program Listing - STOCK.XML
C. Program Listing - StockCaller.Java
D. Program Listing - MATH.C
F. Program Listing - mathcaller.java
This Developer’s Guide contains information
about how to use the tools in the Web Services Integration Toolkit for OpenVMS,
and things to consider as you prepare your legacy application.
The Installation Guide and Release Notes
includes system requirements and installation instructions for OpenVMS, as well
as release notes for the current release of the Web Services Integration
Toolkit for OpenVMS.
For the latest
release information, refer to the Web Services Toolkit for OpenVMS web site at http://www.hp.com/products/openvms/webservices/.
The Web Service
Integration Toolkit for OpenVMS (WSIT) contains a collection of integration
tools. These tools are easy to use, highly extensible, based on standards and
built on open source technology. The
toolkit can be used to call OpenVMS applications written in 3GL languages, such
as C, BASIC, COBOL, FORTRAN, and ACMS from newer technologies and languages
such as Java, Microsoft .NET, Java -RMI, JMS, and web services.
The Web Service
Integration Toolkit is focused on integrating at the API level. It generates a
JavaBean wrapper for a supplied OpenVMS application interface (API). At
runtime, you can specify if the application will be run in the process of the
caller (in-process) or in separate processes (out-of-process) managed by the
WSIT runtime.
1.2 Preparing
the Original (Legacy) Application
Using the Web Services Integration
Toolkit for OpenVMS, as with all programmatic integration, requires some
upfront development work before you can begin performing the integration. Your
existing application is likely to have been written long ago and will benefit
from having a wrapper expose a new
and clean interface. The new interface will expose the legacy implementation.
Separating the interface from the implementation provides encapsulation and the
ability to easily extend and reuse the implementation.
Before you use the Web Services
Integration Toolkit or any other integration technology, you must evaluate the
original application and design one or
more interface classes to expose different features of the business logic.
These new interfaces should be tested with a simple client before you use the
Web Services Integration Toolkit. When you know that the interface classes are
working properly, you can use WSIT to extend the use of the new interface to
the Java environment.
After you have prepared the application,
WSIT can extend the features of the new interface to Java as shown in the
following diagram.
1.3 Exposing
an OpenVMS 3GL Application: Typical Development Steps
Following are the development steps
required to use the Web Services Integration Toolkit to expose an OpenVMS 3GL or
ACMS application. Note that these steps are only required for the development
phase. It is expected that the application has been prepared as discussed in
the previous section.
Note: These tools were renamed in a pre-V1.0
field test kit. See Chapter 3 in the Installation Guide and Release Notes for
a table containing the old and new file names.
1.
Create XML IDL
file (on I64)
Create an XML interface definition file (IDL) that describes the
interface to be exposed. You create an
XML IDL file using the tool named OBJ2IDL.EXE
(for 3GL languages) or STDL2IDL.JAR
(for ACMS). Note: OBJ2IDL.EXE runs on
OpenVMS I64 only. If you are using WSIT
on OpenVMS Alpha, see Section 2.5.5 for information
about the HP TestDrive program.
2.
Validate XML
IDL file
Verify that the XML IDL file correctly
describes the interface being exposed. If it does not, manually update the XML
IDL file until the interface definition is correct. The VALIDATE.JAR allows you to verify that an XML IDL file conforms to
the openvms-integration.xsd schema.
3.
Generate
components
For the interface being exposed, generate
one WSIT server interface wrapper and one WSIT Java
Bean using IDL2CODE.JAR. The generated source code must be built on the
OpenVMS system that hosts the application.
4.
Use the
generated code
Call the generated WSIT JavaBean from the
technology of your choice, including BEA WLS, Apache Axis, JMS, Java RMI, J2EE
or another JavaBean.
The following steps demonstrate how
to wrap a 3GL application using the math sample program found in WSI$ROOT:[SAMPLES.C]. Other 3GL sample programs can be found in
WSI$ROOT:[SAMPLES.COBOL]
and WSI$ROOT:[SAMPLES.BASIC]. (See Section 1.5 for
information about a sample program that wraps an ACMS application.)
The
information in this section is also included in WSI$ROOT:[SAMPLES.C]MATH-SAMPLE.README.
Note: For demonstration
purposes only, the steps below use the wsi$root:[samples.c] directory
as the default
directory. HP recommends that you copy the contents of this directory into
your own local
directory before performing these steps.
The tool OBJ2IDL.EXE is used to generate an XML interface
definition.
Establish a
foreign command:
$
obj2idl = "$WSI$ROOT:[tools]obj2idl.exe"
Compile the
wrapper that exposes the new interface:
$ set
def WSI$ROOT:[samples.c]
$
cc/debug/noopt math.c
Note: Your code must be
compiled with the /DEBUG option for the OBJ2IDL parser to work properly.
Use OBJ2IDL to generate an XML file with the interface definition:
$
obj2idl -f WSI$ROOT:[samples.c]math.obj
The tool OBJ2IDL creates the file math.xml. See the Appendix for a full listing of math.xml.
You should become familiar with the XML description of OpenVMS
applications. Review the math.xml file
and notice the overall structure of the file. Following are the level 1 tags used
to define an interface. These
tags contain lower level tags and more information.
<OpenVMSInterface>
<Primitives></Primitives> Define the fundamental types
referenced in the interface.
<Routines></Routines> Define
the callable routines of the interface.
<Structures></Structures> Define the structures of the
interface.
<Typedefs></Typedefs> Define the type definitions of the interface.
</OpenVMSInterface>
Note: To view the XML file with coloring and a
collapsible outline, use Internet Explorer.
The OBJ2IDL tool is
sometimes unable to extract a complete interface definition from the supplied
object file. When the tool is missing data or has made assumptions, a comment
is placed in the XML file below the line of concern.
The file math.log is also generated from OBJ2IDL. Use this file to
conveniently see an overview of the comments within the XML file. (ACMS does
not create a .log file.)
$ ty
math.log
Generated
IDL file: WSI$ROOT:[samples.c]math.xml
Tue Apr
5 11:22:37 2005
In this case
the tool did not report any issues. However, even in cases where the log file
has not generated any error or warning, you should always review the XML file
to ensure that the interface definition is exactly correct. It is very
important that the XML IDL describe the interface accurately to generate
correct code in Step 3.
The validate.jar
tool is provided to allow you to verify that an XML IDL file conforms to
the openvms-integration.xsd schema. Use this tool to validate all XML IDL
files before they are passed to the IDL2CODE tool. The IDL2CODE tool does not validate the XML IDL file.
The validate tool is an executable JAR file. To run the
tool, you must supply two parameters: an XML IDL file and the openvms-integration schema. For example:
$ java
-jar wsi$root:[tools]validate.jar -x wsi$root:[samples.c]math.xml
–s
wsi$root:[tools]openvms-integration.xsd
Use the
tool IDL2CODE.JAR (also called the Generator) to create a
server wrapper for the application and a JavaBean client. This tool requires
certain JAR files to be in the Java classpath. A command procedure is supplied
to add these files to the java$classpath
logical.
(The java$classpath
logical
lets you define a class path using OpenVMS file specification syntax. Defining
this logical overrides the classpath logical, if set.)
$
@WSI$ROOT:[tools]wsi-setenv - wsi$dev
The New
JAVA$CLASSPATH is:
"JAVA$CLASSPATH"
= "WSI$ROOT:[LIB]WSIRTL.JAR" (LNM$JOB_86F82E00)
= "[]"
=
"WSI$ROOT:[LIB]VELOCITY-DEP-1_4.JAR"
=
"WSI$ROOT:[TOOLS]IDL2CODE.JAR"
$
To generate
files for the math demo, use the following command. In this case, the tool is passed the math.xml file and the application is named math. All
generated files for the application are placed in a subdirectory named generated.
$ create/dir
[.generated]
$ java
"com.hp.wsi.Generator" -i math.xml -a math -o [.generated]
File:
./generated/mathServer/build-math-server.com generated.
File: ./generated/mathServer/methIds.h
generated.
File: ./generated/mathServer/structkeys.h generated.
File: ./generated/mathServer/math.wsi generated.
File: ./generated/mathServer/math.opt generated.
File: ./generated/mathServer/math-server.h generated.
File: ./generated/mathServer/math-server.c generated.
File: ./generated/math/build-math-jb.com generated.
File: ./generated/math/Imath.java generated.
File: ./generated/math/mathImpl.java generated.
*** Application math generated! ***
$
Build the
server:
This command
procedure installs the server image after it has been built. This requires writing to the WSI$ROOT:[DEPLOY] directory, which may be write protected on your
system. (This is a security measure. Have your system manager assist you if
your account does not have the required privileges.)
$ set def
WSI$ROOT:[samples.c.generated.mathserver]
$
@BUILD-MATH-SERVER
Begin server
build procedure.
..configuring
switches and compiler options
..compiling
native server code
..linking
shareable image
..installing
server image
End server build
procedure.
$
Build the
client:
The JavaBean
build procedure creates a JAR file that contains the WSI Java classes used to call
the server created earlier.
$ SET DEF
WSI$ROOT:[samples.c.generated.math]
$ @BUILD-MATH-JB
Begin java bean
build procedure.
The New
JAVA$CLASSPATH is:
"JAVA$CLASSPATH" =
"WSI$ROOT:[LIB]WSIRTL.JAR" (LNM$JOB_86D5AE00)
= "[]"
=
"WSI$ROOT:[LIB]VELOCITY-DEP-1_4.JAR"
=
"WSI$ROOT:[TOOLS]IDL2CODE.JAR"
..Compiling
structure classes
..Compiling math
Interface classes
..Creating
math.JAR file from classes
End of JavaBean
build procedure.
You can run the math sample program in-process or
out-of-process. In-process means that the application will be run in the
process of the caller. (Follow the instructions in step 5b instead of 5a if you
want to run the sample out-of-process.)
Add the math.jar file to the java$classpath.
$ @WSI$ROOT:[tools]wsi-setenv –
WSI$ROOT:[samples.c.GENERATED.math]math.jar
The New
JAVA$CLASSPATH is:
"JAVA$CLASSPATH"
= "WSI$ROOT:[LIB]WSIRTL.JAR" (LNM$JOB_86F82E00)
= "[]"
=
"WSI$ROOT:[LIB]VELOCITY-DEP-1_4.JAR"
=
"WSI$ROOT:[TOOLS]IDL2CODE.JAR"
=
"WSI$ROOT:[SAMPLES.C.GENERATED]MATH.JAR"
$
In
the normal course of development, you would now need to write a JavaBean to
call the math JavaBean that was generated above. However, for the purpose of
this demonstration, a JavaBean file named mathcaller.java
is provided in the directory WSI$ROOT:[samples.c].
See the Appendix for a source listing of this file.
Compile the supplied JavaBean:
$ set def
WSI$ROOT:[samples.c]
$ javac
mathcaller.java
Run the supplied JavaBean:
$ java mathcaller
Sum of 10 and 15
is 25
Product of 10 and
15 is 150
$
You can run the
math sample program either in-process or
out-of-process. Out-of-process means that the sample will be run in a separate
process managed by the WSIT runtime. (Follow the instructions in step 5a
instead of 5b if you want to run the sample in-process.)
Add the math.jar file to the java$classpath.
$ @WSI$ROOT:[tools]wsi-setenv -
WSI$ROOT:[samples.c.GENERATED.math]math.jar
The New
JAVA$CLASSPATH is:
"JAVA$CLASSPATH"
= "WSI$ROOT:[LIB]WSIRTL.JAR" (LNM$JOB_86F82E00)
= "[]"
=
"WSI$ROOT:[LIB]VELOCITY-DEP-1_4.JAR"
=
"WSI$ROOT:[TOOLS]IDL2CODE.JAR"
=
"WSI$ROOT:[SAMPLES.C.GENERATED.MATH]MATH.JAR"
$
In the normal course of development, you
would now need to write a JavaBean to call the math JavaBean that was generated above.
However, for the purpose of this demonstration, a JavaBean file named mathcaller.java is provided in the directory WSI$ROOT:[samples.c]. See the Appendix for a source listing
of this file.
To run the math sample out-of-process, make the following
changes to mathcaller.java:
·
Call a different constructor
·
Call remove when done with server
These changed lines
are underlined in the following listing of mathcaller.java.
$ type
mathcaller.java
import math.*;
import java.io.*;
import com.hp.wsi.WsiIpcContext;
public class
mathcaller {
/** Creates a new
instance of
public
mathcaller() {
}
public static
void main(String[] args) {
try {
mathImpl math = new mathImpl(new
WsiIpcContext());
int num1 = 10;
int num2 = 15;
int result;
result = math.sum(num1, num2);
System.out.println("Sum
of " + num1 + " and " + num2 + "is " + result);
result = math.product(num1, num2);
System.out.println("Product
of " + num1 + " and " + num2 + "is " + result);
math.remove();
} catch
(Exception e) {
System.out.println("Exception
thrown");
}
}
}
Important: Review WSI$ROOT:[DEPLOY]MATH.WSI. By default, the deployment configuration file is the
most restrictive. It assumes the application is not reusable, therefore it
needs a new server process for every client.
After evaluating your application, you can modify math.wsi to scale the deployment configuration for the
application. See Chapter 2, Deployment Considerations, for more information.
Compile the
supplied JavaBean:
$ set def
WSI$ROOT:[samples.c]
$ javac
mathcaller.java
Run the
supplied JavaBean:
$ java mathcaller
Sum of 10 and 15 is
25
Product of 10 and
15 is 150
$
1.4.1 Server/Application Build
Procedure
The Web Services Integration Toolkit
generates a command procedure to build a server. The generated command procedure, named build-<appname>-server.com, creates a shareable image named <appnam>.exe and copies it to the deployment directory WSI$ROOT:[DEPLOY].
The WSIT runtime loads this shareable image to process requests from the
WSIT generated JavaBean.
The shareable image <appnam>.exe is composed of three parts:
·
The
object file provided by the user (in the XML IDL file) to expose the
application interface. For example, wsi$root:[samples.c]math.obj located in wsi$root:[samples.c]math.xml.
·
A
WSIT object file named <appname>-server.obj which exposes the application interface with a set
of fixed WSIT entry points. The source file for this object file is <appname>-server.c.
·
A
WSIT shareable image containing common reusable procedures. This shareable image is named SYS$LIBRARY:WSI$COMMON.EXE.
This
shareable image must provide entry points for the WSIT runtime to call. The entry points for all WSIT applications are
always the same. The entry points are as
follows:
Symbol Name Symbol
Type
WSI$INIT PROCEDURE
WSI$EXIT PROCEDURE
WSI$START_SESSION PROCEDURE
WSI$END_SESSION PROCEDURE
WSI$ACMS_SIGN_IN PROCEDURE
WSI$ACMS_SIGN_OUT PROCEDURE
WSI$VMS_LOGIN PROCEDURE
WSI$VMS_LOGOUT PROCEDURE
WSI$INVOKE PROCEDURE
WSI$INVOKE_DCL PROCEDURE
WSI$GET_FILE PROCEDURE
WSI$INFO_BLOCK DATA
WSI$DCL_PROC_MAPS DATA
WSI$FILENAME_MAPS DATA
1.4.2 Customizing
the Build Environment
In
the default behavior described in the preceding section, the application’s
interface object module is expected to process the requests without calling
others modules. While this approach
allows WSIT applications to be quickly prototyped, it is obviously not
sufficient for “real” applications.
The
application being wrapped will almost always be composed of many object
modules, object libraries, and/or shareable images. These object modules need
to be packaged into a shareable image that includes the WSIT files described
above.
You
can package the object modules in two ways, as follows:
·
Add
the few WSIT build elements to the existing application’s build environment. (This is the recommended method.)
·
Add
the application files to the WSIT server build command procedure.
If
you choose the recommended option above, the file <appname>.opt provides an overview of the files and entry points
that must be added to the new application’s shareable image.
If
you decide to integrate the WSIT files into your application, remember that the
application must be built as a shareable image named <appnam>.exe and must be copied to the WSIT deployment directory WSI$ROOT:[DEPLOY].
On the OpenVMS system on which you
installed WSIT, log in using an account with SYSTEM privileges.
Create a directory to set up the
application. For example:
$ create /dir [.acmsgenerated]
Set default to the newly created
directory:
$ set def [.acmsgenerated]
Execute the following command:
$
@WSI$ROOT:[samples.acms]acmsexample_setup.com
This assumes that the ACMS$EXAMPLES logical is
present and correct on your system.
This DCL script does the following:
·
Creates a local data dictionary for this
application
·
Defines a CDD (common dictionary data) record
(using the supplied .CDO files)
·
Defines a CDD entry task
·
Builds the application, generating a STDL file
(used to import ACMS task and structure definitions)
·
Starts the ACMS application
When prompted for a CDD directory, you
can press Enter to accept the default (which will be under the directory you
just created and set default to), or you may choose another name or location.
For example:
CDD Directory?
DKA100:[USER.ACMSGENERATED.DICTIONARY] :
The sample application is set up and
started when you see the following:
%ACMSINS-S-ADBINS, Application
DISK:[USER.ACMSGENERATED]EMPLOYEE_INFO_APPL_BWX.ADB;
has been installed to ACMS$DIRECTORY
Use the STDL2IDL.JAR tool to
generate an XML interface definition (IDL file) from the STDL file generated in
Step 1.
Run the STDL2IDL importer:
$ java -classpath WSI$ROOT:[TOOLS]stdl2idl.jar
"com.hp.wsi.Import"
-a AcmsApp -f
EMPLOYEE_INFO_APPL_WSI.STDL
Import File was successfully processed.
File: ./acmsapp2_idl.xml generated.
*** Files for Application acmsapp2
successfully generated! ***
Because STDL files completely describe
the ACMS application, the STDL2IDL tool is able to use the STDL file to
create a complete WSIT interface definition representation of that ACMS
application. However, even if the STDL2IDL tool specifies that the IDL generation
was successful, you should review and validate the generated XML file to ensure
complete accuracy. The XML IDL must accurately describe the interface to
generate correct code in Step 4.
For this reason, WSIT includes the validate.jar tool to allow
you to verify that an XML IDL file conforms to the openvms-integration.xsd schema before
it is passed to the IDL2CODE.JAR tool. (The IDL2CODE.JAR tool does not
validate the XML IDL file.) To run the validate.jar tool, supply two
parameters: an XML IDL file and the openvms-integration schema. For
example:
$ java -jar wsi$root:[tools]validate.jar
-x wsi$root:[samples.acms]AcmsApp_idl.xml
-s wsi$root:[tools]openvms-integration.xsd
Use the IDL2CODE.JAR tool to create
a server wrapper for the application and a JavaBean client. This tool requires
certain Jar files to be in the Java classpath. A command procedure is supplied
to add these files to the java$classpath logical.
$ @WSI$ROOT:[tools]wsi-setenv - wsi$dev
The New JAVA$CLASSPATH is:
"JAVA$CLASSPATH" =
"WSI$ROOT:[LIB]WSIRTL.JAR" (LNM$JOB_86F82E00)
= "[]"
=
"WSI$ROOT:[LIB]VELOCITY-DEP-1_4.JAR"
=
"WSI$ROOT:[TOOLS]IDL2CODE.JAR"
$
To generate files for the ACMS sample, use
the following command. In this case we pass the tool the AcmsApp_idl.xml file
(generated above) and we call the application AcmsApp. We also place
all generated files for the application in a subdirectory named generated.
$ create/dir [.generated]
$ java "com.hp.wsi.Generator"
-i AcmsApp_idl.xml -a AcmsApp -o
[.generated]
File:
./generated/acmsapp_server/build-acmsapp-server.com generated.
File:
./generated/acmsapp_server/methIds.h generated.
File:
./generated/acmsapp_server/structkeys.h generated.
File:
./generated/acmsapp_server/acmsapp.wsi generated.
File:
./generated/acmsapp_server/acmsapp.opt generated.
File:
./generated/acmsapp_server/acmsapp-server.h generated.
File:
./generated/acmsapp_server/acmsapp-server.c generated.
File: ./generated/acmsapp_server/build-acmsapp-jb.com
generated.
File: ./generated/acmsapp/Iacmsapp.java
generated.
File:
./generated/acmsapp/acmsappImpl.java generated.
File:
./generated/acmsapp/CONTROL_WORKSPACE.java generated.
File:
./generated/acmsapp/EMPLOYEE_INFO_WKSP.java generated.
*** Application acmsapp generated! ***
$
Build
the server:
The server build procedure links the
generated server files with the user's application, which creates a dynamically
loadable sharable image.
$ set def [.generated]
$ @BUILD-ACMSAPP-SERVER
Begin server build procedure.
..configuring switches and compiler
options
..compiling native server code
..linking shareable image
..installing server image
End server build procedure.
$
Build
the client:
The JavaBean build procedure creates a JAR
file that contains the WSIT Java classes used to call the server created
earlier.
$ @BUILD-ACMSAPP-JB
Begin Java bean build procedure.
The New JAVA$CLASSPATH is:
"JAVA$CLASSPATH" =
"WSI$ROOT:[LIB]WSIRTL.JAR" (LNM$JOB_86F82E00)
= "[]"
= "WSI$ROOT:[LIB]VELOCITY-DEP-1_4.JAR"
=
"WSI$ROOT:[TOOLS]IDL2CODE.JAR"
..Compiling structure classes
..Compiling acmsapp Interface classes
..Creating acmsapp.JAR file from classes
End of JavaBean build procedure.
Add the AcmsApp.jar file to the java$classpath.
$ @WSI$ROOT:[tools]wsi-setenv - acmsapp.jar
The
new JAVA$CLASSPATH is:
"JAVA$CLASSPATH"
= "WSI$ROOT:[LIB]WSIRTL.JAR" (LNM$JOB_86F82E00)
= "[]"
=
"WSI$ROOT:[LIB]VELOCITY-DEP-1_4.JAR"
= "WSI$ROOT:[TOOLS]IDL2CODE.JAR"
= "ACMSAPP.JAR"
$
In the normal course of development, you would now
need to write a client to call the AcmsApp JavaBean that was generated above. However, for the purpose of this
sample, a client file named acmscaller.java is provided in the directory WSI$ROOT:[samples.acms].
Compile the supplied client:
$ set def
WSI$ROOT:[samples.acms]
$ javac acmscaller.java
Run the supplied
client:
$ java acmscaller
******* Creating JavaBean & Server **********
************ Calling AcmsSignIn ***************
***** Calling add and get empl_info tasks ******
************ Calling AcmsSignOut ***************
123456
John Adams
1 Beacon Hill
Boston
MA
01776
******** Removing the JavaBean & Server *********
*********** End ACMS Client *************
$
The output from the Java program shows the code that
the client is executing, as well as the calls that it is making into ACMS. The data displayed was first entered into an
Rdb database via ACMS, then retrieved using ACMS for display purposes.
Beginning in Web Services Integration Toolkit Version 1.1, a new
optional switch –c is provided to tell the WSIT generator (IDL2CODE) to generate a sample client with a
command line interface (S) or generate a sample client with a JSP interface
(J). These samples are provided to make
testing and development with WSIT easier.
Specifying –c S generates only the POJO (Plain Old Java Object)
command line client. Specifying –c
J generates only the JSP client, and –c SJ
generates both kinds of clients.
For
example, to generate sample clients for the C math application from Section
1.4, follow the same sequence of
steps from 1 to 4. At step 3, however, pass in the additional switch shown
below.
Note: WSIT generated JSP
samples require a server environment that supports the JSP V2.0. Examples
include Tomcat 5.5.9 and WebLogic Server V9.0.
$ java "com.hp.wsi.Generator"
-i math.xml -a math -c SJ -o [.generated]
File:
./generated/mathServer/build-math-server.com generated.
File: ./generated/mathServer/methIds.h
generated.
File:
./generated/mathServer/structkeys.h generated.
File: ./generated/mathServer/math.wsi
generated.
File: ./generated/mathServer/math.opt
generated.
File:
./generated/mathServer/math-server.h generated.
File:
./generated/mathServer/math-server.c generated.
File: ./generated/math/build-math-jb.com
generated.
File: ./generated/math/Imath.java
generated.
File: ./generated/math/mathImpl.java
generated.
File:
./generated/mathSamples/POJO/mathMain.java generated.
File:
./generated/mathSamples/POJO/build-math-PoJoClient.com generated.
File:
./generated/mathSamples/JSP/index.html generated.
File: ./generated/mathSamples/JSP/mathMethodList.html
generated.
File:
./generated/mathSamples/JSP/mathPopulate.jsp generated.
File:
./generated/mathSamples/JSP/mathDoCall.jsp generated.
File:
./generated/mathSamples/JSP/build-math-JspClient.com generated.*** Application
math generated! ***
$
Using the generated POJO client sample:
Normally
this class will be written to integrate the WSIT generated JavaBean with the
Java technology of your choice.
The
sample must first be built as shown below.
$ @wsi$root:[tools]wsi-setenv -
WSI$ROOT:[samples.c.generated.math]math.jar
$ set default
WSI$ROOT:[samples.c.generated.mathSamples.POJO]
$ @build-math-PoJoClient
Begin client build procedure.
..Compiling mathMain client class
End of client build procedure.
To run this client, type the following
at the command line:
$ java "math.mathMain"
The sample client is able to make calls
to the methods of the generated JavaBean. There is a limitation that only
methods with primitive arguments can be called. To see which methods the sample
client can call, use the switch –m as shown below.
$ set default
WSI$ROOT:[samples.c.generated.mathSamples.POJO]
$ java math.mathMain -m
The list of available methods within math are:
sum(int P1, int P2)
product(int P1, int P2)
(Methods that take structures or arrays
as parameters are not callable from this command line interface. These methods are denoted by the * next to
them.)
$
To
call the sum and product methods with arguments of 5 and 2, use the commands as
shown below.
$
set default WSI$ROOT:[samples.c.generated.mathSamples.POJO]
$ java math.mathMain -m sum -p1 5 -p2 2
Calling mathImpl.sum:
P1 = 5
P2 = 2
Return value = 7
++ The client was successful ++
$ java math.mathMain -m product -p1 5
-p2 2
Calling mathImpl.product:
P1 = 5
P2 = 2
Return value = 10
++ The client was successful ++
$
Using the generated JSP client sample:
Similar
to the POJO sample, the JSP sample client must first be built as shown below.
$ @wsi$root:[tools]wsi-setenv –
WSI$ROOT:[samples.c.generated.math]math.jar
$ set default
WSI$ROOT:[samples.c.generated.mathSamples.JSP]
$ @build-math-JSPClient
Begin JSP client build procedure.
Unpacking static files into current
location.
Copying math.jar into local
[.WEB-INF.lib] directory
Creating mathJsp.war file
End of JSP client build procedure.
To deploy this client:
Copy mathJsp.War into the deployment
directory for your JSP server.
$
To deploy the JSP, copy the mathJsp.war file to a web server servlet deployment directory.
For example, if you have installed Tomcat (CSWS_JAVA) on OpenVMS, the command
is similar to the following:
$ copy mathJSP.war
sys$common:[apache.jakarta.tomcat.webapps]
After the war file has been copied,
you can view the JSP pages by using a URL similar to the one shown below.
(Replace yourwebserver.hp.com with the actual name of your web server.) By default, Tomcat listens on port 8080. If
the system manger changed the port number, replace 8080 with the new number.
$ copy mathJSP.war sys$common:[apache.jakarta.tomcat.webapps]
Note: Web applications deployed as
Java classes are seen and used immediately, but web applications deployed as
JAR files may require a Tomcat restart in order for them to be seen and used. For information about restarting Tomcat, see
the CSWS_JAVA (Tomcat) for OpenVMS documentation at http://h71000.www7.hp.com/openvms/products/ips/apache/csws_java_relnotes.html
Note: By default, the generated clients
run in-process. See Section 1.4
for changes you will need to
make to run out-of-process.
The following screen captures illustrate
the JSP sample client calling the C Math application.
Example
Web Page 1: The mathJSP Application
Example Web Page 2: The MathJSP
Application Methods
Example Web
Page 3: The MathJSP Application Method Product
Example Web Page 4: The MathJSP Application Method Product Results
1.7 Using ANT with the Web Services Integration Toolkit
The Web Services Integration Toolkit
Version 1.1 provides the capability to use Ant to automate the
tasks for
exposing your application (described in Section 1.4). Ant is a powerful Java-based build
tool that is an
open source Apache project. Ant is
platform independent and highly extendable.
The build
scripts are XML files containing targets and specifying tasks and properties.
For more information
about Ant, see the web site for the Apache Ant Project at
http://ant.apache.org and the Ant Manual at http://ant.apache.org/manual/index.html.
1.7.1 Ant Setup
The Web Services Integration Toolkit Version 1.1 includes
its own binary distribution of Ant 1.6.5.
To set up Ant, establish the foreign command by entering the following command:
$ ant == “@WSI$ROOT:[tools.ant]ant.com”
1.7.2 Configuring the wsit-ant-user.properties File
Before you run Ant to build your application,
you must configure the wsit-ant-user.properties
file by specifying a set of property values. Perform the following steps to
complete the configuration:
1.
Copy the wsit-ant-user.properties file from WSI$ROOT:[tools.ant] to your local directory where you will be
running the Ant build procedure.
2.
Set the application
type
property to be one of the following, based on the kind of application you are
building:
3GL.with.OBJ
3GL.with.IDL
ACMS.with.STDL
For detailed Ant property descriptions, see Section 1.7.4.
3.
Specify values for all required properties for
the kind of application you are building, in the section marked “BEGIN properties
for …”.
4.
Specify values for properties in the section
“BEGIN COMMON properties to customize.”
1.7.3 Using the wsit-ant-userbuild.xml Build File
After you have
configured the properties, you can build the full WSIT application and any
generated sample
clients by
copying the wsit-ant-userbuild.xml file from wsi$root:[tools.ant] to your local
directory and executing the following command:
$ ant "-f wsit-ant-userbuild.xml"
Buildfile: wsit-ant-userbuild.xml
checkinput:
[echo] Verifying properties ...
getidl:
[echo] Calling obj2idl ...
obj2idl:
[echo] Creating XML IDL file ...
[obj2idl] WSIT IDL Generator version
is: V1.0
validate:
[echo] Validating XML IDL file ...
[java] XML file validated successfully
idl2code:
[idl2code] %WSI-I-GENCREOUT, The
specified Output directory does not exist,
creating /WSI$ROOT/samples/c/generated
[idl2code] %WSI-I-GENCREOUT, The
specified Package directory does not exist,
creating /WSI$ROOT/samples/c/generated/math
[idl2code] %WSI-I-GENCREOUT, The
specified Server directory does not exist,
creating /WSI$ROOT/samples/c/generated/mathServer
[idl2code] %WSI-I-GENCREOUT, The
specified Samples directory does not exist, creating
/WSI$ROOT/samples/c/generated/mathSamples
[idl2code] File:
/WSI$ROOT/samples/c/generated/mathServer/build-math-server.com generated.
[idl2code] File:
/WSI$ROOT/samples/c/generated/mathServer/methIds.h generated.
[idl2code] File:
/WSI$ROOT/samples/c/generated/mathServer/structkeys.h
generated.
[idl2code] File:
/WSI$ROOT/samples/c/generated/mathServer/math.wsi generated.
[idl2code] File:
/WSI$ROOT/samples/c/generated/mathServer/math.opt generated.
[idl2code] File:
/WSI$ROOT/samples/c/generated/mathServer/math-server.h generated.
[idl2code] File:
/WSI$ROOT/samples/c/generated/mathServer/math-server.c generated.
[idl2code] File:
/WSI$ROOT/samples/c/generated/math/build-math-jb.com generated.
[idl2code] File:
/WSI$ROOT/samples/c/generated/math/Imath.java generated.
[idl2code] File: /WSI$ROOT/samples/c/generated/math/mathImpl.java
generated.
[idl2code] %WSI-I-GENCREOUT, The
specified directory does not exist, creating
/WSI$ROOT/samples/c/generated/mathSamples/POJO
[idl2code] File:
/WSI$ROOT/samples/c/generated/mathSamples/POJO/mathMain.java generated.
[idl2code] File:
/WSI$ROOT/samples/c/generated/mathSamples/POJO/build-math-PoJoClient.com
generated.
[idl2code] %WSI-I-GENCREOUT, The
specified directory does not exist, creating
/WSI$ROOT/samples/c/generated/mathSamples/JSP
[idl2code] File:
/WSI$ROOT/samples/c/generated/mathSamples/JSP/index.html generated.
[idl2code] File:
/WSI$ROOT/samples/c/generated/mathSamples/JSP/sessiontimeout.html generated.
[idl2code] File:
/WSI$ROOT/samples/c/generated/mathSamples/JSP/mathMethodList.jsp generated.
[idl2code] File:
/WSI$ROOT/samples/c/generated/mathSamples/JSP/mathPopulate.jsp generated.
[idl2code] File:
/WSI$ROOT/samples/c/generated/mathSamples/JSP/mathDoCall.jsp generated.
[idl2code] File:
/WSI$ROOT/samples/c/generated/mathSamples/JSP/mathVerify.jsp generated.
[idl2code] File:
/WSI$ROOT/samples/c/generated/mathSamples/JSP/build-math-JspClient.com
generated.
[idl2code] %WSI-I-GENCREOUT, The
specified directory does not exist, creating
/WSI$ROOT/samples/c/generated/mathSamples/JSP/WEB-INF
[idl2code] File:
/WSI$ROOT/samples/c/generated/mathSamples/JSP/WEB-INF/web.xml generated.
[idl2code] *** Application math
generated! ***
buildserver:
[echo] Building server ...
[echo]
/WSI$ROOT/samples/c/generated/mathServer
[echo] @build-math-server.com
[exec] Begin server build procedure.
[exec] ..configuring switches and compiler options
[exec] ..compiling native server code
[exec] ..linking shareable image
[exec] ..installing server image
[exec] End server build procedure.
buildjavabean:
[echo] Building Java Bean ...
[exec] Begin java bean build
procedure.
[exec] ..Compiling structure classes
[exec] ..Compiling math Interface classes
[exec] ..Creating math.JAR file from classes
[exec] End of JavaBean build
procedure.
buildpojoclient:
[echo] Building Sample POJO Client
...
[javac] Compiling 1 source file to
WSI$ROOT/samples/c/generated/mathSamples/POJO
[jar] Building jar:
WSI$ROOT/samples/c/generated/mathSamples/POJO/mathClient.jar
[echo]
[echo] To run this client, type the following
commands:
[echo]
[echo] $ @wsi$root:[tools]wsi-setenv
- wsi$dev
[echo] $ @wsi$root:[tools]wsi-setenv
- /WSI$ROOT/samples/c/generated/math/math.jar
[echo] $ @wsi$root:[tools]wsi-setenv
- /WSI$ROOT/samples/c/generated/mathSamples/POJO/mathClient.jar
[echo] $ java
"math.mathMain"
[echo]
buildjspclient:
[echo] Building Sample JSP Client
...
[exec] Begin JSP client build
procedure.
[exec] Unpacking static files into
current location.
[exec] Copying math.jar into local
[.WEB-INF.lib] directory
[exec] Creating mathjsp.war file
[exec] End of JSP client build
procedure.
[exec] To deploy this client:
[exec] Copy
WSI$ROOT:[SAMPLES.C.GENERATED.MATHSAMPLES.JSP]mathjsp.war nto the deployment
[exec] directory for your JSP
server.
buildall:
[echo]
[echo] Completed building the math application
...
[echo]
BUILD SUCCESSFUL
Total time: 1 minute 1 second
$
To run a specific target only (for example, the
help target), execute the following command in the directory where the build file
is located. (For detailed target descriptions, see Section 1.7.5.)
Note: The file wsit-ant-userbuild.xml cannot be used with versions of WSIT earlier than V1.1.
$ ant
"-f wsit-ant-userbuild.xml help"
Buildfile: wsit-ant-userbuild.xml
help:
[echo]
[echo] [echo] Most useful targets:
[echo]
[echo] buildall : Executes all of the targets in this
build file.
[echo]
obj2idl : Creates IDL file from
the 3GL application's object module
(IA64 only).
[echo]
stdl2idl : Creates IDL file from
the ACMS application's STDL file.
[echo]
validate : Verifies the
application's IDL file conforms to the
schema.
[echo]
idl2code : Creates a WSIT server
interface wrapper, a WSIT Java Bean
and sample
client code.
[echo]
buildserver : Builds a sharable image
by linking the WSIT server wrapper
with the
application.
[echo]
buildjavabean : Creates a jar file that
contains the WSI Java classes to
call the
server.
[echo]
buildpojoclient : Builds the generated
POJO client code to call the
application.
[echo]
buildjspclient : Builds the generated
JSP client code to call the
application.
[echo] Note: You will need to
customize your property values in wsit-ant-user.properties before running ant
[echo]
BUILD SUCCESSFUL
Total time: 2
seconds
$
1.7.4 Ant Property Descriptions
Required: Set the
apptype property, which specifies application type, to
one of the following values:
3GL.with.OBJ
3GL.with.IDL
ACMS.with.STDL
Name |
Description |
Value of apptype |
|
A
3GL application based on an object (OBJ) file, compiled DEBUG (I64 only, not
supported on Alpha). |
3GL.with.OBJ |
apptype |
A
3GL application based on an IDL file that you have already written or
generated. |
3GL.with.IDL |
|
An ACMS application
based on the application's STDL file. |
ACMS.with.STDL |
Properties
for applications of type 3GL.with.OBJ. Required if apptype is set
to 3GL.with.OBJ.
Name |
Description |
Value (example) |
obj.file |
Specific
location and name of object file (compiled debug) from which WSIT will
generate IDL. |
/disk$ods5/math/source/math.obj |
idl.file |
Specific
location and name of idl file that WSIT will generate using the target OBJ2IDL. |
/disk$ods5/math/source/math.xml |
Properties
for applications of type 3GL.with.IDL. Required if apptype is set
to 3GL.with.IDL.
Name |
Description |
Value (example) |
idl.file |
Specific
location and name of idl file that WSIT will use to generate a JavaBean
wrapper. |
/disk$ods5/math/source/math.xml |
Properties
for applications of type ACMS.with.STDL. Required if apptype is set
to ACMS.with.STDL.
Name |
Description |
Value (example) |
Stdl.file |
Specific
location and name of ACMS STDL file from which WSIT will generate IDL. |
/disk$ods5/math/source/math.stdl |
idl.file |
Specific
location and name of idl file that WSIT will generate using the target STDL2IDL. |
/disk$ods5/math/source/math.xml |
Common
properties for all types of applications. (Required)
Name |
Description |
Value (example) |
appname |
Specify
your application name. |
Math |
build.dir |
Specifiy
the root of a directory that WSIT should use when generating code. |
/disk$ods5/math/generated |
Common
properties for all types of applications. (Optional)
Name |
Description |
Value (actual) |
sample.POJO |
Specify
if sample POJO client that illustrates how to call the WSIT generated JavaBean
should be generated. |
True/False |
sample.JSP |
Specify
if sample JSP client that illustrates how to call the WSIT generated JavaBean
should be generated. |
True/False |
1.7.5 Ant Target Descriptions
Name |
Description |
buildall |
Executes all
of the targets in this build file. |
Obj2idl |
Creates
IDL file from the 3GL application's object module (IA64 only). |
Stdl2idl |
Creates
IDL file from the ACMS application's STDL file. |
validate |
Verifies
the application's IDL file conforms to the schema. |
idl2code |
Creates
a WSIT server interface wrapper, a WSIT Java Bean and sample client code. |
buildserver |
Builds
a sharable image by linking the WSIT server wrapper with the application. |
buildjavabean |
Creates
a jar file that contains the WSI Java classes to call the server. |
buildpojoclient |
Builds
the generated POJO client code to call the application. |
buildjspclient |
Builds
the generated JSP client code to call the application. |
checkinput |
Verifies
all properties have been correctly set. |
getidl |
Determines
if IDL file exists, if not calls appropriate target to generate it, and then
validates it. |
Help |
Displays help information. |
WSIT defines custom ant tasks for the IDL2CODE, OBJ2IDL, and STDL2IDL tools.
1.7.6.1 IDL2CODE Task
Runs
the Generator (IDL2CODE) to create a server wrapper for the application
and a JavaBean client.
1.7.6.2 IDL2CODE Parameters
Attribute
|
Description
|
Type
|
idlfile |
Required.
Filespec for XML IDL file describing the application to wrap. |
java.lang.String |
appname |
Required.
Name to be given to the WSIT generated application. |
java.lang.String |
outdir |
Optional.
Directory in which to generate the wrapper files. |
java.lang.String |
authenticate |
Optional.
Force OpenVMS authentication to be used with this interface. |
boolean |
javadoc |
Optional.
Create JavaDoc based documentation for the generated interface. |
boolean |
tracinglevel |
Optional.
Ouput tracing information at runtime, specify level 1 to 5. |
int |
samplePOJO |
Optional.
Generate sample POJO client for the generated interface. |
boolean |
sampleJSP |
Optional.
Generate sample JSP client for the generated interface. |
boolean |
1.7.6.3 OBJ2IDL Task
Runs
the OBJ2IDL tool to generate an XML interface definition
from a 3GL application’s object module (I64 only).
1.7.6.4 OBJ2IDL Parameters
Attribute
|
Description
|
Type
|
objfile |
Required.
Filespec for the object module. |
java.lang.String |
outfile |
Optional.
Filespec for XML IDL output file. |
java.lang.String |
mapfile |
Optional.
Filespec for map file, default is wsi$root:[tools]openvms-basetypes.xml. |
java.lang.String |
version |
Optional.
Display version information for this tool. |
boolean |
1.7.6.5 STDL2IDL Task
Runs
the STDL2IDL tool to generate an XML interface definition
from an ACMS application’s STDL file.
1.7.6.6 STDL2IDL Parameters
Attribute
|
Description
|
Type
|
stdlfile |
Required.
Name of the STDL file to parse. |
java.lang.String |
idlfile |
Optional.
Filespec for XML IDL output file (relative paths are not supported). |
java.lang.String |
version |
Optional.
Display version information for this tool. |
boolean |
With the Web Services Integration Toolkit Version 1.1 and
Distributed NetBeans for OpenVMS Version 1.1 working together, you can do the
following:
·
Edit text files
generated by the WSIT tools using Distributed NetBeans and a remote FTP
filesystem
·
Remotely compile
your language source files
·
Remotely execute DCL
command procedures
·
Remotely execute Ant
scripts
For more information about remote operations and Distributed
NetBeans in general, see the Distributed NetBeans online help. The online help is available when you install
Distributed NetBeans on your desktop system, and from http://h71000.www7.hp.com/openvms/products/ips/netbeans/documents.html
The WSIT Build Template files are included with Distributed
NetBeans so that you can use the NetBeans template system to create your WSIT
build script and property file from within Distributed NetBeans. To create your WSIT Ant build script and
property file using the template, perform the following steps:
1.
Select the remote
directory in the filesystem explorer where you would like to place the build
template, right mouse click and select New/All Templates.
2.
Select WSIT
Templates/WSIT-Build Ant Script Files. Click Next.
3.
Name your script,
and click OK.
Two files are created in your directory: an Ant build script that is named according
to the previous step, and a property file named wsit-ant-user.properties. You must now customize the property file for
your application. Follow the instructions in the property file to
customize. In addition, you can
customize the Ant build script if desired.
Once you have completed your modifications to the build script and
property file for your application, you should modify the version of Ant that
will used to remote execute your Ant script.
1.8.2 Using the WSIT-Supplied Ant Version
In order to remote execute your WSIT Ant build script, you must
use the WSIT version of Ant when executing your build scripts. You can change the Ant executor in the Distributed NetBeans IDE to point to the WSIT
version of
1.
Select
Tools/Options.
2.
Open Debugging and
Execution/Execution Types/Remote Ant Script Execution.
3.
Select the […]
button to the right of the Remote
External Process property.
4.
Change the value of
the Process property to
pipe ant == "@WSI$ROOT:[tools.ant]ant.com" ; ant
5.
Click OK.
6.
Click Close on the Options
dialog box.
The
Web Services Integrated Toolkit provides an easy to use set of utilities that
can turn standalone applications into distributed applications, making them
more widely accessible. While this is great,
this new found accessibility may raise security concerns. Because of this, WSIT
implements 2 different ways of restricting access to a wrapped application
and/or the system resources that the application accesses.
Depending
on the environment and the granularity needed, you can either set a blanket
setting within the server process that all users are restricted to, or you can
force all users to login using their own account.
Each
is discussed below.
In an application environment where the application’s generated JavaBean and
server wrapper are run in two different processes, you can specify under which
OpenVMS account the server process is to run. You do this by modifying the <Account> attribute within the
deployment descriptor (.wsi file) associated with the application, as shown
in the following example. (The
deployment descriptors can be found in the WSI deployment directory, wsi$root:[deploy].)
<!--
Server Application Options -->
<Account>MyAccount</Account> <!-- Name
of the account the server runs in -->
Note: When the <Account></Account > property is not specified within
the application deployment configuration file (.wsi), WSIT runs the out-of-process servers in the same account
that the wsi$manager is running from. In most cases, this
is the SYSTEM account.
This
method of restricting access has an application level granularity. This means that all of the application’s
server processes run under the specified account. For example, you can set up the Payroll
application to always run under the Payroll account regardless who is
connecting to it.
The
server process method of restricting access has both pros and cons, as follows:
Reasons
to use server process security:
·
It is fast and easy to change during and after
deployment.
·
All users of a given application have the same
access to the system.
·
Requires no change to the client.
·
Users do not need their own account to use the
application.
Potential
problems with server process security:
·
Does not keep users from accessing the
application itself.
·
Makes no distinction between users.
·
Specified accounts require minimum privileges.
·
Requires the JavaBean and server wrapper to run
in two different processes.
1.9.2 Per User Security
If
you need to restrict access to the application itself, or need a finer
granularity in limiting access to system resources, you can do that by using
the optional per user security. You
choose this at generation time by specifying the –l (-L) switch on the IDL2CODE command line. When you specify this option,
WSIT generates an application with two additional methods in the interface, as
follows:
OpenVmsLogin (username, password)
OpenVmsLogout()
Applications
that have these methods in the interface can only be accessed after OpenVmsLogin()
has been successfully called. (The error
“Must login first” is returned until a successful login occurs.) After the user has successfully logged into an account, that account’s
privileges and quotas are used when calling into the application. This means that resources used by the
application can be protected on a per user basis.
The
per user method of restricting access has both pros and cons, as follows:
Reasons
to use per user security:
·
Distinguishes between users, allowing better
access control over resources.
·
Can block access to the application itself.
·
Works whether the JavaBean and server wrapper
are in the same process or different processes.
Potential problems with per user security:
·
Decision to use must be made at code generation
time.
·
Requires client to call Login and Logout
methods.
·
All users require an OpenVMS account in order to
access the application.
Applications running on OpenVMS systems can be roughly divided
into two groups, as follows:
·
Applications
designed for a single client environment
·
Applications
that can be called by multiple clients
The first group, applications
designed for a single client environment, are often older OpenVMS
applications that assume a timesharing runtime environment. The user logs into
the OpenVMS system, which in turn creates a process. The applications are
typically executed entirely in the user’s process. In this design, there is a single user (the
client). There is an assumed one-to-one relationship between the client and the
application.
The second group, applications
that can be called by multiple clients, are often newer OpenVMS applications.
These applications are designed to serially
process multiple clients (one at a time), or to concurrently process multiple clients (all at the same time).
When the Web Services Integration Toolkit exposes an OpenVMS
application as a JavaBean, the application becomes callable from the second
(newer) design model in which multiple clients can call the application from
multiple processes or threads. You should understand in which group your
wrapped application belongs (the specific design model) and manage client
access to the application accordingly. WSIT provides a number of features to
help in managing this interaction, which are discussed in the following
sections.
In the following sections, the term application is used to represent the original application being
exposed. The term client is used to
represent the JavaBean caller which makes calls to the WSIT-generated JavaBean.
There are two ways in which you can deploy your application using
WSIT: in-process deployment and out-of-process
deployment.
In-process deployment occurs when the application and the client are called from the same process, as
illustrated in the following diagram.
There are advantages and disadvantages to using in-process
deployment.
Advantages: Fastest return
time for client calls to application. No overhead added by the WSIT runtime.
Disadvantages: A crash will
bring down all components in the process (client and application).
There are no WSIT deployment settings for in-process applications
--
the interaction between the client and the application is not
managed by the WIST runtime. In-process deployment provides the fastest
execution time, but it requires that the developer ensure that the client does
not establish an environment in which the application will fail.
For example, some J2EE application servers may use multiple
threads to call the client. This requires that the developer determine if the
application can successfully operate in this environment. If the developer determines
that the application can only support one client at a time, then the client
must use a mechanism to order the calls
before they are sent to the application (via the WSIT-generated objects).
If you do not specify out-of-process deployment settings
(described in the following sections), your
application will run in-process by default.
Out-of-process deployment occurs when the client and application are run in different processes, as
illustrated in the following diagram. The WSIT runtime environment manages the
interaction between the two processes. You can customize this environment by
modifying a deployment descriptor file.
There are advantages and disadvantages to using out-of-process
deployment.
Advantages: Typically
scales better than in-process deployments. Allows the use of the WSIT runtime
deployment properties.
Disadvantages: Adds
complexity and overhead to every call.
Most older applications
benefit from using an out-of-process deployment to avoid complex issues that result from
mixing older and newer environments. The WSIT deployment properties, described
in the following sections, allow out-of-process applications to choose from a
wide variety of configurations.
A session is the period of time in which a client uses an
application. A session can last for:
·
The
duration of a single call
·
The
lifetime of the client
The type of session you use should mimic the original design of
the application. For example, in older timesharing applications, a session is
often the entire time that the client uses the application. In newer
applications, the client may use a session to perform a specific task and then
declare that it is finished with the session.
WSIT allows the developer to specify when a session with an
application begins and when it ends. The WSIT-generated JavaBean has a
constructor named <application-name>Impl. For example, the stock sample has a
constructor named stockImpl. To establish an out-of-process deployment,
call the constructor with an instance of the class WsiIpcContext. The WsiIpcContext constructor can be called with one of three different session
types.
1. LIFETIME_SESSION: This is the default session type. The session begins when the
applications Impl object is created and the session ends when the remove method
is called.
2. NO_SESSION:
The session begins when a method call is made on the application and the
session ends when that call returns. The lifetime of the session is a single
method call.
3. TX_SESSION:
The session begins when the client logs into the application by calling the
methods AcmsSignIn or OpenVMSLogin of
the application Impl object. The session ends when the client
calls the methods AcmsSignOut or OpenVMSLogOut.
When deploying an application out-of-process, WSIT allows the
creation of a process pool, which is a collection of processes for the application
that WSIT manages in the background to improve response time. Each process is
running the application. The XML tag <ProcessPooling> is used to configure the properties of the pool.
·
Use
the tag <MaximumProcesses> to specify an upper limit for the
largest number of processes that WSIT can create for the application.
·
Use
the tag <MinimumProcesses>
to specify a lower limit for
the fewest number of processes that WSIT should maintain for the application. The
number specified will be the number of processes WSIT starts initially.
·
Use
the tag <MinimumIdleProcesses> to specify the number of non-busy
processes to keep on an ongoing basis. WSIT creates more processes as needed to
maintain these free processes. WSIT does not create more than <MaximumProcesses> of processes.
·
Use
the tag <MaxInactivitySeconds> to specify when a process should be
removed from the pool and run down. Specify the maximum number of seconds that
an application can be idle before it is automatically stopped.
Running
your application out-of-process allows you to specify configuration
options. These options are contained in
the XML file wsi$root:[deploy]application-name.wsi.
The out-of-process
configuration options are as follows:
|
|
Account (Username) |
Name of the account you want the server to run
in, which determines the access rights and quotas that the server will have.
Requires NETMBX and TMPMBX privileges. |
WorkingDirectory |
Working directory for the server component.
This is important if the server component opens files with names relative to
some assumed working directory of the application. |
SetupCommandFile |
File specification of a DCL command file you
want to run before the server component starts up. |
ServerPath |
Complete file specification where the server
component image is located. |
StackSize |
Stack size to use for each thread within the
server component. The default of 0 means to use the default DECthreads (POSIX
Threads) stack size. |
Reusable |
Default is
not reusable. Uncomment this option if the server application is reusable, which
means the server can be
called by more than one client sequentially.
(See Advanced Out-of-Process Configuration
chapter.) |
MaximumClients |
Maximum
number of clients handled per server. If the server is not reusable, the
default is 1. Modify MaximumClients if, in
addition to being reusable, the server application process can handle
multiple clients concurrently. If this property is greater than 1, the order
of client calls coming into the server process is indeterminate. (See Advanced
Out-of-Process Configuration chapter.) |
MaximumThreads |
Maximum
number of threads allowed to run concurrently. This option is never greater
than MaximumClients. If the server is not reusable, the default is 1. Modify MaximumThreads if, in
addition to being able to handle multiple clients, the server application is
also thread safe. (See Advanced Out-of-Process Configuration chapter.) |
|
|
MaximumProcesses |
Defines the
maximum number of server processes that are allowed to run concurrently to
handle client requests. The total capacity of the application is MaximumProcesses multiplied
by MaximumClients. The default is 5. |
MinimumProcesses |
Minimum number of server processes that are
automatically started to service requests from clients. This value is never
greater than MaximumProcesses. The default is 0. |
MinimumIdleProcesses |
Sets the
number of server processes that will be maintained as idle to serve requests
from clients. As servers become busy, new server processes are started to act
as idle servers. The number of idle server processes can reach (but never be
greater than) the number of MaximumProcesses. |
MaxInactivitySeconds |
Maximum number of seconds that a server
can be idle before it is automatically stopped. The default is 1000 seconds. |
MaxStartupSeconds |
Maximum number
of seconds to wait for a process to startup.
Default is 45 seconds. |
ClientsWaitForServer |
Specifies
whether a client request should wait for a server process to become
available. If set to 0 (the default), the client request fails with an error
if a server is unavailable. If set to 1, the client waits for an available
server. Waiting may appear to be a hung client if no server processes become
available. |
2.3.4.1 Out-of-Process Account Preparation and
Requirements
If you are specifying an account in which to run out-of-process
servers, you may want the account to have a minimal amount of privileges.
You can specify an account to run out-of-process
servers that has only the NETMBX and TMPMBX privileges. To use an account with these privileges,
perform the following steps:
1.
Create an
identifier within the system UAF with the name WSI$SERVER. (Perform this step one time only.)
2.
Grant the
WSI$SERVER identifier to each account used to run a WSIT out-of-process server.
If you do not perform these steps, the privileges
required by the account are as follows:
BYPASS
SYSNAM
SYSPRV
IMPERSONATE
DETACH
TMPMBX
The
primary goal of the Web Services Integration Toolkit is to take the interface
exposed by a user’s application and present it as a Java based interface. These interfaces are defined by their set of
routine calls, the parameters passed in and out of these routines, and the
mechanisms used to pass those parameters. The following sections discuss this
in more detail, and provides a background on the actions WSIT takes to wrap an
application and provide it with a new interface.
2.4.1 Application
Interfaces
(User Supplied)
The
Application’s Programming Interface (API) is where the work begins for
WSIT. The application’s interface,
provided by the user, is parsed by the WSIT tools OBJ2IDL
or STDL2IDL. These tools
create a WSIT-specific Interface Definition Language (IDL) file describing the
application’s interface. This definition includes the set of routines included
within this interface. For each routine, the IDL describes the parameter list
in detail, including the parameter names, the parameter datatypes, and the
passing mechanisms used to pass these parameters.
2.4.2 OpenVMS
Datatypes Supported by WSIT
The
datatype specified for each parameter must be one of the following:
·
a standard OpenVMS datatype (as defined by the
OpenVMS Calling Standard)
·
an array of these datatypes
·
a structure composed of these datatypes
Internally,
WSIT uses the Descriptor datatype definition values, DSC$K_DTYPE_*,
to identify all datatypes. However,
depending on the language that you are using, these may more readily be
recognized as float, double, short, and so on. See the Datatype Mapping section
for a table that lists all of the OpenVMS datatypes that WSIT supports, along
with their Java type mappings.
2.4.3 Passing
Mechanisms
WSIT
supports the three passing mechanisms described by the OpenVMS Calling
Standard. This standard does not dictate which passing mechanism must be used
by a given language compiler. (Note that language semantics and
interoperability considerations might require different mechanisms in different
situations.) WSIT generates the code
needed to pass each parameter using the mechanism specified within the IDL
file. The three passing mechanisms are
as follows:
·
By
“Value”
An immediate value argument item contains the value of the data item. The
argument item, or the value contained in it, is directly associated with the
parameter.
·
By “Reference”
A reference argument item contains the address of
a data item such as a scalar, string, array, or structure. This data item is
associated with the parameter.
·
By “Descriptor”
A descriptor argument item contains the address
of a descriptor, which contains structural information about the argument's type
(such as string length) and the address of a data item. This data item is
associated with the parameter.
An
example of a C module whose interface has been parsed can be found in:
wsi$root:[samples.c]math.c
The
IDL generated from parsing math.c can be found in the Appendix.
2.4.4 JavaBean
Interface (Generated by WSIT)
The
previous section discussed what the user’s application exposes as an interface
and how it gets described. This section
discusses the Java based interface that WSIT generates from that description of
the user’s API. This includes how the
OpenVMS datatypes map into Java types, as well as how WSIT accommodates the
different passing mechanisms.
For
each routine that is exposed by the user’s application, a method is generated
in the new Java based interface. Although the generated methods are named the
same as their routine counterparts, the casing may be different to better
accommodate Web Services based clients. The parameters for each method have a
1-to-1 mapping to their user application counterparts. This mapping is discussed in the following
section.
2.4.5 Datatype
Mapping
When defining the interface within WSIT, you do not regularly need to be
concerned with most issues related to datatype conversion. When you specify the
OpenVMS datatypes for the parameters, WSIT converts them to appropriate Java
types. WSIT converts primitive types
from OpenVMS to Java as described in the mapping table below. WSIT also maps arrays of these types to Java
arrays, and structures comprising of these types to JavaBean style classes that
encapsulate the mapped types.
OpenVMS Type |
Description |
Java Type |
Java In/Out Classes |
DSC$K_DTYPE_BU |
unsigned byte |
byte |
ByteHolder |
DSC$K_DTYPE_WU |
unsigned word |
short |
ShortHolder |
DSC$K_DTYPE_LU |
unsigned long |
int |
IntHolder |
DSC$K_DTYPE_QU |
unsigned quadword |
long |
LongHolder |
DSC$K_DTYPE_OU |
unsigned octaword |
BigInteger |
BigIntegerHolder |
DSC$K_DTYPE_B |
Byte |
byte |
ByteHolder |
DSC$K_DTYPE_W |
Word |
short |
ShortHolder |
DSC$K_DTYPE_L |
Long |
int |
IntHolder |
DSC$K_DTYPE_Q |
quadword |
long |
LongHolder |
DSC$K_DTYPE_O |
octaword |
BigInteger |
BigIntegerHolder |
DSC$K_DTYPE_F |
32bit F float |
float |
FloatHolder |
DSC$K_DTYPE_G |
64bit G float |
double |
DoubleHolder |
DSC$K_DTYPE_D |
64bit D float |
double |
DoubleHolder |
DSC$K_DTYPE_H |
128bit H float |
double* |
DoubleHolder* |
DSC$K_DTYPE_FX |
128bit IEEE float |
double* |
DoubleHolder* |
DSC$K_DTYPE_FS |
32bit IEEE float |
Float |
FloatHolder |
DSC$K_DTYPE_FT |
64bit IEEE float |
double |
DoubleHolder |
DSC$K_DTYPE_T |
String |
String |
StringHolder |
DSC$K_DTYPE_VT |
varying string |
String |
StringHolder |
DSC$K_DTYPE_NU |
decimal string unsigned |
BigDecimal |
BigDecimalHolder |
DSC$K_DTYPE_NL |
decimal string left separate
sign |
BigDecimal |
BigDecimalHolder |
DSC$K_DTYPE_NLO |
decimal string left overpunch
sign |
BigDecimal |
BigDecimalHolder |
DSC$K_DTYPE_NR |
decimal string right separate
sign |
BigDecimal |
BigDecimalHolder |
DSC$K_DTYPE_NRO |
decimal string right overpunch
sign |
BigDecimal |
BigDecimalHolder |
DSC$K_DTYPE_NZ |
decimal string zoned |
BigDecimal |
BigDecimalHolder |
DSC$K_DTYPE_P |
Packed-decimal |
BigDecimal |
BigDecimalHolder |
DSC$K_DTYPE_V |
aligned bit |
boolean |
BooleanHolder |
DSC$K_DTYPE_ADT |
Absolute Date & Time |
Calendar |
CalendarHolder |
* 128 bit floating point datatypes are mapped to doubles within Java, limiting
their range and precision.
Note: All
unsigned integer types are mapped to their signed counterparts when converted.
This shifts the range of values that can be represented by a given
datatype. For example, an unsigned word,
which has a range of 0 to 65535, is mapped to a short, which has a range of
32767 to -32768. Be sure to account for
this in your client if the values are expected to exceed those of the signed
counterpart.
2.4.6 Parameter Usages
The
Application Interface section described how parameters are passed using
specific passing mechanisms. Although
Java does not support these different passing mechanisms for passing
parameters, there is one aspect of the passing mechanism that does apply. The
usage of a parameter describes how the called routine intends to affect that
parameter. The variations are as
follows:
·
In
Only
In
Only states that the called routine intends to only read the parameter and not modify
or write to the parameter. This is the default usage for the by “Value” passing
mechanism, but may be used with by “Reference” or by “Descriptor” if the
developer is sure that the routine is not going to change the parameter value.
·
In
/ Out
In
/ Out states that the called routine intends to both read, and then modify the
contents of the specified parameter. The
caller of the routine must pick up the new value for the parameter on return. This is the default usage for both the by
“Reference” and by “Descriptor” passing mechanisms.
·
Out
Only
Out
Only states that the called routine intends to only write to the specified
parameter and not read it. As with
In/Out, the caller of this routine must pick up the new value for the parameter
on return. This is associated with
either the by “Reference” or by “Descriptor” passing mechanisms.
If
the usage of a parameter is In Only, then the generated Java method can take
the Java type directly, because it does not need to look for a modified
parameter value. However, if the usage
is In/Out or Out Only, then the generated Java method must take a wrapper or
“Holder” class for the mapped Java type. This Holder class allows the client to
retrieve the possibly modified parameter value. Each OpenVMS to Java type mapping
contains an associated Java Holder class for parameters that have a usage other
than In Only. (For more information, see
the Mapping table in the previous section under
the “Java in/out classes” column.)
The
supplied math sample (found in wsi$root:[samples.c]) has the following C based routine:
unsigned int sum (int number1, int number2);
Based
on the mapping above, the Java method generated for it is:
int Sum (int number1, int number2)
The
Java client code is:
int result = myapp.Sum (56, 72);
If
the above C routine was changed to take an in/out parameter, the code would be
as follows:
void sum (int number1, int number2, int *result);
Based
on the mapping table above, the Java method generated is:
void Sum (int number1, int number2, IntHolder result);
The
Java client code is:
IntHolder result = new
IntHolder();
myapp.Sum (56, 72, result);
int iresult = result.value;
2.5 Design Restrictions for
Wrapped Applications
The
Web Services Integration Toolkit is an API level wrapping tool. This means that an appropriate programming
interface into the application must be presented to the Toolkit for it to
successfully work. This includes items such as no terminal input in the exposed
routines, using standard OpenVMS calling mechanisms for passing arguments, and
so on.
Beyond
the standard restrictions mentioned above, the Web Services Integration Toolkit
contains other restrictions that you must be aware of when wrapping your
application. These restrictions are
discussed in the sections below.
2.5.1 Pointer Types Not Supported
Because
of the distributed nature of WSIT-wrapped applications, pointer types are
problematic because their value is dependent on the process space in which they
were created. Although pointers used within the context of the
Pass-by-Reference and Pass-by-Descriptor passing mechanisms are supported, all
other uses of pointers are not supported by WSIT.
The
following table lists the common cases in which pointers are found, and identifies
the pointers that are supported and those that are not supported. (The
descriptions are expressed in C syntax but are relevant for all languages.)
Restriction |
Description |
Routine
parameters cannot be defined as “pointer to pointer.” However,
a single pointer, commonly referred to as pass-by-reference, is supported. |
// This is not
supported void
myfunction( int **p) // This is
supported void
myfunction( int *p) |
User-defined
structures cannot contain pointers to other user-defined structures. (*See Note at end of table.) However,
nested structures are supported. |
// For the
structure buyerData: typedef struct
_buyerData { char buyer_name[MAX_STRING];; } buyerData; // This is not
supported typedef struct
_customerData { buyerData *pbuyer; } customerData; // This is
supported typedef struct
_customerData { buyerData buyer; } customerData; |
Routine
return values must be returned by value and cannot be user-defined
structures. However,
the interface can add a special parameter to the routine to return the same
structure. |
// For the
structure buyerData: typedef struct
_buyerData { char buyer_name[MAX_STRING];; } buyerData; // This is not
supported // This is
supported int buy(buyerData *return_value) |
Note: If a structure contains a pointer to a type, WSIT
passes the pointer as an integer without any regard for the type. The
application must handle the memory appropriately. This memory is only valid in
the context of the application being wrapped and is not valid in the generated
Javabean.
2.5.2 Instantiated WSIT JavaBeans Cannot Be Shared Among Clients
The WSIT runtime supports a many-to-one
relationship between clients and backend servers. However, each client must have its own copy
of the Javabean object (unless you manually add synchronization code to the
generated Javabean class). The Javabean
object acts as the client's personal interface into the backend server. It allows WSIT to make sure that each client
gets the correct context within the server. If a single Javabean instantiation
is shared among clients, they will also share a single server context. If concurrent calls are then made without
synchronization code put in place, this could lead to unexpected results,
including incorrect call data and memory management exceptions.
See Section 4.4, Modifying an Existing Template, for
information about how to manually add synchronization code.
2.5.3 Languages Tested with
Web Services Integration Toolkit
The Web Services
Integration Toolkit was written to wrap ACMS applications and any 3GL-based
applications that are callable using the defined OpenVMS calling standard. However, only the following languages have
been completely tested:
·
ACMS
·
BASIC
·
C
·
COBOL
Other languages that
adhere to the OpenVMS calling standard (including FORTRAN) should work, but
have had limited testing only.
2.5.4 Tips and Hints for
Supported Languages
The following issues apply to all WSIT-supported languages (ACMS, BASIC, C, and
COBOL).
·
The
exception java.lang.UnsatisfiedLinkError: no WSI$JNISHR may be generated:
If you have not started WSIT by calling sys$startup:wsi$startup, an exception is thrown when you run the
generated JavaBean.
The following
issues apply to the BASIC language only.
·
For formal
parameters, passed by value, with types other than strings or signed decimal
data:
OBJ2IDL.EXE defaults to a passing mechanism of reference
and a usage of IN/OUT. Modify the XML to
specify a passing mechanism of value and a usage of IN.
·
For formal
parameters, passed by descriptor:
OBJ2IDL.EXE does not recognize the type of the formal
parameter. In such cases, the type defaults to a null terminated string. Modify the XML to specify the correct type
for the formal parameter. In some cases, you may need to add the type
(primitive or structure) to the XML.
·
For formal
parameters that are arrays, if the passing mechanism is descriptor:
OBJ2IDL.EXE does not recognize the arrays. Modify the XML to specify the array. (See the example of syntax in the C language
section.)
The following issues apply to the C language only.
·
When
passing a formal parameter of byte (type char) by reference:
If a char is being used to represent a single byte and is passed by reference
as a formal parameter, then the generated XML will specify the parameter as
having a type of type=”AutoGen_NullTermString”. Modify the XML to specify type=”char”
which will properly resolve to a byte (DSC$K_DTYPE_B).
·
For
C applications, OBJ2IDL.EXE does not recognize formal parameters that are
arrays:
For example, if an array of userstruct with size 3 is passed as a parameter, then the
XML that is generated will be as follows:
<Routine Name
= "incrementArrayOfStructures" ReturnType = "signed
int">
<Parameter Name = "array" Type = "userstruct"
PassingMechanism = "Reference"
Usage = "IN/OUT"/>
</Routine>
Modify
the XML to specify the array as follows:
<Routine Name
= "incrementArrayOfStructures" ReturnType = "signed
int">
<Parameter Name = "array" Type = "userstruct"
PassingMechanism = "Reference"
Usage = "IN/OUT" ArrayDimension = "1">
<Array LowerBound = "0" UpperBound = "2"/>
</Parameter>
</Routine>
The following
issues apply to the COBOL language only.
·
For all formal
parameters:
OBJ2IDL.EXE defaults the usage to IN/OUT.
OBJ2IDL.EXE defaults the passing mechanism to pass by reference.
2.5.5
Tips and Hints for
OpenVMS Alpha Users
Using I64 generated XML IDL on Alpha:
If you are using the Web Services Integration Toolkit on an
OpenVMS
Alpha system, you can generate your XML file on OpenVMS I64, and in most cases,
copy it to OpenVMS Alpha with few or no modifications.
OpenVMS Alpha users who do not have an I64 system can use an OpenVMS I64 system
provided by the HP TestDrive Program. This system has WSIT installed. To
access this resource you must register (for free) at http://www.testdrive.hp.com/accounts/register.shtml
When using an I64 generated IDL on OpenVMS Alpha, be aware that some compilers
may have different default values on I64 than on Alpha. These differences need
to be addressed. For example, the C
compiler uses a different VMSDataType for primitive types float and double:
C Primitive |
Default Value on
I64 |
Default Value on
Alpha |
float |
DSC$K_DTYPE_FS |
DSC$K_DTYPE_F |
double |
DSC$K_DTYPE_FT |
DSC$K_DTYPE_G |
An application that uses a float must replace the following:
<Primitive Name = "float”
Size = "4” VMSDataType = "DSC$K_DTYPE_FS"/>
with
<Primitive Name =
"float" Size = "4" VMSDataType =
"DSC$K_DTYPE_F"/>
An application that uses a double must replace the following:
<Primitive Name = "float”
Size = "4” VMSDataType = "DSC$K_DTYPE_FT"/>
with
<Primitive Name =
"float" Size = "4" VMSDataType = "DSC$K_DTYPE_G"/>
Before you configure the out-of-process
deployment file, identify your
application’s level of reusability. If your application is reusable, you
can significantly reduce the number of processes needed to service the
clients.
Next, to determine if a single instance
of an application can handle multiple clients, consider how you maintain state and manage I/O within your
application. Applications are frequently designed to accumulate state from call
to call. For example, the first call opens a file, the second call reads from
the file, and the third call updates and writes back the modified record. In cases like this, multiple clients within
the same application may “step on” each other trying to access the same files
using the same channels.
To help you determine your application’s
level of reusability, the following sections describe four applications, each
with a different level of reusability or combination of reusability and
multiple threads.
This is the default configuration for all WSIT out-of-process applications.
An application is not reusable when it can
only be used for one client session.
When the session is finished, the application has created state that prevents
it from being called again. The next client session requires a new instance of
the application. This situation can exist in older applications that assume a
single long-lived client is their only client. To identify this situation look
for global (or static) variables that are used to identify stored
client-specific data. The following
figure shows an application that is not
reusable:
For example, an application may not be
reusable if it has a global variable to hold a client account number and the
account number cannot be modified or reset with a subsequent call or other
mechanism. If a second session requires a different account number to be set,
then the application is not reusable.
Deploying an application as not reusable
is the most restrictive case and has the highest runtime overhead, but is also
the safest configuration. When an application is not reusable, WSIT ensures
that the client always receive a new instance of the application.
The order of events for a non-reusable
application is as follows:
1.
The
client instantiates the WSIT-generated JavaBean. This starts a session with a
free application.
2. WSIT assigns the client the exclusive
use of a process that is running the application. The process may be newly
created or may have been previously created but never used.
3. The client uses the application as it
desires. One or more calls are made as part of the session.
4. The client tells the WSIT runtime that
it is finished with the session by calling the remove method of the
WSIT-generated JavaBean. This assumes that a session type of LIFETIME_SESSION is being used. A non-reusable
application should not use a NO_SESSION
session because of the extremely high overhead which occurs from creating and
deleting a process for every method call.
5. WSIT deletes the process.
3.2 CASE
B: SEQUENTIALLY REUSABLE
An application is sequentially reusable when it is able to process more than one
client session, but requires that exactly
one session be active at a time. The application must initialize its state
before processing the next client session.
When an application is sequentially
reusable, WSIT will not delete the application process when the client is
finished using it. WSIT ensures that only one client can have a session
outstanding with the application.
The following figure shows an application
that is sequentially reusable.
For example, an application is serially
reusable if it has a global variable to hold a client account number and also a
method to initialize (or modify) the account number. In this way, each client
can call the initialize method to erase the state of a previous client’s
session.
The order of events for a sequentially
reusable application is as follows:
1.
The
client instantiates the WSIT generated JavaBean. This starts a session with a
free application.
2.
WSIT
assigns the client the exclusive use of a process that is running the
application. The process may be newly created or may have been previously
created.
3.
The
client uses the application as it desires. One or more calls are made as part
of the session.
4.
The
client tells the WSIT runtime it is finished with the session based on the type
of session used.
5.
WSIT
places the application in a pool so that it is available for another client to
use.
To deploy an application as sequentially
reusable, make the following change to the file wsi$root:[deploy]<application-name>.wsi:
·
Uncomment
the XML tags <Reusable>
</Reusable>
3.3 CASE C: CONCURRENTLY REUSABLE
An application is concurrently reusable when it can be called from multiple clients without regard to the
order of the clients’ sessions. This type of application has a mechanism
for keeping the state of each of the clients separated. WSIT uses a single
thread when forwarding the clients’ calls to the application. From the application’s perspective, the clients’
sessions may be nested. This ensures
that the application processes one client call at a time.
The following figure shows an application
that is concurrently reusable.
For example, an application is
concurrently reusable if its interface uses a context block to hold client
data. In this way, the logic in the application is generic in regard to the
clients.
The order of events for a concurrently reusable
application is as follows:
1.
The
client instantiates the WSIT-generated JavaBean. This starts a session with a
free application.
2.
WSIT
assigns the client the use of a process that is running the application. The
process may be newly created or may have been previously created. Other
instances of the client may also be using the same application, but WSIT
ensures that all method calls are made one at a time on the same thread.
3.
The
client uses the application as it desires. One or more calls are made as part
of the session.
4.
The
client tells the WSIT runtime it is finished with the session based on the type
of session used.
5.
WSIT
places the application in a pool so that it is available for another client to
use.
To deploy an application as sequentially
reusable make the following changes to the file wsi$root:[deploy]<application-name>.wsi:
1.
Uncomment
the XML tags <Reusable> </Reusable>
2.
Uncomment
the XML tag <MaximumClients>
and specify a number greater than one
for the number of client sessions that the application can process.
3.4 CASE D: CONCURRENTLY REUSABLE WITH MULTIPLE THREADS
An application is concurrently reusable and thread-safe when it can be called from multiple clients, at the same
time, on multiple threads. WSIT allows multiple client sessions to call the
application without any attempt to serialize them. The application was designed
to lock shared data when called by multiple threads. It is also written in a
language that is capable of generating thread-safe code. (For example, COBOL
and BASIC do not generate thread-safe code.)
To determine if the application can
handle calls from different clients concurrently, consider the following:
·
Are
all of the application resources that are shared among clients protected in a
thread-safe way? For example, using
global symbols can cause problems unless they are protected by a mutex or
equivalent concept.
·
Is
the language that was used to write the application thread-safe?
The following figure shows an application
that is concurrently reusable with multiple threads.
For example, an application is concurrently
reusable and thread safe if its interface uses a context block to hold client
data, and all access to global data, such as a global queue of client context
blocks, is protected by a thread-safe locking mechanism such as a mutex.
The order of events for a concurrently reusable with multiple threads
application is as follows:
1.
The
client instantiates the WSIT-generated JavaBean. This starts a session with a
free application.
2.
WSIT
assigns the client the use of a process that is running the application. The
process may be newly created or may have been previously created. Other
instances of the client may also be using the same application. WSIT uses
multiple threads to call the application.
3.
The
client uses the application as it desires. One or more calls are made as part
of the session.
4.
The
client tells the WSIT runtime it is finished with the session based on the type
of session used.
5.
WSIT
places the application in a pool so that it is available for another client to
use.
To deploy an application as sequentially
reusable make the following changes to the file wsi$root:[deploy]<application-name>.wsi:
·
Uncomment
the XML tags <Reusable>
</Reusable>
·
Uncomment
the XML tags <MaximumClients>
</MaximumClients> and specify a number greater than one for the number of
client sessions that the application can process.
·
Uncomment
the XML tag <MaximumThreads>
</MaximumThreads> and specify a number greater than one for the number of
threads that WSIT can use to call the application.
The number of threads
allowed to run concurrently should be a percentage of the number of clients
specified. A good rule of thumb is to
look at the average amount of time that each application call is expected to
take.
·
If the calls are small and quick, then the number
of threads allowed to run concurrently could be 25% of the number of
clients.
·
If you expect calls to take longer, then you
should use a larger value, such as 50 to 60%.
For example, if
you specify ten clients per application, and each application call will take
some time, then allow six threads to run. Note that once a system is in place,
this number should be monitored and adjusted as needed.
The Web Services Integration Toolkit
(WSIT) provides a number of different tools that complement each other in the
process of wrapping existing OpenVMS applications. One of the tools in the toolkit is IDL2CODE.JAR, also known as the WSIT generator.
The WSIT generator uses a mechanism based
on Velocity templates. A set of template
files are read, and placeholders within those templates are replaced by
application-specific values. This
becomes the generated code.
More specifically, the generator reads a
WSIT-specific IDL description of the application to be wrapped, then generates
code based on this description. The
generated wrapping code contains the following:
·
Server
wrapper component that builds against the existing application
·
JavaBean
component that provides the new interface into this application
The
standard code that is generated out of the box has been tested and is
robust enough to handle most cases. However, you may want to tailor what is
generated by IDL2CODE.JAR. The following sections describe the process
that IDL2CODE.JAR uses
to generate code, and then describes how you can modify what is generated.
The generation process occurs in four
distinct phases. The first three phases
offer you an opportunity to modify what ultimately is generated. The phases are described in the following
sections.
In Phase 1, the generator reads the WSIT
IDL file describing the application, parses it, and then populates an object model
representation of its contents. This object model is directly accessed by the
templates and template engine in later phases.
The IDL should accurately reflect the interface to the application being
wrapped. This phase is your first
opportunity to affect what is generated.
See Section 1.3, Exposing an OpenVMS 3GL Application,
for more information.
In Phase 2, the generator generates a
master list called Master.lst
of files to generate based on the template file called Master.vm. (In the next phase, the generator steps
through this list of files to generate the actual files.) Modifying Master.vm allows you to change the list of files
to generate, as well as to change which templates to use in generating these
files.
Each line within Master.vm
and
Master.lst
has the following format:
<Object > < Name>
<Output Filename> <Template Filename> <Output
Subdirectory>
where:
Object describes
the component to which this generated file will belong. Object
can have one of the following values:
SW File belongs to the server wrapper component
The
generated file is placed into the subdirectory [.appnameServer]
JB File belongs to the JavaBean component
The
generated file is placed into the subdirectory [.appname]
I File represents an interface within the JavaBean
The
generated file is placed into the subdirectory [.appname]
S File represents a structure definition within the Javabean
The
generated file is placed into the subdirectory [.appname]
C File is part of a generated sample client
The generated
file is placed into the subdirectory [.appnameSamples…]
Name identifies
the name of the object within the object model that this file represents.
Output
filename is the filename of the file to be
generated.
Template filename is the filename of the template to use in
creating this file.
Output Subdirectory optionally
specifies the subdirectory in which to generate the file.
(If used, it overrides the default subdirectory specification.)
In Phase 3, the generator reads the
previously generated Master.lst
file, then generates the listed files.
Each line within Master.lst contains an output filename and an
associated template file to use in its generation. It uses these mappings, along with this
previously populated object model, to create the output files.
You can modify the template files to
change the contents of the individually generated files. The object model can be accessed using
Velocity identifiers.
In Phase 4, the generator optionally runs
the Javadoc utility against the generated JavaBean files, creating a set of
.html files that document the generated interface.
The following example shows you how to
write a new template and add it to the master list so that it will be used
within the generation process.
This example assumes the following simple
WSIT IDL:
<?xml
version="1.0" encoding="UTF-8"?>
<OpenVMSInterface
xmlns="hp/openvms/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="hp/openvms/integration
openvms-integration.xsd"
ModuleName="simple.OBJ"
Language="C89">
<Primitives>
<Primitive Name = "signed
int"
Size = "4"
VMSDataType =
"DSC$K_DTYPE_L"/>
</Primitives>
<Routines>
<Routine Name = "add"
ReturnType = "signed
int">
<Parameter Name =
"p1"
Type =
"signed int"
PassingMechanism
= "Value"
Usage = "IN"/>
<Parameter Name =
"p2"
Type =
"signed int"
PassingMechanism
= "Value"
Usage =
"IN"/>
</Routine>
</Routines>
</OpenVMSInterface>
Step 1: Write Template
using Velocity
For this example, we will write a
template file using Velocity that generates a log file containing the list of
the routines being exposed, along with their parameters. (Save the file as app-logfile.vm.) The completed file will look similar
to the following:
#set( $server =
$application.Server )
Logfile for
${application.Name}
---------------------------------
Routines being exposed Parameters
----------------------------------------------------------------------
#foreach( $routine in
$server.Routines)
${routine.Name}
Description: ${routine.Description}
Return Type: #if( $routine.Returnparam )
$routine.Returnparam.SWFormalDefinition#else void#end
#foreach( $param in
$routine.Parameters)
${param.Name}
($param.SWFormalDefinition)
#end
#end
Note: The
Velocity syntax that is used to pull information from the provided object
model. Within WSIT:
·
All
templates are passed $application,
which is a reference to the top level genConnection
object.
·
All
structure type templates are passed $structure,
which is a reference to the genStructure
object.
·
All
interface templates are passed $interface,
which is a reference to the genInterface
object.
The template files located in WSI$ROOT:[TOOLS.TEMPLATES]show many different
examples of using these tags.
When you finish writing the template,
place it where Velocity can find it. The
path(s) that the Velocity engine uses to find template files is specified in
the file velocity.properties. You can modify this file to add your
directory to the search path, or you can copy your newly written template into
a directory that is already in the path.
Step 2: Modify Master.vm
Next, modify Master.vm to add the new file to the list of files
that are generated. The new file that
you created in Step 1 is considered a server
wrapper template file because it lists the interface as exposed by the application.
Add the
following line to Master.vm in the appropriate place. Type the line exactly as
shown below. (Like any other template
file, the ${application.Name} placeholder is automatically replaced with the
name of the application, causing the generated file to contain the application
name in its filename.)
SW
${application.Name} ${application.Name}.log app-logfile.vm
Step 3: Run IDL2CODE.JAR
Run the generator and review the newly
generated files. If the run is successful,
a log file that looks similar to the following can be found in the [.ServerSimple] subdirectory.
Logfile for Simple
---------------------------------
Routines being exposed Parameters
----------------------------------------------------------------------
add
Description: This is the description for
the add routine
Return Type: signed int
P1 (signed int)
Example 1 showed you how to write and add
your own new template. However, there
may be cases in which you want to directly modify
the behavior of an existing WSIT template.
For instance, you may want to remove the restriction that every client needs to have its own
instantiation of the JavaBean interface class. The way to remove this
restriction is to make sure that the generated JavaBean class has appropriate
synchronization code to serialize all calls through it. (This is not generated by the default WSIT
templates.) This example steps you
through this simple process.
Step 1: Set Default
Directory
Assuming the default location for the
templates, set your default directory to
WSI$ROOT:[tools.templates.javabean].
This is where you will find the templates
used to generate the javabean files.
Step 2: Edit Files to Add
Synchronize Keyword
Assuming that the templates have their
default names, edit the files
INTERFACE-JAVA.VM and INTERFACEIMPL-JAVA.VM.
These files define the interface, and the
implementation of the interface, for the newly generated application.
For every public method definition within
the two files, you must add the synchronized keyword. In particular, add the synchronized
keyword to the: AcmsSignIn,
AcmsSignOut, OpenVmsLogin, OpenVmsLogout,
and remove
methods in each file.
Next, add the synchronized keyword to each method definition within
$interface.Methods
and $interface.AcmsMethods.
For example:
Before:
public#if($routine.Returnparam)
$dtutility.getJBtype($routine.Returnparam.Datatype)#else void#end
${routine.WebServiceName} ($paramformal)
throws
WsiException;
After:
Public synchronized#if($routine.Returnparam)
$dtutility.getJBtype($routine.Returnparam.Datatype)#else void#end
${routine.WebServiceName} ($paramformal)
throws
WsiException;
Step 3: Run IDL2CODE.JAR
Run IDL2CODE.JAR
to generate an application wrapper. The
generated interface methods are synchronized. All method calls to each JavaBean
is serialized.
$ ty stock.c
//
// This is a
sample file intended to be used to demonstrate the WSIT product.
// It defines 2
routines: (buy and sell). Each routine accepts 3 structures:
// buyerData,
sellerData, tickerData.
//
// This code is
intended only to illustrate the WSIT product and is not intended provide
// a usefull
stock trading application.
//
//
#include
<string.h>
#include
<stdlib.h>
#include
<stdio.h>
const MAX_STRING
= 20;
typedef struct
_buyerData {
char buyer_name[MAX_STRING];
unsigned int member_number;
unsigned int balance_dollars;
unsigned int number_shares_desired;
} buyerData;
typedef struct
_sellerData {
char owner_name[MAX_STRING];
unsigned int member_number;
unsigned int balance_dollars;
unsigned int number_shares_available;
} sellerData;
typedef struct
_tickerData {
char symbol[MAX_STRING];
char company_name[MAX_STRING];
} tickerData;
unsigned int buy
(unsigned int max_price, tickerData *symbol, sellerData *pSeller, buyerData *pBuyer)
{
//
// Sell as many shares as possible
//
unsigned int shares_purchased = 0;
if (
pSeller->number_shares_available >= pBuyer->number_shares_desired) {
shares_purchased =
pBuyer->number_shares_desired;
} else {
shares_purchased =
pSeller->number_shares_available;
}
pSeller->number_shares_available =
pSeller->number_shares_available - shares_purchased;
return shares_purchased;
}
unsigned int sell
(unsigned int min_price, tickerData *symbol, sellerData *pSeller, buyerData
*pBuyer) {
//
// Sell as many shares as possible
//
unsigned int shares_sold = 0;
if (
pSeller->number_shares_available >= pBuyer->number_shares_desired) {
shares_sold =
pBuyer->number_shares_desired;
} else {
shares_sold =
pSeller->number_shares_available;
}
pSeller->number_shares_available =
pSeller->number_shares_available - shares_sold;
return shares_sold;
}
$
<?xml version="1.0"
encoding="UTF-8"?>
<OpenVMSInterface
xmlns="hp/openvms/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="hp/openvms/integration
openvms-integration.xsd"
ModuleName="wsi$root:[samples.c]stock.obj"
Language="C89">
<Primitives>
<Primitive Name = "unsigned int"
Size = "4"
VMSDataType = "DSC$K_DTYPE_LU"/>
<Primitive Name =
"AutoGen_FixedString19"
Size = "19"
VMSDataType = "DSC$K_DTYPE_T"
NullTerminatedFlag
= "0"
FixedFlag = "1"/>
</Primitives>
<Typedefs>
<Typedef Name = "tickerData"
TargetName = "_tickerData"/>
<Typedef
Name = "sellerData"
TargetName = "_sellerData"/>
<Typedef Name = "buyerData"
TargetName = "_buyerData"/>
</Typedefs>
<Structures>
<Structure Name = "_tickerData"
TotalPaddedSize = "40">
<Field Name = "symbol"
Type =
"AutoGen_FixedString19"
Offset =
"0"/>
<Field Name = "company_name"
Type =
"AutoGen_FixedString19"
Offset =
"20"/>
</Structure>
<Structure Name = "_sellerData"
TotalPaddedSize = "32">
<Field Name = "owner_name"
Type =
"AutoGen_FixedString19"
Offset =
"0"/>
<Field Name = "member_number"
Type =
"unsigned int"
Offset =
"20"/>
<Field Name = "balance_dollars"
Type =
"unsigned int"
Offset =
"24"/>
<Field Name = "number_shares_available"
Type =
"unsigned int"
Offset =
"28"/>
</Structure>
<Structure Name = "_buyerData"
TotalPaddedSize = "32">
<Field Name = "buyer_name"
Type =
"AutoGen_FixedString19"
Offset = "0"/>
<Field Name = "member_number"
Type =
"unsigned int"
Offset =
"20"/>
<Field Name = "balance_dollars"
Type = "unsigned
int"
Offset =
"24"/>
<Field Name = "number_shares_desired"
Type =
"unsigned int"
Offset =
"28"/>
</Structure>
</Structures>
<Routines>
<Routine Name = "buy"
ReturnType = "unsigned int">
<Parameter Name = "max_price"
Type =
"unsigned int"
PassingMechanism
= "Value"
Usage =
"IN"/>
<Parameter Name = "symbol"
Type =
"tickerData"
PassingMechanism
= "Reference"
Usage =
"IN/OUT"/>
<Parameter Name = "pSeller"
Type = "sellerData"
PassingMechanism = "Reference"
Usage =
"IN/OUT"/>
<Parameter Name = "pBuyer"
Type =
"buyerData"
PassingMechanism
= "Reference"
Usage = "IN/OUT"/>
</Routine>
<Routine Name = "sell"
ReturnType = "unsigned int">
<Parameter Name = "min_price"
Type =
"unsigned int"
PassingMechanism
= "Value"
Usage = "IN"/>
<Parameter Name = "symbol"
Type =
"tickerData"
PassingMechanism
= "Reference"
Usage =
"IN/OUT"/>
<Parameter Name = "pSeller"
Type = "sellerData"
PassingMechanism
= "Reference"
Usage =
"IN/OUT"/>
<Parameter Name = "pBuyer"
Type =
"buyerData"
PassingMechanism
= "Reference"
Usage =
"IN/OUT"/>
</Routine>
</Routines>
</OpenVMSInterface>
$
$ type stockcaller.java
import stock.*;
import java.io.*;
import javax.xml.rpc.holders.StringHolder;
import javax.xml.rpc.holders.StructureHolder;
public class stockcaller {
/**
Creates a new instance of
public
stockcaller() {
}
public
static void main(String[] args) {
try {
stockImpl stock = new stockImpl();
// create a seller object and place in holder
_sellerData sellerData = new _sellerData("Mr
Seller", 12345, 1000000, 1000);
StructureHolder seller = new StructureHolder(sellerData);
// create a buyer object and place in holder
_buyerData buyerData = new _buyerData("Mr
Buyer", 67890, 5000, 995);
StructureHolder buyer = new StructureHolder(buyerData);
// create a ticker object and place in holder
_tickerData tickerData = new
_tickerData("HPQ", "Hewitt Packard");
StructureHolder ticker = new StructureHolder(tickerData);
System.out.println("The sellers
number_shares_available: " + sellerData.getNumber_shares_available());
stock.buy(27, ticker, seller, buyer);
System.out.println("The sellers
number_shares_available: " + sellerData.getNumber_shares_available());
}
catch (Exception e) {
System.out.println("Exception thrown");
}
}
}
$
E Program Listing –
MATH.XML
<?xml version="1.0" encoding="UTF-8"?>
<OpenVMSInterface
xmlns="hp/openvms/integration"
xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
xsi:schemaLocation="hp/openvms/integration openvms-integration.xsd"
ModuleName="DISK$ODS5:[aaa.wsit.math]math.OBJ"
Language="C89">
<Primitives>
<Primitive Name = "unsigned
int"
Size = "4"
VMSDataType =
"DSC$K_DTYPE_LU"/>
<Primitive Name =
"signed int"
Size = "4"
VMSDataType =
"DSC$K_DTYPE_L"/>
</Primitives>
<Routines>
<Routine Name = "sum"
ReturnType = "unsigned
int">
<Parameter Name =
"number1"
Type =
"signed int"
PassingMechanism = "Value"
Usage =
"IN"/>
<Parameter Name =
"number2"
Type =
"signed int"
PassingMechanism = "Value"
Usage =
"IN"/>
</Routine>
<Routine Name = "product"
ReturnType = "unsigned
int">
<Parameter Name =
"number1"
Type =
"signed int"
PassingMechanism = "Value"
Usage =
"IN"/>
<Parameter Name =
"number2"
Type =
"signed int"
PassingMechanism = "Value"
Usage =
"IN"/>
</Routine>
</Routines>
</OpenVMSInterface>