You are browsing the archive for web service.

WebService系列:OC4J安全性提供程序

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

 

 

上面的章节中我们添加了WS安全认证之后执行Web Service报出:wsse:FailedAuthentication的错误,这是由于验证失败的缘故。

为了验证Web Services的安全信息,需要在OC4J服务器端对Web Services所属的Web应用设置安全验证方式,OC4J提供了四种安全验证的方式:

  1. 基于文件的安全提供程序
  2. Oracle Identity Management安全提供程序
  3. 用于第三方LDAP服务器的Oracle安全提供程序
  4. 定制的安全提供程序

 

本文基于本人实际使用过的1,4两种安全提供程序方式的描述

 

一、基于文件的安全提供验证

 

本节采用OC4J默认的“基于文件的安全提供程序”来进行Web Services安全验证,设置步骤如下:

  1. 登录OC4J EM管理页面
  2. 选择“应用程序”标签页中的应用“aronehome”
  3. 选择“应用程序:aronehome”下的标签页“管理”页中的“安全提供程序”任务,选择“转到任务”链接图标
  4. 进入安全提供程序设置界面,选择“领域”标签
  5. 选择角色的数字链接进入角色定义和查询界面
  6. 选择用户的数字链接进入用户定义和查询界面

 

15.ws_web_app_home

 

16.security_provider

 

17.file_based_security_provider

 

18.file_based_security_provider_user

 

19.file_based_security_provider_add_user

 

根据验证的需要创建不同的用户信息,如本示例创建用户:aronehome/aronehome

只要是在这里创建的用户信息都可以用来验证本应用下的安全Web Services,在调用启用了安全验证的Web Service时,

如果调用程序没有提供用来验证的用户信息或者是提供了上面未定义的被认为错误的验证信息,则不会调用Web Services。

 

设置好用户信息之后,再次运行Web Service进行测试!

 

二、定制的安全提供程序

 

基于文件的安全性认证对于在实际的应用中很难满足灵活的用户管理,因此本文描述如何使用定制类型的安全提供程序来通过编写PLSQL程序从数据库表sec_users中验证用户。

下面使用OTN提供的DatabaseLoginModule来, 相关的Jar从OTN下载:http://www.oracle.com/technology/products/jdev/howtos/10g/jaassec/jaasdatabaseloginmodule.zip

1,配置JAR环境

  1. 拷贝DBLoginModule.jar文件包到$ORACLE_HOME/j2ee/home/lib目录下
  2. 修改文件$ORACLE_HOME/j2ee/home/config/application.xml,添加内容:
    <library path=”../../home/lib/DBLoginModule.jar”/>
  3. 重启OC4J

 

2,创建用户信息表

1
2
3
4
5
6
7
8
CREATE TABLE sec_users(
  userid     NUMBER,
  username   VARCHAR2(30),
  PASSWORD   VARCHAR2(30)
);
 
INSERT INTO sec_users VALUES(1,'aronehome','aronehome');
COMMIT;

 

3,编写用户验证的PLSQL过程

下面是一个例子,实际的验证请根据数据库表进行必要的修改:

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
CREATE OR REPLACE PACKAGE aronehome_jaas_utils IS
  TYPE principal_ref IS REF CURSOR;
  FUNCTION get_user_authentication(p_username IN VARCHAR2,
                                   p_password IN VARCHAR2,
                                   p_realm    VARCHAR2) RETURN principal_ref;
