quarta-feira, 10 de março de 2021

JPA 2.1 - Criteria Builder, evitando query adicional causada por FetchType Lazy (lazy-loading)

 Hoje durante a utilização da api criteria para consultas dinâmicas enquanto realizava um curso, me deparei com uma coisa bem chata, no qual eu possuo 3 beans.
  • Estado
  • Cidade
  • Usuário
Ocorria o seguinte inconveniente, devido essa consulta ser usada em filtros decidi usar o CriteriaBuilder pela facilidade em criar  dinamicamente as consultas, porem todas as vezes que eu realizava uma consulta sempre recebia duas consultas adicionais, uma para Cidade e outra para Estado. E antes que me perguntem sim! marquei como lazy essas relações e não desejo nem quero que sejam JoinType Eager sempre, porem ao usar o CriteriaBuilder ele ignora completamente e volta a usar o lazy-loading.

  
    select
        cliente0_.codigo as codigo1_2_,
        cliente0_.cpf_cnpj as cpf_cnpj2_2_,
        cliente0_.email as email3_2_,
        cliente0_.cep as cep4_2_,
        cliente0_.codigo_cidade as codigo_11_2_,
        cliente0_.complemento as compleme5_2_,
        cliente0_.logradouro as logradou6_2_,
        cliente0_.numero as numero7_2_,
        cliente0_.nome as nome8_2_,
        cliente0_.telefone as telefone9_2_,
        cliente0_.tipo_pessoa as tipo_pe10_2_ 
    from
        cliente cliente0_ 
    where
        1=1 limit ?;

    select
        cidade0_.codigo as codigo1_1_0_,
        cidade0_.codigo_estado as codigo_e3_1_0_,
        cidade0_.nome as nome2_1_0_ 
    from
        cidade cidade0_ 
    where
        cidade0_.codigo=?;

    select
        estado0_.codigo as codigo1_3_0_,
        estado0_.nome as nome2_3_0_,
        estado0_.sigla as sigla3_3_0_ 
    from
        estado estado0_ 
    where
        estado0_.codigo=?

O que de fato não é nem de longe ideal para um bom desempenho, mas então oque fazer ? será que existe uma forma de incorporar na primeira query as duas adicionais ? E a resposta é sim! basta fazer o fetch ,  nas relações que deseja evitar as consultas adicionais, mesma coisa que fazemos no HQL.

   Root cliente = querie.from(Cliente.class);           
            
   cliente.fetch(Cliente_.ENDERECO)//Representa o endereço 
          .fetch(Endereco_.CIDADE, JoinType.LEFT)//Realiza o Fetch de Cliente com Cidade
          .fetch(Cidade_.ESTADO, JoinType.LEFT);  //Realiza o Fetch da Cidade com estado
  
A partir de agora a consulta gerada é a seguinte.
  
    select
        cliente0_.codigo as codigo1_2_0_,
        cidade1_.codigo as codigo1_1_1_,
        estado2_.codigo as codigo1_3_2_,
        cliente0_.cpf_cnpj as cpf_cnpj2_2_0_,
        cliente0_.email as email3_2_0_,
        cliente0_.cep as cep4_2_0_,
        cliente0_.codigo_cidade as codigo_11_2_0_,
        cliente0_.complemento as compleme5_2_0_,
        cliente0_.logradouro as logradou6_2_0_,
        cliente0_.numero as numero7_2_0_,
        cliente0_.nome as nome8_2_0_,
        cliente0_.telefone as telefone9_2_0_,
        cliente0_.tipo_pessoa as tipo_pe10_2_0_,
        cidade1_.codigo_estado as codigo_e3_1_1_,
        cidade1_.nome as nome2_1_1_,
        estado2_.nome as nome2_3_2_,
        estado2_.sigla as sigla3_3_2_ 
    from
        cliente cliente0_ 
    left outer join
        cidade cidade1_ 
            on cliente0_.codigo_cidade=cidade1_.codigo 
    left outer join
        estado estado2_ 
            on cidade1_.codigo_estado=estado2_.codigo 
    where
        1=1 limit ?

Espero ter ajudado pessoas que assim como eu tiveram muitos problemas,  para conseguir realizar esse simples procedimento assim como era feito no HQL.

segunda-feira, 1 de junho de 2020

JasperReports Configurar PDF com Autor,Titulo, Assunto,Criador, Senha (Meta Data)

Seguindo com a serie de testes com jasperReports gerando o relatorios, notei que ao abrir o arquivo no navegador ele não tinha um título interessante, então fui procurar em como mudar o mesmo na pagina web, minha pesquisa me levou a descobrir uma série de configurações para a configuração do PDF alem de um simples titulo, assumindo que voce ja tem o arquivo jasperPrint disponivel temos o seguinte codigo.


