Exposed methods

From Cloudrexx Development Wiki
Jump to: navigation, search

Controller methods can be exposed to other components through HTTP, CLI and as a DataSource. This article describes how to do that.

Note: This documentation refers to version 5 or newer. For older versions of Cloudrexx, please refer to JsonData V3/4.

Use cases

Important: Exposed methods should only be used by the controller layer. If you need to expose models, then do use the RESTful API.

Making methods of controllers available (optionally to other components) by exposing them, can be used to provide:

Expose a controller's method

Note: the following used naming (of the registering method getControllersAccessableByJson() and the implementing interface \Cx\Core\Json\JsonAdapter) might suggest that this does provide some sort of a JSON interface. Even though this is true to a certain degree, as the exposed methods are in fact accessible internally to other components through a JSON-like interface, it is in no way limited to that. Yet, the naming of the method and the interface have not (yet) been changed to describe the functionality of exposed methods in a more generic way.

To expose one controller's method, two things are needed. First, the controller must be registered as a controller that does expose methods. This is done by adding the controller's name to the return list of method getControllersAccessibleByJson() of the Component's ComponentController. I.e. to register a controller named ViewGeneratorJsonController as a controller that exposes methods, you would extend the method ComponentController::getControllersAccessibleByJson() as follows:

/**
 * @{inheritdoc}
 */
public function getControllersAccessableByJson() {
    return array(
        'ViewGeneratorJsonController'
    );
}

Second, the controller (this would be ViewGeneratorJsonController from the example above) needs to implement the interface \Cx\Core\Json\JsonAdapter which requires you to implement the following methods:

  • getName()
  • getAccessableMethods()
  • getDefaultPermissions()
  • getMessagesAsString()Deprecated

getName()

This method must return a unique name for this controller. Therefore you should prefix it with your Component's name.

The Controller class of which your controller inherits from does already implicitly declares a getName() method through __call(). Since this is not a real method definition you need to implement the method anyway, otherwise the Interface definition will not be satisfied.

getAccessibleMethods()

This method must return a list of method names to expose. Each entry can be in one of two forms:

  • Non-associative: Simply a name of a method
  • Associative: Name of the method as key, a Permission object as value

Methods are only available to users that fulfill the requirements specified by the passed Permission object. If no Permission object is specified the default permission is used.

getDefaultPermissions()

This method should return a Permission object which is used if no method-specific permission-requirements are set (through getAccessibleMethods()). If this method returns null, then the default values of the Permission class constructor are used.

getMessagesAsString()

Deprecated This should return a list of success or informational messages meant for the caller. They are split by "<br />".

Returning messages this way is deprecated and will be replaced in a later version.

Return error-state and -message

In order to return an error state and an according message the called method has to throw an exception with the message as its message.

Call an exposed method

For a better understanding, the following placeholders will be used by the examples below:

  • <adapterName> is the name your controller's getName() method returns
  • <methodName> is the name of the (exposed) method to invoke
  • <params> see passing params

As a HTTP endpoint

Exposed methods can be reached using the following URL scheme:

/api/Data/Json/<adapterName>/<methodName>[<params>]

This returns a JSON object with the following fields:

  • status: "success" or "error"
  • message: Message as string, separated by HTML BR tags.
  • data: Data returned by the method. Only set if status is "success"

Using the Contrexx Javascript Framework

cx.ajax(
    "<adapterName>",
    "<methodName>",
    {
        // normal jQuery.ajax() options
        data: {
            <params>// additional parameters to pass to the ''JsonData's'' method
        },
        success: function(json) {
            // handle response
            json.status; // "success" or "error"
            json.message; // Message as string, separated by HTML BR tags.
            json.data; // Data returned by the method. Only set if "status" is "success"
        }
    }
);

Internally from other components

Exposed methods can be accessed from other components using \Cx\Core\Json\JsonData():

$jsonData =  new \Cx\Core\Json\JsonData();
$response = $jsonData->data(
    '<adapterName>',
    '<methodName>',
    <params>
);
$response['status']; // "success" or "error"
$response['message']; // Message as string, separated by HTML BR tags.
$response['data']; // Data returned by the method. Only set if "status" is "success"

As a CLI command

Exposed methods can be accessed using the following command:

./cx Data Json <adapterName> <methodName>[ <params>]

This returns the data exactly like the HTTP endpoint variant.

As a DataSource

Not yet implemented. See \Cx\Core\DataSource\Model\Entity\JsonDataSource class.

Params

Receiving params in your method

If an exposed method is called a single argument is passed to it:

array(
    'get' => array(), // params passed to this method
    'post' => array(), // data passed to this method
)

Your method needs to be able to receive an array as its first (and only) argument.

Passing params

There are 3 types of params that can be passed:

  • Flags
  • Key/value pairs
  • Key/value pairs of data

These can be combined in a single call as necessary.

The following table shows how to pass the following params:

  • Flags: flag1 and flag2
  • Key/value pairs: "alice"=>"bob" and "foo"=>"bar"
  • Key/value pairs of data: "alice"=>"bob" and "foo"=>"bar"
Param type Access method Example
Flags HTTP endpoint
/api/Data/Json/<adapterName>/<methodName>/flag1/flag2
Internal call
$response = $jsonData->data(
    '<adapterName>',
    '<methodName>',
    array(
        'get' => array(
            'flag1',
            'flag2',
        ),
    )
);
CLI
./cx Data Json <adapterName> <methodName> flag1 flag2
DataSource endpoint Not yet implemented. See \Cx\Core\DataSource\Model\Entity\JsonDataSource class.
Key/value pairs HTTP endpoint
/api/Data/Json/<adapterName>/<methodName>?alice=bob&foo=bar
Internal call
$response = $jsonData->data(
    '<adapterName>',
    '<methodName>',
    array(
        'get' => array(
            'alice' => 'bob',
            'foo'=>'bar',
        ),
    )
);
CLI
./cx Data Json <adapterName> <methodName> alice=bob foo=bar
DataSource endpoint Not yet implemented. See \Cx\Core\DataSource\Model\Entity\JsonDataSource class.
Key/value pairs of data HTTP endpoint
POST /api/Data/Json/<adapterName>/<methodName>
 
 alice=bob&foo=bar
Internal call
$response = $jsonData->data(
    '<adapterName>',
    '<methodName>',
    array(
        'post' => array(
            'alice' => 'bob',
            'foo' => 'bar',
        ),
    )
);
CLI
echo 'alice=bob&foo=bar' | ./cx Data Json <adapterName> <methodName>
DataSource endpoint Not yet implemented. See \Cx\Core\DataSource\Model\Entity\JsonDataSource class.