sexta-feira, 17 de outubro de 2014

Hello World com Struts 2 - XML

Hoje iremos desmistificar como fazer um projeto simples com struts 2, usando sua abordagem XML. É importante que a pessoa que vá seguir este tutorial já tenha certas noções de Java, Java Web, Maven e Eclipse.

Já presenciei muita gente ficando confusa quando começavam a estudar struts 2, por diversos motivos:
  • A API é diferente se comparada com a do struts 1.
  • Não existe mais struts-config.xml.
  • As taglibs mudaram.
  • Outros milhares de motivos.
Minha proposta nesse post é mostrar o quão é simples o struts 2. Primeiro, devo dar total mérito ao grande mestre Mkyong porque foi de lá que tive a idéia de fazer esse post e inclusive, aprendi lá, a fazer meu primeiro projeto struts 2. Caso você não conheça o site dele, está abaixo.

http://www.mkyong.com/

Eu uso muito o site dele pois, lá existem vários tutoriais e manuais bem escritos e que ajudam muito os desenvolvedores a resolver seus problemas. Recomendo.

Se você é do tipo de pessoa que prefere baixar logo o projeto, segue link: https://www.dropbox.com/s/oppmiq9eyi8geny/workspace_helloworldstruts2.rar?dl=0

Porém, sem mais delongas. Vamos começar.

Passo 1 - Ambiente

Precisaremos dessas ferramentas:

  • Eclipse Luna 4.4.0
  • Apache Tomcat 7.0.54 (clique aqui para baixar)
  • Maven

Precisaremos de um projeto com esta arquitetura.


Caso você não saiba como montar um ambiente assim, recomendo fortemente que você dê uma olhada nesse post: http://precisoestudarsempre.blogspot.com.br/2014/07/como-criar-um-projeto-no-eclipse-com.html

Passo 2 - Dependências

Abra seu pom.xml e ponha a seguinte dependência.

        <dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.3.1.2</version>
</dependency>

Passo 3 - Configuração

Abra o web.xml e ponha a configuração abaixo.

         <filter>
<filter-name>struts2</filter-name>
<filter-class>
                org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
                </filter-class>
</filter>

<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

Nesse momento, você se pergunta: "Porque eu preciso declarar esse filtro ?" Esse filtro é necessário e importante porque ele que é responsável por fazer o dispatching das requisições, ou seja, ele que redireciona a requisição HTTP para sua action correta.

Passo 4 - Mapeamento

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

<package name="cliente" namespace="/Cliente" extends="struts-default">
<action name="IniciarCadastro">
<result>/WEB-INF/pages/cad-cliente.jsp</result>
</action>
<action name="Cadastrar" class="action.ClienteAction">
<result name="SUCCESS">/WEB-INF/pages/det-cliente.jsp</result>
</action>
</package>

</struts>

A única observação que faço aqui é que os atributos name e namespace são diferentes. O primeiro atributo só representa um nome a fim de, identificar o package. O segundo representa espaço de nomes da requisição, exemplo:

http://localhost:8080/HelloWorldStruts2/Cliente/Cadastrar.action

Passo 5 - Montagem da action

public class ClienteAction {
private Cliente cliente;
 
public String execute() {
cliente.setId(1L);
cliente.setNome(cliente.getNome().toUpperCase());
return "SUCCESS";
}

public Cliente getCliente() {
return cliente;
}

public void setCliente(Cliente cliente) {
this.cliente = cliente;
}
}

Para criar uma action não é necessário estender alguma classe. Basta ter um método execute e pronto. Porém, em alguns exemplos você irá ver alguns desenvolvedores utilizando a classe ActionSupport ou a interface Action. Não se espante !! Essas classes oferecem métodos utilitários para ajudar o desenvolvedor.

Passo 6 - JSP

No nosso projeto existem duas JSPs. A primeira é um formulário de cadastro e a outra somente exibe os dados cadastrados.

Formulário de cadastro
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head></head>
<body>
<h1>Struts 2 Hello World Example</h1>

