【问题标题】:How can I use RequestFactory to create an object and initialize a collection whithin it with objects retrieved from another ReqFactory?如何使用 RequestFactory 创建一个对象并使用从另一个 ReqFactory 检索到的对象初始化一个集合?
【发布时间】:2011-06-28 17:42:23
【问题描述】:

我正在努力解决在 GWT 中使用 RequestFactory 的问题。 我有一个用户对象:这个对象有登录和密码字段以及其他集合类型的字段。

public class User {
    private String login;
    private String password;
    private Set<Ressource> ressources;

    // Getters and setters removed for brievety
} 

我需要将这个对象保存在数据库中,所以我使用了 RequestFactory,因为它对我来说似乎是一个 CRUD 类型的操作。

现在对于代码的 RequestFactory 部分,我尝试这样做:

  1. 我创建一个 UserRequestContext 对象来为新用户创建一个请求对象。这给出了类似的东西:

    public interface MyRequestFactory extends RequestFactory {
        UserRequestContext userRequestContext();
        RessourceRequestContext ressourceRequestContext();
    }
    

    为了创建用户对象,我有这样的东西:

    public class UserAddScreen extends Composite {
        private UserProxy userProxy;
        EventBus eventBus = new SimpleEventBus();
        MyRequestFactory requestFactory = GWT.create(MyRequestFactory.class);
        ...
    
        public UserAddScreen() {
            ...
            requestFactory.initialize(eventBus);
        }
    
        public showUserAddScreen() {
            // Textbox for password and login
            // Listbox for ressources
        }
    
    }
    

我已经尝试将它作为一个向导来实现。所以在 UserAddScreen 的开头,我有一个 一个用户代理对象。 此对象字段在向导的每一步都被初始化:

  • 第一步是添加登录名和密码
  • 第二步是向 userProxy 对象添加资源。

对于最后一步,我有两个列表框,第一个列表框包含我从 RessourceRequestContext.getAllRessource 获得的数据库表 Ressources 中的所有资源列表(我有一个循环将它们显示为列表框项RessourceId 作为值),第二个允许我从第一个列表框中添加选定的资源。这是第一个列表框:

    final ListBox userRessourcesListBox = new ListBox(true);
    Receiver<List<RessourceProxy>> receiver = new Receiver<List<RessourceProxy>>() {

        @Override
        public void onSuccess(List<RessourceProxy> response) {
            for(RessourceProxy ressourceProxy : response) {
                ressourcesListBox.addItem(ressourceProxy.getNom() + " " + ressourceProxy.getPrenom(), String.valueOf(ressourceProxy.getId()));
            }
        }
    };
    RessourceRequestContext request = requestFactory.ressourceRequestContext();
    request.getAllRessource().fire(receiver);

因此,如您所见,我的代码循环遍历从 DB 检索到的代理并初始化列表框中的项目。

这里是控制按钮:

final Button addButton = new Button(">");
    addButton.addClickHandler(new ClickHandler() {

        public void onClick(ClickEvent event) {
            for (int i = 0; i < ressourcesListBox.getItemCount(); i++) {
                boolean foundInUserRessources = false;
                if (ressourcesListBox.isItemSelected(i)) {
                    for (int j = 0; j < userRessourcesListBox
                            .getItemCount(); j++) {
                        if (ressourcesListBox.getValue(i).equals(
                                userRessourcesListBox.getValue(j)))
                            foundInUserRessources = true;
                    }

                    if (foundInUserRessources == false)
                        userRessourcesListBox.addItem(ressourcesListBox
                                .getItemText(i), ressourcesListBox
                                .getValue(i));
                }
            }
        }
    });

因此,当有人选择一个或多个用户并单击“>”按钮时,所有选定的项目都会转到名为 userRessourceListBox 的第二个列表框

userRessourcesListBox.setWidth("350px");
    userRessourcesListBox.setHeight("180px");