END aronehome_jaas_utils;
/
CREATE OR REPLACE PACKAGE BODY aronehome_jaas_utils IS
  FUNCTION get_user_authentication(p_username IN VARCHAR2,
                                   p_password IN VARCHAR2,
                                   p_realm    VARCHAR2) RETURN principal_ref AS
    var_username VARCHAR2(100);
    var_userid   NUMBER(10);
    var_password VARCHAR2(100);
    role_cursor  principal_ref;
    failed_authentication EXCEPTION;
  BEGIN
    SELECT userid, username, password
      INTO var_userid, var_username, var_password
      FROM sec_users
     WHERE username = p_username;
 
    IF (var_password = p_password) THEN
      BEGIN
          -- Manager,Administrator,User
          OPEN role_cursor FOR
            SELECT 'User' FROM dual ;
      END;
      -- if password doesn't match, raise Excpetion for LM to
      -- abort the authentication process
    ELSE
      RAISE failed_authentication;
    END IF;
    RETURN role_cursor;
  END get_user_authentication;  
END aronehome_jaas_utils;
/

 

4,设置数据库存贮信息来验证

 

  1. 登录OC4J EM管理界面
  2. 选择需要设置的Web应用,如:aronehome
  3. 切换到应用对应的管理页面,选择“安全提供程序
  4. 选择“更改安全提供程序”按钮来更改设置,设置如下的属性:
    安全提供程序类型:定制安全提供程序
    JAAS 登录模块类: oracle.sample.dbloginmodule.DBProcLM.DBProcLoginModule
  5. 设置登录模块的属性如下:
    Name:jdbcDriver ;Value:oracle.jdbc.driver.OracleDriver
    Name:plsql_procedure ;Value:ARONEHOME_JAAS_UTILS.GET_USER_AUTHENTICATION
    Name:db_schema;Value:aronehome
    Name:db_schema_pw;Value:aronehome
    Name:jdbcUrl;Value:jdbc:oracle:thin:@localhost:1521:xe
    Name:debug;Value:false
    Name:log_level;Value:ALL

 

20.custom_security_provider

 

设置好上面的配置之后,需要从新启动aronehome应用,再次运行Web Service进行测试!

 

注:DatabaseLoginModule的使用请查看OTN的相关文章,Declarative J2EE authentication and authorization with JAAS,上面只是其中一种用法。

 

 

最终的JDeveloper10 Workspace项目文件:Download R12 Form个性化白皮书 Version 1

 

 

WebService系列:为WebService添加安全性

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

 

 

为了保证发布到外网的Web Services不被非法使用,在调用Web Services之前需要进行必要的安全验证。

如前面文章中发布的GreetingWords的Web Service,希望只有授权的用户才具备调用它的权限,

虽然它的wsdl描述文件可以被任何人查看,但是如果不具备相应权限的人则无法通过调用它返回有用的信息。

 

一、设置Web Service安全性认证

 

为了实现这样的功能,按照向导在JDeveloper创建完Web Services后,添加验证信息,步骤如下:

  1. 选择端口,并保证使用“Text Password”验证选项
  2. 左边选择安全下的验证菜单,设置如下图的选项
  3. 从新发布Web Service

 

12.secure_web_service

 

选中 Security 项,并选择GreetingWordsSoapHttpPort,按照下图设置选项

13.secure_web_service_security

 

选择 Security–>Authentication 项,右边选择GreetingWordsSoapHttpPort,按照下图进行选项的设置

14.secure_web_service_authentication

 

 

二、测试Web Service

 

上面添加了Web Service的安全性认证发布之后,在浏览器中输入wsdl的端口地址,如:

http://aronezhang:8888/aronehome/GreetingWordsSoapHttpPort

浏览器显示Web Service的测试页面,输入参数,点击Invoke按钮调用Web Services

21.test_secure_ws

 

Web Services执行返回错误,错误代码为:wsse:InvalidSecurity,错误消息为:Missing <wsse:Security> in SOAP Header

这个错误是由于已发布的Web Services添加了安全验证,而调用的时候没有把相关的验证信息发送给它,导致SOAP Header没有包括安全验证需要的信息。

 

我们可以通过测试页面的功能查看到这个时候发送给服务器的消息是:

1
2
3
4
 
 
 
            aronehome

从发送的消息可以看到,没有任何安全验证的信息。

