You are browsing the archive for REST.

通过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
<?xml version="1.0" encoding="UTF-8" ?>
 
 
 
 
 
 
    <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

 

 

 

扩展RestLet应用来创建和更新资源

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

 

 

上一篇博文中学习了RestLet如何使用它在JDevloper 11g中创建一个简单的Restful服务,它只支持只读操作:GET请求,下面将添加创建和更改Note的功能。

 

一、创建新的资源

 

 

创建一个客户端页面来创建Notes

 

创建是通过HTTP请求的POST来实现,我们需要设计一个HTML页面来提交给我们的RESTful服务的资源链接URL,提交的页面包括了我们需要创建Note的相关数据,Restful服务将接收提交的请求,NotesResource资源类将接收Post请求,将其发送给/notes服务来创建一个Note。

需要保证这个页面不在我们的项目下,否则由于web.xml配置过滤无法运行,因此可以在任何其他目录下创建此静态HTML页面,如test.html 。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
<form name="NoteCreator" action="http://127.0.0.1:7101/oracleseeker-restful/notes" method="post">
  <table cellspacing="2" cellpadding="3" width="100%" border="1">
    <tbody>
      <tr>
        <td width="28%">Name</td>
        <td width="72%"> </td>
      </tr><tr><td width="28%">Description</td>
        <td width="72%"> </td>
      </tr>
     </tbody>
    </table>
 
</form>

 

HTML静态页面的主要功能是提交一个表单执行一个POST方法,将表单数据发送给Notes服务

 

添加POST处理逻辑到NotesResource资源类中

 

首先需要在资源类NotesResource类的构造函数中设置属性,让资源类能够接受POST请求来修改资源

 

1
2
// Allow modifications of this resource via POST requests.   
setModifiable(true);

 

然后重载Resource类的acceptRepresentation方法,这个方法监控请求的内容,获取创建资源所需的信息,然后创建资源,将其添加到收集器中

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    @Override
    public void acceptRepresentation(Representation entity) throws ResourceException {
        Form form = new Form(entity);
        String name = form.getFirstValue(&quot;name&quot;);
        String description = form.getFirstValue(&quot;description&quot;);
 
        getNotes().add(new Note(name, description, new Date()));
 
        // Set the response's status and entity
        getResponse().setStatus(Status.SUCCESS_CREATED);
        Representation rep =  new StringRepresentation(&quot;Note created&quot;, MediaType.TEXT_PLAIN);
        // Indicates where is located the new resource.        
        rep.setIdentifier(getRequest().getResourceRef().getIdentifier() + &quot;/&quot; + name);        
        getResponse().setEntity(rep);
    }

 

创建Note资源

 

运行restful.jsp页面用来发布Web服务到WebLogic,然后运行静态HTML文件

4.create_note

输入Note信息,点击Create按钮,然后会弹出一个窗口显示创建成功的消息。

 

修改URL,检测Note创建是否成功

5.create_complete 

 

 

二、更新现有的资源

 

要POST请求能够支持更新现有资源的功能,只要修改NotesResource资源来,根据请求的URL参数来进行资源定位并进行更新就可以了。

 

在资源类NotesResource类的构造函数中设置可修改资源,并获取URL中的资源参数

 

1
2
3
setModifiable(true); 
String noteName = (String)getRequest().getAttributes().get(&quot;noteName&quot;);
note = getTheNote(noteName);

 

重载acceptRepresentation() 方法,在方法中定位资源,并进行修改,如果没有找到资源,返回提示信息

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    @Override
    public void acceptRepresentation(Representation entity) throws ResourceException {
        Form form = new Form(entity);
        Representation rep = null;
        if(note != null){
            String description = form.getFirstValue(&quot;description&quot;);            
            note.setDescription(description);            
            getResponse().setStatus(Status.SUCCESS_CREATED);            
            rep = new StringRepresentation(&quot;Note updated&quot;, MediaType.TEXT_PLAIN);            
            rep.setIdentifier(getRequest().getResourceRef().getIdentifier() + &quot;/&quot; + note.getName());
        }
        else{
            getResponse().setStatus(Status.CLIENT_ERROR_NOT_FOUND);                        
            rep = new StringRepresentation(&quot;Note could not be found&quot;, MediaType.TEXT_PLAIN);
        }
        getResponse().setEntity(rep);
    }

 

