Java GWT RequestFactory是否支持乐观并发控制的实现?
在GWT应用程序中,我提供用户可以编辑的项目。使用GWT请求工厂加载和保存项目。我现在想要实现的是,如果两个用户同时编辑一个条目,则首先保存的用户将以乐观并发控制的方式获胜。这意味着,当第二个用户保存其更改时,请求工厂后端会识别到存储在后端的项目的版本或存在已更改,因为它已传输到客户端,请求工厂/后端会以某种方式阻止项目更新/保存 我试图在用于保存项目的服务方法中实现这一点,但这不起作用,因为请求工厂将从后端检索的项目交给应用用户更改,这意味着这些项目的版本是来自后端的当前版本,比较没有意义 在请求工厂处理中是否有我可以利用的钩子来实现请求的行为?还有其他想法吗?或者我必须改用GWT-RPC吗…否: 在建议的API实现之前(Java GWT RequestFactory是否支持乐观并发控制的实现?,java,gwt,requestfactory,Java,Gwt,Requestfactory,在GWT应用程序中,我提供用户可以编辑的项目。使用GWT请求工厂加载和保存项目。我现在想要实现的是,如果两个用户同时编辑一个条目,则首先保存的用户将以乐观并发控制的方式获胜。这意味着,当第二个用户保存其更改时,请求工厂后端会识别到存储在后端的项目的版本或存在已更改,因为它已传输到客户端,请求工厂/后端会以某种方式阻止项目更新/保存 我试图在用于保存项目的服务方法中实现这一点,但这不起作用,因为请求工厂将从后端检索的项目交给应用用户更改,这意味着这些项目的版本是来自后端的当前版本,比较没有意义 在
EntityLocator
,在注释1中,但我不清楚如何从其序列化形式重建版本信息),您必须以某种方式将版本发送回服务器。正如我在本期中所说,这不能通过简单地在代理中提供version属性并设置它来实现;但是您可以添加另一个属性:获取它将始终返回
null
(或类似的不存在的值),这样在客户端将其设置为“true”版本属性的值将始终产生更改,从而保证该值将作为“property diff”的一部分发送到服务器;在服务器端,您可以在setter(当RequestFactory应用“property diff”并调用setter时,如果值与“true”版本不同,则抛出异常)或服务方法中处理事情(将从客户机发送的版本(从不同的getter获得的版本与映射到客户机上的版本不同,因为必须始终返回null
)与对象的“真实”版本进行比较,如果不匹配,则引发错误)
比如:
@ProxyFor(MyEntity.class)
interface MyEntityProxy extends EntityProxy {
String getServerVersion();
String getClientVersion();
void setClientVersion(String clientVersion);
…
}
@Entity
class MyEntity {
private String clientVersion;
@Version private String serverVersion;
public String getServerVersion() { return serverVersion; }
public String getClientVersion() { return null; }
public void setClientVersion(String clientVersion) {
this.clientVersion = clientVersion;
}
public void checkVersion() {
if (Objects.equal(serverVersion, clientVersion)) {
throw new OptimisticConcurrencyException();
}
}
}
请注意,我没有对此进行测试,这是纯理论。我们在应用程序中提出了另一种乐观锁定的解决方案。由于无法通过代理本身传递版本(),因此我们将通过HTTP GET参数将其传递给请求工厂 在客户机上:
MyRequestFactory factory = GWT.create( MyRequestFactory.class );
RequestTransport transport = new DefaultRequestTransport() {
@Override
public String getRequestUrl() {
return super.getRequestUrl() + "?version=" + getMyVersion();
}
};
factory.initialize(new SimpleEventBus(), transport);
在服务器上,我们创建一个ServiceLayerDecorator,并从RequestFactoryServlet.getThreadLocalRequest()
读取版本:
公共静态类myServiceLayerCorator扩展ServiceLayerCorator{
@凌驾
公共最终T loadDomainObject(最终类clazz,最终对象domainId){
HttpServletRequest threadLocalRequest=RequestFactoryServlet.getThreadLocalRequest();
字符串clientVersion=threadLocalRequest.getParameter(“version”);
T domainObject=super.loadDomainObject(clazz,domainId);
字符串serverVersion=((HasVersion)domainObject.getVersion();
if(versionMismatch(serverVersion,clientVersion))
报告(“版本错误!”);
返回域对象;
}
}
优点是在RF对域对象应用任何更改之前调用loadDomainObject()
在我们的例子中,我们只跟踪一个实体,所以我们使用一个版本,但这种方法可以扩展到多个实体。感谢指针和建议:)如果在使用我的解决方案之前,没有可用的解决方案,我将尝试此方法或报告中的组合id解决方法。还有很多与facebook相关的事情要做,所以这仍然需要相当长的时间:DLooks对我来说是一个非常好的解决方法。唯一需要解决的问题是自动查找要在客户端发送的实体版本。
public static class MyServiceLayerDecorator extends ServiceLayerDecorator {
@Override
public final <T> T loadDomainObject(final Class<T> clazz, final Object domainId) {
HttpServletRequest threadLocalRequest = RequestFactoryServlet.getThreadLocalRequest();
String clientVersion = threadLocalRequest.getParameter("version") );
T domainObject = super.loadDomainObject(clazz, domainId);
String serverVersion = ((HasVersion)domainObject).getVersion();
if ( versionMismatch(serverVersion, clientVersion) )
report("Version error!");
return domainObject;
}
}