1 Reply Latest reply on Jul 29, 2011 8:01 AM by walker.andrzej.martynowicz.gmail.com

    Weld + Spring + @Inject problem for Conversation

    walker.andrzej.martynowicz.gmail.com

      Hello,


      I'm using trying to build sample application which uses JSF2.0 and Weld. I'm using spring 3.0.5 and Weld 1.0.1-Final (from central maven2 repo).


      All is working OK when spring switched off. The problematic code is:


      package com.corejsf;
      
      import java.io.Serializable;
      import java.util.ArrayList;
      
      import javax.inject.Inject;
      import javax.inject.Named; 
         // or import javax.faces.bean.ManagedBean;
      import javax.enterprise.context.Conversation;
      import javax.enterprise.context.ConversationScoped;
      import javax.enterprise.context.SessionScoped; 
         // or import javax.faces.bean.SessionScoped;
      
      
      @Named // or @ManagedBean
      @ConversationScoped // @SessionScoped
      public class QuizBean implements Serializable {
         private ArrayList<ProblemBean> problems = new ArrayList<ProblemBean>();     
         private int currentIndex;
         private int score;
         
         
         //@Inject @Autowired(required=false)
         
         @Inject
         Conversation conversation;
         
         public QuizBean() {      
            problems.add(
               new ProblemBean(new int[] { 3, 1, 4, 1, 5 }, 9)); // pi
            problems.add(
               new ProblemBean(new int[] { 1, 1, 2, 3, 5 }, 8)); // fibonacci
            problems.add(
               new ProblemBean(new int[] { 1, 4, 9, 16, 25 }, 36)); // squares
            problems.add(
               new ProblemBean(new int[] { 2, 3, 5, 7, 11 }, 13)); // primes
            problems.add(
               new ProblemBean(new int[] { 1, 2, 4, 8, 16 }, 32)); // powers of 2
         }   
      
         public void setProblems(ArrayList<ProblemBean> newValue) { 
            problems = newValue;
            currentIndex = 0;
            score = 0;
         } 
            
         public int getScore() { return score; }
      
         public ProblemBean getCurrent() { return problems.get(currentIndex); }
      
         public String getAnswer() { return ""; }
         public void setAnswer(String newValue) { 
            try {
                if (currentIndex == 0) conversation.begin();
               int answer = Integer.parseInt(newValue.trim());
               if (getCurrent().getSolution() == answer) score++;            
               currentIndex = (currentIndex + 1) % problems.size();
               if (currentIndex == 0) conversation.end();
            }
            
            catch (NumberFormatException ex) {
            }
         }   
      }



      Above works as expected witout spring, but when I turn on the spring, it tries to inject a bean to conversation property and I get following exception:




      org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'quizBean': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: javax.enterprise.context.Conversation com.corejsf.QuizBean.conversation; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [javax.enterprise.context.Conversation] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@javax.inject.Inject()}
           at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:285)
           at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1074)
           at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
           at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
           at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
           at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
           at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
           at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
           at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:580)
           at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
           at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
           at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:276)
           at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:197)
           at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47)
           at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4723)
           at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5226)
           at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5221)
           at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
           at java.util.concurrent.FutureTask.run(FutureTask.java:138)
           at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
           at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
           at java.lang.Thread.run(Thread.java:662)
      Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: javax.enterprise.context.Conversation com.corejsf.QuizBean.conversation; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [javax.enterprise.context.Conversation] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@javax.inject.Inject()}
           at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:502)
           at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:84)
           at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:282)
           ... 21 more
      Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [javax.enterprise.context.Conversation] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@javax.inject.Inject()}
           at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:920)
           at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:789)
           at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:703)
           at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:474)
           ... 23 more
      2011-07-29 13:50:28 org.apache.catalina.core.StandardContext listenerStart
      SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
      org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'quizBean': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: javax.enterprise.context.Conversation com.corejsf.QuizBean.conversation; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [javax.enterprise.context.Conversation] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@javax.inject.Inject()}
           at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:285)
           at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1074)
           at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
           at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
           at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
           at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
           at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
           at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
           at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:580)
           at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
           at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
           at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:276)
           at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:197)
           at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47)
           at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4723)
           at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5226)
           at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5221)
           at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
           at java.util.concurrent.FutureTask.run(FutureTask.java:138)
           at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
           at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
           at java.lang.Thread.run(Thread.java:662)
      Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: javax.enterprise.context.Conversation com.corejsf.QuizBean.conversation; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [javax.enterprise.context.Conversation] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@javax.inject.Inject()}
           at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:502)
           at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:84)
           at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:282)
           ... 21 more
      Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [javax.enterprise.context.Conversation] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@javax.inject.Inject()}
           at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:920)
           at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:789)
           at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:703)
           at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:474)
           ... 23 more






      My configuration files are following (spring configuration is commented out, when you uncomment it you get above exception)


      faces-config.xml:




      <?xml version='1.0' encoding='UTF-8'?>
      <faces-config 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_2_0.xsd"
           version="2.0">
           
           <application>
                <!--  
                <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
                -->
      
          <locale-config>
               <default-locale>en</default-locale>
               <supported-locale>de</supported-locale>
            </locale-config>
            <resource-bundle>
               <base-name>com.corejsf.messages</base-name>
               <var>msgs</var>
            </resource-bundle>
      
      
           </application>
           
      </faces-config>



      web.xml:




      <?xml version="1.0" encoding="UTF-8"?>
      <web-app 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"
           version="2.5">
      
           <display-name>JSF2 and Spring 3.0 tutorial</display-name>
      
           <context-param>
                <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
                <param-value>.xhtml</param-value>
           </context-param>
      
         <context-param>
            <param-name>javax.faces.PROJECT_STAGE</param-name>
            <param-value>Development</param-value>
         </context-param>
      
      <!-- 
           <context-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>WEB-INF/jsf2-*.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>
      
           <listener>
                <listener-class>com.sun.faces.config.ConfigureListener</listener-class>
           </listener>
      
      -->
           <listener>
                   <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
           </listener>
           
           <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>/faces/*</url-pattern>
           </servlet-mapping>
      
         <welcome-file-list>
            <welcome-file>faces/index.xhtml</welcome-file>
         </welcome-file-list>
      
         
      </web-app>



      beans.xml - empty


      jsf2-context.xml (this is spring's application-context.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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
      
            <context:annotation-config/>
           <context:component-scan base-package="com.corejsf"/>
      
      
      </beans>









        • 1. Re: Weld + Spring + @Inject problem for Conversation
          walker.andrzej.martynowicz.gmail.com

          Ok.. It seems that I found workaround. The idea is to move all spring beans to another package and instruct spring to scan for beans in this package.


          The beans needs to be moved to package com.corejsf.spring and the configuration change in jsf2-context.xml needs to be made.


          jsf2-context.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"
               xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
          
                <context:annotation-config/>
               <context:component-scan base-package="com.corejsf.spring"/>
          
          
          </beans>




          For now this works for me, but I still have a question (maybe better for spring forum but somone might now the answer here):


          Is it possible to keep the CDI beans and spring beans in the same package and use the @Inject annotation ? (the @Inject annotation should be used by CDI to inject Conversation object, but instead spring tries to autwire the property when it sees @Inject).


          Thanks for input.