JasperPrint jasperPrint = JasperFillManager.fillReport(jasperStream, parametros,dataSource);            
String nomeArquivo =  "FICHA "+condutor.getNome().toUpperCase();
JRPdfExporter exportadorDePDF = new JRPdfExporter();
SimplePdfExporterConfiguration  configuracaoSimplesDoExportadorDePDF = new SimplePdfExporterConfiguration();
configuracaoSimplesDoExportadorDePDF.setMetadataAuthor("Denis Benjamim");
configuracaoSimplesDoExportadorDePDF.setMetadataTitle(nomeArquivo);
configuracaoSimplesDoExportadorDePDF.setMetadataSubject("Ficha Cadastral Condutor "+condutor.getNome());
configuracaoSimplesDoExportadorDePDF.setMetadataCreator("Transparency Logistica e Transportes ltda");
configuracaoSimplesDoExportadorDePDF.setMetadataKeywords("Ficha,Ficha Cadastral,Condutor,RG,CPF,CNH,habilitacao");;
configuracaoSimplesDoExportadorDePDF.set128BitKey(true);
configuracaoSimplesDoExportadorDePDF.setEncrypted(true);
configuracaoSimplesDoExportadorDePDF.setUserPassword("password");

ByteArrayOutputStream baos = new ByteArrayOutputStream();
exportadorDePDF.setExporterInput(new SimpleExporterInput(jasperPrint));
exportadorDePDF.setExporterOutput(new SimpleOutputStreamExporterOutput(baos));
exportadorDePDF.setConfiguration(configuracaoSimplesDoExportadorDePDF);
exportadorDePDF.exportReport();         

return ResponseEntity.ok()                   
                .header(HttpHeaders.CONTENT_DISPOSITION,"inline; filename="+nomeArquivo+".pdf")
                .body(baos.toByteArray());

Resumindo estou configurando no pdf, o nome do autor, titulo, assunto, criador, palavras chaves, tipo de criptografía, informando que sera criptografado e terá senha, nada além dessas pequenas coisas.

setMetadataAuthor -> Pessoa que solicitou o pdf.
setMetadataTitle-> Titulo do pdf sera exibido na janela
setMetadataSubject ->Assunto do pdf.
setMetadataCreator-> Nome do software ou Empresa responsavel pela criação do PDF.
setMetadataKeywords-> Palavras chaves utilizadas para pesquisa do pdf.
set128BitKey-> Criptografía dos dados no pdf.
setEncrypted->Ativa criptografia.
setUserPassword-> Senha para acessar o pdf.

A classe responsável pela configuração é a SimplePdfExporterConfiguration, nela configuramos as informações conforme visto no codigo.

JRPdfExporter classe responsavel por exportar o pdf.
ByteArrayOutputStream sera usado para junto do JRPdfExporter para gerar o pdf.

setExporterInput -> Fluxo de entrada com jasperPrint.
setExporterOutput -> Fluxo de saida.
setConfiguration -> Arquivo de configuração que sera usado na geraçao do pdf.
exportReport - > Persiste a configuracao personalizada para ser enviada ao navegador.

No pdf temos a seguinte saida em suas propriedades.

domingo, 31 de maio de 2020

JasperReports JRBeanCollectionDataSource Java Bean Complexos

Vamos direto ao ponto. Quando usamos beans dentro de um JRBeanCollectionDataSource  e como no meu caso apenas linquei a pasta do projeto dentro do Jaspersoft Studio, quando temos um objeto diferente dos padrões do JRE, costumo ter um problema na hora de gerar vamos ver o caso:

Tenho uma Class Chamada Condutor dentro dela tenho vários atributos dentre eles alguns são classes como CidadeIBGE, EstadoIBGE e alguns sao Enuns Status,TipoCondutor, conforme imagem:


É importante ser notado que foi detectado corretamente o Class Type, mas mesmo assim vamos acabar esbarrando no problema das seguintes exceçoes NoClassDefFoundError e ClassNotFoundException durante a tentativa de geraçao do relatório com os dados do bean.

Os Bens selecionados tem os seguintes atributos:

Class CidadeIBGE
Class CidadeIBGE

Class EstadoIBGE

Enum Status

Vou usar o enum como o exemplo pois os demais serão exatamente iguais, tem um unico metodo que me é interessante que se refere a descrição, para que ele funcione corretamente sera necesario modificar algumas informacoes:
  1. Class Type Tem de ser o dado dado final, neste caso sera um java.lang.String.
  2. Em description vamos seguir o padrão Bean como se eu quisesse navegar no objeto ate seus atributos, neste caso ficaria situacao.descricao.
  3. Para realizar essas alterações basta dar dois cliques em uma das linhas que deseje editar


Se existe uma forma  de acessar as propriedades dos beans eu nao consegui encontrar, em fim! fica a dica para quem precisar um dia

Spring Boot + JasperReports exportando relatorios para PDF

É hoje temos algumas coisas interessantes para falar dentre elas a dificuldade de encontrar um bom e interessante codigo para gerar um simples pdf a partir de um JasperReport junto com uma aplicação Spring Boot.

