RAD Server Custom API Documentation

1

I have just started experimenting with RAD Server.  One of the features that make the investment attractive is the self documenting API’s feature, which would save a lot of work in supporting external partners connecting to our REST interfaces, and obviate the need to maintain a separate interface specification document, that would invariably falls behind the development.

I have followed the the tutorial in the wiki for creating one's first EMS resource all the way to deployment to a test EMS server. This works fine, without a hitch.

However, when I reach the custom API documentation tutorial, its just simply does not work.

When I call http://localhost:8080/api/apidoc.yaml the server returns:

{
  "error":"Error",
  "description":"Error: No Responses defined for: get "
}

 

The EMS development server has the following corresponding log entries:

{"Request":{"Resource":"API","Endpoint":"GetAPIYAMLFormat","Method":"GET","User":"(blank)","Time":"2017/08/11 12:59:46 AM","Thread":1732}}
{"Error":{"Type":"HTTP","Code":"500","Reason":"Error","Error":"","Description":"Error: No Responses defined for: get ","Thread":1732}}

 

Here is a snippet of my code from the tutorial:

unit Unit1;

// EMS Resource Unit

interface

uses
  System.SysUtils, System.Classes, System.JSON,
  EMS.Services, EMS.ResourceAPI,
  EMS.ResourceTypes, APIDocumentationEndPointObjectsDefinitions;

type
  [ResourceName('Test')]
  [EndPointObjectsYAMLDefinitions(YAMLDefinitions)]
  [EndPointObjectsJSONDefinitions(JSONDefinitions)]

  {$METHODINFO ON}
  TTestResource = class
  published
    // Declare the function
    function MakeJSON(I: Integer): TJSONObject; //It takes an integer as a parameter and returns a JSON Object.
    [EndPointRequestSummary('Items', 'Get items', 'Used to retrieve all the items', 'application/json', '')]
    [EndPointRequestParameter(TAPIDocParameter.TParameterIn.Path, 'Test', 'Path Parameter item Description', false, TAPIDoc.TPrimitiveType.spString, TAPIDoc.TPrimitiveFormat.None, TAPIDoc.TPrimitiveType.spString, '', '')]
    [EndPointResponseDetails(200, 'Ok', TAPIDoc.TPrimitiveType.spObject, TAPIDoc.TPrimitiveFormat.None, '', '#/definitions/items')]
    procedure Get(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    [ResourceSuffix('{item}')]
    procedure GetItem(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
  end;
  {$METHODINFO OFF}

implementation
const
  TestValues: array [0 .. 2] of string = ('a', 'b', 'c'); // It creates an array of string values.

procedure TTestResource.Get(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
var
  LJSON: TJSONArray;
  I: Integer;
begin
  LJSON := TJSONArray.Create;
  for I := Low(TestValues) to High(TestValues) do
    LJSON.Add(MakeJSON(I)); //[{"index":0,"value":"a"},{"index":1,"value":"b"},{"index":2,"value":"c"}]
  AResponse.Body.SetValue(LJSON, True) // True causes AResponse to free JSON
end;

procedure TTestResource.GetItem(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
var
  I: Integer;
begin
  if not TryStrToInt(ARequest.Params.Values['item'], I) then //{"index":I,"value":value}
    AResponse.RaiseBadRequest('Index expected');
  if (I < 0) or (I >= Length(TestValues)) then
    AResponse.RaiseBadRequest('Index out of range');
  AResponse.Body.SetValue(MakeJSON(I), True);
  // True causes AResponse to free JSON
end;

function TTestResource.MakeJSON(I: Integer): TJSONObject;
begin
  Result := TJSONObject.Create;
  Result.AddPair('index', TJSONNumber.Create(I)); //Adds to the JSON object a pair {"index": I}, the index number.
  Result.AddPair('value', TJSONString.Create(TestValues[I])); //Adds to the the JSON object a pair {"value":String}, the string corresponding to the index number.

end;

procedure Register;
begin
  RegisterResource(TypeInfo(TTestResource));
end;

initialization
  Register;
end.

 

Has anybody else experienced this? I looks like the get method has not been fully implemented. Is there a fix for this (I have just updated to RAD Studio 10.2.1)?

 

Thanks in advance,

Simelane

Responses (2)
  • Accepted Answer

    Thursday, September 14 2017, 08:51 AM - #Permalink
    0

    Hi Al,

    Thanks for the response. I actually had followed Stephen's guide, to the letter. Unfortunately he uses the RAD Studio EMS Sample project, which works perfectly even for me.  But the minute you try to apply it to your own EMS package, it does not work.

    There is clearly something in the sample project that is missing in the code generated by the RAD Studio EMS package wizard.

    I am wondering if anyone has been able to use the new EMS documentation attributes to create YAML documentation from their own EMS package - not the sample project supplied with RAD Studio?

    The reply is currently minimized Show
  • Accepted Answer

    Monday, August 14 2017, 03:47 PM - #Permalink
    0

    Have you seen this post on SWAGGER / YAML AND SELF DOCUMENTING RESTFUL API’S that will allows you to take the new documentation attributes used in EMS packages that create YAML documentation that can be used with Swagger.

     

    The reply is currently minimized Show
Your Reply

Please login to post a reply