RequestFactoryEditorDriver在刷新后获取编辑后的数据

问题描述:

让我从我有一个解决方案开始,但我并不认为它很优雅。所以,我正在寻找更干净的方式来做到这一点。RequestFactoryEditorDriver在刷新后获取编辑后的数据

我有一个EntityProxy显示在视图面板中。视图面板是一个只使用显示模式的RequestFactoryEditorDriver。用户点击一个数据元素并打开一个弹出编辑器来编辑EntityProxy的一个数据元素,其数据位数比查看面板中显示的少一些。当用户保存元素时,我需要查看面板来更新显示。

我遇到了一个问题,因为弹出式编辑器流程的RequestFactoryEditorDriver不允许您访问编辑的数据。驱动程序使用上下文中用于发送服务器数据的上下文,但即使将其转换为edit()调用中存储在编辑器驱动程序中的上下文类型,上下文仅允许使用Receiver<Void> 。 [它似乎没有发送和EntityProxyChanged事件,所以我无法听取它并更新显示视图。 - 从头开始​​ - 我现在看到这个事件不是针对这个用例的]

我找到的解决方案是改变我的域对象,坚持返回新保存的实体。然后,像这样创建

editor.getSaveButtonClickHandler().addClickHandler(createSaveHandler(driver, editor)); 
       // initialize the Driver and edit the given text. 
       driver.initialize(rf, editor); 
       PlayerProfileCtx ctx = rf.playerProfile(); 
       ctx.persist().using(playerProfile).with(driver.getPaths())      
         .to(new Receiver<PlayerProfileProxy>(){ 
        @Override 
        public void onSuccess(PlayerProfileProxy profile) { 
         editor.hide(); 
         playerProfile = profile; 
         viewDriver.display(playerProfile); 
        }        
       }); 
       driver.edit(playerProfile, ctx); 
       editor.centerAndShow(); 

弹出的编辑器然后在保存处理我只是火()的情况下,我从冲洗得到()。虽然这种方法有效,但看起来并不正确。 [似乎我应该在显示视图中订阅entitychanged事件,并从那里更新实体和视图。 - 再次从头开始,与之前的原因相同]这种方法也保存完整的实体,而不仅仅是改变的位,这将增加带宽使用。

我认为应该发生的事情是,当你刷新实体时,它应该'乐观地'更新实体的射频管理版本并触发实体代理更改的事件。只有在保存中出现问题时才能恢复实体。实际的保存应该只发送更改的位。以这种方式,不需要重新提取整个实体并通过电线两次发送完整的数据。

有没有更好的解决方案?

我找到了一个更好的解决方案。在调用RequestFactoryEditorDriver edit()并将可编辑代理保存为我的视图代理之前,我使代理可编辑。

PlayerProfileCtx ctx = rf.playerProfile(); 
playerProfile = ctx.edit(playerProfile); 
driver.edit(playerProfile, ctx); 

另外,(我想我以前曾试图这样做,它没有工作,但我一定是做错了什么事,然后)我可以投的是来自于回冲的上下文。这与我拨打edit()调用的驱动程序相同,因此它很安全。

PlayerProfileCtx ctx = (PlayerProfileCtx) driver.flush(); 

这样做解决了rf用fire()发送整个对象而不仅仅是diff的问题。我不知道为什么。这可能是RF Editor Driver中的一个错误。

所以现在我已经从视图中获得了驱动程序的数据,并且不必依赖从服务器发回它。但是我注册了EntityProxyChange事件,所以如果服务器发生冲突,我可以检测并重新获取。

你似乎并没有真正理解RF的细节;另外,你的术语并没有真正帮助理解(冲水与火灾)。

RF中的代理服务器是您检索服务器时的状态快照。您可以通过其他代理服务器中的其他位置对实体进行任何操作,但您的代理服务器永远不会改变以反映这些修改。

EntityProxyChange事件在服务器检测到它已更改时在客户端(对于服务器已知且已从客户端发送的实体)调度:其版本(由getVersionLocator)已经改变,或者它已被删除(如LocatorisLive方法所述)。如果您不使用Locator,它将使用实体的getVersion,并且isLive将被find替换为实体的ID(由其getId方法返回)并检查null(这也是默认实现的isLiveLocator)。
就你而言,如果你没有看到EntityProxyChange被调度,那么检查你是否正确地更新了实体的版本。

最后,RF总是将您的更改差异发送到服务器(ValueProxy除外,在这种情况下差异无意义)。至于检索数据,默认情况下它不会检索链接的代理,除非您明确要求使用with;这与您可能发送的实体无关。

你的情况,更新视图面板,你有3种可能性:

  • 从服务器获取代理回(听EntityProxyChange事件或从弹出一个明确的信号之后,你可以使用find方法RequestContext与代理的stableId作为参数,适当的with为您需要的属性)。
    由于您正在执行第二个HTTP请求,它有点低效,但另一方面它可以处理来自应用程序中其他地方的更改(它们也会触发EntityProxyChange事件)
  • 在相同的HTTP中检索更新后的代理请求作为您用来保存的请求:请求您的请求上下文的save方法返回已保存的实体,或者在相同的HTTP请求中将同一请求上下文中的find方法调用批次,savefind
    这就是你所做的。它发送更改的差异并检索您的视图面板所需的属性。人们可以说它有弹性和视图面板紧密耦合的缺点,这取决于你是否可以接受的权衡。
  • 使用您编辑的实体并将其发送到您的视图面板中的服务器,并且没有额外的数据。
    虽然这看起来更简单,但您会错过其他用户可能对该实体进行的任何更改(仅更改已知的服务器)。

总而言之,我想我会采用目前的解决方案。关于你的代码,我想启动带代理和回调的弹出窗口,并将请求上下文和编辑编辑器驱动程序作为弹出窗口的实现细节:只需要它在完成时调用视图面板,将更新后的代理作为参数传递给回调函数。

有关术语的最后一句话:你刷新编辑司机到字段的值复制回对象/代理,和(独立,但如果连续的),你发送批请求上下文的服务方法和对服务器的代理更改。刷新编辑器驱动程序不会向服务器发送任何内容,这些都是不同的操作。

+0

感谢您的回答,但我不确定您认为我在哪里混合冲水和火灾。我完全按照你所描述的使用它们。同样在RequestFactoryEditorDriver中,flush会返回你初始化它的rf上下文,而不是被编辑的对象,这会阻止你的第三个选项成为可能(除非有一些存取程序找不到)。同时查看发送的http请求,整个实体将被发送到服务器,而不仅仅是增量 - 这与rf的记录方式不同。并且,当您为EntityProxyChange事件提供的条件是什么条件时... – Deanna 2012-03-20 18:09:37

+0

我已经考虑过您的选项1,但正如您所指出的那样,它是对服务器的额外往返。我曾使用过选项2,但由于它不发送差异,因此无法按预期工作。在这个过程开始之前,实体已经存在于服务器上,并进入视图面板。这是我在示例代码中引用的playerProfile。我使用它来初始化RequestFactoryEditorDriver,所以当驱动程序刷新和/或要更新的原始代理时,我希望事件触发(事件总线触发不是rf)。我错过了阻止这些事情的东西吗? – Deanna 2012-03-20 18:16:19

+0

另外,我没有完全理解entityproxy的用例,它只是抓取它时的快照。那你是对的。我认为这是一个更实用的功能,如实体的远程/客户端副本,如果我从服务器中获取同一实体的新副本并发送entityproxychange事件,则会更新该实体。 – Deanna 2012-03-20 18:22:59