You are browsing the archive for web service.

使用Bpel调用IREP中发布的Web Service

十二月 30, 2009 in Oracle EBS二次开发

Oracle EBS R12中提供了将系统接口和客户化接口发布成Web Service的功能,下面将尝试使用Oralce SOA Suite 11g中的Bpel对其进行调用。

 

一、开发以及测试环境

EBS R12.1.1

Weblogic 10.3.1

Oracle SOA Suite 11.1.1.2

Jdeveloper 11.1.1.2.0

二、前提设置

本文描述如何建立一个调用IREP中WEB SERVICE的BPEL流程。在开始之前,必须对一些环境进行安装和设置。涉及到的内容有:

Read the rest of this entry →

WebService系列:问题处理(Troubleshooting)

二月 14, 2009 in Oracle 融合中间件

 

 

WebService系列讲解PLSQL Web Service + OC4J 开发过程中遇到很多的问题,本文将一些常见的问题进行整理,以备后续查阅

这些问题的解决方案不一定是唯一的解决方法,参考的过程中请根据实际情况进行比较的筛选

 

1,OC4J运行Web Service:Missing <wsse:Security> in SOAP Header

原因:SOAP头中没有包括安全验证的信息,需要为请求的消息提供SOAP头信息

解决方案:实现IHeaderHandler接口的类,并赋给Soapclient30的实例;如果使用OC4J测试界面,选择必须的选项,让它包括头信息

 

2,VBA代理程序报错:解析SOAP头失败

背景:已经实现了IHeaderHandler接口,并赋给了Soapclient30的实例,同时OC4J服务器端没有报出任何错误,但是VBA代理程序报错:解析SOAP头失败

我遇到的原因:IHeaderHandler接口的实现类中IHeaderHandler_ReadHeader和IHeaderHandler_WillWriteHeaders函数没有返回True

解决方案:修改IHeaderHandler_ReadHeader和IHeaderHandler_WillWriteHeaders方法的返回值为True

 

3,OC4J运行Web Service:返回自定义Table类型报OWS-04005错误

原因:由于在JDeveloper中发布Web Services的时候没有包括自定义类型的实现类

解决方案:重新发布,选择需要的Java Class文件

 

4,PLSQL:传入Table参数多出一行空行

问题描述:传入的Table类型参数,传到PL/SQL端后,由于序列化的缘故,它会自动在Table后面添加一行空的记录因此在进行PL/SQL处理的时候,需要将Count减1。
                  否则很有可能报出不能插入Null的错误,当然这样的错误很有可能也是程序中没有提供必要的值,需要进行仔细的检查

解决方案:PLSQL程序中将PLSQL 记录表变量的数量减1

 

5,OC4J运行Web Service:Policy requires nonce

错误信息如下:ERROR OWS-04005 An error occurred for port: xxxx: oracle.j2ee.ws.common.soap.fault.SOAP11FaultException: Policy requires nonce.

原因:添加安全验证信息的时候有一个选项没有去掉(Nonce Required in Token/标记中所需的现时)

解决方案:修改Web Services的安全验证设置后重新发布或者在OC4J上面修改选项

 

6,OC4J运行Web Service:The security token could not be authenticated or authorized

原因:提供的安全验证用户名或者密码不正确,这个错误信息不属于程序的错误

解决方案:提供正确的信息,如果无法解决请找OC4J管理员协助

 

以上是我在实际的开发过程中遇到的一些关键问题!!!

 

WebService系列:Office VBA调用已安全性认证的Web Service

二月 14, 2009 in Oracle 融合中间件

 

上一篇文章中已经描述了如何生成 Office VBA 客户端代理程序来调用 Web Service,但是如果Web Service已

添加了安全性认证的话,仅仅使用MS Office2003 WebServices Tools工具产生的代理程序还不足以完成调用。

 

本文描述如何扩展Microsoft提供的SOAP Toolit中的IHeaderHandler接口来格式化SOAP Headers,进而实现

调用Web Service时提供必要的安全认证信息,本文只描述最基本的基于用户名口令认证方式。

 

一、编写安全认证的SOAP头信息

 

WebService系列:为WebService添加安全性一文中,当调用一个已添加安全验证的Web Service时,需要提供必要的验证信息,

验证信息包含在SOAP Header部分,本文的目标就是在VBA代理程序调用Web Service时,添加如下的SOAP Header信息到Web Service的请求消息中

1
2
3
4
5
 
 
 
               aronehome
               aronehome

 

