2016-08-03 38 views
3

我正在嘗試使用Firebase Server SDK和Jersey來創建REST API來執行寫操作。如何從Jersey REST api方法返回Respon,裏面有列表器

這裏就是我想要做:

  1. Initializing Firebase SDK
  2. Getting idToken from Client and Validating idToken
  3. 執行一些寫操作的幾個火力地堡節點
  4. 發送API響應

我想僅當Firebase寫入操作成功或失敗時才返回響應。 這發生在Firebase偵聽器內部。不過,我嘗試從Listener返回值,但我得到錯誤,因爲Firebase偵聽器具有void返回類型。

如何返回偵聽器的響應?

這是我的代碼。

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

回答

1

所以我猜火力地堡SDK在本質上是異步的。在這種情況下,如果您使用的是Jersey 2.x,則可以使用asynchronous server support。您可以在回撥中撥打AsyncResponse.resume(Response)。例如,

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

如果您使用的是Jersey 1.x,則沒有真正的異步選項。您只需要用CountDownLatch阻止流程,在回調中分配本地Response並倒計時。

@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

謝謝。這看起來很有希望,我正在使用以下依賴項。我有什麼需要改變使用澤西島。 2.X? ' \t \t \t com.sun.jersey \t \t \t 球衣服務器 \t \t \t 1.9 \t \t' –

+0

它並不是這麼簡單,只是改變依賴。你仍然需要一些配置。如果您對澤西島2沒有任何經驗,那麼您應該查看[入門指南](http://paulsamsotha.blogspot.com/2015/10/getting-started-with-jersey-2.html) –

+0

我已經設置好了Jersey2.23.1現在。但是,我收到錯誤的異步調用。這裏是錯誤'警告:嘗試將servlet請求放入異步模式失敗。請檢查您的servlet配置 - 請求處理中涉及的所有Servlet實例和Servlet過濾器必須明確聲明支持異步請求處理。 java.lang.IllegalStateException:當前鏈的過濾器或servlet不支持異步操作。# 花費大量時間查找解決方案,它們都無法工作。 –

0

我可能是有點晚了回答這個問題,而是試圖在火力地堡服務器SDK出來後,我發現,你可以創建在SDK中提供的任務等待同步響應。下面的代碼可能會幫助你:

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