DBUnit com HSQLDB + Hibernate + maven

Olá pessoal!

No post de hoje vamos ver como executar nossos unit tests usando o DBunit com HSQLDB em memória, tendo o Hibernate como framework de persistencia e usando o maven. por que isso tudo? Eu passei por uns problemas chatos de configuração que normalmente não temos quando fazemos testes de cada um desses recursos separados, mas, quando tive que colocar tudo na mesma panela, surgiram uns problemas mais chatos para nós, desenvolvedores, estou falando daquelas exceções de não achar o arquivo, exceções genéricas dos frameworks, que nos faz ficar horas e horas googlando, etc.

lets go..

O que vou considerar?

Que você já conhece Hibernate e conhece o DBunit, porém agora pretende rodar seus testes em um projeto do tipo maven e que você tem dois arquivos hibernate.cfg.xml, um para os testes e outro para a aplicação em si.

O problema

Tudo começou quando, ao executar meus testes, simplesmente recebi aquela velha mensagem: cannot open JDBC Connection. Eu disse “como assim? O hibernate.cfg.xml está lá”. Daí comecei a investigar. Um ponto eu já sabia e publiquei aqui nesse troubleshooting: o maven procura o hibernate.cfg.xml em src/main/resources. E para os testes? Ele procura em src/test/resources. Até parece lógico, mas errei aqui e não coloquei meu arquivo de hibernate.cfg.xml de teste nesse local. Porém, veio outro problema: eu tinha renomeado meu arquivo hibernate.cfg.xml para hibernateTest.cfg.xml. Por que? Simplesmente queria ter essa diferença. E deixava assim a configuração nos meus testes:

 protected IDatabaseConnection getConnection() throws Exception {

conn = new DatabaseConnection(new Configuration().configure(“hibernateTest.cfg.xml”)

.buildSettings().getConnectionProvider().getConnection());

return conn;

}

Simplesmente recebia:


 

Dai o que fiz?

Mudei o arquivo para hibernate.cfg.xml e rodei a aplicação e o resultado:

 

Isso me custou umas 3hrs do meu dia. Infelizmente não fui pesquisar porque com o nome diferente do hibernate o maven não encontrava o arquivo, somente com o nome default.

O arquivo do DBunitTest é o mesmo que vimos nos outros post da série, a única diferença é que temos um projeto do tipo “simple maven project”.

Hibernate.cfg.xml para o HSQLDB

<session-factory>

<property name=”hibernate.connection.driver_class”>org.hsqldb.jdbcDriver</property>

<property name=”hibernate.connection.url”>jdbc:hsqldb:mem:db</property>

<property name=”hibernate.connection.username”>sa</property>

<property name=”hibernate.dialect”>org.hibernate.dialect.HSQLDialect</property>

<property name=”hibernate.show_sql”>true</property>

<property name=”hibernate.hbm2ddl.auto”>create-drop</property>

<mapping class=”com.camilolopes.qa.model.dao.bean.Account”/>

</session-factory>

 

Configuração do pom.xml Adicione as dependencias abaixo:

<dependency>

<groupId>hsqldb</groupId>

<artifactId>hsqldb</artifactId>

<version>1.8.0.10</version>

</dependency>

<dependency>

<groupId>javassist</groupId>

<artifactId>javassist</artifactId>

<version>3.12.1.GA</version>

<type>jar</type>

<scope>compile</scope>

</dependency>

<dependency>

<groupId>org.hibernate</groupId>

<artifactId>hibernate-core</artifactId>

<version>3.6.10.Final</version>

<type>jar</type>

<scope>compile</scope>

</dependency>

<dependency>

<groupId>org.dbunit</groupId>

<artifactId>dbunit</artifactId>

<version>2.4.8</version>

<type>jar</type>

<scope>compile</scope>

</dependency>

 

Crie um bean e um teste para persistir o objeto:

Bean

@Entity

@Table(name=”account”)

