Jump to content

Recommended Posts

I've written a fairly small web app for testing and learning using WebBroker that makes a few InterBase database queries and I've got it working as both an ISAPI DLL under IIS on Windows and as an Apache Web Module for Apache 2.4 on Windows. I'm now testing it under Apache for Linux and while a simple database query still works, another part of this app does not.

 

One of the web actions is hooked up to a TDataSetTableProducer and it requires a wait cursor (TFDGUIxWaitCursor) in order to work.  That component has a Provider property where leaving it at the default of FMX worked just fine for Windows versions (IIS and Apache) but fails under Apache for Linux. I tried changing the Provider to Console and replacing the used units but that did not help.

 

Does anyone know how to use datasets for Apache web modules under Linux using FireDAC which requires a wait cursor?

 

Reference: http://docwiki.embarcadero.com/Libraries/Sydney/en/FireDAC.Comp.UI.TFDGUIxComponent.Provider

Share this post


Link to post

Have you tried adding this to your uses clause?

{$ifdef Console}
  FireDAC.ConsoleUI.Wait,
{$else}
  FireDAC.FMXUI.Wait, FireDAC.Comp.UI,
{$endif}

Share this post


Link to post

I had something very close to that--I tested for Linux instead of Console. 

 

And I guess that's the problem--it's not really a console app, even though it doesn't have a GUI.

Share this post


Link to post

What happens if you include the console version unconditionally? 

Share this post


Link to post

Then neither the Linux nor the Windows versions shows the dataset.  At least the way I have it now, the Windows one works.

 

Here's my uses clause:  

  {$IFDEF LINUX}
  FireDAC.ConsoleUI.Wait,
  {$ELSE}
  FireDAC.FMXUI.Wait, FireDAC.Comp.UI,
  {$ENDIF}

Here's a constant defined which shows on the generated web page that indicates which platform it's running under:

{$IFDEF CONSOLE}
  APP_NAME = 'My App Console';
{$ELSE}
  {$IFDEF LINUX}
  APP_NAME = 'My App Linux';
  {$ELSE}
  APP_NAME = 'My App Windows';
  {$ENDIF}
{$ENDIF}

The Windows one shows up for Apache for Windows, the Linux one shows up for Apache for Linux.  The Console one, as you might guess by now, never shows up.

 

So yes, I'm sure the conditional compilation is working as expected.
 

Share this post


Link to post

You can use the console cursor even in a VCL or FMX application. So setting the provider to Console should work in all cases.

  • Like 1

Share this post


Link to post

Should.  And I wish but it doesn't in Apache web modules.

 

Without any conditional compilation, if I use FireDAC.ConsoleUI.Wait, no Apache web modules of either platform will show a dataset result. If I change that unit to either FireDAC.FMXUI.Wait or FireDAC.VCLUI.Wait, then I do get a dataset result but only for the Windows version of the Apache module.

 

Another interesting note, I expanded the testing with platform conditional directives:

{$IFDEF CONSOLE}
  APP_NAME = 'My App Console';
{$ELSE}
  {$IFDEF LINUX}
  APP_NAME = 'My App Linux';
  {$ELSE}
    {$IFDEF WINDOWS}
    APP_NAME = 'My App Windows';
    {$ELSE}
    APP_NAME = 'My App [unknown];
    {$ENDIF}
  {$ENDIF}
{$ENDIF}

and found something interesting:

  • Apache for Linux showed: My App Linux
  • Apache for Windows showed: My App [unknown]

So, Apache for Windows modules evidently don't know what platform they're compiling for!

Share this post


Link to post

Before someone catches my mistake, I just want to point out that the {$IFDEF WINDOWS} is incorrect and would never match because "WINDOWS" is not defined--it should've been {$IFDEF MSWINDOWS}.

 

Still, I'd like to know how to return datasets from FireDAC on Apache for Linux.

Share this post


Link to post

If you explicitly - without conditions - use the FireDAC.ConsoleUI.Wait unit in the project:
Can you describe any errors you may get?

If no errors - can you identify which call that fail?

The connect or the query?

Share this post


Link to post

OK, I explicitly, without any conditional compilation, used first just FireDAC.ConsoleUI.Wait then added FireDAC.Comp.UI in separate tests for both Apache for Windows and Apache for Linux.

 

No errors, no data--from either one.  I change only the first unit (ConsoleUI) to either FireDAC.VCLUI.Wait or FireDAC.FMXUI.Wait and I get a dataset in Apache for Windows but not Apache for Linux.

 

Here's the section of code from my web action item that tries to get the data set (the database is a list of park names and coordinates):

  try
    try
      Log.Debug('getting park list', LOG_TAG);
      dmParksDB.OpenParks;
      Log.Debug('parks table is open', LOG_TAG);
      Result := dstpMyParks.Content;
      Log.Debug('returning park content', LOG_TAG);
    except
      on e:Exception do
        Log.Error(e.Message, LOG_TAG);
    end;
  finally
    dmParksDB.CloseParks;
  end;
  Log.Debug('parks are closed', LOG_TAG);

