Tomcat servlet 上的 Firebase admin sdk
Firebase admin sdk on Tomcat servlet
我想做的事情:
我正在为 java 使用 tomcat v8.5.3 和 Firebase Admin SDK v6.8.1。
上图是我想要做的。
但是我在将请求从 servlet 转发到 jsp
时遇到了问题
这是servletA的doPost代码。
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if(FirebaseApp.getApps().isEmpty()) {
FirebaseOptions options = (FirebaseOptions)getServletContext().getAttribute("options");
FirebaseApp.initializeApp(options);
}
dispatcher = request.getRequestDispatcher("/b.jsp");
try {
process(request, response);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot snapshot) {
for(DataSnapshot item: snapshot.getChildren()) {
couponList.add(item.getValue(CouponItem.class));
}
request.setAttribute("bodyObject", requestBody);
try {
dispatcher.forward(request, response);
} catch (ServletException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void onCancelled(DatabaseError error) {
// TODO Auto-generated method stub
}});
}
protected void process(HttpServletRequest request, HttpServletResponse response)
throws IOException, ParseException{
initMember();
//requestBodyString = getBody(request);
requestBodyString = (String) request.getParameter("body");
JSONParser parser = new JSONParser();
JSONObject jobj = (JSONObject) parser.parse(requestBodyString);
convert(jobj, requestBody);
Ref = FirebaseDatabase.getInstance().getReference("Coupon").child(requestBody.getRequestId());
}
在ValueEventListener的onDataChange中,dispatcher forward不起作用
我发现当代码从
变为 Ref.addListenerForSingleValueEvent 时守护线程发生了变化
Daemon Thread [http-nio-8080-exec-5] (Suspended (breakpoint at line 67 in ServletA))
owns: NioEndpoint$NioSocketWrapper (id=426)
ServletA.doPost(HttpServletRequest, HttpServletResponse) line: 67
ServletA(HttpServlet).service(HttpServletRequest, HttpServletResponse) line: 660
ServletA(HttpServlet).service(ServletRequest, ServletResponse) line: 741
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 231
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 166
WsFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 52
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 193
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 166
StandardWrapperValve.invoke(Request, Response) line: 199
StandardContextValve.invoke(Request, Response) line: 96
NonLoginAuthenticator(AuthenticatorBase).invoke(Request, Response) line: 493
StandardHostValve.invoke(Request, Response) line: 137
ErrorReportValve.invoke(Request, Response) line: 81
AccessLogValve(AbstractAccessLogValve).invoke(Request, Response) line: 660
StandardEngineValve.invoke(Request, Response) line: 87
CoyoteAdapter.service(Request, Response) line: 343
Http11Processor.service(SocketWrapperBase<?>) line: 798
Http11Processor(AbstractProcessorLight).process(SocketWrapperBase<?>, SocketEvent) line: 66
AbstractProtocol$ConnectionHandler<S>.process(SocketWrapperBase<S>, SocketEvent) line: 808
NioEndpoint$SocketProcessor.doRun() line: 1498
NioEndpoint$SocketProcessor(SocketProcessorBase<S>).run() line: 49
ThreadPoolExecutor(ThreadPoolExecutor).runWorker(ThreadPoolExecutor$Worker) line: 1149
ThreadPoolExecutor$Worker.run() line: 624
TaskThread$WrappingRunnable.run() line: 61
TaskThread(Thread).run() line: 748
到
Daemon Thread [firebase-database-event-target] (Suspended (breakpoint at line 87 in ServletA))
ServletA.onDataChange(DataSnapshot) line: 87
Query.onDataChange(DataSnapshot) line: 182
ValueEventRegistration.fireEvent(DataEvent) line: 77
DataEvent.fire() line: 65
EventRaiser.run() line: 55
Executors$RunnableAdapter<T>.call() line: 511
ScheduledThreadPoolExecutor$ScheduledFutureTask<V>(FutureTask<V>).run() line: 266
ScheduledThreadPoolExecutor$ScheduledFutureTask<V>.access1(ScheduledThreadPoolExecutor$ScheduledFutureTask) line: 180
ScheduledThreadPoolExecutor$ScheduledFutureTask<V>.run() line: 293
FirebaseScheduledExecutor(ThreadPoolExecutor).runWorker(ThreadPoolExecutor$Worker) line: 1149
ThreadPoolExecutor$Worker.run() line: 624
Thread.run() line: 748
我认为我在 Tomcat 和 Java 方面的经验不足以解决这个问题。
数据库事件侦听器在单独的线程上运行。您不能对其执行转发或任何响应操作,因为请求线程在您调用 addListenerForSingleValueEvent()
后立即退出。您需要以某种方式停止请求线程退出,直到您的事件侦听器被执行。 CountDownLatch
可能是最简单的方法。
final CountDownLatch latch = new CountDownLatch(1);
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot snapshot) {
latch.countDown();
}
@Override
public void onCancelled(DatabaseError error) {
latch.countDown();
}
});
// Wait for the callbacks to fire
latch.await();
// Send response
我想做的事情:
我正在为 java 使用 tomcat v8.5.3 和 Firebase Admin SDK v6.8.1。
上图是我想要做的。
但是我在将请求从 servlet 转发到 jsp
时遇到了问题这是servletA的doPost代码。
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if(FirebaseApp.getApps().isEmpty()) {
FirebaseOptions options = (FirebaseOptions)getServletContext().getAttribute("options");
FirebaseApp.initializeApp(options);
}
dispatcher = request.getRequestDispatcher("/b.jsp");
try {
process(request, response);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot snapshot) {
for(DataSnapshot item: snapshot.getChildren()) {
couponList.add(item.getValue(CouponItem.class));
}
request.setAttribute("bodyObject", requestBody);
try {
dispatcher.forward(request, response);
} catch (ServletException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void onCancelled(DatabaseError error) {
// TODO Auto-generated method stub
}});
}
protected void process(HttpServletRequest request, HttpServletResponse response)
throws IOException, ParseException{
initMember();
//requestBodyString = getBody(request);
requestBodyString = (String) request.getParameter("body");
JSONParser parser = new JSONParser();
JSONObject jobj = (JSONObject) parser.parse(requestBodyString);
convert(jobj, requestBody);
Ref = FirebaseDatabase.getInstance().getReference("Coupon").child(requestBody.getRequestId());
}
在ValueEventListener的onDataChange中,dispatcher forward不起作用
我发现当代码从
变为 Ref.addListenerForSingleValueEvent 时守护线程发生了变化Daemon Thread [http-nio-8080-exec-5] (Suspended (breakpoint at line 67 in ServletA))
owns: NioEndpoint$NioSocketWrapper (id=426)
ServletA.doPost(HttpServletRequest, HttpServletResponse) line: 67
ServletA(HttpServlet).service(HttpServletRequest, HttpServletResponse) line: 660
ServletA(HttpServlet).service(ServletRequest, ServletResponse) line: 741
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 231
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 166
WsFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 52
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 193
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 166
StandardWrapperValve.invoke(Request, Response) line: 199
StandardContextValve.invoke(Request, Response) line: 96
NonLoginAuthenticator(AuthenticatorBase).invoke(Request, Response) line: 493
StandardHostValve.invoke(Request, Response) line: 137
ErrorReportValve.invoke(Request, Response) line: 81
AccessLogValve(AbstractAccessLogValve).invoke(Request, Response) line: 660
StandardEngineValve.invoke(Request, Response) line: 87
CoyoteAdapter.service(Request, Response) line: 343
Http11Processor.service(SocketWrapperBase<?>) line: 798
Http11Processor(AbstractProcessorLight).process(SocketWrapperBase<?>, SocketEvent) line: 66
AbstractProtocol$ConnectionHandler<S>.process(SocketWrapperBase<S>, SocketEvent) line: 808
NioEndpoint$SocketProcessor.doRun() line: 1498
NioEndpoint$SocketProcessor(SocketProcessorBase<S>).run() line: 49
ThreadPoolExecutor(ThreadPoolExecutor).runWorker(ThreadPoolExecutor$Worker) line: 1149
ThreadPoolExecutor$Worker.run() line: 624
TaskThread$WrappingRunnable.run() line: 61
TaskThread(Thread).run() line: 748
到
Daemon Thread [firebase-database-event-target] (Suspended (breakpoint at line 87 in ServletA))
ServletA.onDataChange(DataSnapshot) line: 87
Query.onDataChange(DataSnapshot) line: 182
ValueEventRegistration.fireEvent(DataEvent) line: 77
DataEvent.fire() line: 65
EventRaiser.run() line: 55
Executors$RunnableAdapter<T>.call() line: 511
ScheduledThreadPoolExecutor$ScheduledFutureTask<V>(FutureTask<V>).run() line: 266
ScheduledThreadPoolExecutor$ScheduledFutureTask<V>.access1(ScheduledThreadPoolExecutor$ScheduledFutureTask) line: 180
ScheduledThreadPoolExecutor$ScheduledFutureTask<V>.run() line: 293
FirebaseScheduledExecutor(ThreadPoolExecutor).runWorker(ThreadPoolExecutor$Worker) line: 1149
ThreadPoolExecutor$Worker.run() line: 624
Thread.run() line: 748
我认为我在 Tomcat 和 Java 方面的经验不足以解决这个问题。
数据库事件侦听器在单独的线程上运行。您不能对其执行转发或任何响应操作,因为请求线程在您调用 addListenerForSingleValueEvent()
后立即退出。您需要以某种方式停止请求线程退出,直到您的事件侦听器被执行。 CountDownLatch
可能是最简单的方法。
final CountDownLatch latch = new CountDownLatch(1);
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot snapshot) {
latch.countDown();
}
@Override
public void onCancelled(DatabaseError error) {
latch.countDown();
}
});
// Wait for the callbacks to fire
latch.await();
// Send response