JAVA + Spring + Netbeans 7.2 - Mysql + CRUD + Struts Lesson 08
Autor: Mario Cezzare Angelicola Chiodi | Publicado: 2012-10-01T18:40:00-07:00




 

 

 

 

 

 

 

 

 

 

 

 

 

 

 
SyntaxHighlighter.config.bloggerMode = true;
SyntaxHighlighter.config.clipboardSwf = 'http://alexgorbatchev.com/pub/sh/current/scripts/clipboard.swf';
SyntaxHighlighter.all();
 
Dando&nbsp;seqüência&nbsp;nos posts de JAVA + Spring, agora vou apresentar o Framework Apache Struts

(ainda não pus a legenda das imagens&nbsp;)
Requisitos :
-&nbsp;Netbeans 7.2
-&nbsp;spring-3.2.0.M2&nbsp;-- link direto
- estar com o banco mysql springlessons, e a tabela contato criada. ver lição 4,5, 6 ou 7
- Struts 1.3.10 (utilizarei a dist que já vem com o NB)


- Ter lido :


Posts Anteriores :&nbsp;

JSNBTut - Base&nbsp;&nbsp;que é uma preparação do ambiente para o desenvolvimento

Opcionais :&nbsp;

JSNBTut - Lesson 01&nbsp;- introdução ao Spring
JSNBTut - Lesson 02&nbsp;-&nbsp;introdução ao gerenciamento de dependências no &nbsp;Spring
JSNBTut - Lesson 03&nbsp;- acessando banco de dados Mysql com beans e injeção de dependências
JSNBTut - Lesson 04&nbsp;-&nbsp;outro jeito rápido de utilizar o Spring e Mysql sem utilizar Arquivos XML.
JSNBTut - Lesson 05&nbsp;-&nbsp;comparação entre as implementações e introdução ao Swing. Jtable + DefaultTableModel e implementação de uma TableModel, ...

Obrigatório:
JSNBTut - Lesson 06&nbsp;- implementando um CRUD ao exemplo , que é o projeto que continuaremos neste post.
JSNBTut - Lesson 07- Finalizando o &nbsp;CRUD completo em Java &nbsp; utilizando&nbsp;Swing e&nbsp;&nbsp;Spring-&nbsp;Implementamos um validador com&nbsp;org.springframework.validation.Validator-&nbsp;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&nbsp;build&nbsp;do projeto no build.xml


Lembrando a estrutura da nossa tabela do mysql


Figura 01 - Tabela Contato



CREATE  TABLE IF NOT EXISTS `springlessons`.`contato` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `nome` VARCHAR(45) NULL ,
  `telefone` VARCHAR(45) NULL ,
  PRIMARY KEY (`id`) )
ENGINE = InnoDB


OBS : as vezes o nome do meu servidor Mysql pode aparece como ns1 (quando estou no escritório) ou localhost (quando estou no lap). Relax, o banco é o mesmo, ok ?


Este é o 8º da série , o objetivo deste post é implementar o programa que terminamos na lição 07 na web. &nbsp;Para isso utilizaremos o framework Struts, e depois integraremos com o Spring.
Algumas info antes de criar o projeto web. Quando se trata de JSP, já existem alguns padrões de implementação e organização dos arquivos :

1) Vendo a organização do projeto (arquivos e pastas)
I ) exemplo criado com o o Maven :
Comando :&nbsp;mvn archetype:generate -DgroupId=com.myapp -DartifactId=meuscontatos-webapp -DarchetypeArtifactId=maven-archetype-webapp


Figura 02 - Gerando um projeto baseado no Maven




Figura 03 - Arquivos gerado pelo mvn


II) o Struts fornece um exemplo também p/ iniciar um projeto, após descompactar a lib do struts veja a pasta apps tem um arquivo&nbsp;struts-blank-1.3.10.war (que é um zip. descompacte esse arquivo)


Figura 04 - Exemplos do struts 1




Figura 05 - Arquivos do exemplo&nbsp;


Então vimos que uma webApp contém a seguinte estrutura (com variações de implementação):

Projeto
--src
&nbsp; --conf : arquivo Manifest
&nbsp; --java : packages e classes Java e arquivos .properties
--web ouWebContent
&nbsp; &nbsp;---META-INF
&nbsp; &nbsp; &nbsp; &nbsp;--context.xml
&nbsp; &nbsp;---WEB-INF
&nbsp; &nbsp; &nbsp; &nbsp;--Arquivos.xml ; normalmente aqui vão o web.xml. o beans.xml, struts-config.xml e TLDs
&nbsp; &nbsp;--Arquivos JSP e html, images, js, css, etc..

então vamos criar a webapp no NB:

2) Criando o Projeto Web



Figura 06 - Novo Projeto




Figura 07 - Nome do projeto




Figura 08 - Defina Servidor Tomcat ou GlassFish




Figura 09 - Adicionando o Struts 1.3.10 que vem com o NB




Figura 10 - Projeto com a inclusão do Struts




Figura 11 - Teste o projeto




Figura 12 - Teste pelo Run Projet



Figura 13 - Teste pelo Run Projet pasando a URL na mão





Figura 14 - Output do NB