<s:form action="Cadastrar" >
<s:textfield name="cliente.nome" label="Nome" />
<s:textfield name="cliente.email" label="E-mail" />
<s:textfield name="cliente.dataNascimento" label="Data de Nascimento" />
<s:submit />
</s:form>

</body>

</html>

Reparem que o nome especificado na action é o mesmo que foi definido no struts.xml. A tag <s:textfield> cria um campo de texto, o atributo name representa o objeto que armazenará o dado e o atributo label dispensa explicação. A tag <s:submit> cria um <input type="submit">.

Exibição de dados
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head></head>
<body>
<h1>Struts 2 Hello World Example</h1>

<h4>
Dados do cliente
</h4>

Id: <s:property value="cliente.id" /><br/>
Nome: <s:property value="cliente.nome" /><br/>
E-mail: <s:property value="cliente.email" /><br/>
Data de Nascimento: <s:date name="cliente.dataNascimento" format="dd/MM/yyyy"/>

<br/>
<br/>
<a href="javascript:history.back()">Voltar</a>
</body>
</html>


A tag <s:property> exibe algo que esteja no request e a tag <s:date> é utilizada para datas. Ela oferece a opções de formatação e exibição.

Acesse: http://localhost:8080/HelloWorldStruts2/Cliente/IniciarCadastro.action

Abaixo, deixo alguns links muito bons para consulta:

Documentação do <s:date> - http://struts.apache.org/release/2.3.x/docs/date.html
Documentação da classe StrutsPrepareAndExecuteFilter - http://struts.apache.org/release/2.1.x/struts2-core/apidocs/org/apache/struts2/dispatcher/ng/filter/StrutsPrepareAndExecuteFilter.html
Struts 2 Hello World Example Mkyong - http://www.mkyong.com/struts2/struts-2-hello-world-example/
Download do projeto pronto: https://www.dropbox.com/s/oppmiq9eyi8geny/workspace_helloworldstruts2.rar?dl=0
Download do Tomcat: https://www.dropbox.com/s/ufln5t05aaqb59d/apache-tomcat-7.0.54.rar?dl=0

Caso eu tenha deixado algum ponto solto ou, cometi algum erro. Deixe sua contribuição nos comentários.
Leia Mais ››

quarta-feira, 15 de outubro de 2014

Tutorial Struts 2 + JasperReports

Caros leitores, foi muito difícil encontrar um tutorial ou manual de Struts 2 + Jasper Reports que fosse rico em detalhes. Encontrei uns tutoriais que explicavam como eu podia fazer mas, não diziam quais eram as versões de libs utilizadas. Isso causou horas e horas de tentativas e erros. Então, para solucionar eu tive que testar as várias combinações de versões de libs mas, enfim cheguei a combinação correta.

Caso você seja aquele tipo de pessoa apressada, disponibilizo aqui o projeto pronto para estudo. Clique aqui para baixar o projeto e, aqui para baixar o tomcat.

Então, sem mais firulas, vamos à lista de ingredientes.

  • Eclipse Luna (4.4.0)
  • Maven
  • Struts 2.3.1.2
  • Jasper Reports 5.1.0
  • Struts2 Jasper Reports plugin 2.3.16.3
  • Javax Servlet 2.5
  • Tomcat 7.0.54
Neste post não irei abordar como confeccionar o jrxml. No projeto já existem um jrxml e um jasper prontos. Logo, não se preocupe.

Mãos à massa !!!

Crie uma action chamada JasperAction e faça essa classe herdar de ActionSupport. Crie um atributo do tipo ArrayList com o nome de myList, crie seus métodos get e set; e um método execute, com essa assinatura.

public String execute() throws Exception {}

O atributo myList representa o datasource do nosso relatório. Datasource é a fonte de dados usada para o relatório. Essa fonte pode ser expressa de algumas formas, dentre as quais temos:uma conexão de banco, uma lista de objetos ou um data source vazio (JREmptyDataSource). No nosso exemplo será uma lista de objetos do tipo Person.

Crie a classe Person. Essa classe possuirá os atributos:
  • id - Long
  • name - String
  • lastName - String
