Child pages
  • Concept REST Services (Outdated)
Skip to end of metadata
Go to start of metadata

Part of 5.0 and used by the GenUIne adminCentral

REST design considerations

About HTTP Methods:

  • GET and POST are supported by all browsers, the rest are quirky to say the least
  • PUT would be nice for create
  • DELETE would be nice for delete
  • IPSecurity filter blocks all but GET and POST
  • Some frameworks simluate methods using a query param named _method

URI design scheme

  • Reading resources are done using GET and a path (GET <resource path>)
  • Performing an action on a resource is done using POST and a trailing action name (POST <resource path>/<action name>)

REST Module infrastructure

RestEndpointManager is an ObservedManager that observes changes in /modules/<modules/rest-endpoints and discovers them runtime. They're exposed to the outside world at .magnolia/rest/*

The requests are processed by RestEndpointServlet

Exceptions are logged by RestExceptionMapper, HTTP 500 is returned (the exception stack trace is not returned).

The endpoints are not accessible unless the session is logged in. A 401 is sent by SecurityFilter (with the login page).

AdminCentral Endpoint (.magnolia/rest/admincentral)

status: started, menu returned is /modules/adminInterface/config/menu

overall stuff like menu config, login and module manager ui

  • get menu
    • method: GET
    • path: .magnolia/rest/admincentral/menu
    • arguments: none
    • returns: MenuConfiguration

Tree Endpoint (.magnolia/rest/tree/<treeName>)

status: proof of concept

Generic endpoint for tree views. A client fetches the tree configuration to build the view, subsequent calls to fetch nodes return data for each column. Each tree is served by a TreeHandler. The TreeHandler can provide functionality that is specific for its tree.

NodeData is not treated as a node in the tree. Instead a returned node in the tree contains NodeDatas that should be rendered as subnodes in the displayed tree. The returned node has column values for each NodeData.

The ConfiguredTreeHandler has a set of named commands. Items on context menu and function menu references one of these commands.

to be decided: how should a context menu item describe that it wants to use a dialog?

to be decided: some context menu items will perform actions solely on the client side, such as refreshing the view, how should this be represented in the config?

to be decided: searching the repository is a very special kind of function bar item, how can it be represented?

Endpoint interface

  • get child nodes
    • method: GET
    • path: .magnolia/rest/tree/<treeName>/<path>
    • arguments: treeName and path in uri
    • returns: TreeNodeWithChildren
  • get tree configuration
    • method: POST
    • path: .magnolia/rest/tree/<treeName>/config
    • arguments: treeName in uri
    • returns: JsonTreeConfiguration
  • execute command
    • method: POST
    • path: .magnolia/rest/tree/<treeName>/<path>/<command>
    • arguments: treeName, path and the name of the command in uri, rest of parameters are used by the actual command
    • returns: TreeCommandExecutionResult

Commands