O q está acontecendo aqui ? (da maneira mais simples)
Nossa aplicação contém arquivos XML que definem o comportamento dos servlets e algumas configurações.

I) Ao carregar a app,
O arquivo struts-config.xml informou uma action de nome Welcome apontado /Welcome.do
Veja o nosso arquivo struts-config.xml sem os comentários :

&lt;?xml version="1.0" encoding="UTF-8" ?&gt;

&lt;!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
          "http://jakarta.apache.org/struts/dtds/struts-config_1_3.dtd"&gt;


&lt;struts-config&gt;
    &lt;form-beans&gt;
    
    &lt;/form-beans&gt;
    
    &lt;global-exceptions&gt;
    
    &lt;/global-exceptions&gt;

    &lt;global-forwards&gt;
        &lt;forward name="welcome"  path="/Welcome.do"/&gt;
    &lt;/global-forwards&gt;

    &lt;action-mappings&gt;
        &lt;action path="/Welcome" forward="/welcomeStruts.jsp"/&gt;
    &lt;/action-mappings&gt;
    
    &lt;controller processorClass="org.apache.struts.tiles.TilesRequestProcessor"/&gt;

    &lt;message-resources parameter="com/myapp/struts/ApplicationResource"/&gt;    
    
    &lt;!-- ========================= Tiles plugin ===============================--&gt;
    &lt;!-- ..... Paths found in Tiles definitions are relative to the main context.
    --&gt;
    &lt;plug-in className="org.apache.struts.tiles.TilesPlugin" &gt;
        &lt;set-property property="definitions-config" value="/WEB-INF/tiles-defs.xml" /&gt;      
        &lt;set-property property="moduleAware" value="true" /&gt;
    &lt;/plug-in&gt;
    
    &lt;!-- ========================= Validator plugin ================================= --&gt;
    &lt;plug-in className="org.apache.struts.validator.ValidatorPlugIn"&gt;
        &lt;set-property
            property="pathnames"
            value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/&gt;
    &lt;/plug-in&gt;
  
&lt;/struts-config&gt;


II) e de onde vem esse .do no fim da solicitação http&nbsp;?
R: da configuração do arquivo web.xml, observe a inicial :
Atenção :
- Na linha&nbsp;&lt;load-on-startup&gt;2&lt;/load-on-startup&gt; dentro da tag &lt;servlet&gt;&nbsp;
- No conjunto &lt;jsp-config&gt; que adicionei as TLDs &nbsp;junto com o projeto. Pode-se usar a url do site, mas e se a WebApp estiver num servidor que não acessa a Internet ?
- E o .do está sendo "resolvido" pela tag &lt;servlet-mapping&gt; com um pattern .do .



&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"&gt;
    &lt;servlet&gt;
        &lt;servlet-name&gt;action&lt;/servlet-name&gt;
        &lt;servlet-class&gt;org.apache.struts.action.ActionServlet&lt;/servlet-class&gt;
        &lt;init-param&gt;
            &lt;param-name&gt;config&lt;/param-name&gt;
            &lt;param-value&gt;/WEB-INF/struts-config.xml&lt;/param-value&gt;
        &lt;/init-param&gt;
        &lt;init-param&gt;
            &lt;param-name&gt;debug&lt;/param-name&gt;
            &lt;param-value&gt;2&lt;/param-value&gt;
        &lt;/init-param&gt;
        &lt;init-param&gt;
            &lt;param-name&gt;detail&lt;/param-name&gt;
            &lt;param-value&gt;2&lt;/param-value&gt;
        &lt;/init-param&gt;
        &lt;load-on-startup&gt;2&lt;/load-on-startup&gt;
    &lt;/servlet&gt;
    &lt;servlet-mapping&gt;
        &lt;servlet-name&gt;action&lt;/servlet-name&gt;
        &lt;url-pattern&gt;*.do&lt;/url-pattern&gt;
    &lt;/servlet-mapping&gt;
    &lt;session-config&gt;
        &lt;session-timeout&gt;
            30
        &lt;/session-timeout&gt;
    &lt;/session-config&gt;
    &lt;welcome-file-list&gt;
        &lt;welcome-file&gt;index.jsp&lt;/welcome-file&gt;
    &lt;/welcome-file-list&gt;
    &lt;jsp-config&gt;
        &lt;taglib&gt;
            &lt;taglib-uri&gt;/WEB-INF/struts-bean.tld&lt;/taglib-uri&gt;
            &lt;taglib-location&gt;/WEB-INF/struts-bean.tld&lt;/taglib-location&gt;
        &lt;/taglib&gt;
        &lt;taglib&gt;
            &lt;taglib-uri&gt;/WEB-INF/struts-html.tld&lt;/taglib-uri&gt;
            &lt;taglib-location&gt;/WEB-INF/struts-html.tld&lt;/taglib-location&gt;
        &lt;/taglib&gt;
        &lt;taglib&gt;
            &lt;taglib-uri&gt;/WEB-INF/struts-logic.tld&lt;/taglib-uri&gt;
            &lt;taglib-location&gt;/WEB-INF/struts-logic.tld&lt;/taglib-location&gt;
        &lt;/taglib&gt;
        &lt;taglib&gt;
            &lt;taglib-uri&gt;/WEB-INF/struts-nested.tld&lt;/taglib-uri&gt;
            &lt;taglib-location&gt;/WEB-INF/struts-nested.tld&lt;/taglib-location&gt;
        &lt;/taglib&gt;
        &lt;taglib&gt;
            &lt;taglib-uri&gt;/WEB-INF/struts-tiles.tld&lt;/taglib-uri&gt;
            &lt;taglib-location&gt;/WEB-INF/struts-tiles.tld&lt;/taglib-location&gt;
        &lt;/taglib&gt;
    &lt;/jsp-config&gt;