public class Account {

@Id

@GeneratedValue

@Column(name=”ID”)

private Long id;

@Column(length=20,name=”TYPE”)

private String type;

}

Test

A classe de test deverá estar assim, e omitir o que não mudou do outro arquivo, como a conexão e o load do .xml.

public DBUnitTest() {

try {

session = getSessionFactory().openSession();

getDataSet();

} catch (Exception e) {

e.getMessage();

}

}

public static SessionFactory getSessionFactory() {

sessionFactory = new Configuration().configure().buildSessionFactory();

return sessionFactory;

}

@Test

public void testSave(){

session.beginTransaction();

Account account = new Account();

account.setType(“USER”);

session.save(account);

}

Enfim, é isso ai. Caso precise rodar seus unit tests com maven + hibernate + hsqldb, sem ter dor de cabeça com arquivo de configuração, essa foi a solução que encontrei.

Abracos, see ya!!

Java WebServices com BD

Olá Pessoal,

Dando continuidade aos post sobre webservice neste ultimo desta série, vamos ver como ter uma aplicação que faz pesquisa no banco de dados e vamos disponibilizar essa pesquisa via webservice. Um cliente nosso, vai consumir essa webservice e conseguir pesquisar em nosso banco, então deixar o “hello world” de lado. Ah, vamos usar o Hibernate framework para fazer a consultar no banco.Outro detalhe, não seguir as melhores praticas para criar  DAO genérica, fiz tudo em uma classe, o objetivo aqui não é DAO, Hibernate etc. E sim disponibilizar um web service para que possa ser consumido pelos clientes, que será uma consulta de clientes pelo ID.

Lets go…

Requisitos

  • Java 6 ou mais recente
  • MySql 5
  • Hibernate

Contexto

Se você não entendeu bem o contexto, vou dar um pouco mais de detalhe, antes de começarmos a desenvolver. Vamos ter dois projetos, um que é a nossa aplicação que pesquisa clientes por ID e o outro o projeto do fornecedor que vai consumir a webservice. O nosso banco já está populado com alguns clientes. No nosso caso serão poucos dados apenas o ID e o CPF.

Desenvolvendo

Nosso código será um pouco grande, pois vou incluir parcialmente o código do Hibernate,  também vou considerar que já conhece o framework, sendo assim, não irei explicar código que não seja relacionado webservice. Se tem dúvida com o Hibernate, pode visitar nossa categoria aqui no blog e ver o que temos por lá.  Certifique-se também que você tem uma tabela no banco populada:

A minha tabela chamei de Cliente.

Crie o projeto Java Project aqui chamei de WSDAO.

Não esqueça de adicionar os .jars do Hibernate  & MySQL ao seu projeto.

Vamos começar pelo bean, então crie uma classe cliente conforme abaixo, os getters/setters foram omitidos.

@Table

@Entity

public class Cliente {

      @Id

      @Column(name=”ID_CLIENTE”)

      @GeneratedValue

      private int id;

      @Column

      private long cpf;

//getters/setters omitidos

Agora vamos criar o nosso DAO, para isso crie uma classe conforme abaixo:

public class ClienteDAO {

            private final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();

            private final SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();

      public Session getSession(){

            Session session = threadLocal.get();

            if (session == null) {

                  session = sessionFactory.openSession();

                  threadLocal.set(session);

            }

            return session;

      }

      public Cliente getCliente(int id) {

            Session session = getSession();

            Cliente cliente = new Cliente();

            try{

                  session.beginTransaction();

            String hql = “from Cliente where id=:idvalue “;

            Query query = session.createQuery(hql );

                  query.setInteger(“idvalue”, id);

                  cliente = (Cliente) query.uniqueResult();

            }catch (HibernateException e) {

                  e.printStackTrace();

            }finally{

                  session.close();

            }

            return cliente;

      }

Criando agora o nosso SEI:

@WebService

public interface Service {

      @WebMethod

      Cliente getCliente(int id);

}

Criando SIB

@WebService(endpointInterface=”br.com.camilolopes.ws.sei.Service”)

public class ServiceImpl implements Service {

