在调用外部程序时,Net.Data 提供以下语言环境供您使用:
访问权限:请确保执行 Net.Data 的用户标识有权执行程序,并对该程序可能 访问的任何对象具有访问权。参见对 Net.Data 访问的文件授予访问权限, 以获取详情。
Net.Data 支持带有 Java 语言环境的现有 Java 应用程序。采用对 Java 小应用程序和 Java 方法(或 应用程序)的支持后,您可以通过 Java 数据库连接 (JDBC**) API 来访问 DB2。
要使用 Java 语言环境,您需要验证 Net.Data 的初始化设置并设置语言环境。
验证初始化文件中是否有类似如下配置语句的语句,并且是在一行上:
ENVIRONMENT (DTW_JAVAPPS) /opt/IBMNetData/lib/libdtwjava.so ( OUT RETURN_CODE ) {% CLIETTE "DTW_JAVAPPS" %}
在此示例中,ENVIRONMENT 条目末尾的 CLIETTE 字符串被注释掉。如果 CLIETTE 字符串未被注释掉,Net.Data 会通过“Net.Data 现场连接”尝试调用 Java 应用程序。在使用不同于 CGI 和 FCGI 的接口运行 Net.Data 时, 使用“Net.Data 现场连接”是必需的。如果 CLIETTE 字符串未被注释掉, 且“Net.Data 现场连接”未在运行,Net.Data 将尝试直接执行 Java 应用程序。但是, 如果使用不同于 CGI 和 FCGI 的接口运行 Net.Data, 可能会导致不可预见的行为。
参见环境配置语句,以进一步了解 Net.Data 初始化文件和语言环境 ENVIRONMENT 语句。
要点:如果想要通过“现场连接”调用 Java 应用程序,则参见设置带有 Cliette 的 Java 语言环境以了解如何设置 Java 语言环境。
借助 Java 语言环境, 可从 Net.Data 宏发出 Java 函数调用,并将 Net.Data 字符串用作参数。这些调用的 Java 函数调用会返回字符串。
Net.Data 提供了两个方法来调用 Java 函数:
在设置和配置方面, 这是最简单的方法。如果通过 CGI 或 FCGI 运行 Net.Data,建议使用此方法。此方法在 Windows、AIX、Linux 和 Solaris 上都可用。
如果将 Net.Data 作为 Web 服务器 API 运行,则建议使用此方法。Java 应用程序通过“现场连接”作为单独的进程运行, 且对于正在处理的其他 Java 的潜在干涉是“屏蔽”的。此方法在 Windows、OS/2 和 AIX 上可用。
设置 Net.Data 调用 Java 函数的过程与您使用的方法无关。
要通过装入 Java 应用程序来调用 Java 函数:
/opt/IBMNetData/bkends/javaapps/gnu.regexp-1.0.8.jar
gnu.regexp-1.0.8.jar 文件是与 Net.Data 一起交付的。
注意: | 每当 Java 函数源代码发生更改时,遵循这些步骤。此方法对 Windows、AIX、Linux 和 Solaris 是可用的。 |
要通过“现场连接”调用 Java 函数:
Net.Data cliette 启动运行 Java 函数的“Java 虚拟机”。
每当您引入新的 Java 函数时,都必须重新创建 Java cliette。
修改示例文件 makeClas.bat,或者为所有的 Java 函数创建一个新的 .bat 文件 来生成一个名为 dtw_samp.class 的 Net.Data cliette 类。下面的示例显示批处理 文件 CreateServer 如何处理三个 Java 函数:
rem Batch file to create dtw_samp for Net.Data java CreateServer dtw_samp.java UserFunctions.java myfile.java javac dtw_samp.java
批处理文件处理以下文件和 Net.Data 提供的名为 Stub.java 的 stub 文件, 用于处理 dtw_samp.class。
使用您自己的 Java 函数来修改 Java 函数样本文件 UserFunctions.java:
====================UserFuctions.java==================== import mypackage.* public String myfctcall(...parameters from macro...) { return ( mypackage.mymethod(...parameters...)); } public String lowlevelcall(...parameters...) { string result; .......code using many functions of your package... return(result) }
Net.Data 在安装期间创建了几个目录。 这些目录中包括您使用 Java 语言环境来创建 Java 函数、定义 cliette 和运行宏所需的文件:
表 13 描述了您操作系统上那些文件的目录与文件名。
操作系统 | 文件名 | 目录 |
---|---|---|
OS/2 | UserFunctions.java | javaapps |
launchjv.com | connect | |
Windows NT | UserFunctions.java | javaclas |
makeClas.bat | javaclas | |
launchjv.bat | connect | |
AIX | UserFunctions.java | javaapps |
launchjv | javaapps | |
rebuild | javaapps | |
gnu.regexp-1.0.8.jar | javaapps | |
Linux & Solaris | 用户 Functions.java | javaapps |
rebuild | javaapps | |
gnu.regexp-1.0.8.jar | javaapps |
在创建了 Java 函数、定义了 cliette 类或运行了 rebuild 并配置了 Net.Data 之后,您就可以运行包含对 Java 函数引用的宏。
以下示例宏演示函数定义和 Java 应用程序函数 reverse_line() 的函数调用。
%{ to call the sample } %FUNCTION (DTW_JAVAPPS) reverse_line(str); %HTML (report){ you should see the string "Hello World" in reverse. @reverse_line("Hello World") You should have the result of your function call. %}
Perl 语言环境能够解释在 Net.Data 宏的一个 FUNCTION 块中指定的在线 Perl 脚本, 或者它能处理存储在服务器上单独文件中的外部 Perl 脚本。
验证 Net.Data 初始化文件中有以下配置语句,并且是在一行上:
ENVIRONMENT (DTW_PERL) DTWPERL ( OUT RETURN_CODE )
参见环境配置语句,以进一步了解 Net.Data 初始化文件和语言环境 ENVIRONMENT 语句。
日文用户: | 日文 SJIS 字符集的某些字符可能会被 Perl 错误地解释成控制字符。 有一个名为 jperl 的开放源代码软件包可解决此问题。下载并安装该软件包, 然后在 Perl 脚本的标题中包括语句use I18N::Japanese.pm。 |
对外部 Perl 脚本的调用在 FUNCTION 块中是由一个 EXEC 语句来标识的:
%EXEC{ perl_script_name [optional parameters] %}必需: 请确保 Perl 脚本名称 perl_script_name 列在 Net.Data 初始化文件中为 EXEC_PATH 配置变量 指定的路径中。
%FUNCTION(DTW_PERL) perl1() { %EXEC{ MyPerl.pl %} %}
有两种方式将信息传递到 Perl (DTW_PERL) 语言环境调用的程序,直接和间接。
%DEFINE INPARM1 = "SWITCH1" %FUNCTION(DTW_PERL) sys1() { %EXEC{ MyPerl.pl $(INPARM1) "literal string" %} %}
Net.Data 变量 INPARM1 被引用并被传递到 Perl 脚本。参数传递到 Perl 脚本的方式与从命令行 调用 Perl 脚本时参数传递到 Perl 脚本的方式相同。使用此方法传送至 Perl 脚本的参数被视作输入类型参数。使用此方法传送至 Perl 脚本的参数被视作输入参数,而对这些值的任何修改都不会反映给 Net.Data。
使用下列其中一种方法在调用 Perl 脚本时直接传送参数:
name="value"
对于复合数据项,可以用一个新行字符 或空字符分开每个项。
如果一个变量名称与 OUT 或 INOUT 参数的名称相同且使用上述语法,则新的值将替换当前值。如果变量名未对应于 OUT 或 INOUT 参数,Net.Data 将忽略它。
以下示例显示了 Net.Data 如何从一个宏传递变量。
%FUNCTION(DTW_PERL) today() RETURNS(result) { $date = `date`; chop $date; open(DTW, "> $ENV{DTWPIPE}") || die "Could not open: $!"; print DTW "result = \"$date\"\n"; %} %HTML(INPUT) { @today() %}
如果 Perl 脚本位于一个名为 today.pl 的外部文件中,那么这个函数可以按下一个 示例来编写:
%FUNCTION(DTW_PERL) today() RETURNS(result) { %EXEC { today.pl %} %}
可以 Net.Data 表传递给由 Perl 语言环境调用的 Perl 脚本。Perl 脚本 根据 Net.Data 宏表参数的 Net.Data 名称来访问它们的值。列标题和字段值都包含在用表名和 列号标识的变量中。例如,在表 myTable 中,列标题是 myTable_N_j, 字段值是 myTable_V_i_j,其中 i 是行号, j 是列号。表的行数与列数是 myTable_ROWS 和 myTable_COLS。
REPORT 和 MESSAGE 块在所有 FUNCTION 部分都是允许的。 它们由 Net.Data 来处理,而不是由 语言环境来处理。当然,Perl 脚本可以将文本写至标准输出流,作为 Web 页面的一部分。
以下示例显示了 Net.Data 如何通过执行外部的 Perl 脚本来生成一个表:
%define { c = %TABLE(20) rows = "5" columns = "5" %} %function(DTW_PERL) genTable(in rows, in columns, out table) { open(D2W,"> $ENV{DTWPIPE}"); print "genTable begins ... "; $r = $ENV{ROWS}; $c = $ENV{COLUMNS}; print D2W "table_ROWS=\"$r\" "; print D2W "table_COLS=\"$c\" "; print "rows: $r "; print "columns: $c"; for ($j=1; $j<=$c; $j++) { print D2W "table_N_$j=\"COL$j\" "; } for ($i=1; $i<=$r; $i++) { for ($j=1; $j<=$c; $j++) { print D2W "table_V_$i","_","$j=\"" $i $j "\" "; } } close(D2W); %} %message{ default: "genTable: Unexpected Error" %} %} %HTML(REPORT){ @genTable(rows, columns, c) return code is $(RETURN_CODE) %}
结果:genTable 生成:
rows: 5 columns: 5 COL1 | COL2 | COL3 | COL4 | COL5 | -------------------------------------------------- [ 1 1 ] | [ 1 2 ] | [ 1 3 ] | [ 1 4 ] | [ 1 5 ] | -------------------------------------------------- [ 2 1 ] | [ 2 2 ] | [ 2 3 ] | [ 2 4 ] | [ 2 5 ] | -------------------------------------------------- [ 3 1 ] | [ 3 2 ] | [ 3 3 ] | [ 3 4 ] | [ 3 5 ] | -------------------------------------------------- [ 4 1 ] | [ 4 2 ] | [ 4 3 ] | [ 4 4 ] | [ 4 5 ] | -------------------------------------------------- [ 5 1 ] | [ 5 2 ] | [ 5 3 ] | [ 5 4 ] | [ 5 5 ] | -------------------------------------------------- return code is 0
REXX 语言环境允许您运行已编写的要在 DTW_REXX 环境中运行的 REXX 程序。“Net.Data REXX 语言环境”提供了允许 REXX 程序容易返回大量数据的控件。
Net.Data 还对将输出引导至浏览器的 REXX SAY 语句提供了支持,而不管用于 Net.Data 的是哪种 Web 服务器环境。如果您使用 Web 服务器 FastCGI、GWAPI 或小服务程序配置来运行本机 REXX,则来自 REXX SAY 语句的输出会按路径发送至 Web 服务器日志文件而不是浏览器。对于已编写的要在 DTW_REXX 环境中运行的 REXX 程序来说,不会出现这种情况。
对变量的支持: 为了允许 REXX 程序容易返回大量数据,Net.Data 会自动将代码添加到 REXX 程序的开头,以及将代码追加到 REXX 程序末尾。此代码是用来处理在 DTW_REXX 函数语句上所提供的变量的。
对 REXX SAY 语句(FastCGI、GWAPI 和 SERVLET 环境)的支持: 在执行 REXX 程序之前,REXX SAY 语句会被 Net.Data 自动转换成 REXX 赋值语句。Net.Data 会自动将代码追加到用来将输出从原始的 REXX SAY 语句引导至浏览器的 REXX 程序。使用 REXX 子例程和函数:由于 Net.Data 将代码添加到 REXX 程序前面,并将代码追加到 REXX 程序的末尾,因此,主要的 REXX 例程必须以 REXX 程序的最后一个语句结束。如果使用 REXX 子例程或函数,则必须确保 REXX 程序的最后一个语句与主要的 REXX 例程相关联。以下是在已编写的要在 DTW_REXX 环境中运行的 REXX 程序中使用子例程和函数的示例:
%function(DTW_REXX) genData(out s1,s2) { call subrtn1 s2=funrtn1() signal rexxEnd /* Go to end of Program */ subrtn1: PROCEDURE EXPOSE s1 string1 = "data for s1" return 0 funrtn1: PROCEDURE retvar = "data for s2" return retvar rexxEnd: /* End of Main Program */ return 0 %} %HTML (Report) { @genData(a,c) Value for s1: $(a) Value for s2: $(c) %}
使用 REXX EXIT 和 RETURN 语句: Net.Data 自动将代码追加到为输出变量提供值的 REXX 程序中,并将输出从 SAY 语句引导至浏览器。如果 REXX 程序从主例程发出 RETURN 或者从任何地方发出 EXIT 语句,但是不是 REXX 程序的最后一个语句, 则将不执行由 Net.Data 追加到 REXX 程序的代码。这将导致丢失 SAY 语句中的输出变量和输出。如果必须在到达最后一个语句之前退出 REXX 程序,则应该分支到正常退出的 REXX 程序中的最后一个语句。如果使用 RETURN 或 EXIT 语句来结束主要的 REXX 程序,则该语句必须是 REXX 程序中的最后一个语句。这包括 REXX 注释语句。例如:
%function(DTW_REXX) genData(out s1,s2) { ...... If S2 < 0 Then signal rexxEnd ...... ...... rexxEnd: /* This comment must be before the following RETURN statement */ return 0 %} %HTML (Report) { @genData(a,c) ...... %}
从 DTW_REXX 函数中调用外部的 REXX 程序: 可以使用 Net.Data %EXEC 语句来从 DTW_REXX 函数中调用 REXX 程序,或者使用由 REXX 提供的方法来从 REXX 程序中调用 REXX 程序。
当使用 Net.Data %EXEC 语句来调用外部的 REXX 程序时,Net.Data 会自动将代码添加到 REXX 程序前面,并将代码追加到 REXX 程序的末尾,以便处理 Output 变量并将输出从 REXX SAY 语句引导至浏览器。
当使用由 REXX 提供的方法来调用 REXX 程序时,Net.Data 不会接收控件,并且不会将代码添加至 REXX 程序。被调用的 REXX 程序必须将输出传送回使用标准 REXX 约定的调用 REXX 程序。当在 GWAPI 或 SERVLET 环境中运行时,来自 REXX SAY 语句的输出将被发送到 Web 服务器日志文件中。
要使用 REXX 语言环境,需要验证 Net.Data 的初始化设置,并设置语言环境。
验证初始化文件中有以下配置语句,并且是在一行上:
ENVIRONMENT (DTW_REXX) DTWREXX ( OUT RETURN_CODE )
参见 Net.Data 管理与编程指南,以进一步了解 Net.Data 初始化文件和语言环境 ENVIRONMENT 语句。
利用 REXX 语言环境,可以执行直接插入 REXX 程序或外部 REXX 程序。直接插入 REXX 程序是一种在宏中具有 REXX 程序的源的 REXX 程序。外部 REXX 程序在外部文件中具有 REXX 程序的源。
要执行直接插入 REXX 程序:
定义一个使用 REXX (DTW_REXX) 语言环境的函数,并在该函数的可执行的语言环境部分中包含 REXX 代码。
示例: 包含直接插入 REXX 程序的函数
%function(DTW_REXX) helloWorld() { SAY 'Hello World' %}
要运行外部 REXX 程序:
定义一个使用 REXX (DTW_REXX) 语言环境的函数,它包含一个路径,该路径指向要在 EXEC 语句中运行的 REXX 程序。
示例: 包含指向外部程序的 EXEC 语句的函数
%function(DTW_REXX) externalHelloWorld() { %EXEC{ helloworld.cmd%} %}
必需条件: 确保 REXX 文件名列示在 Net.Data 初始化文件中为 EXEC_PATH 配置变量指定的路径中。参见EXEC_PATH,以学习如何定义 EXEC_PATH 配置变量。
有两种方式将信息传送到 REXX (DTW_REXX) 语言环境调用的 REXX 程序,即:直接和间接。
%FUNCTION(DTW_REXX) rexx1() { %EXEC{CALL1.CMD $(INPARM) "literal string" %} %}
Net.Data 变量 INPARM1 被引用并被传送到外部的 REXX 程序。通过使用 REXX PARSE ARG 指令,REXX 程序可以引用变量。使用这种方法来传送给 REXX 程序的参数被认为是输入参数,并且对值所作的任何修改不会反映给 Net.Data(传送给程序的参数可以由程序使用和处理,但对参数的更改不会反映给 Net.Data)。
利用 REXX 程序变量池来间接传送参数。当启动了 REXX 程序时,会创建一个包含了关于所有变量的信息的空间, 并由 REXX 解释器来维护。此空间被称为变量池。
当调用 REXX 语言环境 (DTW_REXX) 函数时,REXX 语言环境将在执行 REXX 程序之前把任何输入 (IN) 或输入/输出 (INOUT) 的函数参数存储在该空间中。当调用 REXX 程序时,它可以直接访问这些变量。当成功完成 REXX 程序时,DTW_REXX 语言环境就会确定是否有任何输出 (OUT) 或 INOUT 函数参数。如果有,语言环境将从变量池中检索对应于函数参数的值,并使用新值来更新函数参数值。当 Net.Data 接收控件时,它便使用从 REXX 语言环境中获得的新值来更新所有 OUT 或 INOUT 参数。例如:
%DEFINE a = "3" %DEFINE b = "0" %FUNCTION(DTW_REXX) double_func(IN inp1, OUT outp1){ outp1 = 2*inp1 %} %HTML (Report) { Value of b is $(b), @double_func(a, b) Value of b is $(b) %}
在以上示例中,调用 @double_func 传送了两个参数 a 和 b。REXX 函数 double_func 将第一个参数加倍,然后将结果存储在第二个参数中。当 Net.Data 调用宏时,b 的值为 6。
可以将 Net.Data 表传送至 REXX 程序。REXX 程序作为 REXX stem 变量来访问 Net.Data 宏表参数的值。对于 REXX 程序,列标题和字段值都包含在用表名和列号标识的变量中。例如,在表 myTable 中, 列标题为 myTable_V.j,字段值为 myTable_V.i.j,其中 i 是行号,j 是列号。表中的行数为 myTable_ROWS,表中的列数为 myTable_COLS。
如果在 AIX 系统中有许多个对 REXX 语言环境的调用,则可以考虑 将 RXQUEUE_OWNER_PID 环境变量设置为 0。而调用此 REXX 语言环境的宏可以很方便地 调用许多进程、调用系统资源。
您可以用以下三种方式来设置环境变量:
@DTW_rSETENV("RXQUEUE_OWNER_PID", "0")
/etc/environment: RXQUEUE_OWNER_PID = 0
此方法将影响整个机器上 REXX 的功能。
InheritEnv RXQUEUE_OWNER_PID = 0
此方法将影响 Web 服务器上 REXX 的功能。
以下示例显示了一个宏调用 REXX 函数来生成具有两列、三行的 Net.Data 表。在调用 REXX 函数之后,调用内置函数 DTW_TB_TABLE() 来生成发送回浏览器的 HTML 表。
%DEFINE myTable = %TABLE %DEFINE DTW_DEFAULT_REPORT = "NO" %FUNCTION(DTW_REXX) genTable(out out_table) { out_table_ROWS = 3 out_table_COLS = 2 /* Set Column Headings */ do j=1 to out_table_COLS out_table_N.j = 'COL'j end /* Set the fields in the row */ do i = 1 to out_table_ROWS do j = 1 to out_table_COLS out_table_V.i.j = '[' i j ']' end end %} %HTML (Report) { @genTable(myTable) @DTW_TB_TABLE(myTable) %}
结果:
<table> <tr> <th>COL1</th> <th>COL2</th> </tr> <tr> <td>[1 1]</td> <td>[1 2],</td> </tr> <tr> <td>[2 1]</td> <td>[2 2],</td> </tr> <tr> <td>[3 1]</td> <td>[3 2],</td> </tr> </table>
System 语言环境支持执行命令和调用外部程序。
在初始化文件中添加以下配置语句,并且是在一行上:
ENVIRONMENT (DTW_SYSTEM) DTWSYS ( OUT RETURN_CODE )
参见 Net.Data 管理与编程指南,以进一步了解 Net.Data 初始化文件和语言环境 ENVIRONMENT 语句。
要发出一个命令,可以定义使用 System (DTW_SYSTEM) 语言环境的函数, 它包含一个路径,该路径指向要在 EXEC 语句中发出的命令。例如:
%FUNCTION(DTW_SYSTEM) sys1() { %EXEC { ADDLIBLE.CMD %} %}
如果使用 EXEC_PATH 配置变量来定义至包含可执行对象(例如,命令和程序)的目录的路径, 则可以缩短至该对象的路径。参见EXEC_PATH,以学习如何定义 EXEC_PATH 配置变量。
示例 1: 调用程序
%FUNCTION(DTW_SYSTEM) sys3() { %EXEC {MYPGM.EXE %} %
有两种方式将信息传送到 System (DTW_SYSTEM) 语言环境调用的程序,直接和间接。
%DEFINE INPARM1 = "SWITCH1" %FUNCTION(DTW_SYSTEM) sys1() { %EXEC{ CALL1.CMD $(INPARM1) "literal string" %} %}
Net.Data 变量 INPARM1 被引用并被传送到程序。参数传送到程序的方式与从命令行调用程序时参数传送到程序的方式相同。使用此方法传送给程序的参数被认为是输入参数,并且对值所作的任何修改都不会反映给 Net.Data(传送给程序的参数可以由程序使用和处理,但对参数的更改不会反映给 Net.Data)。
System 语言和不能直接传送或检索 Net.Data 变量,因此这些变量以如下方式使程序可以使用它们:
name="value"
对于复合数据项,可以用一个新行字符 或空字符分开每个项。
如果一个变量名称与输出参数的名称相同且使用上述语法, 则新的值将替换当前值。如果变量名不对应于输出参数,Net.Data 将把它忽略。
以下示例显示了 Net.Data 如何从一个宏传送变量。
%FUNCTION(DTW_SYSTEM) sys1 (IN P1, OUT P2, P3) { %EXEC { UPDPGM %} %}
您可以通过 System 语言环境将 Net.Data 表传送给一个被调用的程序。该程序根据它们的 Net.Data 名来访问 Net.Data 宏表参数的值。列标题和字段值都包含在用表名和列号标识的变量中。例如,在表 myTable 中,列标题是 myTable_N_j, 字段值是 myTable_V_i_j,其中 i 是行号,j 是列号。表的行数与列数是 myTable_ROWS 和 myTable_COLS。
以下示例显示了一个包含函数定义的宏,其中有三个参数 P1、P2 和 P3。P1 是一个输入 (IN) 参数,P2 和 P3 是输出 (OUT) 参数。函数调用程序 UPDPGM,它用 P1 的值更新参数 P2,并将 P3 设置为字符串。在处理 %EXEC 块中的语句之前,DTW_SYSTEM 语言环境在环境空间中存储 P1 和相应的值。
%DEFINE{ MYPARM2 = "ValueOfParm2" MYPARM3 = "ValueOfParm3" %} %FUNCTION(DTW_SYSTEM) sys1 (IN P1, OUT P2, P3) { %EXEC { UPDPGM %} %} %HTML(upd1) { <p> Passing data to a program. The current value of MYPARM2 is "$(MYPARM2)", and the current value of MYPARM3 is "$(MYPARM3)". Now we invoke the Web macro function. <p> @sys1("ValueOfParm1", MYPARM2, MYPARM3) <p> After the function call, the value of MYPARM2 is "$(MYPARM2)", and the value of MYPARM3 is "$(MYPARM3)". <p> %}