Validação de Campos no form // Struts 2 - urgente!

37 respostas
Y

Pessoal, estou usando um desss tutoriais de Spring 2 + Struts2 e estou usando Hibernate tb ! (Não quero usar Ajax).

Seguinte, tenho um jsp (index.jsp), que se campos todos ok => vai para listar.jsp.
Se campos nao ok gostaria que ficasse no index.jsp e mostrasse erros na tela.

O tutorial fala para criar um “NomeAction-salvar-validation.xml”,…
Criei e coloquei as validações do mesmo neste xml. (mais abaixo)

Ao rodar a aplicacao e mandar submeter com campos preenchidos => ok, vai para o outro jsp => SEM PROBLEMA.
Ao rodar a aplicacao e mandar submeter com campos vazios, NÃO aparecem as validacoes na tela (Campo obrigatório) e ainda cai com uma -
javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not insert… etc etc,…

COMO colocar as validações inseridas no validation.xml aparecendo na tela ???

Codigos:

JSP INDEX.JSP
(index.jsp - se ok deve ir para listar.jsp, se nao ok = deve ficar no mesmo jsp mostrando erros. No momento soh funciona se ok)

<%@ taglib prefix="s" uri="/struts-tags"%>
<%@ taglib prefix="sx" uri="/struts-dojo-tags"%>
<html>
	<head>
		<sx:head />
	</head>
	<body>
		<div style="width: 300px;border-style: solid">
			<p>Projeto</p> 
			<s:form action="salvar">
			    <s:textfield id="id" name="projeto.id" cssStyle="display:none" required="true"/>
				<s:textfield id="nome" label="Nome" name="projeto.nome" required="true"/>
				<s:textfield id="data" label="Data" name="projeto.data" required="true"/>
				<s:textfield id="url" label="URL" name="projeto.url" required="true"/>
				<s:textfield id="linguagem" label="Linguagem" name="projeto.linguagem" required="true"/>								
				<s:submit/>
			</s:form>
		</div>
	</body>
</html>

Validation.xml

<validators>
    <field name="projeto.nome">
        <field-validator type="requiredstring">
            <message>Campo Nome é obrigatório</message>
        </field-validator>
    </field>
    <field name="projeto.data">
        <field-validator type="requiredstring">
            <message>Campo Data é obrigatório</message>
        </field-validator>
    </field>
    <field name="projeto.url">
        <field-validator type="requiredstring">
            <message>Campo URL é obrigatório</message>
        </field-validator>
    </field>
</validators>

STRUTS.XML

<?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.objectFactory" value="spring" />
    <constant name="struts.devMode" value="false" />
    <package name="projeto" extends="struts-default">

        <action name="listar" class="projetoAction" method="listar">
            <result>/jsp/listar.jsp</result>
        </action>

        <action name="remover" class="projetoAction" method="remover">
            <result type="redirect">listar.action</result>
        </action>

        <action name="salvar" class="projetoAction" method="salvar">
            <result type="redirect">listar.action</result>            
        </action>

        <action name="alterar" class="projetoAction" method="alterar">
            <result type="redirect">listar.action</result>
        </action>
    </package>
</struts>

37 Respostas

J

Amiga, algumas considerações:

1. Por que não usa mapeamentos com annotations pelo Convention Plugin? São bem mais praticos e aumentam em muito a produtividade.

2. Parece que seu arquivo XML simplesmente está sendo Ignorado. Como os nomes dos campos no form batem com os nomes dos campos no seu XML o motivo aparente é que seu XML de validação não está no mesmo pacote da Action.

3. Onde há validação deve necessariamente haver um mapeamento de input. Ou seja, seu mapeamento de “salvar” deveria estar assim:

<action name="salvar" class="projetoAction" method="salvar"> <result type="redirect">listar</result> <!-- leia o item 5. abaixo --> <result name="input">/paginaDoMeuFormulario.jsp</result> <!-- falta isso --> </action>

