Requisitos :
- Netbeans 7.2
- spring-3.2.0.M2
- estar com o banco mysql springlessons, e a tabela contato criada. ver lição 4,5 ou 6
- Lib XStream , para manipular arquivos XML .
- Ter lido :
Posts Anteriores :
JSNBTut - Lesson 01 - introdução ao Spring
JSNBTut - Lesson 02 - introdução ao gerenciamento de dependências no SpringJSNBTut - Lesson 03 - acessando banco de dados Mysql com beans e injeção de dependências
JSNBTut - Lesson 04 - outro jeito rápido de utilizar o Spring e Mysql sem utilizar Arquivos XML.
JSNBTut - Lesson 05 - comparação entre as implementações e introdução ao Swing. Jtable + DefaultTableModel e implementação de uma TableModel, ...
Obrigatório:
JSNBTut - Lesson 06 - implementando um CRUD ao exemplo , que é o projeto que continuaremos neste post.
Mais abaixo forneço o Projeto do NB p/ acompanhar essa lição SpringLesson07-Base
Durante o desenvolvimento do projeto é normal fazer o programa escrever no console p/ testar valores e acompanhar a execução, por isso deixo alguns trechos de código comentado nos arquivos.
Este é o 7º da série , o objetivo deste post é implementar algumas melhorias no projeto, antes de concluir essa parte do tutorial de Spring.
Melhorias no projeto :
- 1ª Validação do formulário de edição usando o Spring, neste caso , só temos 2 campos, mas e se fossem vários??
- 2ª Splash Screen
- 3ª Tema
- 4ª Exportação de arquivo XML,CSV
- 5ª Importação de arquivo XML,CSV
- 6ª Tirar o projeto do NB, permitindo que ele rode em JVMs** que estejam na mesma rede onde está o banco de dados :
- 7ª Implementar a toda a parte WEB da aplicação
** Quando digo JVMs, penso em OSX, Linux, Windows, etc. utilizando o client java, e fazer uma interface web e no server (com rich faces,servlets e struts) p/ quem não quer ou não tem java , e uma app p/ o Android e outra p/ o Iphone (que é o que tenho na rede aqui, WII e PS2 não conta,rs)
Rede Local : Servidor Linux com o mysql, um apache TomCat (webServices e Servlets), e um samba p/ compartilhar a aplicação na rede local.
Bom, após algumas refatorações e acertos básicos de layout
Download do projeto NB
SpringLesson07-Base
Vamos começar :
Verifique se o projeto está rodando e ...
1) Implementando a validação com o Spring:
Não é necessário adicionar libs por enquanto, o que utilizaremos do Spring já está no projeto, no arquivo spring-context-3.2.0.M2.jar![]() |
Figura 01 - Classes do Spring-context |
I) Vamos criar uma classe que implementa org.springframework.validation.Validator, vou chamá-la de ContatoValidator dentro de um novo package springlesson07.validators
![]() |
Figura 02 - Nova classe ContatoValidator |
II) adicione o texto implements Validator na declaração da classe,
III) Aceite as sugestões do NB de :
- importar as libs necessárias
- implementar os metodos abstratos
Codigo da classe ContatoValidator, essa implementação valida apenas o objeto Contato
package springlesson07.validators; import org.springframework.validation.Errors; import org.springframework.validation.ValidationUtils; import org.springframework.validation.Validator; import springlesson07.model.Contato; public class ContatoValidator implements Validator { @Override public boolean supports(Class<?> clazz) { return Contato.class.equals(clazz); } @Override public void validate(Object obj, Errors errors) { Contato C = (Contato) obj; // esse abaixo também funciona , apenas p/ mostrar // if (C.getNome()==null || C.getNome().trim().length()==0){ // errors.rejectValue("nome", "nome.required", "Nome é obrigatório"); // // } ValidationUtils.rejectIfEmptyOrWhitespace(errors, "nome", "nome.empty","Nome é obrigatório"); ValidationUtils.rejectIfEmptyOrWhitespace(errors, "telefone", "telefone.empty","Telefone é obrigatório"); // if (errors.hasErrors()){ // System.out.println(errors); // } }
2) Chamando o validador no form de edição do contato
I) No springlesson07.view.contato.frameEditaContato.java vamos modificar a função
private void salvarContato(), observe que a solução de validação manual está comentada e a explicação coloquei em etapas .
private void salvarContato(), observe que a solução de validação manual está comentada e a explicação coloquei em etapas .
private void salvarContato() { Contato C = new Contato(); //Solução 1 : validação manual // String preMessage = "Verifique os seguintes erros:\n"; // String message = ""; // // if ("".equals(jTFNome.getText())) { // message += "- Nome deve ser preenchido \n"; // } // System.out.println(message.length()+""); // if (message.length() == 0) { //Solucao 2 - com o Spring // etapa 1 - Carga no objeto if ("".equals(jTFId.getText())) { C.setId(0); } else { C.setId(Integer.parseInt(jTFId.getText())); C.setNome(jTFNome.getText()); C.setTelefone(jTFTelefone.getText()); } //etapa 2 chama nosso validador de Pessoa ContatoValidator CV = new ContatoValidator(); //etapa 3 criamos um objeto result passando o nosso Contato após a carga BeanPropertyBindingResult result = new BeanPropertyBindingResult(C, "Contato"); //etapa 4 chamamos o validador do spring , que pode ou não conter error ValidationUtils.invokeValidator(CV, C, result); //etapa 5 - se não tiver erros entra no bloco que salva if (result.getErrorCount() == 0) { this.contato = C; try { this.getDao().salvar(this.getContato()); System.out.println("Salvando Contato:" + C.getNome()); this.getFlC().atualizaGrade(); this.dispose(); } catch (java.lang.NullPointerException npe) { System.out.println("Erro ao Salvar o Contato."); Logger.getLogger(frameEditaContato.class.getName()).log(Level.SEVERE, null, npe); } } else { //etapa 6 - se tiver error começa a mostrar no console System.out.println("Total de erros : " + result.getErrorCount()); System.out.println("-------------------------------------------------"); //etapa 7 - String p/ conter os erros e mostrar num jOptionPane p/ o usuário String errosGui=""; //etapa 8 - criamos uma lista p/ conter os erros List<ObjectError> allObjectErrors = result.getAllErrors(); //etapa 9 varremos os erros for (ObjectError objectError : allObjectErrors) { if (objectError instanceof FieldError) { FieldError fieldError = (FieldError) objectError; System.out.println("O campo é: " + fieldError.getField()); } System.out.println("Codigo " + Arrays.asList(objectError.getCodes()).toString()); System.out.println("Codigo de erro: " + objectError.getCode()); System.out.println("Mensagem Default: " + objectError.getDefaultMessage()); System.out.println(); errosGui+="- " + objectError.getDefaultMessage()+ "\n"; } // fim da etapa 9 System.out.println("-------------------------------------------------"); // etapa 10 - Informando o usuário JOptionPane.showMessageDialog(null, "Erros ao salvar.Mais detalhes, veja o console.\n" + errosGui ); } // } else { // JOptionPane.showMessageDialog(null, preMessage + message); // } } // ao final sua classe deve conter esses imports : import java.util.Arrays; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JOptionPane; import org.springframework.validation.BeanPropertyBindingResult; import org.springframework.validation.FieldError; import org.springframework.validation.ObjectError; import org.springframework.validation.ValidationUtils; import springlesson07.dao.ContatoDAO; import springlesson07.model.Contato; import springlesson07.validators.ContatoValidator;
II) Teste o programa : Tente criar um novo Contato e salvar sem preencher nada:
o resultado deve ser esse
Observe o output no console do NB :
![]() |
Figura 03 - Teste com validação do Spring |
Observe o output no console do NB :
run: Sep 23, 2012 2:34:25 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@669980d5: startup date [Sun Sep 23 14:34:24 BRT 2012]; root of context hierarchy Sep 23, 2012 2:34:25 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions INFO: Loading XML bean definitions from class path resource [beans-definitions.xml] Sep 23, 2012 2:34:25 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@5470be88: defining beans [dataSource,jdbcTemplate,ContatoDao]; root of factory hierarchy Sep 23, 2012 2:34:25 PM org.springframework.jdbc.datasource.DriverManagerDataSource setDriverClassName INFO: Loaded JDBC driver: com.mysql.jdbc.Driver Sep 23, 2012 2:34:26 PM org.springframework.jdbc.datasource.SingleConnectionDataSource initConnection INFO: Established shared JDBC Connection: com.mysql.jdbc.JDBC4Connection@63779885 Total de erros : 2 ------------------------------------------------- O campo é: nome Codigo [nome.empty.Contato.nome, nome.empty.nome, nome.empty.java.lang.String, nome.empty] Codigo de erro: nome.empty Mensagem Default: Nome é obrigatório O campo é: telefone Codigo [telefone.empty.Contato.telefone, telefone.empty.telefone, telefone.empty.java.lang.String, telefone.empty] Codigo de erro: telefone.empty Mensagem Default: Telefone é obrigatório -------------------------------------------------
3) Adicionando o tema :
Podemos utilizar os pacotes que o Java já tem para dar uma interface mais elegante ao nosso programa :I) Para isso , vamos criar uma classe Tema:
![]() |
Figura 04 - Nova Classe p/ utilizar um Tema |
essa classe fica assim :
package springlesson07.utils; import com.sun.java.swing.plaf.gtk.GTKLookAndFeel; import com.sun.java.swing.plaf.motif.MotifLookAndFeel; import com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel; import com.sun.java.swing.plaf.windows.WindowsLookAndFeel; import java.awt.Component; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import javax.swing.plaf.metal.MetalLookAndFeel; public class Tema { int tema; public Tema() { } public int getTema() { return tema; } public void setTema(int tema) { this.tema = tema; } // public final void setTheme(int numTema, JRootPane rootPane) { // se fosse com MDI public final void setTheme(int numTema, Component rootPane) { setTema(numTema); try { System.out.println("Antigo: " + UIManager.getLookAndFeel()); switch (numTema) { case 1: UIManager.setLookAndFeel(new NimbusLookAndFeel()); break; case 2: UIManager.setLookAndFeel(new MotifLookAndFeel()); break; case 3: UIManager.setLookAndFeel(new WindowsLookAndFeel()); break; case 4: UIManager.setLookAndFeel(new MetalLookAndFeel()); break; case 5: UIManager.setLookAndFeel(new GTKLookAndFeel()); break; default: break; } System.out.println("Novo: " + UIManager.getLookAndFeel()); // // Update the ComponentUIs for all Components. This // // needs to be invoked for all windows. SwingUtilities.updateComponentTreeUI(rootPane); } catch (UnsupportedLookAndFeelException ulfe) { // ulfe.printStackTrace(); System.out.println("nao suportado"); } catch (java.lang.NoClassDefFoundError ncdf) { // ncdf.printStackTrace(); System.out.println("nao disponivel"); } } }
Se estivessemos usando uma aplicação MDI com a classe jDesktop, ao aplicar o tema no pai as filhas já herdam, mas como não estamos fazendo assim : precisamos chamar o tema em cada janela :
no package view
II) no arquivo frameListaContatos vamos criar uma função setTema e chamá-la no contrutor:
public final class frameListaContatos extends javax.swing.JFrame { private ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-definitions.xml"); private ContatoDAO dao = (ContatoDAO) ctx.getBean("contatoDao"); private ContatoTableModel tableModel = new ContatoTableModel(dao.listar()); private Contato contatoAtivo; private frameEditaContato janelaEdicao; /** * Creates new form frameListaContatos */ public frameListaContatos() { initComponents(); carregaTabela(); setJanelaEdicao(new frameEditaContato(this, getDao())); setTema(1); } public void setTema(int tema) { Tema T = new Tema(); T.setTheme(tema, rootPane); } }
III) no arquivo frameEditaContato vamos criar uma função setTema e chamá-la no contrutor:
public final class frameEditaContato extends javax.swing.JFrame { private frameListaContatos flC; private ContatoDAO dao; private Contato contato; //novo construtor public frameEditaContato(frameListaContatos flC, ContatoDAO daoInformed) { initComponents(); this.flC = flC; this.dao = daoInformed; this.contato = new Contato(); // que já possui um id=0 setTema(); } public final void setTema() { Tema T = new Tema(); T.setTheme(1, SwingUtilities.getRootPane(this)); } }
Observe que as classes ganharam o modificador final
4) Teste o programa e veja se aplicou o tema nas duas janelas
![]() |
Figura 05 - Tema implementado |
5) Implementando Exportação arquivos XML.
I) Vamos adicionar 2 botões a nossa Lista de Contatos springlesson07.view.contato.frameListaContatos.java
![]() |
Figura 06 - Adicionando os botões p/ importar/exportar XML |
Imagens :
O spring fornece uma interface p/ trabalhar com o Xstream org.springframework.oxm.xstream.XStreamMarshaller que me levou ao XStream, mas veremos esse pacote numa lição mais a frente (web)
![]() |
Figura 07 - Documentação do Spring |
II ) baixe o Xstream, e após baixar o Binary distribution: , crie uma pasta components dentro do seu projeto e coloque ali os arquivos : xstream-1.4.3.jar e sua dependencia : xmlpull-1.1.3.1.jar
![]() |
Figura 08 - Obtendo o XStream |
III) e adicione as libs no projeto :
![]() |
Figura 09 - Adicionando a lib XStream ao projeto |
Veja que simples fica (1º vamos implementar a solução, depois vamos organizar o código para facilitar a explicação)
Exportar XML : Solução 1
IV) No arquivo springlesson07.view.contato.frameListaContatos.java, clique duas vezes no botão exportar XML : e escreva a função exportarXML(); e deixe o NB criar a função
![]() |
Figura 10 - Utilizando o NB p/ gerar o código da função exportarXML |
private void jBtExportXMLActionPerformed(java.awt.event.ActionEvent evt) { exportarXML(); } private void exportarXML() { XStream xstream = new XStream(); List<Contato> listaContato = this.getDao().listar(); xstream.alias("contato", Contato.class); String xmlOut = xstream.toXML(listaContato); System.out.println("Gerando arquivo XML:"); System.out.println(xmlOut); }Observe o import
import com.thoughtworks.xstream.XStream;
![]() |
Figura 11 - Veja a String p/ o Arquivo XML no console do NB |
7) Alterando o jeito de exportar o XML
Para não fazer o usuário ter q copiar do console e colar em um novo arquivo, vamos criar esse arquivo:com o nome contatos_DIA_MES_ANO.xml e ao gerar o arquivo , vamos abri-lo p/ o usuário (função openFile() que criaremos abaixo). Isso dependerá de qual o programa que o seu SO usará para abrir o arquivo. No meu caso abriu com o Xcode.
I) Alterando a função exportarXML e adicionando a função openFile (solução 1)
No arquivo springlesson07.view.contato.frameListaContatos.java
private void exportarXML() { XStream xstream = new XStream(); List<Contato> listaContato = this.getDao().listar(); xstream.alias("contato", Contato.class); String xmlOut = xstream.toXML(listaContato); System.out.println("Gerando arquivo XML:"); // System.out.println(xmlOut); // p/ gerar o nome do arquivo Calendar calendar = Calendar.getInstance(); String dataHojeFormatada = calendar.get(calendar.DATE) + "/" + (calendar.get(calendar.MONTH) + 1) + "/" + calendar.get(calendar.YEAR) +" "+ calendar.get(calendar.HOUR_OF_DAY) + ":" + + calendar.get(calendar.MINUTE) + ":" + + calendar.get(calendar.SECOND); String dataNomeArquivo = dataHojeFormatada.replace(" ", "_").replace(":", "_").replace("/", "_"); String nomeArquivo = "contatos_" + dataNomeArquivo + ".xml"; // p/ salvar o arquivo solução 1 try { FileOutputStream fs = new FileOutputStream(nomeArquivo); xstream.toXML(listaContato, fs); fs.close(); System.out.println("Arquivo gerado:" + nomeArquivo); //abre o arquivo p/ o usuário fora do programa openFile(new File(nomeArquivo)); } catch (FileNotFoundException ex) { Logger.getLogger(frameListaContatos.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(frameListaContatos.class.getName()).log(Level.SEVERE, null, ex); } } public void openFile(File document) throws IOException { Desktop dt = Desktop.getDesktop(); dt.open(document); }
Observe os imports
import com.thoughtworks.xstream.XStream; import java.awt.Desktop; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.Calendar; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JOptionPane; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import springlesson07.dao.ContatoDAO; import springlesson07.model.Contato; import springlesson07.model.ContatoTableModel; import springlesson07.utils.Tema;
Teste o programa, e o resultado deve ser :
![]() |
Figura 12 - Exportando nosso 1º XML observe que o root node é list |
e no output temos :
run: Sep 24, 2012 12:33:38 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@bd10a5c: startup date [Mon Sep 24 12:33:38 BRT 2012]; root of context hierarchy Sep 24, 2012 12:33:38 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions INFO: Loading XML bean definitions from class path resource [beans-definitions.xml] Sep 24, 2012 12:33:39 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@6401d98a: defining beans [dataSource,jdbcTemplate,ContatoDao]; root of factory hierarchy Sep 24, 2012 12:33:39 PM org.springframework.jdbc.datasource.DriverManagerDataSource setDriverClassName INFO: Loaded JDBC driver: com.mysql.jdbc.Driver Sep 24, 2012 12:33:40 PM org.springframework.jdbc.datasource.SingleConnectionDataSource initConnection INFO: Established shared JDBC Connection: com.mysql.jdbc.JDBC4Connection@31e46a68 Antigo: [Aqua Look and Feel for Mac OS X - com.apple.laf.AquaLookAndFeel] Novo: [Nimbus Look and Feel - com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel] Antigo: [Nimbus Look and Feel - com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel] Novo: [Nimbus Look and Feel - com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel] Gerando arquivo XML: Arquivo gerado:contatos_24_9_2012_12_33_55.xml
Arquivo xml contatos_24_9_2012_12_33_55.xml :
<list> <contato> <id>3</id> <nome>Cliente 1</nome> <telefone>2222-3333</telefone> </contato> <contato> <id>4</id> <nome>Cliente 2 renomeado de novo</nome> <telefone>4444-5555</telefone> </contato> </list>
II) Alterando a função exportarXML (solução 2)
No arquivo springlesson07.view.contato.frameListaContatos.java
private void exportarXML() { XStream xstream = new XStream(); List<Contato> listaContato = this.getDao().listar(); xstream.alias("contato", Contato.class); String xmlOut = xstream.toXML(listaContato); System.out.println("Gerando arquivo XML:"); // System.out.println(xmlOut); // p/ gerar o nome do arquivo Calendar calendar = Calendar.getInstance(); String dataHojeFormatada = calendar.get(calendar.DATE) + "/" + (calendar.get(calendar.MONTH) + 1) + "/" + calendar.get(calendar.YEAR) +" "+ calendar.get(calendar.HOUR_OF_DAY) + ":" + + calendar.get(calendar.MINUTE) + ":" + + calendar.get(calendar.SECOND); String dataNomeArquivo = dataHojeFormatada.replace(" ", "_").replace(":", "_").replace("/", "_"); String nomeArquivo = "contatos_" + dataNomeArquivo + ".xml"; // p/ salvar o arquivo solução 1 // try { // FileOutputStream fs = new FileOutputStream(nomeArquivo); // // xstream.toXML(listaContato, fs); // fs.close(); // // System.out.println("Arquivo gerado:" + nomeArquivo); // //abre o arquivo p/ o usuário fora do programa // openFile(new File(nomeArquivo)); // } catch (FileNotFoundException ex) { // Logger.getLogger(frameListaContatos.class.getName()).log(Level.SEVERE, null, ex); // } catch (IOException ex) { // Logger.getLogger(frameListaContatos.class.getName()).log(Level.SEVERE, null, ex); // // } // p/ salvar o arquivo solução 2 try { Writer writer; writer = new FileWriter(nomeArquivo); ObjectOutputStream out = xstream.createObjectOutputStream(writer); //adicionando um header writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); for (Contato C : listaContato) { out.writeObject(C); } out.close(); System.out.println("Arquivo gerado:" + nomeArquivo); openFile(new File(nomeArquivo)); } catch (IOException ex) { Logger.getLogger(frameListaContatos.class.getName()).log(Level.SEVERE, null, ex); } } public void openFile(File document) throws IOException { Desktop dt = Desktop.getDesktop(); dt.open(document); }
Observe os imports
import com.thoughtworks.xstream.XStream; import java.awt.Desktop; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.ObjectOutputStream; import java.io.Writer; import java.util.Calendar; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JOptionPane; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import springlesson07.dao.ContatoDAO; import springlesson07.model.Contato; import springlesson07.model.ContatoTableModel; import springlesson07.utils.Tema;
![]() | |
|
run: Sep 24, 2012 12:54:50 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@669980d5: startup date [Mon Sep 24 12:54:50 BRT 2012]; root of context hierarchy ...... Gerando arquivo XML: Arquivo gerado:contatos_24_9_2012_13_15_11.xmlArquivo xml contatos_24_9_2012_13_15_11.xml :
<?xml version="1.0" encoding="UTF-8"?> <object-stream> <contato> <id>3</id> <nome>Cliente 1</nome> <telefone>2222-3333</telefone> </contato> <contato> <id>4</id> <nome>Cliente 2 renomeado de novo</nome> <telefone>4444-5555</telefone> </contato> </object-stream>
Funcionamento parecido, gerou o arquivo XML , mas dentro de uma tag <object-stream> e adicionamos um header ao arquivo
Para deixar esse arquivo XML no jeito faremos uma modificação em nosso objeto out assim:
ObjectOutputStream out = xstream.createObjectOutputStream(writer,"contatos");
Teste o programa, e o resultado deve ser :
![]() | |
|
Arquivo xml contatos_24_9_2012_13_41_9.xml :
<?xml version="1.0" encoding="UTF-8"?> <contatos> <contato> <id>3</id> <nome>Cliente 1</nome> <telefone>2222-3333</telefone> </contato> <contato> <id>4</id> <nome>Cliente 2 renomeado de novo</nome> <telefone>4444-5555</telefone> </contato> </contatos>
III) Crie uma nova Classe de nome XmlUtil
![]() |
Figura 15 - Criando uma classe XmlUtil para manipular o XML e organizar melhor o código |
essa classe fica assim :
package springlesson07.utils; import com.thoughtworks.xstream.XStream; import java.awt.Desktop; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.ObjectOutputStream; import java.io.Writer; import java.util.Calendar; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import springlesson07.model.Contato; public class XmlUtil { private Calendar calendar; private String dataHojeFormatada; private String dataNomeArquivo; private String nomeArquivo; private XStream xstream; public XmlUtil() { // p/ gerar o nome do arquivo no contrutor this.calendar = Calendar.getInstance(); this.dataHojeFormatada = calendar.get(calendar.DATE) + "/" + (calendar.get(calendar.MONTH) + 1) + "/" + calendar.get(calendar.YEAR) + " " + calendar.get(calendar.HOUR_OF_DAY) + ":" + +calendar.get(calendar.MINUTE) + ":" + +calendar.get(calendar.SECOND); this.dataNomeArquivo = dataHojeFormatada.replace(" ", "_").replace(":", "_").replace("/", "_"); this.nomeArquivo = "contatos_" + dataNomeArquivo + ".xml"; this.xstream = new XStream(); } public String getNomeArquivo() { return nomeArquivo; } public void setNomeArquivo(String nomeArquivo) { this.nomeArquivo = nomeArquivo; } public XStream getXstream() { return xstream; } public void setXstream(XStream xstream) { this.xstream = xstream; } public void exportarArquivoContatos(List<Contato> list) { try { System.out.println("Gerando arquivo XML:"); getXstream().alias("contato", Contato.class); Writer writer; writer = new FileWriter(getNomeArquivo()); ObjectOutputStream out = getXstream().createObjectOutputStream(writer, "contatos"); writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); for (Contato C : list) { out.writeObject(C); } out.close(); System.out.println("Arquivo gerado:" + getNomeArquivo()); openFile(new File(getNomeArquivo())); } catch (IOException ex) { Logger.getLogger(XmlUtil.class.getName()).log(Level.SEVERE, null, ex); } } public void openFile(File document) throws IOException { Desktop dt = Desktop.getDesktop(); dt.open(document); } }
Alterando a função exportarXML (solução 3)
No arquivo springlesson07.view.contato.frameListaContatos.java
private void exportarXML() { List<Contato> listaContato = this.getDao().listar(); XmlUtil xmlU = new XmlUtil(); xmlU.exportarArquivoContatos(listaContato); JOptionPane.showMessageDialog(null, "Arquivo gerado\n " + xmlU.getNomeArquivo()); }
Após alterar, Teste o programa, clique no botão exportar XML
Se o arquivo exportou corretamente, vamos ver como importar ?
8) Implementando Importação arquivos XML.
Precisamos adicionar o comportamento do botão Importar XML. Logo, precisamos mostrar uma caixa de diálogo p/ o usuário poder escolher o arquivo XML
I) Usuário seleciona o arquivo
No arquivo springlesson07.view.contato.frameListaContatos.java , clique duas vezes no botao importar XML e dentro do actionPerformed escreva uma nova função importarXML e deixe o NB gerar o código
P/ abrir a caixa de diálogo simplesmente e mostrar o arquivo que o usuário selecionou o seguinte código atende :
I) Usuário seleciona o arquivo
No arquivo springlesson07.view.contato.frameListaContatos.java , clique duas vezes no botao importar XML e dentro do actionPerformed escreva uma nova função importarXML e deixe o NB gerar o código
![]() | |
|
private void importarXML() { JFileChooser chooser = new JFileChooser(); int retornoJFC = chooser.showOpenDialog(null); if (retornoJFC == JFileChooser.APPROVE_OPTION) { System.out.println("Arquivo escolhido: \n" + "Pasta: " + chooser.getSelectedFile().getAbsolutePath() + "\n" + "Arquivo: " + chooser.getSelectedFile().getName()); } }
Teste o programa , clique no importar arquivo,selecione um arquivo e veja as informações no console do NB:
![]() |
Figura 18 - Caixa de diálogo p/ o usuário escolher o arquivo a ser importado |
Porém queremos apenas arquivos xml : p/ isso adicionamos a função um filtro (muito simples):
II) Adicionando um filtro ao JFileChooser
import javax.swing.filechooser.FileNameExtensionFilter;
private void importarXML() { JFileChooser chooser = new JFileChooser("Selecione um arquivo XML"); chooser.setFileFilter(new FileNameExtensionFilter("Arquivos XML", "xml")); int retornoJFC = chooser.showOpenDialog(null); if (retornoJFC == JFileChooser.APPROVE_OPTION) { System.out.println("Arquivo escolhido: \n" + "Pasta: " + chooser.getSelectedFile().getAbsolutePath() + "\n" + "Arquivo: " + chooser.getSelectedFile().getName()); } }
Teste o programa , e veja filtro funcionando.
![]() |
Figura 19 - filtro dos tipos de Arquivo por extensão XML |
Certo. já temos o nome e caminho do arquivo. Agora faremos o esquema para importar para nosso banco de dados na tabela contato.
Precisamos fazer algumas modificações antes de continuar.
Para fazer a leitura de Arquivos XML utilizando o esquema desse exemplo, precisamos usar o recurso Annotations .
III) Implementando as anotações
a) no arquivo modelo springlesson07.model.Contato.java
package springlesson07.model; import com.thoughtworks.xstream.annotations.XStreamAlias; @XStreamAlias("contato") public class Contato { private int id; private String nome; private String telefone; public Contato() { this.id = 0; }//gets e sets }
b) precisamos criar uma classe Contatos.java , incluido a anotação por que geramos o arquivo dentro de tags <contatos></contatos>
![]() |
Figura 20 - Adicionando as anotações p/ o XStream |
essa classe fica assim:
package springlesson07.model; import com.thoughtworks.xstream.annotations.XStreamAlias; import java.util.List; @XStreamAlias("contatos") public class Contatos { private List<Contato> list; public Contatos() { } public List<Contato> getList() { return list; } public void setList(List<Contato> list) { this.list = list; } }
IV) implementando a função importarXML no arquivo springlesson07.utils.XmlUtil.java
Adicione outra dependencia do XStream ao projeto (conforme o passo 5 etapa II): dom4j-1.61.jar
![]() |
Figura 21 - adicione a dep do XStream : dom4j-1.61.jar |
usaremos outros imports para essa função :
import com.thoughtworks.xstream.io.xml.Dom4JDriver;
import java.io.BufferedReader;
import java.io.BufferedReader;
import java.io.FileReader;
e para armazenar o Conteúdo do arquivo XML, no definimos o atributo xstream para new XStream(new Dom4JDriver())
V) essa função na classe XmlUtil fica assim: boolean para retornar se importou com sucesso.
public boolean importarArquivoContatos(String F) { this.xstream = new XStream(new Dom4JDriver()); try { getXstream().alias("contato", Contato.class); getXstream().alias("contatos", List.class); getXstream().processAnnotations(Contato.class); BufferedReader input = new BufferedReader(new FileReader(F)); List<Contato> contatos = (List) getXstream().fromXML(input); input.close(); for (Contato C : contatos) { System.out.println("Contato: " + C.getNome() + " - " + C.getTelefone()); } input.close(); return true; } catch (IOException ex) { Logger.getLogger(XmlUtil.class.getName()).log(Level.SEVERE, null, ex); } // arquivos com tags erradas catch (com.thoughtworks.xstream.io.StreamException ex) { System.err.println("Problemas com o arquivo :" + F); Logger.getLogger(XmlUtil.class.getName()).log(Level.SEVERE, null, ex); } return false; }
VI) Alterando a função importarXml do arquivo frameListaContatos (criado no início do passo 8)
VII) Vamos 1º testar com um arquivo XML errado p/ ver esse segundo catch em execução
crie um arquivo de nome contatos_Import_Errado.xml, veja uma tag nomes e outra telefono
Salve esse arquivo e Teste o programa, clique no importar XML e escolha o arquivo que está com erro
o resultado deve ser :
VIII) Vamos 1º testar com um arquivo XML correto.
crie um arquivo de nome contatos_Import.xml, (pode alterar o q que foi gerado pelo programa)
private void importarXML() { JFileChooser chooser = new JFileChooser("Selecione um arquivo XML"); chooser.setFileFilter(new FileNameExtensionFilter("Arquivos XML", "xml")); int retornoJFC = chooser.showOpenDialog(null); if (retornoJFC == JFileChooser.APPROVE_OPTION) { System.out.println("Arquivo escolhido: \n" + "Pasta: " + chooser.getSelectedFile().getAbsolutePath() + "\n" + "Arquivo: " + chooser.getSelectedFile().getName()); XmlUtil xmlU = new XmlUtil(); String message; boolean importResult = xmlU.importarArquivoContatos(chooser.getSelectedFile().getAbsolutePath()); if (importResult) { message = "Importação concluída."; // o q fazer com os dados... } else { message = "Importação com erros.\n" + "Verifique o console."; } JOptionPane.showMessageDialog(rootPane, message); } }
VII) Vamos 1º testar com um arquivo XML errado p/ ver esse segundo catch em execução
crie um arquivo de nome contatos_Import_Errado.xml, veja uma tag nomes e outra telefono
<?xml version="1.0" encoding="UTF-8"?> <contatos> <contato> <nomes>João 1 XML</nome> <telefono>3475-9876</telefone> </contato> <contato> <nome>Cliente 2 XML</nome> <telefone>7654-5432</telefone> </contato> </contatos>
Salve esse arquivo e Teste o programa, clique no importar XML e escolha o arquivo que está com erro
![]() |
Figura 22 - teste de importação de arquivo com tags erradas |
o resultado deve ser :
![]() |
Figura 23 - resultado do teste de importação de arquivo com tags erradas |
VIII) Vamos 1º testar com um arquivo XML correto.
crie um arquivo de nome contatos_Import.xml, (pode alterar o q que foi gerado pelo programa)
<?xml version="1.0" encoding="UTF-8"?> <contatos> <contato> <nome>João 1 XML</nome> <telefone>3475-9876</telefone> </contato> <contato> <nome>Cliente 2 XML</nome> <telefone>7654-5432</telefone> </contato> <contato> <nome>Cliente 3 XML</nome> <telefone>8888-3333</telefone> </contato> <contato> <nome>Cliente 4 XML</nome> <telefone>6543-2222</telefone> </contato> </contatos>Salve esse arquivo e Teste o programa, clique no importar XML e escolha o arquivo correto
![]() |
Figura 24 - teste de importação de arquivo com tags corretas, mas os valores ainda estão apenas no console do NB |
Observe o Output do NB
Arquivo escolhido:
Pasta: /Users/surfer/contatos_Import.xml
Arquivo: contatos_Import.xml
Contato: João 1 XML - 3475-9876
Contato: Cliente 2 XML - 7654-5432
Contato: Cliente 3 XML - 8888-3333
Contato: Cliente 4 XML - 6543-2222
Mas agora o que fazer?? Em uma situação real, precisaríamos verificar esses dados para não duplicar registros, ou quando identificar nome ou telefone, perguntar se deseja atualizar o existente. Também não estou utilizando o atributo id na importação, vou salvar os dados no banco p/ completar o tutorial, mas fica a sugestão de fazer todas as verificações necessárias para manter a integridade dos dados.
IX) Salvando os dados do XML no banco (acho melhor fazer em outro passo, next)
9) Salvando os dados no Mysql
Obs: Durante os testes vou ter q limpar essa tabela várias vezes (até acertar, rs), portanto nas imagens capturadas, as vezes os registros pode estar diferentes. Atenha-se ao código..
Já temos a função salvar que recebe um objeto Contato em nosso ContatoDAO.
Implementação Quick and Dirty:
I) P/ salvar direto sem verificação, basta criar uma instância do ContatoDAO e chamar o método salvar dentro no loop for que varre a lista de contatos criado no passo 8 etapa V, mas para mostrar na tela quantos registros foram importados
- Modificamos a classe XmlUtil p/ armazenar a lista de contatos importados do XML com Get/Set, entre outras coisas, e além disso já fizemos um validador de Contatos no início dessa lição.
Como fica isso ?
II) na classe springlesson07.utils.XmlUtil.java modificamos para o seguinte código:
package springlesson07.utils; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.xml.Dom4JDriver; import java.awt.Desktop; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.ObjectOutputStream; import java.io.Writer; import java.util.Arrays; import java.util.Calendar; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.validation.BeanPropertyBindingResult; import org.springframework.validation.FieldError; import org.springframework.validation.ObjectError; import org.springframework.validation.ValidationUtils; import springlesson07.dao.ContatoDAO; import springlesson07.model.Contato; import springlesson07.validators.ContatoValidator; public final class XmlUtil { private Calendar calendar; private String dataHojeFormatada; private String dataNomeArquivo; private String nomeArquivo; private XStream xstream; // to import private List<Contato> contatosImportados; private int totalImportados; private ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-definitions.xml"); private ContatoDAO dao; public XmlUtil() { // p/ gerar o nome do arquivo no contrutor this.calendar = Calendar.getInstance(); this.dataHojeFormatada = calendar.get(calendar.DATE) + "/" + (calendar.get(calendar.MONTH) + 1) + "/" + calendar.get(calendar.YEAR) + " " + calendar.get(calendar.HOUR_OF_DAY) + ":" + +calendar.get(calendar.MINUTE) + ":" + +calendar.get(calendar.SECOND); this.dataNomeArquivo = dataHojeFormatada.replace(" ", "_").replace(":", "_").replace("/", "_"); this.nomeArquivo = "contatos_" + dataNomeArquivo + ".xml"; this.xstream = new XStream(); this.dao = (ContatoDAO) getCtx().getBean("contatoDao"); } public ApplicationContext getCtx() { return ctx; } public String getNomeArquivo() { return nomeArquivo; } public void setNomeArquivo(String nomeArquivo) { this.nomeArquivo = nomeArquivo; } public XStream getXstream() { return xstream; } public void setXstream(XStream xstream) { this.xstream = xstream; } public void setTotalImportados(int totalImportados) { this.totalImportados = totalImportados; } public int getTotalImportados() { return totalImportados; } public List<Contato> getContatosImportados() { return contatosImportados; } public void setContatosImportados(List<Contato> contatosImportados) { this.contatosImportados = contatosImportados; } private int errosImportacao; public void setErrosImportacao(int errosImportacao) { this.errosImportacao = errosImportacao; } public int getErrosImportacao() { return errosImportacao; } public ContatoDAO getDao() { return dao; } public void setDao(ContatoDAO dao) { this.dao = dao; } public void exportarArquivoContatos(List<Contato> list) { try { System.out.println("Gerando arquivo XML:"); getXstream().alias("contato", Contato.class); Writer writer; writer = new FileWriter(getNomeArquivo()); ObjectOutputStream out = getXstream().createObjectOutputStream(writer, "contatos"); writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); for (Contato C : list) { out.writeObject(C); } out.close(); System.out.println("Arquivo gerado:" + getNomeArquivo()); openFile(new File(getNomeArquivo())); } catch (IOException ex) { Logger.getLogger(XmlUtil.class.getName()).log(Level.SEVERE, null, ex); } } public void openFile(File document) throws IOException { Desktop dt = Desktop.getDesktop(); dt.open(document); } public boolean importarArquivoContatos(String F) { this.xstream = new XStream(new Dom4JDriver()); int erros = 0; int imports = 0; try { getXstream().alias("contato", Contato.class); getXstream().alias("contatos", List.class); getXstream().processAnnotations(Contato.class); BufferedReader input = new BufferedReader(new FileReader(F)); List<Contato> contatos = (List) getXstream().fromXML(input); List<Contato> contatosOk = null; input.close(); for (Contato C : contatos) { System.out.println("Contato: " + C.getId() + " : " + C.getNome() + " - " + C.getTelefone()); ContatoValidator CV = new ContatoValidator(); BeanPropertyBindingResult result = new BeanPropertyBindingResult(C, "Contato"); ValidationUtils.invokeValidator(CV, C, result); if (result.getErrorCount() == 0) { try { this.getDao().salvar(C); imports++; contatosOk.add(C); } catch (java.lang.NullPointerException npe) { // importa os dados mas entra aqui.. p/ examinar com mais calma // System.out.println("Erro ao Salvar o Contato."); // Logger.getLogger(XmlUtil.class.getName()).log(Level.SEVERE, null, npe); } } else { erros++; debugResults(result, erros); } } input.close(); this.setTotalImportados(imports); this.setContatosImportados(contatosOk);// para acessarmos após a importação System.out.println("Total de erros:" + erros); setErrosImportacao(erros); if (erros == 0) { return true; } else { return false; } } catch (IOException ex) { Logger.getLogger(XmlUtil.class.getName()).log(Level.SEVERE, null, ex); } // arquivos com tags erradas catch (com.thoughtworks.xstream.io.StreamException ex) { System.err.println("Problemas com o arquivo :" + F); Logger.getLogger(XmlUtil.class.getName()).log(Level.SEVERE, null, ex); } return false; } private void debugResults(BeanPropertyBindingResult result, int erroN) { System.out.println("Erro nº : " + erroN); System.out.println("Total de erros : " + result.getErrorCount()); System.out.println("-------------------------------------------------"); String erros = ""; List<ObjectError> allObjectErrors = result.getAllErrors(); for (ObjectError objectError : allObjectErrors) { if (objectError instanceof FieldError) { FieldError fieldError = (FieldError) objectError; System.out.println("O campo é: " + fieldError.getField()); } System.out.println("Codigo " + Arrays.asList(objectError.getCodes()).toString()); System.out.println("Codigo de erro: " + objectError.getCode()); System.out.println("Mensagem Default: " + objectError.getDefaultMessage()); System.out.println(); erros += "- " + objectError.getDefaultMessage() + "\n"; } System.out.println("-------------------------------------------------"); } }
III) e modificamos função importarXML do frameListaContatos
private void importarXML() { JFileChooser chooser = new JFileChooser("Selecione um arquivo XML"); chooser.setFileFilter(new FileNameExtensionFilter("Arquivos XML", "xml")); int retornoJFC = chooser.showOpenDialog(null); if (retornoJFC == JFileChooser.APPROVE_OPTION) { System.out.println("Arquivo escolhido: \n" + "Pasta: " + chooser.getSelectedFile().getAbsolutePath() + "\n" + "Arquivo: " + chooser.getSelectedFile().getName()); XmlUtil xmlU = new XmlUtil(); String message; boolean importResult = xmlU.importarArquivoContatos(chooser.getSelectedFile().getAbsolutePath()); if (importResult) { message = "Importação concluída.\n" + "Total de registros importados:" + xmlU.getTotalImportados(); atualizaGrade(); // o q fazer com os dados... } else { message = "Importação com " + xmlU.getErrosImportacao() + "erros.\n" + "Verifique o console."; atualizaGrade(); } JOptionPane.showMessageDialog(rootPane, message); }IV) Teste o programa e tente importar o arquivo XML correto novamente, após importar o arquivo o programa deve exibir uma mensagem de importação concluída e a quantidade de registros incluídos, e a grade e o label Total devem ser atualizados.
![]() |
Figura 25 - Importação do arquivo XML correto p/ o Myqsl. Concluído o processo é informado ao usuário quantos registros foram importados |
E assim podemos importar e exportar arquivos XML do e para o Mysql,
Ficando para implementar as validações num proximo post.
Sugestão , antes de importar os dados p/ o banco , mostre-os p/ o usuário e você pode destacá-los usando uma técnica bem simples que expliquei nesse Tutorial colorir linhas de um jTable
Pois o objetivo aqui foi atendido.
10) Configurando um Splash Screen
Ou seja uma tela de inicialização para o programa. Basicamente ela aparece antes da JVM carregar as classes necessárias para execução e some quando o método main é chamado.Existem vários exemplos na internet de como fazer, até no Wiki do NB e no site da Oracle-SplashSrceen
Vou fazer um simples :
I) Crie uma imagem para o Splash, com o espaço embaixo e coloque essa imagem dentro de um novo package (splash)
![]() |
Figura 26 - meu SplashScreen |
![]() |
Figura 27 - visão atual do projeto |
II) edite o arquivo manifest.mf (ctrl+2 Files) e adicione a entrada p/ o Splash
Manifest-Version: 1.0
X-COMMENT: Main-Class will be added automatically by build
SplashScreen-Image: splash/splash_mcezzare_JSNBTut.png
III) Execute Clean and Build:
![]() |
Figura 28 - Limpando e preparando o projeto p/ distribuição |
Observe o Output
..
ant -f /Users/surfer/NetBeansProjects/_BLOG/SpringLesson07 clean jar init: deps-clean: Updating property file: /Users/surfer/NetBeansProjects/_BLOG/SpringLesson07/build/built-clean.properties Deleting directory /Users/surfer/NetBeansProjects/_BLOG/SpringLesson07/build clean: init: deps-jar: Created dir: /Users/surfer/NetBeansProjects/_BLOG/SpringLesson07/build Updating property file: /Users/surfer/NetBeansProjects/_BLOG/SpringLesson07/build/built-jar.properties Created dir: /Users/surfer/NetBeansProjects/_BLOG/SpringLesson07/build/classes Created dir: /Users/surfer/NetBeansProjects/_BLOG/SpringLesson07/build/empty Created dir: /Users/surfer/NetBeansProjects/_BLOG/SpringLesson07/build/generated-sources/ap-source-output Compiling 12 source files to /Users/surfer/NetBeansProjects/_BLOG/SpringLesson07/build/classes
..
Copying 14 files to /Users/surfer/NetBeansProjects/_BLOG/SpringLesson07/build/classes compile: Created dir: /Users/surfer/NetBeansProjects/_BLOG/SpringLesson07/dist Copying 1 file to /Users/surfer/NetBeansProjects/_BLOG/SpringLesson07/build Created dir: /Users/surfer/NetBeansProjects/_BLOG/SpringLesson07/build/classes/META-INF Copying 1 file to /Users/surfer/NetBeansProjects/_BLOG/SpringLesson07/build/classes/META-INF Copy libraries to /Users/surfer/NetBeansProjects/_BLOG/SpringLesson07/dist/lib. Building jar: /Users/surfer/NetBeansProjects/_BLOG/SpringLesson07/dist/SpringLesson07.jar To run this application from the command line without Ant, try: java -jar "/Users/surfer/NetBeansProjects/_BLOG/SpringLesson07/dist/SpringLesson07.jar"IV) Teste o programa conforme informado na ultima linha
Abra um terminal (windão:Start > Run, digite cmd) e execute o comando acertando a pasta onde está seu SpringLesson07.jar:
java -jar "/Users/surfer/NetBeansProjects/_BLOG/SpringLesson07/dist/SpringLesson07.jar"
![]() |
Figura 29 - programa sendo iniciado pelo terminal (ou seja fora do NB) e mostrando o splashScreen |
11) Rodando o Programa em outras máquinas que tenham JVM instalado
I) localize a pasta dist
Ao executar o Build acima, o NB colocou tudo o que precisa p/ o programa rodar em outro ambiente.
dentro do projeto foi criada uma pasta dist (de distribution )
![]() |
Figura 30 - Aonde está meu projeto p/ distribuição ? e as libs ?? |
II) Aí basta copiar essa pasta, e distribuir isso na rede onde será usado : (toda vez que usamos o Build, essa pasta é removida e criada novamente)
![]() |
Figura 31 - Comprima a pasta dist e pode distribuir o programa. Mas ... e as customizações ? ainda tem alguma ?? |
III) E coloque o zip em algum lugar da rede, descompactando e dando um nome amigável, tipo MeusContatos-1.0, e os usuários podem clicar direto no arquivo.jar que já abrirá o programa.
12) Customizando o Build
Costumo iniciar os programas com scripts. Porquê ?
1) p/ poder solucionar erros mais facilmente
2) p/ gerar um arquivo de log
E não quero ter que toda vez que preparar o projeto p/ distribuição ter que manualmente colocar os arquivos de Script (Windows:.bat, *nix.sh, OSX.command) mais o arquivo LEIAME.txt , então ao usar o Build Project, o NB copie os arquivos para a mesma pasta do programa :
I) vamos criar uma pasta scripts dentro da pasta src
![]() |
Figura 32 - criando uma pasta que conterá os arquivos para serem incluídos na pasta do programa, após a compilação (build) |
![]() |
Figura 33 - Pasta scripts : .bat.sh, command, arquivos txt |
II) Agora vamos criar os arquivos dentro dessa pasta:
vou criar 5 arquivos
LEIAME.txt com as info de execução do programa
.bat p/ quem usa o windão
.sh p/ quem usa linux,OSX,*nix
.sql p/ rodar o banco de dados em caso de nova distribuição e p/ enriquecer o tutorial.
e como esses arquivos são fornecidos com o projeto final no fim da lição, veja a tela abaixo com todos os arquivos abertos :
![]() |
Figura 34 - visão geral da Pasta scripts : .bat.sh, command, arquivos txt, sql |
![]() |
Figura 35 - Pasta scripts : .bat.sh, command, arquivos txt, dentro do projeto NB |
III) Localize pela aba Files o arquivo build.xml
![]() |
Figura 36 - localize o arquivo build.xml |
a) Localize o target -post-compile, e clique duas vezes nele, embaixo dos comentarios vamos adicionar o seguinte :
<target name="-post-compile"> <!-- Empty placeholder for easier customization. --> <!-- You can override this target in the ../build.xml file. --> <mkdir dir="./dist/Db" /> <copy todir="./dist/Db"> <fileset dir="./src/scripts/"> <include name="**/*.sql" /> </fileset> </copy> <copy todir="./dist"> <fileset dir="./src/scripts/"> <include name="**/*.bat" /> <include name="**/*.sh" /> <include name="**/*.txt" /> </fileset> </copy> <!-- nao consegui apagar o arquivo README.TXT <delete quiet="false"> <fileset dir="./dist"> <include name="**/README.TXT" /> </fileset> </delete>--> </target>
b) Salve. Localize o target -clean mais acima , e Run Target
![]() |
Figura 37 - Executando a chamdas a ant de dentro do NB |
c) Localize o target -post-compile, e
![]() |
Figura 38 - testando o target post-compile |
d) Olhe a aba Output:
![]() |
Figura 39 - veja se os arquivos foram copiados |
ant -f /Users/surfer/NetBeansProjects/_BLOG/SpringLesson07 -post-compile Created dir: /Users/surfer/NetBeansProjects/_BLOG/SpringLesson07/dist/Db Copying 1 file to /Users/surfer/NetBeansProjects/_BLOG/SpringLesson07/dist/Db Copying 5 files to /Users/surfer/NetBeansProjects/_BLOG/SpringLesson07/dist BUILD SUCCESSFUL (total time: 0 seconds)
e) Confira se os arquivos foram copiados
![]() |
Figura 40 - conferindo se os arquivos foram copiados |
f) Execute Clean and Build:
![]() |
Figura 41 - como São Tomé, execute o build pelo NB e veja se ainda compila tudo certinho.. |
e verifique se todos os arquivos estão na pasta dist
![]() |
Figura 42 - veja se os arquivos foram copiados pelo build do projeto |
E está pronta a nossa aplicação exemplo.
![]() |
Figura 43- visão final do projeto |
Download do projeto NB
SpringLesson07-final
Experimente executar o Profile e compare os resultados.
E assim concluímos nossa lição 07.
Resumo : o que foi feito ?
- Implementamos um CRUD completo em Java utilizando Swing e Spring
- Implementamos um validador com org.springframework.validation.Validator
- Implementamos um Tema
- Vimos como importar /exportar arquivos XML usando XStream
- Aprendemos a usar Anotações
- Implementamos um SplashScreen
- Aprendemos a distribuir nossa aplicação e customizar o build do projeto no build.xml
- Vimos um pouco de como o NB gera os códigos (que são protegidos no ambiente de código, mas todas as suas propriedades podem ser alterados pelo GUI)
- Vimos mais facilidades do NB
Existem centenas de programas gerenciadores de contatos hoje em dia. O objetivo dessas lições não foi fazer um Software de Agenda. E sim mostrar algumas técnicas p/ implementar um CRUD em Java, utilizando como ferramenta o NetBeans, aproveitando recursos do framework Spring, manipular arquivos XML e pode ser uma base para quem está começando, ou usa o eclipse e não migrou ainda para o NB :) hehe
Tem algumas coisas que são comuns aos sistemas e espero ter demonstrado nesses posts um jeito simples de resolver algumas delas.
no próximo post. WebApps e Struts..
Dúvidas, Contribuições, Sugestões? Poste..
Grato,
Até a próxima.