2016-08-03 42 views
3

hat Ich versuche, REST-API zu erstellen, um Schreibvorgänge mit Firebase Server SDK und Jersey durchzuführen. HierWie Respone von Jersey REST API-Methode, die Listern innerhalb

ist das, was ich zu tun versucht:

  1. Initializing Firebase SDK
  2. Getting idToken from Client and Validating idToken
  3. Performing einige Schreibvorgänge auf wenige Firebase Knoten
  4. Senden api Antwort

Ich möchte return Antwort nur, wenn der Firebase-Schreibvorgang erfolgreich ist oder fehlschlägt. Das passiert innerhalb von Firebase Listeners. Ich versuche jedoch, Wert von Listeners zurückzugeben, ich erhalte Fehler, weil Firebase-Listener void Rückgabetyp haben.

Wie kann ich Antwort vom Zuhörer zurückgeben?

Hier ist mein Code.

MyEndpoint.java

@Path("/restapi") 
//BaseEndpoint does Authentication operations 
public class MyEndpoint extends BaseEndpoint { 

    public void Authenticate(String token, AuthenticationListener authenticationResultListener) { 
     super.Authenticate(token, authenticationResultListener); 
    } 

    @POST 
    @Produces("application/json") 
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED) 
    public Response createCommunity(@FormParam("idToken") String idToken) { 
     Authenticate(idToken, new AuthenticationListener() { 
      @Override 
      public void onAuthenticationSuccess() { 
       // The app only has access as defined in the Security Rules 
       DatabaseReference ref = FirebaseDatabase.getInstance().getReference("/mysamplenode"); 
       ref.addListenerForSingleValueEvent(new ValueEventListener() { 
        public void onDataChange(DataSnapshot dataSnapshot) { 
         String res = dataSnapshot.getKey(); 
         //I will do some write operations on Firebase here 
         //If they complete successfuly only then I want to return api response 
         return Response.status(200).entity().build(); 
        } 
        @Override 
        public void onCancelled(DatabaseError arg0) { 
         System.out.println("DatabaseError-------------" + arg0); 
         return Response.status(500).entity("DatabaseError").build(); 
        } 
       }); 
      } 
      @Override 
      public void onAuthenticationFailure() { 
       return Response.status(403).entity("Forbidden").build(); 
      } 
     }); 
    } 
} 

BaseEndpoint.java

public class BaseEndpoint { 

    public static String uid; 

    public void Authenticate(String token, AuthenticationListener authenticationResultListener) { 
     // idToken comes from the client app 
     FirebaseAuth.getInstance().verifyIdToken(token).addOnFailureListener(new OnFailureListener() { 

      @Override 
      public void onFailure(Exception arg0) { 
       System.out.println("Uid exp= " + arg0); 
       authenticationResultListener.onAuthenticationFailure(); 
      } 
     }).addOnSuccessListener(new OnSuccessListener<FirebaseToken>() { 
      @Override 
      public void onSuccess(FirebaseToken decodedToken) { 
       uid = decodedToken.getUid(); 
       System.out.println("Uid= " + uid); 
       authenticationResultListener.onAuthenticationSuccess(); 
      } 
     }); 
    } 
} 

Antwort

1

So ist die Firebase SDK Ich vermute, in der Natur asynchron. In diesem Fall können Sie, wenn Sie Jersey 2.x verwenden, die asynchronous server support verwenden. Sie können einfach AsyncResponse.resume(Response) in Ihren Rückrufen aufrufen. Zum Beispiel

@POST 
@Produces("application/json") 
@Consumes(MediaType.APPLICATION_FORM_URLENCODED) 
public void createCommunity(@FormParam("idToken") String idToken, 
           @Suspended final AsyncResponse response) { 
    Authenticate(idToken, new AuthenticationListener() { 
     @Override 
     public void onAuthenticationSuccess() { 
      DatabaseReference ref = FirebaseDatabase.getInstance() 
        .getReference("/mysamplenode"); 
      ref.addListenerForSingleValueEvent(new ValueEventListener() { 
       public void onDataChange(DataSnapshot dataSnapshot) { 
        String res = dataSnapshot.getKey();       
        response.resume(Response.status(200).entity().build()); 
       } 
       @Override 
       public void onCancelled(DatabaseError arg0) { 
        response.resume(Response.status(500).entity("DatabaseError").build()); 
       } 
      }); 
     } 
     @Override 
     public void onAuthenticationFailure() { 
      response.resume(Response.status(403).entity("Forbidden").build()); 
     } 
    }); 
} 

