quarta-feira, 21 de agosto de 2013

Serializar objetos



Quando dizemos que um objeto é serializado, estamos afirmando que este objeto será transformado em bytes, e poderá ser armazenado em disco ou transmitido por um stream. 

O stream é um objeto de transmissão de dados, onde um fluxo de dados serial é feito através de uma origem e de um destino.  Tomemos dois tipos de Streamers:

O FileOutputStream é um fluxo de arquivo que permite a gravação em disco.  Já o FileInputStream é justamente o contrário, permitindo a leitura de um arquivo em disco.

Tomemos também duas classes: ObjectInputStream e ObjectOutputStream. Elas são responsáveis por inserir e recuperar objetos serializados do stream.

Vamos ao exemplo, primeiro vamos desenvolver a classe chamada cliente, que será utilizada como Objeto serial de armazenamento:

import java.io.Serializable;
//A classe deve implementar Serializable
public class Cliente implements Serializable
{

    private String nome; 
    private char sexo; 
    private String cpf;

    public Cliente( String nome, char sexo, String cpf )    {
        super( );
        this.nome = nome;
        this.sexo = sexo;
        this.cpf = cpf;
    }

    public String getCpf( )    {
        return cpf;    }

    public void setCpf( String cpf )    {
        this.cpf = cpf;    }

    public String getNome( )    {
        return nome;    }

    public void setNome( String nome )    {
        this.nome = nome;    }

    public char getSexo( )    {
        return sexo;    }

    public void setSexo( char sexo )    {
        this.sexo = sexo;    }

    public String toString( )    {
        return this.nome + " / " + "Sexo: " + this.sexo + "\n" + "CPF: "
            + this.cpf;    }
}

Abaixo segue a main que executará a gravação e a leitura de objetos em um arquivo.

package br.com.artigos.serial;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class ExemploStream
{
   
    public static void main( String[] args )
    {
     // Cria o objeto serializado
     Cliente cliente = new Cliente("Glaucio Guerra",'M',"0000000001");
        try
        {
            //Gera o arquivo para armazenar o objeto
            FileOutputStream arquivoGrav =
                      new FileOutputStream("/Users/glaucio/Desktop/saida.dat");
            //Classe responsavel por inserir os objetos
            ObjectOutputStream objGravar = new ObjectOutputStream(arquivoGrav);
            //Grava o objeto cliente no arquivo
            objGravar.writeObject(cliente);
            objGravar.flush();
            objGravar.close();
            arquivoGrav.flush();
            arquivoGrav.close();
            System.out.println("Objeto gravado com sucesso!");
        }
        catch( Exception e ){
                e.printStackTrace( );
        }
       
        System.out.println("Recuperando objeto: ");
        try
        {
            //Carrega o arquivo
            FileInputStream arquivoLeitura = new FileInputStreamc:/saida.dat");
            //Classe responsavel por recuperar os objetos do arquivo
            ObjectInputStream objLeitura =  new ObjectInputStream(arquivoLeitura);
            System.out.println(objLeitura.readObject());
            objLeitura.close();
            arquivoLeitura.close();
        }
        catch( Exception e ){
                e.printStackTrace( );
        }
    }
}



Saída:

Objeto gravado com sucesso!
Recuperando objeto:
Glaucio Guerra / Sexo: M
CPF: 0000000001


Existem diversas aplicações que utilizam o recurso de serialização. O Hibernate, streams para JME, e qualquer outro tipo de aplicação que trabalhe com fluxo de I/O. Qualquer tipo de trabalho que envolver persistência ou tramitação de dados, a serialização é necessária.

domingo, 11 de agosto de 2013

JDBC



Tipos de Drivers

Tipo 1: Ponte JDBC-ODBC

É o tipo mais simples mas restrito à plataforma Windows. Utiliza ODBC para conectar-se com o banco de dados, convertendo métodos JDBC em chamadas às funções do ODBC. Esta ponte é normalmente usada quando não há um driver puro-Java (tipo 4) para determinado banco de dados, pois seu uso é desencorajado devido à dependência de plataforma.

Tipo 2: Driver API-Nativo

O driver API-Nativo traduz as chamadas JDBC para as chamadas da API cliente do banco de dados usado. Como a Ponte JDBC-ODBC, pode precisar de software extra instalado na máquina cliente.

Tipo 3: Driver de Protocolo de Rede

Traduz a chamada JDBC para um protocolo de rede independente do banco de dados utilizado, que é traduzido para o protocolo do banco de dados por um servidor. Por utilizar um protocolo independente, pode conectar as aplicações clientes Java a vários bancos de dados diferentes. É o modelo mais flexível.

Tipo 4: Driver nativo