在前面的文章中已经说明了VBA代理类主要完成的任务,其中就是初始化一个Soapclient30的实例,

而Soapclient30提供了一个属性HeaderHandler来接收实现IHeaderHandler接口的实现类。

而HeaderHandler对象定义了SOAP头如何读取和写入,下面就描述如何编写实现IHeaderHandler接口的VBA类模块 UserTokenAuthHelper 来返回一个OC4J Web Service能够识别的SOAP头信息。

下面是实现的类模块代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
Option Explicit
 
Implements IHeaderHandler
 
Private Const XmlnsSoap As String = "http://schemas.xmlsoap.org/soap/envelope/"
Private Const SecurityXmlnsWsse As String = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
Private Const SecurityXmlns As String = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
Private Const SecurityXmlnsEnv As String = "http://schemas.xmlsoap.org/soap/envelope/"
Private Const UsernameTokenXmlnsWsse As String = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
Private Const UsernameTokenXmlns As String = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
Private Const WssePasswordType As String = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"
 
Private myUsernameToken As String
Private myPassword As String
Private myMustUnderstand As Integer
 
Public Property Let UsernameToken(ByVal pUsernameToken As String)
    myUsernameToken = pUsernameToken
End Property
 
Public Property Get UsernameToken() As String
    UsernameToken = myUsernameToken
End Property
 
Public Property Let Password(ByVal pPassword As String)
    myPassword = pPassword
End Property
 
Public Property Get Password() As String
    Password = myPassword
End Property
 
Public Property Let MustUnderstand(ByVal pMustUnderstand As Integer)
    myMustUnderstand = pMustUnderstand
End Property
 
Public Property Get MustUnderstand() As Integer
    MustUnderstand = myMustUnderstand
End Property
 
Private Function IHeaderHandler_ReadHeader(ByVal par_Reader As MSOSOAPLib30.ISoapReader, ByVal par_HeaderNode As MSXML2.IXMLDOMNode, ByVal par_Object As Object) As Boolean
    IHeaderHandler_ReadHeader = True
End Function
 
Private Function IHeaderHandler_WillWriteHeaders() As Boolean
    IHeaderHandler_WillWriteHeaders = True
End Function
 
Private Sub IHeaderHandler_WriteHeaders(ByVal par_ISoapSerializer As MSOSOAPLib30.ISoapSerializer, ByVal par_Object As Object)
    Dim tempHeaderDoc As String
    tempHeaderDoc = ""
    tempHeaderDoc = tempHeaderDoc &amp; " " _
                    &amp; "" _
    tempHeaderDoc = tempHeaderDoc &amp; " " _
                    &amp; "" &amp; myUsernameToken &amp; "" _
                    &amp; "" &amp; myPassword &amp; ""
    tempHeaderDoc = tempHeaderDoc &amp; "" _
                    &amp; "" _
                    &amp; ""
    par_ISoapSerializer.WriteXml tempHeaderDoc   
End Sub

上面的UserTokenAuthHelper类实现了按照OC4J的要求将安全验证需要的SOAP Header信息添加到请求消息中的功能

 

二、添加UserTokenAuthHelper实现类到Web Services代理类

 

上面已经实现了UserTokenAuthHelper类来添加SOAP Header信息,用于进行安全验证。只要修改MS Office2003 WebServices Tools生成的Web Services代理类,

将SOAP头信息传给消息即可,在代理类Class_Initialize()方法的最后添加如下的代码:

1
2
3
4
5
6
7
'用户认证
Dim objCurAuthHelper As UserTokenAuthHelper
Set objCurAuthHelper = New UserTokenAuthHelper
objCurAuthHelper.UsernameToken = "aronehome"
objCurAuthHelper.Password = "aronehome"
objCurAuthHelper.MustUnderstand = 1
Set sc_UserListInfo.HeaderHandler = objCurAuthHelper

 

在任何一个代理类都是相同的代码,只要根据实际代理类替换红色部分的Soapclient30变量就可以了。

 

再次运行VBA程序进行调试,提供正确的用户和密码,程序能够成功运行。上面代码中的用户名和密码直接写为aronehome/aronehome,根据情况进行修改,

最后将其修改为让用户录入的方式来提供,当然如果你提供错误的用户名或者密码,那Web Services返回的错误应该是:The security token could not be authenticated or authorized.

 

 

VBA客户端代理程序下载:Download TEMPLFLD_R11i Version 1

 

 

WebService系列:Office VBA调用Web Service

