2015-07-20 23 views
8

Tôi có một dự án Google AppEngine Java được thiết lập để gọi BigQuery để hiển thị các kết quả của một công việc truy vấn. Mã ví dụ và hướng dẫn tôi đã sử dụng có thể được tìm thấy here. Ứng dụng chạy và truy xuất truy vấn từ máy phát triển của tôi, tuy nhiên khi tôi tải lên AppEngine để thử nghiệm trên appspot.com, tệp client_secrets.json (tệp khác cho dev và appspot.com do ủy quyền URL JavaScript) không thể tải bằng cách sử dụng đoạn sau:Đọc các tệp tài nguyên Java trong Google AppEngine

static GoogleClientSecrets getClientCredential() throws IOException { 
if (clientSecrets == null) { 

    clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, 
      new InputStreamReader(new FileInputStream(
       new File("WEB-INF/client_secrets.json")))); 

    Preconditions.checkArgument(!clientSecrets.getDetails().getClientId().startsWith("Enter ") 
     && !clientSecrets.getDetails().getClientSecret().startsWith("Enter "), 
     "Enter Client ID and Secret from https://code.google.com/apis/console/?api=bigquery " 
     + "into bigquery-appengine-sample/src/main/resources/client_secrets.json"); 
} 
return clientSecrets; 

}

đây là appengine-web.xml định nghĩa tập tin tài nguyên của tôi:

<resource-files> 
    <include path="**" /> 
    </resource-files> 

File client_secrets.json được đóng gói đúng cách trong tập tin chiến tranh của tôi. Các lỗi tôi nhận được là:

>/
Uncaught exception from servlet 
java.io.FileNotFoundException: /base/data/home/apps/s~tactile-reason-849/1.385872137632330782/WEB-INF/client_secrets.json (No such file or directory) 
    at java.io.FileInputStream.open(Native Method) 
    at java.io.FileInputStream.<init>(FileInputStream.java:171) 
    at com.google.api.client.sample.bigquery.appengine.dashboard.ServiceUtils.getClientCredential(ServiceUtils.java:71) 
    at com.google.api.client.sample.bigquery.appengine.dashboard.ServiceUtils.newFlow(ServiceUtils.java:103) 
    at com.google.api.client.sample.bigquery.appengine.dashboard.MainServlet.initializeFlow(MainServlet.java:125) 
    at com.google.api.client.extensions.servlet.auth.oauth2.AbstractAuthorizationCodeServlet.service(AbstractAuthorizationCodeServlet.java:124) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717) 
    at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511) 
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166) 
    at com.google.apphosting.utils.servlet.ParseBlobUploadFilter.doFilter(ParseBlobUploadFilter.java:125) 
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
    at com.google.apphosting.runtime.jetty.SaveSessionFilter.doFilter(SaveSessionFilter.java:35) 
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
    at com.google.apphosting.utils.servlet.JdbcMySqlConnectionCleanupFilter.doFilter(JdbcMySqlConnectionCleanupFilter.java:60) 
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
    at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43) 
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
    at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388) 
    at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216) 
    at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182) 
    at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765) 
    at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418) 
    at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.handle(AppVersionHandlerMap.java:257) 
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) 
    at org.mortbay.jetty.Server.handle(Server.java:326) 
    at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542) 
    at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:923) 
    at com.google.apphosting.runtime.jetty.RpcRequestParser.parseAvailable(RpcRequestParser.java:76) 
    at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404) 
    at com.google.apphosting.runtime.jetty.JettyServletEngineAdapter.serviceRequest(JettyServletEngineAdapter.java:146) 
    at com.google.apphosting.runtime.JavaRuntime$RequestRunnable.run(JavaRuntime.java:482) 
    at com.google.tracing.TraceContext$TraceContextRunnable.runInContext(TraceContext.java:437) 
    at com.google.tracing.TraceContext$TraceContextRunnable$1.run(TraceContext.java:444) 
    at com.google.tracing.CurrentContext.runInContext(CurrentContext.java:230) 
    at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContextNoUnref(TraceContext.java:308) 
    at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContext(TraceContext.java:300) 
    at com.google.tracing.TraceContext$TraceContextRunnable.run(TraceContext.java:441) 
    at com.google.apphosting.runtime.ThreadGroupPool$PoolEntry.run(ThreadGroupPool.java:234) 
    at java.lang.Thread.run(Thread.java:745) 

tôi có thể thử sử dụng ServletContext.getResourceAsStream() thay vào đó, tuy nhiên lớp này kết nối với BigQuery trong ứng dụng ví dụ không phải là một lớp Servlet, vì vậy đây sẽ yêu cầu một số tổ chức lại mã để triển khai đúng cách và Google's instructions dường như cho biết mã của tôi sẽ hoạt động. Bất kỳ trợ giúp được đánh giá cao, cảm ơn!

+0

bạn đang sử dụng Maven/Gradle? Nếu vậy, hãy xem xét để đặt các tập tin trong thư mục src/main/resources và cố gắng tải nó như @NamshubWriter cho thấy – zaratustra

Trả lời

9

Tệp tài nguyên không có trên hệ thống tệp, vì vậy, new File("/WEB-INF/client_secrets.json") bình thường sẽ không hoạt động. Thay vào đó, bạn thường cần phải tải nó như một nguồn lực:

InputStream resourceStream = Thread.currentThread().getContextClassLoader() 
    .getResourceAsStream("/WEB-INF/client_secrets.json"); 

Đối với một số lý do, AppEngine sẽ không cho phép bạn tải các tài nguyên dưới WEB-INF bằng cách sử dụng bộ nạp lớp (bạn có thể tải các tài nguyên trong các tập tin jar với ở trên kỹ thuật).

Bạn có thể sử dụng API tệp để truy cập đường dẫn trong WEB-INF trong ứng dụng, nhưng đường dẫn cần phải tương đối. Giả sử rằng các tập tin client_secrets.json là trong thư mục WEB-INF, điều này sẽ làm việc:

clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, 
    new InputStreamReader(new FileInputStream(
     new File("WEB-INF/client_secrets.json")))); 

Để sử dụng File API để đọc các nguồn lực dưới WEB-INF, bạn cũng cũng cần phải đảm bảo tệp appengine-web.xml của bạn bao gồm các nguồn lực trong của bạn WEB-INF:

<resource-files> 
    <include path="/**.json" /> 
</resource-files> 

Xem Configuring appengine-web.xmlWhy can't I read from this file

+0

Cảm ơn bạn đã phản hồi nhanh @NamshubWriter. Tôi đã áp dụng thay đổi bạn đã đề xuất, bây giờ tôi nhận được một lỗi mới: Ngoại lệ không được phép từ servlet java.io.FileNotFoundException: /base/data/home/apps/s~tactile-reason-849/1.385858979910614152/WEB- INF/client_secrets.json (Không có tệp hoặc thư mục nào) –

+0

@ChrisLumpkin Đoạn mã appengine-web.xml của bạn ngụ ý rằng tệp này nằm trong "các lớp" nhưng đoạn mã Java của bạn đang cố gắng truy cập nó trực tiếp trong WEB-INF. Tài nguyên này ở đâu? Nó đến từ một trong các tệp jar của bạn? Bạn có thể xem tệp WAR của bạn để xem chính xác nó ở đâu không? – NamshubWriter

+0

Tôi vừa cập nhật các đoạn ở trên để phản ánh những thay đổi tôi đã thực hiện. Tệp chiến tranh không có WEB-INF/client_secrets.json. –

Các vấn đề liên quan