&lt;/web-app&gt;



III) é chamado o arquivo welcomeStruts.jsp :


Figura 15 - arquivo welcomeStruts.jsp


Observe as linhas : &lt;beans:message&gt; a chave (key) welcome.Propriedade



IV) Essa definições estão no arquivo ApplicationResource.properties dentro do package com.app.struts&nbsp;


Figura 16 - Arquivo properties




observe as linhas finais :


welcome.title=Struts Application

welcome.heading=Struts Applications in Netbeans!

welcome.message=It's easy to create Struts applications with NetBeans.





3) Implementando nossas classes ao projeto:


Vamos manipular a tabela contato do banco, certo ? Precisamos de :&nbsp;

0) adicionar o driver do Mysql ao projeto

1) um modelo Contato

2) uma interface DAO

3) uma classe que implemente a interface DAO

4) uma interface de Serviço

5) uma classe que implemente a interface&nbsp;de Serviço

6) das classes p/ atender os actions que serão mapeados no arquivo struts-config.xml, que extendem a classe&nbsp;org.apache.struts.action.Action,&nbsp;

7) definir as actions e mappings&nbsp;no arquivo&nbsp;struts-config.xml

8) criar a view (interface para o usuário), definindo um form
9) criar uma página que mostre os erros quando acontecer

OBS: ainda não vou utilizar o spring, depois implementaremos:



Mãos a obra..


0) Adicione a Lib do Mysql:


Figura 17 - Adicione a lib do Mysql




1) Criando o modelo :


Figura 18 - Criando o modelo Contato


defina 3 variávess:
int id;
String nome;
String telefone , e escolha refactor&gt;&gt; encapsulate Fields


Figura 19 - Encapsulando a classe Contato


CODE
package com.myapp.model;

public class Contato {
    private int id;
    private String nome;
    private String telefone;

    public Contato() {
        this.id=0;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public String getTelefone() {
        return telefone;
    }

    public void setTelefone(String telefone) {
        this.telefone = telefone;
    }
}



2)&nbsp;Criando&nbsp;uma interface DAO


Figura 20 - Interface DAO



CODE
package com.myapp.dao;

import com.myapp.model.Contato;
import java.util.List;

public interface ContatoDao {

    public void create(Contato contato);

    public List&lt;Contato&gt; findAll();
}


3)&nbsp;Criando&nbsp;uma classe que implemente a interface DAO


Figura 21- Criando a implementação da &nbsp;interface




Figura 22 - nome da Classe de implementação



CODE
package com.myapp.dao;

import com.myapp.model.Contato;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

public class ContatoDaoImpl implements ContatoDao {

    static {

        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (Exception ex) {
            Logger.getLogger(ContatoDaoImpl.class.getName()).log(Level.SEVERE, null, ex);
            throw new ExceptionInInitializerError(ex);
        }

    }

    private Connection getConnection() throws SQLException {
        return DriverManager.getConnection("jdbc:mysql://ns1/springlessons", "springlessons", "DHADdSXcDF29WGXy");
    }

    @Override
    public void create(Contato contato) {
        Connection Con = null;
        PreparedStatement pstm = null;
        try {
            Con = getConnection();
            String sql = "INSERT INTO `springlessons`.`contato`"
                    + "(`nome`,`telefone`)"
                    + " VALUES (?,?)";
            pstm = Con.prepareStatement(sql);
            pstm.setString(1, contato.getNome());
            pstm.setString(2, contato.getTelefone());
            pstm.executeUpdate();

        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            try {
                pstm.close();
            } catch (Exception e) {
                Logger.getLogger(ContatoDaoImpl.class.getName()).log(Level.SEVERE, null, e);
            }
            try {
                Con.close();
            } catch (Exception e) {
                Logger.getLogger(ContatoDaoImpl.class.getName()).log(Level.SEVERE, null, e);
            }
        }
    }

    @Override
    public List&lt;Contato&gt; findAll() {
        Connection Con = null;
        PreparedStatement pstm = null;
        ResultSet rs = null;
        try {
            Con = getConnection();
            String sql = "SELECT `contato`.`id`,`contato`.`nome`,`contato`.`telefone`"
                    + " FROM `springlessons`.`contato`";
            pstm = Con.prepareStatement(sql);
            List&lt;Contato&gt; contatos = new ArrayList&lt;Contato&gt;();
            rs = pstm.executeQuery(sql);

            while (rs.next()) {
                Contato contato = new Contato();
                contato.setId(rs.getInt("id"));
                contato.setNome(rs.getString("nome"));
                contato.setTelefone(rs.getString("telefone"));
                contatos.add(contato);
            }

            return contatos;
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            try {
                pstm.close();
            } catch (Exception e) {
                Logger.getLogger(ContatoDaoImpl.class.getName()).log(Level.SEVERE, null, e);
            }
            try {
                Con.close();
            } catch (Exception e) {
                Logger.getLogger(ContatoDaoImpl.class.getName()).log(Level.SEVERE, null, e);
            }
        }
    }
}