      private ClienteDAO clienteDAO = new ClienteDAO();

      @Override

      public Cliente getCliente(int id) {

            return clienteDAO.getCliente(id);

      }

}

Publicando o serviço:

public class ClientePublish {

      public static void main(String[] args) {

            Endpoint.publish(“http://localhost:9876/wscliente”, new ServiceImpl());

      }

}

Testando com SOAPUI

            Agora precisamos testar, então suba o serviço rodando a classe ClientePublish(Run → as    → Java Application ) e em seguida abra o SOAPUI, crie um projeto e passe a url do  com o wsdl (no meu caso: http://localhost:9876/wscliente?wsdl)

            Ao adicionar url certamente verá o método getCliente a esquerda na tela da esquerda da ferramenta, click no sinal + e dê dois cliques no request1. Sua tela deve ser conforme a image a seguir:

Na tag <arg0>?</arg0> vamos passar o ID do cliente que queremos buscar, então informe os Ids válidos conforme vimos mais cedo na tabela do DB. Vou informar o ID 1 e ele deve retornar o resultado na aba que está a esquerda. Troque a  ? por 1 e execute clicando no botão submit request (uma seta verde que está na parte superior da tela)

note: lembre-se que seu serviço deve tá publicado, ou seja, a classe que faz o publish deve tá rodando. No caso do exemplo do post chamei ela de ClientePublish.

O resultado é conforme a imagem a seguir:

Observe que temos o resultado no formato XML a direita. E  oque acontece se o ID  não existir? Simplesmente não traz nada. :).

Criando o Cliente para Consumir

Agora vamos criar um cliente que vai conseguir esse nosso webservice  que faz uma pesquisa no banco de dados pelo ID do cliente. Para ficar claro e separar o projeto webservice do cliente, vamos criar um projeto separado, lembrando que uma vez o serviço publicado este projeto cliente que vai consumir o webservice, não necessariamente precisa ser desenvolvido em Java, poderia ser em .NET, PHP etc.

Step 1

Crie um novo projeto Java, o do post chamei de WSDAOConsumer somente para facilitar o entendimento no post.

note: não crie os packages conforme a imagem acima, apenas o projeto por enquanto, beleza?

Step 2

            via prompt de comando acesse o src do projeto

Step 3

            import o wsdl para o projeto:

wsimport -keep -p br.ws.cliente http://localhost:9876/wscliente?wsdl

note: Se você não quiser rodar o comando wsimport verifique se a sua IDE dá suporte  na importação do wsdl de maneira visual e execute, o resultado será o mesmo. Depender da versão do Eclipse que estiver usando você terá o suporte.

Step 4

            crie em um package separado a classe que vai usar as operações do service

public class Consumer {