Converte as chamadas JDBC diretamente no protocolo do banco de dados. Implementado em Java, normalmente é independente de plataforma e escrito pelos próprios desenvolvedores. É o tipo mais recomendado para ser usado.

Driver API-Nativo

Antes de mais nada deveremos instalar o drive nativo:

Numero aplicação J2EE utilizando tomcat basta descompactar e jogar o arquivo no diretório \common\lib do tomcat.

Para acesso via aplicação J2SE, basta acrescentar o caminho completo do drive na CLASSPATH.

Exemplo Query (Consulta)

 

String driver      = “jdbc:postgresql://3.3.3.132:5432/teste”;
String user        = “teste”;
String senha      = “teste”;
Class.forName("org.postgresql.Driver");
Connection con = DriverManager.getConnection(driver,user,senha);                 
Statement st = con.createStatement();                                  

ResultSet rs = st.executeQuery("select * from stsip_etr");
            while (rs.next())
                        retorno+= String.valueOf(rs.getString(1));
rs.close();                 
st.close();
con.close();

Exemplo Execução (alteração e deleçao)

String driver      = “jdbc:postgresql://3.3.3.132:5432/teste”;
String user        = “teste”;
String senha      = “teste”;
Class.forName("org.postgresql.Driver");          
Connection con = DriverManager.getConnection(driver,user,senha);                                        
Statement st = con.createStatement();
st.executeUpdate(sql);  
st.close();
con.close();

Exemplo de PreparedStatement

String driver      = “jdbc:postgresql://3.3.3.132:5432/teste”;
String user        = “teste”;
String senha      = “teste”;
Class.forName("org.postgresql.Driver");
Connection con = DriverManager.getConnection(driver,user,senha); 
PreparedStatement pSmt = conn.preparedStatement(SQL);
pSmt.setString(1,”manoel”)
pSmt.setInt(2,32)
int retorno= pSmt.executeUpdate();

ResultSetMetaData

Obtem informaçoes sobre o resultset de uma pesquisa, como por exemplo a quantidade de colunas.

ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM TABLE2");
ResultSetMetaData rsmd = rs.getMetaData();
int numberOfColumns = rsmd.getColumnCount();
boolean b = rsmd.isSearchable(1);


Ponte JDBC-ODBC

 
E apenas inserir em DriverManager.getConnection :

Jdbc:odbc:[nome do driver odbc], Ex:

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");                       
Connection con = DriverManager.getConnection("JDBC:ODBC:audioteca");                                             
Statement st = con.createStatement();
ResultSet rs = st.executeQuery("select * from Interpretes");
         while (rs.next()){
            System.out.println(rs.getString("interprete"));
}

Retornando o numero de linhas em uma pesquisa SQL...


 stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
                ResultSet.CONCUR_READ_ONLY);
stmt.executeQuery(sql);
 
rs.last();               
int rows = rs.getRow();        

rs.beforeFirst();

 

quarta-feira, 7 de agosto de 2013

JNA (Java Native Access)



JNA é um framework permite acessos a bibliotecas nativas (DLL em Windows e so em Linux).

 Integrando com Shared Object (Linux)

 Vamos criar um arquivo simples em C que realiza uma soma ou uma subtração de acordo com um parâmetro recebido. O parâmetro recebido é propositalmente do tipo char* para demonstrar a compatibilidade com o tipo String existente no Java, assim como os outros parâmetros.

Segue portanto o código do arquivo calcjna.c :

#include "stdio.h"
#include "strings.h"
#include "calcjna.h"

int calcular(char* op, int arg1, int arg2) {
           int calc = -1;
if(strcmp(op,"soma") == 0) {
calc =  arg1 + arg2;}
else
if(strcmp(op,"subtracao") == 0) {
calc = arg1 - arg2;}
else {
printf("Operacao %s invalida\n", op);
return calc;
}
printf("Operacao de %s. Executada com sucesso!\n", op);
return calc;
} 

Não podemos esquecer de criar o arquivo Header. Segue o código do arquivo calcjna.h : 

int calcular(char* op, int arg1, int arg2); 

Agora para gerarmos a biblioteca compartilhada:

gcc calcjna.c -shared -I. -o libcalcjna.so 

Pronto, criamos nossa biblioteca nativa (Certifique-se de que o nome do objeto criado inicia com lib). Agora vem a parte interessante que é a comunicação da linguagem Java com o código nativo via JNA. Para fazer isso devemos criar uma interface em Java que fará o mapeamento dos tipos. O mapeamento de tipos compatíveis pode ser encontrado aqui sob a sigla "Default Type Mappings".  

Segue o código de nossa interface ICalcJNA.java : 