根据URL中的参数,找到资源,并对资源中的描述进行修改

 

修改HTML静态页面test.html ,添加Update按钮来提交资源的更新,如下列代码:

 

1
 

 

 

更新资源展示

 

还是和之前一样,先运行restful.jsp页面,再运行静态HTML文件

 

8.update_form

 

更新之后会有成功的消息返回。

6.update_success

 

 

输入URL检测更新是否成功

7.update_complete

 

应用扩展结束!

 

 

三、资源和链接

 

Extending the RestLet application with support for POST/PUT to create and update Resources by Lucas Jellema

http://technology.amis.nl/blog/3592/extending-the-restlet-application-with-support-for-postput-to-create-and-update-resources

 

下载本文的JDeveloper 11g应用:Download 扩展RestLet应用来创建和更新资源 Version 1

 

 

REST 初识

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

 

现在满世界的Web应用都在宣称自己已经RESTful了,目前三种主流的Web服务实现方案中,由于REST模式的Web服务比起SOAP和XML-RPC的服务有着明显的简洁,而导致越来越多的Web服务开始采用REST风格设计和实现,例如Amazon,Google和Yahoo都提供了REST风格的Web查询服务;Google的也推出了Ajax应用下的REST风格搜索API。

 

同时也出现了一些优秀的REST 网络架构实现,如Java版的 Restlet;JCP也制定了关于REST网络服务的规范标准:JAX-RS: Java API for RESTful Web Services (JSR 311)

 

REST简介

 

REST (Representational State Transfer) 表述性状态转移

REST是由Roy Thomas Fielding博士在2000年的博士论文中首次提出的,REST被定义为是一种网络应用的架构风格(architecture style)而不是一个标准,它包括架构元素(element)和架构约束(constraint),REST通常基于使用HTTP,URI,和XML以及HTML这些现有的协议和标准。

 

REST从资源的角度来审视这个网络,分布在各处的资源有URI来确定,客户端的应用通过URI来获取资源的,获取这些资源致使这些应用程序转变其状态,随着不断的获取资源,客户端应用不断地在转变状态,即所谓的表述性状态转移(Representational State Transfer)

 

REST的设计概念和准则

 

  1. 网络上的所有事物都被抽象为资源(resource)
  2. 每个资源对应一个唯一的资源标识(resource identifier)
  3. 对资源的操作包括获取、创建、修改和删除资源,这些操作对应HTTP协议的GET, POST, PUT和DELETE方法
  4. 通过通用的连接器接口(generic connector interface)对资源进行操作
  5. 对资源的各种操作不会改变资源标识
  6. 所有的操作都是无状态的(stateless)
  7. 资源的表现形式为XML或HTML,它取决于读者是机器还是人,消费web服务的客户应用是web浏览器或者其它
  8. 客户端和服务器结构
  9. 能够利用Cache机制
  10. 层次化的系统
  11. Code on Demand – Javascript

 

 

REST的优点

  1. 可以利用Cache来提高响应速度
  2. 通讯本身的无状态可以让不同的服务器处理一系列请求中的不同请求,提高服务器的扩展性
  3. 浏览器即可作为客户端,简化客户端软件系统的要求
  4. REST直接基于现有流行的协议和标准,依赖性更小
  5. 不需要而外的资源发现机制

 

 

参考资料

 

Roy Thomas Fielding博士论文英文版链接

http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm

JSR-000311 JAX-RS: The JavaTM API for RESTful Web Services
http://jcp.org/aboutJava/communityprocess/final/jsr311/index.html

Restlet

http://www.restlet.org/

Google Ajax Search API

http://code.google.com/apis/ajaxsearch/

 

 

后续

 

前面通过发布一个PL/SQL 的功能为一个Web Service展示了基于SOAP的Web服务实现,后续将基于Restlet来实现一个RESTful的Web服务。