Spring + JSF + Facelets Validator = DAO não instanciado

Boa tarde, pessoal.
tudo bem?

Então, tentei de todas as formas fazer a validação de um formulário de uma página jsf e não obtive sucesso.

O problema é o seguinte:

Um objeto DAO que tenho na classe que implementa a Validator não é instanciada pelo Spring.

Essa classe chega a ser executada, mas quando chama o método dao.getByLogin(login); me retorna uma exceção de Nullpointer… dizendo que o dao não foi instanciado.

estou a 3 dias tentando resolver e não está facil hehe

O objetivo desta classe é garantir que não possa ser cadastrado dois usuários com o mesmo login.

Alguém tem alguma idéia de como resolver isto?

ps.: posto o código assim que sair do trabalho. :slight_smile:

Desde já agradeço o apoio de todos.

Alguém me ajuda :smiley:

Amigo acabei de descobrir o mesmo roblema,

Você conseguiu resolver?

Aqui eu tive que bolar uma “marreta”, estou com pressa e não tenho tempo de pesquisar muito:
Olha o que eu fiz:
Criei um construtor para o Validador:

   public ValidadorRazaoSocial() {
        context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        empresaDAOInterface = (DaoGenerico<Empresa, Long>)context.getBean("empresaDAOInterface");
    }

E chamei o velho e bom ApplicationContext lá dentro, dai foi somente chamar meu DAO, deu certo.

Por favor, se você tiver achado uma forma mais “limpa” de resolver, posta ai…

Valeu

Bem, eu resolvi isso tornando o meu campo ‘username’ único e tratando a exceção :lol:

O bean DAO de vocês está sendo injetado corretamente pelo Spring? Postem seus applications e faces xml’s para darmos uma olhada na situação.

Seguem os arquivos: ApplicationContext, Faces-config e o meu validator
Obrigado.
Abraços

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:context="http://www.springframework.org/schema/context"
       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.5.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
    

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="CotamusPU" />
    </bean>

<context:component-scan base-package="com.cotamus" />

  <context:annotation-config/>

    <!--bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />-->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>
   
    <tx:annotation-driven/>

    <!-- declarar os beans aquiii! -->
    <bean id="postoDao" class="com.cotamus.dao.impl.PostoDaoImpl" />
    <bean id="bandeiraDao" class="com.cotamus.dao.impl.BandeiraDaoImpl" />
    <bean id="usuarioDao" class="com.cotamus.dao.impl.UsuarioDaoImpl" />
    <bean id="cotacaoCombustivelDao" class="com.cotamus.dao.impl.CotacaoCombustivelDaoImpl" />
    <bean id="comentariosPostosDao" class="com.cotamus.dao.impl.ComentariosPostosDaoImpl" />
    <bean id="combustivelDao" class="com.cotamus.dao.impl.CombustivelDaoImpl" />
</beans>

Faces-config.xml


<?xml version='1.0' encoding='UTF-8'?>

<!-- =========== FULL CONFIGURATION FILE ================================== -->

<faces-config version="1.2" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">

 <application>
        <view-handler>
            com.sun.facelets.FaceletViewHandler
        </view-handler>
        <el-resolver>
            org.springframework.web.jsf.el.SpringBeanFacesELResolver
        </el-resolver>
    </application>
    <!--<managed-bean>
        <managed-bean-name>PostoMB</managed-bean-name>
        <managed-bean-class>com.cotamus.controller.PostoMB</managed-bean-class>

        <managed-bean-scope>session</managed-bean-scope></managed-bean>-->
    <navigation-rule>
        <from-view-id>/cadastro_usuario.xhtml</from-view-id>
        <navigation-case>
            <from-outcome>salvou</from-outcome>
            <to-view-id>/obrigado.xhtml</to-view-id>
        </navigation-case>
    </navigation-rule>
    <navigation-rule>
        <from-view-id>/alteracao_usuario.xhtml</from-view-id>
        <navigation-case>
            <from-outcome>alterou</from-outcome>
            <to-view-id>/confirmacao.xhtml</to-view-id>
        </navigation-case>
    </navigation-rule>
    <validator>
        
        <validator-id>validaValorCotacao</validator-id>
        <validator-class>com.cotamus.rn.ValidaValorCotacao</validator-class>
    </validator>
    <validator>
        <validator-id>validaNome</validator-id>
        <validator-class>com.cotamus.rn.ValidaNomeUsuario</validator-class>
        </validator>
