views:

476

answers:

3

Hi,

I am using gwt and postgres for my project. On the front end i have few widgets whose data i am trying to save on to tables at the back-end when i click on "save project" button(this also takes the name for the created project).

In the asynchronous callback part i am setting more than one table. But it is not sending the data properly. I am getting the following error:

org.postgresql.util.PSQLException: ERROR: insert or update on table "entitytype" violates foreign key constraint "entitytype_pname_fkey"
  Detail: Key (pname)=(Project Name) is not present in table "project".

But when i do the select statement on project table i can see that the project name is present.

Here is how the callback part looks like:

        oksave.addClickHandler(new ClickHandler(){
                            @Override
                            public void onClick(ClickEvent event) {
                                if(erasync == null)
                                    erasync = GWT.create(EntityRelationService.class);
                                AsyncCallback<Void> callback = new AsyncCallback<Void>(){
                                    @Override
                                    public void onFailure(Throwable caught) {
                                        }

                                    @Override
                                    public void onSuccess(Void result){  }                          
                        };      
    erasync.setProjects(projectname, callback);

                                for(int i = 0; i < boundaryPanel.getWidgetCount(); i++){

                                    top = new Integer(boundaryPanel.getWidget(i).getAbsoluteTop()).toString();
                                    left = new Integer(boundaryPanel.getWidget(i).getAbsoluteLeft()).toString();
                                    if(widgetTitle.startsWith("ATTR")){
                                        type = "regular";

                                            erasync.setEntityAttribute(name1, name, type, top, left, projectname, callback);
                                        }   else{
erasync.setEntityType(name, top, left, projectname, callback);
}                           
                                    }
    }

Question:

  1. Is it wrong to set more than one in the asynchronous callback where all the other tables are dependent on a particular table?
  2. when i say setProjects in the above code isn't it first completed and then moved on to the next one?

Please any input will be greatly appreciated.

Thank you.

+2  A: 

With that foreign key constraint, you must make sure the erasync.setProjects(...) has completed before you insert the rest of the stuff.

I suggest doing the erasync.setEntityAttribute(...) magic in (or from) an onsuccess callback instead of jumping right to it.

npup
I did try to incorporate in onsuccess part but it does not recognize the callback. Does that mean i have to do the asynchronous callback in onsuccess as well?Thank you.
sprasad12
Thank you. i worked...
sprasad12
Oh, great. Thanks for reporting the success! (Did you do it onSuccess? :))
npup
A: 

Because of nature of Async, don't assume setProjects(...) method will be called on the server before setEntityAttribute or setEntityType.

Personally, I prefer to have a Project class which contains all necessary info, for example:
public class Project{
private String projectName;
private List attributes = new ArrayList();
.. other properties

// Getter & Setter methods
}

Then send to the server in one round trip:

Project project = new Project();
project.setProjectName(..);
// Set other properties
erasync.saveProjects(project, callback);

Trung,
http://www.gdevelop.com

Trung
A: 

You're firing several request in which (guessing from the error message) really should be called in sequence.

Any time you call more than one rpc call; try to think that you should be able to rearrange them in any order (because that's allmost what actually happens because they're asynchronous)... If running them in reverse order does not make sense; you cannot fire them sequentially!

Two ways to fix your problem:

Nesting:

    service.callFirst(someData, new AsyncCallback<Void> callback = new AsyncCallback<Void>(){
        @Override
        public void onFailure(Throwable caught) {/*Handle errors*/}
        @Override
        public void onSuccess(Void result){
            service.callSecond(someOtherData, new AsyncCallback<Void> callback = new AsyncCallback<Void>(){ 
                /* onSuccess and onFailure for second callback here */ 
            });
        }                       
    });

Or creating one service call that does both (Recommended):

    service.callFirstAndSecond(someData, someOtherData, new AsyncCallback<Void> callback = new AsyncCallback<Void>(){
        @Override
        public void onFailure(Throwable caught) {/*Handle errors*/}
        @Override
        public void onSuccess(Void result){
            /* Handle success */
        }                       
    });

The second option is most likely going to be much less messy, as several nested asynch callbacks quickly grows quite wide and confusing, also you make just one request.

Stein G. Strindhaug