二月 13, 2009 in Oracle 融合中间件

 

 

Microsoft Office软件作为办公软件系统,已成为人们日常工作的必备工具,而其中的Excel更是各类人员的得力工具,

本文介绍基于Office VBA生成Web Service的客户端代理程序,使VBA程序能够调用Web Service。

 

基于的系统配置如下:

  1. Window XP
  2. Office 2003
  3. MS Office2003 WebServices Tools
  4. SOAP Toolkit3.0
  5. OC4J 10.1.3.3.0

 

一、使用MS Office2003 WebServices Tools

 

MS Office2003 WebServices Tools工具是为了简化在VBA中编写Web Services代理程序代码而设计的一个辅助工具,

它根据Web Services的wsdl描述文件生成对应的代理类以及用户自定义的类型结构类。

 

在 Office 应用程序中,单击“Visual Basic 编辑器”的“工具”菜单中的“Web 服务引用”即可启动 Microsoft Office 2003 Web Services Toolkit。

该工具提供了可用于下列用途的界面:

  1. 发现 Web 服务
  2. 选择所需的服务
  3. 创建为引用这些服务的 Visual Basic for Applications (VBA) 项目充当 Web 服务代理的类。

 

27.office2003_ws_tookit

 

选择“Web服务URL(U)”,输入wsdl的URL地址,如

http://ORACLE:8888/aronehome/UserListInfoSoapHttpPort

点击搜索按钮,右边会显示出Web Services拥有的方法,点击“添加”按钮创建各种类。

根据wsdl的描述内容,它会创建几个类型的类文件:

类前缀 类类型 说明
clsof_Factory_ 对象工厂 如果有用户定义的类型结构则产生
clsws_ Web 服务代理 Web Service的代理类,任何时候都产生
struct_ 用户定义的类型结构 非基本类型,用户自定义的类型则会产生,如PL/SQL中用户定义的Type或者Table都会产生

 

如上面的UserListInfo Web Services会产生如下的3个VBA类模块:

  1. clsof_Factory_UserListInfo
  2. clsws_UserListInfo
  3. struct_AronehomeDemoWs2User:对应的是PL/SQL中声明的user_type自定义类型

 

 

二、服务代理类模块描述

 

Web服务代理类模块主要完成以下工作:

  1. 实例化类(Class_Initialize),按照wsdl要求的类型创建一个SoapClient30对象实例
  2. 通过实例化的SoapClient30对象调用方法(wsm_getUserList(),wsm_updateUserInfo(ByVal ar_pUserList As Variant))
  3. 结束调用(Class_Terminate),释放资源

 

下面是clsws_UserListInfo服务的代理类模块的代码片段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
Private sc_UserListInfo As SoapClient30
Private Const c_WSDL_URL As String = "http://oracle:8888/aronehome/UserListInfoSoapHttpPort?wsdl"
Private Const c_SERVICE As String = "UserListInfo"
Private Const c_PORT As String = "UserListInfoSoapHttpPort"
Private Const c_SERVICE_NAMESPACE As String = "http://com/aronehome/demo/UserListInfo.wsdl"
 
Private Sub Class_Initialize()
    Dim str_WSML As String
    str_WSML = ""
    str_WSML = str_WSML &amp; ""
    str_WSML = str_WSML &amp; ""
    str_WSML = str_WSML &amp; ""
    str_WSML = str_WSML &amp; ""
    str_WSML = str_WSML &amp; ""
    str_WSML = str_WSML &amp; ""
    str_WSML = str_WSML &amp; ""
 
    Set sc_UserListInfo = New SoapClient30
 
    sc_UserListInfo.MSSoapInit2 c_WSDL_URL, str_WSML, c_SERVICE, c_PORT, c_SERVICE_NAMESPACE
    'Use the proxy server defined in Internet Explorer's LAN settings by
    'setting ProxyServer to 
    sc_UserListInfo.ConnectorProperty("ProxyServer") = ""
    'Autodetect proxy settings if Internet Explorer is set to autodetect
    'by setting EnableAutoProxy to True
    sc_UserListInfo.ConnectorProperty("EnableAutoProxy") = True
 
    Set sc_UserListInfo.ClientProperty("GCTMObjectFactory") = New clsof_Factory_UserListInfo
 
End Sub
 
Private Sub Class_Terminate()
 
    'Error Trap
    On Error GoTo Class_TerminateTrap
 
    Set sc_UserListInfo = Nothing
 
Exit Sub
 
