Watch, Follow, &
Connect with Us

Idle Musings of a Delphi Junkie

If you are an EDN Mobile user, you should upgrade

I have been porting many of my DataSnap REST services from using dbExpress for its database access, to take advantage of the FireDAC data access framework. As a side-effect of this, I’ve had to make a change to the EDN Mobile application to handle a slight difference in datatype in some of the datasets it remotes to clients. In particular, the My Member Services and My duplicate accounts functionality may no longer work as intended with EDN Mobile versions 1.1.4 and prior once I upgrade the REST server.

I intend to upgrade the REST service that EDN Mobile consumes one month from today, so you should have plenty of time to upgrade to the latest version of EDN Mobile (currently 1.1.5). The new version should consume the existing  REST service with no issues.

This upgrade also fixes a bug with the way auto login authentication details were stored, so if you are encountering issues in this area, this upgrade will be beneficial to you.

Posted by David Clegg on June 13th, 2013 under EDN, General | 2 Comments »


Cross platform anonymous threads and progress notification

Reading Anders Ohlsson’s latest blog post about using iOS APIs we don’t wrap reminded me of another couple of helper classes that I created, and which ship with the RAD Studio XE4 samples.

The first of these is the TAnonymousThread<T> generic class (in <samples installation directory>Delphi\RTL\CrossPlatform Utils\AnonThread.pas), and is designed to make it easy to create and consume anonymous threads for any activities that will return some kind of result (e.g. fetching data from a remote service). The public API for it is as follows :-

TAnonymousThread<T> = class(TThread)
public
  constructor Create(AThreadFunc: TFunc<T>; AOnFinishedProc: TProc<T>;
    AOnErrorProc: TProc<Exception>; AStartSuspended: Boolean = False;
    AFreeOnTerminate: Boolean = True);
end;

As you can see, the interface is pretty straightforward. It takes a series of procedure and function pointers to allow you to specify a function to be run in the thread, a callback procedure which will be run in the main thread so you can process the result, and a callback procedure which will run in the main thread if an exception occurs during thread processing. By default it will not start the thread suspended, and will free the thread on termination (for platforms that don’t have ARC implementations).

Here is an example of using this class:-

var
  lThread: TAnonymousThread<TDataSet>;
begin
  lThread := TAnonymousThread<TDataSet>.Create(
    function: Boolean
    begin
      //Runs in separate thread
      Result := SomeLongRunningMethodReturningADataSet;
    end,
    procedure(AResult: TDataSet)
    begin
      //Runs in main thread
      SomeMethodToProcessDataInMainThread(AResult);
    end,
    procedure(AException: Exception)
    begin
      //Runs in main thread
      ShowMessage(AException.Message);
    end);
end;

The second class is the TAsyncProgress<T> generic class (in <samples installation directory>Delphi\RTL\CrossPlatform Utils\Xplat.Utils.pas). Like the TAnonymousThread<T> class, it is designed to run a method returning a result in a separate thread, but has the added functionality of showing notification of a long running process. The public API for this class is as follows:-

TAsyncProgress<T> = class
  public
    class procedure Execute(AFunc: TFunc<T>; AOnFinished: TProc<T>;
      AOnError: TProc<Exception>);
  end;

As you can see, it has a similar interface to TAnonymousThread<T>, and accepts callback methods to handle a threaded function, and methods running in the main thread to process the result, or any exception that may occur during thread processing.

Here is an example of using this class:-

TAsyncProgress<Boolean>.Execute(
  function: TDataSet;
  begin
    //Runs in separate thread
    Result := SomeMethodReturningADataSet;
  end,
  procedure(AResult: TDataSet)
  begin
    //Runs in main thread
    SomeMethodToProcessData(AResult);
  end,
  procedure(AException: Exception)
  begin
    //Runs in main thread
    ShowMessage(AException.Message);
  end);

If you look at the implementation of TAsyncProgress<T> in Xplat.Utils.pas, you’ll see that it leverages the FMX.Platform.TPlatformServices class to register and consume an IPleaseWaitService interface. This interface has the following signature:-

