quarta-feira, 25 de fevereiro de 2009

Delphi Intraweb - Gerar dinamicamente JavaScript

Continuação do artigo Delphi Intraweb – JavaScript II (Continua)

Antes de qualquer coisa, preciso registrar a alegria de podermos contar com mais um colaborador no nosso blog.
Prezados leitores, em nome de todos os colaboradores, quero manifestar a alegria em poder contar com mais um grande amigo no time do Estação ZN. Rodrigo Alencar, brother de longas datas tem contribuído com um material de extrema qualidade, pertinência e originalidade.
Rodrigão, seja bem vindo ao Estação ZN, é uma honra poder contar com o sua participação!

Dando continuidade ao tema ...

Para controlarmos, através de JavaScript, a ação de habilitar e desabilitar o IWCombo1 (O que carregamos com os nomes das bandas) vamos gerar dinamicamente o script que vai no browser fazer esse gerenciamento.
Adicione no IWForm mais um IWCheckBox, e codifique conforme ilustrado abaixo:


private
procedure LoadComboBandas;
procedure DesabilitaControles;
procedure BuildScriptControlEnabled;
public

Na seção “private” declarei o método que vai construir dinamicamente o JavaScript, “BuildScriptControlEnabled”.

procedure TZnIWForm.BuildScriptControlEnabled;
const
FunctionJsBodyStatment = 'function %s{%s}';
AQuebraLinhaJs = #13;
AStatementFnc =
' var ZnComboLnd = FindElem("%s");' + AQuebraLinhaJs +
' alert(ZnComboLnd[ZnComboLnd.selectedIndex].innerHTML);' + AQuebraLinhaJs +
' var ZnChkBox = FindElem("%s");' + AQuebraLinhaJs +
' alert(ZnChkBox.innerHTML);' + AQuebraLinhaJs +
' ZnChkBox.checked = !ZnChkBox.checked;' + AQuebraLinhaJs +
' ZnComboLnd.disabled = !ZnChkBox.checked;' + AQuebraLinhaJs +
' if (!ZnComboLnd.disabled){ ' + AQuebraLinhaJs +
' alert(ZnComboLnd.name + " está Habilitado"); ' + AQuebraLinhaJs +
' ZnComboLnd.style.backgroundColor = "#FFFFFF"; ' + AQuebraLinhaJs +
' ZnComboLnd.focus(); ' + AQuebraLinhaJs +
' return true; ' + AQuebraLinhaJs +
' } ' + AQuebraLinhaJs +
' else{ '+ AQuebraLinhaJs +
' ZnComboLnd.style.backgroundColor ="#E7E7E7"; '+ AQuebraLinhaJs +
' return false; ' + AQuebraLinhaJs +
' };'+ AQuebraLinhaJs;
var
StrStatement: String;
begin
StrStatement := AQuebraLinhaJs;
StrStatement := StrStatement + Format(AStatementFnc,
[UpperCase(IWComboBox1.Name), UpperCase(ChckBoxBandas.Name)]);

StrStatement := Format(FunctionJsBodyStatment,
['ZnHabilitaCmbBanda()', StrStatement]);
Self.JavaScript.Add(StrStatement);
ChckBoxBandas.ScriptEvents.Add('onClick').EventCode.Add('ZnHabilitaCmbBanda()');
end;


Observe que temos problemas na hora de trabalharmos com o objeto do tipo “CheckBox”. Veja que, para montar a string que será adicionada a propriedade “JavaScript” do IWForm, na linha 8, recuperamos o objeto com função “FindElem()”.Do contrário, teríamos que usar o nome completo do componente (definido em JavaScript na página web). Ou seja, teríamos que concatenar com o nome do controle (IWCheckBox) no Delphi como bendito sufixo “_CHECKBOX”.
Na linha 9, somos obrigados a simular o comportamento “Click” do objeto. Que absurdo! Do contrário ele não efetiva o “Click”. Pelo menos, essa foi a solução que encontrei, visto que o click do componente não rolava.
Na linha 10, somente então, efetivamos a atribuição de valor a propriedade “disabled” do objeto recuperado na linha 7 (o “IWComboBox1”).

No trecho de código abaixo, podemos ver como ficou no browser a função que dinamicamente montamos no Delphi:

function ZnHabilitaCmbBanda(){
var ZnCombo = document.forms[0].IWCOMBOBOX1;
var ZnChkBox = FindElem("CHCKBOXBANDAS");
ZnChkBox.checked = !ZnChkBox.checked;
ZnCombo.disabled = !ZnChkBox.checked;
if (!ZnCombo.disabled){
alert(ZnCombo.name + " está Habilitado");
ZnCombo.style.backgroundColor = "#FFFFFF";
ZnCombo.focus();
return true;
};
else{
ZnCombo.style.backgroundColor ="#E7E7E7";
};
}


Isso acontece especialmente no Intraweb 8 porque ele trata o comportamento de todo “CheckBox” com uma tag “span”. Como se não bastasse isso, para complicar ainda mais, ele agrega, arbitráriamente, um sufixo ao nome original do componente, “_CHECKBOX”. Isso certamente deve ter complicado a vida de quem tentou trabalhar com JavaScript no Intraweb 8. Veja um trecho de código gerado no browser pelo Intraweb 8 na definição do “CHCKBOXBANDAS”:


<input tabindex="27" type="CHECKBOX" name="CHCKBOXBANDAS_CHECKBOX">
<span onclick="FindElem('CHCKBOXBANDAS_CHECKBOX').checked =
!FindElem('CHCKBOXBANDAS_CHECKBOX').checked;">Habilitar Bandas</span>
</span>


