[Spring+Jpa] dependency Injection funcionando no teste JUnit mas não funcionando no container web

Olás!

Bom estou com uma dificuldade ao utilizar o spring para fazer dependency injection em uma aplicação web JSF.

meu applicationContext.xml:

   <bean id="xiFluxosDao" class="br.com.ogaiht.nxmi.dao.JpaXiFluxosDao">
      <property name="entityManagerFactory" ref="entityManagerFactory"/>
   </bean>
                                  
   <bean id="xiFluxosMgr" class="br.com.ogaiht.nxmi.business.XiFluxosMgrImpl">
      <property name="xiFluxosDao" ref="xiFluxosDao"/>
   </bean>
   
   <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
      <property name="dataSource" ref="dataSource"/>
      <property name="jpaVendorAdapter">
         <bean class="org.springframework.orm.jpa.vendor.TopLinkJpaVendorAdapter">
            <property name="showSql" value="true"/>
            <property name="generateDdl" value="false"/>
            <property name="databasePlatform" value="oracle.toplink.essentials.platform.database.MySQL4Platform"/>
         </bean>
      </property>
      <property name="loadTimeWeaver">
         <bean class="org.springframework.instrument.classloading.SimpleLoadTimeWeaver"/>
      </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:3306/x"/>
      <property name="username" value="user"/>
      <property name="password" value="senha"/>
   </bean>

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

Desta maneira o código abaixo, de teste funciona corretamente, quando busco o applicationContext utilizando o método getConfigLocations():

public class XiFluxosMgrImplTest extends AbstractJpaTests {
	
	XiFluxosMgr xiFluxosMgr;
	
	public void setXiFluxosMgr(XiFluxosMgr xiFluxosMgr) {
		this.xiFluxosMgr = xiFluxosMgr;
	}
	
	@Override
        protected String[] getConfigLocations() {
		return new String[] {"classpath:web/WEB-INF/applicationContext.xml"};
	}

        @Override
	protected void onSetUpInTransaction() throws Exception {
	}

	public void testFindByCodIdentFluxoExists() {
		XiFluxos fluxo = xiFluxosMgr.searchFluxoByPk("F01");
		assertNotNull(fluxo);
	}

        ...

Porém a dependency injection nao funciona quando rodo na web, o managed bean abaixo, deveria ter a propriedade xiFluxosMgr já com os templates jpa … mas esta vindo null.

public class CadastroControl {
    
    private XiFluxosMgr xiFluxosMgr;
         
    public void CadastroControl(){
    }

    public void setXiFluxosMgr(XiFluxosMgr xiFluxosMgr) {
        this.xiFluxosMgr = xiFluxosMgr;
    }

