sábado, 20 de setembro de 2014

Simfony 2 + OSX Mavericks

Entre consultorias, pintou um simfony p/ resolver, ok. Tempos sem escrever  aqui.

Quer começar seus estudos com Simfony2 no mac osX.

Vamos lá:

Baixe a última versão do Xcode disponível e compatível com sua versão do OSX.

Baixe um gerenciador de pacotes ports-like.
Tem o MacPorts e o HomeBrew , escolha um deles, eu prefiro e uso o MacPorts.
uso: port install ...

O mac osx já traz no seu php uma versão do pear pronta p/ instalar :

1 habilite o pear

Localize ond está o pear e as libs do php
$php -i | grep include_path
include_path => .:/php/includes/:/usr/lib/php/pear => .:/php/includes/:/usr/lib/php/pear

Vá na pasta /usr/lib/php e execute o arquivo install-pear-nozlib.phar
$php install-pear-nozlib.phar
agora vc tem o utilitário pecl .


2 se não tiver o composer baixe e instale :

Baixe e coloque junto com os binários de acesso comum
$ curl -sS https://getcomposer.org/installer | php
$ sudo mv composer.phar /usr/local/bin/composer


3 - Baixe o esquema do simfony pelo composer

Veja em http://symfony.com/doc/current/quick_tour/the_big_picture.html
Seguindo os tour, e fazendo o 1º projeto , talvez o simfony reclame de algumas dependências 
1 - TimeZone 
2 - intl
3 - Optimizador de Cache

Resolvendo 


1  - Timezone

Abra o arquivo /etc/php.ini e .defina o seu timezone.
date.timezone =America/Sao_Paulo


2 - INTL

Instale o intl
$sudo pecl update-channels
$sudo pecl install intl
se reclamar :
configure: error: Unable to detect ICU prefix or no failed. Please verify ICU install prefix and make sure icu-config works.
$sudo port -v install icu
$sudo port -v install pcre

Se deu certo você verá

Build process completed successfully
Installing '/usr/lib/php/extensions/no-debug-non-zts-20100525/intl.so'
about to commit 1215 file operations for intl
successfully committed 1215 file operations
install ok: channel://pecl.php.net/intl-3.0.0
configuration option "php_ini" is not set to php.ini location
You should add "extension=intl.so" to php.ini

Adicione essa opção no php.ini
Marios-Mac-Pro:php surfer$ sudo vi /etc/php.ini
e por volta da linha 862 adicione
extension=intl.so

Confira se habilitou
$ php -i | grep intl
intl
intl.default_locale => no value => no value
intl.error_level => 0 => 0
intl.use_exceptions => 0 => 0


3 - Instale o APC

$sudo pecl install apc

se você tiver esse erro :
In file included from /private/tmp/pear/temp/APC/apc.c:45:
/usr/include/php/ext/pcre/php_pcre.h:29:10: fatal error: 'pcre.h' file not found
#include "pcre.h"
         ^
