Как я могу получить Spring для фатального выхода, если ошибка распространяется из удаленного вызова - PullRequest
1 голос
/ 27 августа 2010

У меня есть приложение, которое предоставляет сервис через механизм Spring * RMI RMI proxy. Существует проблема, из-за которой иногда «сообщение» на файловом сервере, на котором хранятся его JAR-файлы, приводит к вызову для передачи NoClassDefFoundError обратно вызывающей стороне.

Пока все достаточно честно. Дело в том, что я хотел бы, чтобы мое приложение просто зависало, если это произойдет - то есть, если Error будет передано обратно вызывающей стороне.

Обратите внимание, что у меня уже есть UncaughtExceptionHandler в приложении, и оно не вызывается (поскольку на самом деле исключение не uncaught )

Ответы [ 2 ]

1 голос
/ 27 августа 2010

Что вы можете сделать, это расширить [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

}

Затем вы будете использовать версию RmiServiceExporter с AutoFail при определении службы rmi в контексте Spring.

РЕДАКТИРОВАТЬ: Оригинальный ответ показал способ убить клиента, когда выдается исключение. Это делается путем создания подкласса RmiProxyFactorty и переопределения doInvoke вместо RmiServiceExporter.

1 голос
/ 27 августа 2010

Если вы предоставляете сервис 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>
...