Crie os gets e sets e os seguintes construtores:


    public Person() {
    }
    public Person(String name, String lastName) {
        this.name = name;
        this.lastName = lastName;
    }
    public Person(Long id, String name, String lastName) {
        this.id = id;
        this.name = name;
        this.lastName = lastName;
    }

Agora basta criar objetos do tipo Person e adicioná-los à lista. Feito isso, pronto !! Nossa action já está terminada. Agora você se pergunta:

"Mas, eu sei que no struts 1 eu precisava invocar as classes do Jasper, passando como parâmetro o caminho do jrxml, o datasource e os possíveis parâmetros o qual, é um HashMap. Depois disso, gero um array de bytes e passo isso para o response, defino um content type, um content disposition (habilitar para download), realizo o write, faço o flush e o close do response. Aonde está tudo isso aí !?"

Bem, vamos as respostas. De fato ainda é necessário definir os parâmetros dentro de um HashMap mas, isso foi melhorado. Mas, essa melhora não só afeta a passagem de parâmetros do relatório mas, como afeta toda a forma de se utilizar Jasper Reports com Struts 2. Agora, não é mais necessário executar todos esses passos que eram feitos no Struts 1 basta, eu definir meu datasource e parâmetros. Feito isso, o Struts 2 lida com o resto. Mas, como ele lida ?

Vá ao struts.xml e mapeie sua action desta forma.

<package name="jasper" namespace="/Jasper" extends="jasperreports-default">
   <action name="myJasperTest" class="action.JasperAction">
       <result name="success" type="jasper">
           <param name="location">/WEB-INF/jasper/template.jasper</param>
           <param name="contentDisposition">attachment;filename="arq.pdf"</param>
           <param name="dataSource">myList</param>
           <param name="format">PDF</param>
       </result>
   </action>
</package>

Não irei explicar aqui o que significa as tags <package>, <action>, <result>, <param>. Caso queira maiores explicações, acesse os links abaixo:


Quero que neste momento você note em duas coisas. A primeira é o extends do meu package e a segunda é o type="jasper" do meu result. Tanto o extends quanto o type estão definidos no plugin Struts 2 Jasper Reports. Lá é definido que os parâmetros (<param>) definidos no mapeamento irão para uma classe específica do plugin (JasperReportsResult) e ela irá fazer todo aquele processamento de geração do relatório.

Note a inversão de controle (IoC) acontecendo de forma linda. S2 S2 S2

O parâmetro location simboliza aonde está o arquivo jasper, o parâmetro contentDisposition simboliza como o arquivo será disponibilizado. No nosso caso, será um download. O parâmetro de dataSource é o que foi falado no início do tópico. Porém, repare que o mesmo nome escrito aí, é o mesmo nome do atributo da nossa action. Isto é necessário pois, um "get" será realizado. Por último, temos o parâmetro format que, como o nome já diz é o formato do arquivo.

Agora, é só abrir o browser e acessar essa url.


Gostou ? Não gostou ? Achou coisa errada ? Comente abaixo que iremos resolver juntos.

OBSERVAÇÃO: Caso você tenha alguma curiosidade de saber como o plugin funciona ou ver como funciona a questão do extends e do type, baixe o JAR do plugin, descompacte-o com o WinRar e veja o arquivo struts-plugin.xml.
Leia Mais ››

quinta-feira, 9 de outubro de 2014

Java + FTP - É possível ?

Construir um projeto Java que precise utilizar de um servidor FTP, é possível ? Terei de usar ferramentas externas para ter acesso aos arquivos ? O que é FTP ?

Todas essas perguntas serão respondidas hoje. Vamos começar pelo começo. FTP é a sigla para File Transfer Protocol o qual, é um protocolo da camada de Aplicação do modelo OSI. Como o próprio nome já diz, esse protocolo é usado para transferência de arquivos. Não entrarei a fundo na explicação do FTP. O que você precisa saber para este tópico está escrito neste parágrafo.

