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

发布于 2024-11-16 23:59:00 字数 4943 浏览 3 评论 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 对象来为新用户创建一个请求对象。这给出了类似的内容:

    公共接口 MyRequestFactory 扩展了 RequestFactory {
        UserRequestContext userRequestContext();
        资源请求上下文 ressourceRequestContext();
    }
    

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

    public class UserAddScreen 扩展 Composite {
        私有 UserProxy 用户代理;
        EventBus eventBus = new SimpleEventBus();
        MyRequestFactory requestFactory = GWT.create(MyRequestFactory.class);
        ...
    
        公共用户添加屏幕(){
            ...
            requestFactory.initialize(eventBus);
        }
    
        公共 showUserAddScreen() {
            // 密码和登录的文本框
            // 资源列表框
        }
    
    }
    

我尝试将其实现为向导。所以在 UserAddScreen 的开头,我有一个 userProxy 对象。 该对象字段在向导的每个步骤中都会初始化:

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

对于最后一步,我有两个列表框,第一个包含我从 RessourceRequestContext.getAllRessource 获得的数据库表资源中拥有的​​所有资源的列表(我有一个循环将它们显示为列表框项,其中 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);

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

以下是控制按钮:

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

之后,我有一个“完成”按钮,该按钮循环第二个列表框中的项目(这是我从第一个列表框中选择的项目),我尝试(再次)使用 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 with)...但它不起作用

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

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

userProxy.getRessource().add(response);

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

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

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

I am struggling with an issue using RequestFactory in GWT.
I have a User object : this object has login and password fields and other fields which are of collection type.

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

    // Getters and setters removed for brievety
} 

I need to persist this object in db so I used RequestFactory because it seems like a CRUD-type operation to me.

Now for the RequestFactory part of the code, this is how I have tried to do it :

  1. I create a UserRequestContext object to create a request object for the new User. Which gives something like :

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

    and to create the user object I have something like this :

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

I have tried to implement it as a wizard. So at the beginning of the UserAddScreen, I have a
a userProxy object.
This object fields are initialized at each step of the wizard :

  • the first step is adding the login and password
  • the second step is adding ressources to the userProxy object.

for this last step, I have two list boxes the first one containing the list of all the ressources i have in my DB table Ressources that I got from RessourceRequestContext.getAllRessource (I have a loop to display them as listbox item with the RessourceId as the value) and the second allows me to add the selected Ressources from this first listbox. Here is the first listbox :

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

So, as you can see, my code loops over the retrieved proxies from DB and initializes the items within the listbox.

Here are the control buttons :

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

So when somebody selects one or more users and click on a ">" button, all the selected items go to the second listbox which is named userRessourceListBox

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

After that, I have a FINISH button, which loops over the items in the second listbox (which are the ones I have selected from the first one) and I try to make a request (again) with RequestFactory to retrieve the ressourceProxy object and initialize the userProxy ressources collection with the result

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

    });

Finally, (in the code above) I try to save the UserProxy object (with the initial request context I have created userProxy with)... but it doesn't work

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

It seems like when looping over the result in the onSuccess method :

userProxy.getRessource().add(response);

I retrieve the response (of type RessourceProxy) but beyond this method, for example when I try to save the userProxy object AFTER THE LOOP, there are no RessourceProxy objects in the ressourceProxy collection of userProxy...

Have you guys ever experienced something like this ?
Perhaps I am not doing it right : do I have to get the ressource with the UserRequestContext ? so that my newUser object and ressources are managed by the same request Context ?
if yes then I think it's a little bit weird to have something mixed together : I mean what is the benefit of having a Ressource-related operation in the User-related request context.

any help would be really really ... and I mean really appreciated ;-)
Thanks a lot

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

醉生梦死 2024-11-23 23:59:00

消息“...已被冻结”意味着该对象已被 edit()ed 或作为参数传递给另一个 RequestContext 实例中的服务方法(它不不管它是否属于相同的子类型(即 UserRequestContextRessourceRequestContext),但尚未被 fire() >d 和/或响应尚未返回服务器(或者返回违规:当调用接收者的 onViolation 时,对象仍然是可编辑的,这与 onSuccessonFailure 相反) 。

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

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

The message "… has been frozen" means that the object has been either edit()ed or passed as an argument to a service method, in another RequestContext instance (it doesn't matter whether it's of the same sub-type –i.e. UserRequestContext vs. RessourceRequestContext– or not) which hasn't yet been fire()d and/or the response has not yet come back from the server (or it came back with violations: when the receiver's onViolation is called, the objects are still editable, contrary to onSuccess and onFailure).

UPDATE: you have a race condition: you loop over the resource IDs and spawn as many requests as the number of items selected by the user, and then, without waiting for their response (remember: it's all asynchronous), you save the user proxy. As soon as you fire() that last request, the user proxy is no longer mutable (i.e. frozen).

IMO, you'd better keep the RessourceProxys retrieved initially and use them directly in the user proxy before saving it (i.e. no more find() request in the "finish" phase). Put them in a map by ID and get them from the map instead of finding them back from the server again.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文