Integrando Spring, Struts 2 e Hibernate
Aqui um pequeno tutorial de como desenvolver uma aplicação web integrando Struts 2, Spring e Hibernate. A idéia básica é usar a implementação do padrão MVC do Struts 2, a Injeção de Dependência do Spring e o Mapeamento Objeto-Relacional do Hibernate.
Ao final do post coloquei um link com a aplicação de exemplo para download.
As ferramentas utilizadas neste exemplo são o Banco de dados MySQL, Eclipse IDE, Spring Framework (versão 2.5.6), Struts (versão 2.1.6) e Hibernate 3.
Vamos dar início ao nosso passo-a-passo…
Montando e configurando o ambiente:
Faça o download do MySQL: aqui
Faça o download do Eclipse IDE: aqui
Faça o download do Spring Framework: aqui
Faça o Download do Struts 2: aqui
Instale o Banco de Dados MySQL, e crie um schema para o nosso tutorial, neste caso vou chama-lo de “example“. Inicie o Eclipse e crie um projeto do tipo Dynamic Web Project, aqui vou chama-lo também de “example“.
Feito isso, você já tem a estrutura básica de sua aplicação montada. Agora precisamos de alguns arquivos de biblioteca, para fazer nossa aplicação funcionar, vamos utilizar os seguintes arquivos, que podem ser encontrados nas distruições do Spring e do Struts que você baixou:
Copie estes arquivos para a pasta WebContent/WEB-INF/lib do seu projeto:
commons-collections.jar
commons-dbcp.jar
commons-fileupload-1.2.1.jar
commons-io-1.3.2.jar
commons-logging-1.1.jar
commons-pool.jar
dom4j-1.6.1.jar
freemarker-2.3.13.jar
hibernate-annotations.jar
hibernate-commons-annotations.jar
hibernate-entitymanager.jar
hibernate3.jar
jaxen-1.1-beta-7.jar
junit-3.8.1.jar
log4j-1.2.15.jar
ognl-2.6.11.jar
persistence.jar
slf4j-api-1.5.0.jar
slf4j-log4j12-1.5.0.jar
spring-aop.jar
spring-beans-2.5.3.jar
spring-context-2.5.3.jar
spring-core.jar
spring-mock-2.0.8.jar
spring-orm.jar
spring-test-2.5.6.jar
spring-web-2.5.3.jar
spring.jar
struts2-core-2.1.6.jar
struts2-spring-plugin-2.1.6.jar
xwork-2.1.2.jar
Você precisará também do driver JDBC do MySQL, qude pode ser baixado aqui. Depois, copie o jar mysql-connector-java-5.1.7-bin.jar para o mesmo diretório lib da nossa aplicação.
Precisaremos também da API javassist, que é usada pelo Hibernate, e pode ser encontrada aqui. Coloque o jar do Javassist no diretório lib da aplicação.
Pronto! Agora vamos finalmente começar a desenvolver…
Vamos primeiro criar nosso Action, chamaremos ele de WelcomeAction, e o colocaremos no pacote “example.actions“. Abaixo o código do Action, bem simples:
package example.actions;
import java.util.Date;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.opensymphony.xwork2.ActionSupport;public class WelcomeAction extends ActionSupport {
private Log logger = LogFactory.getLog(this.getClass());
public static final String MESSAGE = “Struts 2 Hello World Tutorial!”;
public String execute() throws Exception {
logger.info(”returning welcome action”);
setMessage(MESSAGE);
return SUCCESS;}
private String message;
public void setMessage(String message) {
this.message = message;}
public String getMessage() {
return message;
}
public String getCurrentTime() {
return new Date().toString();
}
}
No próximo passo criaremos nossas páginas, a páginal inicial, index.html é simples e apenas faz o redirecionamento para nossa página de boas-vindas, ela ficará assim:
<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.0 Transitional//EN”>
<html>
<head>
<META HTTP-EQUIV=”Refresh” CONTENT=”0;URL=pages/welcomeAction.action”>
</head><body>
<p>Loading …</p>
</body>
</html>
<%@ taglib prefix=”s” uri=”/struts-tags”%><html><head><title>Struts 2 Hello World Application!</title></head><body><s:property value=”message” /><p>Current date and time is: <b><s:property value=”currentTime” /></b></body></html>
No próximo passo, criaremos nosso arquivo de mapeamento dos Actions, chamado struts.xml, no diretório raiz das classes. Coloque este arquivo na pasta “src”, isso fará com que o Eclipse o copie automaticamente para o diretório das classes compiladas.
O arquivo struts.xml mapeando nosso WelcomeAction ficará assim:
<?xml version=”1.0″ encoding=”UTF-8″ ?>
<!DOCTYPE struts PUBLIC“-//Apache Software Foundation//DTD Struts Configuration 2.0//EN”
“http://struts.apache.org/dtds/struts-2.0.dtd”>
<struts>
<constant name=”struts.enable.DynamicMethodInvocation” value=”false” />
<constant name=”struts.devMode” value=”true” /><package name=”pages” namespace=”/pages” extends=”struts-default”>
<action name=”welcomeAction” class=”example.actions.WelcomeAction”> <result>/pages/welcome.jsp</result>
</action>
</package></struts>
Bem simples. O arquivo apenas mapeia nosso WelcomeAction. Agora vamos adicionar ao nosso web.xml o filter do Struts 2, que cuidará de processar as requisições:
<?xml version=”1.0″ encoding=”UTF-8″?>
<web-app id=”WebApp_9″ version=”2.4″ xmlns=”http://java.sun.com/xml/ns/j2ee”xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=”http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd”>
<display-name>Exemplo</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.html</welcome-file>
</welcome-file-list></web-app>
Vamos também adicionar um arquivo básico de log, usando o Log4J. Crie o arquvo log4j.properties no diretório src, no mesmo lugar onde está o struts.xml. O arquivo log4j.properties, ficará assim:
# ***** Set root logger level to DEBUG and its only appender to A.
log4j.rootLogger=info, A# ***** A is set to be a ConsoleAppender.
log4j.appender.A=org.apache.log4j.ConsoleAppender# ***** A uses PatternLayout.
log4j.appender.A.layout=org.apache.log4j.PatternLayout
log4j.appender.A.layout.ConversionPattern=%-4r [%t] %-5p %c %x – %m%n
Como as libs do plugin para o Spring jã estão lá, precisamos também colocar o arquivo “applicationContext.xml” no diretório WEB-INF, por hora ele ficará vazio (ainda não temos beans mapeados pelo Spring), assim:
<beans xmlns=”http://www.springframework.org/schema/beans” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” 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-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd”
default-autowire=”byName”></beans>
Agora você deve fazer o deploy da aplicação, e verá a tela do struts, com a data e nossa mensagem de Hello World. Passado este primeiro e básico passo, vamos integrar tudo ao Spring e ao Hibernate. Vamos adicionar este arquivo de properties ao diretório “src”, ele diz ao Struts para permitir que o Spring gerencie nossos objetos. Aqui o arquivo “struts.xml”:
### specifies the autoWiring logic when using the SpringObjectFactory.
### valid values are: name, type, auto, and constructor (name is the default)
struts.objectFactory.spring.autoWire = name### indicates to the struts-spring integration if Class instances should be cached
### this should, until a future Spring release makes it possible, be left as true
### unless you know exactly what you are doing!
### valid values are: true, false (true is the default)
struts.objectFactory.spring.useClassCache = true### ensures the autowire strategy is always respected.
### valid values are: true, false (false is the default)
struts.objectFactory.spring.autoWire.alwaysRespect = false
<bean id=”entityManagerFactory”class=”org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean”><property name=”jpaVendorAdapter”><bean class=”org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter”><property name=”showSql” value=”true” /><property name=”generateDdl” value=”true” /><property name=”databasePlatform” value=”org.hibernate.dialect.MySQLDialect” /></bean></property></bean><bean id=”dataSource” class=”org.apache.commons.dbcp.BasicDataSource”destroy-method=”close”><property name=”driverClassName” value=”com.mysql.jdbc.Driver” /><property name=”url” value=”jdbc:mysql://localhost:3306/example” /><property name=”username” value=”usuario /><property name=”password” value=”senha” /></bean><bean id=”transactionManager” class=”org.springframework.orm.jpa.JpaTransactionManager” /><tx:annotation-driven /><beanclass=”org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor” />
<?xml version=”1.0″ encoding=”UTF-8″?><persistence xmlns=”http://java.sun.com/xml/ns/persistence”xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”xsi:schemaLocation=”http://java.sun.com/xml/ns/persistencehttp://java.sun.com/xml/ns/persistence/persistence_1_0.xsd”version=”1.0″><persistence-unit name=”example” transaction-type=”RESOURCE_LOCAL” /></persistence>
import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.Id;import javax.persistence.Table;@Entity@Tablepublic class Usuario {private Integer id;private String username;private String senha;@Id@GeneratedValuepublic Integer getId() {return id;}public void setId(Integer id) {this.id = id;}@Columnpublic String getUsername() {return username;}public void setUsername(String username) {this.username = username;}@Columnpublic String getSenha() {return senha;}public void setSenha(String senha) {this.senha = senha;}}
@PersistenceContext(name=”example”)private EntityManager em;
Clique aqui para baixar uma aplicação de exemplo. Basta descompactar e fazer o deploy no Tomcat, alterando os dados do seu banco de dados, claro. Os fontes estão na mesma pasta dos arquivos “.class”.
Dúvidas? Poste sua dúvida aqui nos comentários ou envie ela direto para mim aqui.
Olá,
Excelente o seu blog! parabéns!
Estou com alguns problemas aqui, segui todos os passos antes do hibernate.
Porém não funciona, eu acho que é esses filters lá no web.xml
Olha o erro que da:
[code]HTTP Status 404 -
type Status report
message
description The requested resource () is not available.[/code]
Thiago,
Primeiramente gostaria de agradecer o o feedback!
Um erro 404 significa um erro por motivo de mapeamento errado ou aplicação não disponível no Tomcat. Verifique seu web.xml (se quiser, envie o conteúdo dele pra mim), ok?
EXCELENTE ARTIGO, MAS COMO FAZ PRA FAZER ISSO:
“Agora você deve fazer o deploy da aplicação, e verá a tela do struts, com a data e nossa mensagem de Hello World. Passado este primeiro e básico passo, vamos integrar tudo ao Spring e ao Hibernate. Vamos adicionar este arquivo de properties ao diretório “src”, ele diz ao Struts para permitir que o Spring gerencie nossos objetos. Aqui o arquivo “struts.xml”:”
Eu startei meu tomcat mas o projeto nao esta lá, eu exportei o war dele e quando tento fazer deploy no tomcat ele diz:
“HTTP Status 500 -
type Exception report
message
description The server encountered an internal error () that prevented it from fulfilling this request.
exception
javax.servlet.ServletException: Servlet execution threw an exception
root cause
java.lang.NoClassDefFoundError: org/apache/commons/io/output/DeferredFileOutputStream
org.apache.commons.fileupload.DefaultFileItemFactory.createItem(DefaultFileItemFactory.java:103)
org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:350)
org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:302)
org.apache.catalina.manager.HTMLManagerServlet.doPost(HTMLManagerServlet.java:157)
javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
root cause
java.lang.ClassNotFoundException: org.apache.commons.io.output.DeferredFileOutputStream
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1363)
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1209)
java.lang.ClassLoader.loadClassInternal(Unknown Source)
org.apache.commons.fileupload.DefaultFileItemFactory.createItem(DefaultFileItemFactory.java:103)
org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:350)
org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:302)
org.apache.catalina.manager.HTMLManagerServlet.doPost(HTMLManagerServlet.java:157)
javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
note The full stack trace of the root cause is available in the Apache Tomcat/5.5.26 logs.
Apache Tomcat/5.5.26″
ME AJUDA, QUERIA VER ISSO FUNCIONANDO.
GRATO! E PARABENS
cara, resolvi. era o tomcat que nao tinha o jar commons-io.jar. Resolvido. Agora estou com o mesmo problema do Thiago Felipe Festa, segue meu web.xml:
example
index.html
index.htm
index.jsp
default.html
default.htm
default.jsp
Exemplo
struts2
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
struts2
/*
index.html
MEU WEB.XML
Exemplo
struts2
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
struts2
/*
index.html
”
Exemplo
struts2
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
struts2
/*
index.html
“
Enviei para o seu email um exemplo de web.xml, ok?
Qualquer dúvida, só falar.
Qual a diferença da minha Action extender ActionSupport ou Dispatcher ?
Favor enviar resposta para meu e-mail: jittobr@gmail.com
Ilton,
Teoricamente você pode ter um Action sem extender ActionSupport, entretanto a classe ActionSupport possui diversos métodos que serão utilizados para validação, manipulação de erros, internacionalização, etc.
Se você não extende ActionSupport, terá sérios problemas em usufruir destas vantagens já implementadas pelo Struts, e provavlemente terá que re-implementa-las na mão.
[]s!
Também parei no mesmo erro 404.
Não tenho nem idéia no que devo mexer no struts.xml e no web.xml
Pessoal,
Coloquei uma aplicação de exemplo para download ao final do post, ok? É só descompactar e copiar para dentro da pasta “webapps” do Tomcat, e após reinicia-lo acessar no seu browser:
http://localhost:8080/struts2spring
Os fontes estão no mesmo diretório dos “.class”.