Durante a pesquisa encontrei codigos muito parecidos com este a baixo e sim! Ele funciona perfeitamente.

@GetMapping
public void gerarPDF(@RequestParam Map parametros, HttpServletResponse response) throws IOException,JRException {
       
 if(parametros == null)
  parametros = new HashMap<>();          
           
 InputStream jasperStream = this.getClass().getResourceAsStream("../../../../reports/CondutorFicha.jasper")
 JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(Arrays.asList(condutores.findByCodigo(5)));
 JasperPrint jasperPrint = JasperFillManager.fillReport(jasperStream, parametros,dataSource);
        
 response.setContentType("application/pdf");
 response.setHeader("Content-Disposition", "inline; filename=Ficha.pdf");

 final OutputStream outputStream = response.getOutputStream();
 JasperExportManager.exportReportToPdfStream(jasperPrint, outputStream);            
       
}

Explicando em miúdos:
jasperStream -> Capturando o arquivo do relatório no meu classpath de modo hard( pois existe uma forma mais facil), na sua forma compilada .jasper vi em vários locais que pessoal compila na hora de exibir o relatorio, como nao tenho que trabalhar com múltiplos idiomas preferi trabalhar diretamente com o .jasper ao .jrxml.

dataSource -> linha seguinte criando um JRBeanCollectionDataSource com os BEANS devidamente populados no meu banco.

jasperPrint -> unificando o relatório com seus parametros e dados para daí poder gerar o pdf preenchido.

O objeto response esta informando no header da resposta que vamos devolver um pdf e informando que sera exibido no navegador com o nome de Ficha.pdf.

outputStream -> Capturando a Stream da resposta para ser usada no retorno ao navegador.

JasperExportManager -> tem uma serie de metodos uteis para exportar para uma serie de formatos distintos, que no caso informei qual o jasperprint e para qual saída de fluxo ele iria.

Então se este código funciona perfeitamente por que tentar fazer de outra forma ?.. Insatisfação, teimosia , seja la qual foi o motivo eu queria poder usar todas as partes que conheço do Spring Boot ate o dia de hoje, eis que decido deixar meu código desta forma:

 
@GetMapping(produces = {MediaType.APPLICATION_PDF_VALUE})
public @ResponseBody ResponseEntity gerarPDF(@RequestParam Map parametros){
 if (parametros == null)
     parametros = new HashMap<>();     
    
 try (InputStream jasperStream = applicationContext.getResource("classpath:reports/CondutorFicha.jasper").getInputStream()) {

     JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(Arrays.asList(condutores.findByCodigo(5)));
     JasperPrint jasperPrint = JasperFillManager.fillReport(jasperStream, parametros,dataSource);         
   
     return ResponseEntity.ok()
      .header(HttpHeaders.CONTENT_DISPOSITION,"inline; filename=Ficha.pdf")
      .body(JasperExportManager.exportReportToPdf(jasperPrint));
 }catch(JRException | IOException exception ){
     exception.printStackTrace();
 }
 return ResponseEntity.badRequest().body("Nao foi possivel gerar o pdf");
}
 
Vou descrever  apenas as diferenças do com relação ao primeiro código. Começando que agora ele tem um retorno diferente do primeiro que era um void teremos como retorno um ResponseEntity

@GetMapping -> Agora tem um argumento informando que será produzido um PDF, descartando a configuracao no Header.

@ResponseBody -> Indica que o valor de retorno deve ser vinculado ao corpo da resposta

jasperStream -> é instanciado pelo ApplicationContext do Spring de uma forma mais simples comparando com a anterior na minha opinião. Além de ter usado um TRY Resources para abrir e fechar o fluxo

ResponseEntity - > Builder para a resposta como um HttpServletResponse, nele informei uma parte do header anterior, e no body passei como parâmetro um byte[] pois é isso que este método estático do JasperExportManager nos devolve. Além de ter um pequeno tratamento caso não seja possível gerar o pdf por algum motivo.

sábado, 30 de maio de 2020

Jaspersoft Studio + Lombok Instalação


Devo dizer que foi uma tarefa bem chata de se fazer ainda mais que o lombok no ubuntu não conseguiu reconhecer nem o Eclipse comum quem dirá a versão modificada que é o Jasper Studio nossa maravilhosa IDE para criação de relatórios das Jaspersoft.

Problema: Não instala de forma automática.


Necessidade: devido estar usando lombok no projeto se faz necessário que a IDE de relatórios também seja capaz de compilar os beans gerando assim setters e getters usando as annotations do lombok.

Soluçao: Instalar manualmente. Após encontrar o diretório de instalação do seu Jaspersoft Studio dentro do sistema operacional no seu computador, que no meu caso estava no caminho "/opt/tibco/TIB_js-studiocomm_6.12.2"(Ubuntu 16.04).

Vamos seguir a complicada explicação descrita dentro do proprio jar clicando em Show me what this installer will do to my IDE installation.


