Thursday, July 10, 2008

Deploying Applications Without the Midas Library

When deploying a application that used ClientDataSet, you may want to distribute the Midas.dll. If your don't want to do so, you can also compile it into your exe.

program Project1;

uses
MidasLib,
Forms,
Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.

Reference: Cary Jensen, http://dn.codegear.com/article/29297

Wednesday, July 9, 2008

Print Single Quote in Delphi

This is VERY easy task. I write it down, just in case I forgot...

s := 'Don''t play play!';

ShowMessage(s);


Will give you

Don't play play!

Tuesday, July 8, 2008

How to set a default printer for your application

Here i use an ini file to store my printer index.

1st, I use these components:

Dialogs ----> TPrinterSetupDialog;
Printers ----> TPrinter
IniFiles----> TIniFile


Then here is the form startup and close. PrinterIndex is just a global variable.

procedure TForm1.FormCreate(Sender: TObject);
var
IniFile : TIniFile;
begin
IniFile := TIniFile.Create(ExtractFilePath(Application.ExeName) + 'configuration.ini');
// Read the value from the ini file
PrinterIndex := IniFile.ReadInteger('Printer','Index',0);
IniFile.Free;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var
IniFile : TIniFile;
begin
IniFile := TIniFile.Create(ExtractFilePath(Application.ExeName) + 'configuration.ini');
// Save the value into the ini file
IniFile.WriteInteger('Printer','Index',PrinterIndex);
IniFile.Free;
end;


So in your application you can do it this:

procedure TForm1.Button1Click(Sender: TObject);
begin
// Change current printer index to the value we get from the ini file.
Printer.PrinterIndex := PrinterIndex;
ShowMessage(IntToStr(Printer.PrinterIndex));

// Open the dialog
PrinterSetupDialog1.Execute;

// Set new value to the PrinterIndex variable.
ShowMessage(IntToStr(Printer.PrinterIndex));
PrinterIndex := Printer.PrinterIndex;
...
...

Monday, July 7, 2008

Database Archiving

Ever encounter this problem before?

“Database is not a black hole.”

Did you know that? It will overflow! So? You need to do housekeeping. Take some old records away and put it some where else. Why? Because it will affect your system performance. And not everybody afford to have an Oracle in their company.

You would be lucky if your system needs to do it once a year. What if you need to do it once a month? Or daily? Pain in the ass, right?

So, if there an easy way to do it? Well, I am not a pro in database administration. Never worked with one before in my experience. I just want to emphasize the importance of including the concept of database archiving while you design your system.

Some important points in archiving a database are:
  • How often do you need to archive the database?
  • What tables do you need to archive?
  • How your program can link back to the archived database?
Make sure your system can last for a long run. Don’t let people come in and tell you that you need to archive your database and will charge you this amount.

How many databases do you need?

When been asked, how many databases do you have in your system? One, is it enough?
“Well, my system is small, one should be enough…”

Yeah, I use to think like that too. But not after I encounter this issue in my ex-company, I totally understand how important a good design can help is some critical situation.

But what I mean by good database design? Well you should throw all those ‘table design’, ‘normalize’, and ‘relational table’ things behind first. We just touch the basic, but it’s critical to your application.

For a simple application, you won’t run away from an Application module which interact with the users and a Report module that generates all the report.













One significant problem that countered in this design is, it took minutes for a page to load a report. Of course you won’t see this symptom in the beginning. But after the program runs for some time, enough records populated in the database, then that is when your nightmare begins. (lol)

So what alternative we have here?

Although it makes your application looks sophisticated, but it has its value.
  • Then application performance will not be affected by the report extraction.
  • Reports are extracted by an engine, which should be scheduled to do so accordingly.
  • The extracted report will be saved in another database. Displaying of the report is basically a simple database query. (very fast)
Logically, this design will run longer than the previous one. Next time an IT consultant proposing a system to you, ask for how the put their database. :)
Good to know.

Tomcat Paralyzed in Linux

I have gone through some experience installing tomcat in a Linux box. Just like to share some problem that I encountered.
When I start up the tomcat, one thing that I notice is, after a while, and then tomcat will hang. First it looks very strange to me. I start to question about the performance of the tomcat, which I don think that is the cause of the problem. But luckily after many rounds of try and error, we manage to figure out what went wrong.

1. The setup is: Apache, Tomcat, mod_jk, MySQL.
2. When I start the Tomcat, I monitor the activity vis:
netstat | grep 8009 | wc –l
and the number of instances increase until 512, then the tomcat hang.
3. Something I overlook which also tells me what went wrong:
netstat | grep 3360 | wc -l
4. Finally I conclude that the problem was caused by the SQL connection that is not closed.

When a request comes in, Apache call Tomcat via mod_jk (port 8009). Then in tomcat, my application call MySQL (port 3306) but no response (due to wrong setting. I was doing a migration). So the request keeps on waiting, waiting, waiting. . . and finally all the available ajp connection used up. Then tomcat was paralyzed.

A very strange scenario, as when I run top command, I don’t see java using high CPU or memory.

So, a good experience in deed.
Next time if your tomcat paralyzed too (touch wood), try look at this solution.

Sunday, July 6, 2008

Format First Capital


procedure ShowText();
var
s : String;
i : Integer;
begin
s := 'is another way to think about what you x';
s[1] := UpCase(s[1]);
for i := 1 to Length(s) do
begin
if s[i] = ' ' then
if i < Length(s) then
s[i+1] := UpCase(s[i+1]);
end;

ShowMessage(s);
end;