Results 1 to 7 of 7

Thread: Spring/JBoss/EJB3 -> Problems calling ejbs

  1. #1
    Join Date
    Mar 2007
    Posts
    9

    Default Spring/JBoss/EJB3 -> Problems calling ejbs

    Hello!

    I've put JBoss 4.2.2, EJB3.0 and Spring 2.5.1 together. However, I haven't succeeded to call the local EJBs yet.

    I've defined an EJB as follows:

    Code:
    @Stateless
    @Interceptors(SpringBeanAutowiringInterceptor.class)
    public class AccountServiceImpl implements AccountService, AccountServiceLocal {
    
    	@Autowired
    	private AccountDao accountDao;
    	private String tempFileName = "idsa2008file.dat";
    
    	@Override
    	public List<Account> getAllAccountsMNormal() {
    		return accountDao.getAccounts();
    	}
    The AccountService is used in JSF bean in the web container:
    Code:
    public class AccountAction {
    
    	private AccountService accountService;
    
    	/**
    	 * 
    	 * @return Action string.
    	 */
    	@SuppressWarnings("unchecked")
    	public String getAllAccounts() {
                List<Account> accounts = accountService.getAllAccounts();
                ....
    My application context, separated in 2 different files looks as follows:

    Code:
    	<!--  Repository configuration by annotations -->
         <context:annotation-config/>               
         <context:component-scan base-package="foo"/>
    
    	<!--  Configuration for defined persistence unit in persistence.xml -->
         <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
          <property name="persistenceUnitName" value="fooPersistenceUnit"/>
         </bean>
         
          <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
      		<property name="entityManagerFactory" ref="entityManagerFactory" />
          </bean>
          
          <!--  Transaction configuration by annotions -->
          <tx:annotation-driven transaction-manager="transactionManager"/>
    
    	<jee:jndi-lookup  id="accountServiceEjb" jndi-name="foo/AccountServiceImpl/local" lookup-on-startup="false" proxy-interface="foo.service.AccountService"/>
    
    	<bean id="accountAction"
            class="foo.web.jsf.AccountAction">
             <property name="accountService" ref="accountServiceEjb"/>
        </bean>
    Though, something is wrong. I can deploy the application without errors, but when I call a method on the ejb, the application throws following runtime error:

    Code:
    org.springframework.beans.factory.access.BootstrapException: Unable to return specified BeanFactory instance: factory key [null], from group with resource name [classpath*:beanRefContext.xml]; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [org.springframework.beans.factory.BeanFactory] is defined: expected single bean but found 0
    	org.springframework.beans.factory.access.SingletonBeanFactoryLocator.useBeanFactory(SingletonBeanFactoryLocator.java:410)
    	org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor.getBeanFactoryReference(SpringBeanAutowiringInterceptor.java:132)
    	org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor.getBeanFactory(SpringBeanAutowiringInterceptor.java:113)
    	org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor.autowireBean(SpringBeanAutowiringInterceptor.java:93)
    	sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    	sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    	java.lang.reflect.Method.invoke(Method.java:597)
    	org.jboss.ejb3.interceptor.LifecycleInvocationContextImpl.proceed(LifecycleInvocationContextImpl.java:131)
    	org.jboss.ejb3.interceptor.LifecycleInterceptorHandler.postConstruct(LifecycleInterceptorHandler.java:109)
    	org.jboss.ejb3.EJBContainer.invokePostConstruct(EJBContainer.java:619)
    	org.jboss.ejb3.AbstractPool.create(AbstractPool.java:131)
    	org.jboss.ejb3.InfinitePool.get(InfinitePool.java:49)
    	org.jboss.ejb3.ThreadlocalPool.create(ThreadlocalPool.java:50)
    	org.jboss.ejb3.ThreadlocalPool.get(ThreadlocalPool.java:90)
    	org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:54)
    	org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
    	org.jboss.aspects.security.AuthenticationInterceptor.invoke(AuthenticationInterceptor.java:77)
    	org.jboss.ejb3.security.Ejb3AuthenticationInterceptor.invoke(Ejb3AuthenticationInterceptor.java:110)
    	org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
    	org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:46)
    	org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
    	org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:106)
    	org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
    	org.jboss.ejb3.stateless.StatelessContainer.localInvoke(StatelessContainer.java:240)
    	org.jboss.ejb3.stateless.StatelessContainer.localInvoke(StatelessContainer.java:210)
    	org.jboss.ejb3.stateless.StatelessLocalProxy.invoke(StatelessLocalProxy.java:84)
    	$Proxy91.getAllAccounts(Unknown Source)
    	sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    	sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    	java.lang.reflect.Method.invoke(Method.java:597)
    	org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:301)
    	org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:198)
    	$Proxy82.getAllAccounts(Unknown Source)
    	foo.web.jsf.AccountAction.getAllAccounts(AccountAction.java:35)
    .....
    root cause
    
    org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [org.springframework.beans.factory.BeanFactory] is defined: expected single bean but found 0
    	org.springframework.beans.factory.BeanFactoryUtils.beanOfType(BeanFactoryUtils.java:379)
    	org.springframework.beans.factory.access.SingletonBeanFactoryLocator.useBeanFactory(SingletonBeanFactoryLocator.java:400)
    	org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor.getBeanFactoryReference(SpringBeanAutowiringInterceptor.java:132)
    	org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor.getBeanFactory(SpringBeanAutowiringInterceptor.java:113)
    	org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor.autowireBean(SpringBeanAutowiringInterceptor.java:93)
    	sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    	sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    	java.lang.reflect.Method.invoke(Method.java:597)
    	org.jboss.ejb3.interceptor.LifecycleInvocationContextImpl.proceed(LifecycleInvocationContextImpl.java:131)
    	org.jboss.ejb3.interceptor.LifecycleInterceptorHandler.postConstruct(LifecycleInterceptorHandler.java:109)
    	org.jboss.ejb3.EJBContainer.invokePostConstruct(EJBContainer.java:619)
    	org.jboss.ejb3.AbstractPool.create(AbstractPool.java:131)
    	org.jboss.ejb3.InfinitePool.get(InfinitePool.java:49)
    	org.jboss.ejb3.ThreadlocalPool.create(ThreadlocalPool.java:50)
    	org.jboss.ejb3.ThreadlocalPool.get(ThreadlocalPool.java:90)
    	org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:54)
    	org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
    	org.jboss.aspects.security.AuthenticationInterceptor.invoke(AuthenticationInterceptor.java:77)
    	org.jboss.ejb3.security.Ejb3AuthenticationInterceptor.invoke(Ejb3AuthenticationInterceptor.java:110)
    	org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
    	org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:46)
    	org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
    	org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:106)
    	org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
    	org.jboss.ejb3.stateless.StatelessContainer.localInvoke(StatelessContainer.java:240)
    	org.jboss.ejb3.stateless.StatelessContainer.localInvoke(StatelessContainer.java:210)
    	org.jboss.ejb3.stateless.StatelessLocalProxy.invoke(StatelessLocalProxy.java:84)
    	$Proxy91.getAllAccounts(Unknown Source)
    	sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    	sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    	java.lang.reflect.Method.invoke(Method.java:597)
    	org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:301)
    	org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:198)
    	$Proxy82.getAllAccounts(Unknown Source)
    	foo.web.jsf.AccountAction.getAllAccounts(AccountAction.java:35)
    	........
    I guess the injection is not working properly. There is a accountService instance, however, it can't use it.
    Can anybody help me?

    Thanks

    Kuno

  2. #2
    Join Date
    Aug 2004
    Location
    Linz, Austria
    Posts
    391

    Default

    It seems that you're not defining nested ApplicationContexts there in your beanRefContext.xml file... Check out the javadoc of "org.springframework.beans.factory.access.Singleto nBeanFactoryLocator" for examples.

    Essentially, your "beanRefContext.xml" file will typically define a ClassPathXmlApplicationContext which in turns loads your actual beans. The "beanRefContext.xml" mechanism allows multiple such shared ApplicationContexts to co-exist, differentiated by bean factory locators. In the default EJB3 case, simply define one such ApplicationContext which will be picked up automatically, regardless of name.

    A "beanRefContext.xml" example:

    Code:
    <beans>
    
      <bean id="myContext" class="org.springframework.context.support.ClassPathXmlApplicationContext">
        <constructor-arg value="myContextBeans.xml"/>
      </bean>
    
    </beans>
    Your actual application beans would then be defined in the specified "myContextBeans.xml" file.

    In a larger application, you could have multiple such shared contexts, using different ids. Different groups of EJBs could in turn talk to different shared ApplicationContexts. The specific context to be used can be identified through overriding SpringBeanAutowiringInterceptor's "getBeanFactoryLocatorKey" method.

    Juergen

  3. #3
    Join Date
    Mar 2007
    Posts
    9

    Default

    Quote Originally Posted by Juergen Hoeller View Post
    It seems that you're not defining nested ApplicationContexts there in your beanRefContext.xml file...

    Juergen
    Thanks for your reply. Actually, I tried to configure a beanRefContext.xml, however I'm not quite sure if I have done it right.

    My structure looks like this:

    Code:
    Archive:  app.jar
         META-INF/                
         META-INF/MANIFEST.MF     
         foo/            
         foo/dao/        
         foo/dao/AccountDao.class   
         foo/dao/AccountDaoMock.class   
         foo/dao/hibernate/   
         foo/dao/hibernate/AbstractTransactionalTestCase.class   
         foo/dao/hibernate/AccountDaoImpl.class   
         foo/dao/hibernate/AccountDaoImplTest.class   
         foo/dao/hibernate/AllTests.class   
         foo/domain/     
         foo/domain/Account.class   
         foo/service/    
         foo/service/AccountService.class   
         foo/service/AccountServiceImpl.class   
         foo/service/AccountServiceLocal.class   
         foo/service/AccountServiceTest.class   
         beanRefContext.xml       
         serviceContext.xml       
         META-INF/persistence.xml   
    
    Archive:  foo.ear
         META-INF/                
         META-INF/MANIFEST.MF     
         META-INF/application.xml   
         app.jar                  
         fooWeb.war              
         lib/                     
         lib/spring.jar           
         META-INF/jboss-app.xml
    My beanRefContext.xml

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
    
        <bean id="ear.context" class="org.springframework.context.support.ClassPathXmlApplicationContext">
            <constructor-arg>
                <list>
                    <value>serviceContext.xml</value>
                </list>
            </constructor-arg>
        </bean>
    </beans>
    And then I've added following to my web.xml in fooWeb.war module:

    Code:
    ...
        <context-param>
            <param-name>parentContextKey</param-name>
            <param-value>ear.context</param-value>
        </context-param>
       <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>
    
    ...
    I'm not sure about the last step and it would be nice to have step by step example for integrating EJB3.0 into Spring. I've read the javadoc in org.springframework.beans.factory.access.Singleton BeanFactoryLocator. However, I'm more confused now as I was before ;-} More precisely, I'm not going to write "client code" like
    Code:
     BeanFactoryLocator bfl = SingletonBeanFactoryLocator.getInstance();
    ...
    Also, I had to put the spring library directly in foo.ear : lib/spring.jar. It seams that the SpringBeanAutowiringInterceptor called before the libs in fooWeb.war is actually loaded. Once more it looks like a classloading problem to me and I'm getting a bit frustrated about that.

    Thanks for your help.

    Kuno
    Last edited by qnob; Feb 1st, 2008 at 01:34 AM.

  4. #4

    Default similar problem with glassfish/spring 2.5.1

    beanRefContext.xml:
    <beans>
    <bean id="myContext" class="org.springframework.context.support.ClassPa thXmlApplicationContext">
    <constructor-arg value="applicationContext.xml"/>
    </bean>
    </beans>

    applicationContext.xml:
    <beans>
    ...
    <context:annotation-config/>

    <bean id="beanName" class="java.lang.String">
    <constructor-arg value="Test Bean"/>
    </bean>
    </beans>


    bean class:
    Stateless(mappedName="ejb/TestBeanImpl")
    @Interceptors(SpringBeanAutowiringInterceptor.clas s)
    public class TestBeanImpl implements TestBean {
    @Autowired
    String beanName;

    ...
    }


    The error:
    Unable to return specified BeanFactory instance: factory key [null], from group with resource name [classpath*:beanRefContext.xml]; nested exception is org.springframework.beans.factory.NoSuchBeanDefini tionException: No unique bean of type [org.springframework.beans.factory.BeanFactory] is defined: expected single bean but found 0
    No unique bean of type [org.springframework.beans.factory.BeanFactory] is defined: expected single bean but found 0

  5. #5
    Join Date
    Mar 2007
    Posts
    9

    Default gave it up

    hello!

    sorry can't help. I gave it up after a couple of frustrating days. It seems that spring framework is developing to fast for my intellect or I'm drying to do things with this framework I shouldn't.
    I still stick on spring, though!

    I hope you'll succeed!

    Kuno

  6. #6
    Join Date
    Feb 2008
    Location
    Manila, Philippines
    Posts
    9

    Default

    I've gotten Spring 2.5.1 + EJB3 to work on both JBoss and Glassfish. Though, I've also at times run into issues similar to the above (see my thread on this).

    Like you, I also placed spring.jar into ${JBOSS_HOME}/server/default/lib.

    Here's my current (trivial) setup that works on JBoss 4.2.0.GA (minus the import statements).

    My bean interface:
    Code:
    package foo.ejb;
    
    public interface Service {
    
      public String getVersion();
    
    }
    My Bean implementation:
    Code:
    package foo.ejb;
    
    @Stateless(name = "service")
    public class ServiceBean implements Service {
    
      @Autowired
      private Delegate delegate;
    
      public String getVersion() {
        return delegate.getVersion();
      }
    
    }
    Delegate is a dependency of ServiceBean:
    Code:
    package foo.ejb;
    
    public class Delegate {
      public String getVersion() {
        return "1.0";
      }
    }
    My beanRefContext.xml:
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
    
      <bean class="org.springframework.context.support.ClassPathXmlApplicationContext">
        <constructor-arg type="java.lang.String" value="ejbApplicationContext.xml" />
      </bean>
      
    </beans>
    And my ejbApplicationContext.xml:
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
    
      <bean id="delegate" class="foo.ejb.Delegate" />
      
    </beans>
    And finally, to configure Spring to inject into my EJBs, I used Spring 2.5.1's SpringBeanAutowiringInterceptor. Here's my /META-INF/ejb-jar.xml:
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <ejb-jar version="3.0" 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/ejb-jar_3_0.xsd">
      <interceptors>
        <interceptor>
          <interceptor-class>org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor</interceptor-class>      
        </interceptor>    
      </interceptors>
      <assembly-descriptor>
        <interceptor-binding>
          <ejb-name>*</ejb-name>
          <interceptor-class>org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor</interceptor-class>
        </interceptor-binding>
      </assembly-descriptor>
    </ejb-jar>
    That all goes into foo-ejb.jar.

    Next the stuff that goes into foo-web.war, starting with my controller:
    Code:
    package foo.web;
    
    @Controller
    public class IndexController {
    
      /**
       * Or "service/remote" on JBoss. For Glassfish, remove the suffix.
       */
      @EJB(mappedName = "service/local")
      private Service service;
      
      @RequestMapping("/index.html")
      public void index(ModelMap model) {
        model.addAttribute("version", service.getVersion());
      }
    
    }
    The Freemarker template that comprises the view for the above:
    Code:
    <html>
    <body>
    <p>Version: ${version}</p>
    </body>
    </html>
    Now, an important point: I had problems on both Glassfish and JBoss getting the JNDI lookup correct because of prefixes and suffixes. The most relevant part of my foo-servlet.xml shows how I avoid the "java:comp/env" prefix:
    Code:
    <?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-2.5.xsd
      http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context-2.5.xsd">
    
      <!--
        Use a custom JNDI bean factory configured not to prepend lookups with "java:comp/env"
      -->
      <bean id="jndiFactory"
        class="org.springframework.jndi.support.SimpleJndiBeanFactory">
        <property name="resourceRef" value="false" />
      </bean>
    
      <!--
        Configure the CommonAnnotationBeanPostProcessor to always use JNDI lookup (for EJBs)
        and use the custom JNDI bean factory above.
      -->
      <bean
        class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor">
        <property name="alwaysUseJndiLookup" value="true" />
        <property name="jndiFactory" ref="jndiFactory" />
      </bean>
    
      <!--
        Since we're turning off "annotation-config" in the context:component-scan below, we need
        to explicitly configure an AutowiredAnnotationBeanPostProcessor.
      -->
      <bean
        class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
    
      <!--
        Configure annotation-based component scanning, instantiation and dependency injection. 
      -->
      <context:component-scan base-package="com.talikos.ese.web.controllers" annotation-config="false" />
    
      <!--
        Rest of Spring MVC (view resolver, etc.) configuration goes here.
      -->
    
    </beans>
    Hope this (lengthy post) helps. I really should blog this.

  7. #7
    Join Date
    Mar 2007
    Posts
    9

    Default

    Thanks alistair for your great post. I've put Spring/EJB3 on ice for the moment - got transfered to another project...though, one day, I'll recall it

    Thanks again.

    K

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •