53 Using Oracle WebCenter Portal REST APIs

This chapter describes the WebCenter Portal REST APIs, with which you can retrieve, adding, modify, and delete server data.

This chapter includes the following topics:

More on OTN

This chapter includes some examples that demonstrate how to use WebCenter Portal REST APIs. For more examples, see the Oracle WebCenter Portal Demonstrations and Samples page on the Oracle Technology Network (OTN) at:

http://www.oracle.com/technetwork/middleware/webcenter/ps3-samples-176806.html

53.1 Introduction to REST

REST (REpresentational State Transfer) is an architectural style for making distributed resources available through a uniform interface that includes uniform resource identifiers (URIs), well-defined operations, hypermedia links, and a constrained set of media types. Typically, these operations include reading, writing, editing, and removing, and media types include JSON and XML/ATOM.

REST commands use standard HTTP methods as requests to point to the resource being used. Every request returns a response, indicating the status of the operation. If the request results in an object being retrieved, created, or updated, the response includes a standard representation of that object.

REST supports multiple clients, both from client machines and other servers, and it can be used from just about any client or development technology, including Java, JavaScript, Ruby on Rails, PHP, .Net, and so on.

Tip:

For a good general introduction to REST, see the Wikipedia article Representational State Transfer at http://en.wikipedia.org/wiki/Representational_State_Transfer.

REST is typically used with Rich Internet Applications (RIA) that are client-side scripted and require the ability to interact with data from a server-side application. For example, the WebCenter iPhone App uses WebCenter Portal REST APIs to interact with a WebCenter Portal application. The native iPhone client is written in Objective-C, and the REST APIs enable the client to send and retrieve application data.

53.2 Understanding the Username-Based Security Token Encryption

To provide additional security, every URI, for both href and template attributes, includes a security token parameter that is based on the authenticated username (a utoken).

The security generation algorithm uses a randomly generated "salt" along with the username. The salt ensures that if any of the parameters used to perform encryption become compromised, existing tokens can be invalidated and new ones generated. Most importantly, because the username is used as part of the user token generation algorithm, the salt prevents having to change all user names in the event of a compromise.

The salt is stored in the Credential Store Framework (CSF) in the map o.webcenter.jf.csf.map against key user.token.salt. You can change the value of this key (and other keys used for token encryption) by accessing CSF in Oracle Enterprise Manager.

Caution:

If you change the encryption key values, all existing username based security tokens will immediately become invalid. Only change these values under extraordinary circumstances, like an algorithm parameter compromise.

53.3 Benefits of Using REST

Many excellent articles have been published about REST and the benefits of the RESTful style of software architecture. Some of these benefits include:

  • Using "Hypermedia As The Engine Of Application State" (HATEOAS) links to access the REST API helps promote API robustness. Since the clients only use URIs returned from the server, if the server changes the URI format, the client will continue to function properly. See also Section 53.5, "Understanding the Link Model."

  • Using the standard HTTP protocol allows network infrastructure to cache REST requests where appropriate, reducing load on both the client and server. See also Section 53.11, "Managing Caches."

  • Stateless REST requests allow each request to be served by any number of different servers, helping with scalability.

  • Using the standard HTTP protocol allows a wide variety of clients to interact with the REST APIs without requiring specialized libraries.

53.4 Introduction to WebCenter Portal's REST APIs

In addition to enabling mobile access, WebCenter Portal REST APIs allow you to take advantage of Web 2.0 technologies like Ajax, JavaScript, and JSON to create rich, interactive browser-based user interfaces and to access and modify Oracle WebCenter Portal Framework and WebCenter Portal data. In general, the WebCenter REST commands provide a more natural and easy-to-use alternative to a SOAP-style Web services approach.

Table 53-1 describes the Oracle WebCenter Portal REST APIs provided for WebCenter Portal tools and services features.

Note:

Portal Framework applications only support the REST API for Navigation. All other REST APIs are supported only by the WebCenter Portal application.

Table 53-1 Summary of WebCenter Tools and Services Features Supported by REST APIs

REST API Description Chapter

Discussions

Enable a client to post, read, update, and delete discussion forums, topics, and messages.

Section 33.3.8, "Using the Discussions REST API."

Lists

Enables a client to browse all the lists associated with a named portal; search list columns given a search term; create new lists; add, update, and remove list rows; and similar sorts of list-related tasks

Section 49.4, "Using the Lists REST API."

People Connections

Enable a client to view profile data; manage connection lists, feedback, and messages; create new activities and view activities for users, lists, and portals.

Chapter 42, "Using the People Connections REST APIs."

WebCenter Portal

Enable a client to retrieve portal metadata and view, create, update, and delete portal lists and list items. You can also retrieve portal membership information.

Section 56.2, "Using the WebCenter Portal REST API."

Content Management

Uses the CMIS (Content Management Interoperability Services) RESTful server binding to provide access to the CM VCR (Content Management Virtual Content Repository).

Chapter 31, "Content Management REST API."

Activity Graph

Enables you to retrieve recommendations for connections, portals, and items using the underlying Activity Graph engine.

Section 46.3.2, "Using the Activity Graph REST APIs."

Events

Lets you access calendar events associated with a named portal.

Section 48.3, "Using the Events REST API."

Feedback

Enables a client to create, read, and delete feedback in a social networking application.

Chapter 42, "Feedback REST API."

Search

Lets you post, read, update, and delete searches. You can specify keywords and the scope of the search; for example, the iPhone could search for "smith" in all portals, documents and wiki pages.

Section 45.3.4, "Using the Search REST APIs."

Tags

Enables a client to read, post, update, and delete tags and tagged items.

Section 44.3.2, "Using the Tags REST APIs."

Navigation

Use the navigation REST APIs to create your own interface for displaying navigations.

Note: The navigation REST APIs do not share the resource index described in this chapter.

Section 10.11.2, "Using the Navigation REST APIs."

Personalization

Enables you to access the Personalization Conductor.

Chapter 72, "Conductor API Reference."

Pagelets

Allows remote Web services to retrieve information about resources and pagelets. Inject pagelets into non-proxied pages, allowing the Pagelet Producer to act as a portlet provider for Oracle WebCenter Interaction, Oracle WebLogic Portal, or other third-party portals.

Section 62.7.2.2, "Accessing Pagelets Using REST."


Note:

XSD files for the following URNs:
urn:oracle:webcenter:activities:stream -> activitystream.xsd
urn:oracle:webcenter:messageBoard -> wall.xsd
urn:oracle:webcenter:people -> people.xsd
urn:oracle:webcenter:people:invitations -> people.xsd
urn:oracle:webcenter:people:person -> people.xsd
urn:oracle:webcenter:search:results -> search.xsd
urn:oracle:webcenter:spaces -> spaces.xsd

can be found in your <WCP_ORACLE_HOME>/webcenter/schemas/ directory.

53.5 Understanding the Link Model

