Friday, September 22, 2023

CRUD Web API with Delphi MVC Framework

 DMVCFramework is the most popular Delphi REST framework. It’s used to build web solution based on RESTful style or JSON-RPC protocol (or any kinds of “style” you prefer). It is a first-class framework; it reach the Richardson Maturity Model level 3 - a.k.a. “Glory of REST” - as M. Fowler call it in his famous paper about REST approaches. One of the main strength of DMVCFramework is the ability to build stand-alone applications without any implicit dependencies. That’s it, you can just build your API and deploy it without any framework, runtime etc. Another deployment strategy is to deploy the DMVCFramework APIs as Windows Service, as Apache module (for Windows and Linux), as Linux daemon or as IIS ISAPI (for Windows). All these kind of deployments allows a clean, fast and performant solution with minimal configuration.

Learning by practical examples is always great; therefore, this article will walk you through the creation of a simple but complete RESTful CRUD (create-read-update-delete) API using DMVCFramework. In this example I’ll use PostgreSQL as RDBMS. Yes, I love PostgreSQL, but DMVCFramework can be used with any kind of database engine of course or even no one. Though DMVCFramework can provide RESTful API and JSON-RPC APIs, the greater emphasis in this article will be on a RESTful API and database connectivity.

Continue at :


Monday, October 26, 2015

How to make an ADODataset Readonly ?

Q. How to make an ADODataset Readonly ?

A. Just change LockTyp=ReadOnly

Tuesday, April 7, 2015

Solution to '0.0' is not a valid timestamp in D7

Solution to '0.0' is not a valdi timestamp ;-)

(* SysUtils.pas line 10934 (Delphi 7.1)  *)
(**)(* fix - Timestamp values 0.0 erroneously designated as invalid *)
(* D7.1 *)
(* Walter Prins, originally patched May 2005, submitted 4 June 2009 *)
procedure ValidateTimeStamp(const TimeStamp: TTimeStamp);
begin
  if (TimeStamp.Time < 0) or (TimeStamp.Date < 0) then (* Changed TimeStamp.Date <= 0 to TimeStamp.Date < 0 *)
    ConvertErrorFmt(@SInvalidTimeStamp, [TimeStamp.Date, TimeStamp.Time]);
end;
}

Friday, October 10, 2014

Connecting to Oracle via Delphi

Recently, I had the need to connect to an outdated Oracle 9.2.0.8 Oracle Server.

This are the steps taken by me:

1) Download Oracle 12c - latest as at October 2014
2) 2 zip files
3) Extract All
4) Copy ..\component of zip to the zip1..\component folder

Saturday, May 24, 2014

Refactoring & Scope of Variables

Recently, I had to enhance some legacy codes running into thousands and thousands of lines of code within a loop. In order to facilitate ease of customisation, I decided to refactor the codes breaking chunks of codes into procedures. However, I was concerned with the visibility of the visibility in these procedures of variables declared in the calling procedure.

A google search led me to this valuable article at  delphi.about.com/od/beginners/l/aa060899.htm

Object Pascal Variable Scope

 As mentioned in some of the previous articles understanding Object Pascal variable scope is one of key elements in building applications with Delphi/Object Pascal.

 Scope of Variables and Constants
The term scope refers to the availability of a variable or constant declared (or used) in one part of a program to other parts of a program.
Unless we specify otherwise, changing the value of a variable named, let's say, SomeNumber in one procedure (function) will not affect another variable with the same name in another procedure (function).
Since Delphi requires us to declare variables, it's a lot harder to fall into the trap caused by side effects accidentally. As we know by now, every variable used in some procedure has to be declared in the var section of the event handler.
In general, we declare a variable where we want to use it. For example, if we want to use a variable in an event handler, we declare the variable within the event handler.

Local Scope (+ variable declaration and initialization)
Most variables have local scope, which means that the variable is visible only within the code block in which it is declared (usually: Event Handler for some method). In particular, an event handler will not normally have access to the value of a variable in another event handler.
If we want to be sure a variable is local within an event handler, we have to declare it in the var section inside the event handler. Since we must declare a variable before we can use it, if we can use a variable without declaring it locally, we know that there is a variable with greater scope with the same name somewhere around project.
Let us look at the first example:
1. Start Delphi, this will give us (by default) new application with one blank form.
2. Double click somewhere on the form (to create OnCreate event handler)
3. Write down this code:
procedure TForm1.FormCreate(Sender: TObject);
begin
 ShowMessage(FloatToStr(SomeNumber));
end;

4. If you try to run your project now, you will be prompted with: "Undeclared Identifier: 'SomeNumber'" error. This means that we haven't declared SomeNumber variable in our project (note: entire project, not FormCreate event handler).
5. To declare SomeNumber variable as double type change your code to:
procedure TForm1.FormCreate(Sender: TObject);
var SomeNumber: double;
begin
 ShowMessage(FloatToStr(SomeNumber));
end;

6. Run your project, message box will appear with some strange (value of the memory region where variable is stored) number. Delphi will also give us "Variable 'SomeNumber' might not have been initialized" warning. This means that, before using declared variable, it is a good practice to initialize it (just to be sure). For that purpose add this line of code before ShowMessage...
SomeNumber := 123.45;

7. Now, when you run your project message box will display 123,45 (no errors, no warnings). Finally, we can see why local variables are called local...
8.Add one TButton component to form and double-click it to create Buttons OnClick event handler. Add the following code (so that OnClick looks like):
procedure TForm1.Button1Click(Sender: TObject);
begin
 ShowMessage(FloatToStr(SomeNumber));
end;