重新测试Web Service,在测试页面中选择WS-Security部分的Include In Header选项,然后输入上面OC4J的中定义的用户信息,并输入调用参数,如下图:

22.test_secure_ws_security

1
2
3
4
5
6
7
8
9
10
11
12
 
 
 
 
	      aronehome
	      aronehome
 
 
 
 
 
            aronehome

上面的提交消息中,SOAP Header部分包括了安全验证的信息,提交之后还是报如下的错误信息:

1
2
3
4
5
6
 
 
 
 
   wsse:FailedAuthentication
   The security token could not be authenticated or authorized

 

虽然我们提供了WS安全认证的用户信息,但是执行还是没有成功,这是由于提供的用户认证信息不正确,

后面的文章中将描述如何来通过OC4J提供安全性认证信息。

 

 

WebService系列:PL/SQL调用Web Service(Web Service Callout)

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

 

 

Web Service Callout的意思是在数据库中使用SQL查询、PL/SQL存储过程或Java存储过程来调用Web Service。

 

在Oracle Database 9.2或更高的版本中执行Web Service Callout需要完成以下的工作:

  1. 准备数据库(启用数据库Web Service功能),主要是装载基于Java的Web Service客户端运行环境到数据库中
  2. 装载Web Service的客户端代理到数据库中。生成基于Java的Web Service客户端代理、对应的Java和PL/SQL包装器,装载所有生成的对象到数据库
  3. 使用代理、包装器或DII(dynamic Invocation) APIs来调用Web Service

 

本文介绍基于Oracle Database 10.2.0,并将Web Service发布到独立的OC4J环境中。

基于Oracle Database 9.2的实现,可以参考OTN 技术文章Web Service Callout User Guide

为了实现PL/SQL调用Web Service,需要使用以下工具,从OTN下载

  1. 10.1.3.1 Webservice Callout for 10g (R1 + R2) (ZIP, ~13MB)
  2. JPublisher
  3. OC4J

 

 

一、数据库设置

 

准备数据库的主要工作是装载Web Service客户端运行环境到数据库中。装载客户端运行环境需要JVM而外的内存空间来解析和存贮jar文件。

查看系统的设置,保证shared_pool_sizejava_pool_size的设置分别大于等于96M和80M:

shared_pool_size=96M

java_pool_size=80M

 

1,装载Oracle SOAP客户端到Oracle 10g数据库

下载OC4J,解压oc4j_extended.zip文件,并将它的根目录设为环境变量ORACLE_HOME。可以将SOAP的客户端装载到SYS模式下或者一个特定的用户模式。

使用下列的命令来装载将它装载到aronehome模式下:

1
2
3
4
5
6
7
8
loadjava -u aronehome/aronehome -r -f -v -genmissing -grant public $ORACLE_HOME/webservices/lib/soap.jar ; 
loadjava -u aronehome/aronehome -r -f -v -genmissing -grant public $ORACLE_HOME/lib/dms.jar ;
loadjava -u aronehome/aronehome -r -f -v -genmissing -grant public $ORACLE_HOME/jlib/javax-ssl-1_1.jar ;
loadjava -u aronehome/aronehome -r -f -v -genmissing -grant public $ORACLE_HOME/j2ee/home/lib/servlet.jar ; 
loadjava -u aronehome/aronehome -r -f -v -genmissing -grant public $ORACLE_HOME/j2ee/home/lib/mail.jar ; 
loadjava -u aronehome/aronehome -r -f -v -genmissing -grant public $ORACLE_HOME/j2ee/home/lib/activation.jar ; 
loadjava -u aronehome/aronehome -r -f -v -genmissing -grant public $ORACLE_HOME/j2ee/home/lib/http_client.jar ; 
loadjava -u aronehome/aronehome -r -f -v -genmissing -grant public $ORACLE_HOME/j2ee/home/lib/ejb.jar ;

 

-grant public选项是将装载的Java类授权给public,使其它的模式也可以看到,如果希望是某个特定的模式使用,可以去掉它。

 

