Monday, March 30, 2015

C++ Builder & Dreamfactory - Get Started

Hello Again

I am rather pleased today.  I managed to replicate quickly, the process I had struggled to get right to access Dreamfactory from C++ Builder XE7.  This should apply with syntax corrections to Delhi as well.

I have always been very comfortable with (nee) Borland's development tools.  My affair with them goes back to Turbo C++ 2.0 (if I remember the version correctly).  My first "programme" was a programmer's editor using direct screen access in DOS - which was a big thing in our small community 25 years ago.

There are a number of example that show how to access common, open REST services from Delphi and a few that show how to do that from C++ Builder.

But I could not find any example that showed how Dreamfactory could be accessed from C++ Builder.  Here is a working example.  The objective of this example is to load a table of "City Master" into a ComboBox control.


Create a new form and add the following controls to it

Set 1

ComboBox
RESTClient
RESTRequest
RESTResponse


Set 2

RESTRequest
RESTResponse
RESTResponseDataSetAdapter
FDMemTable

Yes, you need to add TWO RESTRequest and TWO RESTResponse components to the same form.

Ignore the BindingsList1 and BindSourceDB1 for now.

At the end, you should have the following control in your form


  1. RESTClient1
  2. RESTRequest1
  3. RESTResponse1
  4. RESTRequest2
  5. RESTResponse2
  6. RESTResponseDataSetAdapter1
  7. FDMemTable1
  8. cbRequestLocation (this is the ComboBox control)


In the FormCreate event, paste the following code.  This part authenticates your application's session to Dreamfactory and returns a session_id value that we need to store to pass with subsequent calls.

RESTClient1->BaseURL = "http://del-your-dreamfactory-server-name/rest";
RESTRequest1->Method = rmPOST;
RESTRequest1->Resource = "user/session";
RESTRequest1->Params->AddItem("X-DreamFactory-Application-Name", "yourApplicationName", pkHTTPHEADER);
TJSONObject *o = new TJSONObject();
__try {
TJSONObject *o = new TJSONObject();
o->AddPair( new TJSONPair("email","yourUserName"));
o->AddPair( new TJSONPair("password","yourPassword")) ;
RESTRequest1->AddBody(o);
                RESTRequest1->Execute();
}
__finally {
o->Free();
}

When the RESTRequest->Execute() method finishes, it triggers an event. In this event, we extract the value of "session_id" from the JSON and use that to add another HTTP header field for session ID.  Every request to Dreamfactory requires these two HTTP headers to be set.  The first one is simple enough - we have seen that in the previous code example.  Here we add two HTTP headers to our next request - which gets the actual data from Dreamfactory.


  1. X-DreamFactory-Application-Name
  2. X-DreamFactory-Session-Token


void __fastcall TfrmMainMenu::RESTRequest1AfterExecute(TCustomRESTRequest *Sender)

{
String sSessionID;
        // RESTResponse1->JSONText contains the JSON string returned by the authentication above
        // RESTResponse1->JSONText has to be converted to a JSON Object before we can extract values from it
TJSONObject *JSON = (TJSONObject*)TJSONObject::ParseJSONValue(RESTResponse1->JSONText);
       // Get a JSON key/value pair from the JSON object
TJSONPair *pair = JSON->Get("session_id");
       // Get the JSON value part of the key session_id and store it in our variable
sSessionID = pair->Value();
       // The REST service to next consume.  Below, "mssql_utilities" is the Dreamfactory service
       // And car_location" is the table from which we are extracting information
       // We want all rows, so we are not using any condition or filter
RESTRequest2->Resource = "mssql_utilities/car_location";
        // Add the two HTTP headers that are mandatory for getting data from Dreamfactory
RESTRequest2->Params->AddItem("X-DreamFactory-Application-Name", "NDTVi", pkHTTPHEADER);
RESTRequest2->Params->AddItem("X-DreamFactory-Session-Token", sSessionID, pkHTTPHEADER);
        // Call the Dreamfactory server and get the data
RESTRequest2->Execute();

}


So far, so good.  After this, things get a little involved which is where I spent most of my time.

Hopefully, this will help you.

Select the FDMemTable1 object and in the Object Inspect click the ellipsis on the FieldDefs property.  See image below. The FieldDefs property is circled in red.


When you click on the ellipsis, you can add the columns that your REST call will return.  I like to keep the column name EXACTLY as they are returned by the REST call - which is normally the way they are defined in the database. If you work with SQL Server and with ADO.Net, you may not be used to worrying about the case of column names.  I would suggest you pay attention to this when working with C++ Builder and Dreamfactory.  Makes life easier.  

I have added two columns

Location ID : ftInteger
Location : ftString

Select the correct type from the Object Inspected for the FieldDefs dialog.  Always good to.



This is what the FieldDefs property editor looks like for one column



Now is the "visual" part.  I have not been able to figure out how to do this programatically, which is for some reason, my preferred method.

In the Object Inspector, select TResponseDataAdapter and set the Dataset property to FDMemTable1.  See the image below.



On the form, click the FDMemTable object and call up the LiveBindings designer.  The FDMemTable object shows up as BindSourceDB1 and you can see FDMemTable1 in the second row of this object.

Now, connect the following

1. * from BindSourceDB1 to Synch of cbRequestLocation
2. Location from BindSourceDB1 to Item.Text of cbRequestLocation




That's it.  Voila, run your application and the ComboBox will show the rows from the table.

Of course, you need to replace all user names, password, server names, Dreamfactory service names and tables names and column names with your own.

Subsequent articles will look at how to pass parameters to filter records and order and sort.

Cheers


2 comments:

  1. Hello, congratulations for the post! For version of Dreamfactory 2.0, what changes in the settings to make the connection?

    ReplyDelete
  2. Is there any example to do CRUD process using dreamfactory and RADStudio?

    ReplyDelete