IPleaseWaitService = interface
  procedure StartWait;
  procedure StopWait;
end;

I have created an implementation of this interface for iOS in iOS.Services.pas, and for OSX in Mac.Services.pas. The iOS implementation uses the technique that Anders blogged about to show the network activity indicator in the iOS status bar, but it also uses the UIActivityIndicatorView class to show a spinning progress indicator in the centre of your application view. Similarly the OSX implementation uses the NSProgressIndicator class to show a spinning progress indicator in the center of your main OSX application view.

To register an implementation for a given platform, simply add the relevant *.Services.pas file to your project.

In addition to leveraging the IPleaseWaitService interface via the TAsyncProgress<T> class, you can also interact with this service directly using helper methods in XPlat.Utils.pas, by utilizing the following:-

//Returns an instance of the IPleaseWaitService registered for the current platform
function PleaseWaitService: IPleaseWaitService;

//Runs the specified procedure (unthreaded), using the IPleaseWaitService interface to
//indicate execution progress.
procedure ProgressProc(AProc: TProc);

//Wraps a call to IPleaseWaitService.StartWait, if the service has been registered
procedure StartWait;

//Wraps a call to IPleaseWaitService.StopWait, if the service has been registered
procedure StopWait;

There are sample applications for iOS showing how to consume the TAnonymousThread<T> and TAsyncProgress<T> classes located in <samples base>Delphi\RTL\CrossPlatform Utils\AsyncProgress/AnonymousThread.dproj and <samples base>Delphi\RTL\CrossPlatform Utils\AsyncProgress/AsyncProgress.dproj respectively.

Posted by David Clegg on April 30th, 2013 under Delphi, OSX, Windows, iOS | 2 Comments »


Persisting settings in Delphi iOS applications

I thought I’d celebrate the release of RAD Studio XE4 by climbing back on the article writing horse. My first article is about persisting settings in iOS applications written in Delphi, and can be found on EDN.

As always, all feedback is greatfully received. And I’ll see if I can conjure up a few more over the coming weeks (no promises though :-)).

Posted by David Clegg on April 23rd, 2013 under Delphi, iOS | 2 Comments »


Are you eligible?

A couple of weeks ago, I implemented a new EDN feature which may have gone unnoticed by many of you. When you log into Member Services, you will now see a new ‘My eligible field tests’ option in the navigation bar to the left.

My eligible field tests navigation element

My eligible field tests navigation element

When you click on this, it will show you a list of any field tests you may be eligible to participate in, due to having a registration for a qualifying Embarcadero product.

Eligible field tests

Eligible field tests

As of today, this means that all current Delphi XE3, C++ Builder XE3, and RAD Studio XE3 users have access to the Quintessence field test, which will allow you to test and provide feedback on the latest iteration of iOS support in Delphi.

When you find an eligible field test that you think you may want to participate in, click the ‘Sign up’ link to the right of the table, and you will be taken through the field test sign up process. Once you’ve signed up for a field test, clicking this link again should (in a roundabout way) take you to the overview page for that field test. I intend to enhance this further so that any eligible field tests you’ve already registered for will handle this in a more seamless method (think of it as replacing the roundabout with a freeway :-)).

Posted by David Clegg on December 4th, 2012 under EDN, General | 20 Comments »


Introducing EDN Mobile v1.1

EDN Mobile

EDN Mobile

A new version of EDN Mobile has been launched, and along with it comes a few new features that moves it from being simply a clone of the http://members.embarcadero.com website, to instead starting to harness some of the features found in Android smartphones.

I used this opportunity to write an EDN article about it, for the benefit of the one or two community members who don’t follow my blog :-). Feel free to take a read to find out more about the newest features of EDN Mobile, and please take it for a test run and let me know what you think.

Posted by David Clegg on July 2nd, 2012 under EDN, General | 2 Comments »


EDN Mobile: Maintenant avec la localisation française!

Thanks to a totally unsolicited email from EDN community member Whiler, I am pleased to announce that EDN Mobile now supports the French locale.