No Intraweb 5 isso não acontece. Primeiro, não existe o sufixo na definição JavaScript do componente. Segundo, embora exista a tag span, ela presta somente para exibir o conteúdo do caption do IWCheckBox, o comportamento do CheckBox não está programado nela. Portanto, não precisaríamos simular o click em código conforme eu fiz na linha 04 da “function ZnHabilitaCmbBanda()”. Alias, se alguém tiver algo a acrescentar a minha análise, por favor, fique a vontade. Em outras, palavras, foi a solução que encontrei.

Outro ponto importante, quero destacar nesse exemplo a atribuição dinâmica da propriedade “ScriptEvent” do TIWCheckBox, “ChkBoxBandas”. Isso está sendo feito na linha 28 do procedimento “BuildScriptControlEnabled”.

Artigo completo (View Full Post)

segunda-feira, 9 de fevereiro de 2009

Sistema de tarifação, HSQLDB e Java - PARTE 2.

Continuando o post anterior...

O problema é interceptar determinados eventos em um servidor de download para tarifação em tempo real em um servidor de tarifação. O servidor de download permite a instalação de plug-ins escritos em Java para interceptar os eventos de download.

No post anterior vimos a implementação do servidor de download e um plugin de exemplo. Neste post vamos ver a outra ponta: o sistema de tarifação. O sistema de tarifação é um sistema implementado em um servidor de banco de dados com tabelas e stored procedures.

O sistema que vamos ver é um sistema simulado, composto de uma tabela e três procedures que consultam e atualizam o sistema.

As procedures são as seguintes e todas possuem dois parâmetros, o primeiro é o id do usuário e o segundo o servico que ele esta tentando acessar.

boolean queryBalance(int, string) - consulta se o usuário possui saldo para acessar o serviço.
void charge(int, string) - tarifa o usuário no serviço especificado.
void credit(int, string) - estorna o usuário no serviço especificado.

O sistema é implementado no HSQLDB, um gerenciador de banco de dados escrito em Java. O HSQLDB possui um instalação simples e rápida. O HSQLDB possui suporte a stored procedures escritas em Java.

Para a instalação basta fazer o download e descompactar o arquivo no diretório de sua preferência.

Após descompactar no diretório de destino você vai ter uma pasta chamada hsqldb. No prompt de comando dentro dessa pasta execute o camando abaixo para executar o HSQLDB no modo servidor.

java -classpath ./lib/hsqldb.jar org.hsqldb.Server

Para executar a ferramenta administrativa do HSQLDB execute o comando abaixo.

java -cp ./lib/hsqldb.jar org.hsqldb.util.DatabaseManager

Para a criação das stored procedures utilizei o Netbeans. Uma stored procedure no HSQLDB é um método stático de uma classe Java. E a classe Java deve estar no classpath do servidor. Esse método acessa o ambiente do servidor através de um parâmetro Connection declarado na assinatura do método.

Nesse sistema criei uma classe chamada hsqldbSP_Billing no pacote hsqldbSP_Billing. A classe é a seguinte.

package hsqldbSP_Billing;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class hsqldbSP_Billing {

public static double DOWNLOAD = 10;

public static boolean query(Connection conn, Integer id, String service) throws SQLException{
boolean hasBalance = false;
Statement st = null;
ResultSet rs = null;
st = conn.createStatement();
String sql = "select amount from balance where id = " + id;
rs = st.executeQuery(sql);

if(rs.next()) {
double amount = rs.getDouble("amount");
if(amount > 0){
hasBalance = true;
}
}

st.close();
return hasBalance;
}

public static void charge(Connection conn, Integer id, String service) throws SQLException{
String sql = "update balance set amount = amount - ? where id = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setDouble(1, DOWNLOAD);
pstmt.setInt(2, id);

pstmt.executeUpdate();

pstmt.close();
}

public static void credit(Connection conn, Integer id, String service) throws SQLException{
String sql = "update balance set amount = amount + ? where id = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setDouble(1, DOWNLOAD);
pstmt.setInt(2, id);

pstmt.executeUpdate();

pstmt.close();
}
}


No HSQLDB podemos criar aliases para as SPs através do seguinte comando.
CREATE ALIAS QUERYBALANCE FOR "hsqldbSP_Billing.hsqldbSP_Billing.query"

No HSQLDB a assinatura da procedure possui somente do dois últimos parâmetros pois a Connection será passada pelo servidor. Parar executar as stores procedures a sintaxe é a seguinte.
call queryBalance(1, 'DOWNLOAD')
call charge(1, 'DOWNLOAD')
call credit(1, 'DOWNLOAD')

Executando o código.

Faça o download do arquivo hsqldb.zip e copie seu conteúdo para a pasta do HSQLDB. Este arquivo possui dois arquivos para auxiliar na execução do HSQLDB para este exemplo, o run.bat que executa o servidor HSQLDB com as SPs no classpath e o arquivo manager.bat que executa a ferramente administrativa do HSQLDB. Além disso esse arquivo possui a configuração inicial das tabelas e aliases necessárias para o sistema.

No arquivo hsqldbSP_Billing.zip está o projeto Netbeans com o código das SPs criadas.

No próximo post vamos criar a infra necessária para acessar o sistema de tarifação através de um sistema BPEL.

Até o próximo post!
Rodrigo Alencar.

Artigo completo (View Full Post)

 
BlogBlogs.Com.Br