`
hot88zh
  • 浏览: 178478 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Proposal: Finalize Web Services APIs

阅读更多

Introduction

Now that the OpenSocial REST API and the Shindig implementation is stabilizing, we can finalize the SocialSite REST API – which is OpenSocial plus our extensions that support friending, groups, enchanced search and gadget management. This proposal presents a way to do that.

Currently, our SocialSite extensions are implemented in an adhoc fashion: a simple Servlet that parses the incoming URL and uses a large and unweildy if-else statement to decide which POJOs to create, retrieve, update or delete and to return JSON data. Only JSON is supported, unlike OpenSocial APIs which support JSON, XML and Atom. On the client-side, the SocialSite JavaScript API is different from the OpenSocial web services in many ways and does not use the Shindig infrastructure for supporting batching of calls.

Benefits

By abandoning our adhoc implementation and instead implementing our web services via Shindig ~DataRequestHandlers on the server-side and using standard OpenSocial request facilities the server-side we get these benefits:

  • Support for OpenSocial style REST and JSON-RPC on the server-side
  • Support for JSON-RPC batching of requests on client-side
  • Comply with OpenSocial requirements for extensions

The rest of this document presents a design for our new web services in terms of URIs and HTTP actions/verbs POST, GET, PUT and DELETE as well as notes on how to implement these new web services using the framework provided by Shindig.

References

The proposal is based on these specifications and codebases:

 

The REST API handlers and URIs

On the server-side, each URI root such as '/people' or '/activities' is handled by a ~DataRequestHandler with methods for POST, GET, PUT and DELETE. These methods accept and return Java beans and Shindig specific collection classes that hold Java beans. Shindig takes care of converting POJOS to and from XML, Atom and JSON formats.

Note that, though we are talking about REST and URIs and HTTP verbs, these same handlers are used for JSON-RPC implementation and by implementing them we get support for both REST and JSON-RPC interaction -- all taken care of by Shinding.

This section lays out the SocialSite extensions to OpenSocial by explaining each of the handlers that we will implement or modify to add the URIs and actions we need.

 

PersonHandlerImpl

We will extend the Shindig PersonHandlerImpl, which supports the '/people' APIs discussed in the. We will add support for the new URIs and actions below.

POJO type: returns and accepts Profiles

	/people/@all [?search={searchString}]
		GET - get all people

	/people/{userId}/{groupId}
		GET - members of a group

	/people/{userId}/@union/{groupId1}/{groupId2}
		GET - union of members in two groups

To create a friend connection, you post a Profile representation of the person you wish to friend to your friends collection:

	/people/{yourUserId}/@friends

To get a list of people who have invited you to be a friend, do a get on:

	/people/{yourUserId}/@requests

To accept a friendship, post a Profile representation of the requesting person to your friend collection:

	/people/{yourUserId}/@friends

To ignore a friendship, do a delete on:

	/people/{yourUserId}/@requests/{userId}

 

GroupDefinitionHandler

POJO type: returns GroupDefinition

	/groupdef
		GET - get group definition	

 

GroupHandler

POJO type: Returns and accepts Groups

Types of groups:

  • Public: visible to all, anybody can ask to join
  • Closed: not visible to all, join by invitation only
  • Private: visible to only one user who can add/remove folks as needed

NOTE that we will implement only public groups for October milestone

	/groups/@public [?search={searchString}]
		GET - get list of all public groups defined in system
		POST - create a new public group

	/groups/@public/{groupId}
		GET - get public group
		PUT - update a public group that you are the admin of
		DELETE - delete a public group that you are the admin of

	/groups/{userId}
		GET - get list all groups (public, private and closed) associated with a user

	/groups/{userId}/@friends
		GET - get list of groups (public, private and closed) that friends belong to

 

GroupMemberHandler

POJO type: returns and accepts Profiles

Do this inside the people handler!

	/members/{groupId}
		GET - get list of members in group
		POST - add a new member to the group

	/members/{groupId}/{userId}
		PUT - update a member in group 
		DELETE - delete a member in group 
	

To ask to join a group, post a sufficient Profile representation of yourself to:

	/members/{groupId}

To get a list of incoming group membership requests:

	/members/@requests

To accept an incoming group request, post sufficient Group representation to:

	/members/{groupId}

To reject an incoming group request, do a delete on the request:

	/members/{groupId}/@requests/{userId}

 

MessageHandler

POJO type: Returns and accepts MessageContents

	/messages/{userId}/outbox
		POST - create a new message, recipient(s) should be specified in content
		GET - get sent messages for user [added by Bobby]

	/messages/{userId}/inbox
		GET - get messages for user

	/messages/{userId}/inbox/{messageId}
		GET - get individual message
		PUT - update message for user (i.e. mark it as read)
		DELETE - delete a message

SearchHandler

POJO type: Returns SearchResults

	/search/{searchString}
		GET - get combined search results

GadgetHandler

POJO type: Returns and accepts InstalledGadgets

	/gadgets/@all  [?search={searchString}]
		GET - all gadgets known to system, with optional search string

	/gadgets/@user/{userId} - [?destination={destinationId}]
		GET - all user's installed gadgets

	/gadgets/@user/{userId}
		POST - install a gadget for user (destination specified in content)

	/gadgets/@group/{groupId} - [?destination={destinationId}]
		GET - all group's installed gadgets

	/gadgets/@group/{groupId}
		POST - install a gadget for group (destination specified in content)

 

 

Implementing the SocialSite extensions

For each handler you implement:

On the server-side

Define a POJO to represent the data item handled

Define a simple POJO to represent that type and provide a way to serialize and de-serialize the POJO to XML and JSON. Shindig expects us to return POJO objects, which Shindig will automatically convert to either JSON or XML, depending on what was requested.

In some cases, we can use our existing POJOs for this -- but I expect that some of our POJOs expose more information than we want to return to the client. In those cases, we might have to develop simple wrapper POJOs that expose just the things we want.

Implement the DataRequestHandler interface

Implement the get(), post(), put() and delete() methods as needed. Define a URI parsing template that can be applied to incoming RequestItems, use the RequestItem to get data from the request in the form of POJOs. See our existing handler implementationsfor examples.

Add your handler to those in CustomHandlerProvider

Guice is used to inject handlers into the Shindig Servlet, so you will need to add your handlers to our CustomHandlerProvider.

On the client side

Define JavaScript object to match your POJO

Define a JavaScript object to match your Java POJO and code thatcan construct this from JSON data. See sectionprivacy.js for an example of how to do this.

Define JavaScript request methods to support your handler

Define JavaScript methods to create needed requests and process the responses. If you support full CRUD for your data type then you'll need four methods like so (see socialsite.js for examples):

  • socialsite.newCreateXXXRequest()
  • socialsite.newFetchXXXRequest()
  • socialsite.newUpdateXXXRequest()
  • socialsite.newDeleteXXXRequest()

Modify your Gadgets to use the new APIs

Modify your existing SocialSite Gadgets to use your new methods instead of the old deprecated JS APIs.

Clean up

Delete your old and no longer needed code from the SocialSiteGadgetDataServlet and socialsite.js.

 

Appendix A: Mapping the old REST API to the new

This section lists URI patterns from the old REST API and, in highlights, explains which parts of the new REST API to use instead.

Profiles

/profiles
	getOnProfilesUrl
	DONE

/profiles/{ownerId}
	getOnProfilesAndOwnerUrl
	putOnProfileUrl
	DONE

/allprofiles
	getOnAllProfilesUrl
	Use PersonHandlerImpl /people/@all instead

/profiles/{ownerId}/friendsgroups
	getOnFriendsGroupsUrl - returns - Collection of Groups POJOs in JSON form
	Use GroupHandler /groups/@friends insead
	
/profiles/{ownerId}/request/{friendId}
	putOnRequestFriendUrl
	use POST to /people/{userId}/@friends 

/profiles/{ownerId}/accept/{friendId}
	putOnAcceptFriendUrl
	use POST to /people/{userId}/@friends instead

/profiles/{ownerId}/reject/{friendId}
	See notes above 

Groups

/groups
	getOnGroupsUrl - returns - GroupDefinition in JSON form
	Use GroupDefinitionHandler /groupdef instead

/groups/{groupHandle}
	getOnGroupsAndGroupIdUrl - returns - Group POJO in JSON form
	putOnGroupUrl - updates - Group POJO from JSON data
 	Use GroupHandler and /groups/@public and /groups/@public/{groupId} instead

/groups/{groupHandle}/members
	getOnGroupMembersGroupsUrl - returns - Group POJOs 
	Use PersonHandlerImpl /people/{userId}/{groupId} instead

/groups/{groupHandle1}/{groupHandle2}
	getOnCommonGroupMembersUrl - Group POJOs
	Use PersonHandlerImpl /people/{userId}/@union/{groupId1}/{groupId2} instead

/groups/{groupHandle}/activities
	getOnGroupActivities - Activity POJOs
	Use standard OpenSocial /activities/{userId}/{groupId} instead

/groups/{groupHandle}/myfriends/{ownerId}
	getMyFriendsInGroupUrl - returns - Profile POJOs
	Use standard OpenSocial /people/{userId}/{groupId} instead

/groups/{groupHandle}/admin/{ownerId}
	getOnGroupAdminsUrl - returns - type value of MEMBER or ADMIN
 	Instead, use a field in the group to indicate user's standing

/currentgroup
	getOnCurrentGroupUrl - Group POJO for current group 
	Instead, passing groupId to gadget and get group by ID

/mygroups
	getOnMyGroupsUrl - returns - Group POJOs
	Use standard OpenSocial API instead /groups/{userId}

/mygroups/add/{ownerId}
	putOnAddRemoveGroupUrl
	Instead, use POST to /members/{groupId}

/mygroups/remove/{ownerId}
	putOnAddRemoveGroupUrl
	Instead, use DELETE on /members/{groupId}/{userId}

/allgroups
	getOnAllGroupsUrl
	Use /groups/@public instead

/groups/{groupHandle}/create/{ownerId}
	putOnCreateGroup
	Use POST to /groups/@public instead

/groups/{groupHandle}/invite/{ownerId}
	putOnInviteFriendToGroupUrl
	Use POST to /members/{groupId} instead

/groups/{groupHande}/{ownerId}/accept/{memberId}
	putOnAcceptGroupMemberUrl
	See notes above on joining groups

/groups/{groupHande}/{ownerId}/reject/{memberId}
	putOnRejectGroupMemberUrl
	See notes above on joining groups

Notifications

/notifications/{ownerId}
	getOnNotificationsAndOwnerUrl
	Use GET on /messages/{userId}/inbox instead

/notifications/id/{notficationId}
	getOnNotificationId
	Use GET on /message/{userId}/inbox/{messageId} instead

/notifications/person/{fromId}/{toId}/{subject}
	putOnMessageToPersonUrl
	Use POST to /messages/{userId}/outbox with person recipient in data instead

/notifications/group/{fromId}/{toId}/{subject}
	putOnMessageToGroupUrl
	Use POST to /messages/{userId}/outbox with group recipient in data instead

/notifications/id
	deleteOnNotificationUrl
	Use GET on /message/{userId}/inbox/{messageId} instead

Search

/search/{searchString}
	getOnSearch
	Use SearchHandler instead with same URL

/search/profile/{searchString}
	getOnProfileSearch
	Use PersonHandler and  /people/@all [?search={searchString}] instead

/search/group/{searchString}
	getOnGroupSearch
	Use GroupHandler and  /groups/@public [?search={searchString}] instead

/search/gadget/{searchString}
	getOnGadgetSearch
	Use GadgetHandler and  /gadgets [?search={searchString}] instead

Gadgets

/installedgadgets/user/{ownerId}/{destination}
	putOnCreateInstalledGadgetForUser
	Use POST to /gadgets/@user/{userId} instead

/installedgadgets/group/{groupId}/{destination}
	putOnCreateInstalledGadgetForGroup
	Use POST /gadgets/@group/{groupId} instead

/installedgadgets/id
	deleteOnInstalledGadgetUrl
	Use DELETE on either /gadgets/@user/{userId}/{gadgetId} or the group equivalent
分享到:
评论

相关推荐

    AES Proposal:Rijndael

    AES算法Rijndael实现的设计文档,作者为Joan Daemen, Vincent Rijmen。全英文。

    开源项目-golang-go.zip

    开源项目-golang-go.zip,proposal: add typed enum support · Issue #19814 · golang/go

    CSCI-4700-Init-Proposal:使用它作为编写提案的模板

    CSCI-4700-Init-Proposal:使用它作为编写提案的模板

    typeclass-proposal:Dotty的Typeclass建议

    建议书 该提议基于Martin Odersky的,并试图解决功能性编程Scala社区的一些已知缺点。 因此,该提议的理由应与原始提议相同。 基本原理 有两种主要的Scala程序结构样式:标准(面向对象)类层次结构或使用隐式参数...

    r-consortium-proposal:申请https

    数据学院数据记者的R课程 在这个项目中,我们希望为记者和数据记者...devtools::install_github("school-of-data/r-consortium-proposal", subdir="r-package") learnr::run_tutorial("en-recipe-template", packag

    research-proposal:申请独立博士后职位的研究建议

    关于 这是一份正在进行中的 2 页研究提案,用于我独立的博士后奖学金申请。 有关我为什么要这样做的更多信息,请访问我博客上的相关帖子: 想看看 PDF 版本吗? 您可以从以下链接找到最新编译的 PDF: ...

    proposal:集线器

    r-hub :R社区需要的一切建设者 GáborCsárdi,基于先前版本的作者:JJ Allaire(RStudio),Ben Bolker(麦克马斯特大学)Dirk Eddelbuettel(Debian),Jay Emerson(耶鲁大学),Nicholas Lewin-Koh(基因技术)...

    proposal:R财团提案

    输出 pdf_document 默认 R的数量 ,阿图罗·阿苏科拉。 西班牙马德里卡洛斯三世大学信息通信工程系。 支持作者: 。 德国明斯特大学地理信息研究所。...数量是“现象,物体或物质的属性,其中属性的大小可以表示为...

    node-default-module-proposal:针对Node中的ES模块的适度建议

    Node.js中ES模块的适度建议指导原则该解决方案必须100%向后兼容。 将来,开发人员应该能够在不了解CommonJS模块系统的情况下编写Node程序和库。... Web浏览器使用的默认解析算法不会自动附加文件扩展名

    quantumguys_proposal:拟议的量子论网站

    QuantumGuys_Proposal 拟议的量子论网站

    dfg-proposal:DFG研究补助金计划的LaTeX模板

    LaTeX DFG模板 上次更新时间:2021年3月 基本DFG(德国研究基金会,德国研究基金会)拨款提案的LaTeX模板。 注意:您需要pdflatex和biber (不是bibtex )来编译文档。 致谢 这个模板是基于模板和基于RTF的 ,在2020...

    proposal:gRFC的存储库

    gRPC RFC 介绍 在继续之前,请阅读gRPC组织的和。 此存储库包含有关gRPC实质性功能更改的设计建议,这些更改需要预先设计。 前期设计过程的目标是: 为社区提供有关即将发生的更改以及围绕它们的设计注意事项的更...

    proposal:前往专案设计文件

    提出变更建议介绍Go项目的开发过程是设计驱动的。 在对语言,库或工具进行重大更改之前,必须先进行讨论,有时甚至要正式记录下来,然后才能实施。 本文档介绍了对Go项目进行提议,记录和实施更改的过程。...

    mop-minus-proposal:Perl 类生成器

    curl -L https://github.com/yuki-kimoto/mop-minus-proposal/archive/master.tar.gz > mop-minus-master.tar.gz cpanm mop-minus-master.tar.gz 例子 # Point.pm package Point { use mop::minus; has x = 0; ...

    FET_Proposal:来自OpenDreamKit的匿名FET提案模板

    阅读整个proposal.pdf文件。 直接修正错别字。 在您的姓名首字母中查找WRITE HERE注释,然后实施它们。 在邮件列表上评论其他建议。 作为工作包的负责人 编辑文件WorkPackages / <WorkPackageName> .tex。 有关更...

    毕业设计视频会议源码-GSoC-20-Proposal:GSoC-20-提案

    毕业设计视频会议源码GSoC-20-提案 在 Tensorflow Graphics 中实现 Mesh RCNN 联系信息 姓名:马达夫·艾扬格大学 : 电子邮件ID ...它能够通过查看相应的无约束现实生活图像(具有多个对象、遮挡、不同的照明)来预测...

    ARnft-proposal:ARnft框架折射

    建议书 ARnft框架折射

    pgdl_proposal:提交PGDL研讨会

    这是在NeurIPS 2020上针对预测深度学习挑战的入门套件开发的。 先决条件: 的Python 3.6.6 Tensorflow 2.2 大熊猫pyyaml scikit学习我提出的算法的主要代码可以在baselines / proposed_complexity中查看用法: (1)...

    非科班出身程序员刷题-proposal:提议

    非科班出身程序员刷题开放计算教育 使最佳实践成为普遍实践 埃文科尔 顾问:Benoît Vanderose & Bruno Dumas 2020 年 ...已经为新手程序员开发了许多很棒的资源、课程、工具和学习环境。...这可以说是最大的编程学生群体...

    yearn-aave-proposal:yearn的arcaip

    向往的ARC 提出评论要求

Global site tag (gtag.js) - Google Analytics