Wenn Sie Jersey 1.x verwenden, gibt es keine asynchrone Option. Sie müssen nur den Fluss mit einem CountDownLatch blockieren, einen lokalen Response in den Callbacks zuweisen und rückwärts zählen.

@POST 
@Produces("application/json") 
@Consumes(MediaType.APPLICATION_FORM_URLENCODED) 
public void createCommunity(@FormParam("idToken") String idToken) { 
    Response response; 
    CountDownLatch latch = new CountDownLatch(1); 
    Authenticate(idToken, new AuthenticationListener() { 
     @Override 
     public void onAuthenticationSuccess() { 
      DatabaseReference ref = FirebaseDatabase.getInstance() 
        .getReference("/mysamplenode"); 
      ref.addListenerForSingleValueEvent(new ValueEventListener() { 
       public void onDataChange(DataSnapshot dataSnapshot) { 
        String res = dataSnapshot.getKey();       
        response = Response.status(200).entity().build(); 
        latch.countDown(); 
       } 
       @Override 
       public void onCancelled(DatabaseError arg0) { 
        response = Response.status(500).entity("DatabaseError").build(); 
        latch.countDown(); 
       } 
      }); 
     } 
     @Override 
     public void onAuthenticationFailure() { 
      response = Response.status(403).entity("Forbidden").build(); 
      latch.countDown(); 
     } 
    }); 
    latch.await(); 
    return response; 
} 
+0

Vielen Dank. Das sieht vielversprechend aus, ich verwende folgende Abhängigkeit. Was muss ich ändern, um Jersey zu benutzen? 2.X? ' \t \t \t com.sun.jersey \t \t \t Jersey-Server \t \t \t 1,9 \t \t' –

+0

Es ist nicht so einfach wie nur wechselnde Abhängigkeiten. Sie benötigen noch eine Konfiguration. Wenn Sie keine Erfahrung mit Jersey 2 haben, sollten Sie diese [Erste Schritte Leitfaden] (http://paulsamtha.blogspot.com/2015/10/getting-started-with-jersey-2.html) –

+0

Ich habe Setup Jersey2.23.1 jetzt. Aber ich bekomme einen Fehler für Async-Anruf.Hier ist der Fehler 'WARNUNG: Der Versuch, die Servlet-Anfrage in den asynchronen Modus zu stellen, ist fehlgeschlagen. Bitte überprüfen Sie Ihre Servlet-Konfiguration - alle Servlet-Instanzen und Servlet-Filter, die an der Anfrageverarbeitung beteiligt sind, müssen die Unterstützung für die asynchrone Anfrage explizit deklarieren. java.lang.IllegalStateException: Ein Filter oder Servlet der aktuellen Kette unterstützt keine asynchronen Operationen. " Haben viel Zeit damit verbracht, die Lösung zu finden, keiner von ihnen hat funktioniert. –

0

ich vielleicht ein wenig zu spät, diese Frage zu beantworten, aber nach dem Firebase Server SDK heraus versuchen, fand ich, dass Sie eine Aufgabe in dem SDK auf eine Antwort warten schaffen synchron. Das folgende Snippet könnte Ihnen dabei helfen:

public class BaseEndpoint { 

    public static String uid; 

    public void Authenticate(String token, AuthenticationListener authenticationResultListener) { 
     // idToken comes from the client app 
     FirebaseToken firebaseToken = null; 
     try { 
      Task<FirebaseToken> authTask = FirebaseAuth.getInstance().verifyIdToken(token); 
      Tasks.await(authTask); 
      firebaseToken = authTask.getResult(); 
     } catch (Exception e) { 
      authenticationResultListener.onAuthenticationFailure(); 
     } 
     uid = firebaseToken.getUid(); 
     System.out.println("Uid= " + uid); 
     authenticationResultListener.onAuthenticationSuccess(); 
    } 
}