为什么我在 AppEngine 中使用 HttpURLConnection 会得到 ClassCastException?

Why do I get ClassCastException using HttpURLConnection in AppEngine?

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

我知道由于 SOP(同源策略)而无法从客户端执行此操作,而且 RequestBuilder 不是服务器上的解决方案。我也遵循了 the web site and 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

无需发出真正的请求,远程服务运行良好:它能够序列化 return 对象到客户端。该问题与客户端和服务器之间的通信无关,更像是 AppEngine 不支持 HttpURLConnection。但它应该在服务器上(不是吗?)

如有任何想法,我们将不胜感激!提前致谢

您的问题与 GWT 无关:只要您在服务器上 运行,您可以使用任何 'normal' Java 并且它会工作,除非 AppEngine 有限制.

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

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

谢谢@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();

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