尝试在google app engine for java中实现异步http时遇到奇怪的exception

我正在尝试在java中实现async http。 这是代码的重要部分:

for (String urlString : urls) { // TODO: try and get rid of these two heap allocations url = new URL(urlString); request = new HTTPRequest(url); request.addHeader(userAgentHeader); request.addHeader(authorizationHeader); request.addHeader(acceptEncodingHeader); request.addHeader(acceptCharsetHeader); responses.add(URLFetchServiceFactory.getURLFetchService().fetchAsync(reques t)); apiCallsMade++; } for (Future futureResponse : responses) { parseResponse(new String(futureResponse.get().getContent())); } 

我一直收到这个错误:

com.google.apphosting.api.ApiProxy $ CallNotFoundException:找不到API包’urlfetch’或调用’Fetch()’。

我环顾四周寻找类路径中缺少的任何jar子,但没有看到任何遗漏。 你知道代码是哪个jar吗? 我搜索了这个错误并搜索了这个组,但什么也没找到。 谢谢,大卫

使用Google appengine,您无法在本地Java应用程序中使用这些api。 只有在使用google appengine sdk开发和部署Web应用程序时,这才有效。 这只是为了这种方式而设计的。

当您使用此API时,它将使用http客户端,并且在应用引擎环境的情况下,它将使用谷歌基础设施。 如果您仍想对为google appengine设计的应用程序进行unit testing,则可以考虑使用LocalURLServiceFactory。

这是我为博客创建的一个简单的工作示例:

 package org.appEngineAsync.server; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Future; import org.appEngineAsync.client.GreetingService; import com.google.appengine.api.urlfetch.HTTPHeader; import com.google.appengine.api.urlfetch.HTTPRequest; import com.google.appengine.api.urlfetch.HTTPResponse; import com.google.appengine.api.urlfetch.URLFetchServiceFactory; import com.google.gwt.user.server.rpc.RemoteServiceServlet; @SuppressWarnings("serial") public class GreetingServiceImpl extends RemoteServiceServlet implements GreetingService { private HTTPRequest request = null; HTTPHeader acceptCharsetHeader = new HTTPHeader("Accept-Charset", "utf-8"); // All three of these data types are synchronized for thread safety List> responses = new CopyOnWriteArrayList>(); protected List tempSingleUrl = new CopyOnWriteArrayList(); StringBuffer sb = new StringBuffer(); public String greetServer(String input) throws Exception { List urlsToFetchInParrallel = new ArrayList(); urlsToFetchInParrallel.add("http://gdata.youtube.com/feeds/api/channels?q=" + input + "&start-index=1&max-results=10&v=2"); urlsToFetchInParrallel.add("http://gdata.youtube.com/feeds/api/channels?q=" + input + "&start-index=11&max-results=10&v=2"); urlsToFetchInParrallel.add("http://gdata.youtube.com/feeds/api/channels?q=" + input + "&start-index=21&max-results=10&v=2"); urlsToFetchInParrallel.add("http://gdata.youtube.com/feeds/api/channels?q=" + input + "&start-index=31&max-results=10&v=2"); urlsToFetchInParrallel.add("http://gdata.youtube.com/feeds/api/channels?q=" + input + "&start-index=41&max-results=10&v=2"); urlsToFetchInParrallel.add("http://gdata.youtube.com/feeds/api/channels?q=" + input + "&start-index=51&max-results=10&v=2"); urlsToFetchInParrallel.add("http://gdata.youtube.com/feeds/api/channels?q=" + input + "&start-index=61&max-results=10&v=2"); urlsToFetchInParrallel.add("http://gdata.youtube.com/feeds/api/channels?q=" + input + "&start-index=71&max-results=10&v=2"); urlsToFetchInParrallel.add("http://gdata.youtube.com/feeds/api/channels?q=" + input + "&start-index=81&max-results=10&v=2"); urlsToFetchInParrallel.add("http://gdata.youtube.com/feeds/api/channels?q=" + input + "&start-index=91&max-results=10&v=2"); return performHttpRequest(urlsToFetchInParrallel); } // pass in 10 urls at a time private final String performHttpRequest(List urls) throws NumberFormatException, Exception { URL url = null; request = null; byte[] tempBuffer = null; byte[] buffer = null; ByteArrayInputStream memoryStream = null; ByteArrayOutputStream baos = null; final int buffSize = 8192; int size = 0; sb.setLength(0); responses.clear(); try { for (String urlString : urls) { url = new URL(urlString); request = new HTTPRequest(url); request.addHeader(acceptCharsetHeader); responses.add(URLFetchServiceFactory.getURLFetchService().fetchAsync(request)); } for (Future futureResponse : responses) { try { memoryStream = new ByteArrayInputStream(futureResponse.get().getContent()); tempBuffer = new byte[buffSize]; baos = new ByteArrayOutputStream(); while ((size = memoryStream.read(tempBuffer, 0, buffSize)) != -1) { baos.write(tempBuffer, 0, size); } buffer = baos.toByteArray(); } catch (Exception ex) { // TODO: log or take other action return null; } finally { try { baos.close(); } catch (Exception ex) { // TODO: log } } // TODO: put this on one line when done debugging String responseString = new String(buffer, "UTF-8"); sb.append(responseString); } // TODO: put this on one line when done debugging String allResponsesString = sb.toString(); return allResponsesString; } catch (Exception ex) { // TODO: log return null; } finally { try { request = null; url = null; memoryStream = null; tempBuffer = null; baos = null; } catch (Exception ex) { // TODO: log return null; } } } } 

我唯一的猜测是,由于Future在尝试访问其响应之前没有完成。 但这是一个完整而彻底的猜测!

也许在访问其.get()之前检查每个futureResponses .isDone().isCancelled() .get()