Construir um projeto Java que precise utilizar de um servidor FTP, é possível ? Sim, é possível e não somente, é possível como, é fácil também.

Terei de usar ferramentas externas para ter acesso aos arquivos ? Não. Salvo somente os casos em que seja obrigatório usar alguma ferramenta externa ou, seja de vontade do próprio desenvolvedor.

Agora que já sabemos que é possível trabalhar com Java + FTP, vamos ao exemplo.

Primeira etapa - Montar o ambiente

Montar um ambiente Java + FTP é fácil. Precisamos de:

  • Eclipse Luna (4.4.0)
  • Maven (se quiser)
  • Jar Commons Net 3.3 (caso não use Maven)
Caso você não queira usar o Maven, sem problemas. Baixe o JAR do Commons Net, clicando aqui. No nosso exemplo usaremos o Maven. Crie um Maven Project com o archtype quickstart. Caso você possua alguma dúvida com a criação do projeto, nosso amigo Mkyong realizou uma ótima contribuição, através do link.Com o projeto criado, insira a seguinte dependência:

<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.3</version>
</dependency>

Depois de ter inserido a dependência, já podemos começar a programar.

Segunda etapa - Programação

Para habilitar o FTP na sua máquina é necessário realizar algumas configurações no Windows, clique aqui para mais informações. Com seu servidor FTP habilitado e criado, vamos para o Java.

Crie uma classe com o nome de App. Depois de ter criado a classe, vamos criar duas constantes (LOGIN e PASSWORD).

private static final String LOGIN = "meu_usuario";
private static final String PASSWORD = "minha_senha";

Crie um método main e crie um método chamado gerarConexao(). Este método será responsável por gerar a conexão FTP e retornar o objeto que representa o mesmo.

private FTPClient gerarConexao() throws SocketException, IOException{
    FTPClient ftpClient = new FTPClient();
    ftpClient.connect("127.0.0.1"); //Conecta ao Servidor FTP
    ftpClient.login(LOGIN, PASSWORD); //efetua o login no Servidor
    //ftpClient.changeWorkingDirectory("minha_pasta"); //Muda o diretório de trabalho do servidor
    return ftpClient;
}

O código acima é bem tranquilo. Creio que não necessito fazer mais explicações.

Com o nosso método de realizar conexões feito, podemos trabalhar diretamente com os arquivos. Vamos agora, listar todos os arquivos do servidor. Construa o método lerArquivos(FTPClient ftpClient). Este método recebe uma instância de FTPClient o qual, representa nossa conexão.

private void lerArquivos(FTPClient ftpClient) throws IOException{
    FTPFile[] arqs = ftpClient.listFiles(); //lista os arquivos
        System.out.println ("Listando arquivos: \n");
        for (FTPFile f : arqs){
        System.out.println(f.getName() + " - " + f.getType()); //imprimo o nome do arquivo e seu tipo
        }
}

O método acima também é bem tranquilo. Abaixo, listo alguns métodos de listagem de arquivos.
  • listFiles() - Retorna uma lista de Objetos do tipo FTPFile. Para mais informações sobre a classe, clique aqui.
  • listNames(String caminho) – Mesmo que o anterior, mas passando como parâmetro o caminho do diretório a ser listado.
  • listNames() - Retorna um array de Strings contendo o nome dos arquivos no diretório de trabalho atual.
Agora vamos escrever um método para por arquivos no nosso servidor FTP. Escreva o método escreverArquivo(FTPClient ftpClient). Este método recebe uma instância de FTPClient 
qual, representa nossa conexão.

private void escreverArquivo(FTPClient ftpClient) throws IOException{    
    FileInputStream novoArq = new FileInputStream("C:\\minha_pasta\\arquivo_origem.txt");
    if(ftpClient.storeFile("nome_novo_arquivo.txt", novoArq)){
    System.out.println("Arquivo armazenado com sucesso!");
    } else {
    System.out.println("Erro ao armazenar o arquivo.");
    }
}