Class_TerminateTrap:
    UserListInfoErrorHandler ("Class_Terminate")
End Sub
 
Private Sub UserListInfoErrorHandler(str_Function As String)
 
    'SOAP Error
    If sc_UserListInfo.FaultCode &lt;&gt; "" Then
        Err.Raise vbObjectError, str_Function, sc_UserListInfo.FaultString
    'Non SOAP Error
    Else
        Err.Raise Err.Number, str_Function, Err.Description
    End If
 
End Sub
 
Public Function wsm_getUserList() As Variant
    'Error Trap
    On Error GoTo wsm_getUserListTrap
 
    wsm_getUserList = sc_UserListInfo.getUserList()
 
Exit Function
wsm_getUserListTrap:
    UserListInfoErrorHandler "wsm_getUserList"
End Function
 
Public Sub wsm_updateUserInfo(ByVal ar_pUserList As Variant)
    'Error Trap
    On Error GoTo wsm_updateUserInfoTrap
 
    sc_UserListInfo.updateUserInfo ar_pUserList
 
Exit Sub
wsm_updateUserInfoTrap:
    UserListInfoErrorHandler "wsm_updateUserInfo"
End Sub

 

这样VBA程序或者VBA宏就可以调用服务代理类中的方法来调用Web Service了 

 

三、编写VBA宏代码调用代理类方法来调用Web Service

 

上面通过MS Office2003 WebServices Tools工具已经生成了调用Web Service的VBA代理类,下面编写VBA宏代码来调用它们

 

1,调用结果返回自定义复杂类型

上面的PL/SQL函数示例声明中看到,get_user_list函数返回一个基于自定义类型user_type的Table类型user_tbl,

对应的是通过MS Office2003 WebServices Tools工具可以生成的代理类clsws_UserListInfo中的wsm_getUserList()方法

下面是VBA宏代码调用的片段:

1
2
3
4
5
6
7
8
9
10
11
Dim clsUserListInfo As clsws_UserListInfo
Dim objCurUserListArray() As struct_AronehomeDemoWs2User
Dim objCurUser As struct_AronehomeDemoWs2User
 
Set clsUserListInfo = New clsws_UserListInfo
objCurUserListArray = clsUserListInfo.wsm_getUserList
 
For i = 0 To UBound(objCurUserListArray)
    Set objCurUser = objCurUserListArray(i)
    MsgBox objCurUser.username + "" + objCurUser.password
Next

 

2,提供复杂数据类型参数调用WebServices

 

上面的PL/SQL函数示例声明中看到,update_user_info函数返回一个基于自定义类型user_type的Table类型user_tbl,

对应的是通过MS Office2003 WebServices Tools工具可以生成的代理类clsws_UserListInfo中的wsm_getUserList()方法

下面是VBA宏代码调用的代码片段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Dim lines As Integer
Dim clsUpdateUserInfo As clsws_UserListInfo
Dim objCurUserInfoArrary() As struct_AronehomeDemoWs2User
Dim objCurUserInfo As struct_AronehomeDemoWs2User
 
lines = 3
 
ReDim objCurUserInfoArrary(lines) As struct_AronehomeDemoWs2User
 
For i = 1 To 3
    Set objCurUserInfo = New struct_AronehomeDemoWs2User
    objCurUserInfo.userid = i
    objCurUserInfo.username = "a" + i
    objCurUserInfo.password = "b" + i
 
    Set objCurUserInfoArray(i) = objCurUserInfo
Next
 
Set clsUpdateUserInfo = New clsws_UserListInfo
clsUpdateUserInfo.wsm_updateUserInfo objCurUserInfoArray

 

注:上面传给Web Service的Table为objCurUserInfoArray,而PL/SQL在接收到这个Table时的count数要比实际的多一行,多出的一行全是空值,

是由于SOAP在进行序列化的过程中添加的,因此在PL/SQL代码中,需要将传入的Table变量的count数减去1,可能有的同学已经注意到PLSQL update_user_info方法中的“p_user_list.count -1”了。

 

三、执行VBA程序

 

如果上面的Web Service按照前期的课题中一样添加的安全性配置,那通过上面的代码在VBA程序中调用Web Services是执行不成功的,报出如下的错误:
ERROR OWS-04005: Missing <wsse:Security> in SOAP Header
和我们使用OC4J自带的测试页面进行测试时一样的错误,是由于没有提供安全验证信息到SOAP Header中。
而通过MS Office2003 WebServices Tools工具为我们产生的Web Services代理类中没有安全验证相关的内容,我们需要自己编写程序来产生SOAP Header的内容

 

 

