【问题标题】:Request Factory GWT editor change isn't persisting related JDO entities请求工厂 GWT 编辑器更改未保留相关的 JDO 实体
【发布时间】:2012-12-12 01:15:10
【问题描述】:

我在 GWT 2.5 中使用(并且是新手)RequestFactory,在 AppEngine 数据存储区中,JDO 实体具有一对多关系。我刚刚开始使用 GWT RequestFactoryEditorDriver 来显示/编辑我的对象。

驱动程序可以很好地遍历我的对象,并正确显示它们。但是,当我尝试编辑“相关”对象上的值时,更改不会持久保存到数据存储区。

当我在 UI 上更改 b.name 并单击“保存”时,我注意到只调用了 A 的 persist() 调用。 B 的 persist() 永远不会被调用。如何让 editorDriver 在 ARequest 和 BRequest 请求上下文中触发? (因为我想要的是在我的编辑仅针对 B 对象时调用 B 的 InstanceRequest<AProxy,Void> persist()。)

另外,AFAICT,如果我在 BProxy 上有一个编辑器,那么编辑器(并遵循编辑器合同)显示的任何对象 b 都应该由驱动程序自动“context.edit(b)”来制作它可变的。但是,在我的情况下,“上下文”是 ARequest,而不是 BRequest。

我是否必须像这里提到的那样制作一个 ValueAwareEditor:GWT Editor framework 并在 flush() 调用中创建一个新的 BRequest 并触发它,以便在触发 ARequest 之前对 B 的更改单独保留在 BRequest 中?

editorDriver.getPaths() 给我: “bs”

此外,驱动程序肯定会看到 B 属性的更改,因为 editorDriver.isChanged() 在我 fire() 上下文之前返回 true。

我的客户端或服务器端日志中没有错误,并且注释处理器运行时没有警告。

以下是我设置驱动程序的方法:

editorDriver = GWT.create(Driver.class);
editorDriver.initialize(rf, view.getAEditor());

final ARequest aRequest = rf.ARequest();
        final Request<List<AProxy>> aRequest = aRequest.findAByUser(loginInfo.getUserId());
        String[] paths = editorDriver.getPaths();
        aRequest.with(paths).fire(new Receiver<List<AProxy>>() {

            @Override
            public void onSuccess(List<AProxy> response) {
                AProxy a = response.get(0);
                ARequest aRequest2 = rf.aRequest();
                editorDriver.edit(a, aRequest2);
                aRequest2.persist().using(a);
            }
        });

这是我的实体的外观:

public abstract class PersistentEntity {
    public Void persist() {
        PersistenceManager pm = getPersistenceManager();
        try {
            pm.makePersistent(this);
        } finally {
          pm.close();
        }
        return null;
    }


    public Void remove() {
        PersistenceManager pm = getPersistenceManager();
        try {
            pm.deletePersistent(this);
        } finally {
          pm.close();
        }
        return null;
    }
}

@PersistenceCapable(identityType = IdentityType.APPLICATION)
@Version(strategy=VersionStrategy.VERSION_NUMBER, column="VERSION",
         extensions={@Extension(vendorName="datanucleus", key="field-name", value="version")})

public class A extends PersistentEntity {

        ... (Id, version omitted for brevity)
    @Persistent
    private String name;

        @Persistent
        private List<B> bs;

    public String getName() {
        return name;
    }

        ...

    public void setName(String name) {
        this.name = name;
    }

    public List<B> getBs() {
        return bs;
    }

    public void setBs(List<B> bs) {
        this.bs = bs;
    }

}

... (same annotations as above omitted for brevity)

public class B extends PersistentEntity {

        ... (Id, version omitted for brevity)
    @Persistent
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

这里是代理:

@ProxyFor(A.class)
public interface AProxy extends EntityProxy {
    String getName();
    List<BProxy> getBs();
    void setName(String name);
    void setBs(List<BProxy> bs);
}

@ProxyFor(B.class)
public interface BProxy extends EntityProxy {
    String getName();
    void setName(String name);
}

这是我的服务存根:

@Service(A.class)
public interface ARequest extends RequestContext {

    Request<List<A>> findAByUser(String userId);

    InstanceRequest<AProxy, Void> persist();
    InstanceRequest<AProxy, Void> remove();
}

@Service(B.class)
public interface BRequest extends RequestContext {

    Request<List<A>> findB(String key);

    InstanceRequest<BProxy, Void> persist();
    InstanceRequest<BProxy, Void> remove();
}

编辑: 我现在更改了我的 ARequest 接口和服务实现以支持“saveAndReturn”方法,这样我就可以在服务器端递归地“持久化”“a”:

Request<UserSandboxProxy> saveAndReturn(AProxy aProxy);

我现在发现,当我“刷新”我的 RequestFactoryEditorDriver 时,客户端上下文对象具有我的新“b.name”值。但是,如果我调用“context.fire()”并在服务器端检查我的“saveAndReturn”方法,则生成的服务器端对象“a”,就在我“持久化”它之前,不包含对“ b.name”在列表的任何项目上。

为什么会发生这种情况?我如何调试为什么这个客户端信息不通过线路到达服务器?

我考虑、尝试和排除的选项:

1) 确保 APT 已运行,并且代理或服务接口上没有警告/错误

2) 确保我的代理在列表的 AProxy 中确实有一个有效的设置器

【问题讨论】:

  • 您使用的是 OpenSessionInView(又名 session-per-request)模式吗?对于 JDO,这意味着一个 PersistenceManager 跨越整个 HTTP 请求。
  • @ThomasBroyer 不,我不是。现在,我有这个方法:private static PersistenceManager getPM() { return JDOHelper.getPersistenceManagerFactory("transactions-optional").getPersistenceManager(); } 我为每个 DAO 操作调用它,例如“persist()”等,并在操作结束后立即 pm.close()。但是无论“persist()”是否正确完成,我至少不应该在调试时看到我的服务器端(pre-persist)obj有我的更改值吗?这对我是否使用 OSIV 有何影响?我从新加载的应用程序中尝试了“a.name”和“b.name”操作的设置。

标签: google-app-engine gwt one-to-many requestfactory gwt-editors


【解决方案1】:

必须使用每个请求的会话模式,RequestFactory 才能正常工作。更多细节在这里:https://code.google.com/p/google-web-toolkit/issues/detail?id=7827

【讨论】:

  • 太棒了!非常感谢,托马斯!我终于使用 Guice 和 PersistenceManager 的 RequestScoped 实例来实现这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-26
  • 2012-03-14
  • 1970-01-01
相关资源
最近更新 更多