</faces-config>

Classe que implementa o validator

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.cotamus.rn;


import com.cotamus.dao.UsuarioDao;
import com.cotamus.dao.impl.DaoGenericoImpl;
import com.cotamus.entities.Usuario;
import javax.annotation.Resource;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;

/**
 *
 * @author juliano
 */
public class ValidaNomeUsuario implements Validator {
    @Resource
    private UsuarioDao usuarioDao;

    public UsuarioDao getUsuarioDao() {
        return usuarioDao;
    }

    public void setUsuarioDao(UsuarioDao usuarioDao) {
        this.usuarioDao = usuarioDao;
    }
    public void validate(FacesContext context, UIComponent toValidate, Object value) throws ValidatorException {
        Usuario login = new Usuario();

        login.setLogin((String) value);
       //para verificar se o dao esta vindo nulo...
        if(usuarioDao!=null){
            System.out.println("ele nao eh nulo!");

        }else{
            System.out.println("ele EH nulo!");
        }


	if (usuarioDao.getUsuarioByNomeUsuario(login)!=null) {
		((UIInput)toValidate).setValid(false);

		FacesMessage message = new FacesMessage("Por favor escolha outro login, pois este já existe.");
		context.addMessage(toValidate.getClientId(context), message);
	}
    }

}

[quote=gbvbahia01]Amigo acabei de descobrir o mesmo roblema,

Você conseguiu resolver?

Aqui eu tive que bolar uma “marreta”, estou com pressa e não tenho tempo de pesquisar muito:
Olha o que eu fiz:
Criei um construtor para o Validador:

   public ValidadorRazaoSocial() {
        context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        empresaDAOInterface = (DaoGenerico<Empresa, Long>)context.getBean("empresaDAOInterface");
    }

E chamei o velho e bom ApplicationContext lá dentro, dai foi somente chamar meu DAO, deu certo.

Por favor, se você tiver achado uma forma mais “limpa” de resolver, posta ai…

Valeu[/quote]
Caso eu não encontre outra solução acho que vou utilizar esta mesmo, amigo. Tenho 1 semana para terminar meu tcc não tá fácil! heuheu
Obrigado pela ajuda.
Abraços

Declara seu validator lá no applicationContext também, o SpringbeanFacesELResolver chama do contexto do spring a injeção. Se não tiver o validator lá, ele não receberá as injeções. Dá uma testada aí e me diz se funcionou.

[quote=gbvbahia01]Amigo acabei de descobrir o mesmo roblema,

Você conseguiu resolver?

Aqui eu tive que bolar uma “marreta”, estou com pressa e não tenho tempo de pesquisar muito:
Olha o que eu fiz:
Criei um construtor para o Validador:

   public ValidadorRazaoSocial() {
        context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        empresaDAOInterface = (DaoGenerico<Empresa, Long>)context.getBean("empresaDAOInterface");
    }

E chamei o velho e bom ApplicationContext lá dentro, dai foi somente chamar meu DAO, deu certo.

Por favor, se você tiver achado uma forma mais “limpa” de resolver, posta ai…

Valeu[/quote]
[/quote]

Bom, deu certo em partes, tipo: o dao foi criado com sucesso, mas quando coloquei a aplicação no ar e comecei a testar, da problema… O Spring meio que não está conseguindo gerenciar o entitymanager e ele acaba fechando e/ou a aplicação da problema de falta de memória… Deste jeito, que eu falei, deu mo bode aqui :frowning:

Com o EJB dá o mesmo problema, mas dá para resolver, com Spring não consegui achar solução, olha que já fui em vários posts…

Declararia como um bean normal?
Tipo assim:

<bean id="validaNome" class="com.cotamus.rn.ValidaNomeUsuario /> 

?

Obrigadoooo!!

Sim sim, dessa forma mesmo xxta.

Como procedeu aí?

[]'s

Não deu certo… :frowning:

depois tentei retirar o trecho abaixo do faces-config.xml mas também não adiantou:

    <validator>
        <validator-id>validaNome</validator-id>
        <validator-class>com.cotamus.rn.ValidaNomeUsuario</validator-class>
        </validator>