    public String searchFluxoByCodIdentFluxo(){
        try{
            XiFluxos fluxo = xiFluxosMgr.searchFluxoByPk("F01");
            ...
            ...
            

Finalmente segue meu web.xml:

<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
   
    <context-param>
        <param-name>com.sun.faces.verifyObjects</param-name>
        <param-value>false</param-value>
    </context-param>
    <context-param>
        <param-name>com.sun.faces.validateXml</param-name>
        <param-value>true</param-value>
    </context-param>
    <context-param>
        <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
        <param-value>client</param-value>
    </context-param>
     <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>
    
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    
    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>
    
    <filter>
        <filter-name>MyFacesExtensionsFilter</filter-name>
        <filter-class>org.apache.myfaces.webapp.filter.ExtensionsFilter</filter-class>
        <init-param>
            <param-name>maxFileSize</param-name>
            <param-value>20m</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>MyFacesExtensionsFilter</filter-name>
        <servlet-name>Faces Servlet</servlet-name>
    </filter-mapping>
    <filter-mapping>
        <filter-name>MyFacesExtensionsFilter</filter-name>
        <url-pattern>/faces/myFacesExtensionResource/*</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>MyFacesExtensionsFilter</filter-name>
        <url-pattern>*.jsf</url-pattern>
    </filter-mapping>
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.jsf</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>/faces/*</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>faces/welcomeJSF.jsp</welcome-file>
    </welcome-file-list>
</web-app>

Enfim, este é meu problema, ja tentei de varias maneiras arrrumar mas não consegui. Nem sei como pesquisar isso no google. :slight_smile:

Se alguem ja sabe o motivo do problema gostaria de saber. :slight_smile:

Fico no aguardo,

Att. Thiago

Oi Thiago,

Eu nunca usei o Spring para fazer injeção de dependências em Managed Beans do JSF, mas me parece que me falta alguma coisa na sua configuração.

Eu não sei se o pessoal do Spring já fez algum InjectionProvider para os ManagedBeans, mas eu acho que a chance de eles já terem feito é grande. Se eles não tiverem feito, não é difícil de você fazer o seu próprio. Você vai precisar de um InjectionProvider que carrega as configurações do applicationContext.xml, como você fez no seu teste.

Alguns links que possam te ajudar:
http://blogs.sun.com/rlubke/entry/jsf_ri_1_2_and
http://weblogs.java.net/blog/jhook/archive/2007/05/jsf_12_ri_backi.html
http://java.sun.com/developer/technicalArticles/J2EE/injection/

Estes InjectionProviders são específicos do Mojarra (sun-ri). Com certeza o MyFaces tem alguma coisa análoga. Pela especificação do JSF pura você só consegue fazer com @Resource.

Além disso, o Urubatan já fez isso que você está fazendo no projeto spring-annotations. Vale a pena dar uma olhada.

vc colocou o DelegateVariableResolved no faces-config.xml ???

se o prob esta na injeção no MB, então pode ser isso

[s]

[quote=Fabio Kung]Oi Thiago,

Eu nunca usei o Spring para fazer injeção de dependências em Managed Beans do JSF, mas me parece que me falta alguma coisa na sua configuração.

Eu não sei se o pessoal do Spring já fez algum InjectionProvider para os ManagedBeans, mas eu acho que a chance de eles já terem feito é grande. Se eles não tiverem feito, não é difícil de você fazer o seu próprio. Você vai precisar de um InjectionProvider que carrega as configurações do applicationContext.xml, como você fez no seu teste.

Alguns links que possam te ajudar:
http://blogs.sun.com/rlubke/entry/jsf_ri_1_2_and
http://weblogs.java.net/blog/jhook/archive/2007/05/jsf_12_ri_backi.html
http://java.sun.com/developer/technicalArticles/J2EE/injection/

Estes InjectionProviders são específicos do Mojarra (sun-ri). Com certeza o MyFaces tem alguma coisa análoga. Pela especificação do JSF pura você só consegue fazer com @Resource.

Além disso, o Urubatan já fez isso que você está fazendo no projeto spring-annotations. Vale a pena dar uma olhada.[/quote]

Fábio, uma vez tentei fazer DI na unha, mas sem sucesso, para trabalhar com Hibernate. Por um acaso você não teria umas referências boas para passar?

Valeu

Muito bom é isso mesmo! Dei uma olhada lá no pdf do guia de referência do Spring e realmente fala disso no capítulo 14.

Aí funcionou a parte da DI sem problema.

Porém agora parece que no contexto WEB as minhas anotattions na classe de entidade não estão servindo para nada, daí na hora de utilizar o getJpaTemplate.().find … da um erro de casting na classe.

O método na classe dao que extende JpaDaoSupport aonde ocorre o problema:

public XiFluxos findByPk(String codIdentFluxo) {
	    XiFluxos fluxo = new XiFluxos();
            fluxo = (XiFluxos) getJpaTemplate().find(
				"select f from XiFluxos f where f.codIdentFluxo = ?1",
				codIdentFluxo).get(0);
            return fluxo;
	}

O erro que ocorre é: br.com.ogaiht.nxmi.entity.XiFluxos cannot be cast to br.com.ogaiht.nxmi.entity.XiFluxos

Lembrando que este não ocorre se eu executar pelo Junit…

Preciso colocar mais alguma coisa no applicationContext pra isso? ou no web.xml?

Obrigado,

E ai pessoal, alguem sabe o motivo desse problema acima?
Falta alguma configuração no applicationContext.xml?

Att,
Thiago

E ai pessoal, algume sabe o motivo desse problema acima?
Esta faltando alguma configuração no applicationContext? ou no spring-config?

att,
Thiago

E ai pessoal, algume sabe o motivo desse problema acima?
Esta faltando alguma configuração no applicationContext? ou no spring-config?

att,
Thiago

Tente fazer destas formas:

EntityManager em =  getJpaTemplate().getEntityManager();
Query qr = em.createQuery("from XiFluxos f where f.codIdentFluxo = :cod ");
qr.setParameter(1, codIdentFluxo);
qr.setMaxResults(1);
XiFluxos fluxo = (XiFluxos) qr.getSingleResult();

ou
Se este codigo for id da Entity

XiFluxos fluxo = (XiFluxos) getJpaTemplate().find(XiFluxos.class, Integer.parseInt(codIdentFluxo) );

PS: Não testei mais acho que deve dar certo!!

Eu heim! A mensagem acima saiu 3x!

Mas continuando, vou tentar esta abordagem. Mas a idéia era utilizar o Spring pra fazer DI e trazer o entityManager automágicamente! :slight_smile:

Obrigado,

Não entendi!

O que você chama de “DI na unha”? Seria não usar nenhum container?
Em que contexto?

Clássico problema de ClassLoaders. Você não colocou nenhum dos jars que você usa na sua aplicação no common/lib do seu container web né?

Certifique-se de que todos os jars e classes que você usa estão dentro de WEB-INF/classes e WEB-INF/lib.

Acho que não coloquei não, mas pode ser que tenha colocado na aplicação e ja tinha lá no container WEB. Vou olhar quando chegar em casa. Mas todos os jars coloquei pelo netbeans 6 atraves do menu de propriedades do projeto.

Vou conferir direitinho lá e posto aqui depois

Obrigado!

Não entendi!

O que você chama de “DI na unha”? Seria não usar nenhum container?
Em que contexto?[/quote]

Sem usar Spring.