Again we have "Undeclared Identifier: 'SomeNumber'" error. This is what local variables are all about: even if we have declared (and initialized) SomeNumber variable in OnCreate event handler of the form, SomeNumber is not accessible in the OnClick handler of TButtton. We simply cannot use SomeNumber (with 123.45 value) in the OnClick (at least for now). This means that SomeNumber from OnCreate and SomeNumber from OnClick are two different variables (that can, of course, hold different values) 9. Don't close this project, jet. We will need it again...
10. Add the following line before ShowMessage in the OnClick event handler (we will need it later, don't worry about this for now)
SomeNumber:=555.55;
   Sharing variables across procedures (event handlers)
Occasionally we will want to share the values of variables (and constants) across event handlers or across units. For example, if an application is designed to perform a calculation involving one SomeNumber at a time, that SomeNumber should be available to all procedures in a unit.
Depending on where we declare a variable, the variable can be thought of as a true global variable accessible by any other code in the application, or a unit-level variable accessible by any code in the unit.
   Unit level variables - unit level scope
We put the declaration statements for unit-level variables in a var section in the unit's implementation section. Unit-level constants are declared in a const section.
Let's look at the second example:
0. We will be modifying our first example (be sure to have it)
1. Add declaration of SomeNumber, so that implementation code of the unit looks like:
...
implementation
{$R *.DFM}
var
  SomeNumber: Double;
...
2. Run your program. As you can see, we don't have "Undeclared Identifier: 'SomeNumber'" error in OnClick handler of the TButton. When program starts message box will appear with 123.45 value. When you click on the Button1 message box will display 555.55; that's why we need step 10 in the first example - we have initialized SomeNumber to 555.55 in the OnClick event of the Button1. What's this? We have two SomeNumber variables in our project and they both hold different values.
Obviously, we have to be careful when assigning values to unit-level variables. Although we can use the same variable (or constant) name for both local and unit-level variables, this is not a good idea. Any var (or const) declaration contained in a procedure takes precedence over global (unit-level) declarations. Duplicating the names makes the global variable invisible to the procedure (Delphi doesn't tell us whether a global variable has been defined with the same name as a local variable). That is why SomeNumber holds the 123,45 value in the OnCreate event handler of the form (we cannot use global variable SomeNumber in the OnCreate procedure)
Note 1: If you really have to use two variables with the same SomeNumber name (one global and one local), you can access the global SomeNumber variable value in the forms OnCreate procedure with the call to unit1. SomeNumber (unit1 is the name of the unit with the global SomeNumber variable). That is, something like
unit1.SomeNumber:=444.44;
will change value of the global variable SomeNumber inside OnCreate event handler of the form (remember that there is a SomeNumber variable local to this procedure which will stay unchanged)
Note 2: As global SomeNumber is global to the unit we can access (more important: change) its value from any other procedure inside this unit. However click to Button 1 will reset SomeNumber value to 555.55. Better way to initialize global variables is inside initialization section of the unit.
   Global variables - program level scope
If we want to create true global variables (or/and constants) in a project, we have to place the declaration in the interface section of the unit. Variables declared in the interface section will be visible (accessible) to any unit which uses that unit.
For example, to change SomeNumber variable value that is declared in Unit1 from Unit2, use this statement:
Unit1.SomeNumber:=999.99;
Be sure to add Unit1 to the uses clause of Unit2.    Conclusion
That's it. I hope you have had the power to come to the end of this article. As we can see, there is much to be stated about variable scope in Object Pascal. Of course, there is more: static variables (or typed constants) are something we could name "constant variables". I'll be dealing with static variables in some of the future articles...

Wednesday, August 21, 2013

Installing Delphi 5 on Windows XP Professional on a Virtual PC

Just bought a 64-bit Windows 8 laptop and wanted to migrate a Delphi 5 installation from an old Windows XP laptop. This is what I did to successfully migrate Delphi 5 plus all installed VCL.

1. Downloaded and installed VMware on the Windows 8 laptop
2. Created a new Virtual Machine and installed Windows 7 Professional
3. Copied the whole Borland folder from the old Windows XP laptop to the Virtual Machine
4. Using Regedit, export out the Borland registry entry
5. Copy (4) to the root drive of the Virtual Machine
6. Double-click on (5) to import into the Virtual Machine registry
7. Copy *.bpl from the ...Delphi5\projects\bpl into the bin folder
8. Copy from c:\windows\system32\*,bpl to the same folder in the Virtual machine

Basic idea is that runtime bpls must reside in the bin folder whilst design-time bpls resided in projects\bpl.

That's it :-)

Welcome to Delphi... Delphi... Delphi

I have been a Delphi Developer since Delphi 3 when I finally decided on Delphi in 1996 as my programming language of choice for the Windows 32 environment. So what have I created with Delphi ?

Would you believe that I had single-handedly created a full ERP2 system comprising ERP+CRM where ERP=Sales Distribution+MRP+ Procurement Management+Planning & Production +Finacial Management + Human Resources Management System.

Since 15th February 2009, we have visitors from more than 60 countries including Malaysia, United States, Brazil, Italy, Australia, India, Turkey, Russian Federation, Spain, Indonesia, Hungary, South Africa, Germany, Mexico, Argentina, Singapore, Saudi Arabia, Colombia, Czech Republic, Canada, France, Croatia,Thailand, Bulgaria, Slovenia, Hong Kong, Poland, Sri Lanka, Chile, Japan, Austria, Ukraine, Azerbaijan, Ireland, Tunisia, Greece, Taiwan, Egypt, Bolivia, Paraguay, Iran, Islamic Republic , Morocco, Angola, Belgium, Portugal, Norway, Venezuela, United Arab Emirates, Algeria, Korea, Republic Of, Slovakia, Georgia, Lebanon, Macedonia, Sweden, Philippines, Vietnam, Dominican Republic