4. Por que não usa validação pelas anotações de validação do Struts2 ou do Hibernate Validator pelo uso do Full Hibernate Plugin (http://cwiki.apache.org/S2PLUGINS/full-hibernate-plugin.html)? Este plugin inclusive faz a necessidade do uso do spring desaparecer pois injeta, fecha e “comita” as sessões e transações Hibernate automaticamente pra você usando apenas a arquitetura de Interceptors do próprio Struts2.

5. Onde você usa type=“redirect” não precisa colocar “listar.action”. Basta “listar”.

Y

Obrigada Jose.
Sim, a validation.xml está no mesmo diretório da action.
Coloquei input, tirei o listar. action e continua NÃO FUNCIONANDO.

Simplesmente ignora.
A aplicação continua e cai porque dá erro no banco.
(Eu tento inserir sem conteúdo.) Meu teste de erro eh com os campos em branco e apenas submeto.

Ao inves de entrar na validação, ele ignora e cai ao inserir no banco.

NÃO ENTENDO PQ NAO FUNCIONA !!!
Isso funciona mesmo ???

Vou ter q voltar ao velho actionerror - adicionando mensagenzinha de erro ?!?!

J

Pode me chamar de Yoshi, ok?

Amiga, um detalhe que me chamou atenção foi o nome da sua action: “projetoAction”. É isso mesmo, com “p” minúsculo? Ou você configurou a action via spring com esse nome?

O nome do xml não pode ser só “Validation.xml”. Deve ser

projetoAction-validation.xml
(se sua action possuir só um mapeamento que exigir validação)

ou

projetoAction-salvar-validation.xml
(se sua action possuir mais de um mapeamento que exigir validação)

Que funciona, funciona, porque já usei muito esse tipo de validação antes de começar a usar validações por anotações :wink:

Porém nunca usei a validação com XML tendo mapeado as actions via Spring (até porque acho perda de tempo usar Spring no Struts2). Se for o caso, tente usar o nome da classe para o nome do XML de validação. Nesse caso os nomes seriam:

ProjetoAction-validation.xml

ou

ProjetoAction-salvar-validation.xml

Um forte abraço.

Y

oi Yoshi,

O nome são:
ProjetoAction.java (a action)
ProjetoAction-salvar-validation.xml e
ProjetoAction-alterar-validation.xml

(Aqui na empresa tem q ser tudo em portugues)

Outra coisa, nao consegui baixar nada no http://code.google.com/p/full-hibernate-plugin-for-struts2/downloads/list
Porque aqui, só downloads pequenos.

A coisa tah feia pro meu lado… hehehe

Y

Ah, por que “perda de tempo usar Spring no Struts2” ???

Eu tentei seguir esse tutorial:
http://struts.apache.org/2.x/docs/struts-2-spring-2-jpa-ajax.html

Achei que era boa dica da Apache…, mas esse validation.xml… Não funciona nem…

J

Amiga,

esse tutorial data de 2006 com ultima atualizacao em fev/2008. Na epoca nao havia o Full Hibernate Plugin (que evita o uso do spring e da validacao nativa do struts2) nem o Jquery Plugin (que evita o uso do ajax nativo do struts2).

Existe a linha

<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">

no inicio de seus XMLs de validacao?

quanto ao Full Hibernate Plugin, nem a biblioteca voce consegue baixar?
http://full-hibernate-plugin-for-struts2.googlecode.com/files/struts2-fullhibernatecore-plugin-2.1.2-GA.jar
Ela possui menos de 53KB. Nao precisa baixar o javadoc nem os fontes.

Veja alguns exemplos de uso dele aqui:
http://www.vaannila.com/struts-2/struts-2-tutorial/struts-2-tutorial.html

Esta usando uma versao meio antiga dele, mas ainda serve.

J

Ah… lembrei de uma coisa!

O “requiredstring” acaba nao valendo quando o o campo esta no formulario. Este validador testa se a String existe. Todavia, a string sempre existira, nem que seja uma string vazia. Deves, portanto, configurar um tamanho minimo para a string para que o validador tenha efeito.

Veja mais em
http://struts.apache.org/2.x/docs/requiredstring-validator.html
http://struts.apache.org/2.x/docs/stringlength-validator.html
http://struts.apache.org/2.x/docs/required-validator.html

PS: desculpe estar escrevendo sem caracteres especiais, mas to com um teclado aqui que eh preferivel trabalhar em ingles rrsrsrs.

Y

Não precisa se desculpar !
Está bom demais.
Vou tentar seguir sua dica.

O que estou tentando é subir um simples CRUD usando o que acho de melhor em arquitetura. Struts, Hibernate, etc…

Muito obrigada.

Y

Yoshi, eu consigo validar o lado client com Hibernate Plugin ?
Pensei que o validator do Hibernate era apenas para a parte server ?

Você tem algum exemplo de configuração disso ?

Para constar => (Acho que meu problema estava mesmo ligado ao requiredstring mesmo)

Importante deixar aqui, pois como ninguem mais me respondeu, pode ser dúvida de outros.

Bom, acho que vou para essa linha: Struts2 + Hibernate (validação e injeção).
Se tiver exemplo (CRUD mesmo), tutorial, poste, ok ?

Vai ajudar muito !!!
Obrigada.

J

Amiga,

Para ver como usar o Full Hibernate Plugin pode baixar os exemplos no site do projeto ou ver exemplos on-line em
http://www.vaannila.com/struts-2/struts-2-tutorial/struts-2-tutorial.html

Vale a pena investir nesse plugin, pois o trabalho fica significativamente menor porque ele abstrai o uso das sessoes e transacoes hibernate e facilita imensamente o trabalho de validacao.

Com esse plugin a validacao e sempre do lado do servidor, mas e muito rapida. Lembre-se que validacao do lado do servidor e muito mais segura.

Outras coisas no seu JSP:

  • Sugiro usar o Jquery Plugin ao inves do Dojo Plugin. E bem mais rapido e estavel e com mais recursos.
  • Faltou voce usar a tag <s:head/> dentro de .
Y

Obrigada, estou fuçando essa página, mas creio que o Full Hibn Plugin só encontro em:

Struts 2 Hibernate Integration Tutorial e
Struts 2 Hibernate Validation Tutorial

O resto não interessa, certo ?

[]´s

J

isso mesmo. so esses 2.

Y

Minha maior preocupação eh se esse Plugin faz as validações necessárias do form na parte client ?
Porque o que me lembro do Hibn é que a validação do mesmo era na parte server…

procede ?

Sendo assim a validação do Struts (que não adianta, não consigo usar), não seria melhor ?

J

A única, repito, única vantagem de validações do lado do cliente é a redução no tráfego da rede.
Nem mesmo a performance é necessariamente melhor do lado do cliente.

Validações do lado do servidor são infinitamente mais seguras porém forçam a “ida e vinda” de informações pela rede.

Y

Ok, obrigada e desculpa a chateação aí !
É que aqui na equipe de desenv, creio que não passe… a não ser que eu use algo no JS.
Aqui dizem q cada camada deve cuidar de suas validações.
Ou seja, se tenho um form, não posso submete-lo com erros, mesmo que seja uma definição de negócio.
Enfim,
Obrigada !

J

Que pensamento, hein?

Quer dizer que se tiverem uma mesma camada modelo usada por um cliente swing, outro JSP e outro mobile terao que REPETIR regras de validacao em todos os 3? E mais, se uma mesma entidade consta em 5 forms, teremos que REPETIR as regras de validacao 5x?

E por isso que o lema do Hibernaete Validotor e: “DRY - Dont Repeat Yourself” (nao repita voce mesmo)

Mas, se a regra ai e essa, boa sorte.

PS: mesmo a validacao nativa do struts2 faz validacao no servidor em alguns casos, como validacao envolvendo datas, por exemplo.

Y

Não me referi a isso, mas a algo que estou tentando resolver.
Um simples CRUD !!! (ninguém merece, rs).

Mas se o form necessita de validações, que isso seja resolvido por aí e não depois de cálculos, de considerar o negócio em si, etc…

Entendo sua posição, deve estar correta, mas acho tb esse pensamento algo a se considerar…

De qq maneira, to lascada, rs.

Não consigo MESMO colocar esse ‘bendito’ validation.xml pra aparecer no form !
Aparece somente no console do Tomcat:
SEVERE: Validation error for projeto.nome:Campo Nome é obrigatório.

Nada de aparecer no form.
:frowning:

J

mostra como ficou todo teu XML de mapeamento agora.

J

Ah, e quanto a

O Hibernate validator eh acionado do lado do servidor, mas antes das “regras de negocio”. No caso do trabalho em conjunto com o struts2, sua validacao ocorre antes da chamada do metodo mapeado. Se nenhum erro de validacao for detectado, ai sim, seu metodo mapeado sera invocado (suas regras de negocio).

Y

INDEX.JSP

<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
	<s:head/>   
	<body>
		<div style="width: 300px;border-style: solid">
			<p>Projeto</p> 
			<s:form action="salvar">
			    <s:textfield id="id" name="projeto.id" cssStyle="display:none" required="true"/>
				<s:textfield id="nome" label="Nome" name="projeto.nome" required="true"/>
				<s:textfield id="data" label="Data" name="projeto.data" required="true"/>
				<s:textfield id="url" label="URL" name="projeto.url" required="true"/>
				<s:textfield id="linguagem" label="Linguagem" name="projeto.linguagem" required="true"/>								
				<s:submit/>
			</s:form>
		</div>
	</body>
</html>

STRUTS.XML

<?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.objectFactory" value="spring" />
    <constant name="struts.devMode" value="false" />
    <package name="projeto" extends="struts-default">
        <action name="listar" class="projetoAction" method="listar">
            <result>/jsp/listar.jsp</result>
        </action>

        <action name="remover" class="projetoAction" method="remover">
            <result type="redirect">listar.action</result>
        </action>

        <action name="salvar" class="projetoAction" method="salvar">
            <result type="redirect">listar</result>
            <result name="input">/jsp/index.jsp</result>                  
        </action>

        <action name="alterar" class="projetoAction" method="alterar">
            <result type="redirect">listar.action</result>
        </action>
    </package>
</struts>

ProjetoAction-salvar-validation.xml

<!DOCTYPE validators PUBLIC
"-//OpenSymphony Group//XWork Validator 1.0//EN"
"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
    <field name="projeto.nome">
        <field-validator type="required">
            <message>Campo Nome é obrigatório</message>
        </field-validator>
    </field>
    <field name="projeto.data">
        <field-validator type="required">
            <message>Campo Data é obrigatório</message>
        </field-validator>
    </field>
    <field name="projeto.url">
        <field-validator type="required">
            <message>Campo URL é obrigatório</message>
        </field-validator>
    </field>
</validators>
Y

applicationContext.xml

<?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: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">

    <bean
        class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

    <bean id="projetoService" class="ProjetoServiceImpl" />

    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource" />
        
        
        <property name="jpaVendorAdapter">
            <bean
                class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="database" value="MYSQL" />
                <property name="showSql" value="true" />
            </bean>
        </property>
    </bean>

    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost/prototipo" />
        <property name="username" value="a" />
        <property name="password" value="b" />
    </bean>

    <bean id="transactionManager"
        class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager" />

    <bean id="projetoAction" scope="prototype"
        class="ProjetoAction">
        <constructor-arg ref="projetoService" />
    </bean>
</beans>
J

Ainda ocorre o mesmo erro de antes?

Sequer volta para a tela de formulario?

Ah, e seu JSP esta com um errinho bobo.

Deveria estar
<html>  
     <head>
         <s:head/>     
     </head>
     <body>  
....
Y

Não, não volta !
Desisto.
Q inferno conseguir um Crudzinho em java…
Esses tutoriais nao func mesmo !

Vou tentar a ‘sorte’ amanhã.

até

(obrigada)

J

Ainda acho que o spring ta atrapalhando o meio de campo.

Tente mudar o mapeamento de “salvar” para ignorar o spring so para testar a validacao:

<action name="salvar" class="ProjetoAction" method="salvar"> <!-- ProjetoAction e nao projetoAction --> <result type="redirect">listar</result> <result name="input">/jsp/index.jsp</result> </action>

Veja o que acontece.

Outras dicas:

  • evite classe no pacote raiz
  • veja se sua action estende ActionSupport
Y

Oi Yoshi,
-Não ha classe no pacote raiz e a Action implementa Preparable (Xwork).
-O ‘projetoAction’ (‘p’ minúsculo, vem da definição da applicationContext.xml)
Tentei seguir o tutorial:

http://struts.apache.org/2.0.14/docs/struts-2-spring-2-jpa-ajax.html

Achei que era algo certo…

:S

J

Amiga,

como te disse, esse tutorial é antigo e feito usando-se a família 2.0.x do Struts2.

Como disse, tente fazer o mapeamento ignorando o spring só para ver se a validação funciona, ok?

Y

Não, não funciona.
Cai na mesma coisa, ele tenta inserir no banco e cai.
Desisto desse crud.
Obrigada !

J

Amiga, não desista assim.

Deve ser algum detalhe simples. Ja participei da criação de 3 aplicações bem grandes usando struts2 + hibernate que são bem mais que CRUDs.

Sua classe action estende Actionsupport ou apenas implementa Preparable? Deve estender o ActionSupport.

Verifique também se seu projeto tem todas as bibliotecas necessárias.

Y

Pois é, Yoshi,
Um simples CRUD nao valida. Eu só não posso ficar dias numa coisa que não funciona, rs.
Já estou apelando para outtros aqui do trabalho, que não encontram o problema.

  1. Ele implementa Preparable (Como no tutorial)
  2. Ele insere no banco, mostra os inseridos, ele sõ não valida os campos do form.
  3. As libs estão ok !

obrigada.

Y

Sim, sim, não vou entrar nessa questão,…
Mas mesmo assim poderia haver um CRUD na internet (velho ou não),
com validações do Struts2 funcionando, certo ?

Porque até outros colegas, que repassei a aplicação simples já desistiram.

Aqui no trabalho fica sempre a eterna briga do que é mais simples java .net…
Sinceramente, se eu nem consigo subir um CRUD java, tá difícil justificar.

Era essa minha missão…

Abordata

J

Amiga, não posso dizer se o erro é no tutorial ou em sua implementação sem ver todo seu projeto. O fato é que o struts2 é usado por milhares ou até milhões de usuários e se um CRUD com validação não funcionasse ele não teria cerca de 3mil downloads por mês (http://people.apache.org/~vgritsenko/stats/projects/struts#Monthly).

Quanto ao java x .Net todo desenvolvedor java honesto sabe que o .Net é mais produtivo, com certeza. A questão é o custo das licenças do visual studio/ windows server e a perfomence e escalabilidade de aplicações .Net.

Agora, se for pra comparar só produtividade, Grails e Rails são muito mais produtivos que .Net e com alta performance e escalabilidade.

G

Oi! Estou tentando desabilitar a validação do struts2,estou usando aversão 2.1.8.
Tenho meu form JSP que envia a requisição para o Servlet, e quando volta do servlet ele retorna msn de erro: Invalid field value for field.
Eu gostaria que neste meu metodo esta validação não fosse feita, pois estou somente limpando os get do form.
Não uso validador.xml do struts, faço minhas validações no form

public  class XXX extends ActionSupport implements Preparable

Help!

J

Amigo, para evitar validação, há duas opções:

  1. usar a anotação @SkipValidation sobre o método mapeado

  2. mapear essa ação passando por uma pilha de interceptors que não use o “defaultStack”

Mas, em todo caso, essa mensagem que aparece pra você sempre ocorrerá em caso de campo inválido (exemplo: preenchimento de número em data).

G

Correto foi este erro que achei de double para String.

Devido ao fato de eu estar utilizando virgula no meu preço quando é editado pelo usuario.
Quando minha action vai pegar o valor gera erro.

Html envia 15,00 devido a mascara.
Meus metodos e assim

public double getPreco(){

return this.preco;

}

public void setPreco(double preco) {

this.preco = preco;

}

Estou pesando em pegar e alterar meu get para tipo String e criar uma função que o transforme em double.
Pois quando utilizo HttpServlet, tenho todo o trabalho de tratar para double:

double dVlr = 0;

try {

dVlr = formatador.parse(request.getParameter(vlr)).doubleValue();

request.setAttribute(vlr”,String.valueOf(dVlr));

} catch (Exception e) {

request.setAttribute(vlr”,“0);

sMsg = Valor do Pago deve ser válido !;

}

Acho isto muito tosco!

Value!!!

G

O que eu acabei fazendo foi:
Peguei meu metado

alterei para isto:

public void setValorLancamento(String valorLancamento) throws Exception {	    	

this.valorLancamento = stringToDouble(valorLancamento);

}

Crei a função:

public double stringToDouble(String sVlr) throws Exception {

//import java.text.*;

DecimalFormat formatador  = new DecimalFormat();

formatador.applyPattern("######0,00;- #####0,00");

double dVlr = 0;

try {

dVlr = formatador.parse(sVlr).doubleValue();

}catch(Exception e){

throw new Exception (Valor digitado invalido! );	

}

return dVlr;

}

Bom agora esta funcionado direito, mas deve existir um modo mais inteligente de se fazer isto,ou não?
Obs.:
Estou usando a seguinte arquitetura:
JSP+Struts2+Hibernate+MySQL.

O meu JSP é assim, que mostra o valor:

Valeu!

J

Amigo, esse problema é devido entre as diferenças entre nossos sistema de formatação de números e o sistema americano.

Aqui, ponto é separados de milhar e vírgula de decimais. Nos EUA (e acho que na maioria dos lugares) é o contrário.

Neste link
http://struts.apache.org/2.1.8.1/docs/formatting-dates-and-numbers.html

É exclicada uma maneira “formal” de corrigir isso.

Mas há outras dicas legais aqui:
http://www.roseindia.net/struts/struts2/struts-2-format.shtml

G

Obrigadão.

Criado 30 de dezembro de 2009
Ultima resposta 8 de fev. de 2010
Respostas 37
Participantes 3