      public static void main(String[] args) {

            Service service = new ServiceImplService().getServiceImplPort();

                  Cliente cliente = service.getCliente(1);

                  System.out.println(cliente.getId());

                  System.out.println(cliente.getCpf());

      }

}

O resultado é mais simples possível, apenas imprime o resultado no console:

A questão é: “imprime no console, porque o meu projeto é assim, ele usa o prompt para imprimir as coisas que ele consome do web service”.Analise e pense dessa forma com o exemplo acima.Porém, Se fosse um projeto JEE eu poderia exibir isso em uma view JSF em uma tabela ou também não poderia exibir em lugar nenhum, e pegar o resultado do WS e salvar em tabela no meu banco de dados, enfim são N possibilidades que podemos fazer com os dados que estamos consumindo, isso vai está atrelado as regras de negócio do seu projeto. Resolvi trazer essa abordagem, para quem está chegando não ache que para consumir um web service deve rodar em cima de Java Application apenas.

Vou ficando por aqui, espero que vocês tenham gostado dessa  série de posts sobre web service.

Abraços, see ya!!

Mapeando Schemas diferentes Hibernate

olá Pessoal,

O post de hj veremos como ler uma tabela que está em um schema diferente do default do seu projeto usando o Hibernate. Será um post curto e bem prático.
Lets go…

Contexto

A situação aqui é muito simples. Precisamos ler uma tabela que está em outro schema do banco de dados via Hibernate. O que fazer?

Primeiro
Terá que ter o modelo da tabela e criar um bean no seu projeto Java e fazer os devidos mapeamento com base no modelo algo como:

@Entity
@Table(name=”Usuario”, schema=”ereaders”)
public class Usuarios {
@Id
@GeneratedValue
private int id;
@Column
private String nome;
@Column
private String email;
//getters/setters omitidos

Observe onde temos o pulo do gato, no atributo schema da anotação @Table onde informo qual schema usar. Por default é usado o que foi definido no arquivo hibernate.cfg.xml. Por falar nele precisamos atualizar com o novo bean ao <mapping/> :class=”br.com.camilolopes.bean.Usuarios”

note: assuma que seu hibernate.cfg.xml está apontando para um BD diferente. Alguma coisa como:
<property name=”hibernate.connection.url”>jdbc:mysql://localhost/auge</property>

Testando
Podemos checkar se de fato o conteúdo da tabela Usuario do schema ereaders, é o que está sendo lido, para isso, temos o seguinte dado na tabela Usuario:

 

Aqui nos temos os Bds:

DAO
Vou assumir que você já tem seu DAO implementado e inicializando as sessões corretamente, caso tenha dúvida verifique os posts sobre o assunto na categoria de Hibernate do blog. Criei uma classe que vai usar HQL para fazer um select na tabela e em seguida imprimir:

public class UsuariosDAO extends DAO {   
    public List getListUsuarios(){
        begin();
        Session session = getSession();
        String hql = “select us.email from Usuarios us”;
        Query query = session.createQuery(hql);
        List list = query.list();
            return list;
    }
}

Na classe main,vamos colocar isso só para ver o resultado:
public static void main(String[] args) {
        UsuariosDAO usuariosDAO = new UsuariosDAO();
                List<String> listUsuarios = usuariosDAO.getListUsuarios();
        for (String usuarios : listUsuarios) {
            System.out.println(usuarios);
        }
    }

Resultado

 

Enfim, temos dados de uma tabela em outro schema. A linha acima de camilo@ é que habilitei o sql_show no arquivo de configuração do hibernate.cfg.xml.

Problema
Como tudo não são flores, um problema aqui é que você não pode esquecer que o usuario informado no hibernate.cfg.xml deve ter permissão ao menos de leitura das tabelas no outro esquema. Do contrário verá exceções na tela com a mensagem permission denied. Se o usuário for diferente terá que criar uma session com o user que tem permissão.

Vou ficando por aqui, espero que tenham gostado do post. Muito simples não é?
Abraços, see ya!!

Sincronizando dados WorkBench para MySQL

olá Pessoal,

Neste post vou mostrar como sincronizar dados do WorkBench com o MySQL, assim as alterações realizadas no Workbench, causará impacto direto no banco, lembrando que esse recurso não fica de forma default por medida de segurança. O post será bem pequeno e objetivo. Vou considerar que você já tem o workbench instalado e uma base de dados no MySQL. Apesar de para uns parecer um posts para usuários básicos,  mas fazer modelagem de dados é algo que acontece com uma certa frequencia à depender do projeto. E saber usar uma ferramenta de modelagem  não é nada mal.

lets go…

Post Relacionado

Starting…

Mas, você deve está se perguntando e se eu alterar as tabelas no WorkBench estas alterações serão refletidas automaticamente no Banco de Dados? A resposta é não. Para que isso seja possível, precisamos informar ao WorkBench que ele deve passar as alterações para o BD.

O processo é bem semelhante ao que fizemos para importar do MySQL para o WorkBench. Basta ir em DataBase ==> Synchronize Model.

Siga as instruções da ferramenta, porém fique atento apenas para a penúltima tela, pois deve ser informado quais tabelas serão atualizadas e certifique-se de ignore aquelas que não sofreram alterações. Do contrário tudo que estiver no BD, será substituído e perdido. Veja, como ficou a nossa:

Espero que tenham gostado do post, vou ficando por aqui, e até próxima.

See ya! Abraços,

Relatório Ireport + JasperReport com Hibernate

olá Pessoal,

Neste post vou mostrar como gerar um relatório usando Ireport de onde as informações vem do BD. Além disso usaremos o Hibernate para conexão. É bem comum uma aplicação o cliente querer algum tipo de relatório. Para gerar os relatorios vamos usar Ireport e o JasperReport. Fiz uma pesquisa rapida na internet e vi alguns posts eram limitados à criar relatórios sem banco de dados, alguns com banco de dados, porem confusos de entender eu sentir dificuldade de compreender,levando em conta que nunca tivesse visto o assunto. E no “mundo real”, se gera relatório de uma base de dados, que na maioria das vezes é um banco de dados. Bom eu tentarei ser pratico no post e a teorica abordada aqui será o suficiente para saber o que significa se deseja se aprofundar no assunto sugiro usar o velho Google e participar das comunidades ou comprar um livro.

Outro ponto  é que neste post será um Java Project normal, em outro post veremos como fazer isso em JEE em um projeto JSF.

Lets go..

Iniciando

Vou levar em conta, que você já tem um BD e uma tabela de onde deseja extrair a informação. Essa é a minha:

ireportbdus

Requisitos:

Você precisa fazer o download do Ireport. A versão mais recente é 3.7.6 neste momento que escrevo o post.


Configuração

copiar os .jars que estã na pasta ext do Ireport para o projeto Java . Se for JEE, adicionar na pasta lib. Não esquecer do .jar para o banco de dados caso os dados relatório venha de um banco de dados, que é o mais real e comum.