4)&nbsp;Criando&nbsp;uma interface de Serviço


Figura 23 - criando a interface de Serviço



CODE
package com.myapp.service;

import com.myapp.model.Contato;
import java.util.List;


public interface ContatoService {

    public void create(Contato contato);

    public List&lt;Contato&gt; findAll();
}




5)&nbsp;Criando&nbsp;uma classe que implemente a interface&nbsp;de Serviço



Figura 24 - Implemente a interface




Figura 25 - nome da implementação


CODE
package com.myapp.service;

import com.myapp.dao.ContatoDao;
import com.myapp.dao.ContatoDaoImpl;
import com.myapp.model.Contato;
import java.util.List;


public class ContatoServiceImpl implements ContatoService {
    private ContatoDao dao = new ContatoDaoImpl();
    
    @Override
    public void create(Contato contato) {
        dao.create(contato);
    }

    @Override
    public List&lt;Contato&gt; findAll() {
        return dao.findAll();
    }
    
}




6)&nbsp;Criando&nbsp;as classes p/ atender os&nbsp;actions&nbsp;que serão&nbsp;mapeados&nbsp;no arquivo&nbsp;struts-config.xml, que&nbsp;extendem&nbsp;a classe&nbsp;org.apache.struts.action.Action,&nbsp;

dentro de um novo package ...action
- CreateContatoAction.java
- ContatoForm.java
- RedirectContatoAction.java



I) CreateContatoAction.java


Figura 26 - Criando a Action


CODE
package com.myapp.action;

import com.myapp.model.Contato;
import com.myapp.service.ContatoService;
import com.myapp.service.ContatoServiceImpl;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

public class CreateContatoAction extends Action {

    private ContatoService userService = new ContatoServiceImpl();

    public void setContatoService(ContatoService userService) {
        this.userService = userService;
    }

    @Override
    public ActionForward execute(
            ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response) throws Exception {
//        return super.execute(mapping, form, request, response);

        ContatoForm contatoForm = (ContatoForm) form;
        Contato contato = new Contato();
        BeanUtils.copyProperties(contato, contatoForm);
        userService.create(contato);
        return mapping.findForward("list");

    }
}



II) ContatoForm.java



Figura 27 - mande o NB criar essa classe no package action


CODE
package com.myapp.action;

import org.apache.struts.action.ActionForm;

public class ContatoForm extends ActionForm {

    private String nome;
    private String telefone;

    public ContatoForm() {
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public String getTelefone() {
        return telefone;
    }

    public void setTelefone(String telefone) {
        this.telefone = telefone;
    }
}


III) RedirectContatoAction.java


Figura 28 - Adicionando a action de redirect



CODE
package com.myapp.action;

import com.myapp.service.ContatoService;
import com.myapp.service.ContatoServiceImpl;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

public class RedirectContatoAction extends Action {

    private ContatoService contatoService = new ContatoServiceImpl();

    public void setContatoService(ContatoService contatoService) {
        this.contatoService = contatoService;
    }

    @Override
    public ActionForward execute(
            ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response) throws Exception {
//        return super.execute(mapping, form, request, response);
        request.setAttribute("contatos", contatoService.findAll());
        return mapping.findForward("sucess");
    }
}



7) Definindo as actions e mappings&nbsp;no arquivo&nbsp;struts-config.xml
Xml
&lt;?xml version="1.0" encoding="UTF-8" ?&gt;

&lt;!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
          "http://jakarta.apache.org/struts/dtds/struts-config_1_3.dtd"&gt;


