[英]How to return Respone from Jersey REST api method which has listners inside
I am trying to create REST apis to perform write operations using Firebase Server SDK and Jersey. 我正在尝试创建REST apis以使用Firebase Server SDK和Jersey执行写入操作。
Here is what I am trying to do: 这是我想要做的:
I want to return Response only if Firebase write operation succeeds or fails. 我想仅在Firebase写入操作成功或失败时返回Response。 That happens inside of Firebase Listeners. 这发生在Firebase监听器内部。 However, I try to return value from Listeners, I get error becuase Firebase listeners have void return type. 但是,我尝试从Listeners返回值,我得到错误,因为Firebase侦听器具有void返回类型。
How can I return response from the listener? 我怎样才能从听众那里回复?
Here is my code. 这是我的代码。
MyEndpoint.java 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 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();
}
});
}
}
So I'm guessing the Firebase SDK is asynchronous in nature. 所以我猜测Firebase SDK本质上是异步的。 In which case, if you're using Jersey 2.x, you can use the asynchronous server support . 在这种情况下,如果您使用的是Jersey 2.x,则可以使用异步服务器支持 。 You can just call AsyncResponse.resume(Response)
in your callbacks. 您可以在回调中调用AsyncResponse.resume(Response)
。 For example 例如
@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());
}
});
}
If you're using Jersey 1.x, there's not really an async option. 如果您使用的是Jersey 1.x,那么实际上并不存在异步选项。 You just need to block flow with a CountDownLatch
, assign a local Response
in the callbacks, and count down. 您只需要使用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;
}
I might be a little late in answering this question, but after trying the Firebase server SDK out I found that you can create a Task available in the SDK to wait for a response synchronously. 我可能在回答这个问题时有点迟,但在尝试使用Firebase服务器SDK后,我发现您可以在SDK中创建一个可用于同步等待响应的任务。 The snippet below might help you out: 下面的代码段可能会帮到你:
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();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.