Hypermedia is at the core of two of the most successful Web-based formats: HTML and ATOM. HTML and ATOM allow consumers to navigate to other hypermedia documents through links–for example, clicking on a link to go to a news article.

Hypermedia drives the RESTful application state (known as HATEOAS: Hypermedia As The Engine Of Application State).

Note:

HATEOAS analogy to define application state:

Suppose you are completing your taxes in your favorite browser. You finish entering your W-2 data and move on to deductions when the browser crashes. The state you lost—the fact that you were on deductions and still needed to enter data—is the application state; not the W-2 data entered (that is, change states from the current state).

HATEOAS dictates that this state—the application state—be captured wholly in hypermedia. Application state is where you are in the application, not what data you've entered into the application. One of the benefits of this approach is that it simplifies the client and server, because they do not need to be aware of the state they are in. The link contains all the state information necessary to process the request, so, when the browser restarts and returns to the link, the user will be at the same place in the tax process.

Given a set of top-level URI entry points to a RESTful service, all interactions beyond those entry points are driven by hypermedia links returned in response representations. This link-centered approach helps keep the client from becoming too tightly coupled to the server URLs. The client is using URLs given to it by the server, therefore the client code does not break if the server URLs change format.

Understanding this link model helps you understand how to use the data the service returns to navigate the REST APIs.

This section describes the hypermedia link model used by WebCenter's RESTful services. It includes the following subsections:

53.5.1 Using the Resource Index

In WebCenter, the Resource Index is your starting point for all authenticated access. The Resource Index provides access to the set of top-level URI entry points. It provides the way in to all the available WebCenter RESTful services. The Resource Index URI is the only URI that you need to know.

Tip:

A REST client is helpful for generating custom REST requests. For example, a Firefox RESTClient add-on is available at:

http://restclient.net/

Other similar REST clients can also be easily obtained.

The WebCenter Resource Index URI is:

http://host:port/rest/api/resourceIndex

Note:

Access to the Resource Index always requires authentication; however, you can (optionally) access the CMIS resource entry point anonymously using the following URI:

http://host:port/rest/api/cmis/repository

See also Section 53.9, "Security Considerations for CMIS REST APIs," and Section 53.8, "Security Considerations for WebCenter Portal REST APIs."

The first step in using the WebCenter Portal REST APIs is to send a GET request to the Resource Index. The response varies depending on the services available and the media type of the request. Example 53-1 shows how the response might look if you made an Ajax request using JavaScript (and possibly a client-side scripting library, such as Dojo) to retrieve the JSON data for the Resource Index. Note that this is an abridged sample response and does not include all of the links actually present in a real response.

Example 53-1 Response to a GET on the Resource Index

{
  "resourceType": "urn:oracle:webcenter:resourceindex",
  "links": [
    {
      "template": "opaque-template-uri",
      "resourceType": "urn:oracle:webcenter:messageBoard",
      "href": "opaque-uri",
      "capabilities": "urn:oracle:webcenter:read"
    },
    {
      "resourceType": "urn:oracle:webCenter:cmis",
      "href": "opaque-uri",
      "capabilities": "urn:oracle:webcenter:read"
    },
    {
      "template": "opaque-template-uri",
      "resourceType": "urn:oracle:webcenter:discussions:forums",
      "href": "opaque-uri",
      "capabilities": "urn:oracle:webcenter:read"
    },
    {
      "resourceType": "urn:oracle:webcenter:resourceindex",
      "rel": "self",
      "href": "http://host:port/rest/api/resourceIndex",
      "capabilities": "urn:oracle:webcenter:read"
    },
    {
      "template": "opaque-template-uri",
      "resourceType": "urn:oracle:webcenter:activities:stream",
      "href": "opaque-uri",
      "capabilities": "urn:oracle:webcenter:read"
    },
    {
      "template": "opaque-template-uri",
      "resourceType": "urn:oracle:webcenter:people:person",
      "capabilities": "urn:oracle:webcenter:read"
    },
    {
      "template": "opaque-template-uri",
      "resourceType": "urn:oracle:webcenter:feedback",
      "href": "opaque-uri",
      "capabilities": "urn:oracle:webcenter:read"
    },
    {
      "template": "opaque-template-uri",
      "resourceType": "urn:oracle:webcenter:spaces",
      "href": "opaque-uri",
      "capabilities": "urn:oracle:webcenter:read"
    },
    {
      "template": "opaque-template-uri",
      "resourceType": "urn:oracle:webcenter:people",
      "href": "opaque-uri",
      "capabilities": "urn:oracle:webcenter:read"
    }
  ]
}

By interpreting the links returned in the Resource Index data, you can retrieve the URI entry point for an individual service by locating the URI for the resource type you want to use. You can then continue navigating through the hypermedia until you can perform the required operation. Example 53-2 shows a method that locates a URI given the Resource Index JSON data.

Example 53-2 Locating the URI for a Particular Service in the Resource Index

/* Parse the resourceIndex to find the specified URL and
 * return it.
 *
 * @Param jsonData the JSON data retrieved from calling
 *        the /rest/api/resourceIndex URL.
 * @Param strResourceType the resource type of the URL
 *        you want to retrieve from the resourceIndex data.
 *        E.g., 'urn:oracle:webcenter:activities:stream'
 */
function getResourceURL(jsonData, strResourceType)
{
  // Using the HATEOAS model, we browse the returned links
  // looking for the one with the correct resource type.
  for (var i = 0; i < data.links.length; i++) {
    if (data.links[i].resourceType == strResourceType) {
      return data.links[i].href;
    }
  }
}

53.5.2 Anatomy of a Link

The resourceType, rel, and capabilities attributes of the hypermedia link provide metadata that enable clients to determine which URI (href or template) to use, without having to parse the URIs directly. The URIs are opaque—the metadata determines which link is useful in a given circumstance.

Example 53-3 and Example 53-4 show the anatomy of a hypermedia link as XML and in JSON document fragments, respectively.

Example 53-3 Link in an XML Document Fragment

<links>
  <link href="opaque-URI"
        template="opaque-template-URI (optional)"
        rel="rel-name"
        title="human-readable-title (optional)"
        type="media-type (optional)"
        resourceType="resource-type"
        capabilities="operation"/>
  ...repeat as needed...
</links>

Example 53-4 Link in a JSON Document Fragment

"links": [
  {
    "href":"opaque-URI",
    "template":"opaque-template-URI (optional)",
    "rel":"rel-name",
    "title":"human-readable-title (optional)",
    "type":"media-type (optional)",
    "resourceType":"resource-type",
    "capabilities":"operation"
  },
  ...repeat as needed...
]

Multiword field, element, and attribute names are formatted in camel case, unless the representation is attempting to conform to a specification not under the service author's direct control. Acronyms are treated as normal words with their case adjusted accordingly (for example, fooXml or xmlFoo) as shown in Example 53-5 and Example 53-6.

Example 53-5 XML Naming Convention

<myElement>text</myElement>

Example 53-6 JSON Naming Convention