to achando que essa nao é a forma certa de utilizar o spring em um validator, acho que existe uma classe validator do spring…
vou dar uma procurada e caso apareçam mais dúvidas ou encontre a solução posto aqui!

Obrigado a todos!
abraços

po cara… acho q vc nao ta certo

hehehehe

[quote=hopster]po cara… acho q vc nao ta certo

hehehehe[/quote]

e como é o certo?

:shock:

[quote=xxta]Não deu certo… :frowning:

depois tentei retirar o trecho abaixo do faces-config.xml mas também não adiantou:

    <validator>
        <validator-id>validaNome</validator-id>
        <validator-class>com.cotamus.rn.ValidaNomeUsuario</validator-class>
        </validator>

to achando que essa nao é a forma certa de utilizar o spring em um validator, acho que existe uma classe validator do spring…
vou dar uma procurada e caso apareçam mais dúvidas ou encontre a solução posto aqui!

Obrigado a todos!
abraços[/quote]

Não tem como fazer IOC nos validadores e conversores do JSF(1.2), não dá!
Pesquisei muito e até na documentação existe essa informação, por isso temos que esquecer esta forma… mas tem uma segunda opção:
O que pode ser feito neste caso é utilizar um validator dentro do bean, na tag JSF em vez de utilizar o

<f:validator validatorid="idvalidador"/>

utilize a chamada

<h:inputTextarea validator="#{Beanname.metodovalidador}" value="#{Beanname.value}"/>

O método utilizado no bean deve ser idêntico ao método que é utilizado na classe validador.
Sem retorno, recebendo os mesmos parâmetros e se houver erros lançar a ValidatorException da mesma forma.
O acredito que o mesmo pode ser feito com converter, já que um converter também pode ser indicado na tag da mesma forma que o validator.
OBS:

  1. Não há necessidade de implementar a interface validador no bean.
  2. Não há necessidade de por o bean como validator no faces-config.xml, somente a declaração normal do bean.

[quote=gbvbahia01][quote=xxta]Não deu certo… :frowning:

depois tentei retirar o trecho abaixo do faces-config.xml mas também não adiantou:

    <validator>
        <validator-id>validaNome</validator-id>
        <validator-class>com.cotamus.rn.ValidaNomeUsuario</validator-class>
        </validator>

to achando que essa nao é a forma certa de utilizar o spring em um validator, acho que existe uma classe validator do spring…
vou dar uma procurada e caso apareçam mais dúvidas ou encontre a solução posto aqui!

Obrigado a todos!
abraços[/quote]

Não tem como fazer IOC nos validadores e conversores do JSF(1.2), não dá!
Pesquisei muito e até na documentação existe essa informação, por isso temos que esquecer esta forma… mas tem uma segunda opção:
O que pode ser feito neste caso é utilizar um validator dentro do bean, na tag JSF em vez de utilizar o

<f:validator validatorid="idvalidador"/>

utilize a chamada

<h:inputTextarea validator="#{Beanname.metodovalidador}" value="#{Beanname.value}"/>

O método utilizado no bean deve ser idêntico ao método que é utilizado na classe validador.
Sem retorno, recebendo os mesmos parâmetros e se houver erros lançar a ValidatorException da mesma forma.
O acredito que o mesmo pode ser feito com converter, já que um converter também pode ser indicado na tag da mesma forma que o validator.
OBS:

  1. Não há necessidade de implementar a interface validador no bean.
  2. Não há necessidade de por o bean como validator no faces-config.xml, somente a declaração normal do bean.
    [/quote]

Obrigado, gbvbahia01.
Vou testar qdo chegar em casa!!
No momento estou utilizando da forma acima, usando o validator normal e verificando no método validate se o dao for nulo busco a informação no XML, pois se deixasse no construtor estourava a memória pq ele era instanciado toda vez que era solicitada uma validação:

context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); empresaDAOInterface = (DaoGenerico<Empresa, Long>)context.getBean("empresaDAOInterface");

Apresento amanhã o TCC e como está funcionando não sei se vou alterar no projeto em si, mas vou testar.
Após a apresentação faço as devidas correções e posto o resultado :slight_smile:

Muito obrigado!
abraços