I now invite other community members to provide localizations in any of the supported languages. As of Android 4.0.3, this list is available here. The localization process is pretty simple, and involves downloading these XML files, and replacing the English text values with the localized version (leaving the name attribute untouched). Once you’re done, you can email me the updated file, and I’ll incorporate it into a subsequent release of EDN Mobile.

Also, if you email me your intent to perform a localization, or add a comment here, I can keep everyone updated in the comments so we don’t have multiple people working on the same localization.

Posted by David Clegg on May 2nd, 2012 under EDN, General | 1 Comment »


EDN in your pocket

If any of you have been following Anders’ blog (and if you haven’t, you should), you’ll know he’s been doing a lot with the iOS support that Delphi XE2 offers. He is currently working on getting an app approved in the Apple AppStore that will bring a lot of the functionality available to you via the Member Services website.

Well, I’m pleased to say that I’ve beaten him to the punch, and last night I unleashed EDN Mobile, which will allow all you Android users out there to carry a little bit of EDN with you wherever you go. Please download it, and let me know your thoughts. As we surface more of EDN’s functionality via DataSnap REST services in future, we’ll be looking to expand the functionality on offer.

Finally, thanks to Nick Hodges for bravely putting up his hand to beta test this app for me. :-)

Posted by David Clegg on April 26th, 2012 under EDN, General | 8 Comments »


The Christchurch Earthquake - A call for help

As you are probably aware, last week New Zealand’s second largest city, Christchurch, was hit by a devastating earthquake. One that looks to be the countries largest natural disaster ever. There have been many various ways for people around the world to help out, but there was one that I found out about today that I had to share with my fellow developers and friends in the Delphi community. Please bear with me as I elaborate.

Over the last few months, I have really embraced Twitter, and one of the people I follow is an iOS and OSX developer based in New Zealand named David Frampton. Among other apps, he is the developer responsible for the hugely successful Chopper and Chopper 2 iOS and OSX games. When the quake struck, Twitter was a flurry of activity, and one of the stories unfolding revolved around his mother.

First he tweeted that his mother was in the Christchurch CBD, and he was waiting to hear from her. As many Kiwis were doing at this stage, he was intently watching the story unfolding on television. One of the first images showing the extent of the destruction centered around a 4 storey office building (the Pyne Gould Corporation building).

When David witnessed this footage, he exclaimed that this was his mothers workplace, and that she was probably on the third floor of the building. The next day, and after an anxious night with little sleep, he tweeted that his mum has been found. She was still trapped, but was talking to rescuers. This was followed a few hours later by a tweet confirming that his mother had been rescued, and was relatively unharmed.

His mothers name is Anne Bodkin, and at the time of writing she remains the last person to have been rescued alive from any of the ruined buildings littering Christchurch’s landscape. Rescuers are still working bravely and tirelessly to see if they can find any more trapped survivors.

