Above and beyond (help with Spring RMI)

Hi,

This question is really above and beyond the call of duty for the sun forums so I'm not expecting much help, but maybe some of you RMI experts could shed some light that might help me get to the bottom of what's going wrong.

I have a simple Login Service that I want to expose over RMI. The service worked fine when I did this myself but since my app uses Spring, and Spring (supposedly) can be configured to do this automatically I thought I'd give it a shot.

Ultimately the result is an "ExportException: object already exported" when Spring attempts to create the service (i.e. long before the client attempts to retrieve it). Has anyone with Spring experience any idea whether this is a bug, or me being thick (most likely).

Service Interfacepackage com.myapp.service;

import java.rmi.Remote;

import java.rmi.RemoteException;

import com.myapp.domainmodel.User;// Is serializable

publicinterface ILoginServiceextends Remote

{

public User login(String username, String password)throws RemoteException;

}

Stack Trackeorg.springframework.beans.factory.BeanCreationException: Error creating bean with name'org.springframework.remoting.rmi.RmiServiceExporter' defined in file [C:\Projects\myapp\workspace\myappTest\env\spring\application-context.xml]: Initialization of bean failed; nested exception is java.rmi.server.ExportException: object already exported

java.rmi.server.ExportException: object already exported

at sun.rmi.transport.ObjectTable.putTarget(Unknown Source)

at sun.rmi.transport.Transport.exportObject(Unknown Source)

at sun.rmi.transport.tcp.TCPTransport.exportObject(Unknown Source)

at sun.rmi.transport.tcp.TCPEndpoint.exportObject(Unknown Source)

at sun.rmi.transport.LiveRef.exportObject(Unknown Source)

at sun.rmi.server.UnicastServerRef.exportObject(Unknown Source)

at java.rmi.server.UnicastRemoteObject.exportObject(Unknown Source)

at java.rmi.server.UnicastRemoteObject.exportObject(Unknown Source)

at org.springframework.remoting.rmi.RmiServiceExporter.afterPropertiesSet(RmiServiceExporter.java:249)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1059)

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:275)

at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:320)

at org.springframework.context.support.FileSystemXmlApplicationContext.<init>(FileSystemXmlApplicationContext.java:89)

at org.springframework.context.support.FileSystemXmlApplicationContext.<init>(FileSystemXmlApplicationContext.java:74)

at org.springframework.context.support.FileSystemXmlApplicationContext.<init>(FileSystemXmlApplicationContext.java:65)

at com.myapp.service.spring.ServiceLocatorTest.setUp(ServiceLocatorTest.java:21)

at org.jmock.core.VerifyingTestCase.runBare(Unknown Source)

at junit.framework.TestResult$1.protect(TestResult.java:106)

at junit.framework.TestResult.runProtected(TestResult.java:124)

at junit.framework.TestResult.run(TestResult.java:109)

at junit.framework.TestCase.run(TestCase.java:118)

at junit.framework.TestSuite.runTest(TestSuite.java:208)

at junit.framework.TestSuite.run(TestSuite.java:203)

at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:478)

at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:344)

at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)

Extract from application-context.xml<bean id="loginService" class="com.myapp.service.impl.LoginService" singleton="true" lazy-init="false">

<constructor-arg>

<bean id="persistenceManager" class="com.myapp.persistence.hibernate.PersistenceManager" singleton="true" >

<constructor-arg><ref bean="hibernateSessionFactory"/></constructor-arg>

</bean>

</constructor-arg>

<constructor-arg value="3" /> <!-- Maximum Failed Login Attempts -->

<constructor-arg value="900" /> <!-- Seconds Before Failure Count Reset -->

</bean>

<bean class="org.springframework.remoting.rmi.RmiServiceExporter">

<property name="serviceName" value="loginService"/>

<property name="service" ref="loginService"/>

<property name="serviceInterface" value="com.myapp.service.ILoginService"/>

<property name="registryPort" value="1199"/>

</bean>

[6102 byte] By [SteveNaivea] at [2007-10-2 5:46:19]
# 1
Does your implementation of ILoginService extend UnicastRemoteObject? I've never worked with Spring, but my guess is that it's trying to manually export an instance of your class, but because it extends UnicastRemoteObject that has already been done.
carr_onstotta at 2007-7-16 1:56:07 > top of Java-index,Core,Core APIs...
# 2
Mine doesn't but when I look at the Spring source it seems to create a proxy which does. Thanks for your help - looks like (another) bug in Spring.
SteveNaivea at 2007-7-16 1:56:07 > top of Java-index,Core,Core APIs...
# 3
Doh! Spring was not at fault. Just being incredibly stupid (again) all along.
SteveNaivea at 2007-7-16 1:56:07 > top of Java-index,Core,Core APIs...