2,装载Oracle JAX-RPC客户端到Oracle 10g R2数据库

下载10.1.3.1 Webservice Callout for 10g 工具集,解压后可以看到dbwsclientws.jar和dbwsclientdb102.jar文件

使用下列的命令来装载将Oracle JAX-RPC装载到aronehome模式下:

loadjava -u aronehome/aronehome -r -v -f -genmissing -grant public dbwsclientws.jar dbwsclientdb102.jar

-grant public选项是将装载的Java类授权给public,使其它的模式也可以看到,如果希望是某个特定的模式使用,可以去掉它。

 

 

二、生成Web Service代理

 

这部分使用JPublisher来生成Web Service客户端代理

1,下载安装JPublisher。添加下列jar文件到CLASSPATH环境变量

${ORACLE_HOME}/sqlj/lib/dbwsa.jar
${ORACLE_HOME}/sqlj/lib/translator.jar
${ORACLE_HOME}/sqlj/lib/runtime12.jar
${ORACLE_HOME}/jdbc/lib/ojdbc14.jar

 

2,设置JAVA_HOME指向JDK1.4,并将JAVA_HOME/bin添加到PATH环境变量中

3,运行JPublisher来生成Web Service客户端代理和PL/SQL包装器

首先取得已发布的Web Service的描述文件(WSDL),通过Web Service的端口连接在浏览器中打开Web Service的相关信息,如下图

11.ws_endpoint

 

通过Service Description连接可以查看到WSDL文件内容,将其保存文wsdl为后缀的文件,如GreetingWordsSoapHttpPort.wsdl
运行下面的命令:

jpub -u aronehome/aronehome -sysuser sys/sys -proxywsdl=GreetingWordsSoapHttpPort.wsdl -endpoint=http://aronezhang:8888/aronehome/GreetingWordsSoapHttpPort

命令将创建Web Service客户端代理和它的Java和PL/SQL包装器,同时装载代理和包装器到数据库。命令会输入如下的信息:

1
2
3
4
5
6
7
8
9
GreetingWordsSoapHttpPortClientJPub.java 
plsql_wrapper.sql 
plsql_dropper.sql 
plsql_grant.sql 
plsql_revoke.sql 
Executing plsql_dropper.sql 
Executing plsql_wrapper.sql 
Executing plsql_grant.sql 
Loading plsql_proxy.jar

 

三、运行PL/SQL包装器来调用Web Service

 

在SQLPLUS或者PL/SQL Developer中运行Web Service的PL/SQL包装器的方法来输出欢迎语

1
2
3
4
5
SQL &gt; conn aronehome/aronehome
SQL &gt; select jpub_plsql_wrapper.GreetingWords('aronehome') as GreetingWords from dual;
 GreetingWords
--------------------------------------------------------------------------------
Hello aronehome, 2009-02-08

 

四、使用DII API调用Web Service

 

除了上面所描述的生成和装载客户端代理来在PL/SQL中调用Web Service外,也可以使用SYS.UTL_DBWS 包中的Web Service客户端DII APIs或者PL/SQL DII APIs来调用Web Service

前面章节中下载的JPublisher包中包括了SQL脚本utl_dbws_decl.sql 和utl_dbws_body.sql,以SYS用户运行这两个脚本。这样就可以使用SYS.UTL_DBWS来调用Web Service

下面是一段示例代码:

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
DECLARE
  service_          sys.utl_dbws.service;
  call_             sys.utl_dbws.CALL;
  service_qname     sys.utl_dbws.qname;
  port_qname        sys.utl_dbws.qname;
  operation_qname   sys.utl_dbws.qname;
  string_type_qname sys.utl_dbws.qname;
  retx              anydata;
  retx_string       VARCHAR2(100);
  retx_len          NUMBER;
  params            sys.utl_dbws.anydata_list;