{"myElement": "text"}

This section includes the following subsections that describe the different attributes of the hypermedia link:

53.5.2.1 Resource Type

The resourceType link attribute indicates the type of resource to which the link points. Clients should use the resourceType to determine the expected response bodies for GET and POST and allowable request bodies for POST and PUT.

For more information, see Section 53.7, "Navigating Hypermedia Using HTTP."

53.5.2.2 Relationship

The rel link attribute indicates the relationship of the linked object to the current object (that is, the object that contains the list of links). The value of this attribute is a space-separated list of the following currently supported values:

  • self - The linked object is the current object

  • related - The linked object is related to the current object

  • via - The linked object is the source of the information for the current object

  • alternate - The linked object is a substitute for the current object (typically, the same object in another format, such as an HTML page that displays the current object)

  • urn:oracle:webcenter:parent - The linked object is the parent of the current object. That is, the linked object owns the current object

    Note:

    Some REST APIs for some WebCenter features may contain additional rel link attributes. See the REST API documentation for each specific feature for more information.

53.5.2.3 Capabilities

The capabilities link attribute indicates which methods are supported by the linked resource.

Links are returned only if a client is allowed to access that resource. User authorization can affect the capabilities a client has with the links returned in a response representation. In general, services only return the capabilities that the current authorized user has permission to execute and that the resource supports.

If there is no link, then the client cannot access the resource. If a link has no capabilities, then it is not returned to the client, meaning that the client does not have permission to do anything with that link (even read it).

Capability-based expression of hypermedia links communicates the range of operations that the client can expect to succeed, which allows the client to dynamically configure any associated UI to provide the best overall user experience.

The value of this attribute is a space-separated list of the following values:

  • urn:oracle:webcenter:create - This maps to the HTTP verb POST

  • urn:oracle:webcenter:read - This maps to the HTTP verb GET

  • urn:oracle:webcenter:update - This maps to the HTTP verb PUT

  • urn:oracle:webcenter:delete - This maps to the HTTP verb DELETE

Note:

The top-level resourceIndex links only returns the read capability, even if the user is authorized with additional capabilities.

Note:

Querying a resource for the allowed HTTP verbs using OPTIONS returns the verbs that the resource can support in general, and does not take a user's access into account. The capabilities attribute in a link describes exactly what the current user can do with the current resource. OPTIONS may return more HTTP verbs than the current user is allowed.

53.5.2.4 Media Type

The type link attribute indicates the media types supported by the linked object.

All REST services, except for CMIS, support both XML (application/xml) and JSON (application/json) media type. CMIS currently supports only ATOM. For more information about the CMIS REST API, see Chapter 31, "Content Management REST API."

53.5.2.5 Templates

The template link attribute indicates that the client can use a URI template, instead of the href URI, to provide parameterized values for the linked object. Links must include at least an href or a template URI, but can include both.

Some hypermedia links support request query parameters that allow the client to configure the link in different ways. Rather than force the client to know the URI format and manually build the URI, URI templates are used. These templates allow client code to easily insert data into a URI without having to understand exactly how the URI works. This maintains the opacity of hypermedia URIs and protects the client from changes to the URI format.

Example 53-7 shows a URI template including several request query parameters.

Example 53-7 URI Template

http://host:port/.../lists?startIndex={startIndex}&itemsPerPage={itemsPerPage}&q={searchTerms}&projection={projection]

WebCenter Portal REST APIs use a simple slot replacement syntax that follows many industry URI template schemes.

For example, using the template in Example 53-7, to see 10 list items (default) on the first page, the client would provide a value of 1 for the startIndex parameter and a value of 10 for the itemsPerPage parameter, as shown in Example 53-8.

Example 53-8 URI Template with Parameter Values

http://host:port.../lists?startIndex=1&itemsPerPage=10

Note:

All unused parameters must be removed from a template before it can be used. Clients may not submit unprocessed templates to the service that produced it; doing so results in undefined behavior, generally returning a status code of 500.

Clients must process templates into valid URI form before submitting to the server. Clients must replace slots with appropriate values, taking care to properly URI encode any value replacing the slot token. If a client does not have a suitable value for one or more of the slots in the template, then it must replace the slot token with an empty string.

You must URL-encode special or reserved character in parameter values. For example, to search lists for a person named Günter, you must URL-encode the ü as shown in Example 53-9.

Example 53-9 Encoding Special Characters in URI Templates

http://host:port.../lists?q=G%FCnter

Common Request Query Parameters

Many resources support a common set of request query parameters. For example, when retrieving a collection of entities, it is common to change the shape of the results set by limiting the quantity or details of the results. The REST framework uses the following request parameters to scope results and provide security:

  • startIndex - Specifies the index of the first matching result that should be included in the result set (0-n ... zero based). This is used for pagination.

  • itemsPerPage - Specifies the maximum number of results to return in the response (1-n). This is used for pagination.

  • q - Specifies implementation-specific searching. Searches may be specified using the following format (square brackets [] denote optional values):

    [[field1:[operand]][:]value1[;field2:operand:value2]]
    

    For example:

    &q=login:equals:monty
    &q=title:contains:issues
    &q=creator:equals:monty;description:contains:Urgent
    

    While each resource uses the same format for the q parameter, the way search is implemented is different depending on the resource being searched. For more information about how each resource implements search, see the chapter for the specific service.

  • projection - Reserved for implementation-specific projection of model representations, such as variable recursion depth, field or attribute filtering. Valid values are summary or details.

    For example, requesting a projection of summary for a collection of lists, returns only the title, description, and hypermedia links. Requesting a projection of details results in the server sending back a collection of lists that includes all the column metadata for each list. This may require additional processing time or database queries on the server.

    The following example request results in the response entity containing a deeper object graph.

    http://host:port/...lists&projection=details
    
  • data - This parameter accepts a comma separated list of data sets and items. This parameter lets clients specify what data they would like to receive. For example, a mobile device application might use this parameter to limit the amount of XML data returned. If both the projection and data query string parameters are present, the data parameter will be used to determine which data to return. If you specify the constant 'data' as the data parameter, all the standard information will be returned for the resource.

For information about how these parameters are supported by specific resources, see the chapter for the appropriate service.

53.6 Understanding Items Hypermedia

A collection of items makes up the actual content of responses. This is at the same level as the links section described previously. Each item (including the top-level tag in each response) has one common attribute (resourceType) in addition to resource-specific content and format. For details beyond the resourceType, see the chapter for the specific service.

See Example 53-13 for an example that describes a collection of entities/items. Example 53-15 describes a single entity/item.

53.7 Navigating Hypermedia Using HTTP

You can navigate REST service hypermedia in a similar way to that used to browse and interact with HTML or an ATOM feed. Interactions are performed on the resources identified by links using HTTP methods. The REST services return response codes and response bodies to the client, and the client uses the hypermedia in the response to drive further interactions.

Table 53-2 describes the general pattern followed when constructing opaque resource URIs. The resourceType differentiates whether the HTTP method operates on a collection of resources or an individual resource.