之后,我有一个 FINISH 按钮,它循环遍历第二个列表框中的项目(这是我从第一个列表框中选择的项目),然后我尝试(再次)使用 RequestFactory 发出请求以检索 ressourceProxy对象并使用结果初始化 userProxy 资源集合

final Button nextButton = new Button("Finish");

    nextButton.addClickHandler(new ClickHandler() {

        public void onClick(ClickEvent event) {
            RessourceRequestContext request = requestFactory.ressourceRequestContext();
            for(int i = 0; i < userRessourcesListBox.getItemCount(); i++) {
                Receiver<RessourceProxy> receiver = new Receiver<RessourceProxy>() {
                    @Override
                    public void onSuccess(RessourceProxy response) {
                        userProxy.getRessource().add(response);
                    }
                };
                request.find(Long.parseLong(userRessourcesListBox.getValue(i))).fire(receiver);
            }
              creationRequest.save(newUserProxy).fire(new Receiver<Void>() {

                @Override
                public void onSuccess(Void response) {
                    Window.alert("Saved");
                }
            });
        }

    });

最后,(在上面的代码中)我尝试保存 UserProxy 对象(使用我创建 userProxy 的初始请求上下文)...但它不起作用

creationRequest.save(newUserProxy).fire(...)

似乎在 onSuccess 方法中循环结果时:

userProxy.getRessource().add(response);

我检索响应(类型为 RessourceProxy)但超出此方法,例如当我尝试在循环后保存 userProxy 对象时,userProxy 的 ressourceProxy 集合中没有 RessourceProxy 对象...

你们有过这样的经历吗? 也许我做得不对:我是否必须使用 UserRequestContext 获取资源?以便我的 newUser 对象和资源由相同的请求上下文管理? 如果是,那么我认为将某些东西混合在一起有点奇怪:我的意思是在与用户相关的请求上下文中进行与资源相关的操作有什么好处。

任何帮助都会真的很......我的意思是真的很感激;-) 非常感谢

【问题讨论】:

    标签: gwt collections persistence requestfactory


    【解决方案1】:

    消息“...已被冻结”表示对象已被 edit()ed 或作为参数传递给服务方法,在另一个 RequestContext 实例中(无论它是否属于同一个子-type –i.e. UserRequestContext vs. RessourceRequestContext– 还不是fire()d 和/或响应尚未从服务器返回(或者它返回违规:当接收者的onViolation 被调用,对象仍然是可编辑的,与onSuccessonFailure相反)。

    更新:你有一个竞争条件:你循环资源 ID 并产生与用户选择的项目数量一样多的请求,然后,无需等待他们的响应(请记住:这都是异步的),您保存用户代理。只要您fire() 发出最后一个请求,用户代理就不再是可变的(即冻结)。

    IMO,您最好保留最初检索到的 RessourceProxys 并在保存之前直接在用户代理中使用它们(即在“完成”阶段不再有 find() 请求)。通过 ID 将它们放入地图中,然后从地图中获取它们,而不是再次从服务器finding 将它们返回。

    【讨论】:

    • 其实我觉得我的解释不好。所以会尽量提供一个更简洁的。我将编辑问题以提供更多解释。
    • 非常感谢您的帮助 Thomas,我认为您是对的...我几乎可以肯定这是并发异步请求的问题,但不知道如何处理,所以谢谢同时,我也尝试过用另一种方式来实现。我没有循环,而是设法通过一次性异步请求从 DB 中获取所有内容。然后,我可以确定在进一步编写如下代码时一切都已初始化:request.getRessourcesById(ids).fire(receiver);知道 ids 是 id 的数组列表,响应是 Object 的列表。它有效,但可能有点脏
    猜你喜欢
    • 2017-01-16
    • 1970-01-01
    • 1970-01-01
    • 2022-11-20
    • 1970-01-01
    • 2016-12-18
    • 2016-05-30
    • 2015-03-19
    • 1970-01-01
    相关资源
    最近更新 更多