Considerações nao teremos dentro da pasta de instalação do Jaspersoft Studio um arquivo chamado Eclipse.ini nas sim Jaspersoft Studio.ini, como pode ser visto a seguir:


Copie o arquivo jar do lombok para dentro deste diretório e caso não tenha permissão de escrever, como eu basta conceder essa permissão pelo terminal  :x.

Após o arquivo estar no diretório abra o arquivo .ini e adicione no final do arquivo o caminho para o jar  do lombok lembrando se seu jar tem de estar com o mesmo nome que você informar no arquivo de configuração caso contrário vai acontecer um erro e a IDE não deve abrir.


basta colar a seguinte instrução " -javaagent:lombok.jar  " - Sem as aspas por favor rs. O arquivo deve ficar como acima, e para ter certeza conseguiu instalar corretamente basta abrir a IDE  > Help > About TIBCO Jaspersoft Studio e como pode notar na imagem temos descrito a versão do lombok instalada descrita nesta janela.



Agora e so compilar seu projeto e Correr para o abraço

terça-feira, 1 de outubro de 2019

JPA MAPEAMENTO MAP COM CHAVE ENUM E VALOR OBJECT


A baixo a descrição em código de como Mapear um objeto do tipo Map tendo como chave um Enum e valor uma Entidade que poderia ser qualquer outro Objeto

@Data @AllArgsConstructor @NoArgsConstructor @Builder
@Entity
@Table(schema = "gdf",name = "tb_VeiculoPneus")
 public
 class VeiculoPneus implements Serializable{

    @Id
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "CodVeiculo")
 private Veiculos codigoVeiculo;


    @OneToMany
    @JoinTable(name = "tb_VeiculoPosicaoPneu",schema = "gdf"
       ,uniqueConstraints = 
         @UniqueConstraint(name="UK_PNEU_VEICULOPOSICAOPNEU"
          ,columnNames={"CodPneu"})
       ,joinColumns= 
         @JoinColumn(name="CodVeiculoPneus"
          ,foreignKey= 
            @ForeignKey(name="FK_VEICULOPNEUS_VEICULOPOSICAOPNEU")
         )
       ,inverseJoinColumns=  
         @JoinColumn(name="CodPneu"
          ,foreignKey= 
            @ForeignKey(name="FK_PNEU_VEICULOSPOSICAOPNEU")
         ) 
    )
    @MapKeyEnumerated(EnumType.STRING)
    @MapKeyClass(PosicaoPneu.class)
    @MapKeyColumn(name ="CodPosicao")
 private Map<PosicaoPneu,Pneu> pneus;   

 }

Este mapeamento gera a seguinte saída SQL:

 create table gdf.tb_VeiculoPosicaoPneu
 (
    CodVeiculoPneus int not null
  , CodPneu         bigint not null
  , CodPosicao      varchar(255) not null
  , primary key (CodVeiculoPneus, CodPosicao)
        )
  
 alter table gdf.tb_VeiculoPosicaoPneu 
       add constraint UK_PNEU_VEICULOPOSICAOPNEU 
 unique (CodPneu)
 
 alter table gdf.tb_VeiculoPosicaoPneu 
       add constraint FK_PNEU_VEICULOSPOSICAOPNEU 
       foreign key (CodPneu )
       references gdf.tb_Pneu
    
 alter table gdf.tb_VeiculoPosicaoPneu 
       add constraint FK_VEICULOPNEUS_VEICULOPOSICAOPNEU 
       foreign key (CodVeiculoPneus) 
       references gdf.tb_VeiculoPneus

segunda-feira, 26 de agosto de 2019

Script Batch (cmd) Windows SQLServer Backup

Bom dia!

Durante o final de semana trabalhei em um script para relização do backup via prompt de comando, mas não é apenas um backup que ele realiza dentre as tarefaz atribuidas o script segue os seguintes passos:


  1. Faz backup de múltiplas bases
  2. Compacta utilizando 7-zip
  3. Move o arquivo Compactado para um diretorio na rede.
  4. Caso ocorra algum erro envia e-mail para notificar
  5. Caso ocorra tudo bem tambem envia um e-mail notificando
Requisitos para que esse script funcione corretamente:
  • SQLCMD 
  • 7z
  • Blat

quarta-feira, 27 de junho de 2018

PFsense DNS Resolver Host Overrides e Domain Overrides como configurar

Boa Noite!

Depois de muitas duvidas em como configurar  principalmente o Host Overrides finalmente consegui chegar a uma conclusão de como configurar corretamente. Comecemos com o mais simples Domain Overrides.

Cenário tenho um servidor Samba como controlador de Dominio e gostaria que ao realizar uma consulta dns em minha rede o pfsense responde-se de forma satisfatória as pesquisas então vamos assumir que meu dominio é SANTOS.TRANSPARENCY e a maquina na qual ele responde esta no meu ip de rede 192.168.1.5 então navego pelo menu Services > DNS Resolver rolo a pagina até embaixo e clico em +add e faço a seguinte configuração conforme a baixo.