BEGIN
  service_qname   := sys.utl_dbws.to_qname(NULL, 'GreetingWords');
  service_        := sys.utl_dbws.create_service(service_qname);
  port_qname      := sys.utl_dbws.to_qname(NULL, 'SoapHttpPort');
  operation_qname := sys.utl_dbws.to_qname('http://com/aronehome/GreetingWords.wsdl/types/',
                                           'GreetingWordsElement');
  call_           := sys.utl_dbws.create_call(service_,
                                              port_qname,
                                              operation_qname);
  sys.utl_dbws.set_target_endpoint_address(call_,
                                           'http://AroneZhang:8888/aronehome/GreetingWordsSoapHttpPort');
  string_type_qname := sys.utl_dbws.to_qname('http://www.w3.org/2001/XMLSchema',
                                             'string');
  sys.utl_dbws.add_parameter(call_,
                             'String_1',
                             string_type_qname,
                             'ParameterMode.IN');
  sys.utl_dbws.set_return_type(call_, string_type_qname);
  params(0) := anydata.convertvarchar('Arone.Zhang');
  retx := sys.utl_dbws.invoke(call_, params);
  retx_string := retx.accessvarchar2;
  dbms_output.put_line('PL/SQL DII client return ' || retx_string);
END;

 

 

WebService系列:将PL/SQL功能发布为Web Service到OC4J

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

 

本文述如何将PL/SQL的功能发布为Web Service的实现步骤:

  1. 按照业务要求编写PL/SQL功能
  2. 使用JDeveloper10g工具的PL/SQL Web Service向导创建PL/SQL的Web Service
  3. 使用JDeveloper10g工具将创建的Web Service发布到OC4J上
  4. 通过浏览器来测试已发布的Web Service

 

开发工具:JDeveloper10.1.3.3.0

Web Service发布环境:OC4J10.1.3.3.0

 

一、编写PL/SQL代码

 

需要发布为Web Service的PL/SQL功能和我们平时所编写的PL/SQL功能没有什么区别,因此直接提供一段PL/SQL的实现代码,方便后面的说明。

下面创建一个存储函数来根据传入用户名来返回欢迎词,欢迎词中除了包括欢迎用户还包括当前日期

下面是PLSQL的定义和实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
CREATE OR REPLACE PACKAGE oracleseeker_demo_ws IS
  FUNCTION get_greeting_words(p_user_name VARCHAR2) RETURN VARCHAR2;
END oracleseeker_demo_ws;
 
CREATE OR REPLACE PACKAGE BODY oracleseeker_demo_ws IS 
  FUNCTION get_greeting_words(p_user_name VARCHAR2) RETURN VARCHAR2 IS
    l_time VARCHAR2(20); 
  BEGIN 
    SELECT to_char(SYSDATE, 'YYYY-MM-DD') INTO l_time FROM dual; 
    RETURN 'Hello ' || p_user_name || ', ' || l_time; 
  EXCEPTION
    WHEN OTHERS THEN
    RETURN 'error'; 
  END; 
END oracleseeker_demo_ws;

此存储功能输出的一个测试结果如下:

Hello aronehome, 2009-02-08

 

二、转换PL/SQL功能为Web Service

 

主要有以下的几个步骤:

  1. 配置JDeveloper10g连接到数据库(aronehome_conn)
  2. 配置JDeveloper10g连接到OC4J10g(aronehome_oc4j)
  3. 创建JDeveloper工作空间和项目(aronehome_workspace, WebService)
  4. 发布PLSQL功能为Web Service

 

本文省略前面3个步骤的描述,重点介绍如何发布PLSQL为Web服务

  1. 切换到Application Navigator下的Applications项,右键选择项目WebService,选择上下文菜单New…
  2. 选择Business Tier节点下的Web Service,右边选择Items项为:PL/SQL Web Service
  3. 选择已创建的数据库连接aronehome_conn、数据库包aronehome_demo_ws、Web Service Name为GreetingWords、Java Package为com.aronehome
  4. 向导步骤2使用默认选项,下一步
  5. 向导步骤3选择功能get_greeting_words,选择完成创建Web Service

 

