【问题标题】:Spring - Passing Listener via RMISpring - 通过 RMI 传递监听器
【发布时间】:2015-10-01 15:37:27
【问题描述】:

基础

我有几个项目,它们实现了一个缓存服务——每个都有自己的,每个几乎都和其他的一样。我已将现有的缓存服务压缩并缩短为一个项目,其中包含两种不同的缓存服务——一种用于基本对象,一种用于复杂对象(它扩展了基本服务)。我创建了 2 个项目 - 一个部署为 .war 文件,而 API 项目则用于此部署。

整个应用程序运行在带有最新 JDK 7 的 JBoss AS 7.1 “Thunder”上。

问题

每当删除旧的缓存条目时,特别需要通知一个类。为此,我使用 CleanupListeners 实现了一个通知程序。

CleanupListener.java

public interface CleanupListener extends Remote {

    public abstract boolean supports(Class<?> clazz) throws RemoteException;

    public abstract void notify(Object removedObject) throws RemoteException;

}

缓存服务中的必要实现

public void registerCleanupListener(CleanupListener listener) {
    listeners.add(listener);
}

private void fireCleanupEvent(Object removedObject) {
    for (CleanupListener cleanupListener : listeners) {
        try {
            if (cleanupListener.supports(removedObject.getClass())) {
                cleanupListener.notify(removedObject);
            }
        } catch (RemoteException re) {
            LOGGER.error("Remote Listener not available", re);
        }
    }
}

监听器通过private final HashSet&lt;CleanupListener&gt;进行管理
需要通知的项目使用这个接口的实现:

@Component
public class CleanupEventListener extends UnicastRemoteObject implements CleanupListener {

    protected CleanupEventListener() throws RemoteException {
        super();
    }

    @Resource
    private ClassRequiresNotification notifyMe;

    public boolean supports(Class<?> clazz) {
        return SupportedObject.class.isAssignableFrom(clazz);
    }

    public void notify(Object removedObject) {
        notifyMe.someMethod((SupportedObject) removedObject);
    }
}

还有一个注册 bean:

@Component
public class CleanupEventListenerRegistrator {

    @Resource
    private CleanupEventListener cleanupEventListener;

    @Resource
    private BasicCacheService cacheService;

    @PostConstruct
    public void init() {
        cacheService.registerCleanupListener(cleanupEventListener);
    }
}

远程服务通过 SpringBean 导出:

@Bean
public RmiServiceExporter basicCacheServiceExporter(BasicCacheService basicCacheService) {
    RmiServiceExporter cacheService = new RmiServiceExporter();
    cacheService.setService(basicCacheService);
    cacheService.setServiceName(BASIC_CACHE_SERVICE_NAME);
    cacheService.setServiceInterface(some.package.BasicCacheService.class);
    return cacheService;
}

并通过 XML-Config 注册:

<bean id="basicCacheService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
    <property name="lookupStubOnStartup" value="false"/>
    <property name="serviceUrl" value="basicCacheService" />
    <property name="serviceInterface" value="some.package.BasicCacheService" />
    <property name="refreshStubOnConnectFailure" value="true"/>
</bean>

异常

所以,每当我尝试调用预期的方法时,我都会遇到两个异常之一:

要么我得到一个NoSuchObjectException(罕见),要么更常见的是一个ClassNotFoundException 包裹在UnmarshalException

我做了什么

我已经查阅了 JavaDocs,大量搜索并在这里筛选了几个问题,但无济于事。我发现了一些信息,标准属性rmi.codebase 设置为true,这可能需要重写一些代码,但是我们已经在项目的另一个地方使用 RMI,它在那里工作得很好。添加 SecurityManager 会破坏我们应用程序的其余部分(由于外部先决条件)并调用 NoSuchObjectException。 到目前为止,StackOverflow 中的答案已经产生“这是代码库的问题”、“您需要安装 securityManager”、“类必须具有相同的名称并且在同一个包中”,当然还有“这是代码库” .我提到了两次,因为它确实经常出现,但没有一次提到如何处理代码库问题。

附加信息

我不确定这是否重要,但这里有更多信息: cacheservice-project用java代码配置,使用服务的project用XML配置。
Listener-Interface 不是通过 Annotations 或 XML-Beans 导出的,因为有几篇文章(这里至少包括一篇文章)暗示这将导出类,但只在服务器端监听,这不是我想要的。
我还尝试将 CleanupListener 设为一个抽象类,它本身扩展了 UnicastRemoteObject ,但也没有成功 - 事实上,它比我现在拥有的更糟糕。
我正在 Eclipse 中编写和测试应用程序。
通过命令行中的 gradle 组装和发布到服务器。

问题

有谁知道这里的问题是什么,以及如何实际解决它?当我所做的一切都遇到异常或“是的,这是一个代码库错误”时,情况变得非常严重,因为两者都没有帮助。

任何帮助将不胜感激。

【问题讨论】:

    标签: java eclipse spring rmi event-listener


    【解决方案1】:

    实际答案

    好的,这既令人尴尬又让人放松。首先...

    好消息

    如上所述的侦听器接口有效。它在服务器端注册,并在调用时向客户端发出通知,然后客户端可能会采取相应的行动。因此,如果您一直在寻找整个“通过监听器”问题的答案,那么您就有了。

    坏消息

    然而,我对某些事实一无所知。除其他事项外,codebase 一词实际涵盖的内容。在我的特殊情况下,问题是缓存服务本身不依赖于其他项目,它应该保留哪些(自定义)类。所以从技术上讲,代码库实际上问题 - 由于在 build.gradle 中缺乏依赖关系。

    我希望我不会在此浪费任何人的时间,如果是这样,请接受我的道歉,希望这个问题在某个时候对其他人有所帮助。

    【讨论】:

    • 您的意思是“该类的用途是什么”或“该类已更改”?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-26
    • 2015-08-19
    • 2016-08-13
    • 1970-01-01
    相关资源
    最近更新 更多