And here is how you, my fellow software developers, can step in to help. Today, I found that David and a bunch of other New Zealand developers have rallied together and are giving 100% of the proceeds from sales of their applications directly to the New Zealand Red Cross appeal (http://www.appappeal.co.nz/). Of course, once I found this out I rushed off to the AppStore and purchased a copy of the excellent Chopper 2 for my iPhone. At the time of writing, there are 31 applications to choose from, written by a bunch of extremely talented New Zealand developers (including PikPok Games; the software house responsible for a host of excellent iPhone and Android games). Please take the time to browse the software on offer, and see if any take your fancy. If they do, please consider a purchase. Not only will you get some kick-ass new software, but you will also be helping out the Christchurch quake victims, who can really do with a helping hand right now.

Posted by David Clegg on February 27th, 2011 under General | Comment now »


Six months in a leaky boat

Yesterday I discovered a potential resource leak when using the dbExpress Ado.NET provider, which can cause connections to be created and never freed. This leak was discovered when I implemented and started consuming a helper method which allows me to easily determine whether a data reader contains a specified column.

class method DbUtils.ColumnExists(AReader: DbDataReader; AColumnName: String): Boolean;
begin
  var Table: DataTable := AReader.GetSchemaTable;
  Table.DefaultView.RowFilter := String.Format('ColumnName =''{0}''', AColumnName);
  Result := (table.DefaultView.Count > 0)
end;

The above code seemed pretty innocuous, but a bit of spelunking using Reflector discovered that the call to TAdoDbxDataReader.GetSchemaTable resulted in the associated TAdoDbxConnection cloning itself into a private variable, and this connection was never closed. So if this method is called multiple times using different connections, each call would result in an additional database connection being made which wasn’t being closed until the application exited. For the app that this bug was discovered in, this meant that an ever increasing number of connections were being established to an InterBase database, eventually resulting in stored procedure calls that never finished executing.

If you think you may be affected by this bug, please take a look at http://qc.embarcadero.com/wc/qcmain.aspx?d=82886, and vote/rate as you see fit. In addition to providing more details as to the cause of the leak, it also suggests the following possible workaround.

class method CloseConnection(AConnection: TAdoDbxConnection);
begin
  var Field: FieldInfo := AConnection.GetType.GetField('FClonedConnection',
    (BindingFlags.GetField or (BindingFlags.NonPublic or BindingFlags.Instance)));
  if (Field <> nil) then
  begin
    var Con: TAdoDbxConnection := (Field.GetValue(AConnection) as TAdoDbxConnection);
    if (Con <> nil) then
    begin
      Con.Close;
      Field.SetValue(AConnection, nil)
    end;
  end;
  AConnection.Close;
end;

Now, obviously this workaround is pretty brittle, and could easily break if the DBX team change their internal implementation of TAdoDbxConnection (especially if said change involved renaming FClonedConnection), but I have verified that it works against the release of DBX that currently ships with Delphi Prism. The DBX team have been made aware of this bug, so hopefully it will be resolved in a not too distant release, and give the above kludge a short life expectancy.

Posted by David Clegg on March 11th, 2010 under .NET, Database, Delphi, InterBase, Prism, dbExpress | Comment now »


Migrating IIS7 configurations

In the process of setting up my development environment on a new laptop, I was looking for a way to migrate my IIS7 configurations from the old laptop, so I didn’t have to manually configure the many web applications and virtual directories required in my day to day development duties. As there was no obvious ‘Export’ or ‘Import’ options available, I asked my good friend Mr Google, who suggested this article.

The steps outlined seemed pretty straightforward, and just what I was looking for. A few of the commenters remarked that they couldn’t get the process to work, with HTTP 503 errors being reported when attempting to run imported web sites. After the import I had the same problem with my web sites and static content being served, but unlike the commenters, with a little diagnostics and a smattering of common sense, I was able to solve the problem.

The first step was to take a peek in the event viewer to see if that would give any insight into what was going on.

image

As the above screenshot shows, the IIS worker process was unable to find a DLL with the name compdyn.dll. This DLL is used by the dynamic HTTP compression feature of IIS7, which is not installed by default, and a quick squiz into the C:\Windows\System32\inetsrv directory confirms that the DLL is not present on my system. I fired up Programs and Features so I could install this feature, but after waiting a few minutes I was informed that the installation had failed. This time the event log wasn’t too helpful as to why.

image

Working on a hunch that this may have been due to the install process failing because of locked files, I rebooted my machine, tried to apply the configuration change again, and this time it succeeded. I then confirmed that the config change had the desired effect, and that compdyn.dll now existed in the C:\Windows\System32\inetsrv directory. This dance was went another round, due to another required dll that was missing, but once all required IIS features had been installed, I was successfully able to run my imported web applications. As it turns out, I suspect a full reboot was probably not necessary, as the files in use were probably being locked by the IIS worker process attempting to service the failed request. So it would probably have been sufficient to either recycle the applicable application pool, or restart the IIS service.

Posted by David Clegg on April 16th, 2009 under .NET, ASP.NET, IIS | 4 Comments »




Server Response from: BLOGS1