O método acima cria um novo arquivo no FTP com o nome especificado no primeiro parâmetro do método storeFile. Este método retorna um boolean que, informa se a criação foi feita com sucesso ou não. O parâmetro novoArq representa o arquivo de origem da gravação.

Nosso último método, terá a tarefa de realizar o download de um arquivo que está no FTP. Construa o método recuperarArquivo(FTPClient ftpClient). Este método recebe uma instância de FTPClient o qual, representa nossa conexão.

private void recuperarArquivo(FTPClient ftpClient) throws IOException{
    FileOutputStream fos = new FileOutputStream("C:\\minha_pasta\\arquivo_download.txt");
    if (ftpClient.retrieveFile("arquivo_fonte.txt", fos ))
    System.out.println("Download efetuado com sucesso!");
    else
            System.out.println ("Erro ao efetuar download do arquivo.");
}

Acima, é possível notar que o método retrieveFile recebe dois parâmetros. O primeiro parâmetro representa o nome do arquivo que será feito o download e o segundo representa o destino do arquivo. Este método retorna um boolean que, indica se houve êxito ou não.

Precisamos de um método agora para realizar desconexão do nosso programa com o servidor FTP. Escreva o método logout(FTPClient ftpClient). Este método recebe uma instância de FTPClient o qual, representa nossa conexão.

private void logout(FTPClient ftpClient) throws IOException{
    ftpClient.logout();
    ftpClient.disconnect();
}

Este método dispensa explicações. Por último, temos o método main que chama todos os outros métodos.

public static void main( String[] args ) throws SocketException, IOException 
    {
    App app = new App();
    FTPClient ftpClient = app.gerarConexao();
    app.lerArquivos(ftpClient);
    app.escreverArquivo(ftpClient);
    app.recuperarArquivo(ftpClient);
    app.logout(ftpClient);
    }

Caso você queira baixar o projeto, clique aqui.

É possível notar, que trabalhar com Java e FTP é simples. Procurei por uma abordagem 100% Java mas, não achei. Quem souber, deixe nos comentários sua contribuição. A API Commons Net faz todo o trabalho pesado e para o desenvolvedor só fica a tarefa de processar os arquivos.

Referências:
http://www.devmedia.com.br/desenvolvendo-um-cliente-ftp/3547
Leia Mais ››

quarta-feira, 8 de outubro de 2014

Sugestão de site para modelagem de banco

Caros leitores, a dica de hoje é o site databaseanswers. A proposta desse site é muito interessante. Nele existem vários modelos prontos, todos esperando para ser usados por você. Ééééé simmmm, você mesmo que, é iniciante e quer fazer algum tipo de projetinho mas, não tem idéia da modelagem ou do que fazer. Então, os seus problemas acabaram. Agora é a sua hora de montar o seu banco e começar a programar.

Para acessar um modelo basta, seguir os seguintes passos:

Acessar a página

Escolha um tema

Salve a imagem



É importante observar que todos os modelos já são normalizados e que nenhum tipo de script é disponibilizado, ou seja, é necessário que você monte os scripts por sua conta.
Então, mãos à massa. O link está abaixo.

http://www.databaseanswers.org/data_models/index.htm

Agradecimento especial ao meu amigo Delson Vercosa Jr. o qual, descobriu esse site e comentou comigo.




Leia Mais ››

sexta-feira, 3 de outubro de 2014

Importância de seguir por email o blog

Caros leitores,

no canto direito superior da tela, existe um campo de texto chamado "Seguir por email".


Este campo serve para que, você, caro leitor, ponha seu e-mail e acompanhe as novidades do blog Preciso Estudar Sempre. Para cada post criado, você receberá um e-mail informativo.

Depois de escrever seu e-mail no campo de texto, aperte o botão Submit. Após ter sido pressionado, uma janela será aberta com um captcha a ser preenchido.


Preencha o captcha corretamente e aperte o botão Complete Subscription Request.



IMPORTANTE: Você receberá um e-mail com um link para ativação de sua inscrição. Clique no link e ative sua inscrição. Não apague este e-mail antes de clicar no link, ele é importante. Se você não clicar no link, sua inscrição não estará completa e você não conseguirá receber as novidades do blog.

