【问题标题】:GWT RequestFactory STRANGE behavior : No error reportingGWT RequestFactory 奇怪的行为:没有错误报告
【发布时间】:2012-07-27 13:41:58
【问题描述】:

我确实有问题,但我不知道会发生什么... GWT 初学者,从事个人项目。

环境:

  • ma​​ven 项目,包含两个模块

    • 一个模块是'model',具有HibernateHSQLDBSpring依赖. HSQLDB 运行嵌入式,在内存中,从 spring applicationContext.xml 配置

    • 另一个模块是“网络”,并具有所有 GWT 依赖项

该应用程序是使用一些 Spring Roo 生成的代码作为基础构建的,随后进行了修改和扩展。

问题是,当编辑某些实体字段并按下保存时,什么也没有发生。创建新实体实例时没有问题,仅在编辑时更改某些字段并按“保存”基本上会覆盖新值。 所以我开始彻底调试客户端代码,启用休眠和 Spring 详细日志记录,但仍然......什么都没有。

然后我做了一个(对我来说)令人惊讶的发现。 检查 GWT 响应负载,我看到了这个:

    {"S":[false],"O":        [{"T":"663_uruC_g7F5h5IXBGvTP3BBKM=","V":"MS4w","S":"IjMi","O":"UPDATE"}],"I":[{"F":true,"M":"Server Error: org.hibernate.PersistentObjectException: detached entity passed to persist: com.myvdm.server.domain.Document; nested exception is javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: com.myvdm.server.domain.Document"}]}  

啊哈,分离的实体传递给坚持! 请注意gwt客户端代码使用这个sn-p调用服务:

requestContext.persist().using(proxy);

可以说这可能会触发异常,调用 merge() 可以解决问题,但是,请继续阅读问题 3...

现在出现三个问题:

  • 为什么不以某种方式将其作为错误/异常发送给客户端?
  • 为什么 Hibernate 不记录这个?
  • 为什么 Spring Roo 生成的代码(如我所说,用作基础)没有表现出这个问题?

非常感谢,

寻求一些意见/建议。


在 T. BROYER 的回应后编辑::

您好 Thomas,感谢您的回复。

我有一个实现 RequestTransport 和 send() 的自定义类。这就是我收集响应负载的方式。实现如下::

public void send(String payload, final TransportReceiver receiver) {
    TransportReceiver myReceiver = new TransportReceiver() {

        @Override
        public void onTransportSuccess(String payload) {
            try {
                receiver.onTransportSuccess(payload);
            } finally {
                eventBus.fireEvent(new RequestEvent(RequestEvent.State.RECEIVED));
            }
        }

        @Override
        public void onTransportFailure(ServerFailure failure) {
            try {
                receiver.onTransportFailure(failure);
            } finally {
                eventBus.fireEvent(new RequestEvent(RequestEvent.State.RECEIVED));
            }
        }
    };

    try {
        wrapped.send(payload, myReceiver);
    } finally {
        eventBus.fireEvent(new RequestEvent(RequestEvent.State.SENT));
    }
}

这是在编辑模式下单击“保存”按钮时执行的代码:

RequestContext requestContext = editorDriver.flush();
    if (editorDriver.hasErrors()) {
        return;
    }

    requestContext.fire(new Receiver<Void>() {
        @Override
        public void onFailure(ServerFailure error) {
            if (editorDriver != null) {
                setWaiting(false);
                super.onFailure(error);
            }
        }

        @Override
        public void onSuccess(Void ignore) {
            if (editorDriver != null) {
                editorDriver = null;
                exit(true);
            }
        }

        @Override
        public void onConstraintViolation(Set<ConstraintViolation<?>> errors) {
            if (editorDriver != null) {
                setWaiting(false);
                editorDriver.setConstraintViolations(errors);
            }
        }
    });

根据你说的,应该调用onSuccess(),而且是调用

那么我如何准确地隔离造成问题的代码呢?我有这个方法可以创建一个新的请求上下文以持久化对象

        @Override
        protected RequestContext createSaveRequestContextFor(DocumentProxy proxy) {
            DocumentRequestContext request = requests.documentRequestContext();
            request.persist().using(proxy);
            return request;
        }

这就是它的名称::

 editorDriver.edit(getProxy(), createSaveRequestContextFor(getProxy()));

至于 Spring 问题,您是说在两个后续请求 find() 和 persist() 之间,不应关闭 JPA entityManager。我仍在调查此问题,但在按下编辑按钮后,我看到消息“org.springframework.orm.jpa.EntityManagerFactoryUtils - Closing JPA EntityManager”,这是不对的,可能没有应用 @Transactional 注释...

【问题讨论】:

    标签: spring hibernate gwt hsqldb requestfactory


    【解决方案1】:

    为什么不以某种方式将其作为错误/异常发送给客户端?

    是的。 "S": [false] 表示第一个(也是唯一一个)方法调用(请记住,RequestContext 是一个批处理!)失败。调用的ReceiveronFailure 方法将被调用。

    ServerFailure 中的"F": true 表示这是一个致命 错误,因此Receiver#onFailure 的默认实现会抛出RuntimeException。但是,由于您根本不使用 Receiver,因此不会发生任何事情,并且会默默地忽略错误。

    请注意,批处理请求本身已成功,因此全局 Receiver(您将传递给 RequestContext#fire 的那个)将调用其 onSuccess 方法。
    另请注意,Request#fire(Receiver)Request#to(Receiver) 后跟 RequestContext#fire() 的简写(没有参数)。

    为什么 Hibernate 不记录这个?

    这个我不知道,抱歉。

    为什么 Spring Roo 生成的代码(如我所说,用作基础)没有表现出这个问题?

    好的,我们来探究异常的根本原因:实体是由您的Locator(或实体类的findXxx静态方法)加载的,然后在实例上调用persist方法。如果您没有在 findpersist 方法中使用相同的 JPA EntityManager / Hibernate 会话,那么您将遇到问题。
    Request Factory 希望您使用 open session in view 模式来克服这个问题。不幸的是,我不知道 Spring Roo 生成什么样的代码。

    【讨论】:

      【解决方案2】:

      关于 Thomas 提到的 open session in view 模式,只需将此过滤器定义添加到您的 web.xml 即可在您的 Spring 应用程序中打开该模式:

      <filter>
          <filter-name>
              Spring OpenEntityManagerInViewFilter
          </filter-name>
          <filter-class>
               org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
          </filter-class>
      </filter>
      <filter-mapping>
          <filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
          <url-pattern>/*</url-pattern>
      </filter-mapping>
      

      【讨论】:

      • 对了,谢谢Ümit,我找到了问题,而且是因为一些格式错误的配置文件...但是,一个问题仍然悬而未决,为什么Hibernate没有报告任何错误?在这样的事情上,我肯定会看到堆栈跟踪...
      • 我不记得 100% 但是我有一个类似的设置 Hibernate + JPA2 + Requestfactory 当我遇到这个问题时,我相信保存方法中抛出了一个异常,我让它登录了GWT 的控制台。不确定我的 Spring 应用是否也记录了它。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-24
      • 1970-01-01
      相关资源
      最近更新 更多