import com.sun.jna.Library;
public interface ICalcJNA extends Library {
public int calcular(String operacao, int elemento1, int elemento2);
} 

Veja que mapeamos o tipo char* para o tipo String do Java, bem como o tipo int que é o mesmo em ambas linguagens.  

Estamos quase no fim, só falta criar o arquivo responsável pela carga da biblioteca, que terá o nome de CalcJNA.java : 

import com.sun.jna.Native;

public class CalcJNA {
public static void main(String args[]) {
ICalcJNA calc = 
(ICalcJNA) Native.loadLibrary("calcjna", ICalcJNA.class);
int i = calc.calcular("soma", 10, 5);
System.out.println(i); i = calc.calcular("subtracao", 10, 5); System.out.println(i); i = calc.calcular("divisao", 10, 5); System.out.println(i);
}
}

OBS Linux

Devemos  informar somente o nome da biblioteca sem o inicio lib e sem o final .so.

A partir de agora é só compilar e executar o código, caso você não tenha gravado o arquivo jna.jar em algum diretório que o Java o encontre, deveremos informar explicitamente ao compilador onde ele deve buscar as classes que utilizamos, no meu caso o arquivo JAR está no mesmo diretório que estão todos os outros arquivos que criamos aqui. Portanto, vamos compilar:

 javac -cp .:./jna.jar CalcJNA.java

 Após isto é so rodar o programa:

java -cp .:./jna.jar CalcJNA

O resultado deveria ser esse:

Operacao de soma. Executada com sucesso!
15

Operacao de subtracao. Executada com sucesso!
5

Operacao divisao invalida
-1
 

Integrando com Windows (DLL)
 

O objetivo aqui será obter a data e a hora do sistema através de uma biblioteca nativa do sistema operacional, vamos obter essas informações através da DLL KERNEL32.DLL que fica localizada no diretório de instalação do Windows e na subpasta SYSTEM32.
 
1 Passo: Criar nossa interface que é a única parte burocrática na utilização do JNA:

import com.sun.jna.win32.StdCallLibrary;
public interface IKernel32 extends StdCallLibrary {
   void GetSystemTime(DataHoraSistema result);
} 

Podemos notar que existe uma diferença aqui nessa interface, aqui ela não é herança de Library, mas sim de StdCallLibrary. Isso porque essa DLL usa a convenção __stdcall de chamada de métodos, porém na maioria dos casos as bibliotecas serão herança de Library mesmo.

Definimos no código acima a interface de acesso ao método GetSystemTime que recebe um parâmetro do tipo Structure pois o método nativo recebe como parâmetro uma estrutura nativa e que será populada com informações de data e hora do sistema.

Para isso teremos que definir uma classe Java que será herança da classe Structure. Isso só é necessário quando métodos nativos recebem ou devolvem parâmetros do tipo de estruturas nativas. Lembrando que a DLL em questão possui vários outros métodos, mas como utilizaremos apenas um, definimos apenas ele. Salve esse arquivo como IKernel32.java.


2 Passo: Vamos então mapear nossa estrutura Java para trocarmos informações com a biblioteca nativa através dessa estrutura:

 import com.sun.jna.Structure;

 public class DataHoraSistema extends Structure {
   public short wYear;
   public short wMonth;
   public short wDayOfWeek;
   public short wDay;
   public short wHour;
   public short wMinute;
   public short wSecond;
   public short wMilliseconds;
}

Criamos aqui um tipo que é herança de Structure e mapeamos os tipos para short que é o equivalente ao tipo WORD do Windows. Para isso utilizamos a tabela de mapeamento que encontramos aqui como citado no primeiro artigo. Salve como DataHoraSistema.java.

3 Passo: Implemente a interface IKernel32:
 

import com.sun.jna.Native; 

public class Kernel32JNA {
   public static void main(String args[]) {
      IKernel32 lib =
         (IKernel32) Native.loadLibrary("kernel32", IKernel32.class);
      DataHoraSistema time = new DataHoraSistema();
      lib.GetSystemTime(time);
      System.out.println("Data: " + time.wDay +
                         "/" + time.wMonth +
                         "/" + time.wYear);
      System.out.println("Hora: " +
                         time.wHour +
                         ":" +
                         time.wMinute);
   }
}

No código acima apenas obtemos uma instância da biblioteca KERNEL32.DLL através do método loadLibrary do JNA que é quem faz toda a mágica e, a partir daí, trabalhamos com os tipos e métodos fornecidos pela própria biblioteca nativa e que mapeamos na classe DataHoraSistema do Java. 

A partir daí é só a gente compilar:

javac -cp .;jna.jar Kernel32JNA.java

E executar:

java -cp .;jna.jar Kernel32JNA