&lt;struts-config&gt;
     &lt;form-beans&gt;
        &lt;form-bean name="contatoForm" 
              type="com.myapp.action.ContatoForm"&gt;
        &lt;/form-bean&gt;
    &lt;/form-beans&gt;
    
    &lt;global-exceptions&gt;
        &lt;exception 
            type="java.lang.Exception" 
            key="user.global.ex"
            path="/error.jsp" /&gt;
    &lt;/global-exceptions&gt;

    &lt;global-forwards&gt;
        &lt;forward name="welcome"  path="/Welcome.do"/&gt;
    &lt;/global-forwards&gt;

    &lt;action-mappings&gt;
        &lt;action path="/Welcome" forward="/welcomeStruts.jsp"/&gt;
        &lt;action
            path="/RedirectContato"
            type="com.myapp.action.RedirectContatoAction"&gt;
            &lt;forward 
                name="sucess"
                path="/index.jsp"&gt;
            &lt;/forward&gt;
        &lt;/action&gt;        
        &lt;action
            path="/CreateContato"
            type="com.myapp.action.CreateContatoAction"
            name="contatoForm"
            input="/RedirectContato.do"&gt;
            &lt;forward 
                name="list"
                path="/RedirectContato.do"&gt;
            &lt;/forward&gt;
        &lt;/action&gt;
        &lt;!--  samples 
            &lt;action
            path="/"
            type="com.myapp."
            name=""
            scope=""
            validate=""
            input="" /&gt;
        &lt;/action-mappings&gt;
        --&gt;
    &lt;/action-mappings&gt;
    
    &lt;controller processorClass="org.apache.struts.tiles.TilesRequestProcessor"/&gt;

    &lt;message-resources parameter="com/myapp/struts/ApplicationResource"/&gt;    
     &lt;plug-in className="org.apache.struts.tiles.TilesPlugin" &gt;
        &lt;set-property property="definitions-config" value="/WEB-INF/tiles-defs.xml" /&gt;      
        &lt;set-property property="moduleAware" value="true" /&gt;
    &lt;/plug-in&gt;
    
    &lt;!-- ========================= Validator plugin ================================= --&gt;
    &lt;plug-in className="org.apache.struts.validator.ValidatorPlugIn"&gt;
        &lt;set-property
            property="pathnames"
            value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/&gt;
    &lt;/plug-in&gt;
  
&lt;/struts-config&gt;




8) Criando a view (interface para o usuário), definindo um form



Figura 29 - Arquivo index.jsp


CODE
CODE






9) criar uma página que mostre os erros quando acontecer




Figura 30 - Preparando uma página p/ mostrar os erros




Figura 31 - Página error.jsp


o projeto deve estar assim :


Figura 32 - Estrutura do projeto até esse ponto




3) Testando o Projeto Web

Run&gt;&gt; Project


Figura 33 - Testando a app




Figura 34 - Testando a app, mais um cadastro




Figura 35 - O programa em Swing da lição anterior acessando a mesma tabela que a pagina




Está cadastrando.
Mas está com um comportamento estranho:

1º mostra uma tela de cadastro e ao cadastrar mostra a &nbsp;lista dos cadastrados.Porquê ?

Se quisermos entrar direto na lista completa precisamos acessar pelo seguinte endereço na url :

http://localhost:8080/SpringLesson08-SpringStruts/RedirectContato.do

e o link p/ acessa a pagina criada pelo NB+Struts hello, por esse&nbsp;http://localhost:8080/SpringLesson08-SpringStruts/Welcome.do



Como acertamos isso ? Bom tem centenas de jeitos, vamos fazer o mais simples 1º

I) defina como index.html no arquivo web.xml

&lt;welcome-file-list&gt;
        &lt;welcome-file&gt;index.html&lt;/welcome-file&gt;
&lt;/welcome-file-list&gt;


e no index.html aponte p/ o mapping desejado :&nbsp;





&lt;html&gt;
    &lt;head&gt;
        &lt;title&gt;&lt;/title&gt;
        &lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;script type="text/javascript"&gt;
            location.href='/SpringLesson08-SpringStruts/RedirectContato.do';
        &lt;/script&gt;
    &lt;/body&gt;
&lt;/html&gt;


II) Salve os arquivos, o NB automaticamente faz o Deploy da app,clique em Run. veja se o apontamento do arquivo html funcionou.

Vou fornecer a versão 1 do projeto como está até aqui.
SpringLesson08-SpringStruts-v1



4) Implementando o Spring ao projeto com o struts.

1) adicione a lib do spring ao projeto


Figura 36 - Adicionando a lib do Spring


2) altere o struts-config.xml

Xml
&lt;?xml version="1.0" encoding="UTF-8" ?&gt;

&lt;!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
          "http://jakarta.apache.org/struts/dtds/struts-config_1_3.dtd"&gt;


&lt;struts-config&gt;
     &lt;form-beans&gt;
        &lt;form-bean name="contatoForm" 
              type="com.myapp.action.ContatoForm"&gt;
        &lt;/form-bean&gt;
    &lt;/form-beans&gt;
    
    &lt;global-exceptions&gt;
        &lt;exception 
            type="java.lang.Exception" 
            key="user.global.ex"
            path="/error.jsp" /&gt;
    &lt;/global-exceptions&gt;

    &lt;global-forwards&gt;
        &lt;forward name="welcome"  path="/Welcome.do"/&gt;
    &lt;/global-forwards&gt;

    &lt;action-mappings&gt;
        &lt;action path="/Welcome" forward="/welcomeStruts.jsp"/&gt;
        &lt;action
            path="/RedirectContato"&gt;
            &lt;forward 
                name="sucess"
                path="/index.jsp"&gt;
            &lt;/forward&gt;
        &lt;/action&gt;        
        
        &lt;action
            path="/CreateContato"
            name="contatoForm"
            input="/RedirectContato.do"&gt;
            &lt;forward 
                name="list"
                path="/RedirectContato.do"&gt;
            &lt;/forward&gt;
        &lt;/action&gt;
