如何使用RequestFactory创建一个对象并使用从另一个ReqFactory检索的对象初始化一个集合?

时间:2011-06-26 12:16:40

标签: gwt collections persistence requestfactory

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

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

    // Getters and setters removed for brievety
} 

我需要在db中保留这个对象,所以我使用了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
        }
    
    }
    
  2. 我尝试将其作为向导实现。所以在UserAddScreen的开头,我有一个 userProxy对象。 此对象字段在向导的每个步骤初始化:

    • 第一步是添加登录名和密码
    • 第二步是将ressources添加到userProxy对象。

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

        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));
                    }
                }
            }
        });
    

    所以当有人选择一个或多个用户并点击“&gt;”时按钮,所有选定的项目将转到名为userRessourceListBox

    的第二个列表框
    userRessourcesListBox.setWidth("350px");
        userRessourcesListBox.setHeight("180px");
    

    之后,我有一个FINISH按钮,循环遍历第二个列表框中的项目(这是我从第一个列表框中选择的项目),我尝试使用RequestFactory(再次)请求检索ressourceProxy使用结果

    对象并初始化userProxy ressources集合
    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获取ressource?以便我的newUser对象和资源由相同的请求上下文管理? 如果是,那么我认为将某些东西混合在一起有点奇怪:我的意思是在用户相关的请求上下文中使用与资源相关的操作有什么好处。

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

1 个答案:

答案 0 :(得分:0)

消息“...已被冻结”表示该对象已被edit()编辑或作为参数传递给另一个RequestContext实例中的服务方法(无论是否为相同的子类型-ie UserRequestContextRessourceRequestContext - 或不是)尚未fire() d和/或响应尚未从服务器返回(或者它带有违规行为:当调用接收者的onViolation时,对象仍然可以编辑,与onSuccessonFailure相反。

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

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