У меня есть приложение, которое предоставляет сервис через механизм Spring RMI proxy , Существует проблема, из-за которой иногда «сообщение» на файловом сервере, на котором хранятся его JAR-файлы, заставляет вызов передавать NoClassDefFoundError
обратно вызывающей стороне.
Пока что это достаточно справедливо. Дело в том, что я хотел бы, чтобы мое приложение просто аварийно завершало работу, если это происходит, то есть если ошибка
будет передана обратно вызывающей стороне.
Обратите внимание, что у меня уже есть UncaughtExceptionHandler
в приложении, и это не вызывается (потому что исключение не является на самом деле необработанным )
Если вы предоставляете службу RMI через RmiServiceExporter
(или любой другой подкласс RemoteExporter
), то вы можете вводить произвольные перехватчики в стек вызовов, которые будут вызываться всякий раз, когда вызывается служба RMI.
Эти перехватчики могут перехватывать любую сгенерированную ошибку NoClassDefFoundError
и вызывать System.exit()
.
Например:
public class ExitInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
try {
return methodInvocation.proceed();
} catch (NoClassDefFoundError noClassDefFoundError) {
noClassDefFoundError.printStackTrace();
System.exit(1);
return null;
}
}
}
и
<bean id="exporter" class="org.springframework.remoting.rmi.RmiServiceExporter">
<!-- existing properties -->
<property name="interceptors">
<bean class="com.x.ExitInterceptor"/>
<property>
</bean>
Что вы можете сделать, так это расширить [RmiServiceExporter][1]
и обработать исключение в методе invoke
. Это можно сделать следующим образом
public class AutoFailRmiServiceExporter extends RmiProxyFactoryBean implements ApplicationContextAware {
private ApplicationContext ac;
@override
public Object invoke(RemoteInvocation invocation,
Object targetObject)
throws NoSuchMethodException,
IllegalAccessException,
InvocationTargetException {
try {
super.invoke(methodInvocation, target);
} catch (NoClassDefFoundError e) {
if {ac instanceof ConfigurableApplicationContext) {
(ConfigurableApplicationContext)ac).close();
else {
//log error
}
}
}
//application context setter
}
. Затем вы должны использовать свою версию AutoFail RmiServiceExporter при определении службы rmi в контексте весны.
РЕДАКТИРОВАТЬ: Исходный ответ показал способ убить клиента при возникновении исключения. Это делается путем создания подкласса RmiProxyFactorty и переопределения doInvoke вместо RmiServiceExporter.