Tuesday, November 16, 2010

Why Intraweb Javascript is not minified?

Well, mine are! ;-)

After a lot of IW JavaScript debugging I asked myself: Why IW JavaScript code is not minified? You know, those .js files included in the header of the page generated by an Intraweb web application....?

If you want to know more about JS minification, you can read here. Simple performance comparisons can be seen here. You may note that the performance may increase up to 50% depending on the original, not minified, JavaScript file.

Well, If Atozed doesn't minify their JavaScript, I can minify them myself. All JavaScript code distributed with Intraweb is inside the resource file IWData.res (look inside the DCU folder).
To minify the scripts I've used two different tools: A resource tool to export IW JavaScript inside the resource file, and a JavaScript minifier. The resource tool was Resource Hacker (old and good resource utility written in Delphi 3, still very useful). Just open the IWData.res using Resource Hacker and you will see something like that:

You can export all the RCData resouces with a single operation choosing the menu option shown above. Choosing this option, Resource Hacker will save all RCData resources and a .RC file. With those files you will be able to recompile IWData.res from modified (minified JavaScript) files. In my IW version (10.0. 0.17) the saved files from 51 to 68 are the JavaScript internal files.

After that, I used the JavaScript Obfuscator to minimize it (there is a fully functional evaluation version available). You can use any JS compressor/minifier, like the excellent YUI online compressor. After compression, all the JavaScript files were reduced to 107 KB (275 KB before compression), 39% of their original size!
Then, you can recompile IWData.res, using the .rc file generated by Resource Hacker, using Delphi's own resource compiler (brcc32.exe, in BDS 2006). Copy the recompiled IWData.res to the IW dcu folder replacing the original file (backup the original FIRST!), and you are ready to go!
You will have a faster IW application and as an extra bonus your ISAPI DLL will be 170 KB smaller! :-)

Note: I've tryied the JavaScript Obfuscator tool to minify and obfuscate IW JS libraries, but later I've found out that the resulting JavaScript was tooooo dammmn slow. So I'm only minifying it using YUI online compressor

Wednesday, November 10, 2010

Doing nice things with Intraweb + jQuery!

Well, the first example I saw using Intraweb and jQuery playing together was a nice post from Hadi Hariri (Originaly here, but the page is gone. You still can read it in google cache, here).
Then, in IW 10 I saw a new component "TIWjQueryWidget". Fotunately, it came with sources, and I could see that it is simple, very simple indeed.
I already knew a little about jQuery and I saw that it would be relatively simple to use in with Intraweb (would it?).
What do you think that IW misses most? For me: Maybe, a nice Ajax enabled data grid, modal dialogs, a nice looking page control/tab sheet container, some mask inputs and some other minor things. Well, I've started from the most challenging one (at least, before any knowledge about it!): the data grid. I've choosen jQGrid. A nice, beautiful, simple and well written ajax grid. I wish (Win32) Delphi's DBGrid was as good as (Web) jQGrid!
Many, many hours of work during my spare time, almost a second divorce ;-) and voilá! I've made it work! Not much Delphi code, but due to the lack of Intraweb source code, books, articles and examples I had to search every little piece of information in newsgroups, blogs and IW - very restrict - sources. Now I see why IW is not a killing framework to create web applications: Chad kept the source code closed for toooooo damn long (still today)! It is just too hard to understand the "meat" of IW without the source code! The reason that thousands of developers started to write good components for Delphi - making Delphi a terrific tool back in 1995 - was just because the best teacher was there in your hard disk: RTL/VCL sources!

Well, back to IW + jQuery: The jQGrid is working. A limited version of it, but it works pretty damn good for now. I'm proud and happy to use it today in a production environment, in a respected brazilian bank (internal) web application. This bank is among the 60's biggests in the world. For you foreigner that may ask "what? a brazilian bank?". You'd better think twice! Brazil has one of the most advanced banks in the world, when we talk about software and technology (the same can be said about elections! After all, we knew our next president 3 HOURS after the voting finishes ;-) ).

Soon I will put some IW + jQuery demos live, at work!

Below a little screen shot of my IWjQGrid using the old "country" table, from Delphi demos!



I would like to know what you think about it.

Wednesday, October 13, 2010

Maldito bug do ConnectionBroker!

Há algum tempo venho experimentando uns crashes constantes do IDE do Delphi (tanto D6 quanto BDS2006) ao trabalhar com um projeto multi-camadas baseado no DataSnap.
De forma a abstratir a conexão do ClientDataSet do protocolo (DCOM, Socket ou WebConnection), eu utilizo um TConnectionBroker em cada DataModule onde tem TClientDataSet ligado ao servidor.

Pois bem, reparei que ao clicar no item de menu "Close All" do Delphi sempre ocorria um Access Violation, que com frequência obrigava-me a reiniciar o IDE. Resolvi identificar a causa do erro. Instalei um novo ExceptionHandler para o IDE, baseado no JclDebug, que me permitiria obter o stack trace.
Em seguida, quando o erro tornou a ocorrer, salvei o stack trace e pude então identificar a fonte do AV. Ele sempre ocorria no método TConnectionBroker.GetConnected.
Bastou 5 minutos investigando o código do TConnectionBroker para verificar onde está o problema: O ConnectionBroker não seta a property Connection para NIL internamente se o objeto Connection for destruído, caso os dois tenham Owners diferentes (estejam em DataModules diferentes).
Em design time, dentro do IDE do Delphi, frequentemente o objeto Connection é destruído ANTES do ConnectionBroker. Como a property ConnectionBroker.Connection continua diferente de NIL, qualquer referência ao Connection irá gerar um AV.

