ERP都是以财务会计为导向的系统,就连SAP ECC也不可能完胜企业的每个业务模块,这就需要其他软件作为外围系统给以支持,最终将数据在ERP系统汇总。此外,企业也少不了与客户 供应商 代工厂 物流 多方向数据交互。这些情况都需要ERP提供数据接口支持,目前,最流行的当然是WebService, 主流的ERP开发语言都支持这个,不主流的也支持,下面我们就看下不主流的Genero如何搭建WebServce Server&Client端的
Server端:直接上代码,传递的是我们ERP经常用到的Table结构数据
IMPORT com
GLOBALS
TYPE body RECORD #定义一个全局的body结构类型
store_num INT,
store_name CHAR(20),
addr CHAR(20),
city CHAR(20),
contact_name CHAR(30),
phone CHAR(18),
order_num INT,
quantity SMALLINT,
PRICE DECIMAL(8,2),
stock_num INT,
description CHAR(15)
END RECORD
DEFINE mycust RECORD #定义一个结构类型,包含一个参照body结构的动态二维数组(其实就是一个Table结构)
input DYNAMIC ARRAY OF body
END RECORD
END GLOBALS
MAIN
DEFINE l_connect STRING
DEFINE ret INTEGER
#连接数据库
LET l_connect = "AnyDBName+driver='dbmsqt3xx',source='C:/Users/mtk68099/Documents/My Genero Files/samples/databases/custdemo/sqlite/custdemo.db'"
CONNECT TO l_connect
IF SQLCA.SQLCODE THEN
EXIT PROGRAM SQLCA.SQLCODE
END IF
CALL createservice() #创建Server端服务
DISPLAY "Starting server..."
CALL com.WebServiceEngine.Start()
DISPLAY "The server is listening."
WHILE TRUE
# Process each incoming requests (infinite loop)
LET ret = com.WebServiceEngine.ProcessServices(-1) #Server端响应状态
DISPLAY "Processing request..."
CASE ret
WHEN 0
DISPLAY "Request processed."
WHEN -1
DISPLAY "Timeout reached."
WHEN -2
DISPLAY "Disconnected from application server."
EXIT PROGRAM
WHEN -3
DISPLAY "Client Connection lost."
WHEN -4
DISPLAY "Server interrupted with Ctrl-C."
WHEN -10
DISPLAY "Internal server error."
END CASE
IF int_flag<>0 THEN
LET int_flag=0
EXIT WHILE
END IF
END WHILE
DISPLAY "Server stopped"
END MAIN
FUNCTION createservice()
DEFINE service com.WebService # A WebService
DEFINE op com.WebOperation # Operation of a WebService
#Create WebService object
LET service = com.WebService.CreateWebService("myReply", "http://dongdongli/server")
#Create WebOperation object
LET op = com.WebOperation.CreateRPCStyle("reply", "Reply", mycust, null)
#publish the operation, associating with the WebService object
CALL service.publishOperation(op,NULL)
#Register the webService
CALL com.WebServiceEngine.RegisterService(service)
END FUNCTION
#将接收到Client端的数据,显示出来
FUNCTION reply()
DEFINE X INT
LET x = 1
FOR x = 1 TO mycust.input.getLength()
DISPLAY mycust.input[x].*
END FOR
CALL mycust.input.clear()
END FUNCTION
如果对 FUNCTION createservice 里面的参数不理解,你可以点击应用程式 右键新建一个SOA->SOAP Server,里面有详细的参数说明(这里我就不多废话了), 最简单的,你也可以拿这个SOAP Server.4gl做Template,写自己的Function就好
OK 编译启动我们的WebService Server端,启动顺利,正在等待我们的Client端调用。迫不及待写Client端了吧,下面我们就开始:
Client端:先不急着上代码,因为这里很多不需要你手动写。有了Server端,我们要知道URL, 根据URL和方法得到我们想要的WSDL,所以我们得到WSDL
http://http://17X.2X.134.12X/dongdongli/server/myReply?WSDL ,浏览器打开看看是否OK
打开另外一个Genero Studio 写我们的Client端
点击应用程式 右键加入Web Service->Client 消耗WSDL(什么破翻译)->输入我们的WSDL 点结束就OK了,编译产生的wsdl文件,新建一个4gl,把产生的wsdl内容全部copy到4gl里面去,下面你只要做两件事就好了,写一个MAIN函数, 写一个Reply Function(这里一定要 CALL Reply_g() ,这是调用Server端的Funtion),很简单基本不用我说什么
#-------------------------------------------------------------------------------
# File: untitled-5.4gl
# GENERATED BY fglwsdl 134149
#-------------------------------------------------------------------------------
# THIS FILE WAS GENERATED. DO NOT MODIFY.
#-------------------------------------------------------------------------------
IMPORT FGL WSHelper
IMPORT com
IMPORT xml
GLOBALS "untitled-6.inc"
GLOBALS
DEFINE l_input INT
DEFINE i INT
TYPE cust_struct DYNAMIC ARRAY OF RECORD
store_num INTEGER,
store_name CHAR(20),
addr CHAR(20),
city CHAR(20),
contact_name CHAR(30),
phone CHAR(18),
order_num INT,
quantity SMALLINT,
PRICE DECIMAL(8,2),
stock_num INT,
description CHAR(15)
END RECORD
DEFINE g_status CHAR(2),
mycust cust_struct
END GLOBALS
#-------------------------------------------------------------------------------
# Service: myReply
# Port: myReplyPortType
# Server: http://172.28.134.129/dongdongli/server/myReply
#-------------------------------------------------------------------------------
PRIVATE DEFINE ReplyHTTPReq com.HTTPRequest
PRIVATE DEFINE ReplyHTTPResp com.HTTPResponse
MAIN
DEFINE l_connect STRING
LET l_connect = "AnyDBName+driver='dbmsqt3xx',source='C:/Users/mtk68099/Documents/My Genero Files/samples/databases/custdemo/sqlite/custdemo.db'"
CONNECT TO l_connect
IF SQLCA.SQLCODE THEN
EXIT PROGRAM SQLCA.SQLCODE
END IF
PREPARE p1 FROM
"SELECT a.store_num, a.store_name, a.addr, a.city, a.contact_name, a.phone,
b.order_num, c.quantity, c.price, c.stock_num, d.description
FROM customer AS a
INNER JOIN orders AS b
INNER JOIN items AS c
INNER JOIN stock AS d
WHERE a.store_num = b.store_num AND b.order_num = c.order_num
AND c.stock_num = d.stock_num AND a.store_num = ?"
DECLARE c1 CURSOR FOR p1
CLOSE WINDOW SCREEN
OPEN WINDOW w1 AT 1,1 WITH FORM "ConnectToDB"
CALL display_store()
MENU ""
ON ACTION NEXT
CALL display_store()
ON ACTION QUIT
EXIT MENU
ON ACTION CLOSE
EXIT MENU
END MENU
CLOSE FORM ConnectToDB
CLOSE WINDOW w1
END MAIN
FUNCTION display_store()
INPUT l_input FROM store_input
AFTER FIELD store_input
OPEN c1 USING l_input
WHILE i >= 1
CLEAR record1[i].*
LET i = i - 1
END WHILE
CALL mycust.clear()
FOREACH c1 INTO mycust[i+1].*
DISPLAY mycust[i+1].* TO record1[i+1].*
LET i = i + 1
END FOREACH
CLOSE C1
CALL Reply()
END INPUT
END FUNCTION
# Operation: Reply
#-------------------------------------------------------------------------------
FUNCTION Reply()
DEFINE X,Y INT
LET x = 1
LET Y = mycust.getLength()
CALL Reply.input.element.clear()
# Reply结构定义在untitled-6.inc里
FOR X = 1 TO Y
LET Reply.input.element[x].store_num = mycust[x].store_num
LET Reply.input.element[x].store_name = mycust[x].store_name
LET Reply.input.element[x].addr = mycust[x].addr
LET Reply.input.element[x].city = mycust[x].city
LET Reply.input.element[x].contact_name = mycust[x].contact_name
LET Reply.input.element[x].phone = mycust[x].phone
LET Reply.input.element[x].order_num = mycust[x].order_num
LET Reply.input.element[x].quantity = mycust[x].quantity
LET Reply.input.element[x].PRICE = mycust[x].PRICE
LET Reply.input.element[x].stock_num = mycust[x].stock_num
LET Reply.input.element[x].description = mycust[x].description
END FOR
CALL Reply_g() RETURNING g_status
END FUNCTION
这个主要功能和DB Connect那篇文章类似,只不过每次把Client端查询的结构发送给了Server端