2009-11-16 10 views
2

J'expose certains services en utilisant RMI sur Spring. Chaque service a une dépendance à l'autre bean de service qui effectue le travail de traitement réel. Par exemple:Les références des services exposés RMI doivent-elles être transitoires?

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

Mon AccountRmiServiceImpl ressemble à ceci:

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

    private AccountService accountService; 

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

Ma question est la suivante: pourrait AccountServiceImpl être créé sans mettre en oeuvre l'interface marqueur Serializable? Si c'est le cas, alors sa référence dans AccountRmiServiceImpl devrait être rendue transitoire. Cela signifie qu'il ne sera pas sérialisé et transféré au client où l'invocation RMI est faite. C'est possible?

Répondre

2

Peut-être que.

Vous pourrait marquer définitivement le champ accountService comme transitoire, qui en effet l'empêcher d'être sérialisés et envoyés via RMI (ou plus exactement, parviennent pas être sérialisés et lancer une exception). Cependant, à ce stade, le AccountRmiServiceImpl qui a été reconstruit de l'autre côté aura une valeur nulle pour son serviceService, ce qui, sans aucun autre changement, conduira probablement à un NullPointerException plus tard.

Si votre AccountServiceImpl n'est pas serialisable (au sens Java), mais vous êtes toujours en mesure de créer une instance de celui-ci sur la base des informations serialisable simple, alors vous avez de la chance. Vous pouvez implémenter la sérialisation vous-même à l'aide des méthodes writeObject/readObject ou writeReplace/readResolve (voir Serializable pour plus de détails). Si les instances de AccountServiceImpl ne sont sérialisables dans aucun sens du mot (par exemple une classe interne anonyme avec une logique inline, ainsi que des références aux variables locales finales dans sa portée externe), il n'y a aucun moyen de l'envoyer. Quel genre d'objet serait recréé de l'autre côté? Si c'est la situation dans laquelle vous vous trouvez, vous devrez refactoriser votre code pour rendre les classes sérialisables.

+0

Merci pour la réponse dtsazza. Disons que AccountServiceImpl met en œuvre Serializable. Le même problème se reproduit mais maintenant avec des références d'objet DAO. Les implémentations DAO ne sont pas sérialisables et cela n'a aucun sens de les implémenter car Spring les injecte en tant que dépendances. –

+0

Si les * contenus * (champs) d'une classe ne sont pas sérialisables, la classe n'est pas sérialisable. Vous devez agir "de bas en haut" - et si vous ne pouvez pas faire un des champs "Serializable" * et * ne peut pas le reconstituer manuellement, alors vous n'avez pas de chance. N'oubliez pas de marquer les champs comme «transitoire» s'ils ne font pas partie de l'état persistant (par exemple, les caches ou le thread actuel). –