Table 53-2 HTTP Methods

HTTP Method Response for a Collection of Resources Response for an Individual Resource

GET

Returns resource collection container (200 HTTP response code)

Returns resource (200 HTTP response code)

PUT

Cannot update a collection of resources (405 HTTP response code)

Updates and returns resource (200 HTTP response code)

POST

Creates and returns a new resource within the collection.

Note: Can return a 201 or 204 HTTP response code. The returned code depends on whether the newly created object is directly addressable or not. For instance, activities cannot be addressed individually, so they return a 204 no-content response code.

Cannot create a resource within an individual resource (405 HTTP response code)

DELETE

Cannot delete a collection of resources (405 HTTP response code)

Deletes resource (204 HTTP response code)


Collection resources generally support reading a collection (GET) and creating a subordinate to that collection (POST). Individual resources generally support reading a resource (GET), updating a resource (PUT), and deleting a resource (DELETE).

HTTP Response Status Codes

Table 53-3 describes the potential response status codes.

Table 53-3 HTTP Response Status Codes

HTTP Response Status Code Description

200

OK. Upon successful completion of a GET or PUT. This is accompanied by a resource representation as a response body.

201

Created. Upon successful completion of a POST. This has a location header to the newly-created resource.

204

No content, or any request that does not return content. For example, creating an object that cannot be linked. Upon successful completion of a DELETE.

400

Bad Request. The URI was malformed or could not be processed; for example, the IDs were not formatted correctly, or the ID was supplied in the URI on a POST.

401

Unauthorized. Client may retry by submitting credentials. This may be accompanied with a fault response body to help diagnose the issue.

403

Forbidden. Client does not have permission to perform a particular action, such as creating or deleting a resource. Re-authenticating as the same user does not help. This may be accompanied with a fault response body to help diagnose the issue.

404

Not Found. Referencing a specific resource with an ID, but that resource does not exist.

405

Method Not Allowed. This includes a list of valid methods for the requested resource.

406

Not Acceptable. The Accept header media type(s) sent by the client are not supported for the requested operation.This may be accompanied with a fault response body to help diagnose the issue.

409

Conflict. Possibly the resource ID is in use, or an entity has been modified by another process during an update.This may be accompanied with a fault response body to help diagnose the issue.

422

Bad entity body, the data in the body, although syntactically correct, was not valid, or could not be processed; for example, invalid data when updating a row.

500

Internal server error. The server encountered an unexpected condition that prevented it from fulfilling the request.

501

Not Implemented. The server does not support the functionality required to fulfill the request. This is the appropriate response when the server does not recognize the request method and is not capable of supporting it for any resource.


53.8 Security Considerations for WebCenter Portal REST APIs

All of the WebCenter REST URIs reference protected resources (similar to protected web pages) and require authentication for access.

Note:

The one exception to the authenticated access rule is access to the CMIS resources. CMIS resources can be accessed anonymously through the CMIS URI entry point:

http://host/port/rest/api/cmis/repository

See also Section 53.9, "Security Considerations for CMIS REST APIs."

You can pass this authentication in with the request using basic authentication, or you can configure the client and the WebCenter REST service to use single sign-on. For more information about single sign-on, see the "Configuring SSL" chapter in Administering Oracle WebCenter Portal.

Basic authentication sends the user's password in plain text. If you use this type of authentication, you should consider securing the connection using SSL. For more information, see the "Configuring SSL" chapter in Administering Oracle WebCenter Portal.

To provide additional security, every URI, for both href and template attributes, includes a security token parameter. The security token is user-scoped. This means that it is based on and scoped to an authenticated user and can be bookmarked or cached across that user's sessions. These security tokens help prevent Cross-Site Request Forgery (CSRF) attacks.

For example:

<link
  template="opaque-template-uri/@me?startIndex={startIndex}&itemsPerPage={itemsPerPage}
     &token=generated-token" resourceType="urn:oracle:webcenter:messageBoard"
     href="opaque-uri/@me?token=generated-token" capabilities="urn:oracle:webcenter:read"
/>

Note:

The security token is not used for authentication or identity propagation.

WebCenter Portal REST APIs operate under the identity of the authenticated user. For example, the portal REST APIs only return information for, and allow changes to, portals to which the user has access.

53.9 Security Considerations for CMIS REST APIs

The CMIS REST APIs do not use the same authentication scheme as the other WebCenter Portal REST APIs. Whereas other WebCenter Portal REST APIs do not allow unauthenticated access and prompt the user for authentication before allowing access, the CMIS REST APIs do allow unauthenticated access.

If a document requires authentication information and does not receive that information (because it is being accessed by an unauthenticated user), a 404 error is returned. This does not necessarily mean that the document cannot be found, rather that the (unauthenticated) user does not have the appropriate permissions to access the document. For the request to succeed, it should include basic authentication headers to identify the current user.

CMIS stands for Content Management Interoperability Services, a standard REST interface for Enterprise Content Management Systems. For more information, see Chapter 31, "Content Management REST API."

53.10 Understanding Common Types

This section describes the common types that are shared by multiple WebCenter Portal REST APIs.

53.10.1 Common Types

Common types provide a consistent way to reference objects used in the WebCenter Portal REST APIs.

This section includes the following subsections:

53.10.1.1 personReference

This is a generic data type that represents a user in the system. It is used by several APIs, for example to identify the author of a message board or feedback message, or a user's manager or direct reports. It is made up of the following elements:

  • guid - The GUID of the user

  • id - The login ID of the user

  • displayName - The display name of the user

The personReference also includes a link to the user's profile icon. You can control the size of the icon by providing values: small, medium, or large.

Depending on where the personReference type is included, it can also return links to the associated REST APIs of the generating response. For example, if the personReference type is included as the author in a message board response, it includes links to message board services.

53.10.1.2 groupSpaceReference

This is a generic data type that represents a portal. It is used by several APIs, for example in the activity stream, to identify a portal in which a particular activity occurred. It is made up on the following elements:

  • guid - The GUID of the portal

  • name - The name of the portal

  • displayName - The display name of the portal

The groupSpaceReference also includes an html link, rest link, and icon link.

53.10.2 Portable Contact Types

Portable Contact types provide users with a standard way to access their address books and friends lists over the Web. Portable Contact types are used by the Profile component of the People Connections service.

Note:

These types are based on the Portal Contact Types in WebCenter. They may include additional data.

This section includes the following subsections:

53.10.2.1 name Portable Contact Type

This is a portable contact type that provides information about the user's name. It is made up of the following elements:

  • formatted - The formatted version of the full name of the user, for example, Michael David Jones Ph.D.

  • familyName - The family name, or last name, of the user, for example Jones

  • givenName - The given name, or first name, of the user, for example Michael

  • honorificSuffix - The honorific suffix of the user, for example, Esq. or Ph.D.

  • initials - The first initials of the user, for example, M. D.

  • maidenName - The maiden name of the user