plsql_ws_wizard1

 

plsql_ws_wizard2_webservice_version

 

plsql_ws_wizard3_select_database

 

plsql_ws_wizard4_message_format

 

plsql_ws_wizard5_program_units

 

 

三、发布Web Service到OC4J

 

创建完Web Service后,在项目的Resource目录下会有一个Web Service发布配置文件WebService.deploy生成。
右键选择WebService.deploy,选择Deploy to下的aronehome_oc4j连接,如图

plsq_ws_deploy_ws_5

系统自动弹出Web Service对应的J2EE应用配置,可以进行修改,开始在项目设置的时候已经进行了必要的修改,不需要进一步更改。

7.deploy_ws_configure

 

点击确定按钮发布Web Service到指定的OC4J应用下。同时会有发布日志查看发布情况: 

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
----  Deployment started.  ----    2009-2-8 4:55:23
Target platform is 独立 OC4J 10g 10.1.3 (aronehome_oc4j).
Wrote WAR file to D:\Arone.Zhang\Respository\Blog\series\WebService\aronehome_workspace\WebService\deploy\WebServices.war
Wrote EAR file to D:\Arone.Zhang\Respository\Blog\series\WebService\aronehome_workspace\WebService\deploy\aronehome_workspace-WebService-WS.ear
正在上载文件 aronehome.ear...
aronehome 的 Application Deployer 开始。
将档案复制到 D:\oc4j_extended_101330\j2ee\home\applications\aronehome.ear
初始化 D:\oc4j_extended_101330\j2ee\home\applications\aronehome.ear 开始...
解压缩 aronehome.ear
解压缩 aronehome.ear 完成
解压缩 WebServices.war
解压缩 WebServices.war 完成
初始化 D:\oc4j_extended_101330\j2ee\home\applications\aronehome.ear 结束...
启动应用程序: aronehome
初始化类加载程序
初始化 EJB 容器
加载连接器
启动资源适配器
初始化 EJB 会话
提交类加载程序
初始化 WebServices 开始...
初始化 WebServices 结束...
已启动的应用程序: aronehome
将 Web 应用程序绑定到站点 default-web-site 开始...
将应用程序 aronehome 的 WebServices Web 模块绑定到上下文根 aronehome 下的站点 default-web-site
初始化 Web 应用程序 WebServices 的 Servlet oracle.j2ee.ws.server.JAXRPCServlet
将 Web 应用程序绑定到站点 default-web-site 结束...
aronehome 的 Application Deployer 完成。操作时间: 5323 msecs
Elapsed time for deployment:  57 seconds
----  Deployment finished.  ----    2009-2-8 4:56:20

登陆OC4J,查看Web Service信息

http://localhost:8888/em

选择应用aronehome下的Web服务标签页,可以看到已经发布的Web Service GreetingWords

8.ws_HttpPort

 

四、测试Web Service

 

测试GreetingWords Web Service可以通过上图左上角的测试服务按钮来启动,也可以通过Web服务对应的端口地址来测试

9.ws_test_url

 

10.ws_test_page

 

输入参数值:Arone.Zhang

点击Invoke按钮运行Web Service。

运行的结果如下:

1
2
3
4
 
 
 
			Hello Arone.Zhang, 2009-02-08

可以看到Web Service返回的结构值为:Hello Arone.Zhang, 2009-02-08

同样可以直接在浏览器中输入Web 服务对应的端口地址来测试Web Service:

http://aronezhang:8888/aronehome/GreetingWordsSoapHttpPort

 

相关源代码:Download Oracle EBS二次开发系列视频教程之打开Form模板源代码文件(3) Version 1

 

 

 

通过ADF Data Control 发布RESTFul 服务的资源

