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?
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.