Resultado:

Data: 5/2/2008
Hora: 13:26

JNI (Java Native Inteface)


 
 
 
JNI, Java Native Interface, é uma suíte de programação que permite código em Java rodando sob uma máquina virtual Java (JVM) chamar e ser chamada por aplicações nativas. Aplicações nativas são programas escritos para plataformas de hardware e sistema operacional específicos. É possível fazer chamadas para C, C++ e Assembly, dentre outras.

C/C++

1- Criar uma aplicação JAVA.

class OlaMundo {
            public native void diga ();

            static {
                        System.loadLibrary("olanativo");
            }
            public static void main (String[] args) {
                        OlaMundo ola = new OlaMundo ();
                        ola.diga();
            }
}

Pode compilar usando javac OlaMundo.java, e após isto gere um arquivo OlaMundo.h, utilizando o comando javah OlaMundo

2- Criamos nossa aplicação em C++ chamada JAVA_OlaMundo_diga e importaremos nossa header OlaMundo.h para dentro dela...

#include <stdio.h>
#include "OlaMundo.h"

JNIEXPORT void JNICALL Java_OlaMundo_diga (JNIEnv * env, jobject jobj){
   printf("ola mundo\n");
}

3- Compilamos e chamamos: java OlaMundo

Desvantagens de se usar JNI:

Perda da portabilidade.

Uma aplicação que usa uma implementação nativa só funcionará para os binários compilados disponíveis e existem muitos conceitos envolvidos para fazer uma aplicação JNI funcionar. É necessário conhecimento em mais de uma linguagem.

Java Client-Server


O modelo cliente-servidor, em computação, é uma estrutura de aplicação distribuída que distribui as tarefas e cargas de trabalho entre os fornecedores de um recurso ou serviço, designados como servidores, e os requerentes dos serviços, designados como clientes.

 A aplicação client server e relizada através de portas Sockets, ela é composta como uma aplicação comum de I/O de quatro partes: open, read, write e close.

Aplicação cliente:
import java.net.*;
import java.io.*;
import java.lang.*;

public class client{
       DataInputStream i1;
       DataInputStream cinput;
       PrintStream coutput;
       Socket clisoc; 

       public client(){
                  try{
                         clisoc = new Socket("127.0.0.1",4321);
                         cinput = new DataInputStream(clisoc.getInputStream());
                         coutput= new PrintStream(clisoc.getOutputStream());
                         i1  = new DataInputStream(System.in);  
                        while(true){
                                   System.out.print("Entre com uma palavra: ");
                                   String str = i1.readLine();
                                   coutput.println(str);   
                                   String str2 = cinput.readLine();
                                   System.out.println("Recebido do servidor: "+str2);
                                   if (str.equals("BYE")){
                                               System.out.println("Disconectado: "+

                                               clisoc.getInetAddress()+":"+clisoc.getPort());
                                               clisoc.close();
                                               System.exit(0);
                                  }
                     }
               }
              catch(Exception e){
                    System.err.print(e);
                    System.exit(1);
              }
}

public static void main(String args[]){
           new client();
           }
}


Aplicação servidora:

import java.net.*;
import java.io.*;
import java.lang.*;

public class server{
 ConexBasica cb;
 public server(int port){
  System.out.println("Server listening in port: "+port);
  cb= new ConexBasica(port);cb.start();
 }
 public static void main(String args[]){
  new server(4321);}
}
class ConexBasica extends Thread{
 int pt;
 ServerSocket ssocket;Conexsec csec;
 public ConexBasica(int port){
  pt = port;
 }
 public void run(){
  try{
   ssocket = new ServerSocket(pt); }
  catch(Exception e){
   System.err.println(e);
   System.exit(1);}
  while (true){
   try{
    Socket clisocket = ssocket.accept();
    csec = new Conexsec(clisocket);
    csec.start();}
   catch(Exception e){} }
 }
}
class Conexsec extends Thread{
 Socket   csk;
 PrintStream  soutput;DataInputStream sinput;
 public Conexsec(Socket s){
  csk = s;
 }
 public void run(){
 System.out.println("Criada conexcao: "+csk.getInetAddress()+":"+csk.getPort());
  try{
   soutput = new PrintStream(csk.getOutputStream());
   sinput = new DataInputStream(csk.getInputStream());
   while(true){
    String str = sinput.readLine();
    soutput.println("Eco do servidor: "+str);
    System.out.println(str);
    if (str.equals("BYE")){
     csk.close();
System.out.println("Disconectado: "+csk.getInetAddress()+":"+csk.getPort()+". Listening...");
     stop();
    }
   }
  }
  catch(Exception e){
   System.err.println(e);
  }
 }
}