Aviso: Este post é quase um livro!

Algum tempo atraz, mas precisamente na matéria sobre WindowListener, comentei sobre a lógica necessária para enviar uma Janela Swing para a bandeja do sistema, ou Area de Notificação, ou SystemTray, ou como você gosta de chamar aquele cantinho inferior direito, ao lado do relógio, onde fica um aglomerado de ícones que as vezes nem conhecemos.

Teoricamente tudo é facil, o difícil é apenas implementar a solução ao nosso projeto já finalizado…
Mas vamos parar no pensamento que “tudo é facil”, e seguir em frente com este tutorial que ficou bem grande, e é quase todo código!

Primeiro vamos à lógica necessária:
Se você deseja enviar uma janela para a bandeja do sistema, desista, você nunca vai conseguir isso (ao menos em java), missão impossível.
O que podemos fazer é uma pequena “gambiarra”, invisível aos olhos de meros mortais.
Essa “POG” consiste em:

– Capturar o evento “MINIMIZAR” ou “FECHAR” ou qualquer outra porcaria que você queira.
– Deixar a janela que foi minimizada INVISÍVEL!
– Instanciar uma nova classe que coloca um icone bonitinho ao lado do relógio.
– Colocar um menu flutuante nesse icone (Menu Popup)
– Capturar os eventos de click nos itens deste menu
- Caso o item selecionado seja “Abrir novamente a jenela principal” deve-se deixar o frame principal VISIVEL novamente e “matar” as variáveis utilizadas para criar o icone bonitinho ao lado do relógio.

(mais…)

Realizando um teste básico

O Axis aceita que um Web Service seja chamado via uma requisição HTTP-GET. Portanto, ao digitar um endereço é possível testar o web service. No exemplo deste artigo o endereço é este: http://localhost:8080/axis/Servico.jws?method=soma&valor1=2&valor2=4 .

Como pode-se notar, o endereço é a junção de um namespace, que é o endereço do WebService representado por http://localhost:8080/axis/Servico.jws , a variável method que, como seu nome diz, contém o nome do método que se deseja executar, e uma sequência dos parâmetros deste método. Lembrando que o nome dos parâmetros deve ser o mesmo definido na função da classe.

O resultado da execução é um documento XML com a resposta 6 . Novamente, dependendo do browser não será visivel as tags XML. O XML que retornou na execução está abaixo:

<?xml version=”1.0″ encoding=”UTF-8″?>
<soapenv:Envelope
      xmlns:soapenv=”http://schemas.xmlsoap.org/soap/envelope/”
      xmlns:xsd=”http://www.w3.org/2001/XMLSchema”
      xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”>
<soapenv:Body>
<somaResponse soapenv:encodingStyle=”http://schemas.xmlsoap.org/soap/encoding/”>
<somaReturn xsi:type=”xsd:int”>6</somaReturn>
</somaResponse>
</soapenv:Body>
</soapenv:Envelope>

Criando um cliente em Java para acessar o Servidor

O cliente também é uma classe simples, mas exige conhecimento em algumas classes não tão comuns no dia-a-dia.

As classes Service e Call são classes do Axis , portanto, para compilar e executar esta classe é necessário que todo o diretório lib, encontrado dentro do zip do Axis esteja no CLASSPATH da aplicação.

Visto este detalhe, abaixo encontra-se o arquivo fonte do cliente de Web Service. Esta classe fará a conexão ao Web Service para somar 2 com 4 e irá apresentar o resultado 6 na saída padrão.

import org.apache.axis.client.Service;
import org.apache.axis.client.Call;
public class Cliente {
     public static void main(String[] args) throws Exception {
          // Endereço, local onde encontra-se o Web Service
          String local = “http://localhost:8080/axis/Servico.jws”;
         // Criando e configurando o serviço
          Call call = (Call) new Service().createCall();
         // Configurando o endereço.
          call.setTargetEndpointAddress(local);
          // Marcando o método a ser chamado.
          call.setOperationName(“soma”);
          // Parâmetros da função soma.
          Object[] param = new Object[]{new Integer(2),new Integer(4)};
         // Retorno da Função
          Integer ret = (Integer)call.invoke(param);
         // Imprime o resultado: ret = 2 + 4.
          System.out.println(“Resultado da soma : “ + ret);
     }
}

