Programando em CGI no Sistema Windows Seven, e não podendo escolher o IIS (o Express e o Cassini não executam CGI), fizemos a opção pelo Tomcat. Tendo que usar o Microsoft Access devido aos custos com exportação de dados e conversão de tipos para o Mysql em aplicações legadas, optamos pelo servidor Tomcat 7. O Tomcat é mais compatível com a arquitetura CGI e ainda roda servlets JSP.
Diante de todos estes fatores, o acesso aos dados por ODBC tornou-se o mais viável. Mas ao tentar este acesso, o browser informou que não era possível acessar o ODBC via MIcrosoft Access Driver devido ao erro de sistema 126.
Em sistemas Microsoft isto é muito comum, pois cada atualização joga DLLs sobre as já existentes, provocando conflitos entre número de parâmetros e seus tipos de dados. E isto ocorre com o pacote de objetos que contém o ODBC. Com isto, a biblioteca odbcjt32.dll pode se tornar incompatível com o sistema da máquina (pasmem).
Resolvendo o problema no Windows XP e Seven
Vamos resolver o problema de forma que possa ser aplicado ao Windows XP e Seven.
Como o Seven não vai deixar (em alguns casos) você copiar a biblioteca odbcjt32.dll para o C:\Windows\System32, crie um diretório C:\Meusystem com os arquivos:
msjter40.dll
odbcjt32.dll
odbcji32.dll
Tire as bibliotecas odbcji32.dll e msjter40.dll do C:\Windows\System32.
No registro do Windows, na chave ODBCINST.INI, altere os parâmetros Driver e Setup do Microsoft Access Driver para este PATH (C:\Meusystem ):
Programação com Scripts para Web
Blog da Rede Blogazine
Conteúdos com Pesquisa e Revisão
domingo, 19 de fevereiro de 2012
segunda-feira, 13 de fevereiro de 2012
Lazarus Object Pascal - Programando em CGI
CGI é uma antiga forma de programar não proprietária em sua infra-estrutura, como é o ISAPI da Microsoft.
Vamos a algumas particularidades da programação em CGI que o tornam mais conveniente que o ISAPI em determinadas situações.
O ISAPI precisa ser preparado a base de objetos, forma de concepção de programação que exige planejamento anterior. Após o planejamento de métodos e propriedades que o objeto vai ter, é preciso utilizar ferramentas Microsoft de construção e dominar terminologias de construção que mudam de ano para ano e que provocam o advento de ferramentas cada vez mais complexas.
Se você desejar fazer uma aplicação simples de banco de dados e desejar ler um banco de dados em um arquivo TXT com uma certa estrutura, ou um XML, vai ter que dominar os aborrecidíssimos e instáveis objetos Microsoft, e que são portas para invasão, devido à não checagem de invasão de áreas de memória.
O Lazarus Pascal
O Lazarus Pascal, clone quase idêntico 100 % ao Delphi, possui componentes e capacidades já bem construídos em função das numerosas inconsistências do seu semelhante. Instale os dois pacotes do diretório:
<Diretório de Instalação>\Lazarus\Components\fpweb
Os pacotes a serem instalados são (nesta ordem):
weblaz.lpk
lazwebextra.lpk
Utilize a opção do menu:
Package => Open Package file (lpk)
Compile e Instale ambos, NA ORDEM QUE RECOMENDAMOS.
Se tudo correr bem, o Lazarus vai reiniciar.
Primeira versão - Utilizando o objeto TCustomCGIApplication
Inicie um novo projeto do tipo console.
program project1;
{$mode objfpc}{$H+}
uses
Classes, SysUtils, httpDefs, custcgi, custweb
{ you can add units after this };
Type
TMyCGIApp = Class(TCustomCGIApplication)
Protected
function InitializeWebHandler: TWebHandler; override;
end;
TMyCGIHandler = class(TCGIHandler)
public
procedure HandleRequest(ARequest: TRequest; AResponse: TResponse); override;
end;
{$R *.res}
Procedure TMyCGIHandler.HandleRequest(ARequest : Trequest; AResponse : TResponse);
begin
AResponse.Content := '<H1>Hello</H1>';
end;
function TMyCGIApp.InitializeWebHandler: TWebHandler;
begin
Result := TMyCGIHandler.Create(self);
end;
begin
With TMyCGIApp.Create(Nil) do
try
Initialize;
Run;
finally
Free;
end;
end.
Segunda versão - Usando fpweb e o WebModule
Utilize a opção de novo projeto do tipo CGI Application.
A unit gerada nem precisará ser mexida:
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, HTTPDefs, websession, fpHTTP, fpWeb, fphtml;
type
{ TFPWebModule1 }
TFPWebModule1 = class(TFPWebModule)
HTMLProducer1: THTMLEntityProducer;
private
{ private declarations }
public
{ public declarations }
end;
var
FPWebModule1: TFPWebModule1;
implementation
{$R *.lfm}
initialization
RegisterHTTPModule('TFPWebModule1', TFPWebModule1);
end.
A única alteração virá como resultado da colocação de um componente THTMLEntityProducer da paleta fpweb.
Selecione o WebModule, e clique em sua propriedade Actions (que inicia com o valor 0 items). Aparece uma caixa de diálogo, onde você deverá pressionar o botão Add. Clicando na nova ação (action) aparecem as suas propriedades no Object Inspector. Clique então em Contents e coloque um trecho de HTML como abaixo:
<H1>HTMLEntityProducer</H1>
<P>Action 1</P>
Coloque o valor True na propriedade Default.
Compile e coloque o executável em um diretório com autorização de execução de cgis em um servidor web. Se você executar este programa pelo Lazarus, ele mostrará a mensagem:
Project <nome do projeto> raised Exception Class 'Exception' with message:
No REQUEST_METHOD passed from server.
Os fóruns de discussão da Internet não foram capazes de esclarecer os usuários do Lazarus de forma correta a respeito deste erro e nem do uso correto dos componentes fpweb. Foi preciso um enorme esforço para descobrir estas informações, sem documentação. Por isso estamos colocando esta ajuda para os "abandonados pelos técnicos".
Vamos a algumas particularidades da programação em CGI que o tornam mais conveniente que o ISAPI em determinadas situações.
O ISAPI precisa ser preparado a base de objetos, forma de concepção de programação que exige planejamento anterior. Após o planejamento de métodos e propriedades que o objeto vai ter, é preciso utilizar ferramentas Microsoft de construção e dominar terminologias de construção que mudam de ano para ano e que provocam o advento de ferramentas cada vez mais complexas.
Se você desejar fazer uma aplicação simples de banco de dados e desejar ler um banco de dados em um arquivo TXT com uma certa estrutura, ou um XML, vai ter que dominar os aborrecidíssimos e instáveis objetos Microsoft, e que são portas para invasão, devido à não checagem de invasão de áreas de memória.
O Lazarus Pascal
O Lazarus Pascal, clone quase idêntico 100 % ao Delphi, possui componentes e capacidades já bem construídos em função das numerosas inconsistências do seu semelhante. Instale os dois pacotes do diretório:
<Diretório de Instalação>\Lazarus\Components\fpweb
Os pacotes a serem instalados são (nesta ordem):
weblaz.lpk
lazwebextra.lpk
Utilize a opção do menu:
Package => Open Package file (lpk)
Compile e Instale ambos, NA ORDEM QUE RECOMENDAMOS.
Se tudo correr bem, o Lazarus vai reiniciar.
Primeira versão - Utilizando o objeto TCustomCGIApplication
Inicie um novo projeto do tipo console.
program project1;
{$mode objfpc}{$H+}
uses
Classes, SysUtils, httpDefs, custcgi, custweb
{ you can add units after this };
Type
TMyCGIApp = Class(TCustomCGIApplication)
Protected
function InitializeWebHandler: TWebHandler; override;
end;
TMyCGIHandler = class(TCGIHandler)
public
procedure HandleRequest(ARequest: TRequest; AResponse: TResponse); override;
end;
{$R *.res}
Procedure TMyCGIHandler.HandleRequest(ARequest : Trequest; AResponse : TResponse);
begin
AResponse.Content := '<H1>Hello</H1>';
end;
function TMyCGIApp.InitializeWebHandler: TWebHandler;
begin
Result := TMyCGIHandler.Create(self);
end;
begin
With TMyCGIApp.Create(Nil) do
try
Initialize;
Run;
finally
Free;
end;
end.
Segunda versão - Usando fpweb e o WebModule
Utilize a opção de novo projeto do tipo CGI Application.
A unit gerada nem precisará ser mexida:
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, HTTPDefs, websession, fpHTTP, fpWeb, fphtml;
type
{ TFPWebModule1 }
TFPWebModule1 = class(TFPWebModule)
HTMLProducer1: THTMLEntityProducer;
private
{ private declarations }
public
{ public declarations }
end;
var
FPWebModule1: TFPWebModule1;
implementation
{$R *.lfm}
initialization
RegisterHTTPModule('TFPWebModule1', TFPWebModule1);
end.
A única alteração virá como resultado da colocação de um componente THTMLEntityProducer da paleta fpweb.
Selecione o WebModule, e clique em sua propriedade Actions (que inicia com o valor 0 items). Aparece uma caixa de diálogo, onde você deverá pressionar o botão Add. Clicando na nova ação (action) aparecem as suas propriedades no Object Inspector. Clique então em Contents e coloque um trecho de HTML como abaixo:
<H1>HTMLEntityProducer</H1>
<P>Action 1</P>
Coloque o valor True na propriedade Default.
Compile e coloque o executável em um diretório com autorização de execução de cgis em um servidor web. Se você executar este programa pelo Lazarus, ele mostrará a mensagem:
Project <nome do projeto> raised Exception Class 'Exception' with message:
No REQUEST_METHOD passed from server.
Os fóruns de discussão da Internet não foram capazes de esclarecer os usuários do Lazarus de forma correta a respeito deste erro e nem do uso correto dos componentes fpweb. Foi preciso um enorme esforço para descobrir estas informações, sem documentação. Por isso estamos colocando esta ajuda para os "abandonados pelos técnicos".
sexta-feira, 2 de dezembro de 2011
Instalação do IISExpress
Entre os diversos servidores Web "thin" para a plataforma Windows está o IISExpress.
É um produto desenvolvido sobre o framework .NET 4.0 (dotnet 4.0) capaz de executar ASP e ASP.NET necessário para pequenos testes com o protocolo HTTP. Junto com ele vem um gerenciador de extensões para instalação dos produtos "derivados" (Web Plataform Installer), como o Visual Studio 2010 SP1, Microsoft SQL Server Data Tools, Application Request Routing 2.5 e outros.
Ele funciona maravilhosamente bem no Windows 7 professional (a versão 7 não tem nada a ver com o a marca Windows Seven).
É dificílimo achar o IISExpress, pois os blogueiros comentam, comentam e não dizem onde baixar, então colocamos aqui um link para o usuário:
Ele funciona na porta HTTP 8080.
Baixe também o gerenciador de extensões WPIlauncher para obter as extensões desejadas (não é obrigatório):
Executando o IISexpress
Após instalado, podemos fazer um atalho e executar o programa em:
C:\Program Files\IIS Express
ou
C:\Arquivos de Programas\IIS Express
O executável é:
iisexpress.exe
Ao executarmos o programa, aparece uma janela do console:
É um produto desenvolvido sobre o framework .NET 4.0 (dotnet 4.0) capaz de executar ASP e ASP.NET necessário para pequenos testes com o protocolo HTTP. Junto com ele vem um gerenciador de extensões para instalação dos produtos "derivados" (Web Plataform Installer), como o Visual Studio 2010 SP1, Microsoft SQL Server Data Tools, Application Request Routing 2.5 e outros.
Ele funciona maravilhosamente bem no Windows 7 professional (a versão 7 não tem nada a ver com o a marca Windows Seven).
É dificílimo achar o IISExpress, pois os blogueiros comentam, comentam e não dizem onde baixar, então colocamos aqui um link para o usuário:
Ele funciona na porta HTTP 8080.
Baixe também o gerenciador de extensões WPIlauncher para obter as extensões desejadas (não é obrigatório):
Executando o IISexpress
Após instalado, podemos fazer um atalho e executar o programa em:
C:\Program Files\IIS Express
ou
C:\Arquivos de Programas\IIS Express
O executável é:
iisexpress.exe
Ao executarmos o programa, aparece uma janela do console:
A porta de execução é realmente 8080. Execute o seguinte endereço no browser:
O site fica no caminho:
C:\Users\usuario\Documents\My Web Sites\WebSite1
Bom trabalho.
quinta-feira, 8 de setembro de 2011
Servlet completo de leitura de tabela MSAccess - JSP
Como prometido, a seguir a listagem explicada do servlet J2EE para leitura de registros de uma tabela em um banco MSAccess. Ao final, basta unir os trechos em fonte de cor vermelha para obter a script. Os parâmetros a serem substituídos estão sublinhados (PRESTE BASTANTE ATENÇÃO).
Definição de pacote
package TesteServlet.servlets;
Esta declaração produz uma árvore hierarquica dentro da Workspace de um projeto, por exemplo, feito no Eclipse:
O diretório src é dos fontes (source) em java. TesteServlet é o nome do pacote, e servlets é como um grupo de assunto dentro dele. Sugerimos até que você utilize esta conveção para os servlets. TesteServlet pode ser substituído por um nome que lembre a finalidade de seu pacote de classes.
Importação de Bibliotecas
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
O primeiro bloco contém as bibliotecas java cuja responsabilidade é gerenciar as entradas e saídas (java.io) e as consultas e atualizações de bancos de dados (java.sql). O segundo bloco traz as rotinas responsáveis pela característica de servlet de nossas classes.
Estes blocos poderiam ser declarados como:
import java.io.*;
java.sql.*;
javax.servlet.*;
No entanto, muitas rotinas seriam incorporadas sem necessidade.
Corpo do Servlet
Vamos dar o esquema do servlet que vamos apresentar, e posteriormente o método que é o coração do processo.
/**
* Servlet implementation class LeTabela
*/
public class LeTabela extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public LeTabela() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
// Posteriormente vamos dar o conteúdo deste método - LOCAL DO CÓDIGO
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
}
}
Nesta classe (LeTabela - que extende HttpServlet ) são declarados 3 métodos:
Os dois últimos métodos se confundem com o próprio "espírito HTTP". No browser estamos sempre enviando parâmetros (via formulário), ou seja, POST, ou recebendo parâmetros (via análise da requisição), ou seja, GET.
Em nosso caso, executaremos o método GET (doGet) do servlet, ou seja, chamado o servlet, ele dispara este método.
Detalhamento do método doGet
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
Connection conn;
Statement stmt;
ResultSet rs;
String S = "";
response.setContentType("text/html");
PrintWriter out = response.getWriter();
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
// URL da conexão
conn = DriverManager.getConnection("jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=//SERVIDOR/compartilhamento/Nome do banco.mdb");
stmt = conn.createStatement();
rs = stmt.executeQuery("SELECT * FROM Nome da Tabela");
while(rs.next()){
String fname=rs.getString("Nome do Campo");
S += "•"+fname+"<BR>";
}
rs.close();
stmt.close();
conn.close() ;
} catch (Exception e) {
System.out.println(e.toString());
}
out.println(S+"<BR>");
}
Definição de pacote
package TesteServlet.servlets;
Esta declaração produz uma árvore hierarquica dentro da Workspace de um projeto, por exemplo, feito no Eclipse:
O diretório src é dos fontes (source) em java. TesteServlet é o nome do pacote, e servlets é como um grupo de assunto dentro dele. Sugerimos até que você utilize esta conveção para os servlets. TesteServlet pode ser substituído por um nome que lembre a finalidade de seu pacote de classes.
Importação de Bibliotecas
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
O primeiro bloco contém as bibliotecas java cuja responsabilidade é gerenciar as entradas e saídas (java.io) e as consultas e atualizações de bancos de dados (java.sql). O segundo bloco traz as rotinas responsáveis pela característica de servlet de nossas classes.
Estes blocos poderiam ser declarados como:
import java.io.*;
java.sql.*;
javax.servlet.*;
No entanto, muitas rotinas seriam incorporadas sem necessidade.
Corpo do Servlet
Vamos dar o esquema do servlet que vamos apresentar, e posteriormente o método que é o coração do processo.
/**
* Servlet implementation class LeTabela
*/
public class LeTabela extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public LeTabela() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
// Posteriormente vamos dar o conteúdo deste método - LOCAL DO CÓDIGO
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
}
}
Nesta classe (LeTabela - que extende HttpServlet ) são declarados 3 métodos:
- Construtor LeTabela público (se não for público, a classe não pode ser instanciada);
- Método doGet;
- Método doPost;
Os dois últimos métodos se confundem com o próprio "espírito HTTP". No browser estamos sempre enviando parâmetros (via formulário), ou seja, POST, ou recebendo parâmetros (via análise da requisição), ou seja, GET.
Em nosso caso, executaremos o método GET (doGet) do servlet, ou seja, chamado o servlet, ele dispara este método.
Detalhamento do método doGet
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
Connection conn;
Statement stmt;
ResultSet rs;
String S = "";
response.setContentType("text/html");
PrintWriter out = response.getWriter();
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
// URL da conexão
conn = DriverManager.getConnection("jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=//SERVIDOR/compartilhamento/Nome do banco.mdb");
stmt = conn.createStatement();
rs = stmt.executeQuery("SELECT * FROM Nome da Tabela");
while(rs.next()){
String fname=rs.getString("Nome do Campo");
S += "•"+fname+"<BR>";
}
rs.close();
stmt.close();
conn.close() ;
} catch (Exception e) {
System.out.println(e.toString());
}
out.println(S+"<BR>");
}
A tentativa de estabelecimento de conexão com um banco de dados e a sua manipulação deve estar dentro de um bloco de tratamento de POSSÍVEIS exceções ( try { ... } catch ( ...) { ... }. Por esta razão, declaramos as variáveis necessárias fora deste bloco, para que sejam acessíveis de qualquer lugar dentro do método, pois o bloco try ... catch PROTEGE AS VARIÁVEIS LOCAIS A ELE. Por exemplo, se você declarar a variável S dentro deste bloco, o comando final (out.println) não a conhecerá.
Abertura da conexão
Como explicado no post Conexão JDBC com banco MSAccess, a conexão é feita pelas instruções:
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
conn = DriverManager.getConnection("jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=//<servidor>/<compartilhamento>/<Nome do mdb>.mdb");
conn = DriverManager.getConnection("jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=//<servidor>/<compartilhamento>/<Nome do mdb>.mdb");
Aqui usamos a pior condição, ou seja, o banco Access em um outro servidor. Mas a forma recomendada é colocar o banco no servidor Web e fazer a conexão pelo nome do ODBC. A melhor prática, frisamos, é ter as scripts e banco de dados no mesmo servidor acessado pelos clientes. Se você não confia na segurança de seu servidor, coloque um outro na DMZ (zona protegida por um roteador) da qual ele faz parte, para que não possa ser devassado caso o servidor Web seja invadido.
Acesso através da linguagem SQL
stmt = conn.createStatement();
rs = stmt.executeQuery("SELECT * FROM Nome da Tabela");
rs = stmt.executeQuery("SELECT * FROM Nome da Tabela");
Na frase do executeQuery podem ser colocadas cláusulas WHERE (condicionais) ou ORDER BY (ordenação). Mas hoje, com bibliotecas que ordenam as tabelas HTML resultantes de pesquisa, esta ordenação deve ser feita no cliente, economizando recursos do servidor de banco de dados.
Listando os registros de forma bem básica
while(rs.next()){
String fname=rs.getString("Nome do Campo");
S += "•"+fname+"<BR>";
}
String fname=rs.getString("Nome do Campo");
S += "•"+fname+"<BR>";
}
Um simples loop while resolve a situação. Cada valor de campo é extraído por um tipo de instrução get da interface Java Resultset:
Tipo de Dado | Instrução |
Blob (Memo) | getBlob() |
Data | getDate() |
Inteiro | getInt() |
String | getString() |
Em nosso exemplo simplificamos tudo para a forma String.
Lembre-se que para a exibição num resultado do tipo HTML ou XHTML, o valor terá que ser convertido para o modo string, para ser concatenado com as tags.
Fechando os objetos
Ao final de seu uso, os objetos devem ser fechados, para a boa integridade da pilha de objetos da máquina virtual Java.
rs.close();
stmt.close();
conn.close() ;
Armadilha da exceção do bloco try ... catch
} catch (Exception e) {
System.out.println(e.toString());
}
Este catch se presta a capturar quaisquer outras exceções que não as ServletException, IOException.
Final
out.println(S+"<BR>");
} // Fecha o método
Esta instrução out.println exibe o resultado de tudo o que foi armazenado na variável S durante o loop. Se nada foi lido, pelo fato do SQL não ter achado nada, será exibido um vazio.
Fechando os objetos
Ao final de seu uso, os objetos devem ser fechados, para a boa integridade da pilha de objetos da máquina virtual Java.
rs.close();
stmt.close();
conn.close() ;
Armadilha da exceção do bloco try ... catch
} catch (Exception e) {
System.out.println(e.toString());
}
Este catch se presta a capturar quaisquer outras exceções que não as ServletException, IOException.
Final
out.println(S+"<BR>");
} // Fecha o método
Esta instrução out.println exibe o resultado de tudo o que foi armazenado na variável S durante o loop. Se nada foi lido, pelo fato do SQL não ter achado nada, será exibido um vazio.
quarta-feira, 7 de setembro de 2011
Conexão JDBC com banco MSaccess
Para os programadores Java e JSP que estão em dúvida com a conexão JDBC para este banco de dados tão eficiente, aqui vão os trechos de código para a conexão:
JDBC sobre ODBC
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
conn = DriverManager.getConnection("jdbc:odbc:Teste");
JDBC puro no servidor local
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
conn = DriverManager.getConnection("jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=C:/Users/usuario/Documents/Teste.mdb");
JDBC puro no servidor local
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
conn = DriverManager.getConnection("jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=//<servidor>/<compartilhamento>/<Nome do mdb>.mdb");
Protótipo do código
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
conn = DriverManager.getConnection(...);
.
.
.
conn.close() ;
} catch (Exception e) {
System.out.println(e.toString());
}
A conexão, bem como as instruções de leitura, atualização ou adição de registros devem estar dentro de um bloco de tratamento de exceções.
Lembrete Final
Em todos os casos, é preciso:
Dar permissão nas chaves de registro (via regedit.exe ou regedt32.exe) referentes a ODBC para que o usuário Web anônimo (IUSR_<nome do servidor> ou Anon_Web) possa modificá-las ou criar novas;
Dar permissão nos diretórios C:\Windows\Temp para Todos no modo de alteração e criação;
Dar permissão no diretório onde está o banco de dados para que o usuário Web anônimo (IUSR_<nome do servidor> ou Anon_Web) possa modificar ou criar arquivos.
Num próximo post, colocaremos o servlet completo.
JDBC sobre ODBC
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
conn = DriverManager.getConnection("jdbc:odbc:Teste");
JDBC puro no servidor local
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
conn = DriverManager.getConnection("jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=C:/Users/usuario/Documents/Teste.mdb");
JDBC puro no servidor local
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
conn = DriverManager.getConnection("jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=//<servidor>/<compartilhamento>/<Nome do mdb>.mdb");
Protótipo do código
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
conn = DriverManager.getConnection(...);
.
.
.
conn.close() ;
} catch (Exception e) {
System.out.println(e.toString());
}
A conexão, bem como as instruções de leitura, atualização ou adição de registros devem estar dentro de um bloco de tratamento de exceções.
Lembrete Final
Em todos os casos, é preciso:
Dar permissão nas chaves de registro (via regedit.exe ou regedt32.exe) referentes a ODBC para que o usuário Web anônimo (IUSR_<nome do servidor> ou Anon_Web) possa modificá-las ou criar novas;
Dar permissão nos diretórios C:\Windows\Temp para Todos no modo de alteração e criação;
Dar permissão no diretório onde está o banco de dados para que o usuário Web anônimo (IUSR_<nome do servidor> ou Anon_Web) possa modificar ou criar arquivos.
Num próximo post, colocaremos o servlet completo.
quarta-feira, 27 de julho de 2011
O pernicioso null em campo numérico e a conversão em inteiro (Cint) no ASP
Ficamos perplexos com um problema em ASP ao se listar campos de números inteiros que podem ou não estar preenchidos.
O que "disse" a consulta
O campo Diâmetro é numérico, no entanto pode ou não estar preenchido. O programador está testando, em uma consulta (query), se o mesmo está em uma faixa de valores fornecidos (Expr1 e Expr2).
Na execução, vem a mensagem:
Executamos a consulta, fornecendo dois valores e dando o OK, e aparece a mensagem:
Isto ocorre porque o VB não consegue converter nulo (Null) em inteiro.
O teste com IsEmpty (ÉVazio)
No entanto, para campos preenchidos ou não a consulta apresentou o resultado:
E qual a solução para se testar a faixa de valores ?
Para resolver o problema, concatena-se um zero à esquerda (que não altera em nada o valor, tanto do Nulo quanto de qualquer número) do campo de Diâmetro:
O que "disse" a consulta
O campo Diâmetro é numérico, no entanto pode ou não estar preenchido. O programador está testando, em uma consulta (query), se o mesmo está em uma faixa de valores fornecidos (Expr1 e Expr2).
Na execução, vem a mensagem:
Executamos a consulta, fornecendo dois valores e dando o OK, e aparece a mensagem:
Isto ocorre porque o VB não consegue converter nulo (Null) em inteiro.
O teste com IsEmpty (ÉVazio)
Foi feito o teste com a função "IsEmpty" que testa se o campo está vazio.
No entanto, para campos preenchidos ou não a consulta apresentou o resultado:
E qual a solução para se testar a faixa de valores ?
Para resolver o problema, concatena-se um zero à esquerda (que não altera em nada o valor, tanto do Nulo quanto de qualquer número) do campo de Diâmetro:
Ampliando:
E eis que obtemos sucesso. Veja a listagem sem a condição de faixa de valores:
segunda-feira, 13 de junho de 2011
jQuery explica a diferença entre Internet Explorer e Mozilla like
Fomos motivados a escrever este post para que TODOS entendam a diferença de interpretação entre o browser Internet Explorer e os Mozilla like (Chrome, Flock, Opera, Firefox).
Para isto vamos dar um exemplo (somos objetivos):
<html>
<head>
<script type="text/javascript" src="jquery-1.6.1.js"></script>
<script type="text/javascript">
jQuery.noConflict();
function abre(){
jQuery("div").each(function(){
document.write(jQuery(this).attr("class"));
});
}
</script>
</head>
<body onLoad="abre();">
<div class="hq pagina">
<div class="hq tira">
<div class="hq quadro"><div class="hq texto">fff</div></div>
<div class="hq quadro"><div class="hq texto">ggg</div></div>
</div>
<div class="hq tira">
<div class="hq quadro duplo"><div class="hq texto">hhh</div></div>
</div>
<div class="hq tira">
<div class="hq quadro"><div class="hq texto">mmm</div></div>
<div class="hq quadro"><div class="hq texto">nnn</div></div>
</div>
</div>
</body>
</html>
O que faz este código (não esqueça de incluir o jquery-1.6.1.js) é listar as classes das tags DIV.
Resultado no Chrome/Firefox:
Resultado no Internet Explorer:
O Internet Explorer é deficiente e ingrato. Ficamos por dois dias em cima deste comportamento anômalo, até descobrir a grande contradição do Internet Explorer:
Imediatamente após colocar na tela um resultado de script javascript, ele DESTRÓI o conteúdo da página base. Ele não tem buffer.
E como resolver ?
Rescreeva o código javascript assim:
function abre(){
var s = "";
jQuery("div").each(function(){
s = s + jQuery(this).attr("class");
});
document.write(s);
}
Desta forma, como os resultados do jQuery são armazenados em um buffer (variável s), a página não é destruída en quanto o HTML é lido pelo jQuery.
Problema Resolvido, pois Deus é poderoso.
Para isto vamos dar um exemplo (somos objetivos):
<html>
<head>
<script type="text/javascript" src="jquery-1.6.1.js"></script>
<script type="text/javascript">
jQuery.noConflict();
function abre(){
jQuery("div").each(function(){
document.write(jQuery(this).attr("class"));
});
}
</script>
</head>
<body onLoad="abre();">
<div class="hq pagina">
<div class="hq tira">
<div class="hq quadro"><div class="hq texto">fff</div></div>
<div class="hq quadro"><div class="hq texto">ggg</div></div>
</div>
<div class="hq tira">
<div class="hq quadro duplo"><div class="hq texto">hhh</div></div>
</div>
<div class="hq tira">
<div class="hq quadro"><div class="hq texto">mmm</div></div>
<div class="hq quadro"><div class="hq texto">nnn</div></div>
</div>
</div>
</body>
</html>
O que faz este código (não esqueça de incluir o jquery-1.6.1.js) é listar as classes das tags DIV.
Resultado no Chrome/Firefox:
Resultado no Internet Explorer:
O Internet Explorer é deficiente e ingrato. Ficamos por dois dias em cima deste comportamento anômalo, até descobrir a grande contradição do Internet Explorer:
Imediatamente após colocar na tela um resultado de script javascript, ele DESTRÓI o conteúdo da página base. Ele não tem buffer.
E como resolver ?
Rescreeva o código javascript assim:
function abre(){
var s = "";
jQuery("div").each(function(){
s = s + jQuery(this).attr("class");
});
document.write(s);
}
Desta forma, como os resultados do jQuery são armazenados em um buffer (variável s), a página não é destruída en quanto o HTML é lido pelo jQuery.
Problema Resolvido, pois Deus é poderoso.
Assinar:
Postagens (Atom)