Announcement Announcement Module
Collapse
No announcement yet.
EJB3 in an EAR file Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • EJB3 in an EAR file

    Hi all,

    I have inherited a system that contains EJB2.1 and Spring, and my task is to remove the EJB v2.1 components and replace them with EJB3 components. So far this hasn't been a problem, up till I got to the Spring part.

    The original configuration of EJB2.1 placed all the beans within JNDI bound under the name "secure-client". The new EJB3 configuration places all the beans within JNDI under the name of the ear file.

    The Spring config is still trying to look for the beans under the old "secure-client" name, and I have been struggling to find out where in the Spring configuration that behaviour is controlled.

    I have spent a significant amount of time trying to Google for an explanation for how Spring finds EJBs inside the JNDI tree, when the EJBs are deployed from an ear file, but have not yet been able to find any concrete information describing this.

    Can anyone point to anything that describes how this works?

    The Spring EJB3 beans are defined like this:

    <bean id="persistenceStore"
    class="org.springframework.jndi.JndiObjectFactoryB ean">
    <property name="jndiName"
    value="java:comp/env/ejb/PersistenceServiceBean" />
    <property name="proxyInterface"
    value="alchemy.persistence.PersistenceStore" />
    </bean>

    The error I get is this:

    javax.naming.NameNotFoundException: secure-client not bound

    Regards,
    Graham
    --

  • #2
    When posting code please use [ code][/code ] tags, it makes your posted code more readable.

    Regarding your exception there must be something in your spring configuration or an external property file which points to the secure-client stuff. Also posting the complete stacktrace would help (and any additional configuration files).

    And please remind the [ code][/code ] tags when doing so.

    Comment


    • #3
      The string "secure-client" appears in a property called "j2ee.clientName" which exists in the client, I can find no reference to this string in the Spring config files anywhere.

      The problem is that I am looking for some understanding on how Spring "finds" EJB3 beans that are defined inside an ear file. At some point, I need to tell Spring the name of this ear file, either programmatically, or in a config file somewhere, but I can find no definitive answer that says "Spring looks here inside JNDI for your beans".

      The full stacktrace looks like this:

      Code:
      javax.naming.NameNotFoundException: secure-client not bound
      	at org.jnp.server.NamingServer.getBinding(NamingServer.java:529)
      	at org.jnp.server.NamingServer.getBinding(NamingServer.java:537)
      	at org.jnp.server.NamingServer.getObject(NamingServer.java:543)
      	at org.jnp.server.NamingServer.lookup(NamingServer.java:296)
      	at sun.reflect.GeneratedMethodAccessor61.invoke(Unknown Source)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      	at java.lang.reflect.Method.invoke(Method.java:585)
      	at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:294)
      	at sun.rmi.transport.Transport$1.run(Transport.java:153)
      	at java.security.AccessController.doPrivileged(Native Method)
      	at sun.rmi.transport.Transport.serviceCall(Transport.java:149)
      	at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:466)
      	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:707)
      	at java.lang.Thread.run(Thread.java:595)
      	at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:247)
      	at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:223)
      	at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:126)
      	at org.jnp.server.NamingServer_Stub.lookup(Unknown Source)
      	at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:625)
      	at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:587)
      	at javax.naming.InitialContext.lookup(InitialContext.java:351)
      	at org.jboss.naming.client.java.javaURLContextFactory$EncContextProxy.invoke(javaURLContextFactory.java:129)
      	at $Proxy0.lookup(Unknown Source)
      	at javax.naming.InitialContext.lookup(InitialContext.java:351)
      	at org.springframework.jndi.JndiTemplate$1.doInContext(JndiTemplate.java:123)
      	at org.springframework.jndi.JndiTemplate.execute(JndiTemplate.java:85)
      	at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:121)
      	at org.springframework.jndi.JndiLocatorSupport.lookup(JndiLocatorSupport.java:71)
      	at org.springframework.jndi.JndiObjectLocator.lookup(JndiObjectLocator.java:106)
      	at org.springframework.jndi.JndiObjectTargetSource.afterPropertiesSet(JndiObjectTargetSource.java:95)
      	at org.springframework.jndi.JndiObjectFactoryBean$JndiObjectProxyFactory.createJndiObjectProxy(JndiObjectFactoryBean.java:169)
      	at org.springframework.jndi.JndiObjectFactoryBean$JndiObjectProxyFactory.access$000(JndiObjectFactoryBean.java:158)
      	at org.springframework.jndi.JndiObjectFactoryBean.afterPropertiesSet(JndiObjectFactoryBean.java:117)
      	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1058)
      	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:363)
      	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:226)
      	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:147)
      	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:269)
      	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:318)
      	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:81)
      	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:66)
      	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:57)
      	at alchemy.runtime.registry.spring.SpringClientRegistry.refresh(SpringClientRegistry.java:60)
      	at alchemy.runtime.registry.spring.SpringClientRegistry.<init>(SpringClientRegistry.java:50)
      	at alchemy.runtime.registry.RegistryFactory.getInstance(RegistryFactory.java:111)
      	at alchemy.runtime.command.CommandServiceLocator.getService(CommandServiceLocator.java:51)
      	at alchemy.trader.entity.EntityFinder.refresh(EntityFinder.java:335)
      	at alchemy.trader.entity.EntityFinder.<init>(EntityFinder.java:130)
      	at alchemy.trader.entity.EntityFinder.getInstance(EntityFinder.java:106)
      	at com.standardbank.alchemy.plugin.ApplicationWorkbenchAdvisor.initAlchemy(ApplicationWorkbenchAdvisor.java:103)
      	at com.standardbank.alchemy.plugin.ApplicationWorkbenchAdvisor.preStartup(ApplicationWorkbenchAdvisor.java:75)
      	at org.eclipse.ui.internal.Workbench.init(Workbench.java:1099)
      	at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:1863)
      	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:422)
      	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
      	at com.standardbank.alchemy.plugin.Application.run(Application.java:28)
      	at org.eclipse.core.internal.runtime.PlatformActivator$1.run(PlatformActivator.java:78)
      	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:92)
      	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:68)
      	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:400)
      	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:177)
      	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      	at java.lang.reflect.Method.invoke(Method.java:585)
      	at org.eclipse.core.launcher.Main.invokeFramework(Main.java:336)
      	at org.eclipse.core.launcher.Main.basicRun(Main.java:280)
      	at org.eclipse.core.launcher.Main.run(Main.java:977)
      	at org.eclipse.core.launcher.Main.main(Main.java:952)

      Comment


      • #4
        Spring looks where you tell it to look just as you normally would do with a InitialContext object.

        However the stuff from your client seems to be the cullprit, some kind of ServiceLocator is trying to locate some beans, which ofcourse after your refactoring aren't there anymore.

        However it might be solved by changing the property file to represent the correct location...

        Comment


        • #5
          Doing a global search and replace for secure-client to the name of the ear file works around the initial problem, but now I am getting the exception "PersistenceServiceBean not bound".

          It seems to have found the name of the ear file in JNDI, but the next problem lies directly underneath. The bean definition shows in theory that it is looking for an entry "PersistenceServiceBean":

          Code:
          	<bean id="persistenceStore"
          		class="org.springframework.jndi.JndiObjectFactoryBean">
          		<property name="jndiName"
          			value="PersistenceServiceBean/remote" />
          		<property name="proxyInterface"
          			value="alchemy.persistence.PersistenceStore" />
          	</bean>
          According to JBoss, the bean is under JNDI like so:

          Code:
            +- alchemy-trader-ear-4.2.0-SNAPSHOT (class: org.jnp.interfaces.NamingContext)
            |   +- PersistenceServiceBean (class: org.jnp.interfaces.NamingContext)
            |   |   +- local (proxy: $Proxy197 implements interface alchemy.persistence.PersistenceStore,interface org.jboss.ejb3.JBossProxy,interface javax.ejb.EJBLocalObject)
            |   |   +- remote (proxy: $Proxy196 implements interface alchemy.persistence.PersistenceStore,interface org.jboss.ejb3.JBossProxy,interface javax.ejb.EJBObject)
          Is the bean defined correctly for EJB3?

          Comment


          • #6
            Solution: Spring calls EJB3

            I eventually found that using the raw EJB name, prepended with the name of the EAR file, works:

            Code:
            	<bean id="persistenceStore"
            		class="org.springframework.jndi.JndiObjectFactoryBean">
            		<property name="jndiName"
            			value="alchemy-trader-ear-${version}/PersistenceServiceBean/remote" />
            		<property name="proxyInterface"
            			value="alchemy.persistence.PersistenceStore" />
            	</bean>
            The name of the ear in this case was "alchemy-trader-ear".

            Because in this case the ear file is generated by maven, the ear filename contains the version number of the ear. Our maven build process makes a properties file available where a key called "version" contains the version number.

            Spring is made aware of this property file, and in turn the ${version} variable by placing the following at the top of the Spring config:

            Code:
            	<bean id="propertyConfigurer"
            		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            		<property name="locations">
            			<list>
            				<value>/alchemy-trader-version.properties</value>
            			</list>
            		</property>
            	</bean>

            Comment

            Working...
            X