Este código está dentro de um arquivo chamado Cliente.java, após compilar e executar esta classe exibirá o resultado ” Resultado da soma: 6 “ como desejado.

O framework do Axis trata a primitiva int e a classe wrapper Integer como sendo iguais. Portanto, tanto faz usar uma ou outra. Neste exemplo, foi criado o Web Service com dois parâmetros int e aqui no cliente estamos usando dois parâmetros Integer .

Como pode-se notar, o framework do Axis abstrai qualquer trabalho com XML, evitando que o desenvolvedor necessite conhecer a sintaxe do XML do SOAP.

 

E com isso, chegamos ao fim deste tutorial, boa sorte no desenvolvimento do seu webservice!

Implementando um Web Service simples

O objetivo é aprender, então será criado um serviço bem simples. O serviço é a soma de duas variáveis inteiras retornando o resultado. Este exemplo poderá servir para qualquer outra implementação. Abaixo está a classe implementada. O nome do arquivo é Servico.java:

public class Servico {
      public int soma(int valor1, int valor2) {
            return valor1 + valor2;
      }
}

Agora só falta disponibilizá-lo no nosso servidor para o mundo acessar. E, para fazer isso, deve-se alterar o nome do arquivo de Servico.java para Servico.jws, coloca-lo no diretório: CATALINA_HOME / webapps / axis / e iniciar o servidor, se ele já não estiver iniciado. Se já estiver iniciado, o seu Web Service está publicado.

Os arquivos. jws são lidos pelo Axis e representam Java Web Services. O Axis se baseará nesses arquivos (. jws) para criar os arquivos de definição WSDL. Todos os métodos públicos existentes nessas classes serão automaticamente disponibilizados para terceiros.

Criar documentos XML é demorado e, muitas vezes, chato. Gerar o WSDL é uma característica muito relevante na escolha de uma implementação de SOAP e o Axis é um dos poucos frameworks que conseguem fazer essa façanha de maneira transparente para o desenvolvedor. É por esse motivo que ele é altamente recomendado na construção de Web Services.

Para acessar o Web Service criado basta abrir um navegador e ir ao endereço: http://localhost:8080/axis/Servico.jws . Da mesma forma que os outros dois Web Services foram vistos, este também terá um link para ver a especificação WSDL, e novamente poderá ser visto ou não dependendo do seu navegador.

O arquivo WSDL da classe Servico ficará como abaixo:

<?xml version=”1.0″ encoding=”UTF-8″?>
<wsdl:definitions targetNamespace=”http://localhost:8080/axis/Servico.jws”   
       xmlns=”http://schemas.xmlsoap.org/wsdl/”   
       xmlns:apachesoap=”http://xml.apache.org/xml-soap”   
       xmlns:impl=”http://localhost:8080/axis/Servico.jws”   
       xmlns:intf=”http://localhost:8080/axis/Servico.jws”   
       xmlns:soapenc=”http://schemas.xmlsoap.org/soap/encoding/”   
       xmlns:wsdl=”http://schemas.xmlsoap.org/wsdl/”   
       xmlns:wsdlsoap=”http://schemas.xmlsoap.org/wsdl/soap/”   
       xmlns:xsd=”http://www.w3.org/2001/XMLSchema”>  
    <wsdl:message name=”somaRequest”>  
<wsdl:part name=”valor1″ type=”xsd:int”/>  
<wsdl:part name=”valor2″ type=”xsd:int”/>  
   </wsdl:message>  
   <wsdl:message name=”somaResponse”>  
<wsdl:part name=”somaReturn” type=”xsd:int”/>  
   </wsdl:message>  
   <wsdl:portType name=”Servico”>  
     <wsdl:operation name=”soma” parameterOrder=”valor1 valor2″>  
<wsdl:input message=”impl:somaRequest” name=”somaRequest”/>  
       <wsdl:output message=”impl:somaResponse” name=”somaResponse”/>  
     </wsdl:operation>  
   </wsdl:portType>  
<wsdl:binding name=”ServicoSoapBinding” type=”impl:Servico”>  
<wsdlsoap:binding style=”rpc” transport=”http://schemas.xmlsoap.org/soap/http”/>  
     <wsdl:operation name=”soma”>  
       <wsdlsoap:operation soapAction=”"/>  
       <wsdl:input name=”somaRequest”>  
         <wsdlsoap:body encodingStyle=”http://schemas.xmlsoap.org/soap/encoding/”   
             namespace=”http://DefaultNamespace” use=”encoded”/>  
       </wsdl:input>  
       <wsdl:output name=”somaResponse”>  
         <wsdlsoap:body encodingStyle=”http://schemas.xmlsoap.org/soap/encoding/”   
             namespace=”http://localhost:8080/axis/Servico.jws” use=”encoded”/>  
       </wsdl:output>  
     </wsdl:operation>  
   </wsdl:binding>  
   <wsdl:service name=”ServicoService”>  
<wsdl:port binding=”impl:ServicoSoapBinding” name=”Servico”>  
<wsdlsoap:address location=”http://localhost:8080/axis/Servico.jws”/>  
     </wsdl:port>  
   </wsdl:service>  
</wsdl:definitions>  

 

Analisar este arquivo é essencial para entender a profundidade da implementação. Uma das linhas mais importantes para este arquivo é a 19ª linha, onde define-se o nome do método e o nome de seus parâmetros. Eles deverão ser de conhecimento público para que as interfaces cliente consigam se comunicar com o Web Service.

O que são Controladores ou Modificadores de Acesso?
Com certeza você já os viu, aqui mesmo neste blog. O projeto JSF, jReMSN, Hibernate e até mesmo o projeto Webservice estão cheios deles, mas o que são?

  • default
  • public
  • private
  • protected
  • final
  • abstract

Como pode ver, essas são palavras que sempre nos acompanham nas declarações de classes, métodos e variáveis, aqui vamos ver uma breve descrição de cada uma.

(mais…)

Passo 1
(Este tutorial foi desenvolvido por Cleber Calvi)

 

Gravação de Dados!

Vamos criar a nossa tela (simples) onde pegaremos os dados a serem registrados na base de dados. Ex:

Mantendo um padrão de desenvolvimento, na pasta Source teremos as seguintes camadas:

View > beans;
Service > camada responsável por fazer a comunição entre a view e a dao, fazendo tratamentos e conversões de dados, passando os dados de maneira clara para ambas as camadas;
DAO > camada responsável por trabalhar com a base de dados.

 

Criaremos uma base de dados, nela criaremos uma tabela e a seguinte stored procedure:

create procedure gravar
  @nome varchar(20),
  @idade decimal(10,0)
  AS
  if exists (select nome from dados where nome=@nome)
    begin
       select ‘D’
  end
  else
    begin
      insert into dados
      values (@nome, @idade)
      select ‘O’
end

Obs.: lembrando que essa é uma procedure simples e que devemos evitar clausulas where comparando “Strings”.

Criada nossa procedure, vamos as classes Java.
Criaremos no bean o seguinte método:

public String gravar(){
   String retorno=null;
   String status;
   status = service.gravar(this.nome, this.idade);
   if(status.equals(“D”) || status.equals(“F”)){
      retorno = “falha”;
   }else{
      retorno = “sucesso”;
   }
   return retorno;
}

 

Agora iremos criar a classe service que deverá ficar semelhante ao código abaixo:

package br.com.web.control.service;
import br.com.web.control.dao.HibernateDAO;