Clique na Imagem para Ampliar

Salvo e em seguida aplico as mudanças. Verifico se vou conseguir realizar um ping no dominio e se vai apontar para o ip desejado.

Clique na Imagem para Ampliar
Observamos que no primeiro comando estou conseguindo "pingar" o dominio perfeitamente. No segundo é o nome registrado  da maquina dentro do meu DHCP, tambem respodendo perfeitamente.

Agora vamos para o Host Overridades

Cenario tenho um ubuntu server com GLPI e OCSINVENTORY, e eu desejo acessar o GLPI diretamente ao digitar no navegador http://glpi/ até ai bastaria eu dar o nome de glpi a esta maquina no serviço de dhcp e ativar a função no DNS Resolver de mapear os dns registrados no dhcp Server, mas sempre temos um mas, durante a instalação dos clientes do ocsinventory por padrão vem a url http://ocsinventory-ng/ocsinventory eu poderia mudar a url para http://192.168.1.4/ocsinventory, mas seria pouco pratico para mim então eu quero acessar ambos pelas url, vamos a configuração.

Mas antes lembra quando voce configurou o seu pfsense e colocou um dominio ? Não lembra ? tudo bem só ir no menu System > General setup e veja o que digitou em Domain essa informação é importante pois sera usada para realizar a substituição do host, no meu caso é santos.transparency.

A configuração a baixo mostra o seguinte:

Host: NOME DA MAQUINA NO MEU DHCP SERVER O QUAL FOI MAPEADO NO DNS

Domain: que no meu caso é santos.transparency, por isso é importante saber qual o dominio(FQND)

IP ADDRESS: IP da maquina que ira responder as pesquisas pelos Host names no meu caso 192.168.1.4

Em Additional Names for this host vou adicinar os dominios adicionais que quero que passem para essa maquina, como pode ser visto na imagem poderia haver muitos mais.

Clique na imagem para Ampliar
Em caso de duvidas deixe nos comentarios.

quinta-feira, 20 de julho de 2017

Refatoração de Codigo Java

Olá!
Me solicitaram uns novos argumentos a esta janela:


No caso são os tipos de motoristas(Funcionario,Agregado e Terceiro). Até bacana mas senti que precisava ser dinâmico independente da escolha caso nao fosse assim nao estaria interessante. Pensei em como iria implementar este codigo tentei varias coisas ontem, mas sem sucesso, isso por que programar de cabeça cheia nao dá. Ai fiz o de sempre no caminho para casa por 25 km fiquei pensando em como solucionar meu problema, e então saiu o primeiro codigo que deu certo:

Ai olhei para esse codigo e pensei.. que feio.. deve ter alguma forma de melhorar esse codigo fazendo de outra maneira, ai me ocorreu usar  de mudar e pensei no seguinte. Tenho 3 JCheckBoxp posso usar um Case e colocar  o codigo dentro de 2 casos, Ai criei um metodo que armazenava os JCheckBox ao um List caso eles estivessem selecionados.
Pronto com isso eu consegueria pegar a quantidade e quais  JCheckBox estariam selecionados. Dai foi so juntar A+B, o switch  case recebia  o total da lista e dentro de cada caso havia um codigo diferente, conforme podemos ver a baixo utilizei o proprio texto do componente como clasula da pesquisa ja que eram identicos as categorias.

Olha que belezinha comparando a quantidade de linhas com o primeiro codigo esse ai tem apenas 10 e com uma cara muito mais limpa e clara sem falar legivel.

Recebe os JCheckBox caso tenha 1 seja ele qual for concatena com a String que ja havia com o codigo mais generico e observem como pego o argumento se so tem 1 com certeza  esta na posição 0 do list, depois pego o texto descrito no componente e o transformo todas as letras para Maiusculas, Ai esta o primeiro. No Segundo precisei adicionar um pouco mais  por causa da propria pesquisa mas a ideia foi praticamente a mesma do 1.

E é isso refatorem sempre que der os codigos reduza o tamanho melhore os metodos e vamos continuar com as boas praticas.

quinta-feira, 10 de março de 2016

Expressões Regulares Java - Regex

Olá

Durante meus quase 10 anos de programação com a linguagem Java, não consigo recordar se precisei ou não utilizar expressões regulares... mas durante alguns dos desafios no site HackerRank, fui forçado a estudar para conseguir resolver o desafio que exigia que em uma String X, caso ouve-se pontos(Padrão inglês não tem acentos).

No Site da Oracle existe uma ótima documentação que qualquer um pode ler facilmente a aprender, mas para variar esta em inglês(Sim Jovens Inglês é indispensável).

Segundo a Oracle o que podemos fazer com expressões regulares são pesquisas, edições ou manipulação do texto e dados em Strings;