  • commons-beanutils

  • commons-collections

  • commons-digester

  • commons-logging

  • groovy-all

  • iText

  • poi

  • jasperreports


Veja o que é Ireport & JasperReport (de forma simples e direta):

Ireport = é uma especie de IDE para criação do layout do seu relatório, ou seja, que cara vai ter e o que vai ter no seu relatório. E é aqui que fazemos a conexão com o banco de dados e consequentemente as tabelas e onde informamos quais colunas de uma tabela vai aparecer no relatório. Ele gera um arquivo .jrxml que será lido por JasperReport.


JasperReport = É uma API que permite nossa classe Java estabelecer uma “conversa” com o nosso layout-relatório. Isso vem a ser util para que sua aplicação Java, gere relatórios em um único ambiente. O usuário não percebe que foi gerado por algo “fora” Java(isso para aqueles que sabem o que é Java).

Na pratica como acontece:

– o desenvolvedor vai lá e cria o layout do relatório com base no proposito deste e põe logomarca da empresa e os dados que devem aparecer. Não precisa ser um webdesigner para desenhar o layout. E é no Ireport que falamos de onde vem a info se será de um BD ou não.

-No JasperReport apenas setamos onde está o layout .jrxml do Ireport e em seguida informamos e é aqui que informamos para qual tipo vamos exportar o relatório: PDF,XML, HTML, TEXT. Podemos dizer que será gerado um arquivo em um local especifico ou se for um JEE, que vai ser carregado pelo Browser.

Note: os nomes das variaveis da classe devem estar iguais aos nomes dos campos (fields) no layout do relatório.

Mão na massa

Vamos colocar mão na massa por partes:

Parte 1: ir para o Ireport (não vou enumerar porque vai ficar zuado a formatação)

vamos primeiro criar um arquivo no Ireport e seguir as instruções do assistente que é bem simples:

ireportimg1

Na parte de banco de dados basta informar os de conexão do banco.

ireportimg2

Feito isso temos o o relatório na tela e podemos edita-lo. Observe que já foi montando com os dados do banco de dados, ou seja, com os nomes da coluna e nos devidos locais, isso acontece no Ireport mais recente, as vezes antigas não faziam isso.

ireportimg3

Parte 2: No Eclipse

Agora no Eclipse precisamos criar um projeto. Este será um Java Project.

Passos:

-Crie o Bean (os nomes entre o bean e os fields no layout devem ser os mesmos)

-Crie conexão com banco de dados (usamos o Hibernate)

-Crie um método List na classe DAO usando HQL com a query que deseja;

-importar para o projeto do eclipse o arquivo jrxml

-crie a classe main com exportando o relatório


Abaixo veja a estrutura do meu projeto

ireportprojectbdmain

note: é recomendavel colocar o .jrxml em um package para terceiro não ter acesso, mas coloquei fora só para mostrar que é possível rodar fora sem problemas algum.

A classe Bean

