0

我正在努力解决在 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 对象。此对象字段在向导的每一步都被初始化:

  • 第一步是添加登录名和密码
  • 第二步是将资源添加到 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 对象和资源由相同的请求上下文管理?如果是,那么我认为将某些东西混合在一起有点奇怪:我的意思是在与用户相关的请求上下文中进行与资源相关的操作有什么好处。

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

4

1 回答 1

0

消息“...已被冻结”意味着该对象已被edit()编辑或作为参数传递给服务方法,在另一个实例中(它是否属于相同的子类型 - 即vs. -RequestContext无关紧要)) 还没有被d 和/或响应还没有从服务器返回(或者它返回了违规:当接收者被调用时,对象仍然是可编辑的,与and相反)。UserRequestContextRessourceRequestContextfire()onViolationonSuccessonFailure

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

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

于 2011-06-27T11:07:55.410 回答