2010-03-16 5 views
1

J'utilise gwt et postgres pour mon projet. Sur le front-end j'ai peu de widgets dont j'essaie de sauvegarder les données sur les tables en back-end quand je clique sur le bouton "save project" (cela prend aussi le nom du projet créé).Callback asynchrone - gwt

Dans la partie de rappel asynchrone, je définis plusieurs tables. Mais il n'envoie pas les données correctement. Je reçois l'erreur suivante:

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". 

Mais quand je fais l'instruction select sur la table de projet, je peux voir que le nom du projet est présent.

Voici comment la partie de rappel ressemble:

 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. Est-il erroné de définir plusieurs dans le rappel asynchrone où toutes les autres tables dépendent d'un particulier table?
  2. quand je dis que setProjects dans le code ci-dessus n'est pas d'abord terminé et ensuite passé à la suivante?

S'il vous plaît, toute contribution sera grandement appréciée.

Merci.

Répondre

2

Avec cette contrainte de clé étrangère, vous devez vous assurer que le erasync.setProjects (...) est terminé avant d'insérer le reste du contenu.

Je suggère de faire la magie erasync.setEntityAttribute(...) dans (ou à partir) d'un rappel de succès au lieu de sauter directement vers elle.

+0

J'ai essayé d'incorporer dans la partie onsuccess mais elle ne reconnaît pas le rappel. Cela signifie-t-il que je dois aussi faire le rappel asynchrone en cas de succès? Merci. – suprasad

+0

Merci. J'ai travaillé ... – suprasad

+0

Oh, super. Merci d'avoir signalé le succès! (L'avez-vous fait sur le succès? :)) – npup

0

En raison de la nature de la méthode Async, ne présumez pas setProjects(...) sera appelé sur le serveur avant setEntityAttribute ou setEntityType.

Personnellement, je préfère avoir une classe Project qui contient toutes les informations nécessaires, par exemple:

public class Project{ 
     private String projectName; 
     private List attributes = new ArrayList(); 
     .. other properties 

    // Getter & Setter methods 
} 

ensuite envoyer au serveur dans un voyage aller-retour:

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

Vous tir plusieurs requêtes dans lesquelles (deviner à partir du message d'erreur) devraient être appelées en séquence.

Chaque fois que vous appelez plusieurs appels RPC; essayez de penser que vous devriez pouvoir les réorganiser dans n'importe quel ordre (parce que c'est ce qui se passe réellement parce qu'ils sont asynchrones) ... Si les exécuter dans l'ordre inverse n'a pas de sens; vous ne pouvez pas les tirer séquentiellement!

Deux façons de résoudre votre problème:

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

Ou créer un appel de service qui fait à la fois (recommandé):

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

La deuxième option va très probablement être beaucoup moins désordonné, car plusieurs rappels asynchrones imbriqués se développent rapidement assez loin et prêtent à confusion, aussi vous ne faites qu'une requête.