1 error generated.
make: *** [apc.lo] Error 1
rolling back 211 file operations
ERROR: `make' failed

Talvez precise fazer 2 coisas:

1 - Baixe o command line tools mais atual da versão do seu Xcode no site da apple



Eu vi vários comentários absurdos na internet, inclusive em fóruns respeitados pela comunidade.
Não vi ninguém procurar esse arquivo local.
O pacote está procurando a lib pcre.h no lugar errado. Veja os diretórios de Include -I ( -I. -I/private/tmp/pear/temp/APC -DPHP_ATOM_INC -I/private/tmp/pear/temp/pear-build-rootH9ph8q/APC-3.1.13/include -I/private/tmp/pear/temp/pear-build-rootH9ph8q/APC-3.1.13/main -I/private/tmp/pear/temp/APC -I/usr/include/php -I/usr/include/php/main -I/usr/include/php/TSRM -I/usr/include/php/Zend -I/usr/include/php/ext -I/usr/include/php/ext/date/li)

Procurando local : obs: se você já fez alguma instalação pelo ports, esse arquivo já existe em sua maquina , e as dependências  também.

$ sudo find / -name "pcre.h"

/opt/local/include/pcre.h .

Resolvendo o problema da compilação :

Vá no diretório /usr/include/ e adicione os alias p/ as libpcre* q estão no diretório encontrado.
Marios-Mac-Pro:include surfer$ pwd
/usr/include
$sudo ln -s /opt/local/include/pcre* .

Confira se criou 
Marios-Mac-Pro:include surfer$ ls -laoh | grep pcre
lrwxr-xr-x    1 root    25B Sep 21 00:55 pcre.h -> /opt/local/include/pcre.h
lrwxr-xr-x    1 root    33B Sep 21 00:55 pcre_scanner.h -> /opt/local/include/pcre_scanner.h
lrwxr-xr-x    1 root    37B Sep 21 00:55 pcre_stringpiece.h -> /opt/local/include/pcre_stringpiece.h
lrwxr-xr-x    1 root    28B Sep 21 00:55 pcrecpp.h -> /opt/local/include/pcrecpp.h
lrwxr-xr-x    1 root    31B Sep 21 00:55 pcrecpparg.h -> /opt/local/include/pcrecpparg.h
lrwxr-xr-x    1 root    30B Sep 21 00:55 pcreposix.h -> /opt/local/include/pcreposix.h

Chame a instalação do apc de novo:

$sudo pecl install apc
Se não souber o q são as perguntas (opções do cache), apenas pressione enter até continuar compilando

e... se deu tudo certo você verá:
Build process completed successfully
Installing '/usr/include/php/ext/apc/apc_serializer.h'
+ create dir /usr/include/php/ext/apc
Installing '/usr/lib/php/extensions/no-debug-non-zts-20100525/apc.so'
about to commit 213 file operations for APC
successfully committed 213 file operations
install ok: channel://pecl.php.net/APC-3.1.13
configuration option "php_ini" is not set to php.ini location
You should add "extension=apc.so" to php.ini

Adicione essa opção no php.ini
Marios-Mac-Pro:php surfer$ sudo vi /etc/php.ini
e adicione por volta da linha 863
extension=apc.so

Confira se habilitou :

$ php -i | grep apc
.....

Se deu tudo certo. ao rodar o check pós criação do projeto, você deve receber essa mensagem:

Marios-Mac-Pro:simfony surfer$ cd simfony/
Marios-Mac-Pro:simfony surfer$ php app/check.php 

Symfony2 Requirements Checker
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

> PHP is using the following php.ini file:
  /etc/php.ini

> Checking Symfony requirements:
  ......................................

                                               
 [OK]                                          
 Your system is ready to run Symfony2 projects 


Veja o esquema de demonstração da aplicação criada:

Marios-Mac-Pro:simfony surfer$ php app/console server:run

Server running on http://127.0.0.1:8000

Acesse pelo navegador 

OBS: Fiz o processo paralelo em um debian, meu ambiente de dev, e a sequência, foi a mesma,
apenas instalando o pacote libpcre3-dev (p/ compilar o apc), e adicionando as extensões nos 2 php.ini (cli e apache)
obtive o mesmo resultado com as seguintes recomendações que ficam p/ outro post:

                                             
 [OK]                                        
 Your system is ready to run Symfony2 projects
                                             

Optional recommendations to improve your setup
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 * When using the logout handler from the Symfony Security Component,
   you should have at least PHP 5.4.11 due to PHP bug #63379 (as a
   workaround, you can also set invalidate_session to false in the
   security logout handler configuration)
   > Install PHP 5.4.11 or newer if your project uses the logout
   > handler from the Symfony Security Component.

 * You should use PHP 5.3.18+ or PHP 5.4.8+ to always get nice error
   messages for fatal errors in the development environment due to PHP
   bug #61767/#60909
   > Install PHP 5.3.18+ or PHP 5.4.8+ if you want nice error messages
   > for all fatal errors in the development environment.

 * short_open_tag should be disabled in php.ini
   > Set short_open_tag to off in php.ini*.


Bons estudos. Qualquer dúvida, poste aqui.
Até a próxima                                              




sábado, 21 de setembro de 2013

PhpKiisf Demo

Sobre o framework ; o porquê, como e onde veja esse post PHPKiisf 0_0

P/ quem já está acompanhando

Coloquei o framework funcionando em
http://phpkiisf.mcezzare.com.br/

e alguns exemplos em
http://phpkiisf.mcezzare.com.br/examples/

Já disponibilizei um banco mysql p/ demonstração do Framework.
O gerador de Models já gera classes prontas p/ serem colocadas na pasta models. (ainda preciso finalizar isso, por enquanto copie e cole o código em um novo arquivo.)


O gerador de  UML já foi iniciado.



Claro que tem algumas coisas p/ corrigir. Mas com o tempo.

P/ instalar e verificar as funcionalidades , baixe os fontes na pasta root de seu site através do svn:

user@hostws:/var/sites/phpkiisf.mcezzare.com.br# svn checkout https://phpkiisf.googlecode.com/svn .

Configure o arquivo /lib/phpkiisf.ini na seção DATABASE
[]'s



obs: contribuições são sempre Bem Vindas

Web Rapid Files


Olá.
Outro dia uma pessoa me mandou uma dúvida por email sobre um post de MVC, perguntando do dispatcher.
Por causa desse tema acabei criando um framework com uma série de utilidades p/ fast deploy. que hoje tem uma cópia funcional e os fontes podem ser obtidos por svn.

Veja o resumo no post PHP Kiisf - a simple PHP FrameWork .
Mas p/ responder ao email, compartilhei um projeto que precisei implementar em algumas empresas que tinham receio de usar serviços gratuitos como google drive, dropbox entre outros.

Esse projeto está acessível em http://code.google.com/p/webrapidfiles/
Ainda não usa um dispatcher real e nem um autoloader , mas tem um esquema bacana de usar MVC atribuindo as rotas de url aos controllers responsáveis e todos os POSTS do aplicativo postam p/ o PostController que processa o conteúdo postado e delega ao método responsável.

Tem bastante coisa funcionando com jQuery também. (no popups, yes modal ;) )

O aplicativo tem um instalador que :
Fazendo a configuração correta no apache, e  informando um usuário com permissões adequadas em um banco mysql, o sistema cria as tabelas e configura o necessário p/ iniciar seu uso com o usuário admin.

Veja o manual de instalação

E o motivo do post , um resumo bem rápido do pseudo "dispatch".
1 - Após o login a pessoa vai p/ a https://code.google.com/p/webrapidfiles/source/browse/trunk/web/pages/privado.php
2 - nessa pagina tem um require :
require_once($_SERVER['DOCUMENT_ROOT'] ."/pages/opcoes.php"); 

https://code.google.com/p/webrapidfiles/source/browse/trunk/web/pages/opcoes.php
que inclui os models e controllers de acordo com o parâmetro section na url
require_once($_SERVER['DOCUMENT_ROOT']."/app/controller/".$controller.".php");
require_once($_SERVER['DOCUMENT_ROOT']."/app/model/".$model.".class.php");

e junto com a view
https://code.google.com/p/webrapidfiles/source/browse/trunk/web/pages/view.php
aí as urls ficam assim:
http://xpto?
section=uploads&action=upload
section=grupos&action=index
section=admin&action=index


Espero ter ajudado.
Mas p/ um esquema mais completo veja o dispatcher do PHPKiisf que já está mais elaborado e vou dar continuidade no projeto.

E uma cópia de demonstração acessível em http://phpkiisf.mcezzare.com.br

[]'s
Até a próxima

sábado, 27 de abril de 2013

PHP Kiisf - a simple PHP FrameWork

Após fazer tantos sites em PHP, decidi começar um framework já que utilizo quase que a mesma técnica de desenvolvimento.

Existem vários frameworks em php hoje, vide http://www.phpframeworks.com/, ou direto os top 10
http://www.phpframeworks.com/top-10-php-frameworks/, então porque criar mais um e não melhorar algo existente ?

Porquê todos ele são muito bons. E fazem muitas coisas automá[(t|g)]ica. Isso requer um tempo para que o desenvolvedor se ambiente com o kit e comece a produzir. Pode valer a pena dependendo do contexto.


E após longo tempo de projeto, as pessoas se esquecem do principal objetivo de um Framework, que é de ser simples.


No entanto, compartilho mais uma visão de desenvovimento, com o conhecimento que possuo hoje.


Neste FrameWork tem um combinado de quase todas as coisas que já escrevi neste blog, pode ser acompanhado diretamente do repositório SVN do Google.


PHPKissf : 

Keep it in simple Framework

Basicamente o que isso faz ?

Na verdade, o que deu origem ao fmwk, foi um dispatcher que venho melhorando conforme o uso nesses anos. Um dispatcher é o seguinte:
Como nos links , o browser faz solicitações via GET ou POST por uma URL.
Por regras de configuração (.htaccess e mod_rewrite) todas as requisições são redirecionadas para um arquivo, que é o index.php,  que chama esse dispatcher.

O dispatcher por sua vez, tem uma lista de rotas, ou seja, caminhos de url, pré-determinados p/ chamar os controllers e seus métodos, e os parâmetros são encapsulados e  tratados procurando trazer um pouco mais de segurança p/ aplicação, e facilidade p/ o desenvovimento.

Então tem os default Model, Controller, View e Dao(opcional), que podem ser extendidos para os Objetos de Negócio de acordo com as necessidades.

Bem, como a intenção é que seja bastante utilizado, para que possa ser melhorado, escrevi o código em inglês, abaixo algumas funcionalidades.

PHPKissf : 
https://code.google.com/p/phpkiisf/

 Basic Components are:
 PHP/Backend All start from
--Dispatcher / based on Rewrite Rules forcing all to index.php 
 PHP/Modules in this Framework -All extensible


 --Default Controller
 --Default Model
 --Default View
 --Default Dao
 --Some Functions and Classes on /Lib 
--Global Configuration and Initialization file 

HTML,JS,CSS/Interface
--Customizable Skins , Boilerplate Default 
--jQuery latest 

Logo coloco alguns exemplos de uso...
Até a próxima...

domingo, 14 de outubro de 2012

Namespaces e Autoload de classes em PHP 5


Este artigo é uma continuação da explicação do uso da função __autoload , só que neste utilizando namespaces.

Bem, como vimos a utilização do recurso de autoload, agora vou adequar os arquivos do post anterior p/ poder utilizar o recurso de namespaces. Pode parecer um pouco confuso até pegar o jeito, mas vale a pena. Esse novo conceito necessita de organização  e  algumas dicas q eu dou são:
Importantes:
1 - que vc utilize os namespaces de acordo com sua estrutura física de arquivos e pastas.Evite perda de tempo e confusões desnecessárias
2 - que vc dê uma boa lida nesses links :
namespaces
static 
spl


3 - que você aceite o novo padrão de implementação que está sendo pedido, e esqueça o jeito procedural de fazer as coisas. Daqui para frente pense sempre em OOP, Classes , Reutilização de Código;
4 - que antes de sair codificando alguma coisa, verifique se já existe alguma design pattern para o seu problema;
5 - Veja na documentação fornecida pelo fabricante ou mantenedor os modelos exemplos fornecidos. Penso que ninguém melhor para mostrar o melhor uso. No caso do php o site do PHP , da ORACLE e da IBM são boas referências;

Opcionais:
6 - Se possível faça um modelo UML antes do sistema, existem diversas ferramentas que facilitam criar os diagramas e uns até exportam o diagrama p/ código fonte (C,C++,PHP,JAVA,etc..), eu gosto do Astah
7 - Se vc quiser usar um esquema automágico no carregamento de classes, utilize sempre o mesmo esquema nos nomes de arquivos ou tudo.php ou tudo .class.php, no exemplo anterior eu mostrei um jeito semi-automático criando um array com os nomes das classse (aí pode utilizar qualquer nome, pois o mapeamento será manual, p/ pequenas aplicações não tem problema), e caminho dentro de uma função __autoload .
Nesse esquema a função spl_autoload_register já faz isso. 

8- Utilize uma IDE p/ desenvolver, Netbeans, Eclipse, Dreamweaver, tanto faz. e utilize uma ferramenta que gere documentação de seu código. Isso permite analisar mais fácilmente o que já foi implementado e o que falta.


9- Quando achar que já sabe o bastante, continue pesquisando, as tecnologias são dinâmicas e requerem sempre atualizações ou melhorias.Penso que sempre existirá um jeito mais rápido de se fazer algo que já está sendo feito, depende do ponto de vista e da experiência do desenvolvedor.

Vamos ao namespaces :

1- Introdução namespaces 

Antes de mostrar o projeto final, vou mostrar um exemplo simples p/ facilitar o entendimento ainda utilizando uma função __autoload():
Observe que quando vc quiser usar o comando use .. . a classe deve ter na 1ª linha uma definição de namespace p/ ser acessível.
E a definição namespace na classe que vc quer disponilizar o acesso.


/test/Foo.php este com namespace tests
<?php
namespace tests;

class Foo {

    public function __construct() {}

    public function sayHello() {
        echo 'Hello <br>';
        $dt = new \DateTime();
    }

    public static function sayBye() {
        echo 'Bye ';
    }

    public static function init() {}

}?>

/autoload.php sem utilizar declaração namespace
<?php
function __autoload($classe) {
    echo "receiving $classe<br>";
    $nameClassOnly = strpos(strrev($classe), "\\");

    $classeAux = substr($classe, -$nameClassOnly);
    echo "would be $classeAux??<br>";

    $finalClass = str_replace('\\', '/', $classe);

    echo "including $finalClass<br>";
    require_once $finalClass . '.php';
    spl_autoload_register(array($classe, 'init'));//registra a classe com o metodo statico init
}?>

/callFoo.php sem utilizar declaração namespace mas usando o autoload e o comando use namespace\classe


<?php
require 'autoload.php';
use tests\Foo ;
$foo = new Foo();
$foo->sayHello();

$dt = new DateTime();
echo $dt->format(date('d/m/Y H:i:s')) . "<br>";
//static method
Foo::sayBye();

echo "<pre>";
print_r(spl_autoload_functions());
echo "</pre>";?>

resultado :



/callFoo_1.php sem utilizar declaração namespace mas usando o autoload e o comando use namespace\classe  e utilizando um Alias p/ a classe Foo


<?php
require 'autoload.php';
use tests\Foo as MyFooClass;
$foo = new MyFooClass();

$foo->sayHello();
$dt = new DateTime();
echo $dt->format(date('d/m/Y H:i:s')) . "<br>";

MyFooClass::sayBye();
echo "<pre>";
print_r(spl_autoload_functions());
echo "</pre>";
?>

resultado :

e como fica isso mais perto da realidade sem Foo, bar, etc ?

/callCliente.php sem utilizar declaração namespace mas usando o autoload e o comando use ...
<?php
require 'autoload.php';
use app\model\Cliente;
use app\lib\Utils;

$cliente = new Cliente();
$util= new Utils();
$util->mostraObjeto($cliente);
echo "<pre>";
print_r(spl_autoload_functions());
echo "</pre>";
?>

/app/model/Cliente.php
<?php
namespace app\model;
final class Cliente {

    private $id;
    private $nome;
    private $email;

    function __construct() {
        $this->id = 0;
        $this->nome = null;
        $this->email = null;
    }
    

    public static function init() {
        __construct();
    }

    public function getId() {
        return $this->id;
    }

    public function setId($id) {
        $this->id = $id;
    }

    public function getNome() {
        return $this->nome;
    }

    public function setNome($nome) {
        $this->nome = $nome;
    }

    public function getEmail() {
        return $this->email;
    }

    public function setEmail($email) {
        $this->email = $email;
    }
    public function __toString() {
        return "id:".$this->getId()." nome:".$this->getNome()." email:".$this->getEmail();
    }
}

?>


/app/lib/Utils.php
<?php
namespace app\lib;
class Utils {
      private  $styleBox;  

      public static function init(){
          __construct() ;
      }
     public function __construct() {}

    public static function mostraObjeto($object) {
        echo "<pre style=\"
        font-family: Tahoma, Geneva, sans-serif;
 background-color: #FFC;
 font-size: 9px;
 border: thin solid #03C;
 cursor: text;
 filter: Xray;\">";
        print_r($object);
        echo "</pre>";
        echo "<hr size=\"1\" width=\"100%\">";
    }
}?>
Teste.
resultado

Experimente criar novas classes e usá-las, ou mover os arquivos de lugar p/ entender bem o conceito de namespace

Agora que você já entendeu o conceito de namespaces vamos a Aplicação, a idéia é fazer um CRUD dos Clientes utilizando o jQuery para realizar as operações e o PHP servir apenas como um BackEnd e DataStore , mas como já expliquei neste post como utilizar namespaces,  vou começar o Post da aplicação. pois já temos o que precisamos...



Dúvidas, Contribuições, Sugestões? Poste..Grato,Até a próxima.

sábado, 13 de outubro de 2012

Autoload de classes em PHP 5


Breve explicação deste post:

Estava aqui escrevendo um post de jQuery + php, um CRUD de clientes,  e achei que o exemplo estava meio pobre em termos de php, então pensei em melhorar um pouco o exemplo.
OBS: os clientes são armazenados em $_Session[] e arrays, pois já tem muito CRUD de php-mysql por aí, e o objetivo é mostrar o jQuery.
As telas abrem em divs, os forms não tem action , pois o jQuery lê os campos do form, posta e fecha o div. as action são invocadas a partir do nome dos elementos.
Então antes de organizar  este projeto que já funciona, estou criando este post p/ compartilhar a experiência que tive com o autoload até chegar nos namepaces. veja abaixo uma foto da app.

Figura 01- Propósito final do proximo post
obs: Arquivos dessa App. :

surfer@surfer-OptiPlex-360:/var/sites/test.lpanic.intra$ ls -R
.:
Cliente.class.php  ClienteHandler.php  custom.css  custom.js  images  index.php  jquery-1.8.2.min.js  jqueryFormExample.js  jqueryFormExample.php  Utils.class.php

./images:
bin_empty.png  book_add.png  page_refresh.png  table_refresh.png


Esse Post

Eu não usava esse recurso de autoload e tenho projetos antigos que tem mais de 10 requires em cada página. Na época era como eu sabia fazer (php 3 e 4).


Esse recurso de autoload de classes que pode ser usado a partir do php5, economiza algumas linhas. Procurei em vários lugares na web, mas não tinha entendido como usar, já que consegui usar, vou dividir. :)


Já tenho alguma experiência com JAVA e hoje separo meus objetos, interfaces e classes em pacotes.
O php agora tem o recurso de namespaces que tenta ser parecido com o conceito de package do java com algumas modificações no uso. E utiliza um esquema de autoload com uma implementação melhorada do __autoload (spl_autoload_register), porém precisa de métodos estáticos, então mostrarei isso na 3ª parte do post, depois de mostrar o autoload, pois teremos que modificar a função criada na 2ª implementação


Imaginemos uma aplicação onde temos clientes e a estrutura p/ esses clientes vou apenas mostrar o básico, pois a idéia é mostrar o recurso de autoload:
-- M -> Cliente.php, ClienteDao.php
-- V  -> index.php
-- C -> ClienteController

1- Jeito Antigo:


PHP (tudo num arquivo só p/ explicar o exemplo)
<?

//----arquivo cliente.php model
class Cliente {

    private $id;
    private $nome;
    private $email;

    public function Cliente() {
        
    }

//construtor
//gets e sets
}

//----arquivo clienteDAO.php dao
require_once('cliente.php');

class ClienteDAO {

    private $cliente;
    private $listaCliente;

    public function ClienteDAO() {
        
    }

//construtor
//gets e sets

    public function add(Cliente $cliente) {
        $sql = "Insert into ..";
//conexao .. recorset .. execute $sql
    }

    public function remove(Cliente $cliente) {
        
    }

    public function saveOrUpdate(Cliente $cliente) {
        
    }

    public function getListaCliente() {
        $sql = "SELECT * FROM cliente";
//conexao .. recorset .. execute $sql 
        return $this->listaCliente;
    }

//..etc
}

//----arquivo clienteController.php controller
require_once('cliente.php');
require_once('clienteDAO.php');

class ClienteController {

    private $clienteDao;

    public function ClienteController() {
        $this->clienteDao = new ClienteDAO();
    }

//construtor
//gets e sets

    public function add(Cliente $cliente) {
        $this->clienteDao->add(cliente);
    }

    public function remove(Cliente $cliente) {
        $this->clienteDao->remove(cliente);
    }

    public function saveOrUpdate(Cliente $cliente) {
        $this->clienteDao->saveOrUpdate(cliente);
    }

    public function getListaCliente() {
        return $this->clienteDao->getListaCliente();
    }

}

//..etc
?>
e no index.php ou outro arquivo do site vc teria
//..etc e no index.php por exemplo 
require_once('cliente.php');
require_once('clienteController.php');

$clienteController = new ClienteController();
$arrClientes= $clienteController->getListaCliente(); 
print_r($arrClientes);

Observe os require.

2- Utilizando o __autoload

P/ cada classe que temos temos que fazer um require ou include da classe desejada.
Um jeito de não precisar fazer isso em todas as páginas é criar um arquivo com a lista de classes,  que faz esses includes ao criar objetos,  e incluir esse arquivo no inicio de cada página.:
arquivo autoload.php
<?
function __autoload($classe) {

    $classes = array(
        'Cliente' => 'Cliente.php',
        'ClienteDAO' => 'ClienteDAO.php',
        'ClienteController' => 'ClienteController.php',
    );
    require_once $classes[$classe];
}?>

e o index

<?php
require 'autoload.php';
$cliente = new Cliente();
$clienteDao = new ClienteDAO();
echo "<pre>";
print_r($cliente);
print_r($clienteDao);
echo "</pre>";
?>


o resultado deve ser :
Figura 02 - Teste simples


3- Utilizando o spl_autoload_register

Porém nas versões mais novas do PHP, já tem recursos mais modernos. existe uma função spl_autoload_register que recebe como param um array (nome_classe,metodo_que_inicializa).
Porém p/ usar essa função o método deve ser static. Então vamos modificar as classes e organizar os arquivos :

Figura 03 - Arquivos em projeto do NetBeans
Adicionamos o atributo static nas funções init para poder registrá-las com o spl


ClienteController.php
class ClienteController {

    private $dao;
    
    public function __construct() {
        $this->dao = new ClienteDAO(); 
    }

    public static function init() {
       __construct();
        
    }
    
}



ClienteDAO.php
<? final class ClienteDAO {

    private $cliente;
    private $listaCliente;
    private $arrObjCliente;

    public function __construct() {
        $this->cliente = new Cliente();
        $this->listaCliente = array(new Cliente());
        $this->arrObjCliente = new ArrayObject($this->listaCliente);
    }
    public static function init() {
        __construct();

    }
}?>

Cliente.php
<?php

final class Cliente {

    private $id;
    private $nome;
    private $email;

    function __construct() {
        $this->id = 0;
        $this->nome = null;
        $this->email = null;
    }

    public static function init() {
        __construct();
    }

    public function getId() {
        return $this->id;
    }

    public function setId($id) {
        $this->id = $id;
    }

    public function getNome() {
        return $this->nome;
    }

    public function setNome($nome) {
        $this->nome = $nome;
    }

    public function getEmail() {
        return $this->email;
    }

    public function setEmail($email) {
        $this->email = $email;
    }

}

?>


Autoload.php
<?php
//autoload.php
function __autoload($classe) {

    $classes = array(
        'Cliente' => 'app/model/Cliente.php',
        'ClienteDAO' => 'app/dao/ClienteDAO.php',
        'ClienteController' => 'app/controller/ClienteController.php',
        'Controller' => 'app/controller/Controller.php',
        'Utils' => 'app/lib/Utils.class.php'
    );
    echo "including $classes[$classe]<br>" ;
    require_once $classes[$classe];
    spl_autoload_register(array($classe, 'init'));
}?>


index.php
<?php
require 'autoload.php';
$cliente = new Cliente();
$clienteDao = new ClienteDAO();
$clienteController = new ClienteController();
echo "<pre>";
print_r($cliente);
echo "<hr>";
print_r($clienteDao);
echo "<hr>";
print_r($clienteController);
echo "</pre>";
?>

e o resultado deve ser esse:
Figura 04 - resultado com o autoload

p/ mostrar esses objetos de um jeito um pouco melhor vou chamar uma função mostraObjeto de uma nova classe Utils. Até aqui não tem problema criar uma classe com esse nome. mas se vc for usar algum framework, cuidado pois vários tem seu próprio Utils. Isso se resolve utilizando namespaces que vou mostrar mais pra frente. Vou tirar a linha do echo "including $classes[$classe]<br>" ;  para não ficar mostrando isso ao carregar as classes. 

Utils.class.php
<?php
define('CHARSET', 'UTF-8');
define('REPOSITORIO',$_SERVER['DOCUMENT_ROOT'] . '/files/');

class Utils {
      private $styleBox;  

      public static function init(){
          __construct() ;
      }
    public function __construct() {
        $this->styleBox="
        font-family: Tahoma, Geneva, sans-serif;
 background-color: #FFC;
 font-size: 9px;
 border: thin solid #03C;
 cursor: text;
 filter: Xray;
 font-weight: bold;";
    }

    public function mostraObjeto($object) {
//        var_dump($object); 
        echo "<pre style=\"".$this->styleBox."\">";
        print_r($object);
        echo "</pre>";
        echo "<hr size=\"1\" width=\"100%\">";
    }


    function includeFile($file) {
        try {
            $fileX = $_SERVER['DOCUMENT_ROOT'] . $file;
            //die($fileX);
            if (file_exists($fileX)) {
                require_once $fileX;
            } else {
                //throw new Exception("Arquivo '$file' n&atilde;o encontrado");
                throw new Exception("A operação deste modulo '$file' ainda  n&atilde;o foi implementada.");
            }
        } catch (Exception $ex) {
            echo $ex->getMessage();
        }
    }

    function destaca($x, $y, $upper = false) {
        if ((strlen($x) > 0) && (strlen($y) > 0)) {
            $y = ($upper) ? strtoupper($y) : $y;
            $saida = str_replace($y, "<font color=red>" . $y . "</font>", $x);
        } else {
            $saida = $x;
        }

        return $saida;
    }

    function mostraDinheiro($val) {
        if ($val) {
            $valFormatado = 'R$ ' . number_format($val, 2, ',', '.');
        } else {
            $valFormatado = "";
        }

        return $valFormatado;
    }

    function arrumaStr($str, $ucase = 'lower') {
        $str = trim(str_replace(" ", "", $str));
        for ($i = 0; $i < strlen($str); $i++) {
            $Astr[$i] = $str{$i};
        }

        $sem = array("c", "C", "a", "e", "i", "o", "u", "A", "E", "I", "O", "U", "A", "O", "a", "o", "a", "e", "i", "o", "u", "A", "E", "I", "O", "U", "A", "O");
        $com = array("ç", "Ç", "á", "é", "í", "ó", "ú", "Á", "É", "Í", "Ó", "Ú", "Ã", "Õ", "ã", "õ", "`a", "`e", "`i", "`o", "`u", "`A", "`E", "`I", "`O", "`U", "â", "ô", "Â", "Ô");
        $strFinal = implode("", str_replace($com, $sem, $Astr));
        if ($ucase == 'lower') {
            return strtolower($strFinal);
        } else {
            return strtoupper($strFinal);
        }
    }

    public function mostraSQL($sqlQuery) {
        echo "<pre style=\"border:solid 1px #EA9C5C; padding:3px; color:#000000; background-color:#ededed \">";
        echo $sqlQuery;
        echo "</pre>";
        echo "<hr size=\"1\" width=\"100%\">";
    }
    public function getHumanReadableSize($param) {

        if ($param < 1024) {
            return $param . ' B';
        } elseif ($param < 1048576) {
            return round($param / 1024, 2) . ' KiB';
        } elseif ($param < 1073741824) {
            return round($param / 1048576, 2) . ' MiB';
        } elseif ($param < 1099511627776) {
            return round($param / 1073741824, 2) . ' GiB';
        } elseif ($param < 1125899906842624) {
            return round($param / 1099511627776, 2) . ' TiB';
        } elseif ($param < 1152921504606846976) {
            return round($param / 1125899906842624, 2) . ' PiB';
        } elseif ($param < 1180591620717411303424) {
            return round($param / 1152921504606846976, 2) . ' EiB';
        } elseif ($param < 1208925819614629174706176) {
            return round($param / 1180591620717411303424, 2) . ' ZiB';
        } else {
            return round($param / 1208925819614629174706176, 2) . ' YiB';
        }
    }

}

?>
e o index alterado
<?php
require 'autoload.php';
// nem criando o construtor assim nao funciona
//$cliente = new Cliente(33,'Mario Cezzare','mcezzare@gmail.com');
$cliente = new Cliente();
$cliente->setId(33);
$cliente->setNome('Mario Cezzare');
$cliente->setEmail('mcezzare@gmail.com');

$clienteDao = new ClienteDAO();
$clienteController = new ClienteController();

$util = new Utils();
$util->mostraObjeto($cliente);
$util->mostraObjeto($clienteDao);
$util->mostraObjeto($clienteController);?>

e o resultado :
Figura 05 - mostraObjeto customizado 

Agora só p/ mostrar o objeto (array ou array de objetos) de um jeito mais compacto vou criar uma função mostraObjetoArr
Utils.class.php

<?     public function mostraObjetoArr($object) {
        echo "<pre style=\"border:solid 1px #EA9C5C; padding:3px; color:#000000; background-color:#ededed \">";
        echo "Object: <br>";  
        if (is_array($object)) {
            foreach ($object as $key => $value) {
                echo "$key:<b>$value</b> &nbsp;";
                if (is_array($value)) {
                    foreach ($value as $val) {
                        echo "$value:<b>$val</b> &nbsp;|&nbsp;";
                    }
                }
                echo "<br>";
            }
        }
        echo "</pre>";
        echo "<hr size=\"1\" width=\"100%\">";
    }?>

e p/ isso poder funcionar precisamos adicionar o metodo __toString em nosso objeto Cliente

Cliente.class.php
<?
//....
public function __toString() {
        return "id:".$this->getId()." nome:".$this->getNome()." email:".$this->getEmail();
    }?>

e no index agora :


<?php
require 'autoload.php';
// nem criando o construtor assim nao funciona
//$cliente = new Cliente(33,'Mario Cezzare','mcezzare@gmail.com');
$cliente = new Cliente();
$cliente->setId(33);
$cliente->setNome('Mario Cezzare');
$cliente->setEmail('mcezzare@gmail.com');


$util = new Utils();
//$util->mostraObjeto($cliente);
//$util->mostraObjeto($clienteDao);
//$util->mostraObjeto($clienteController);

$cliente2 = new Cliente();
$cliente2->setId(26);
$cliente2->setNome('Joao Test');
$cliente2->setEmail('jtest@gmail.com');

$arrClientes = array();
array_push($arrClientes, $cliente);
array_push($arrClientes, $cliente2);
$util->mostraObjetoArr($arrClientes);

//jeito mais moderno de armazenar arrays
$arrObjectNative = new ArrayObject($arrClientes);
$util->mostraObjeto($arrObjectNative);?>

e o resultado : 
Figura 06 - resultado após o metodo __toString e mostrando o objeto ArrayObject
so coloquei o $arrObjectNative p/ mostrar um jeito mais eficiente de armazenar arrays de tipos de objetos, o objetivo que era mostrar o autoload dentro de um MVC foi atendido.
Arquivos deste Post
AutoLoad_ExemploPHP.zip

Agora vou ter que fazer alguns acertos p/ poder utilizar os namespaces e mostro a app pronta no próximo post dela. Se quiser ver como utilizar os namespaces nesse exemplo siga para esse post :




Dúvidas, Contribuições, Sugestões? Poste..
Grato,
Até a próxima.


quarta-feira, 3 de outubro de 2012

JAVA + Spring + Netbeans 7.2 - Mysql + Hibernate 3 + CRUD + Struts 2 Lesson 09

Dando seqüência nos posts de JAVA + Spring, agora vou apresentar o Framework Apache Struts em sua versão 2.

(ainda não pus a legenda das imagens )
Requisitos :
Netbeans 7.2
spring-3.2.0.M2 -- link direto
- estar com o banco mysql springlessons, e a tabela contato criada.
- Struts 2

- Lib XStream , para manipular arquivos XML .

- Ter lido :
Posts Anteriores : 
JSNBTut - Base  que é uma preparação do ambiente para o desenvolvimento

Opcionais : 
JSNBTut - Lesson 01 - introdução ao Spring
JSNBTut - Lesson 02 - introdução ao gerenciamento de dependências no  Spring
JSNBTut - Lesson 03 - acessando banco de dados Mysql com beans e injeção de dependências
JSNBTut - Lesson 04 - outro jeito rápido de utilizar o Spring e Mysql sem utilizar Arquivos XML.
JSNBTut - Lesson 05 - comparação entre as implementações e introdução ao Swing. Jtable + DefaultTableModel e implementação de uma TableModel, ...
JSNBTut - Lesson 06 - implementando um CRUD ao exemplo , que é o projeto que continua da lição 5.
JSNBTut - Lesson 07
- Finalizando o  CRUD completo em Java   utilizando Swing e  Spring
- Implementamos um validador com org.springframework.validation.Validator
- Implementamos um Tema
- Vimos como importar /exportar arquivos XML usando XStream
- Aprendemos a usar Anotações
- Implementamos um SplashScreen
- Aprendemos a distribuir nossa aplicação e customizar o build do projeto no build.xml


JSNBTut - Lesson 08
- 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  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  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

Este é o 9º da série , o objetivo deste post é implementar o programa que terminamos na lição 07 na web utilizando  o framework Struts 2 , e depois integraremos com o Spring 3 e o Hibernate 3, passando o controle da app p/ o Spring.
Os arquivos dos 2 projetos finalizados nesse Post estão ao final das explicações ou no final deste Post:

Nesta lição , eu procurei capturar quase todos os passos em telas, pois nada como a referência de cada framework ou componente p/ explicar sua utilização, o que mostro aqui é um jeito de implementar.


Adiantando,  algumas coisas que faremos ?

- Aprenderemos a conectar no Mysql pelo NB e armazenar um driver
- Aprenderemos a utilizar e configurar o Hibernate pelo NB
- Aprenderemos a fazer a engenharia reversa das tabelas do banco para as configurações do Hibernate gerando os arquivos de para os mappings: Hibernate Mapping
na versão V1:

- Introduziremos o  Full Hibernate Plugin's Session Factory
- Introduziremos o conceito de BO (Business Objects)


- Utilizar os recursos de Injeção de dependências do Spring:
- Deixaremos a app apenas (pode ser que sobre alguma) com as libs necessárias no final do Projeto.



Nesta lição adicionei o campo email:
Lembrando a estrutura da nossa tabela do mysql
Figura 01 - Tabela Contato
CREATE  TABLE IF NOT EXISTS `springlessons`.`contato` (
  `id` INT(11) NOT NULL AUTO_INCREMENT ,
  `nome` VARCHAR(45) NULL DEFAULT NULL ,
  `telefone` VARCHAR(45) NULL DEFAULT NULL ,
  `email` VARCHAR(45) NULL DEFAULT NULL ,
  PRIMARY KEY (`id`) )
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci

Let's Go.

 1) Obtendo as Libs


Não consegui utilizar as libs adicionadas ao projeto pelo NB. Portanto vamos adicionar algumas manualmente , e depois organizar.


LIBS:
Struts 2:
-antlr-2.7.6.jar
-commons-collections-3.1.jar
-commons-fileupload-1.2.1.jar
-commons-io-1.3.2.jar
-commons-lang-2.3.jar
-commons-logging-1.1.jar
-freemarker-2.3.13.jar
-javassist-3.9.0.GA.jar
-ognl-2.6.11.jar
-struts2-convention-plugin-2.1.6.jar
-struts2-core-2.1.6.jar
-struts2-fullhibernatecore-plugin-1.4-GA.jar
-xwork-2.1.2.jar

Hibernate 3

-ejb3-persistence.jar

-hibernate-annotations.jar
-hibernate-commons-annotations.jar
-hibernate-validator.jar
-hibernate3.jar
-jta-1.1.jar


Dom4j
-dom4j-1.6.1.jar

apache-log4j-1.2.17
-log4j-1.2.15.jar

slf4j-1.7.1

-slf4j-api-1.5.8.jar
-slf4j-log4j12-1.5.8.jar



jUnit
-junit-3.8.1.jar

2) Iniciando o Projeto

Figura 02 - Nova WebApp

Figura 03 - Nova WebApp / Setup
Não adicione nenhum Framework, vamos adicionar depois :

Figura 04- Sem Frameworks

Figura 05 - Lista das libs utilizadas


2)-Adicionando a conexão do mysql ao NB


Figura 06 - Conectando o NB ao Mysql 

Figura 07 - Conectando o NB ao Mysql 

Figura 08 - Conectando o NB ao Mysql - novo driver

Figura 09 - Conectando o NB ao Mysql - Teste de conexão

Figura 10 - Driver disponíveis


3)-Criando o arquivo de configuração do Hibernate pelo NB

Isso criará o arquivo hibernate.cfg.xml
Figura 11 - Gerando o arquivo hibernate.cfg.xml

Figura 12 - Gerando o arquivo hibernate.cfg.xml pelo Wizard

Figura 13-confirme o nome  do arquivo hibernate.cfg.xml

Figura 14-Escolha a conexão

Figura 15- Arquivo gerado hibernate.cfg.xml

Figura 16 - configurando a engenharia reversa das tabelas

Figura 17-confirme o nome  do arquivo hibernate.revenge.xml

Figura 18-escolha as tabelas p/ gerar os mappings

Figura 19-Arquivo gerado hibernate.revenge.xml


4)-Fazendo a Engenharia reversa das tabelas do schema e Adicionando o mapeamento aos campos

Isso criará o arquivo hibernate.reveng.xml e os nossos Modelos Contato.java e Usuario.java
Figura 20 - fazendo a engenharia reversa das tabelas

Figura 21 - fazendo a engenharia reversa das tabelas, escolha os arquivos XML criados

Figura 22 -Arquivos gerados


Figura 23 -Arquivo final do hibernate


hibernate.cfg.xml :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.url">jdbc:mysql://ns1:3306/springlessons?zeroDateTimeBehavior=convertToNull</property>
    <property name="hibernate.connection.username">springlessons</property>
    <property name="hibernate.connection.password">DHADdSXcDF29WGXy</property>
    <mapping resource="com/springlesson09/model/Usuario.hbm.xml"/>
    <mapping resource="com/springlesson09/model/Contato.hbm.xml"/>
  </session-factory>
</hibernate-configuration>



hibernate.revenge.xml :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-reverse-engineering PUBLIC "-//Hibernate/Hibernate Reverse Engineering DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-reverse-engineering-3.0.dtd">
<hibernate-reverse-engineering>
  <schema-selection match-catalog="springlessons"/>
  <table-filter match-name="contato"/>
  <table-filter match-name="usuario"/>
</hibernate-reverse-engineering>

Contato.hbm.xml :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated Oct 1, 2012 11:10:50 PM by Hibernate Tools 3.2.1.GA -->
<hibernate-mapping>
  <class catalog="springlessons" name="com.springlesson09.model.Contato" table="contato">
    <id name="id" type="java.lang.Integer">
      <column name="id"/>
      <generator class="identity"/>
    </id>
    <property name="nome" type="string">
      <column length="45" name="nome"/>
    </property>
    <property name="telefone" type="string">
      <column length="45" name="telefone"/>
    </property>
    <property name="email" type="string">
      <column length="45" name="email"/>
    </property>
  </class>
</hibernate-mapping>

Usuario.hbm.xml :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated Oct 1, 2012 11:10:50 PM by Hibernate Tools 3.2.1.GA -->
<hibernate-mapping>
  <class catalog="springlessons" name="com.springlesson09.model.Usuario" table="usuario">
    <id name="id" type="java.lang.Integer">
      <column name="id"/>
      <generator class="identity"/>
    </id>
    <property name="nome" type="string">
      <column length="45" name="nome" not-null="true"/>
    </property>
    <property name="email" type="string">
      <column length="45" name="email" not-null="true">
        <comment>licao 09 - WEB</comment>
      </column>
    </property>
    <property name="senha" type="string">
      <column length="45" name="senha" not-null="true"/>
    </property>
  </class>
</hibernate-mapping>


Usuario.java :
package com.springlesson09.model;
// Generated Oct 1, 2012 11:10:44 PM by Hibernate Tools 3.2.1.GA
/**
 * Usuario generated by hbm2java
 */
public class Usuario  implements java.io.Serializable {


     private Integer id;
     private String nome;
     private String email;
     private String senha;

    public Usuario() {
    }

    public Usuario(String nome, String email, String senha) {
       this.nome = nome;
       this.email = email;
       this.senha = senha;
    }
   
    public Integer getId() {
        return this.id;
    }
    
    public void setId(Integer id) {
        this.id = id;
    }
    public String getNome() {
        return this.nome;
    }
    
    public void setNome(String nome) {
        this.nome = nome;
    }
    public String getEmail() {
        return this.email;
    }
    
    public void setEmail(String email) {
        this.email = email;
    }
    public String getSenha() {
        return this.senha;
    }
    
    public void setSenha(String senha) {
        this.senha = senha;
    }

}


Contato.java :
package com.springlesson09.model;
// Generated Oct 1, 2012 11:10:44 PM by Hibernate Tools 3.2.1.GA
/**
 * Contato generated by hbm2java
 */
public class Contato  implements java.io.Serializable {


     private Integer id;
     private String nome;
     private String telefone;
     private String email;

    public Contato() {
    }

    public Contato(String nome, String telefone, String email) {
       this.nome = nome;
       this.telefone = telefone;
       this.email = email;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }
   
   
    public String getNome() {
        return this.nome;
    }
    
    public void setNome(String nome) {
        this.nome = nome;
    }
    public String getTelefone() {
        return this.telefone;
    }
    
    public void setTelefone(String telefone) {
        this.telefone = telefone;
    }
    public String getEmail() {
        return this.email;
    }
    
    public void setEmail(String email) {
        this.email = email;
    }
}



5)-Criando uma interface DAO


Figura 24 - Criando uma interface

Figura 25 - Criando uma interface ContatoDAO

ContatoDAO.java
package com.springlesson09.dao;

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


public interface ContatoDAO {

public void saveOrUpdateContato(Contato contato);
 public List<Contato> listContato();
 public Contato listContatoById(Integer contatoId);
 public void deleteContato(Integer contatoId);
    
}

6) Criando a implementação do DAO


Figura 26 - Implementando uma interface

Figura 27- Implementando uma interface, aproveite o NB

ContatoDAOImpl.java
package com.springlesson09.dao;

import com.googlecode.s2hibernate.struts2.plugin.annotations.SessionTarget;
import com.googlecode.s2hibernate.struts2.plugin.annotations.TransactionTarget;
import com.springlesson09.model.Contato;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.Transaction;


public class ContatoDAOImpl implements ContatoDAO {

    @SessionTarget
    Session session;
    @TransactionTarget
    Transaction transaction;

    /**
     *
     * @param contato
     */
    @Override
    public void saveOrUpdateContato(Contato contato) {
//        throw new UnsupportedOperationException("Not supported yet.");
        try {
            session.saveOrUpdate(contato);
        } catch (Exception e) {
            transaction.rollback();
            e.printStackTrace();
        }
    }
    /**
     *
     * @return
     */
    @SuppressWarnings("unchecked")
    @Override
    public List<Contato> listContato() {
        List<Contato> courses = null;
        try {
            courses = session.createQuery("from Contato").list();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return courses;
    }

    @Override
    public Contato listContatoById(Integer contatoId) {
        Contato contato = null;
        try {
            contato = (Contato) session.get(Contato.class, contatoId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return contato;
    }

    @Override
    public void deleteContato(Integer contatoId) {
        try {
            Contato contato = (Contato) session.get(Contato.class, contatoId);
            session.delete(contato);
        } catch (Exception e) {
            transaction.rollback();
            e.printStackTrace();
        }
    }
}


7) Preparando o action (service)


Figura 28- Implementando a action
Figura 29- Implementando a action

ContatoAction.java :
package com.springlesson09.service;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.springlesson09.dao.ContatoDAO;
import com.springlesson09.dao.ContatoDAOImpl;
import com.springlesson09.model.Contato;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.ServletActionContext;

public class ContatoAction extends ActionSupport implements ModelDriven<Contato> {

    private static final long serialVersionUID = -6659925652584240539L;
    private Contato contato = new Contato();
    private List<Contato> contatoList = new ArrayList<Contato>();
    private ContatoDAO contatoDAO = new ContatoDAOImpl();

    @Override
    public Contato getModel() {
        return contato;
    }

    public String saveOrUpdate() {
        contatoDAO.saveOrUpdateContato(contato);
        return SUCCESS;
    }

    /**
     * To list all contatos.
     *
     * @return String
     */
    public String list() {
        contatoList = contatoDAO.listContato();
        return SUCCESS;
    }

    /**
     * To delete a contato.
     *
     * @return String
     */
    public String delete() {
        HttpServletRequest request = (HttpServletRequest) ActionContext.getContext().get(ServletActionContext.HTTP_REQUEST);
        contatoDAO.deleteContato(Integer.parseInt(request.getParameter("id")));
        return SUCCESS;
    }

    /**
     * To list a single contato by Id.
     *
     * @return String
     */
    public String edit() {
        HttpServletRequest request = (HttpServletRequest) ActionContext.getContext().get(ServletActionContext.HTTP_REQUEST);
        contato = contatoDAO.listContatoById(Integer.parseInt(request.getParameter("id")));
        return SUCCESS;
    }

    public Contato getContato() {
        return contato;
    }

    public void setContato(Contato contato) {
        this.contato = contato;
    }

    public List<Contato> getContatoList() {
        return contatoList;
    }

    public void setContatoList(List<Contato> contatoList) {
        this.contatoList = contatoList;
    }
}

8) Criando os arquivos XML struts.xml e web.xml

Figura 30- Implementando os arquivos XML


src/struts.xml :

<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
    <package name="default" extends="hibernate-default">
        <action name="saveOrUpdateContato" method="saveOrUpdate" class="com.springlesson09.service.ContatoAction">
            <result name="success" type="redirect">listContato</result>
        </action>
        <action name="listContato" method="list" class="com.springlesson09.service.ContatoAction">
            <result name="success">/register.jsp</result>
        </action>
        <action name="editContato" method="edit" class="com.springlesson09.service.ContatoAction">
            <result name="success">/register.jsp</result>
        </action>
        <action name="deleteContato" method="delete" class="com.springlesson09.service.ContatoAction">
            <result name="success" type="redirect">listContato</result>
        </action>
    </package>
</struts>


WEB-INF/web.xml :

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
    <display-name>Struts2Example19</display-name>
    <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>

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>


O NB já deve ter criado os arquivo XML context.xml e o beans.xml:

META-INF/context.xml 

<?xml version="1.0" encoding="UTF-8"?>
<Context antiJARLocking="true" path="/SpringLesson09"/>


WEB-INF/beans.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans 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/beans_1_0.xsd">
</beans>



Remova a lib do Hibernate  que o NB adicionou
Figura 31- Limpe o que o NB adicionou
e deixe apenas as utilizadas.
Figura 32- Limpeza das biblotecas

9) Criando os arquivos jsp e css

I) acertemos o index.jsp que o NB criou :
index.jsp :
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib uri="/struts-tags" prefix="s"%>
<!DOCTYPE html>
<html>
    <head>
        <title></title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body>
        <script type="text/javascript">
            location.href='/SpringLesson09/listContato';
        </script>
    </body>
</html>


II)register.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
         pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@taglib uri="/struts-tags" prefix="s"%>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
        <title>Novo Contato</title>
        <s:head />
        <style type="text/css">
            @import url(style.css);
        </style>
    </head>
    <body>
        <s:form action="saveOrUpdateContato">
            <s:push value="contato">
                <s:hidden name="id" />
                <s:textfield name="nome" label="Nome" />
                <s:textfield name="telefone" label="Fone" />
                <s:textfield name="email" label="Email" />

                <s:submit />
            </s:push>
        </s:form>

        <s:if test="contatoList.size() > 0">
            <div class="content">
                <table class="contatoTable" cellpadding="5px">
                    <tr class="even">
                        <th>Nome</th>
                        <th>Fone</th>
                        <th>Email</th>
                        <th>&nbsp;</th>
                        <th>&nbsp;</th>

                    </tr>
                    <s:iterator value="contatoList" status="contatoStatus">
                        <tr
                            class="<s:if test="#contatoStatus.odd == true ">odd</s:if><s:else>even</s:else>">
                            <td><s:property value="nome" /></td>
                            <td><s:property value="telefone" /></td>
                            <td><s:property value="email" /></td>

                            <td><s:url id="editURL" action="editContato">
                                    <s:param name="id" value="%{id}"></s:param>
                                </s:url> <s:a href="%{editURL}">Edit</s:a></td>
                            <td><s:url id="deleteURL" action="deleteContato">
                                    <s:param name="id" value="%{id}"></s:param>
                                </s:url> <s:a href="%{deleteURL}">Delete</s:a></td>
                            </tr>
                    </s:iterator>
                </table>
            </div>
        </s:if>
    </body>
</html>



III) o style.css

@CHARSET "ISO-8859-1";

.content {
font-family: sans-serif;
font-size: small;
}


.userTable {
 border-width: 1px 1px 1px 1px;
 border-spacing: 2px;
 border-style: outset outset outset outset;
 border-color: black black black black;
 border-collapse: collapse;
}

.userTable td {
 border-width: 1px 1px 1px 1px;
 border-spacing: 2px;
 border-style: outset outset outset outset;
 border-color: black black black black;
 border-collapse: collapse;
}

.userTable th {
 border-width: 1px 1px 1px 1px;
 border-spacing: 2px;
 border-style: outset outset outset outset;
 border-color: black black black black;
 border-collapse: collapse;
 background-color: rgb(255, 255, 255);
}

.odd {
background-color: #FFFFF0;
}

.even {
background-color: #FAF0E6;
}


10) Conferindo a estrutura do projeto :

Figura 33- Visão do projeto

11) Testando 

Figura 34-1º Teste sem utilizar as DI Spring


Observe o Log :
INFO: No Spring WebApplicationInitializer types detected on classpath
Oct 2, 2012 8:46:08 PM org.apache.catalina.core.ApplicationContext log
INFO: Initializing Spring root WebApplicationContext
Oct 2, 2012 8:50:54 PM org.apache.catalina.core.ApplicationContext log
INFO: SessionListener: contextDestroyed()
Oct 2, 2012 8:50:54 PM org.apache.catalina.core.ApplicationContext log
INFO: ContextListener: contextDestroyed()
Oct 2, 2012 8:52:25 PM org.apache.catalina.core.ApplicationContext log
INFO: No Spring WebApplicationInitializer types detected on classpath
Oct 2, 2012 8:52:25 PM org.apache.catalina.core.ApplicationContext log
INFO: Initializing Spring root WebApplicationContext
Oct 2, 2012 8:52:36 PM org.apache.catalina.core.ApplicationContext log
INFO: ContextListener: contextInitialized()
Oct 2, 2012 8:52:36 PM org.apache.catalina.core.ApplicationContext log
INFO: SessionListener: contextInitialized()
Oct 2, 2012 8:52:36 PM org.apache.catalina.core.ApplicationContext log
INFO: ContextListener: attributeAdded('org.apache.jasper.compiler.TldLocationsCache', 'org.apache.jasper.compiler.TldLocationsCache@6a74f160')
Oct 2, 2012 8:52:53 PM org.apache.catalina.core.ApplicationContext log
INFO: Closing Spring root WebApplicationContext
Oct 2, 2012 8:53:10 PM org.apache.catalina.core.ApplicationContext log
INFO: No Spring WebApplicationInitializer types detected on classpath
Oct 2, 2012 8:53:10 PM org.apache.catalina.core.ApplicationContext log
INFO: Initializing Spring root WebApplicationContext
Oct 2, 2012 8:54:20 PM org.apache.catalina.core.ApplicationContext log
INFO: Closing Spring root WebApplicationContext
Oct 2, 2012 8:54:25 PM org.apache.catalina.core.ApplicationContext log
INFO: No Spring WebApplicationInitializer types detected on classpath
Oct 2, 2012 8:54:25 PM org.apache.catalina.core.ApplicationContext log
INFO: Initializing Spring root WebApplicationContext
Oct 2, 2012 8:56:40 PM org.apache.catalina.core.ApplicationContext log
INFO: Closing Spring root WebApplicationContext
Oct 2, 2012 8:56:44 PM org.apache.catalina.core.ApplicationContext log
INFO: No Spring WebApplicationInitializer types detected on classpath
Oct 2, 2012 8:56:44 PM org.apache.catalina.core.ApplicationContext log
INFO: Initializing Spring root WebApplicationContext
Oct 2, 2012 9:02:24 PM org.apache.catalina.core.ApplicationContext log
INFO: No Spring WebApplicationInitializer types detected on classpath
Oct 2, 2012 9:02:24 PM org.apache.catalina.core.ApplicationContext log
INFO: Initializing Spring root WebApplicationContext
Oct 2, 2012 9:02:37 PM org.apache.catalina.core.ApplicationContext log
INFO: ContextListener: contextInitialized()
Oct 2, 2012 9:02:37 PM org.apache.catalina.core.ApplicationContext log
INFO: SessionListener: contextInitialized()
Oct 2, 2012 9:02:37 PM org.apache.catalina.core.ApplicationContext log
INFO: ContextListener: attributeAdded('org.apache.jasper.compiler.TldLocationsCache', 'org.apache.jasper.compiler.TldLocationsCache@fae7b85')


Experimente adicionar, atualizar e excluir registros:

Download do projeto NB:


Certo. Já que as lições são sobre o Spring. Vamos fazer o Spring gerenciar tudo isso


vou começar outra numeração:
Para que o Spring possa gerenciar os beans, precisaremos fazer algumas modificações no projeto.
Como implementar um BO(Business Objects) em vez de um serviço, essa adaptação fiz do mkYoung
e por isso no App vc verá uma estrutura para uma tabela customer, que tem a mesma implementação com menos métodos.

0) Apr

Se tiver problemas de memória com o TomCat, mesmo definindo no arquivo catalina.sh  JAVA_OPTS="-Xms128M -Xmx256" ou mais, e instalando o Apr ou use o GlassFish ;)

I) baixe os fontes da libapr : 

Figura 35-Instalação do APR


II) compie e instale
307  cd /Users/surfer/Downloads/JavaDocs/apr-1.4.6 
308  ./configure 
309  make
310  sudo make install


Apos compilar e instalar , crie os links p/ dentro de uma pasta que já está no CLASSPATH do tomcat
no caso do MAC OSX  

 311  cd /Library/Java/Extensions

 322  ln -s /usr/local/apr/lib/* .
Figura 36-linkando as novas libs



Apos compilar e instalar , instale o native que vem com  tomcat que tem como parámetro o local estão os binários do libapr



  348  cd /Users/surfer/_java/Servers/apache-tomcat-7.0.30/bin/tomcat-native-1.1.24-src/jni/native 
  349  ./configure --help
  350  ./configure --with-apr=/usr/local/apr/ --with-java-home=/System/Library/Frameworks/JavaVM.framework/Versions/Current/ 
  351  make
  352  sudo make install





Figura 37-Instalação do APR no tomcat Native

Figura 38-Instalação do APR no tomcat Native

na proxima vez que vc iniciar o tomcat no log deve aparecer algo como :

Log :
Oct 2, 2012 10:45:09 PM org.apache.catalina.core.AprLifecycleListener init
INFO: Loaded APR based Apache Tomcat Native library 1.1.24 using APR version 1.4.6.
Oct 2, 2012 10:45:10 PM org.apache.catalina.core.AprLifecycleListener init
INFO: APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true].
Oct 2, 2012 10:45:10 PM org.apache.catalina.core.AprLifecycleListener initializeSSL
INFO: OpenSSL successfully initialized (OpenSSL 0.9.8l 5 Nov 2009)
Oct 2, 2012 10:45:12 PM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["http-apr-8080"]
Oct 2, 2012 10:45:12 PM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["ajp-apr-8009"]
Oct 2, 2012 10:45:12 PM org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 4661 ms
Oct 2, 2012 10:45:12 PM org.apache.catalina.core.StandardService startInternal
INFO: Starting service Catalina
Oct 2, 2012 10:45:12 PM org.apache.catalina.core.StandardEngine startInternal
INFO: Starting Servlet Engine: Apache Tomcat/7.0.30

2) pegue a versão mais atual do full-hibernate-plugin-for-struts2 e verifique as libs

O projeto novo deve ficar com a seguinte estrutura :
Figura 39- Visão do projeto p/implementar o Spring

Figura 40- Visão do projeto p/implementar o Spring- Libs

usei o recurso de mapeamento p/ gerar a classe Customer

3) Crie a interface ContatoBo

Figura 41 - Adicionando um BO para o Contato


Java :
package com.springlesson09.model;

import java.util.List;

public interface ContatoBo {

    public void saveOrUpdateContato(Contato contato);

    public List<Contato> listContato();

    public Contato listContatoById(Integer contatoId);

    public void deleteContato(Integer contatoId);
}

4) Implemente a interface ContatoBo

Figura 42 - Implementando a Interface do BO
Figura 43 - Implementando a Interface do BO, pelo NB


Java :
package com.springlesson09.model;

import com.springlesson09.dao.CustomerDAO;
import java.util.List;


public class CustomerBoImpl implements CustomerBo {
     CustomerDAO customerDAO;
        //DI via Spring
    public void setCustomerDAO(CustomerDAO customerDAO) {
        this.customerDAO = customerDAO;
    }
        
        
    @Override
    public void addCustomer(Customer customer) {
        customerDAO.addCustomer(customer);

    }

    @Override
    public List<Customer> listCustomer() {
        return customerDAO.listCustomer();
    }
    
}

5) Verifique a classe de implementação do ContatoDAO

Usaremos os métodos do hibernate e não da nossa implementação ; observe :

ContatoDAOImpl.java
package com.springlesson09.dao;

import com.googlecode.s2hibernate.struts2.plugin.annotations.SessionTarget;
import com.googlecode.s2hibernate.struts2.plugin.annotations.TransactionTarget;
import com.springlesson09.model.Contato;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class ContatoDAOImpl extends HibernateDaoSupport implements ContatoDAO {

    @SessionTarget
    Session session;
    @TransactionTarget
    Transaction transaction;

    /**
     *
     * @param contato
     */
//    @Override
    public void saveOrUpdateContato(Contato contato) {
        try {
//            session.saveOrUpdate(contato);
            session.save(contato);
        } catch (Exception ex) {
            transaction.rollback();
            java.util.logging.Logger.getLogger(ContatoDAOImpl.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
    }

    /**
     *
     * @return
     */
//    @SuppressWarnings("unchecked")
//    @Override
    public List<Contato> listContato() {
        List<Contato> contatos = null;
        try {
            contatos = session.createQuery("from Contato").list();
        } catch (Exception ex) {
            java.util.logging.Logger.getLogger(ContatoDAOImpl.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        return contatos;
    }

//    @Override
    public Contato listContatoById(Integer contatoId) {
        Contato contato = null;
        try {
            contato = (Contato) session.get(Contato.class, contatoId);
        } catch (Exception ex) {
            java.util.logging.Logger.getLogger(ContatoDAOImpl.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        return contato;
    }

//    @Override
    public void deleteContato(Integer contatoId) {
        try {
            Contato contato = (Contato) session.get(Contato.class, contatoId);
            session.delete(contato);
        } catch (Exception ex) {
            transaction.rollback();
            java.util.logging.Logger.getLogger(ContatoDAOImpl.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
    }
}

6) Agora vamos criar a action p/ Contato

vou chmar de outro nome ContatoSpringAction.java p/ enfatizar o uso do Spring

Java :
package com.springlesson09.service;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ModelDriven;
import com.springlesson09.dao.ContatoDAO;
import com.springlesson09.dao.ContatoDAOImpl;
import com.springlesson09.model.Contato;
import com.springlesson09.model.ContatoBo;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.ServletActionContext;


public class ContatoSpringAction implements ModelDriven {

    Contato contato = new Contato();
    List<Contato> contatoList = new ArrayList<Contato>();
    ContatoDAO contatoDAO = new ContatoDAOImpl();
    ContatoBo contatoBo;

    @Override
    public Object getModel() {
        return contato;
    }

    public Contato getContato() {
        return contato;
    }

    public void setContato(Contato contato) {
        this.contato = contato;
    }

    public List<Contato> getContatoList() {
        return contatoList;
    }

    public void setContatoList(List<Contato> contatoList) {
        this.contatoList = contatoList;
    }

    public ContatoDAO getContatoDAO() {
        return contatoDAO;
    }

    public void setContatoDAO(ContatoDAO contatoDAO) {
        this.contatoDAO = contatoDAO;
    }

    public void setContatoBo(ContatoBo contatoBo) {
        this.contatoBo = contatoBo;
    }

    public String execute() throws Exception {
        return sync();
    }

    public String sync() throws Exception {
        return "success";
    }

    public String listcontato() throws Exception {
        contatoList = contatoDAO.listContato();
        return sync();
    }

    public String saveOrUpdateContato() throws Exception {

        contatoDAO.saveOrUpdateContato(contato);
        //reload
        contatoList = null;
        contatoList = contatoDAO.listContato();
        return sync();

    }

    public String listContatoById() throws Exception {

        contato = contatoDAO.listContatoById(contato.getId());
        return sync();

    }

    public String deleteContato() throws Exception {
        HttpServletRequest request = (HttpServletRequest) ActionContext.getContext().get(ServletActionContext.HTTP_REQUEST);
        contatoDAO.deleteContato(Integer.parseInt(request.getParameter("id")));
//        contatoDAO.deleteContato(contato.getId());
        contatoList = null;
        contatoList = contatoDAO.listContato();
        return sync();

    }
    
     public String edit() throws Exception {
        HttpServletRequest request = (HttpServletRequest) ActionContext.getContext().get(ServletActionContext.HTTP_REQUEST);
        contato = contatoDAO.listContatoById(Integer.parseInt(request.getParameter("id")));
        return sync();
    }
}

7) Implementemos um arquivo de nome jdbc.properties p/ ser lido pelo bean dataSource

Figura 44 - Arquivo properties


jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://ns1:3306/springlessons
jdbc.username=springlessons
jdbc.password=DHADdSXcDF29WGXy

8) Implementemos os Beans no arquivo applicationContext.xml

WEB-INF/applicationContext.xml: obs: neste caso coloquei todos os beans dentro desse arquivo

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">


        <!-- Meus Beans -->
        <!-- customer -->

    <bean id="customerAction" class="com.springlesson09.service.CustomerAction">
        <property name="customerBo" ref="customerBo" /> 
    </bean>
 
    <bean id="customerBo" class="com.springlesson09.model.CustomerBoImpl" >
        <property name="customerDAO" ref="customerDAO" />
    </bean>
 
    <bean id="customerDAO" class="com.springlesson09.dao.CustomerDAOImpl" >
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
    
    <!-- contato -->
    <bean id="contatoAction" class="com.springlesson09.service.ContatoSpringAction">
        <property name="contatoBo" ref="contatoBo" /> 
    </bean>

    <bean id="contatoBo" class="com.springlesson09.model.ContatoBoImpl" >
        <property name="contatoDAO" ref="contatoDAO" />
    </bean>

    <bean id="contatoDAO" class="com.springlesson09.dao.ContatoDAOImpl" >
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
    
    
    <!-- ADD PERSISTENCE SUPPORT HERE (jpa, hibernate, etc) -->
    <bean 
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location">
            <value>WEB-INF/jdbc.properties</value>
        </property>
    </bean>
 
    <bean id="dataSource" 
          class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
    </bean>
 
    <bean id="sessionFactory" 
              class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
 
        <property name="dataSource">
            <ref bean="dataSource"/>
        </property>
 
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
            </props>
        </property>
 
        <property name="mappingResources">
            <list>
                <value>com/springlesson09/model/Customer.hbm.xml</value>
                <value>com/springlesson09/model/Contato.hbm.xml</value>
            </list>
        </property> 
 
    </bean>
    
</beans>   

9) Implementemos os Actions no arquivo struts.xml

src/java/struts.xml. Obs: mantive comentado como era antes do spring p/ facilitar a comparação

<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
    <constant name="struts.devMode" value="true" />
 
    <!--<package name="default" namespace="/" extends="struts-default">-->
    <package name="default" namespace="/" extends="hibernate-default">
      <!-- customer -->
        <action name="addCustomerAction" 
                  class="com.springlesson09.service.CustomerAction" 
                  method="addCustomer" >
            <result name="success">/customer.jsp</result>
        </action>
 
        <action name="listCustomerAction"
                        class="com.springlesson09.service.CustomerAction" 
                        method="listCustomer" >
            <result name="success">/customer.jsp</result>
        </action> 
        <!-- contato --> 
        <action name="addContatoAction" 
                 class="com.springlesson09.service.ContatoSpringAction" 
                 method="saveOrUpdateContato" >
           <result name="success">/contato.jsp</result>
       </action>

       <action name="listContatoAction"
                       class="com.springlesson09.service.ContatoSpringAction" 
                       method="listcontato" >
           <result name="success">/contato.jsp</result>
       </action> 
       
       <action name="deleteContatoAction"
                       class="com.springlesson09.service.ContatoSpringAction" 
                       method="deleteContato" >
           <result name="success">/contato.jsp</result>
       </action>
       <action name="editContatoAction"
                       class="com.springlesson09.service.ContatoSpringAction" 
                       method="edit" >
           <result name="success">/contato.jsp</result>
       </action>  
        <!--  
            Antes do Spring  
            
        <package name="default" extends="hibernate-default">
        <action name="saveOrUpdateContato" method="saveOrUpdate" class="com.springlesson09.service.ContatoAction">
            <result name="success" type="redirect">listContato</result>
        </action>
        <action name="listContato" method="list" class="com.springlesson09.service.ContatoAction">
            <result name="success">/register.jsp</result>
        </action>
        <action name="editContato" method="edit" class="com.springlesson09.service.ContatoAction">
            <result name="success">/register.jsp</result>
        </action>
        <action name="deleteContato" method="delete" class="com.springlesson09.service.ContatoAction">
            <result name="success" type="redirect">listContato</result>
        </action>-->
    </package>
</struts>

10) Acertos no arquivo web.xml

XML :

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
    <display-name>Struts2Example19</display-name>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>
    
    <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>

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
 
    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>

</web-app>

11) Arquivos jsp

I) index.jsp
index.jsp :
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib uri="/struts-tags" prefix="s"%>
<!DOCTYPE html>
<html>
    <head>
        <title></title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body>
        
        <h2>JNSBTut Lesson 09 
        Spring 3 +  Full Hibernate Plugin's  + Struts 2</h2>
        
        <img src="images/splash_mcezzare_JSNBTut09.png" /><br>
        <ul>
            <li><s:a href="/SpringLesson09-v2/listCustomerAction.action">Customer</s:a></li>
            <li><s:a href="/SpringLesson09-v2/listContatoAction.action">Contato</s:a></li>
        
        </ul>
    </body>
</html>


II)contato.jsp (por enquanto p/ cadastrar e atualizar, no update não carrega a lista)

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
         pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@taglib uri="/struts-tags" prefix="s"%>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
        <title>Novo Contato</title>
        <s:head />
        <style type="text/css">
            @import url(style.css);
        </style>
    </head>
    <body>
        <s:form action="addContatoAction">
            <s:push value="contato">
                <s:hidden name="id" />
                <s:textfield name="nome" label="Nome" />
                <s:textfield name="telefone" label="Fone" />
                <s:textfield name="email" label="Email" />

                <s:submit />
            </s:push>
        </s:form>

        <s:if test="contatoList.size() > 0">
            <div class="content">
                <table class="contatoTable" cellpadding="5px">
                    <tr class="even">
                        <th>Nome</th>
                        <th>Fone</th>
                        <th>Email</th>
                        <th>&nbsp;</th>
                        <th>&nbsp;</th>

                    </tr>
                    <s:iterator value="contatoList" status="contatoStatus">
                        <tr
                            class="<s:if test="#contatoStatus.odd == true ">odd</s:if><s:else>even</s:else>">
                            <td><s:property value="nome" /></td>
                            <td><s:property value="telefone" /></td>
                            <td><s:property value="email" /></td>

                            <td><s:url id="editURL" action="editContato">
                                    <s:param name="id" value="%{id}"></s:param>
                                </s:url> <s:a href="%{editURL}">Edit</s:a></td>
                            <td><s:url id="deleteURL" action="deleteContato">
                                    <s:param name="id" value="%{id}"></s:param>
                                </s:url> <s:a href="%{deleteURL}">Delete</s:a></td>
                            </tr>
                    </s:iterator>
                </table>
            </div>
        </s:if>
    </body>
</html>





IV) customer (está no zip do projeto)

12) Teste

teste os dois: o CRUD
Figura 45 - Teste das implementações


o banco agora está assim : 
Figura 46 - Tabelas do banco

CREATE  TABLE IF NOT EXISTS `springlessons`.`customer` (
  `CUSTOMER_ID` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT ,
  `NAME` VARCHAR(45) NOT NULL ,
  `ADDRESS` VARCHAR(255) NOT NULL ,
  `CREATED_DATE` DATETIME NOT NULL ,
  PRIMARY KEY (`CUSTOMER_ID`) )
ENGINE = InnoDB
AUTO_INCREMENT = 5
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci 

CREATE  TABLE IF NOT EXISTS `springlessons`.`contato` (
  `id` INT(11) NOT NULL AUTO_INCREMENT ,
  `nome` VARCHAR(45) NULL DEFAULT NULL ,
  `telefone` VARCHAR(45) NULL DEFAULT NULL ,
  `email` VARCHAR(45) NULL DEFAULT NULL ,
  PRIMARY KEY (`id`) )
ENGINE = InnoDB
AUTO_INCREMENT = 96
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci

Coloquei uma imagem no index.jsp , veja como ficaram os arquivos:

Figura 47 - Projeto Organizado após as alterações - Classes e JSPs


e como ficaram as Libs:

Figura 48 - Projeto Organizado após as alterações - Libs
AO compilar o programa, observe tudo o q ele está carregando no Output : 
I) ao rodar no TomCat
Log :

IOct 3, 2012 2:51:15 AM org.apache.catalina.core.AprLifecycleListener init
INFO: Loaded APR based Apache Tomcat Native library 1.1.24 using APR version 1.4.6.
Oct 3, 2012 2:51:15 AM org.apache.catalina.core.AprLifecycleListener init
INFO: APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true].
Oct 3, 2012 2:51:16 AM org.apache.catalina.core.AprLifecycleListener initializeSSL
INFO: OpenSSL successfully initialized (OpenSSL 0.9.8l 5 Nov 2009)
Oct 3, 2012 2:51:17 AM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["http-apr-8080"]
Oct 3, 2012 2:51:17 AM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["ajp-apr-8009"]
Oct 3, 2012 2:51:17 AM org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 4328 ms
Oct 3, 2012 2:51:17 AM org.apache.catalina.core.StandardService startInternal
INFO: Starting service Catalina
Oct 3, 2012 2:51:17 AM org.apache.catalina.core.StandardEngine startInternal
INFO: Starting Servlet Engine: Apache Tomcat/7.0.30
Oct 3, 2012 2:51:17 AM org.apache.catalina.startup.HostConfig deployDescriptor
INFO: Deploying configuration descriptor /Users/surfer/_java/Servers/apache-tomcat-7.0.30/conf/Catalina/localhost/SpringLesson09-v3.xml
log4j:WARN No appenders could be found for logger (org.springframework.web.context.ContextLoader).
log4j:WARN Please initialize the log4j system properly.
02:51:45 - INFO: Full Hibernate Plugin Validation using Hibernate Validator 3.x 
Oct 3, 2012 2:51:46 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /Users/surfer/_java/Servers/apache-tomcat-7.0.30/webapps/docs
Oct 3, 2012 2:51:46 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /Users/surfer/_java/Servers/apache-tomcat-7.0.30/webapps/examples
Oct 3, 2012 2:51:48 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /Users/surfer/_java/Servers/apache-tomcat-7.0.30/webapps/host-manager
Oct 3, 2012 2:51:48 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /Users/surfer/_java/Servers/apache-tomcat-7.0.30/webapps/manager
Oct 3, 2012 2:51:49 AM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-apr-8080"]
Oct 3, 2012 2:51:49 AM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-apr-8009"]
Oct 3, 2012 2:51:49 AM org.apache.catalina.startup.Catalina start
INFO: Server startup in 32021 ms
Oct 3, 2012 2:51:55 AM org.apache.jasper.compiler.TldLocationsCache tldScanJar
INFO: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
02:53:26 - DEBUG: Preparing Injection Hibernate Session and Transaction process: /listContatoAction - Method: com.springlesson09.service.ContatoSpringAction.listcontato() 
02:53:26 - DEBUG: Full Hibernate Plugin's Session Factory: destroy factory required... 
02:53:26 - DEBUG: Full Hibernate Plugin's Session Factory: C3P0 not found 
02:53:26 - DEBUG: Full Hibernate Plugin's Session Factory: All SessionFactories Destroyed sucessful 
02:53:26 - DEBUG: Hibernate Session Required (from current Thread) - SessionFactory required: (default) 
02:53:26 - DEBUG: No Hibernate Session in current thread. New Hibernate Session will be created and returned (SessionFactory "(default)") 
02:53:26 - DEBUG: New Hibernate Session required - SessionFactory required: (default) 
02:53:26 - DEBUG: Full Hibernate Plugin's Session Factory build started... 
02:53:26 - DEBUG: Full Hibernate Plugin's Session Factory using Hibernate Annotation Configuration 
02:53:26 - DEBUG: Full Hibernate Plugin's Session Factory configuration file "/hibernate.cfg.xml" configured 
02:53:27 - DEBUG: SessionFactory "" configured from "/hibernate.cfg.xml" file 
02:53:27 - DEBUG: "" configured as the *default* SessionFactory of the Full Hibernate Plugin's Session Factory  
02:53:27 - DEBUG: Full Hibernate Plugin's Session Factory built successful 
02:53:27 - DEBUG: New Hibernate Session created and returned (SessionFactory "") 
02:53:27 - DEBUG: Hibernate Session from Full Hibernate Plugin's Hibernate Session Factory 
02:53:27 - DEBUG: Hibernate Session injected (by annotation) into Action. Field "session". Class "com.springlesson09.dao.ContatoDAOImpl" 
02:53:27 - DEBUG: Hibernate Transaction injected (by annotation) into Action. Field "transaction". Class "com.springlesson09.dao.ContatoDAOImpl" 
02:53:27 - WARN: Full Hibernate Plugin Validation Allowed only in Actions that 'ISA' ActionSupport 
Hibernate: 
    select
        contato0_.id as id5_,
        contato0_.nome as nome5_,
        contato0_.telefone as telefone5_,
        contato0_.email as email5_ 
    from
        springlessons.contato contato0_
02:53:36 - DEBUG: Hibernate Transation  org.hibernate.transaction.JDBCTransaction@3cd16610 rolledback by Full Hibernate Plugin 
02:53:36 - DEBUG: Hibernate Session closed 
02:53:36 - DEBUG: Hibernate Session closed by Full Hibernate Plugin's Hibernate Session Factory 
02:53:36 - DEBUG: Hibernate Transaction Committed 
02:53:36 - DEBUG: Injection Hibernate Session and Transaction process for /listContatoAction - Method: com.springlesson09.service.ContatoSpringAction.listcontato() finished 
02:54:12 - DEBUG: Preparing Injection Hibernate Session and Transaction process: /editContatoAction - Method: com.springlesson09.service.ContatoSpringAction.edit() 
02:54:12 - DEBUG: Hibernate Session Required (from current Thread) - SessionFactory required: (default) 
02:54:12 - DEBUG: No Hibernate Session in current thread. New Hibernate Session will be created and returned (SessionFactory "(default)") 
02:54:12 - DEBUG: New Hibernate Session required - SessionFactory required: (default) 
02:54:12 - DEBUG: New Hibernate Session created and returned (SessionFactory "") 
02:54:12 - DEBUG: Hibernate Session from Full Hibernate Plugin's Hibernate Session Factory 
02:54:12 - DEBUG: Hibernate Session injected (by annotation) into Action. Field "session". Class "com.springlesson09.dao.ContatoDAOImpl" 
02:54:12 - DEBUG: Hibernate Transaction injected (by annotation) into Action. Field "transaction". Class "com.springlesson09.dao.ContatoDAOImpl" 
02:54:12 - WARN: Full Hibernate Plugin Validation Allowed only in Actions that 'ISA' ActionSupport 
Hibernate: 
    select
        contato0_.id as id5_0_,
        contato0_.nome as nome5_0_,
        contato0_.telefone as telefone5_0_,
        contato0_.email as email5_0_ 
    from
        springlessons.contato contato0_ 
    where
        contato0_.id=?
02:54:13 - DEBUG: Hibernate Transation  org.hibernate.transaction.JDBCTransaction@11ace672 rolledback by Full Hibernate Plugin 
02:54:13 - DEBUG: Hibernate Session closed 
02:54:13 - DEBUG: Hibernate Session closed by Full Hibernate Plugin's Hibernate Session Factory 
02:54:13 - DEBUG: Hibernate Transaction Committed 
02:54:13 - DEBUG: Injection Hibernate Session and Transaction process for /editContatoAction - Method: com.springlesson09.service.ContatoSpringAction.edit() finished 
02:54:15 - DEBUG: Preparing Injection Hibernate Session and Transaction process: /addContatoAction - Method: com.springlesson09.service.ContatoSpringAction.saveOrUpdateContato() 
02:54:15 - DEBUG: Hibernate Session Required (from current Thread) - SessionFactory required: (default) 
02:54:15 - DEBUG: No Hibernate Session in current thread. New Hibernate Session will be created and returned (SessionFactory "(default)") 
02:54:15 - DEBUG: New Hibernate Session required - SessionFactory required: (default) 
02:54:15 - DEBUG: New Hibernate Session created and returned (SessionFactory "") 
02:54:15 - DEBUG: Hibernate Session from Full Hibernate Plugin's Hibernate Session Factory 
02:54:15 - DEBUG: Hibernate Session injected (by annotation) into Action. Field "session". Class "com.springlesson09.dao.ContatoDAOImpl" 
02:54:15 - DEBUG: Hibernate Transaction injected (by annotation) into Action. Field "transaction". Class "com.springlesson09.dao.ContatoDAOImpl" 
02:54:15 - WARN: Full Hibernate Plugin Validation Allowed only in Actions that 'ISA' ActionSupport 
Hibernate: 
    insert 
    into
        springlessons.contato
        (nome, telefone, email) 
    values
        (?, ?, ?)
Hibernate: 
    select
        contato0_.id as id5_,
        contato0_.nome as nome5_,
        contato0_.telefone as telefone5_,
        contato0_.email as email5_ 
    from
        springlessons.contato contato0_
02:54:17 - DEBUG: Hibernate Transation  org.hibernate.transaction.JDBCTransaction@17f74864 rolledback by Full Hibernate Plugin 
02:54:17 - DEBUG: Hibernate Session closed 
02:54:17 - DEBUG: Hibernate Session closed by Full Hibernate Plugin's Hibernate Session Factory 
02:54:17 - DEBUG: Hibernate Transaction Committed 
02:54:18 - DEBUG: Injection Hibernate Session and Transaction process for /addContatoAction - Method: com.springlesson09.service.ContatoSpringAction.saveOrUpdateContato() finished 
02:54:21 - DEBUG: Preparing Injection Hibernate Session and Transaction process: /deleteContatoAction - Method: com.springlesson09.service.ContatoSpringAction.deleteContato() 
02:54:21 - DEBUG: Hibernate Session Required (from current Thread) - SessionFactory required: (default) 
02:54:21 - DEBUG: No Hibernate Session in current thread. New Hibernate Session will be created and returned (SessionFactory "(default)") 
02:54:21 - DEBUG: New Hibernate Session required - SessionFactory required: (default) 
02:54:21 - DEBUG: New Hibernate Session created and returned (SessionFactory "") 
02:54:21 - DEBUG: Hibernate Session from Full Hibernate Plugin's Hibernate Session Factory 
02:54:21 - DEBUG: Hibernate Session injected (by annotation) into Action. Field "session". Class "com.springlesson09.dao.ContatoDAOImpl" 
02:54:21 - DEBUG: Hibernate Transaction injected (by annotation) into Action. Field "transaction". Class "com.springlesson09.dao.ContatoDAOImpl" 
02:54:21 - WARN: Full Hibernate Plugin Validation Allowed only in Actions that 'ISA' ActionSupport 
Hibernate: 
    select
        contato0_.id as id5_0_,
        contato0_.nome as nome5_0_,
        contato0_.telefone as telefone5_0_,
        contato0_.email as email5_0_ 
    from
        springlessons.contato contato0_ 
    where
        contato0_.id=?
Hibernate: 
    delete 
    from
        springlessons.contato 
    where
        id=?
Hibernate: 
    select
        contato0_.id as id5_,
        contato0_.nome as nome5_,
        contato0_.telefone as telefone5_,
        contato0_.email as email5_ 
    from
        springlessons.contato contato0_
02:54:21 - DEBUG: Hibernate Transation  org.hibernate.transaction.JDBCTransaction@42886462 rolledback by Full Hibernate Plugin 
02:54:21 - DEBUG: Hibernate Session closed 
02:54:21 - DEBUG: Hibernate Session closed by Full Hibernate Plugin's Hibernate Session Factory 
02:54:21 - DEBUG: Hibernate Transaction Committed 
02:54:21 - DEBUG: Injection Hibernate Session and Transaction process for /deleteContatoAction - Method: com.springlesson09.service.ContatoSpringAction.deleteContato() finished 
02:54:21 - DEBUG: Preparing Injection Hibernate Session and Transaction process: /listContatoAction - Method: com.springlesson09.service.ContatoSpringAction.listcontato() 
02:54:21 - DEBUG: Hibernate Session Required (from current Thread) - SessionFactory required: (default) 
02:54:21 - DEBUG: No Hibernate Session in current thread. New Hibernate Session will be created and returned (SessionFactory "(default)") 
02:54:21 - DEBUG: New Hibernate Session required - SessionFactory required: (default) 
02:54:21 - DEBUG: New Hibernate Session created and returned (SessionFactory "") 
02:54:21 - DEBUG: Hibernate Session from Full Hibernate Plugin's Hibernate Session Factory 
02:54:21 - DEBUG: Hibernate Session injected (by annotation) into Action. Field "session". Class "com.springlesson09.dao.ContatoDAOImpl" 
02:54:22 - DEBUG: Hibernate Transaction injected (by annotation) into Action. Field "transaction". Class "com.springlesson09.dao.ContatoDAOImpl" 
02:54:22 - WARN: Full Hibernate Plugin Validation Allowed only in Actions that 'ISA' ActionSupport 
Hibernate: 
    select
        contato0_.id as id5_,
        contato0_.nome as nome5_,
        contato0_.telefone as telefone5_,
        contato0_.email as email5_ 
    from
        springlessons.contato contato0_
02:54:23 - DEBUG: Hibernate Transation  org.hibernate.transaction.JDBCTransaction@1f4e8ac9 rolledback by Full Hibernate Plugin 
02:54:23 - DEBUG: Hibernate Session closed 
02:54:23 - DEBUG: Hibernate Session closed by Full Hibernate Plugin's Hibernate Session Factory 
02:54:23 - DEBUG: Hibernate Transaction Committed 
02:54:23 - DEBUG: Injection Hibernate Session and Transaction process for /listContatoAction - Method: com.springlesson09.service.ContatoSpringAction.listcontato() finished






II) ao rodar no GlassFish (não funcionou)
Log :
INFO: JMX005: JMXStartupService had Started JMXConnector on JMXService URL service:jmx:rmi://mmac.lpanic.intra:8686/jndi/rmi://mmac.lpanic.intra:8686/jmxrmi
INFO: WEB0169: Created HTTP listener [http-listener-1] on host/port [0.0.0.0:8080]
INFO: WEB0169: Created HTTP listener [http-listener-2] on host/port [0.0.0.0:8181]
INFO: WEB0169: Created HTTP listener [admin-listener] on host/port [0.0.0.0:4848]
INFO: WEB0171: Created virtual server [server]
INFO: WEB0171: Created virtual server [__asadmin]
INFO: WEB0172: Virtual server [server] loaded default web module []
INFO: defaultVirtualServer = server
INFO: SEC1002: Security Manager is OFF.
INFO: No default web.xml
INFO: standardContext = StandardEngine[glassfish-web].StandardHost[server].StandardContext[/osgi]
INFO: No default web.xml
INFO: standardContext = StandardEngine[glassfish-web].StandardHost[__asadmin].StandardContext[/osgi]
INFO: SEC1010: Entering Security Startup Service
INFO: SEC1143: Loading policy provider com.sun.enterprise.security.provider.PolicyWrapper.
INFO: SEC1115: Realm [admin-realm] of classtype [com.sun.enterprise.security.auth.realm.file.FileRealm] successfully created.
INFO: SEC1115: Realm [file] of classtype [com.sun.enterprise.security.auth.realm.file.FileRealm] successfully created.
INFO: SEC1115: Realm [certificate] of classtype [com.sun.enterprise.security.auth.realm.certificate.CertificateRealm] successfully created.
INFO: SEC1011: Security Service(s) Started Successfully
INFO: WELD-000900 1.1.8 (Final)
INFO: PWC1412: WebModule[null] ServletContext.log():No Spring WebApplicationInitializer types detected on classpath
INFO: PWC1412: WebModule[null] ServletContext.log():Initializing Spring root WebApplicationContext
SEVERE: log4j:WARN No appenders could be found for logger (org.springframework.web.context.ContextLoader).
SEVERE: log4j:WARN Please initialize the log4j system properly.
INFO: Hibernate 3.5.0-Final
INFO: hibernate.properties not found
INFO: Bytecode provider name : javassist
INFO: using JDK 1.4 java.sql.Timestamp handling
INFO: Mapping class: com.springlesson09.model.Customer -> customer
INFO: Mapping class: com.springlesson09.model.Contato -> contato
INFO: Initializing connection provider: org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider
INFO: RDBMS: MySQL, version: 5.1.63-0ubuntu0.11.10.1
INFO: JDBC driver: MySQL-AB JDBC Driver, version: mysql-connector-java-5.1.22 ( Revision: ${bzr.revision-id} )
INFO: Using dialect: org.hibernate.dialect.MySQLDialect
INFO: Transaction strategy: org.springframework.orm.hibernate3.SpringTransactionFactory
INFO: No TransactionManagerLookup configured (in JTA environment, use of read-write or transactional second-level cache is not recommended)
INFO: Automatic flush during beforeCompletion(): disabled
INFO: Automatic session close at end of transaction: disabled
INFO: JDBC batch size: 15
INFO: JDBC batch updates for versioned data: disabled
INFO: Scrollable result sets: enabled
INFO: JDBC3 getGeneratedKeys(): enabled
INFO: Connection release mode: auto
INFO: Maximum outer join fetch depth: 2
INFO: Default batch fetch size: 1
INFO: Generate SQL with comments: disabled
INFO: Order SQL updates by primary key: disabled
INFO: Order SQL inserts for batching: disabled
INFO: Query translator: org.hibernate.hql.ast.ASTQueryTranslatorFactory
INFO: Using ASTQueryTranslatorFactory
INFO: Query language substitutions: {}
INFO: JPA-QL strict compliance: disabled
INFO: Second-level cache: enabled
INFO: Query cache: disabled
INFO: Cache region factory : org.hibernate.cache.impl.NoCachingRegionFactory
INFO: Optimize cache for minimal puts: disabled
INFO: Structured second-level cache entries: disabled
INFO: Echoing all SQL to stdout
INFO: Statistics: disabled
INFO: Deleted entity synthetic identifier rollback: disabled
INFO: Default entity-mode: pojo
INFO: Named query checking : enabled
INFO: Check Nullability in Core (should be disabled when Bean Validation is on): enabled
INFO: building session factory
INFO: Not binding factory to JNDI, no JNDI name configured
INFO: 01:18:33 - INFO: Full Hibernate Plugin Validation using Hibernate Validator 3.x 

INFO: WEB0671: Loading application [SpringLesson09-v2] at [/SpringLesson09-v2]
INFO: SpringLesson09-v2 was successfully deployed in 30,920 milliseconds.
WARNING: PWC4011: Unable to set request character encoding to UTF-8 from context /SpringLesson09-v2, because request parameters have already been read, or ServletRequest.getReader() has already been called
WARNING: PWC4011: Unable to set request character encoding to UTF-8 from context /SpringLesson09-v2, because request parameters have already been read, or ServletRequest.getReader() has already been called
WARNING: PWC4011: Unable to set request character encoding to UTF-8 from context /SpringLesson09-v2, because request parameters have already been read, or ServletRequest.getReader() has already been called
INFO: 01:19:46 - DEBUG: Preparing Injection Hibernate Session and Transaction process: /listContatoAction - Method: com.springlesson09.service.ContatoSpringAction.listcontato() 

INFO: 01:19:46 - DEBUG: Full Hibernate Plugin's Session Factory: destroy factory required... 

INFO: 01:19:46 - DEBUG: Full Hibernate Plugin's Session Factory: C3P0 not found 

INFO: 01:19:46 - DEBUG: Full Hibernate Plugin's Session Factory: All SessionFactories Destroyed sucessful 

INFO: 01:19:46 - DEBUG: Hibernate Session Required (from current Thread) - SessionFactory required: (default) 

INFO: 01:19:46 - DEBUG: No Hibernate Session in current thread. New Hibernate Session will be created and returned (SessionFactory "(default)") 

INFO: 01:19:46 - DEBUG: New Hibernate Session required - SessionFactory required: (default) 

INFO: 01:19:46 - DEBUG: Full Hibernate Plugin's Session Factory build started... 

INFO: Hibernate Annotations 3.5.0-Final
INFO: Hibernate Commons Annotations 3.2.0.Final
INFO: 01:19:47 - DEBUG: Full Hibernate Plugin's Session Factory using Hibernate Annotation Configuration 

INFO: configuring from resource: /hibernate.cfg.xml
INFO: Configuration resource: /hibernate.cfg.xml
INFO: Reading mappings from resource : com/springlesson09/model/Usuario.hbm.xml
INFO: Reading mappings from resource : com/springlesson09/model/Contato.hbm.xml
INFO: Reading mappings from resource : com/springlesson09/model/Customer.hbm.xml
INFO: Configured SessionFactory: null
INFO: 01:19:47 - DEBUG: Full Hibernate Plugin's Session Factory configuration file "/hibernate.cfg.xml" configured 

INFO: Unable to find org.hibernate.search.event.FullTextIndexEventListener on the classpath. Hibernate Search is not enabled.
INFO: Mapping class: com.springlesson09.model.Usuario -> usuario
INFO: Mapping class: com.springlesson09.model.Contato -> contato
INFO: Mapping class: com.springlesson09.model.Customer -> customer
INFO: Hibernate Validator 3.1.0.GA
INFO: Using Hibernate built-in connection pool (not for production use!)
INFO: Hibernate connection pool size: 20
INFO: autocommit mode: false
INFO: using driver: com.mysql.jdbc.Driver at URL: jdbc:mysql://ns1:3306/springlessons?zeroDateTimeBehavior=convertToNull
INFO: connection properties: {user=springlessons, password=****}
WARNING: Could not obtain connection to query metadata
java.sql.SQLException: No suitable driver found for jdbc:mysql://ns1:3306/springlessons?zeroDateTimeBehavior=convertToNull
 at java.sql.DriverManager.getConnection(DriverManager.java:602)
 at java.sql.DriverManager.getConnection(DriverManager.java:154)
 at org.hibernate.connection.DriverManagerConnectionProvider.getConnection(DriverManagerConnectionProvider.java:133)
 at org.hibernate.cfg.SettingsFactory.buildSettings(SettingsFactory.java:114)
 at org.hibernate.cfg.Configuration.buildSettingsInternal(Configuration.java:2163)
 at org.hibernate.cfg.Configuration.buildSettings(Configuration.java:2159)
 at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1383)
 at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:954)
 at com.googlecode.s2hibernate.struts2.plugin.util.HibernateSessionFactory.createAndTestSessionFactory(HibernateSessionFactory.java:282)
 at com.googlecode.s2hibernate.struts2.plugin.util.HibernateSessionFactory.rebuildSessionFactory(HibernateSessionFactory.java:227)
 at com.googlecode.s2hibernate.struts2.plugin.util.HibernateSessionFactory.getNewSession(HibernateSessionFactory.java:155)
 at com.googlecode.s2hibernate.struts2.plugin.util.HibernateSessionFactory.getSession(HibernateSessionFactory.java:100)
 at com.googlecode.s2hibernate.struts2.plugin.interceptors.SessionTransactionInjectorInterceptor.getHibernateSessionFromFactory(SessionTransactionInjectorInterceptor.java:379)
 at com.googlecode.s2hibernate.struts2.plugin.interceptors.SessionTransactionInjectorInterceptor.injectHibernateCoreSessionByAnnotation(SessionTransactionInjectorInterceptor.java:454)
 at com.googlecode.s2hibernate.struts2.plugin.interceptors.SessionTransactionInjectorInterceptor.injectHibernateCoreSessionByAnnotation(SessionTransactionInjectorInterceptor.java:470)
 at com.googlecode.s2hibernate.struts2.plugin.interceptors.SessionTransactionInjectorInterceptor.intercept(SessionTransactionInjectorInterceptor.java:165)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:163)
 at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:122)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:195)
 at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:148)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:93)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:235)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:89)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:128)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at org.apache.struts2.interceptor.ProfilingActivationInterceptor.intercept(ProfilingActivationInterceptor.java:104)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at org.apache.struts2.interceptor.debugging.DebuggingInterceptor.intercept(DebuggingInterceptor.java:267)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:126)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:148)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:138)
 at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:128)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:176)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:52)
 at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:468)
 at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)
 at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:76)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:217)
 at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279)
 at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
 at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
 at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
 at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:161)
 at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331)
 at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
 at com.sun.enterprise.v3.services.impl.ContainerMapper$AdapterCallable.call(ContainerMapper.java:317)
 at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)
 at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:860)
 at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:757)
 at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1056)
 at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:229)
 at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
 at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
 at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
 at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
 at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
 at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
 at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
 at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
 at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
 at java.lang.Thread.run(Thread.java:680)

INFO: Using dialect: org.hibernate.dialect.MySQLDialect
INFO: Disabling contextual LOB creation as connection was null
INFO: Using default transaction strategy (direct JDBC transactions)
INFO: No TransactionManagerLookup configured (in JTA environment, use of read-write or transactional second-level cache is not recommended)
INFO: Automatic flush during beforeCompletion(): disabled
INFO: Automatic session close at end of transaction: disabled
INFO: Scrollable result sets: disabled
INFO: JDBC3 getGeneratedKeys(): disabled
INFO: Connection release mode: auto
INFO: Maximum outer join fetch depth: 2
INFO: Default batch fetch size: 1
INFO: Generate SQL with comments: disabled
INFO: Order SQL updates by primary key: disabled
INFO: Order SQL inserts for batching: disabled
INFO: Query translator: org.hibernate.hql.ast.ASTQueryTranslatorFactory
INFO: Using ASTQueryTranslatorFactory
INFO: Query language substitutions: {}
INFO: JPA-QL strict compliance: disabled
INFO: Second-level cache: enabled
INFO: Query cache: disabled
INFO: Cache region factory : org.hibernate.cache.impl.NoCachingRegionFactory
INFO: Optimize cache for minimal puts: disabled
INFO: Structured second-level cache entries: disabled
INFO: Echoing all SQL to stdout
INFO: Statistics: disabled
INFO: Deleted entity synthetic identifier rollback: disabled
INFO: Default entity-mode: pojo
INFO: Named query checking : enabled
INFO: Check Nullability in Core (should be disabled when Bean Validation is on): disabled
INFO: building session factory
INFO: Not binding factory to JNDI, no JNDI name configured
WARNING: SQL Error: 0, SQLState: 08001
SEVERE: No suitable driver found for jdbc:mysql://ns1:3306/springlessons?zeroDateTimeBehavior=convertToNull
SEVERE: Could not build Full Hibernate Plugin's Session Factory
SEVERE: org.hibernate.exception.JDBCConnectionException: Cannot open connection
 at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:99)
 at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
 at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:52)
 at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:449)
 at org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:167)
 at org.hibernate.jdbc.BorrowedConnectionProxy.invoke(BorrowedConnectionProxy.java:74)
 at $Proxy146.getMetaData(Unknown Source)
 at com.googlecode.s2hibernate.struts2.plugin.util.HibernateSessionFactory.createAndTestSessionFactory(HibernateSessionFactory.java:285)
 at com.googlecode.s2hibernate.struts2.plugin.util.HibernateSessionFactory.rebuildSessionFactory(HibernateSessionFactory.java:227)
 at com.googlecode.s2hibernate.struts2.plugin.util.HibernateSessionFactory.getNewSession(HibernateSessionFactory.java:155)
 at com.googlecode.s2hibernate.struts2.plugin.util.HibernateSessionFactory.getSession(HibernateSessionFactory.java:100)
 at com.googlecode.s2hibernate.struts2.plugin.interceptors.SessionTransactionInjectorInterceptor.getHibernateSessionFromFactory(SessionTransactionInjectorInterceptor.java:379)
 at com.googlecode.s2hibernate.struts2.plugin.interceptors.SessionTransactionInjectorInterceptor.injectHibernateCoreSessionByAnnotation(SessionTransactionInjectorInterceptor.java:454)
 at com.googlecode.s2hibernate.struts2.plugin.interceptors.SessionTransactionInjectorInterceptor.injectHibernateCoreSessionByAnnotation(SessionTransactionInjectorInterceptor.java:470)
 at com.googlecode.s2hibernate.struts2.plugin.interceptors.SessionTransactionInjectorInterceptor.intercept(SessionTransactionInjectorInterceptor.java:165)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:163)
 at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:122)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:195)
 at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:148)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:93)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:235)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:89)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:128)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at org.apache.struts2.interceptor.ProfilingActivationInterceptor.intercept(ProfilingActivationInterceptor.java:104)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at org.apache.struts2.interceptor.debugging.DebuggingInterceptor.intercept(DebuggingInterceptor.java:267)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:126)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:148)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:138)
 at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:128)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:176)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:52)
 at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:468)
 at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)
 at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:76)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:217)
 at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279)
 at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
 at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
 at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
 at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:161)
 at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331)
 at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
 at com.sun.enterprise.v3.services.impl.ContainerMapper$AdapterCallable.call(ContainerMapper.java:317)
 at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)
 at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:860)
 at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:757)
 at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1056)
 at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:229)
 at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
 at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
 at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
 at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
 at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
 at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
 at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
 at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
 at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
 at java.lang.Thread.run(Thread.java:680)
Caused by: java.sql.SQLException: No suitable driver found for jdbc:mysql://ns1:3306/springlessons?zeroDateTimeBehavior=convertToNull
 at java.sql.DriverManager.getConnection(DriverManager.java:602)
 at java.sql.DriverManager.getConnection(DriverManager.java:154)
 at org.hibernate.connection.DriverManagerConnectionProvider.getConnec
SEVERE: tion(DriverManagerConnectionProvider.java:133)
 at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:446)
 ... 76 more

SEVERE: Error! Please, check your JDBC/JDNI Configurations and Database Server avaliability. 
 at /listContatoAction - Method: com.springlesson09.service.ContatoSpringAction.listcontato()
 Could not open or inject a Hibernate Session in ValueStack: org.hibernate.exception.JDBCConnectionException: Cannot open connection
SEVERE: com.googlecode.s2hibernate.lang.BuildSessionFactoryException: org.hibernate.exception.JDBCConnectionException: Cannot open connection
 at com.googlecode.s2hibernate.struts2.plugin.util.HibernateSessionFactory.rebuildSessionFactory(HibernateSessionFactory.java:246)
 at com.googlecode.s2hibernate.struts2.plugin.util.HibernateSessionFactory.getNewSession(HibernateSessionFactory.java:155)
 at com.googlecode.s2hibernate.struts2.plugin.util.HibernateSessionFactory.getSession(HibernateSessionFactory.java:100)
 at com.googlecode.s2hibernate.struts2.plugin.interceptors.SessionTransactionInjectorInterceptor.getHibernateSessionFromFactory(SessionTransactionInjectorInterceptor.java:379)
 at com.googlecode.s2hibernate.struts2.plugin.interceptors.SessionTransactionInjectorInterceptor.injectHibernateCoreSessionByAnnotation(SessionTransactionInjectorInterceptor.java:454)
 at com.googlecode.s2hibernate.struts2.plugin.interceptors.SessionTransactionInjectorInterceptor.injectHibernateCoreSessionByAnnotation(SessionTransactionInjectorInterceptor.java:470)
 at com.googlecode.s2hibernate.struts2.plugin.interceptors.SessionTransactionInjectorInterceptor.intercept(SessionTransactionInjectorInterceptor.java:165)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:163)
 at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:122)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:195)
 at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:148)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:93)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:235)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:89)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:128)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at org.apache.struts2.interceptor.ProfilingActivationInterceptor.intercept(ProfilingActivationInterceptor.java:104)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at org.apache.struts2.interceptor.debugging.DebuggingInterceptor.intercept(DebuggingInterceptor.java:267)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:126)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:148)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:138)
 at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:128)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:176)
 at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
 at org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:52)
 at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:468)
 at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)
 at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:76)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:217)
 at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279)
 at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
 at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
 at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
 at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:161)
 at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331)
 at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
 at com.sun.enterprise.v3.services.impl.ContainerMapper$AdapterCallable.call(ContainerMapper.java:317)
 at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)
 at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:860)
 at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:757)
 at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1056)
 at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:229)
 at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
 at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
 at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
 at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
 at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
 at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
 at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
 at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
 at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
 at java.lang.Thread.run(Thread.java:680)
Caused by: org.hibernate.exception.JDBCConnectionException: Cannot open connection
 at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:99)
 at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
 at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:52)
 at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:449)
 at org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:167)
 at org.hibernate.jdbc.BorrowedConnectionProxy.invoke(BorrowedConnectionProxy.java:74)
 at $Proxy146.getMetaData(Unknown Source)
 at com.googlecode.s2hibernate.struts2.plugin.util.HibernateSessionFactory.createAndTestSessionFactory(HibernateSessionFactory.java:285)
 at com.googlecode.s2hibernate.struts2.plugin.util.HibernateSessionFactory.rebuildSessionFactory(HibernateSessionFactory.java:227)
 ... 71 more
Caused by: java.sql.SQLException: No suitable
SEVERE:  driver found for jdbc:mysql://ns1:3306/springlessons?zeroDateTimeBehavior=convertToNull
 at java.sql.DriverManager.getConnection(DriverManager.java:602)
 at java.sql.DriverManager.getConnection(DriverManager.java:154)
 at org.hibernate.connection.DriverManagerConnectionProvider.getConnection(DriverManagerConnectionProvider.java:133)
 at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:446)
 ... 76 more

INFO: Domain Pinged: stable.glassfish.org
WARNING: PWC4011: Unable to set request character encoding to UTF-8 from context /SpringLesson09-v2, because request parameters have already been read, or ServletRequest.getReader() has already been called


Download do projeto NB
SpringLesson09-v2.3.zip



Resumo, o que vimos :

- Aprendemos a conectar no Mysql pelo NB e armazenar um driver
- Aprendemos a utilizar e configurar o Hibernate pelo NB
- Aprendemos a fazer a engenharia reversa das tabelas do banco para as configurações do Hibernate gerando os arquivos de para os mappings: Hibernate Mapping
na versão V1:
- Implementar o Struts 2.1.6
- Criamos uma interface contatoDAO
- Implementamos a interface com a classe ContatoDaoImpl
- Criamos uma interface de Serviço ContatoAction que extende com.opensymphony.xwork2.ActionSupport.ActionSupport implementando ModelDriven
- Definimos as actions e mappings no arquivo struts-config.xml e web.xml
- Removemos as libs repetidas adicionadas pelo NB
- Implementamos a interface  com a classe ContatoServiceImpl
- Criamos as classes p/ atender os actions que são mapeados no arquivo struts.xml, que extendem a classe org.apache.struts.action.Action
- Definimos as actions e mappings no arquivo struts.xml
- Criamos uma view através de um arquivo index.jsp



na versão V2:
- Habilitamos o módulo APR no TomCat
- introduzimos o  Full Hibernate Plugin's Session Factory
- introduzimos o conceito de BO (Business Objects)
- Criamos uma interface de Serviço ContatoSpringAction que extende com.opensymphony.xwork2.ActionSupport.ActionSupport
- Externalizamos as credenciais do banco em um arquivo.properties
- Implementamos os Beans no applicationContext.xml para o Spring poder utilizar seus recursos de Injeção de dependências
- Aprendemos a usar as anotações do HB Transactional e Session
- Criamos uma vier p/ mostrar os erros
- Integramos o Spring 3 com o Struts 2 e delegamos a responsabilidade dos beans p/ serem gerenciados pelo Spring
- Vimos nos logs a ordem em que as classes são instanciadas e como localizar erros
- Testamos os cadastro e vimos funcionando


Vamos implementar as funcionalidades do Sistema que fizemos com Swing na lição 7, mas melhorando nossa interface utilizando outros recursos como facelets,richFaces, etc..

Dúvidas, Contribuições, Sugestões? Poste..
Grato,
Até a próxima.