views:

46

answers:

1

I'm exposing some services using RMI on Spring. Every service has a dependency to other service bean which does the real processing job. For example:

<bean id="accountService" class="example.AccountServiceImpl">
    <!-- any additional properties, maybe a DAO? -->
</bean>

<bean id="rmiAccount" class="example.AccountRmiServiceImpl"/>

<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
    <!-- does not necessarily have to be the same name as the bean to be exported -->
    <property name="serviceName" value="AccountService"/>
    <property name="service" ref="accountService"/>
    <property name="serviceInterface" value="example.AccountService"/>
    <!-- defaults to 1099 -->
    <property name="registryPort" value="1199"/>
</bean>

My AccountRmiServiceImpl looks like this:

public class AccountRmiServiceImpl implements AccountRmiService {
    private static final long serialVersionUID = -8839362521253363446L;

    private AccountService accountService;

    @Autowired
    public void setAccountService(AccountService accountService) {
        this.accountService = accountService;
    }
}

My question is: could AccountServiceImpl be created without implementing the Serializable marker interface? If it is a case, then its reference in AccountRmiServiceImpl should be made transient. This means that it would not be serialized and transfered to the client where the RMI invocation is being made. Is it possible?

+1  A: 

Maybe.

You could definitely mark the accountService field as transient, which would indeed stop it from being serialised and sent over RMI (or more accurately, failing to be serialised and throwing an exception). However, at this point the AccountRmiServiceImpl that's reconstructed on the other side will have a null value for its accountService, which without any other changes would almost certainly lead to a NullPointerException later.

If your AccountServiceImpl is not serialisable (in the Java sense), but you are still able to create an instance of it based on some simple serialisable information, then you're in luck. You can implement the serialisation yourself using the writeObject/readObject or writeReplace/readResolve methods (see Serializable for details).

If instances of AccountServiceImpl are not serialisable in any sense of the word (e.g. an anonymous inner class with inline logic as well as references to final local variables in its outer scope), then there's no way to send this across. What kind of object would be recreated on the other side? If this is the situation you find yourself in, you'd need to refactor your code to make the class(es) serialisable.

Andrzej Doyle
Thanks for the answer dtsazza. Let's say that AccountServiceImpl does implement Serializable. The same problem reoccurs but now with DAO object references. DAO implementations aren't serializable and there's no sense making them implement this interface because Spring injects them as dependencies.
Boris Pavlović
If the *contents* (i.e. fields) of a class aren't Serializable, then the class isn't Serializable. You need to act "bottom-up" - and if you can't make one of the fields `Serializable` *and* can't reconstitute it manually, then you're out of luck. Don't forget to mark fields as `transient` if they're not part of the persistent state, though (e.g. caches or current Thread).
Andrzej Doyle