Feito tudo isso, está pronto. Agora é só acompanhar as novidades do blog. Então, não perca tempo :D
Leia Mais ››

segunda-feira, 29 de setembro de 2014

Processamento de texto com JFileHelper

Caros leitores, resolvi escrever esse post porque não achei muito material referente a essa tecnologia. Logo, espero ajudar e contribuir a todas as pessoas que precisam de uma ajuda e não conseguiu encontrar.

A API JFileHelper serve para processamentos de texto e no meu caso foi usado para processar arquivos do formato txt mas, não sei, se é possível processar arquivos em outros formatos. Acredito que não pois, no site da API não diz nada sobre isso.

Nesse post serão usados os exemplos do site da API, a fim de facilitar o processo de aprendizagem. É possível processar texto com diferentes formatos. Quando digo formatos, quero dizer que a API suporta arquivos em que seus campos estão separados por algum caracter (, | . ; -) ou espaçamento.

Não irei abordar aqui todo o poderio que a API possui. Caso queira tal conhecimento, aconselho que visite o site oficial:

http://jfilehelpers.com/

No nosso exemplo, usaremos um arquivo em que seus campos possuem tamanho fixo. Segue abaixo:


Os pontinhos representam a quantidade de posições que cada campo possui. Para tal arquivo de texto, precisaremos construir uma classe com a seguinte estrutura.


Agora vamos às explicações e curiosidades.

@FixedLengthRecord() -> Determina que está classe irá lidar com arquivos de tamanho fixo.

@FieldFixedLength(inteiro) -> Determina que o atributo marcado terá somente o número de posições especificadas na anotação.

@FieldAlign(alignMode=AlignMode.Right) -> Determina que o campo marcado será alinhado à direita quando for retirado do texto. Para mais informações, visitar o seguinte site:

https://github.com/fcoury/jfilehelpers/blob/master/Source/src/org/coury/jfilehelpers/enums/AlignMode.java

@FieldTrim(trimMode=TrimMode.Right) -> Determina que o campo marcado terá seus espaços em branco retirados à direita. Para mais informações, visitar o seguinte site:

https://github.com/fcoury/jfilehelpers/blob/master/Source/src/org/coury/jfilehelpers/enums/TrimMode.java

@FieldConverter(converter = ConverterKind.Date, format = "dd-MM-yyyy") -> Determina que o campo será convertido para a classe especificada no atributo converter e no formato especificado no atributo format. Para mais informações, visitar o seguinte site:

https://github.com/fcoury/jfilehelpers/blob/master/Source/src/org/coury/jfilehelpers/annotations/FieldConverter.java

https://github.com/fcoury/jfilehelpers/blob/master/Source/src/org/coury/jfilehelpers/enums/ConverterKind.java

@FieldOptional -> Determina que o campo será opcional.

@FieldIgnored -> Determina que o atributo marcado será ignorado no processamento do texto.

CURIOSIDADE: A API funciona de forma posicional, ou seja, a ordem dos atributos é importante. No nosso exemplo, possuíamos o atributo name, o qual era precedido pelo atributo custId. No arquivo esta ordem deve ser mantida e vice-versa.

Caro leitor, se você possuir algum conhecimento sobre tal tecnologia ou, notar que cometi algum erro, sendo primário ou não, enriqueça-nos com seu comentário abaixo.
Leia Mais ››

segunda-feira, 8 de setembro de 2014

Projeto Spring MVC para estudos

Pessoal vou por aqui zipado um projeto pronto para fins de estudo. O projeto possui as seguintes tecnologias:


  • Spring MVC , Core, ORM e AOP 3.1.2
  • JPA
  • Hibernate 4.1.7
  • JSP e JSTL 1.2
  • JasperReports 5.1.0
  • MySQL 5.1.18
  • Servlet 1.0.1
  • Tiles 2.2.2
  • Gson 2.2.4
  • Javax Mail 1.4.3
  • Tomcat v7.0.54

Leia Mais ››