十月 23, 2008 in Oracle 融合中间件

 

 

前面2篇文章我们跟随Lucas一起基于RESTLet开发了Restful的Web服务,其中的数据使用的是静态的数据,这样的情景在实际的应用中比较少见,

一般都是通过Business Service层来隐藏数据库的持久层和Web服务,以更清晰的层次来发布资源。

 

下面我们使用ADF Model中的Data Control & Data Bindings功能来实现一个业务服务层(Business Service),

通过创建一个:Placeholder Data Control来实现,首先创建一个Note的数据类型,然后通过Placeholder Data Control来发布一个Note对象的集合。

 

应用中通过BindingContainer才能使用Data Control,BindingContainer负责进行应用程序和数据集合(collections)、数据操作(operations)之间的连接,

这样的连接称为数据绑定(Data Bindings),基于使用这些集合的方式,我们可以使用各种类型的数据绑定,

如:表格,列表和树。BindingContainer通常被页面绑定配置文件PageDefinition文件初始化,页面绑定配置文件包括了数据绑定的配置信息。

 

创建 placeholder data control

路径:Business Tier –> Placeholder Data Control

 

9.placeholder_data_control

 

创建完ResourceDataPlaceHolder之后,从Data Controls属性窗口的上下文菜单中选择Create Placeholder Data Type

在创建Placeholder Data Type窗口中指定数据类型名称:Note;以及数据类型的属性:name, description, creationDate,切换到Sample Data标签页,输入静态的样例数据

 

10.create_placeholder_data_type

 

11.create_placeholder_data_type_data

 

创建完成之后,Data Control显示如下图:

12.data_control

 

打开我们在第一篇文章中创建的restful.jsp页面,从Data Control面板中拖动Note到页面上,然后选择创建一个Table组件,

创建完成之后会生成一个页面绑定文件叫做restfulPageDef.xml,它就是BindingContainer的设计时的配置文件,

它创建了一个基于ResourceDataPlaceHolder数据集合的迭代器,然后绑定到了一个Table来访问Data Control的数据,代码如下:

 

1
2
3
4
5
6
7
8
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;
 
 
 
 
 
 
    <table id="Note"><tbody></tbody></table>

 

在DataBindings.cpx的文件中对页面绑定配置文件PageDefinition的定义:

 

1
 

 

配置ADF Binding Filter

 

上面通过拖拽来定义JSP页面,JDeveloper在web.xml文件中自动配置了ADF Binding Filter,过滤器会在web应用和BindingContainers交互之前初始化ADF Binding Context,

然而默认创建的是只处理*.jsp 和 *.jspx的相关请求,因此需要修改为*来处理RESTful服务的任何请求,修改URL匹配模式为:

 

1
2
3
4
        ADFBindingFilter
        *
        FORWARD
        REQUEST

 

 

使我们的应用能够访问Note table binding

 

如果在应用中我们需要在多个地方访问Note 表格绑定,那我们需要在一个集中的地方去处理获得表格的绑定,因此将这个方法放到我们的控制类RestfulAppliction中,

这个方法首先得到ADF的上下文ADFContext,绑定上下文BindingContext,然后从绑定容器BindingContainer中获得table binding

 

1
2
3
4
5
6
7
8
9
10
11
12
public static JUCtrlRangeBinding getNotesTableBinding() {
            ADFContext ctx = ADFContext.getCurrent();
            OracleExpressionEvaluatorImpl elev =
                (OracleExpressionEvaluatorImpl)ctx.getExpressionEvaluator();
            HttpBindingContext data = (HttpBindingContext)elev.evaluate(&quot;${data}&quot;);
            DCBindingContainer bc =
                data.findBindingContainer(&quot;com_oracleseeker_demo_restfulPageDef&quot;);
            bc.refresh(DCBindingContainer.PREPARE_MODEL);
            JUCtrlRangeBinding tableBinding =
                (JUCtrlRangeBinding)bc.findNamedObject(&quot;Note&quot;);
            return tableBinding;
        }

 

 