Vou usar como referencia para dar uma explicada básica o desafio que estava tentando realizar no HackerRank.

Possuía esta entrada:
He is a very very good boy, isn't he?
Que deveria sair com esta saída:
He
is
a
very
very
good
boy
isn
t
he
Em suma precisava retirar a pontuação da frase.
E o próprio enunciado dava a dica sobre usar expressões regulares. Então fui estudar para tentar resolver meu problema.


ConstrutorDescrição
[abc]a, b, or c (Classe Simples)
[^abc]Qualquer carácter exceto a, b, ou c (negação)
[a-zA-Z]a até z, ou A até Z, inclusive (alcance)
[a-d[m-p]]a ate d, ou m até p: [a-dm-p] (Uniao)
[a-z&&[def]]d, e, ou f (interseção)
[a-z&&[^bc]]a até z, exceto para b e c: [ad-z] (subtração)
[a-z&&[^m-p]]a até z, e não m até p: [a-lq-z] (subtração)

 Dai fui testando um a um para ver como se comportam afinal , ver algo funcionando e muito diferente de ler como funciona.

Ai pensei só quero as letras sem  acentos, de cara iria usar a expressão [a-zA-Z] , mas como nada é tao simples, usei o método replaceAll da API String. Ela aceita dois Argumentos, o primeiro um Regex e o segundo a String que ira substituir de acordo com o Regex.

Porem ser usar ele desta forma String.replaceAll("[a-zA-Z]", " "); . Se eu fizer exatamente assim estou dizendo para ele substituir qualquer letra Minuscula ou Maiúscula por Espaço " ";
Meu objetivo e justamente o contrario, então como é o contraio eu vou negar essa regra invertendo a saida dela usando  o simbolo da negação ^ , mudando minha expressao para String.replaceAll("[^a-zA-Z]", " ");

Agora sim tenho a saida que quero sem os Acento. Mas para complementar e explicar como fiz para conseguir as palavras cada uma em uma linha.



String.replaceAll("[^a-zA-Z]", " ").split(" ") adicionando o split(" ") eu tenho como retorno um Array de String[] e com isso posso usar um forEach para percorrer o Array e Imprimir em cada linha cada uma das palavras.

Duvidas ? Comenta ai.

quinta-feira, 5 de novembro de 2015

CRIAR PROJETO MAVEN EM JSP 2.2 - ECLIPSE

Olá a Todos.

Se voce como eu esta a horas tentando entender o por que vc tenta criar um projeto Maven com jsp e acontece varias falhas, dentre elas nao consegue mudar o modulo dinamico para 2.5 ou superior, bem o problema é bem mais simples do que parece.
Durante a criação de um novo projeto maven nesta tela, caso a caixa circulada não  esteja selecionada a selecione.

Depois so completar os dados de acordo e clicar em finish




sexta-feira, 12 de setembro de 2014

Enviar E-mail com texto e anexo Commons Mail

Olá, recentemente comecei testar novas tecnologias para envio de e-mails. Onde muito se falava do Commons Mail, por ser simples e de fácil configuração se considerado com o Java Mail, o qual é mais complexo. 

Curiosidade importante, Commons Mail é baseado no Java Mail. Bom vamos la para utilizar o Commons Mail é necessário o Java Mail e o próprio Commons Mail, e caso esteja utilizando Java 6 é necessario o JAF.

No próprio site da Commons Apache, existe diversos tutorias básicos contendo ótimos exemplos confira aqui.

No meu caso vou dar uma importante dica, caso como eu você esteja utilizando iReport para gerar relatórios ou algum outro meio que utilize Array de Bytes(Essa solução é usada para  que não seja necessário persistir o arquivo em disco). Se parou para olhar o exemplo no site da Commons Apache percebeu que ele usa a classe EmailAttachment  , e esta classe apenas aceita o caminho do arquivo (Em String) que ja esta no disco. E como ja dito para casos que você vai gerar o arquivo em por exemplo um Array de Bytes existe métodos especifico dentro da classe MultiPartEmail.  O método sobrecarregado chamado attach, possui atualmente cerca de 6 metodos com este mesmo nome utilizando construtores diferentes( Isso é mesmo necessario ser dito ? ). O construtor que irei demostrar no codigo a baixo é o seguinte:


public MultiPartEmail attach(DataSource ds,String name,String description,String disposition) throws EmailException

Este construtor recebe um Objeto do tipo DataSource contendo os dados do mesmo, um nome, uma descrição e disposição. Para resumir abaixo o codigo que utilizo hoje a partir deles com certeza voce vai entender muito melhor:


public class Email {  
    private Object[] para;
    MultiPartEmail multiPartEmail;

