EMS Resource Overview

From RAD Studio
Jump to: navigation, search

Go Up to Extending the EMS Server‎


An EMS resource is an extension of the EMS Server API.

When you load an EMS resource into the EMS Server, the EMS Server registers it and exposes all its endpoints. EMS client applications can use a TBackendEndpoint component to access the endpoints of your EMS resource.

Note: Before you can define one or more EMS resources, create an EMS package where you can define them.

Defining a Resource Class

A resource class is a class that represents an EMS resource.

Declaring a Resource Class

You can declare resource classes as regular classes. For example:

Delphi:

TMyResource = class;

C++:

// .h
class TMyResource {};

Resource classes must have at least one constructor that matches either of the following:

  • The constructor does not accept any parameter.
  • The constructor accepts a single parameter of type TComponent.

Resource Names

Each EMS resource has a resource name that uniquely identifies that resource. When you access your resource from an EMS client application, you must fill the Resource property of your TBackendEndpoint component with the name of the target resource.

By default, the name of the EMS resource that your class represents is the name of your class without the "T" prefix (if it uses one). For example, the name of the resource of the class above is "MyResource". If you want to use a different name for your EMS resource, you can customize it later.

Defining Endpoint Methods

After you define a resource class, you should add one or more endpoint methods to that class.

An endpoint method is a method that handles API requests that target the resource where that method is defined.

API requests must specify a request method (for example, "GET") and an optional resource suffix. Each endpoint method of a resource class must handle one combination of request method and resource suffix.

When the EMS Server receives a request that an endpoint method can handle:

  1. The EMS Server executes that endpoint method.
  2. The endpoint method generates a response.
  3. The EMS Server sends the generated response back to the client application that sent the original request.

Declaring an Endpoint Method

To declare an endpoint method, you must declare a method within your resource class that meets the following requirements:

  • It is declared with public or published visibility.
  • Its name starts with a string matching a request method name: Get, Put, Post, Delete, or Patch.
    Get, PutItem and PostWhateverYouWant are all valid names for endpoint methods. You can use any case for this prefix; for example, Get, get and GET are all valid prefixes for the name of an endpoint method.
  • Its signature has no return value and accepts only the following three parameters in the following order: TEndpointContext, TEndpointRequest, and TEndpointResponse.
  • Delphi:
procedure MethodName(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
  • C++:
void MethodName(TEndpointContext* AContext, TEndpointRequest* ARequest, TEndpointResponse* AResponse);

If a method of a resource class does not meet all of the requirements above, the EMS Server does not map any API endpoint to that method.

Implementing an Endpoint Method

Your implementation of an endpoint method must fill the instance of TEndpointResponse that it receives with data, usually JSON data. You can use the SetValue method of the Body property of TEndpointResponse to fill the response with JSON data, or you can use SetBytes or SetStream to write raw data into the response body.

See Tutorial: Implementing Your First EMS Resource for some simple examples.

Request Methods

The name of an endpoint method starts with the name of the request method that the endpoint method handles. Hence, a single endpoint method cannot handle two or more different request methods.

The EMS Server API supports the following types of request methods:

Name Description

GET

To retrieve data.

PUT

To create a new item and obtain its ID.

POST

To replace an existing item with new data.

PATCH

To update part of the data of an existing item.

DELETE

To delete an item.

Resource Suffixes

A resource suffix is the string at the end of and endpoint URL, right after the resource name (in lowercase). For example, if the URL to access an endpoint is http://example.com/ems/myresource/item/count and the name of the resource is "MyResource", the resource suffix of that endpoint is "item/count" (or "/item/count").

Each endpoint method is mapped to a specific resource suffix. When you access your resource from an EMS client application, you must fill the ResourceSuffix property of your TBackendEndpoint component with the resource suffix string.

By default, the resource suffix of an endpoint method is an empty string. To assign a different resource suffix to an endpoint method, you must customize the mapping of the endpoint method later.

A resource suffix is always a path relative to the URL of the resource itself. If you assign a resource suffix starting with a slash (/) to an endpoint method, the EMS Server ignores the starting slash. For example, both "/item/count" and "item/count" are valid resource suffixes that point to the same endpoint URL, such as http://example.com/ems/myresource/item/count.

Special Segments for Resource Suffixes

A segment is a string that contains characters other than slashes. A resource suffix may be composed of several segments separated by slashes. For example, "item/count" contains two segments, "item" and "count".

Resource suffixes support the following special segments:

Segment Description

*

Matches any segment.

For example, the resource suffix "*/count" matches "foo/count" and "bar/count".

{<identifier>}

Where <identifier> may be any identifier, such as "item" or "key".

Matches any segment and stores the matched segment in the TEndpointRequest.Params property with your identifier as key and the actual string from the request URL as value.

For example, the resource suffix "{item}/bar" matches "foo/bar" and fills the TEndpointRequest.Params property with the following pair: item=foo.

Note: You can only use these special segments as complete segments. In resource suffixes such as "foo*/bar" or "{foo}bar/count", the EMS Server interprets "foo*" and "{foo}bar" as regular strings, not as special segments.

Endpoint Names

The name of an endpoint is the display string that represents that endpoint in the EMS Console UI.

By default, the name of the endpoint that an endpoint method represents is the name of that method. If you want to use a different name for your endpoint, you can customize it later.

Endpoint names must be unique within a resource. If you use the same endpoint name for two different endpoint methods, the EMS Server appends a number at the end of repeated endpoint names to make them unique. For example, if you have two endpoint methods and you change their mapping so that both use "MyEndpoint" as endpoint name, the first endpoint method keeps that endpoint name, but the name of the second endpoint method becomes "MyEndpoint2".

Customizing the Mapping of Your Resources

Before you register your resource classes in the EMS Server, you can change how you map each resource class and endpoint method to the EMS Server API.

You can change resource names, resource suffixes and endpoint names. However, you cannot change request methods, they are always defined by the prefix of the name of an endpoint method.

To customize the mapping of a resource, you can define a resource attributes object for that resource and use that object when you register your resource. In Delphi, you can alternatively customize the mapping of your resource using attributes.

Defining a Resource Attributes Object

A resource attributes object is an instance of TEMSResourceAttributes.

To customize the mapping of a resource using a resource attributes object:

  1. Create an instance of TEMSResourceAttributes.
  2. Fill the properties of your resource attributes object with the mappings that you want your resource to use.
  3. Pass your object as the second parameter of RegisterResource when you register your resource.

You can use the following properties of TEMSResourceAttributes to customize the mapping of your resource:

Property Description

ResourceName

Determines the name of your resource.

ResourceSuffix

Given the name of an endpoint method, determines the resource suffix of that endpoint method.

EndPointName

Given the name of an endpoint method, determines the name of the endpoint that the specified endpoint method represents.

Note: You only need to define the mapping data that you want to change. For example, if you do not change the value of the ResourceName, the EMS server uses the default name of your resource (which is based on the name of your resource class).

For example:

  • Delphi:
// var MyResourceAttributes: TEMSResourceAttributes;
MyResourceAttributes.Create();
MyResourceAttributes.ResourceName := 'Resource';
MyResourceAttributes.ResourceSuffix['Get'] := '{item}';
MyResourceAttributes.EndPointName['Get'] := 'GetItem';
  • C++:
std::auto_ptr<TEMSResourceAttributes> MyResourceAttributes(new TEMSResourceAttributes());
MyResourceAttributes->ResourceName = "Resource";
MyResourceAttributes->ResourceSuffix["Get"] = "{item}";
MyResourceAttributes->EndPointName["Get"] = "GetItem";

Customizing the Mapping of Resources Using Attributes (Delphi)

To customize the mapping data of your resource classes and endpoint methods in Delphi, you can annotate them using the following attributes:

Member Type Attribute Description

Resource class

ResourceName

Determines the name of your resource.

Endpoint method

ResourceSuffix

Determines the resource suffix of the endpoint method.

EndpointName

Determines the name of the endpoint that the endpoint method represents.

For example:

[ResourceName('Resource')]
TMyResource = class
published
    [ResourceSuffix('{item}')]
    [EndpointName('GetItem')]
    procedure Get(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
end;

Registering a Resource

Once your resource class and its endpoint methods are defined, you need to:

  1. Pass your resource class to TypeInfo to obtain the RTTI information of your resource class.
  2. Pass the RTTI information of your resource class to the EMS Server using RegisterResource.

You should call RegisterResource on the Register method of your package.

For example:

  • Delphi:
RegisterResource(TypeInfo(TMyResource));
  • C++:
RegisterResource(__typeinfo(TMyResource));

Registering a Resource with a Resource Attributes Object

If you created a resource attributes object to customize the mapping data of your resource class and its endpoint methods, pass your resource attributes object to RegisterResource as its second parameter.

For example:

  • Delphi:
RegisterResource(TypeInfo(TMyResource), MyResourceAttributes);
  • C++:
RegisterResource(__typeinfo(TMyResource), MyResourceAttributes.release());

See Also