Considero isto um bug. O correto seria utilizar o mecanismo de notificação que existe no TComponent, utilizando FreeNotification e RemoveFreeNotification, de forma que o TDispatchConnection notifique o TConnectionBroker sempre que for destruído. Assim o ConnectionBroker poderá setar internamente o Connection para nil. Detalhe: Este problema só ocorre em DesignTime, dentro do IDE. Em testes não consegui fazer o problema se repetir dentro de aplicações.

Para implementar este comportamento em um descendente customizado do TConnectionBroker seria necessário sobrecarregar o método SetConnection, que é privado. Logo, tive que criar uma "cópia" do TConnectionBroker em outra unit, e dar outro nome para ele, TConectionBrokerEx.
O método SetConnection do meu TConnectionBrokerEx ficou assim (o resto do código é cópia exata do código do TConnectionBroker):
procedure TConnectionBrokerEx.SetConnection(const Value: TCustomRemoteServer);
resourcestring
SNoConnectToBroker = 'Connection not allowed to TConnectionBroker';
begin
if FConnection <> Value then
begin
if Value = Self then
raise Exception.Create(SNoCircularConnection)
else
if Assigned(Value) and (Value is TConnectionBroker) then
raise Exception.Create(SNoConnectToBroker);
// As linhas abaixo marcadas com {*} foram adicionadas para promover a
// notificação entre Connection e ConnectionBroker quando os dois possuem
// Owners diferentes (estão em DataModules/Forms diferentes)
if Assigned(FConnection) then {*}
FConnection.RemoveFreeNotification(Self); {*}
FConnection := Value;
if Assigned(FConnection) then {*}
FConnection.FreeNotification(Self); {*}
end;
end;
Substituí todos os TConnectionBroker do meu projeto por TConnectionBrokerEx e pus um fim definitivo nos AV's que me forçavam reiniciar o IDE dezenas de vezes por dia! :-)

Sunday, September 26, 2010

Acessar o host pela VM do Virtualbox

Tenho várias máquinas virtuais do VirtualBox que utilizo no desenvolvimento. Muitas vezes preciso acessar uma aplicação COM+ ou um servidor de banco de dados hospedado na máquina HOST. Quando usamos a placa de rede da VM em modo NAT, o endereço de IP do host na rede é 10.0.2.2. Basta usar este endereço para conectar à aplicação COM+ ou ao RDBMS e pronto!

Wednesday, September 8, 2010

Obter o cliente de e-mail default

Rápida e rasteira que coloquei lá no forum da Embarcadero hoje! Obter o cliente, ou melhor, a linha de comando default do sistema, para envio de email:


function GetDefaultEmailCommand: string;
var
Reg: TRegistry;
begin
Reg := TRegistry.Create;
try
Reg.RootKey := HKEY_CLASSES_ROOT;
if Reg.OpenKeyReadOnly('mailto\shell\open\command') then
begin
Result := Reg.ReadString('');
Reg.CloseKey;
end;
finally
Reg.Free;
end;
end;

Tuesday, August 31, 2010

Incluir informação de versão (e ícone!) em aplicações Console escritas em Delphi

Não sou muito de fazer apliações console, mas me deparei com algumas atualmente. Fui incluir informação de versão e.... cadê??? O IDE não permite incluir em um projeto criado como console. Então dá-se um jeito:

1) Abra o projeto, e selecione o arquivo .DPR
2) inclua a diretiva {$R *.res} logo após as units que são declaradas (antes de declarações de variáveis, constantes, etc.)
3) Inclua a linha

Application.Run

logo depois do BEGIN

4) Abra o Project - Options e veja que agora já pode incluir ícone e informação de versão! :-)

5) Depois disso, comente ou remova a linha incluída no item 3, e voilá!

Monday, March 1, 2010

Squadra, HandProt, Congado & cia ltda.

Pessoal,

tenho recebido um grande números de comentários e reclamações de usuários de sistemas mais antigos escritos em Delphi usando proteção do HandProt da Squadra, cujos desenvolvedores sumiram no mundo, deixando os usuários a ver navios, principalmente sem poder mudar de computador, uma vez que o HandProt não deixa instalar mais do que um certo número de vezes.

Well, como escrevi num outro texto aqui, a proteção do SystemBuilder (pacotes de componentes para desenvolvimento Delphi) é moleza de quebrar, para quem tem a versão trial. Se alguém precisar, me escreva que eu ensino.

Já o HandProt, eu nunca tentei quebrá-lo. Não é impossível, pois já vi sistema usando o HandProt que foi craqueado. Mas eu não sei o nível de dificuldade.
Eu conheci o Congado (da Alma Informática, SNE) e sei que ele usa o HandProt. Gostaria de saber dos usuários de Congado (e outros protegidos pelo HandProt) se eles já tentaram contato com a Squadra. A Squadra, sediada em Belo Horizonte, tem plenas condições de resolver este problema para o usuário (resetando remotamente o número de instalações para que o usuário possa instalar em outro computador).
Não que a Squadra tenha obrigação de fazê-lo, mas um pouco de boa vontade seria muito bom para a imagem da empresa.

Vou ver o que eu consigo em relação ao HandProt. Se é possível quebrá-lo sem ter que passar noites acordado :). Assim que eu tiver novidades eu posto aqui.

Abraço!