Here are the log entries:

2021-06-22 01:11:10:777  [TID 139867211564800][DEBUG   ] getting park list [web]
2021-06-22 01:11:10:791  [TID 139867211564800][DEBUG   ] parks table is open [web]
2021-06-22 01:11:10:791  [TID 139867211564800][DEBUG   ] returning park content [web]
2021-06-22 01:11:10:794  [TID 139867211564800][DEBUG   ] parks are closed [web]


"dstpMyParks" is a TDataSetTableProducer whose DataSet property is hooked to a query in a data module.

 

I'm using a different web action item to make a simple database query of the same "parks" database and table and it works fine on all platforms.

 

If you want to see the code, it's on GitHub (still has the conditional compilation).

 

I am wondering if there is a library file I'm missing. Before I copied libgds.so to the Linux system, the park lookup function did not work--no error, just no data.

 

Thanks for your suggestions.

Share this post


Link to post

I get the feeling that is isn't related to the wait cursor, but the timer implementation that comes with either of the Wait implementation units. While both the VCL and FMX implementations use a TTimer (VCL/FMX), the console implementation simply doesn't support a timer at all.

Share this post


Link to post
Posted (edited)

Interesting. So, what would that imply? FireDAC's TDataSet requires a TTimer or multi-threading of some sort?


My debugging shows the query is returning records. In fact, I set up a memory table and copied the records there, switched the table producer to point to the memory table but it still shows an empty page. I guess that's not surprising as the problem is higher up, either with the TDataSet or the TDataSetTableProducer.

 

As another test, I created a console-based Windows web sever using the same data modules, thinking for sure the console wait-cursor would work--nope.

 

Oh well, this is not a critical issue, more of a curiosity; although I'm now leery of writing Linux web modules...

Edited by corneliusdavid
grammar correction

Share this post


Link to post

Can it be reproduced in a miniature example, using only direct FireDAC calls?

 

Are you sure there is no exception handling or error eating inside your library routines?

Share this post


Link to post

The code I showed above is pretty minimal. The logging is from LoggerPro and simply writes a line to a file. The dmParksDB.OpenParks simply opened the FireDAC query, which as I looked at the source for the DataSetTableProducer, realized is completely unnecessary. So basically, the code above could be reduced to:

try
  Result := dstpMyParks.Content;
except
  on e:Exception do
    Log.Error(e.Message, LOG_TAG);
end;

which does not call any of my library routines until logging the error message in the exception handler, and there are no errors in the log (but plenty of log messages before and after this).

 

And for the record, I modified my code to look like the above with no change.

 

I should also note I have been using a regular PageProducer to show nice headers and footers with an HTMLTag in the PageProducer's HTML that gets replaced in OnHTMLTag with the DataSetTableProducer.Content in the code above. I replaced that PageProducer and hooked it up directly to the DataSetTableProducer which still works for Apache for Windows (not quite as pretty because it doesn't have the surrounding header/footer HTML) and still does not work for Apache for Linux.

 

So yes, I've cut out as much of my own code as possible to eliminate the possibility it's something I'm doing.

 

There are two possibilities left: 1) there's some setting in FireDAC or WebBroker I have missed that needs to be configured differently when running under Apache for Linux, or 2) I've uncovered a bug somewhere in FireDAC or WebBroker.

Share this post


Link to post

Have you checked that opening the relevant FireDAC dataset (whatever is happening in dmParksDB.OpenParks) actually contains data on Linux? I mean, if there is no data in the dataset what can we expect?

Share this post


Link to post

The WebBroker project is a cross-platform project, compiling to Windows or Linux depending on the platform selected.  Therefore, all the code, data modules, settings, etc. are exactly the same between the two. This all runs on my Windows 10 machine where I have 1) IIS, 2) Apache for Windows, 3) Apache for Linux in a Linux subsystem, all running simultaneously but listening on different ports. The database is an InterBase database on a different machine. All data from all apps on all platforms are pulling from the same table from the same database.

 

Yes, I'm sure there's data--I can see it by simply switching the port on the browser's address line to access a different web server to test it out. And, like I mentioned previously, a different web action item in the same WebBroker project that queries for a specific record (without using the DataSetTableProducer) works just fine on all platforms, even Apache for Linux. This alone verifies the Apache for Linux version of the project is connecting successfully to the database and can return data--and that there is actually data.

 

For an example of what this looks like, you can visit MyParks.net which is running a separate copy of this project I built for IIS before doing the Apache version.  All the code and data modules are the same (except for some minor differences in setting up logging) and it points to the same database from which I'm testing the Apache versions.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×