public class HibernateService{
       private HibernateDAO dao = new HibernateDAO();
       //Construtor
       public HibernateService(){
       }
       public String gravar(String nome, int idade){
          String retorno;
          try{
             retorno = dao.gravar(nome, idade);
          }catch (Exception e) {
             retorno = “E”;
          }
       return retorno;
       }
}

Obs.: lembrando que o package e o importe irão variar de acordo com a estrutura e nomes do seu projeto.

E finalmente a classe DAO:

package br.com.web.control.dao;
import org.hibernate.Query;
import org.hibernate.Transaction;
import org.hibernate.classic.Session;

public class HibernateDAO{
    //Objeto para manuseio da classe de Conexao
    Conexao conexao = new Conexao();

    //Construtor
    public HibernateDAO(){
    }

    public String gravar(String nome, int idade) throws Exception{
        Session session = getConexao().getSession();
        String retorno = null;
        Query query = null;
        try{
           Transaction trans = session.beginTransaction();
           query = session.getNamedQuery(“gravar”);
           query.setString(0, nome);
           query.setInteger(1, idade);
           retorno = String.valueOf(query.uniqueResult());
           trans.commit();
        }catch(Exception he) {
           throw new Exception();
        } finally{
           session.close();
        }
        return retorno;
    }

    public Conexao getConexao() {
        return conexao;
    }

    public void setConexao(Conexao conexao) {
        this.conexao = conexao;
    }
}

E a classe conexão:

package br.com.web.control.dao;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;

public class Conexao {
    //Objeto que irá conter a configuração de conexão
    private SessionFactory factory;
    //Método construtor
    public Conexao(){ };

    /* Método que configura a conexão com o hibernate
    * abre e retorna uma sessão */
    public Session getSession(){
        this.factory = new Configuration().configure().buildSessionFactory();
        Session session = this.factory.openSession();
        return session;
    }
}

 

Bom, até agora muito código e pouca explicação né! Vamos agora explicar um pouco o que foi feito.

O bean é responsável por pegar os dados da tela e enviar para a camada service, ao receber os dados de volta ele irá verificar para qual tela ele deve direcionar a aplicação através do status, que nada mais é que o retorno da classe Service.

A camada service está pegando os dados e enviando para a camada DAO, caso haja algum erro na camada DAO, a service irá tratar esse erro mandando uma mensagem de status “F” que trataremos como erro, caso não dê problema apenas repassa o valor recebido da stored procedure.

A camada DAO é responsável por toda a parte de base de dados, para isso criamos a classe “dao” que irá receber os valores da service, abrir uma sessão através da classe “Conexão” (Session session = getConexao().getSession();), montar e executar a query (Transaction trans = session.beginTransaction(); query = session.getNamedQuery(“gravar”); query.setString(0, nome); query.setInteger(1, idade); retorno = String.valueOf(query.uniqueResult()); trans.commit();) .

A classe Conexão apenas cria a sessionFactory baseado no arquivo hibernate.cfg.xml.

Porém para que tudo isso funcione ainda é necessário criar o “hbm.xml” que terá como primeiro nome, o mesmo que foi dado a sua base de dados, nesse caso “HBM.hbm.xml”.

<?xml version=“1.0″ encoding=“UTF-8″?>
<!DOCTYPE hibernate-mapping PUBLIC “-//Hibernate/Hibernate Mapping DTD//EN”
     “http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd”>
<!– ************************************************************************************************ –>
<!– Mapeamento de Stored Procedures que usamos na aplicalção –>
<!– ************************************************************************************************ –>
<hibernate-mapping auto-import=”true” default-lazy=”false”>
      <sql-query name=“gravar” callable=“true”>
            <return-scalar column=“mensagem” type=“string” />
            { call gravar(?,?) }
      </sql-query>
</hibernate-mapping>

 

Nesse arquivo é que serão mapeadas as procedures que serão chamadas e seus retornos. No caso da gravação onde teremos apenas uma mensagem, o mapeamento é simples como o apresentado acima.

Próxima Página »