Some of the elements may not be present depending on the user repository configuration and data.

53.10.2.2 address Portable Contact Type

This is a portable contact type that provides information about the user's address. It is made up of the following elements:

  • formatted - The formatted version of the full address

  • type - The type of the address, for example, Home, Work

  • streetAddress - The street address

  • poBox - The post office box number

  • locality - The city or locality

  • region - The state or region

  • postalCode - The zip code or postal code

  • country - The country

Some of the elements may not be present depending on the user repository configuration and data.

53.10.2.3 organization Portable Contact Type

This is a portable contact type that provides information about the user's organizational affiliation. It is made up of:

  • name - The name of the organization

  • employeeNumber - The employee number of the user

  • employeeType - The employee type of the user.

  • department - The department within the organization to which the user belongs

  • defaultGroup - The default group to which the user belongs

  • title - The job title of the user within the organization

  • description - A textual description of the user's role within the organization

  • expertise - The expertise of the user within the organization

  • startDate - The date when the user joined the organization

Some of the elements may not be present depending on the user repository configuration and data.

53.10.2.4 value Portable Contact Type

This is a generic object that contains data for a wide variety of contact information. It is made up of the following elements:

  • primary - A boolean value that identifies whether this is the primary piece of information of this type for this person. The primary element may not be present and is only relevant if there are multiple values for the same type of data.

  • value - The value for this type

  • type - The type of information. Valid types are:

    • standard: with valid values of work, home, other

    • phoneNumber: with valid values of work, home, fax, pager, mobile

    • photos: with a valid value of thumbnail

53.11 Managing Caches

Client-side developers need to know how to handle HTTP cache headers in both requests and responses. Individual resources that have a "last modified" date are also return entity tags. The entity tags can be used to make retrieval of a specific entity more efficient. To learn more about the use of entity tags in caching, refer to the Hypertext Transfer Protocol specification:

http://www.w3.org/Protocols/

53.12 Configuring a Proxy Server

This section explains how to set up a simple, response-rewriting reverse HTTP proxy on an Apache server. A proxy server is typically employed to avoid cross-domain request problems associated with making XMLHttpRequest (XHR) calls from a browser client. These calls are typically associated with the Ajax development technique for creating rich, interactive client-side interfaces. REST APIs are typically used within this kind of client-side development scenario.

Note:

This section illustrates a simple example of setting up a proxy server on Apache. For more detailed information, refer to the Apache Server documentation available at http://httpd.apache.org/docs. You can also use Oracle HTTP Server (OHS) for your proxy server. For more information, see Administrator's Guide for Oracle HTTP Server.

The basic steps for setting up a proxy server on Apache are:

  1. Obtain access to an Apache server. Oracle recommends Apache 2.2.7 or a later version.

  2. Make sure the server has the mod_substitute and mod_proxy modules installed. Note that Apache versions 2.2.7 and later include mod_substitute by default. It is also possible to use mod_sed or mod_line_edit, however these configurations are not supported by Oracle.

  3. Open the httpd.conf or the virtual host configuration file, and add the following lines, substituting your server name/information where appropriate:

    ProxyRequests           Off
    LoadModule              substitute_module       modules/mod_substitute.so
    SetOutputFilter         SUBSTITUTE
     
    ProxyPass               /rest/api/              http://myhost:8888/rest/api/
    ProxyPassReverse        /rest/api/              http://myhost:8888/rest/api/
    Substitute              s|myhost|yourhost|n
     
    ProxyPass               /pathname/rest/api/        http://myhost:8888/rest/api/
    ProxyPassReverse        /pathname/rest/api/        http://myhost:8888/rest/api/
    Substitute              s|myhost:8888/rest/api|yourhost/pathname/rest/api|n
    

    Note:

    Two servers are being proxied in this example scenario. Note that the following two calls are actually talking to these two different servers, but they appear to clients to be the same server host:

    http://myhost/rest/api/resourceIndex

    http://myhost/pathname/rest/api/resourceIndex

  4. Restart the Apache server. For example, on Linux, you could do this:

    sudo /etc/init.d/httpd restart
    

Note that on some configurations of Linux, proxying with Apache in this fashion requires you tell selinux to allow outbound connections from httpd. You can accomplish this by enabling the httpd_can_network_connect flag in selinux's GUI or through the command line.

Developer Tip:

Set the UserDir permissions in httpd.conf to allow users to drop these files in their own public_html directory. For example, you might hit http://host/~yourname/sample.html to access your sample application, and then have the sample application make XHR calls to http://host/rest/api/resourceIndex.

53.13 WebCenter Portal's REST API Examples

This section includes some examples illustrating how to use the WebCenter Portal REST APIs. It includes the following subsections:

53.13.1 Navigating the Message Board Hypermedia

This section includes examples to illustrate how to navigate the REST service hypermedia. The examples show how to read messages on a message board, post messages to another user's message board, delete unwanted messages, and filter message board messages.

This section includes the following subsections:

53.13.1.1 Accessing the Resource Index

The first step is always to access the Resource Index (Example 53-10).

Example 53-10 Accessing the Resource Index

GET /resourceIndex

This request returns a list of the top-level URI entry points to the RESTful services, including the entry point for the message board (Example 53-11).

Example 53-11 Response to Accessing the Resource Index

200 OK
Accept: application/json;charset=UTF-8