&lt;!--     renomeado apos adicionar o spring
         &lt;action
            path="/CreateContato"
            type="com.myapp.action.CreateContatoAction"
            name="contatoForm"
            input="/RedirectContato.do"&gt;
            &lt;forward 
                name="list"
                path="/RedirectContato.do"&gt;
            &lt;/forward&gt;
        &lt;/action&gt;
        
        &lt;action
            path="/RedirectContato"
            type="com.myapp.action.RedirectContatoAction"&gt;
            &lt;forward 
                name="sucess"
                path="/index.jsp"&gt;
            &lt;/forward&gt;
        &lt;/action&gt; 
        
        
        
        --&gt;
        &lt;!--  samples 
            &lt;action
            path="/"
            type="com.myapp."
            name=""
            scope=""
            validate=""
            input="" /&gt;
        &lt;/action-mappings&gt;
        --&gt;
    &lt;/action-mappings&gt;
    &lt;controller&gt;
        &lt;set-property 
            property="processorClass" 
            value="org.springframework.web.struts.DelegatingRequestProcessor" /&gt;
    &lt;/controller&gt;
    &lt;message-resources parameter="MessageResources"/&gt;    
    &lt;plug-in className="org.springframework.web.struts.ContextLoaderPlugIn" &gt;
        
    &lt;/plug-in&gt;
    
&lt;!--    &lt;controller processorClass="org.apache.struts.tiles.TilesRequestProcessor"/&gt;

    &lt;message-resources parameter="com/myapp/struts/ApplicationResource"/&gt;    
    
  
    &lt;plug-in className="org.apache.struts.tiles.TilesPlugin" &gt;
        &lt;set-property property="definitions-config" value="/WEB-INF/tiles-defs.xml" /&gt;      
        &lt;set-property property="moduleAware" value="true" /&gt;
    &lt;/plug-in&gt;
    
     ========================= Validator plugin ================================= 
    &lt;plug-in className="org.apache.struts.validator.ValidatorPlugIn"&gt;
        &lt;set-property
            property="pathnames"
            value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/&gt;
    &lt;/plug-in&gt;--&gt;
  
&lt;/struts-config&gt;




3) crie o arquivo action-servlet.xml

Xml
&lt;?xml version="1.0" encoding="UTF-8" ?&gt;
&lt;!DOCTYPE beans PUBLIC 
"-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"&gt;

&lt;beans&gt;
    &lt;bean name="/CreateContato"
          class="com.myapp.action.CreateContatoAction"&gt;
        &lt;property name="contatoService"&gt;&lt;/property&gt;
    &lt;/bean&gt;
    &lt;bean name="/RedirectContato"
          class="com.myapp.action.RedirectContatoAction"&gt;
        &lt;property name="contatoService"&gt;&lt;/property&gt;
    &lt;/bean&gt;
    &lt;bean id="contatoService"
          class="com.myapp.service.ContatoServiceImpl"&gt;
        &lt;!--&lt;property name="contatoDao"&gt; isso causa um erro  o correto esta abaixo--&gt;
        &lt;property name="dao"&gt;
            &lt;!-- injeção da dependência--&gt;
            &lt;bean 
                id="contatoDao" 
                class="com.myapp.dao.ContatoDaoImpl"&gt;
            &lt;/bean&gt;
        &lt;/property&gt;
    &lt;/bean&gt;
&lt;/beans&gt;


4) salve os arquivos modificados.

5) teste o programa e veja o Log do NB:

Não deve conter nenhum erro, se tiver verifique as configurações nos arquivos XML
Sep 27, 2012 1:02:18 PM org.springframework.web.struts.ContextLoaderPlugIn init
INFO: ContextLoaderPlugIn for Struts ActionServlet 'action, module '': initialization started
Sep 27, 2012 1:02:18 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing WebApplicationContext for namespace 'action-servlet': startup date [Thu Sep 27 13:02:18 BRT 2012]; root of context hierarchy
Sep 27, 2012 1:02:19 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from ServletContext resource [/WEB-INF/action-servlet.xml]
Sep 27, 2012 1:02:20 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@fe2254a: defining beans [/CreateContato,/RedirectContato]; root of factory hierarchy
Sep 27, 2012 1:02:21 PM org.springframework.web.struts.ContextLoaderPlugIn initWebApplicationContext
INFO: Using context class 'org.springframework.web.context.support.XmlWebApplicationContext' for servlet 'action'
Sep 27, 2012 1:02:21 PM org.springframework.web.struts.ContextLoaderPlugIn init
INFO: ContextLoaderPlugIn for Struts ActionServlet 'action', module '': initialization completed in 2610 ms
Sep 27, 2012 1:02:21 PM org.apache.catalina.util.LifecycleBase start
INFO: The start() method was called on component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/SpringLesson08-SpringStruts]] after start() had already been called. The second call will be ignored.


6) altere as actions no package actions
CODE
package com.myapp.action;

import com.myapp.model.Contato;
import com.myapp.service.ContatoService;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

public class CreateContatoAction extends Action {

//    private ContatoService userService = new ContatoServiceImpl();
    // com o Spring
    private ContatoService contatoService;

    public void setContatoService(ContatoService userService) {
        this.contatoService = userService;
    }

    @Override
    public ActionForward execute(
            ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response) throws Exception {
//        return super.execute(mapping, form, request, response);

        ContatoForm contatoForm = (ContatoForm) form;
        Contato contato = new Contato();
        BeanUtils.copyProperties(contato, contatoForm);
        contatoService.create(contato);
        return mapping.findForward("list");

    }
}