从ADF Data Control中发布Notes资源

 

我们必须在资源类NotesResource中实现represent()方法来处理GET请求,然后返回数据。

 

添加类的私有变量:notesTableBinding

添加代码到构造函数中:

1
notesTableBinding= RestfulApplication.getNotesTableBinding();

 

 

在represent()方法中循环处理TableBinding返回的数据

 

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
    @Override
    public Representation represent(Variant variant) throws ResourceException {
        if (MediaType.TEXT_XML.equals(variant.getMediaType())) {
            try {
                DomRepresentation representation =
                    new DomRepresentation(MediaType.TEXT_XML);
                Document doc = representation.getDocument();
                Element root = doc.createElement(&quot;notes&quot;);
                doc.appendChild(root);
                RowIterator ri = notesTableBinding.getRowIterator();                    
                ri.reset();                    
                Row[] rows  = ri.getAllRowsInRange();
 
                for (Row row : rows) {
                    Element eltNote = doc.createElement(&quot;note&quot;);
 
                    Element eltName = doc.createElement(&quot;name&quot;);
                    eltName.appendChild(doc.createTextNode((String)row.getAttribute(&quot;name&quot;)));
                    eltNote.appendChild(eltName);
 
                    Element eltDescription = doc.createElement(&quot;description&quot;);
                    eltDescription.appendChild(doc.createTextNode((String)row.getAttribute(&quot;description&quot;)));
                    eltNote.appendChild(eltDescription);
 
                    Element eltCreationDate =
                        doc.createElement(&quot;creationDate&quot;);
                    eltCreationDate.appendChild(doc.createTextNode(((oracle.jbo.domain.Date)row.getAttribute(&quot;creationDate&quot;)).toString()));
                    eltNote.appendChild(eltCreationDate);
                    root.appendChild(eltNote);
                }
                doc.normalizeDocument();
                return representation;
 
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

 

 

运行restful.jsp,修改URL指向资源/notes,运行如下的结果:

 

13.notes_xml_date

 

 

 

添加开始行和最大行的功能

 

 

一般在应用中调用Web服务都会进行分页,因此就会有一个页面显示数据多少行到多少行,

因此我们的URL看起来像是这样的:http://host:port/webapp/notes?start=26&maxRows=25

添加两个私有变量到资源类NotesResource中

 

1
2
    int startRow = 0;
    int maxRows = -1;

 

在类的构造函数中获取请求URL中的开始行和最大行参数的值

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
        String startRowParam =
            request.getResourceRef().getQueryAsForm().getFirstValue(&quot;start&quot;);
        if (startRowParam != null) {
            startRow = Integer.parseInt(startRowParam);
        } else {
            startRow = 0;
        }
        String maxRowsParam =
            request.getResourceRef().getQueryAsForm().getFirstValue(&quot;maxRows&quot;);
        if (maxRowsParam != null) {
            maxRows = Integer.parseInt(maxRowsParam);
        } else {
            maxRows = -1;
        }

 

在represent()方法中加入限制

 

1
2
3
ri.reset();
ri.setRangeSize(maxRows);
ri.setRangeStart(startRow);

 

在URL中添加参数:http://127.0.0.1:7101/oracleseeker-restful/notes?maxRows=2&start=1 运行结果:

14.notes_xml_maxrow_data

 

 

上面三篇文章使用RestLet开源库来创建Restful 服务,同时利用JDeveloper 11g的新特性来发布数据。

 

资源链接

 

Publishing resources exposed by ADF Data Control in RESTful services using RestLet and JDeveloper 11g by Lucas Jellema

http://technology.amis.nl/blog/3600/publishing-resources-exposed-by-adf-data-control-in-restful-services-using-restlet-and-jdeveloper-11g

 

下载本文的JDeveloper 11g应用Download BIP报表中格式化币种金额 Version 1