Commands are configured in the repository, arguments to a command are set using node data and mapped in using C2B. Parameters in the request are mapped onto the command using reflection before execution. A command is a use-once object (fresh instance created for every request). Commands include:

  • create content
    • arguments: optional name (defaults to 'untitled'), itemType
    • returns: TreeNodeWithChildren of the newly created nodes parent
    • note:
      • if the new name is already taken a unique name will be generated
      • for the website tree the command must also set the default template (CreateWebsiteNodeCommand performs this)
      • for the users tree the command must also add the newly added user to UserManager
  • delete content
    • arguments: none other than the path
    • returns: a TreeNodeWithChildren of the deleted nodes parent
    • note: must also deactivate the deleted node
  • rename content
    • arguments: the new name
    • returns: TreeNodeWithChildren of parent of the node that changed name
    • note:
      • if the new name is already taken a unique name will be generated
      • for the users tree the command must update ACLs after rename
  • move content
    • arguments: new path, name of node to place before/after
    • returns: TreeNodeWithChildren of the parent that the node was moved to and the previous parent
    • note:
      • if the new name is already taken a unique name will be generated
  • copy content
    • arguments: new path, name of node to place before/after
    • returns: TreeNodeWithChildren of the parent that the node was copied to
    • note:
      • the new content must be deactivated
      • if the new name is already taken a unique name will be generated
  • activate
  • activate incl subnodes
  • add nodedata
    • arguments: name, value and type (type and value optional defaults to empty string)
    • returns: a TreeNodeWithChildren of the node where nodedata was added
    • note: if the name is already taken a unique name will be generated
  • set nodedata
    • arguments: name and value
    • returns: a TreeNodeWithChildren of the node where nodedata was changed
  • remove nodedata
    • arguments: name of nodedata to remove
    • returns: a TreeNodeWithChildren of the node where nodedata was removed
  • rename nodedata
    • arguments: name of nodedata to rename, new name
    • returns: a TreeNodeWithChildren of the node where nodedata was renamed
    • note: what if the new name already exists? create unique or fail?
  • list versions
  • revert to version
  • import and export
    • note: does this even make sense to do with REST? (there's certainly nothing to return as JSON)
  • search
    • arguments: search query
    • returns: search result
  • set metadata property
    • arguments: name, value and type

Command return values

Update: Commands return TreeCommandExecutionResult that contains all the changed nodes

To be decided: After invoking the command its up to the handler to return a good response. Depending on the command we need to return very different things:

  • Create, we need to return the new nodes parent so that the client sees how the new node is ordered among its siblings
  • Move, we need to return the parent that the node moves to, see above, and we need to let the client know that it is no longer where it used to be.
  • and so on...

Website Endpoint (.magnolia/rest/website)

replaced by the tree endpoint

  • get child pages
    • method: GET
    • path: .magnolia/rest/website/<path>
    • arguments: path in uri
    • returns: WebsitePageList
  • create page
    • method: PUT
    • path: .magnolia/rest/website/<path>
    • arguments: path in uri
    • returns WebsitePage
  • delete page
    • method: DELETE
    • path: .magnolia/rest/website/<path>
    • arguments: path in uri
  • update page (name, title, template)
    • method: POST
    • path: .magnolia/rest/website/<path>/update
    • arguments: WebsitePage (only name, title and template sticks)
  • search pages
  • activate page
    • method: POST
    • path: .magnolia/rest/website/<path>/activate
  • deactivate page
    • method: POST
    • path: .magnolia/rest/website/<path>/deactivate
  • move page
    • method: POST
    • path: .magnolia/rest/website/<path>/move
    • arguments: to=<website path>
  • copy page
    • method: POST
    • path: .magnolia/rest/website/<path>/copy
    • arguments: to=<website path>
  • edit page using dialog (page properties)
    • method: POST
    • path: .magnolia/rest/website/<path>/edit
    • arguments: dialog=<dialogName>
    • returns: a dialog structure with values from the repository
  • save page using dialog (page properties)
    • method: POST
    • path: .magnolia/rest/website/<path>/save
    • arguments: dialog=<dialogName> and a whole bunch of parameters needed to represent the values
    • returns: OK or a validation error structure
  • list versions
    • method: POST
    • path: .magnolia/rest/website/<path>/versions
    • returns: ?
  • revert to version
    • method: POST
    • path: .magnolia/rest/website/<path>/revert/<version>
  • import + export
    • transport is already defined as an XML document

Templating Endpoint (.magnolia/rest/templating ?)

status: not implemented

  • get paragraph definitions (for select paragraph dialog)
    • method GET
    • path .magnolia/rest/templating/paragraphs
    • arguments
      • paragraphs - comma seperated list of paragraphs
    • returns ParagraphDefinitionList
  • add paragraph using dialog
    • method POST
    • path .magnolia/rest/templating
    • today sends in repository, path, nodeCollection and node=mgnlNew
  • edit paragraph using dialog
    • today sends in paragraphName, is this necessary, can we send in a dialogName instead?
  • move paragraph (within node collection)
  • delete paragraph

Dialogs Endpoint (.magnolia/rest/dialogs/)

status: proof of concept - has tabs, validation, supports only edit and date controls

next steps: implement on client side, evaluate, refactor adminInterface instead of reinventing

to be decided: how can we remain backwards compatible with fckeditor content

to be decided: multipart file upload using REST or not

  • load dialog
    • method GET
    • path .magnolia/rest/dialogs/<dialogName>
    • arguments
      • mgnlRepository
      • mgnlPath
      • mgnlNodeCollectionName
      • mgnlNode
    • returns
      • Dialog populated from repository
    • example /.magnolia/rest/dialogs/howTo?mgnlRepository=website&mgnlPath=/howTo-jsp/main/0
  • create node with dialog
    • method POST
    • path .magnolia/rest/dialogs/<dialogName>/create
    • arguments
      • mgnlRepository
      • mgnlPath
      • mgnlNodeCollectionName
      • mgnlNode
    • returns
      • ValidationResult
    • example /.magnolia/rest/dialogs/howTo/create?mgnlRepository=website&mgnlPath=/howTo-jsp&mgnlNodeCollectionName=main&title=ASDFGH12345
  • update node with dialog
    • method POST
    • path .magnolia/rest/dialogs/<dialogName>/update
    • arguments
      • mgnlRepository
      • mgnlPath
      • mgnlNodeCollectionName
      • mgnlNode
    • returns
      • ValidationResult
    • example /.magnolia/rest/dialogs/howTo/update?mgnlRepository=website&mgnlPath=/howTo-jsp/main/0&title=ASDFGH12345

Repository Endpoint (.magnolia/rest/repository/<repositoryName>/)

CRUD for supported item types

How do we return both the new state of modified nodes and messages like activation failures?

Need to do multipart upload of files and multivalue jcr properties

Should be able to share commands with tree endpoint

Module Store (.magnolia/rest/modulestore ?)

list installed modules

list available modules

get module info

Workflow

Data Module

DMS

+ Tools

See Also

http://dev.day.com/content/ddc/blog/2008/07/cheatsheet/_jcr_content/par/download/file.res/cheatsheet.pdf

3 Comments

  1. two points:

    Note: why are we not using the same URI as for serving content? sling for instance uses the 'accepts' header to see what format should be served (json, html, ..). It might be much simpler to get/post to the content.

    1. Seems we re really would be missing the extensions in the above described approach. global script resolution for extensions as in sling woud be nice and yes, I agree with Philipp, it would be good if that could all be done at the regular location of the content as they are just different styles to render. Also, sling includes a selector to indicate the depth of the request (how many levels down in the hierarchy do we want to see the response, up to infinity - so one can say page.2.json or page.infinity.xml). This feature however can cause some serious security/dos attack vectors.

    2. why are we not using the same URI as for serving content?

      because the public-facing uri does not (necessarily) correspond to the actual jcr path (think uri mappings, virtual uris and other trickeries). In terms of our rest api, I'd rather have a straightforward prefix+workspace+realpath approach (/.rest /website /path/to/my/node), i.e use the rest api like you'd use a "regular" server-side code api.