CODE
package com.myapp.action;

import com.myapp.service.ContatoService;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

public class RedirectContatoAction extends Action {

//    private ContatoService contatoService = new ContatoServiceImpl();
    // com o Spring
    private ContatoService contatoService ;
    public void setContatoService(ContatoService contatoService) {
        this.contatoService = contatoService;
    }

    @Override
    public ActionForward execute(
            ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response) throws Exception {
//        return super.execute(mapping, form, request, response);
        request.setAttribute("contatos", contatoService.findAll());
        return mapping.findForward("sucess");
    }
}


7) altere a classe dao.ContatoServiceImpl

CODE
package com.myapp.service;

import com.myapp.dao.ContatoDao;
import com.myapp.model.Contato;
import java.util.List;


public class ContatoServiceImpl implements ContatoService {
//    private ContatoDao dao = new ContatoDaoImpl();
    // depois do spring
    private ContatoDao dao;
    
    @Override
    public void create(Contato contato) {
        getDao().create(contato);
    }

    @Override
    public List&lt;Contato&gt; findAll() {
        return getDao().findAll();
    }
}




8) compile &nbsp;e teste. veja o erro :

Log
Offending resource: ServletContext resource [/WEB-INF/action-servlet.xml]
Bean '/CreateContato'; nested exception is org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: &lt;property&gt; element for property 'contatoService' must specify a ref or value
Offending resource: ServletContext resource [/WEB-INF/action-servlet.xml]
Bean '/CreateContato'
 -&gt; Property 'contatoService'
 at org.springframework.beans.factory.parsing.FailFastProblemReporter.error(FailFastProblemReporter.java:68)
 at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:85)



9) acerte o arquivo action-servlet.xml e adicione as ref


&lt;?xml version="1.0" encoding="UTF-8" ?&gt;
&lt;!DOCTYPE beans PUBLIC 
"-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"&gt;

&lt;beans&gt;
    &lt;bean name="/CreateContato"
          class="com.myapp.action.CreateContatoAction"&gt;
        &lt;property name="contatoService" ref="contatoService"&gt;&lt;/property&gt;
    &lt;/bean&gt;
    &lt;bean name="/RedirectContato"
          class="com.myapp.action.RedirectContatoAction"&gt;
        &lt;property name="contatoService" ref="contatoService"&gt;&lt;/property&gt;
    &lt;/bean&gt;
    &lt;bean id="contatoService"
          class="com.myapp.service.ContatoServiceImpl"&gt;
        &lt;!--&lt;property name="contatoDao"&gt; isso causa um erro  o correto esta abaixo--&gt;
        &lt;property name="dao"&gt;
            &lt;!-- injeção da dependência--&gt;
            &lt;bean 
                id="contatoDao" 
                class="com.myapp.dao.ContatoDaoImpl"&gt;
            &lt;/bean&gt;
        &lt;/property&gt;
    &lt;/bean&gt;
&lt;/beans&gt;


10) compile &nbsp;e teste. veja o erro :&nbsp;Log


org.springframework.beans.factory.BeanCreationException: Error creating bean with name '/CreateContato' defined in ServletContext resource [/WEB-INF/action-servlet.xml]: Cannot resolve reference to bean 'contatoService' while setting bean property 'contatoService'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'contatoService' defined in ServletContext resource [/WEB-INF/action-servlet.xml]: Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'dao' of bean class [com.myapp.service.ContatoServiceImpl]: Bean property 'dao' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
 at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:329)


A classe precisa dos Gets/Sets

11) encapsule &nbsp;a classe&nbsp;ContatoServiceImpl


Figura 37 - Encapsule a classe ContatoServiceImpl


CODE
package com.myapp.service;

import com.myapp.dao.ContatoDao;
import com.myapp.model.Contato;
import java.util.List;


public class ContatoServiceImpl implements ContatoService {
//    private ContatoDao dao = new ContatoDaoImpl();
    // depois do spring
    private ContatoDao dao;
    
    @Override
    public void create(Contato contato) {
        getDao().create(contato);
    }

    @Override
    public List&lt;Contato&gt; findAll() {
        return getDao().findAll();
    }

    public ContatoDao getDao() {
        return dao;
    }

    public void setDao(ContatoDao dao) {
        this.dao = dao;
    }
    
}


compile &nbsp;e teste.

Log
Sep 27, 2012 1:43:55 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing WebApplicationContext for namespace 'action-servlet': startup date [Thu Sep 27 13:43:55 BRT 2012]; root of context hierarchy
Sep 27, 2012 1:43:55 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from ServletContext resource [/WEB-INF/action-servlet.xml]
Sep 27, 2012 1:43:55 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@3e898802: defining beans [/CreateContato,/RedirectContato,contatoService]; root of factory hierarchy
Sep 27, 2012 1:43:56 PM org.springframework.web.struts.ContextLoaderPlugIn initWebApplicationContext
INFO: Using context class 'org.springframework.web.context.support.XmlWebApplicationContext' for servlet 'action'
Sep 27, 2012 1:43:56 PM org.springframework.web.struts.ContextLoaderPlugIn init
INFO: ContextLoaderPlugIn for Struts ActionServlet 'action', module '': initialization completed in 921 ms
Sep 27, 2012 1:43:56 PM org.apache.catalina.core.StandardContext reload
INFO: Reloading Context with name [/SpringLesson08-SpringStruts] is completed