{
  "resourceType": "urn:oracle:webcenter:resourceindex",
  "links": [
    {
      "resourceType": "urn:oracle:webcenter:resourceindex",
      "capabilities": "urn:oracle:webcenter:read",
      "rel": "self",
      "href": "http://host:port/rest/api/resourceIndex"
    },
    {
      "resourceType": "urn:oracle:webcenter:messageBoard",
      "capabilities": "urn:oracle:webcenter:read",
      "href": "opaque-messageBoard-URI"
    },
  ...repeating for other services...
}

You can examine this list to find the URI that you require to access your message board. You should look for the link with a resourceType of urn:oracle:webcenter:messageBoard. The href for this link is the one that you require to access your message board.

For other resources rel, type, and template also help find the correct link.

53.13.1.2 Reading Messages

Once you have determined the correct URI for your message board, you can send a GET request to that URI to read your messages (Example 53-12).

To read messages on a message board, you must be logged in.

Example 53-12 Retrieving Messages from Your Message Board (GET)

GET /opaque-messageBoard-URI
 

The response provides information about all the messages on your message board (Example 53-13).

Example 53-13 Response to Retrieving Messages from Your Message Board

200 OK
Accept: application/json;charset=UTF-8
 
{
  "resourceType": "urn:oracle:webcenter:messageBoard",
  "links": [
    {
      "resourceType": "urn:oracle:webcenter:messageBoard",
      "capabilities": "urn:oracle:webcenter:read urn:oracle:webcenter:create",
      "rel": "self",
      "href": "opaque-messageBoard-URI"
    }
  ]
  "items": [
    {
      "resourceType": "urn:oracle:webcenter:messageBoard:message",
      "links": [
        {
          "resourceType": "urn:oracle:webcenter:messageBoard:message",
          "capabilities": "urn:oracle:webcenter:read urn:oracle:webcenter:delete",
          "rel": "self",
          "href": "opaque-message-URI"
        }
      ]
      "id": "89add57c-7a35-4d35-b24f-ea9259612eb8",
      "body": "What's up?  It's been a while.  Some of us are going to Conner O'Neal's after work.  Want to go?",
      "created": "2009-09-10T11:18:46.696-0700",
      "author": {
        "id": "carl",
        "displayName": "carl",
        "guid": "649A27F09D5C11DEBFAA799CBD41D9B8",
        "links": [
          {
            "resourceType": "urn:oracle:webcenter:people:person",
            "capabilities": "urn:oracle:webcenter:read",
            "rel": "via",
            "href": "opaque-person-URI"
          },
          {
            "resourceType": "urn:oracle:webcenter:messageBoard",
            "capabilities": "urn:oracle:webcenter:read urn:oracle:webcenter:create",
            "href": "opaque-messageBoard-URI-for-Carl"
          },
          {
            "type": "text/html",
            "resourceType": "urn:oracle:webcenter:spaces:profile",
            "capabilities": "urn:oracle:webcenter:read",
            "rel": "alternate",
            "href": "opaque-profile-URI"
          }
        ]
      },
    }
  ],
  "startIndex": 0,
  "itemsPerPage": 1,
}

From the response you can see that you have read and create capabilities on your message board. So you can read its contents and post new messages.

In addition, the response also includes a collection of items (in this case the collection consists of just a single item). These items, with a resourceType of urn:oracle:webcenter:messageBoard:message, are the messages on your message board. The capabilities attribute for the message indicates that, for this particular message, you can read it or delete it from your message board.

For each message, the response provides the following information:

  • id - the identifier of the message

  • body - the text of the message

  • author - the author of the message. The author element is also made up of several other elements:

    • id - the identifier, or user name, of the author of the message

    • displayName - the name of the author, formatted for display

    • guid - the globally unique identifier of the author

Within the author element there is also a collection of three links. The resourceType of these links are:

  • urn:oracle:webcenter:people:person - enables you to view information about the author of the message

  • urn:oracle:webcenter:messageBoard - enables you to read or create a message on the author's message board

  • urn:oracle:webcenter:spaces:profile - enables you to read a text/html document of the author's profile

53.13.1.3 Creating a New Message

Now that you have read the message on your message board, you probably want to reply to Carl on his message board. To do this you should send a POST request to the URI for Carl's message board.

To find the correct URI, use the href from the author link with resourceType of urn:oracle:webcenter:messageBoard.

A POST request creates a subordinate resource of the resource to which you post it. In this case, we are posting to the messageBoard, so we should post its subordinate resource: message (Example 53-14).

Example 53-14 Creating a Message on Another User's Message Board (POST)

POST opaque-messageBoard-URI-for-Carl
Accept: application/json;charset=UTF-8
Content-Type: application/json;charset=UTF-8
 
{
    "body": "sure; see you guys at 6."
}

The response shows that your message was successfully created on Carl's message board (Example 53-15).

Example 53-15 Response to Creating a Message on Another User's Message Board

201 Created
Content-Type: application/json;charset=UTF-8
 
{ 
  "id": "36b8464f-afda-44b5-90ad-8ecedcb040a3", 
  "body": "sure; see you guys at 6.", 
  "created": "2009-09-10T12:21:09.785-0700", 
  "resourceType": "urn:oracle:webcenter:messageBoard:message", 
  "links": [ 
    { 
      "resourceType": "urn:oracle:webcenter:messageBoard:message", 
      "capabilities": "urn:oracle:webcenter:read urn:oracle:webcenter:update urn:oracle:webcenter:delete", 
      "rel": "self", 
      "href": "opaque-message-URI" 
    },
  "author": { 
    "id": "mike", 
    "displayName": "mike", 
    "guid": "649657609D5C11DEBFAA799CBD41D9B8", 
    "links": [ 
      { 
        "resourceType": "urn:oracle:webcenter:people:person", 
        "capabilities": "urn:oracle:webcenter:read", 
        "rel": "self", 
        "href": "opaque-person-URI" 
      }, 
      { 
        "resourceType": "urn:oracle:webcenter:messageBoard", 
        "capabilities": "urn:oracle:webcenter:read urn:oracle:webcenter:create", 
        "href": "opaque-messageBoard-URI" 
      }, 
      { 
        "type": "text/html", 
        "resourceType": "urn:oracle:webcenter:spaces:profile", 
        "capabilities": "urn:oracle:webcenter:read", 
        "rel": "alternate", 
        "href": "opaque:profile:URI" 
      } 
    ] 
  }
  ] 
}

53.13.1.4 Updating a Message

A PUT request is very similar to a POST request, except that it is performed on the resource being edited, instead of on the parent resource.

From the response to your earlier POST request, when you created your message on Carl's message board, you can see that you have read, update, and delete capabilities on the message. You can also see that the href provides the URI for your message. Something came up at work and you must stay a bit later. Using the URI for your message, you can now send a PUT request to update the message and let Carl know that you are going to be late (Example 53-16).

Example 53-16 Updating a Message (PUT)

PUT opaque:message:URI
Accept: application/json;charset=UTF-8
Content-Type: application/json;charset=UTF-8
 
{
    "body": "working late; see you guys at 7."
}

The response is nearly identical to that of POST, except that the body contains your updated message (Example 53-17).

Example 53-17 Updating a Message

200 OK
Content-Type: application/json;charset=UTF-8
 
{ 
  "id": "36b8464f-afda-44b5-90ad-8ecedcb040a3", 
  "body": "working late; see you guys at 7.", 

...deleted for brevity...

}

53.13.1.5 Deleting a Message

Performing a DELETE request on a resource deletes it, if you have the delete capability on the resource. The link to your message on Carl's message board supports delete.

You decide to delete the message that you left on Carl's message board (Example 53-18).

Example 53-18 Deleting a Message (DELETE)

DELETE opaque:message:URI

The response is simply a status code of 204 (Example 53-19).

Example 53-19 Response to Deleting a Message

204 NO CONTENT

Note:

DELETE is idempotent, meaning that it can be sent multiple times with the same result. Therefore if you try to delete the same object twice, you still receive the same 204 response even though it has previously been deleted.

53.13.1.6 Filtering Messages

Messages can be filtered (using the HTTP verbs GET, POST, and PUT) based on visibility criteria. Messages posted on message boards falls into the following visibility categories:

  • Public

  • Private

  • Hidden

  • Public and hidden

  • Private and hidden

Public vs Private Messages

The owner of a message board can mark any message as private. When a message is marked as private, that message is not visible to anyone other than the owner of the message. By default, all messages are public.

Messages can also be sent as private messages. If Mike, for example, is viewing Carl's message board, only public messages (including those sent or received as private) will be visible to user Mike.

Hidden vs Non-hidden Messages

The owner of a message board can mark any message as hidden. When a message is marked as hidden, that message will not be visible to the message board's owner, but will remain visible to anyone else viewing that person's message board.

The following examples show how to retrieve,

Example 53-20 Retrieving Filtered Messages (GET)

  • me

       all
         rest/api/messageBoards/person/@me 
       private
         rest/api/messageBoards/person/@me/private
       public
         rest/api/messageBoards/person/@me/public
       hidden and public
         rest/api/messageBoards/person/@me/hidden 
       private and hidden
         rest/api/messageBoards/person/@me/private_hidden
    
  • person

       rest/api/messageBoards/person/<GUID> 
    

    Note that the GUID of the logged in user for whom to retrieve messages is required.

  • space-guid

       rest/api/messageBoards/space/<GUID>
    

    Note that visibility-based filtering is not available for space-guid.

Example 53-21 Using Filtering for New Messages (POST)

  • me

       all
         rest/api/messageBoards/person/@me 
       private
         {"body" : "<BODY_CONTENT>","visibilityType" : "private"}
       public
         {"body" : "<BODY_CONTENT>","visibilityType" : "public"}
       hidden and public
        {"body" : "<BODY_CONTENT>","visibilityType" : "hidden"}
       private and hidden
         {"body" : "<BODY_CONTENT>","visibilityType" : "private_hidden"}
    
  • person

       rest/api/messageBoards/person/<GUID> 
    

    For a GUID other than that of "me":

       public 
         {"body" : "<BODY_CONTENT>","visibilityType" : "public"}
       private
         {"body" : "<BODY_CONTENT>","visibilityType" : "private"}
    
  • space-guid

       rest/api/messageBoards/space/<GUID>
    

    Note that visibility-based filtering is not available for space-guid.

Example 53-22 Using Filtering for Modified Messages (PUT)

  • me

       all
         rest/api/messageBoards/person/@me/messages/<msg guid>
       private
         {"body" : "<BODY_CONTENT>","visibilityType" : "private"}
       public
         {"body" : "<BODY_CONTENT>","visibilityType" : "public"}
       hidden and public
        {"body" : "<BODY_CONTENT>","visibilityType" : "hidden"}
       private and hidden
         {"body" : "<BODY_CONTENT>","visibilityType" : "private_hidden"}
    
  • person

       rest/api/messageBoards/person/<GUID>/messages/<msg guid>
    

    For a GUID other than that of "me":

       public 
         {"body" : "<BODY_CONTENT>","visibilityType" : "public"}
       private
         {"body" : "<BODY_CONTENT>","visibilityType" : "private"}
    
  • space-guid

       rest/api/messageBoards/space/<GUID>/messages/<msg guid>
    

    Note that visibility-based filtering is not available for space-guid.

53.13.2 Displaying Activity Stream Data

To properly display Activity Stream data, you must:

  • Retrieve the Activity Stream URI entry point

  • Retrieve the Activity Stream data

  • Process the Activity Stream data for display

More on OTN

This sample is available on the Oracle WebCenter Portal Demonstrations and Samples page on the Oracle Technology Network (OTN) at:

http://www.oracle.com/technetwork/middleware/webcenter/ps3-samples-176806.html

In Example 53-23:

  • The getResourceURL method shows you how to retrieve the URI entry point for the Activity Stream service by retrieving the JSON data for the main Resource Index (/rest/api/resourceIndex) and locating the URI for the Activity Stream resource in that data.

  • The formatMessage method processes the Activity Stream data into a displayable format. This involves locating an individual message and replacing any template parameters in the message with the name of the object or user that corresponds to that parameter. The parameters also include links to display the object or user. They may contain links to REST services for those objects or users, if available.

Note:

To get the Resource Index and Activity Stream JSON data, make Ajax requests using Javascript (and possibly a client-side scripting library like Dojo) and pass the resulting data into the appropriate methods.

Example 53-23 Displaying Activity Stream Data

/* Parse the resourceIndex to find the specified URL and
 * return it.
 *
 * @Param jsonData the JSON data retrieved from calling
 *        the /rest/api/resourceIndex URL.
 * @Param strResourceType the resource type of the URL
 *        you want to retrieve from the resourceIndex data.
 *        E.g., 'urn:oracle:webcenter:activities:stream'
 */
function getResourceURL(jsonData, strResourceType)
{
  // Using the HATEOAS model, we browse the returned links
  // looking for the one with the correct resource type.

  for (var i = 0; i < data.links.length; i++) {
    if (data.links[i].resourceType == strResourceType) {
      return data.links[i].href;
    }
  }
}


/* Parse the resourceIndex to find the activity stream URL and
 * then load it.
 *
 * @Param jsonData the JSON data retrieved from calling
 *        the /rest/api/resourceIndex URL.
 */
function getActivitiesURL(jsonData)
{
  // Parse the JSON data to get the activities URI entry point.

  var strHref = getResourceURL(jsonData,
    'urn:oracle:webcenter:activities:stream');

  // INSERT CODE HERE: Implement getting the JSON data from the
  // strHref URL with the Accept header set to "application/json",
  // and use the formatMessage(index, jsonData) function to get
  // the displayable activity message for each activity.

}


/* Replace activity message parameters.
 *
 * @Param index the index of the activity to process
 * @Param jsonData the JSON data retrieved from calling
 *        the /rest/api/resourceIndex URL.
 */
function formatMessage(index, jsonData)
{
  var activity = jsonData.items[index];
  var strMessage = activity.message;

  // Look for activity parameters and replace them in the message.

  if (activity.templateParams && activity.templateParams.items) {
    for (var i = 0; i < activity.templateParams.items.length; i++) {
      var param = activity.templateParams.items[i];

      // Each parameter also has a set of links which at least
      // includes an HTML link and possibly a REST API link.

      strMessage = strMessage.replace(param.key, param.displayName);
    }
  }
  if (activity.detail) {
    strMessage = strMessage + "<br><font size='1'>" +
      activity.detail + "</font>";
  }
  return strMessage;
}

53.13.3 Updating User Status

The following example shows how to use REST APIs to update a user's WebCenter Portal profile status.

Note:

You must host the sample on a web server (for example, Apache or Oracle HTTP Server) or an application server. To avoid cross site scripting errors, you should proxy URL access to the REST service. On Apache or OHS, the conf commands would look like (change myspaceshost and port accordingly):
ProxyPass /webcenter/ http://myspaceshost:port/webcenter/
ProxyPassReverse /webcenter/ http://myspaceshost:port/webcenter/
ProxyPass /rest/ http://myspaceshost:port/rest/
ProxyPassReverse /rest/ http://myspaceshost:port/rest/
ProxyPreserveHost on
More on OTN

This sample is available on the Oracle WebCenter Portal Demonstrations and Samples page on the Oracle Technology Network (OTN) at:

http://www.oracle.com/technetwork/middleware/webcenter/ps3-samples-176806.html

Updating user status involves making a sequence of asynchronous AJAX calls to get the URL for the status object:

urn:oracle:webcenter:resourceindex
   urn:oracle:webcenter:people
      urn:oracle:webcenter:people:person:status

The HTML page for updating user status (Example 53-24) includes an input field where users can enter the new status message (statusMessage). Clicking the Update Status button (or pressing Enter) calls the updateStatus method to make the initial call to the Resource Index.

Example 53-24 HTML Body

<body>
<div>New status message:&nbsp;<input id="statusMessage" type="text"
   onkeyup="{if (event.keyCode==13) updateStatus();}" maxlength="250"
   size="60" /></div>
<div>
<button id="button1" onclick="updateStatus();">Update Status</button>
</div>
<div id="statusResults"></div>
</body>

Figure 53-1 shows the HTML page.

Figure 53-1 New Status Message HTML Page

HTML page for entering new status

The code in Example 53-25 retrieves the Resource Index (resourceIndexURL variable set to /rest/api/resourceIndex). The Resource Index is returned as an AJAX request object (resourceIndexRequest).

Example 53-25 Retrieving the Resource Index

function updateStatus() {
   // Set the UI to busy state. This is cleared in the success and error callbacks
   setUIBusy("Updating status...");
   //get the Resource Index
   resourceIndexRequest.get(
      resourceIndexURL,
      resourceIndexCallback,
      clearUIBusy);
}

The getResourceURL method shown in Example 53-26 traverses the links in the data returned by a REST call to find a specified string (URN) that identifies the required resource type.

Example 53-26 Traversing the Links

function getResourceURL(data, strResourceType) {
   for (var i = 0; i < data.links.length; i++) {
      if (data.links[i].resourceType == strResourceType) {
         return data.links[i].href;
      }
   }
   return null;
}

Example 53-27 uses getResourceURL to parse the Resource Index to find the user profile URL. The data is returned as an AJAX request object (profileRequest).

Example 53-27 Retrieving the User Profile

function resourceIndexCallback(data) {
   //get my user profile
   profileRequest.get(
      getResourceURL(data, 'urn:oracle:webcenter:people'),
      profileCallback,
      clearUIBusy);
}

Example 53-28 takes the new status message provided by the user in the HTML page (statusMessage) and uses request.put to update the status object (retrieved by again calling getResourceURL).

Example 53-28 Retrieving the Status Object

function profileCallback(data) {
   profile = data;
   // get the URL for the status object
   var url = getResourceURL(data, 'urn:oracle:webcenter:people:person:status');
   // get the new status and escape double quotes
   var newStatus = document.getElementById
      ('statusMessage').value.replace(/\"/g. "\\\"");
   //send a JSON string representing the new status object
   var statusMessage = '{"note": "' + newStatus + '"}';
   statusRequest.put(
      getResourceURL(data, 'urn:oracle:webcenter:people:person:status'),
         statusMessage, renderStatusPutResults, clearUIBusy);
}

The renderStatusPutResults method, shown in Example 53-29, renders the new status object.

Example 53-29 Rendering the New Status Object

function renderStatusPutResults(data) {
   var name = profile.displayName;
   // get the URL for my profile HTML page in WebCenter Portal
   var profileURL = getResourceURL(profile,
      'urn:oracle:webcenter:spaces:profile');
   var html = 'Status for <a href="' + profileURL + '" target="_blank">'
      + name + '</a> is: ' + data.note;
   // clear the UI busy state and print the new status message
   clearUIBusy(html);
}

Example 53-30 shows the code for disabling and reenabling the UI.

Example 53-30 Disabling the UI

function setUIBusy(message) {
   document.getElementById('statusResults').innerHTML = message;
   document.getElementById('button1').disabled = true;
   document.getElementById('statusMessage').disabled = true;
}

function clearUIBusy(message) {
   document.getElementById('statusResults').innerHTML = message;
   document.getElementById('button1').disabled = false;
   document.getElementById('statusMessage').disabled = false;
}

Example 53-31 shows the library that assists in AJAX calls. Most of this is not WebCenter specific and works for any XHR requests to a service that returns JSON.

The library includes a reusable XHR object. This object supports HTTP GET, POST, PUT, and DELETE. All functions are asynchronous and take a URL and two callback functions, one for success, and one for failure. Success calls are made with a JavaScript object containing the return data. Failure calls are made with an error string. POST and PUT also take a data argument which must be a JSON string.

Example 53-31 AJAX Library

function AjaxRequest() {
   // constructor to create an object oriented AJAX request
   var xhr = null;

   // get XHR object. Should work for IE 6+, Safari, and Mozilla based browsers
   if (window.XMLHttpRequest) {
      xhr = new window.XMLHTTPRequest;
   } else {
      try {
         xhr = new ActiveXObject('MSXML2.XMLHTTP.3.0');
      } catch (ex) {
         xhr = null;
      }
   }
   if (xhr == null) {
      alert("Your browser does not support AJAX");
   }

   this.get = function(url, callback, errorCallback) {
      xhr.open('GET', url, true);
      // the REST APIs return XML by default. Please return JSON
      xhr.setRequestHeader('Accept', 'application/json; charset=utf-8');
      sendRequest(null, callback, errorCallback);
   };

   this.post = function(url, data, callback, errorCallback) {
      xhr.open('POST', url, true);
      // set headers to send and receive JSON
      xhr.setRequestHeader('Accept', 'application/json; charset=utf-8');
      xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
      sendRequest(data, callback, errorCallback);
   };

   this.put = function(url, data, callback, errorCallback) {
      xhr.open('PUT', url, true);
      // set headesr to send and receive JSON
      xhr.setRequestHeader('Accept', 'application/json; charset=utf-8');
      xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
      sendRequest(data, callback, errorCallback);
   };

   this.deleteResource = function(url, callback, errorCallback) {
      xhr.open('DELETE', url, true);
      sendRequest(null, callback, errorCallback);
   };

   // set the callbacks and send the request with data, if any
   function sendRequest(data, callback, errorCallback) {
      xhr.onreadystatechange = function () {
         processResponse(xhr, callback, errorCallback);
      };
      xhr.send(data);
   }

   function processResponse(xhr, callback, errorCallback) {
      var data = null;
      // can get called here many times. 4 means really done
      if (xhr.readyState == 4) {
         // let's call any HTTP codes in the 200s success
         if (xhr.status >= 200 && xhr.status <300) {
            // convert response text into a JSON object. This is insecure.
            // data should not be blindly evaluated from the server return.
            // consider using json2.js http://www.JSON.org/js.html
            data = eval('(' + xhr.responseText + ')');
            callback(data);
         } else {
            // we got an error. Format an error string
            data = 'Error: ' + xhr.status + ' ' + xhr.statusText + '<br />'
               + xhr.responseText;
            errorCallback(data);
         }
      }
   }
}