下一篇文章将描述如何在VBA调用中添加认证信息以支持Web Service的认证

 

 

WebService系列:创建PL/SQL复合式数据类型Web Services

二月 13, 2009 in Oracle 融合中间件

 

 

本文描述基于PLSQL中记录和记录表复合式数据类型的功能函数来创建Web Services。

 

一、创建Web Service

 

1,准备数据

我就利用前面文章中用来验证的用户信息表 sec_users 作为操作的实例

1
2
3
4
5
INSERT INTO sec_users VALUES(1,'aronehome','aronehome');
INSERT INTO sec_users VALUES(2,'aronezhang','aronezhang');
INSERT INTO sec_users VALUES(3,'amyyu','amyyu');
 
COMMIT;

 

2,PL/SQL函数功能声明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
CREATE OR REPLACE PACKAGE aronehome_demo_ws2 IS
 
  TYPE user_type IS RECORD (
    userid    NUMBER,
    username  VARCHAR2(30),
    password  varchar2(30)
  );
  TYPE user_tbl IS TABLE OF user_type INDEX BY BINARY_INTEGER ;
 
  FUNCTION get_user_list RETURN user_tbl;
  PROCEDURE update_user_info(p_user_list user_tbl) ;
 
END aronehome_demo_ws2;
/
 
CREATE OR REPLACE PACKAGE BODY aronehome_demo_ws2 IS
 
  FUNCTION get_user_list RETURN user_tbl IS
    l_user_list user_tbl;
  BEGIN
    l_user_list.delete ;
 
    FOR cur IN (SELECT userid , username, password FROM sec_users) LOOP
      l_user_list(l_user_list.COUNT + 1) := cur;
    END LOOP;
 
    RETURN l_user_list;
  END get_user_list;
 
  PROCEDURE update_user_info(p_user_list user_tbl) IS
  BEGIN
    FOR i IN 1 .. p_user_list.count -1 LOOP
       UPDATE sec_users
          SET password = p_user_list(i).password
        WHERE userid = p_user_list(i).userid;
    END LOOP;
  END update_user_info;
 
END aronehome_demo_ws2;
/

 

上面两个函数过程的声明:

  1. get_user_list 函数用来得到用户信息列表,返回一个Table数据类型作为结果
  2. update_user_info过程用来成批更新用户的密码,传入一个Table数据类型作为参数

 

3,创建WebService

 

创建的详细步骤请参考前面相关的文章,由于后续文章需要从Microsoft VBA调用发布的WebServices,因此在创建WebServices的时候需要特别注意两个地方

  1. 创建PL/SQL J2EE 1.4 Web Service的第一个步骤中需要选择SOAP1.1 Binding标准
  2. 第二个步骤中需要选择SOAP Message Format为:RPC/Encoded
  3. 其它步骤没有特殊的地方

 

最后发布Web Service,对应的endpoint为:http://ORACLE:8888/aronehome/UserListInfoSoapHttpPort,WSDL文件包含在附件下载中

 

二、SQL到XML类型映射(Call-Ins)

 

从WebServices调用数据库资源的时候(Call-Ins),一个SQL操作如PL/SQL的存储过程、函数或者SQL语句都被映射为Web服务操作,

SQL操作的参数会从SQL的类型映射为XML类型,下表列出复合式SQL数据类型与XML类型间的映射

SQL 类型 XML 类型
Primitive PL/SQL indexby table Array
PL/SQL indexby table complexType
PL/SQL record complexType
SQL table complexType

注:此表不包括基本SQL类型与XML类型间的映射

 

下面我们来看看一段wsdl内容的片断代码

1
 

 

上面ArrayOfAronehomeDemoWs2UserTypeUser复合式类型就是由AronehomeDemoWs2UserTypeUser类型的元素组成,

而AronehomeDemoWs2UserTypeUser则是由AronehomeDemoWs2UserTypeBase基础类型扩展而来的类型,AronehomeDemoWs2UserTypeBase基础类型由:

userid:decimal
username:string
password:string

三个元素组成,这样的结构和PL/SQL table的结构是一样的。在JDeveloper的结构窗口中可以看到类型对应的Java实现类

26.ws_java_class

 

相关的JDeveloper Wordspace文件:Download Oracle EBS二次开发系列视频教程之开发基于Table的Form(4) Version 1 

 

下一篇文章将描述如何生成Microsoft VBA的Web Service客户端代理程序