    public Email() {
        multiPartEmail = new MultiPartEmail();      
        try {
            multiPartEmail.setFrom("seuMail@seuDominio","Seu Nome");
        } catch (EmailException ex) {
            Logger.getLogger(Email.class.getName()).log(Level.SEVERE, null, ex);
        }
        multiPartEmail.setAuthentication("emailAutencar@dominio", "senha");
        multiPartEmail.setHostName("seuHost");
        multiPartEmail.setSmtpPort(PORTA_SMTP);
        multiPartEmail.setDebug(true);//DEBUG
    }

    @Override
    public boolean enviar() {
        try {
            for (Object object : para) {//Percorre a lista de destinatarios e add ao email
                multiPartEmail.addTo(object.toString());
            }
            multiPartEmail.send();//envia
            return true;
        } catch (EmailException ex) {
            JOptionPane.showMessageDialog(null, ex.getMessage(), "Informação do Sistema", JOptionPane.ERROR_MESSAGE);
            Logger.getLogger(Email.class.getName()).log(Level.SEVERE, null, ex);
        }
        return false;
    }

    @Override
    public boolean enviar(byte[] arquivo) {
        try {
            multiPartEmail.attach(new ByteArrayDataSource(arquivo, "aplication/pdf"), //Converte Array de Bytes em um DataSource
                                  new SimpleDateFormat("yyyyMMdd HH:mm").format(new Date()) + ".pdf",//Nome do Arquivo escolhi que seria desta Forma
                                  "relatorio",
                                  EmailAttachment.ATTACHMENT);
        } catch (EmailException ex) {
            Logger.getLogger(Email.class.getName()).log(Level.SEVERE, null, ex);
        }
        return this.enviar();
    }

    @Override
    public void setPara(List<String> para) {
        this.para = para.toArray();
    }
   
