为什么我在AppEngine中使用HttpURLConnection获取ClassCastException?

时间:2015-09-17 18:23:11

标签: google-app-engine gwt classcastexception urlfetch cross-site

我尝试从使用App Engine的GWT应用程序调用外部Web服务(不是我的)。

我知道由于SOP(同源策略)而无法从客户端执行此操作,并且RequestBuilder不是服务器上的解决方案。我按照the web site上的教程和using java.net以及

进行了操作

这是客户端

AsyncCallback<CustomObject> callback = new AsyncCallback<CustomObjectCustomObject>() {

                @Override
                public void onFailure(Throwable caught) {
                    caught.printStackTrace();

                }

                @Override
                public void onSuccess(CustomObject result) {
                    // code omitted
                }
            };

service.callMethod(aString, callback);

这是服务器

try {
            String xmlRequest = "xmlToSend";
            URL url = new URL("https://www.externalWebService.com");
            HttpURLConnection  conn = (HttpURLConnection)url.openConnection();
            conn.setRequestMethod("POST");
            conn.setAllowUserInteraction(false);
            conn.setDoOutput(true);
            conn.setRequestProperty("Content-Type","application/soap+xml");
            conn.setRequestProperty( "Content-length", Integer.toString(xmlRequest.length()));
            conn.setRequestProperty("charset", "utf-8");
            conn.setConnectTimeout(10000);



            OutputStream rawOutStream = conn.getOutputStream();
            PrintWriter pw = new PrintWriter(rawOutStream);
            pw.print(xmlRequest);
            pw.flush();
            pw.close();     

            if(conn.getResponseCode() != 200){
                // Something...
            }

我在conn.getResponseCode()处发出同样的错误:

java.lang.ClassCastException: com.google.appengine.repackaged.org.apache.http.message.BasicHttpRequest cannot be cast to com.google.appengine.repackaged.org.apache.http.client.methods.HttpUriRequest

在没有提出真实请求的情况下,远程服务运行良好:它能够序列化并将对象返回给客户端。该问题与客户端和服务器之间的通信无关,它更像是AppEngine不支持HttpURLConnection。但它应该在服务器上(不是吗?)

任何想法都会得到高度赞赏!提前致谢

2 个答案:

答案 0 :(得分:1)

您的问题与GWT无关:只要您在服务器上运行,您就可以使用任何“普通”Java,除非AppEngine有限制,否则它将起作用。

您的类中似乎已导入Apache {HttpClient的repackaged版本。你不应该这样做:下载你自己的HttpClient .jar,将它添加到依赖项并使用它。

AppEngine在HttpClient方面也存在一些问题。有一个可用的适配器here可以解决大部分问题。

答案 1 :(得分:0)

谢谢@Marcelo,你是对的!

这是我找到的解决方案。

我在构建路径中添加了httpcore.jarhttpclient.jar,并为服务器编写了以下代码(客户端是相同的):

    String xmlRequest = "xmlToSend";

    CloseableHttpClient httpclient = HttpClients.custom().build();

    //RequestConfig requestConfig = RequestConfig.custom()
    //      .setConnectionRequestTimeout(10000)
    //      .build();

    try {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        Writer writer = new OutputStreamWriter(out);
        writer.write(xmlToSend);
        writer.flush();
        writer.close();

        HttpPost request = new HttpPost("https://www.externalWebService.com/path");
        request.setEntity(new ByteArrayEntity(out.toByteArray()));
        //request.setConfig(requestConfig);


    CloseableHttpResponse response = httpclient.execute(request);

    if(response.getStatusLine().getStatusCode() == 200){
                // retrieve content with a BufferReader 
                // from response.getEntity().getContent()
                ...
            }

代码有效并且是最新的。

修改

使用代理时,这是解决方案的其余部分。我的只处理NTCredentials,否则可以使用UsernamePasswordCredentials代替。

HttpHost proxy = new HttpHost("addresse.proxy.com", port);

CredentialsProvider credsProvider = new BasicCredentialsProvider();
    credsProvider.setCredentials(
            new AuthScope(proxy),
            new NTCredentials(System.getProperty("user.name") + ":" + password));

RequestConfig requestConfig = RequestConfig.custom()
        .setProxy(proxy)
        .build();


CloseableHttpClient httpclient = HttpClients.custom()
        .setDefaultCredentialsProvider(credsProvider)
        .setDefaultRequestConfig(requestConfig)
        .build();

再次感谢您的帮助,我真的很感激!