12) Teste. experimente fazer mais um cadastro.



Figura 38 - Testando a app de novo




13) se tivéssemos outros objetos e tabelas precisaríamos da conexão compartilhada entre os DAOs.


Figura 39 - Crie a classe de conexão ao Mysql




CODE
package com.myapp.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;

public class ConexaoMysql {

    private Connection Conexao;

    public ConexaoMysql() {
        connect();
    }

    static {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (Exception ex) {
            Logger.getLogger(ConexaoMysql.class.getName()).log(Level.SEVERE, null, ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public Connection getConexao() {
        return Conexao;
    }

    public final void connect() {
        try {
            this.Conexao = DriverManager.getConnection("jdbc:mysql://ns1/springlessons", "springlessons", "DHADdSXcDF29WGXy");
        } catch (SQLException ex) {
            Logger.getLogger(ConexaoMysql.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}




14) altere o contatoDaoImpl p/ usar essa conexão :

CODE
package com.myapp.dao;

import com.myapp.model.Contato;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

public class ContatoDaoImpl implements ContatoDao {

    ConexaoMysql Conexao = new ConexaoMysql();
    @Override
    public void create(Contato contato) {
        Connection Con = this.Conexao.getConexao();
        PreparedStatement pstm = null;
        try {
//            Con = getClass();
            String sql = "INSERT INTO `springlessons`.`contato`"
                    + "(`nome`,`telefone`)"
                    + " VALUES (?,?)";
            pstm = Con.prepareStatement(sql);
            pstm.setString(1, contato.getNome());
            pstm.setString(2, contato.getTelefone());
            pstm.executeUpdate();

        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            try {
                pstm.close();
            } catch (Exception e) {
                Logger.getLogger(ContatoDaoImpl.class.getName()).log(Level.SEVERE, null, e);
            }
            try {
                Con.close();
            } catch (Exception e) {
                Logger.getLogger(ContatoDaoImpl.class.getName()).log(Level.SEVERE, null, e);
            }
        }
    }

    @Override
    public List&lt;Contato&gt; findAll() {
    Connection Con = this.Conexao.getConexao();
        PreparedStatement pstm = null;
        ResultSet rs = null;
        try {
//            Con = getConnection();
            String sql = "SELECT `contato`.`id`,`contato`.`nome`,`contato`.`telefone`"
                    + " FROM `springlessons`.`contato`";
            pstm = Con.prepareStatement(sql);
            List&lt;Contato&gt; contatos = new ArrayList&lt;Contato&gt;();
            rs = pstm.executeQuery(sql);

            while (rs.next()) {
                Contato contato = new Contato();
                contato.setId(rs.getInt("id"));
                contato.setNome(rs.getString("nome"));
                contato.setTelefone(rs.getString("telefone"));
                contatos.add(contato);
            }

            return contatos;
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            try {
                pstm.close();
            } catch (Exception e) {
                Logger.getLogger(ContatoDaoImpl.class.getName()).log(Level.SEVERE, null, e);
            }
            try {
                Con.close();
            } catch (Exception e) {
                Logger.getLogger(ContatoDaoImpl.class.getName()).log(Level.SEVERE, null, e);
            }
        }
    }
}



Salve, e teste:


Figura 40 - Testando a app a pós as alterações


E assim integramos o struts 1.3.10 com o Spring 3.2
Projeto NB


Figura 41a - Arquivos do projeto




Figura 41b - Arquivos do projeto


Como este projeto tem propósitos educacionais , os frameworks são libs do NB, e estão incluídas inteiras com todas as deps.
Fica como lição de casa, adicionar manualmente apenas as libs utilizadas.


Figura 42 - Libs utilizadas do projeto


Download do projeto NB
SpringLesson08-SpringStruts-v2

Resumo, o que vimos :

- Organização de projetos WEB
- Implementar o Struts 1.3.10
- Criamos uma interface contatoDAO
- Implementamos a interface com a classe ContatoDaoImpl
- Criamos uma interface de Serviço ContatoService
- Implementamos a interface &nbsp;com a classe ContatoServiceImpl
- Criamos as classes p/ atender os actions que são mapeados no arquivo struts-config.xml, que extendem a classe org.apache.struts.action.Action
- Definimos as actions e mappings no arquivo struts-config.xml
- Criamos uma view através de um arquivo index.jsp
- Criamos uma vier p/ mostrar os erros
- Integramos o Spring 3 com o Struts 2
- Definimos nossos beans no arquivo &nbsp;action-servlet.xml
- Vimos nos logs a ordem em que as classes são instanciadas e como localizar erros
- Compartilhamos a conexão através de uma classe ConexaoMysql
- Testamos o cadastro e vimos funcionando


humm e como ficaria essa implementação com o Struts 2?
até o &nbsp;próximo post...