getting strange exception trying to implement asyn

2019-01-25 12:45发布

问题:

I'm trying to implement async http in java. Here is the important part of the code:

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<HTTPResponse> futureResponse : responses) 
{ 
    parseResponse(new String(futureResponse.get().getContent())); 
} 

I keep getting this error:

com.google.apphosting.api.ApiProxy$CallNotFoundException: The API package 'urlfetch' or call 'Fetch()' was not found.

I looked around for any jars that were missing from the classpath but didn't see anything missing. Do you know which jar that code is in? I googled the error and also searched through this group but found nothing. Thanks, David

回答1:

With Google appengine, you cannot use those api's in the local java applications. This will work only when you develop and deploy web application using google appengine sdk. This is designed to work this way only.

When you use this api, it will make use of http client and in case of app engine environment, it will make use of google infrastructure. If you still want to unit test the application designed for google appengine you might consider using LocalURLServiceFactory.



回答2:

here's a simple working example of how to do this that I created for my blog:

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<Future<HTTPResponse>> responses = new CopyOnWriteArrayList<Future<HTTPResponse>>();

protected List<String> tempSingleUrl = new CopyOnWriteArrayList<String>();

StringBuffer sb = new StringBuffer();



public String greetServer(String input) throws Exception

{

List<String> urlsToFetchInParrallel = new ArrayList<String>();



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<String> 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<HTTPResponse> 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;

}

}

}

}


回答3:

My only guess is that it's due to a Future not completing before attempting to access its response. But that's a complete and utter guess!

Maybe check each of the futureResponses .isDone() and .isCancelled() before accessing its .get().