    @Override
    public void setMensagem(String mensagem) {
        try {
            multiPartEmail.setMsg(mensagem);//Este Metodo deve ser chamado antes do anexo, caso contrario o texto nao será exibido
        } catch (EmailException ex) {
            Logger.getLogger(Email.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void setAssunto(String assunto) {
        multiPartEmail.setSubject(assunto);
    }

}

obs: Eu levei um tempo para descobrir um pequeno "Pulo do Gato", apesar de estar descrito da Documentação oficial, quando desejar enviar email com mensagem é necessario que no caso MultiPartEmail, o metodo referente ao corpo do email seja chamado antes ao metodo referente ao anexo, caso contrario  não irá funcionar como esperado.

sexta-feira, 7 de junho de 2013

[Linux] Criando Script SH de Backup Ubuntu part 2 - Armazenando e Compactando Tar e Gzip mãos a Obra!

Continuando... Agora irei demonstrar o basico para o armazenamento utilizando o Tar  e compactando com o Gzip.

tar -cvzf  /media/usbBackup/$Y$m$d-$H-$M-$S-Sever.tar.gz /home/denis/'VirtualBox VMs'/Server

Sendo o padrão de sintaxe: tar [parâmetros] [DESTINO] [ORIGEM], abaixo descreverei os parametros que utilizei.

  • -c  - extrai um arquivo para a saída padrão;
  • -v  - exibe detalhes sobre o procedimento;
  • -z  - Usada para que o arquivo seja compactado com gzip
  • -f   - Especifica o arquivo que será usado.
Sendo que utilizei a referencia a Part 1, para realizar a tarefa abaixo.Utilizei variaveis para guardar os valores ,Ano,Mes,Dia,Hora,Minuto e segundos "$Y$m$d-$H-$M-$S", quando se concatena varias variaveis nao se deve utilizar o underscore, eu utilizei ifen.


Y  `date + %Y`
m  `date + %m`
d   `date + %d`
H  `date + %H`
`date + %M`
S   `date + %S`



[Linux] Criando Script SH de Backup Ubuntu part 1 - Formatar nome de arquivo com Data e Hora

Bom dia!

 Vamos ao que interessa, na primeira parte  vou mostrar como conseguir formatar a data e hora para ser add ao nome do arquivo.. estarei usando o exemplo que faz parte da minha vida todos os dias rs.

1º Abrir o Terminal do Ubuntu, de forma simples apenas aperte ctrl+alt+t


2º Se digitar a palavra date será exibido na tela, o dia da semana, mes do ano, hora e ano.

3º Para pegar apenas a data de forma personalizada observe as variaveis abaixo.

  • %d - Mostra apenas o Dia ex: 07.
  • %m - Mostra apenas o Mes ex: 06.
  • %y - Mostra apenas o Ano ex: 13.
  • %H - Mostra apenas a Hora com duas Casas ex: 10
  • %M - Mostra apenas os Minutos duas Casas ex: 41
  • %S - Mostra apenas os Segundos duas Casas ex: 40

4º Para concatenar observe o exemplo digitando no terminal o seguinte comando:
"date +%d-%m-%y_%H:%M:%S" 

sábado, 19 de maio de 2012

Abrir aplicação padrao do Sistema Operacional (SO) Java

  -Em mais uma necessidade de saber como fazer tal coisa e fazer tal outra coisa vou deixar aqui a forma de abrir um arquivo com o programa padrão do SO usando Java.
  - Utilizei deste conhecimento para abrir uma foto em um JLabel.


  1. try {
  2.      Desktop.getDesktop().open(new File(pdf));//Sendo que pdf é o caminho do arquivo
  3. } catch (IOException ex) {
  4.      Logger.getLogger(FormAluno.class.getName()).log(Level.SEVERE, null, ex);
  5. }

B cannot be cast to java.sql.Blob

Bom dia!

   - Mais uma vez meus problemas me levam a aprender mais e mais, Amem!. Primeira vez que necessitei carregar uma imagem para um banco de dados, e claro eu nao sabia q é necessario um campo do tipo blob ou semelhantes.
 -  Entao segui alguns exemplos do guj, até que encontrei algo interessante e tentei. Porem ao tentar persistir os dados do banco tive um problema de Cast(Conversao) de um byte [] para um sql Blob, entao abaixo sintaxe de como fazer este cast.




  1. //Cria uma referencia a uma imagem ja transformada em Array de bytes
  2. byte [] imagem=imagem.getFoto()
  3. //Declara a variavel foto que seja uma variavel de instancia do objeto SerialBlob que recebe o Array
  4. Blob foto = new SerialBlob(imagem)

terça-feira, 15 de maio de 2012

Enumeration para Collection

Olá Galerinha!

 - Devido a um "Trabalho" da faculdade me vejo forçado a aprender sobre redes, mais exatamente como varrer uma rede local, é claro que para que isso ? Bom para saber as interfaces  de rede que um determinado host(Maquina) possui.
 - Pesquisei o InetAddress e o Inet4Addrees, classes para trabalhar com Host e seus Ip. Claro que elas não sabem como indentificar as propriedades das placas de redes quem faz isso é a interface NetworkInterface.

 - Em fim menos historia e mais ação, o problema com essa interface é que ela é velha demais, e ainda usa o Enumeration, que pelo o que andei lendo nao é usado desde a versao 1.2, existe uma forma de passar um Enumeration para um collection, a propria classe Collections possui um metodo para a conversão abaixo Codigo.


  1.  List<NetworkInterface> lista= Collections.list(NetworkInterface.getNetworkInterfaces());

quarta-feira, 22 de fevereiro de 2012

Criando Parametro e Modificando seu Tipo - iReport

Boa Tarde,.

 - Como meu Camarada Wellington estava com dificuldade nisso, vou postar um pequeno tópico informativo sobre como criar e modificar um parâmetro dentro do iReport o mesmo se aplica ao plugin do NetBeans.


1- Este é um relatorio bem simples que costumo usar as vezes, bom primeira parte é simples para criar basta clicar com o botão direito em parâmetros > Adicionar Parameter.


Depois de criado você deve renomear o mesmo para um nome que lhe seja agradável, essa é uma taréfa simples, mas notem na imagem abaixo meu caso as propriedades do parâmetro já estão abertas, Caso você crie e não apareça e só clicar com o direito no parâmetro e clicar em propriedades e vai aparecer a janela com as propriedades do seu parâmetro.


Nome: o nome dado ao parâmetro.
Parametrer Class: refere ao tipo do parâmetro.
Use as prompt:  refere-se a uma pequena caixa  solicitando o valor para o parâmetro todas as vezes que você visualizar o relatorio no iReport, se você não deseja preencher o parâmetro desclique a mesma e a caixa não ira aparecer. 
Default Value Expression : Para bom entendedor ... é a Expressão Padrão, ou valor padrão para o parâmetro.
Desciption: descrição
Properties: Caso deseje setar alguma propriedade não me lembro agora mas não recordo de utilizar isso.

Bom acredito que grande parte das pessoas que  esta prestando atenção, já tenha notado onde se modifica o tipo do parâmetro , para quem não notou é no campo Parametrer Class conforme podem ver abaixo existe grande partes das classes java utilizadas atualmente.
Bom espero que tenha ajudado é isso. 

sábado, 27 de agosto de 2011

Criação de Componente Personalizado NetBeans

Boa Noite

 - Bem para quem nao esta acostumado com a Ide netbeans, vai ver muita gente com dor de cabeça por que nao consegue personalizar a criação do  componente durante a criação, pois dizem que o codigo esta protegido... isso e meia verdade, vou usar como exemplo um JTable.


-Clicando no botao dentro do Circulo irá abrir a tela abaixo:

-Como podem ver digitei o codigo personalizado, que no caso utilizei um objeto da classe DefaultTableModel , detalhe essa classe tem o construtor sobrecarregado passei um Array com o Nome de cada Coluna no primeiro argumento e no segundo argumento um inteiro que será o total de linhas a iniciar esse modelo, notem como o codigo ficou na Ide apos essa inserção:


Observe a Linha 113.... como pode ver o codigo esta na parte que teoricamente nao se pode mexer bem simples, abraços.