  1. @Entity
  2. @Table(name=“tusuario”)
  3. public class Usuario {
  4. @Column
  5. private String nome;
  6. @Column
  7. private String email;
  8. @Id
  9. private int id;
  10. //gets/sets omitidos

Gerando o relatório

Essa é a classe principal que de fato faz gerar o relatório em PDF, pegando o layout definido no Ireport o JasperReport faz a conversão, veja:

  1. public class GerarRelatorio {
  2. public static void main(String[] args) throws JRException,SQLException {
  3. System.out.println(“Gerando relatório…”);
  4. UsuarioDAO usuarioDAO = new UsuarioDAO();
  5. List listaUs = usuarioDAO.listaTodos();
  6. JasperReport pathjrxml = JasperCompileManager.compileReport(“relatorio/reportex.jrxml”);
  7. JasperPrint printReport = JasperFillManager.fillReport(pathjrxml, nullnew JRBeanCollectionDataSource(listaUs));
  8. JasperExportManager.exportReportToPdfFile(printReport, “relatorio/reportex.pdf”);
  9. System.out.println(“Relatorio gerado”);
  10. }

Entendendo o código acima

Minha classe UsuarioDAO: ela retorna todos os usuarios atraves de uma query HQL.

  1. public List listaTodos(){
  2. Query query = getSession().createQuery(“from Usuario”);
  3. List listaUs = query.list();
  4. return listaUs;
  5. }

Note: Informando o JRXML: Link interessante

Na classe relatório precisamos informar onde está o arquivo jrxml(nao esqueca de criar o folder)

  1. JasperReport report = JasperCompileManager.compileReport(“relatorio/reportcamilo.jrxml”);

Dica:

Se o jrxml estiver no mesmo package que a classe que gera o relatório o código acima é valido do contrario, deve ser conforme abaixo:

  1. “../relatorio/reportblog.jrxml”

Passando o DATA SOURCE

O data source nada mais eh que uma lista com os dados que serao inseridos no relatorio.

  1. JasperPrint print = JasperFillManager.fillReport(report, null,new JRBeanCollectionDataSource(listaUS));

obs. No primeiro argumento temos o caminho do layout do relatorio gerado pelo ireport, parametro pode ser null e criamos um data source com o conteudo da lista que tem o resultado HQL

  1. class dao
  2. public List listaUsuario(){
  3. Query query = getSession().createQuery(“from Tusuario”);
  4. List lista = query.list();
  5. return lista;

em outra classe ….
TUsuarioDAO tusuariodao = new TUsuarioDAO();
List listaUS = tusuariodao.listaUsuario();

em outra classe …

  1. TUsuarioDAO tusuariodao = new TUsuarioDAO();
  2. List listaUS = tusuariodao.listaUsuario();

Exportando para um Formato

Para exportar temos metodos para cada formato de exportacao

  1. JasperExportManager.exportReportToPdfFile(print,“relatorio/RelatorioUser.pdf”);

obs. No primeiro argumento temos a variavel que tem o relatorio preenchido e o caminho que deve ser exportado .So rodar a classe main, agora.

Download do Projeto

Vou ficando por aqui espero que tenham gostado do post.

See you next post. 🙂