2015-07-20 16 views
8

Mam projekt Google Java AppEngine, który wywołuje BigQuery, aby wyświetlić wyniki zadania zapytania. Przykładowy kod i instrukcje, których użyłem, można znaleźć pod adresem here. Aplikacja uruchamia i pobiera zapytanie z mojego komputera deweloperskiego, jednak po przesłaniu do AppEngine w celu przetestowania na appspot.com pojawia się plik client_secrets.json (inny plik dla dev i appspot.com z powodu autoryzacji JavaScript JavaScript) nie może być załadowany za pomocą następujący fragment:Odczytywanie plików zasobów Java w aplikacji GoogleEngine

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; 

}

Oto moja AppEngine-web.xml definicja pliku zasobów:

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

plik client_secrets.json pakowany jest właściwie w moim pliku wojennego. Błąd pojawia się:

>/
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) 

mogę spróbować użyć ServletContext.getResourceAsStream() zamiast jednak klasa, która łączy się z BigQuery w przykładowej aplikacji nie jest klasą Servlet, więc będzie to wymagało trochę reorganizację kodu do prawidłowego wdrożenia, a Google's instructions wydaje się wskazywać, że mój kod powinien działać. Jakakolwiek pomoc się przyda, dzięki!

+0

używasz Maven/Gradle? Jeśli tak, rozważ umieszczenie pliku w katalogu src/main/resources i spróbuj załadować go jak @NamshubWriter pokazuje – zaratustra

Odpowiedz

9

Pliki zasobów nie znajdują się w systemie plików, więc new File("/WEB-INF/client_secrets.json") ordinary nie będzie działać. Zamiast tego, zwykle trzeba załadować go jako zasób:

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

z jakiegoś powodu, AppEngine nie pozwoli Ci załadować zasobów pod WEB-INF przy użyciu programu ładującego klasy (można załadować zasobów w plikach jar z powyższych technika).

Możesz użyć użyć API pliku, aby uzyskać dostęp do ścieżek w WEB-INF w aplikacji, ale ścieżki muszą być względne. Zakładając, że plik client_secrets.json znajduje się w folderze WEB-INF, to powinno działać:

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

Aby użyć File API do odczytu zasobów pod WEB-INF, można również muszą również upewnić się, że plik appengine-web.xml obejmuje zasoby w WEB-INF:

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

Zobacz Configuring appengine-web.xml i Why can't I read from this file

+0

Dzięki za szybką odpowiedź @NamshubWriter. Zastosowałem zmianę, którą zasugerowałeś, teraz otrzymuję nowy błąd: Wyczyść wyjątek od serwletu java.io.FileNotFoundException: /base/data/home/apps/s~tactile-reason-849/1.385858979910614152/WEB- INF/client_secrets.json (Brak takiego pliku lub katalogu) –

+0

@ChrisLumpkin Twój appengine-web.xml sugeruje, że ten plik jest pod "klasami", ale twój fragment kodu Java próbuje uzyskać do niego dostęp bezpośrednio w WEB-INF. Gdzie jest ten zasób? Czy pochodzi z jednego z plików jar? Czy możesz przejrzeć plik WAR, aby zobaczyć, gdzie dokładnie jest? – NamshubWriter

+0

Właśnie zaktualizowałem fragmenty powyżej, aby odzwierciedlić zmiany, które wprowadziłem. Plik wojenny ma WEB-INF/client_secrets.json. –

Powiązane problemy