Spring Remoting HTTP 调用程序 - 异常处理

标签 spring spring-remoting

我正在使用Spring's 'HTTP Invoker' remoting solution将 DAO 公开给许多不同的应用程序,但在单个服务器中拥有所有数据库访问权限。

这工作得很好,但是如果服务器抛出 HibernateSystemException,Spring 会序列化它并通过线路将其发送回客户端。这不起作用,因为客户端在其类路径中没有(也不应该)有 HibernateSystemException。

是否有一种方法可以让 Spring Remoting 将我的异常包装在我指定的客户端和服务器之间常见的内容中,以避免出现此类问题?

我知道我可以在我的服务器代码中通过将 DAO 所做的所有事情包装在 try/catch 中来做到这一点,但这无疑是草率的。

谢谢, 罗伊

最佳答案

我也遇到了这个问题;我通过 HTTP Invoker 公开一个服务,该服务使用 Spring 3.1、JPA 2 和 Hibernate 作为 JPA 提供程序来访问数据库。

为了解决这个问题,我编写了一个自定义拦截器和一个名为 WrappedException 的异常。拦截器捕获服务抛出的异常,并使用反射和 setter 将异常和原因转换为 WrappedException。假设客户端在其类路径上有 WrappedException,则堆栈跟踪和原始异常类名对客户端是可见的。

这减轻了客户端在其类路径上放置 Spring DAO 的需要,并且据我所知,在转换过程中没有丢失任何原始堆栈跟踪信息。

拦截器

public class ServiceExceptionTranslatorInterceptor implements MethodInterceptor, Serializable {

    private static final long serialVersionUID = 1L;

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        try {
            return invocation.proceed();
        } catch (Throwable e) {
            throw translateException(e);
        }
    }

    static RuntimeException translateException(Throwable e) {
        WrappedException serviceException = new WrappedException();

        try {
            serviceException.setStackTrace(e.getStackTrace());
            serviceException.setMessage(e.getClass().getName() +
                    ": " + e.getMessage());
            getField(Throwable.class, "detailMessage").set(serviceException, 
                    e.getMessage());
            Throwable cause = e.getCause();
            if (cause != null) {
                getField(Throwable.class, "cause").set(serviceException,
                        translateException(cause));
            }
        } catch (IllegalArgumentException e1) {
            // Should never happen, ServiceException is an instance of Throwable
        } catch (IllegalAccessException e2) {
            // Should never happen, we've set the fields to accessible
        } catch (NoSuchFieldException e3) {
            // Should never happen, we know 'detailMessage' and 'cause' are
            // valid fields
        }
        return serviceException;
    }

    static Field getField(Class<?> clazz, String fieldName) throws NoSuchFieldException {
        Field f = clazz.getDeclaredField(fieldName);
        if (!f.isAccessible()) {
            f.setAccessible(true);
        }
        return f;
    }

}

异常

public class WrappedException extends RuntimeException {

    private static final long serialVersionUID = 1L;

    private String message = null;

    public void setMessage(String message) {
        this.message = message;
    }

    @Override
    public String toString() {
        return message;
    }
}

Bean 接线

<bean id="exceptionTranslatorInterceptor" class="com.YOURCOMPANY.interceptor.ServiceExceptionTranslatorInterceptor"/>

<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
    <property name="beanNames" value="YOUR_SERVICE" />
    <property name="order" value="1" />
    <property name="interceptorNames">
        <list>
            <value>exceptionTranslatorInterceptor</value>
        </list>
    </property>
</bean>

关于Spring Remoting HTTP 调用程序 - 异常处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9668420/

相关文章:

spring - Spring 交易中的一个连接?

java - FTPSClient 抛出异常 javax.net.ssl.SSLHandshakeException : Remote host closed connection during handshake

java - 在 @ResponseStatus 中使用多个值 HttpStatus

spring - RMI 服务导出器和 HttpInvoker 之间的区别?

tomcat - spring hessian 客户端套接字连接重置

java - Spring Boot REST API - 请求超时?

java - Groovy - 集成测试

java - 无法反序列化 HTTP 调用程序远程服务的结果 [...];嵌套异常是 java.lang.ClassNotFoundException :

java - Spring Remoting - HTTP 调用者