【问题标题】:Why do I get ClassCastException using HttpURLConnection in AppEngine?为什么我在 AppEngine 中使用 HttpURLConnection 得到 ClassCastException?
【发布时间】:2015-09-17 18:23:11
【问题描述】:

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

我知道由于 SOP(同源策略)和 RequestBuilder 不是服务器上的解决方案,从客户端执行此操作是不可能的。我也按照the web siteusing 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。但它应该在服务器上(不是吗?)

任何想法将不胜感激!提前致谢

【问题讨论】:

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


    【解决方案1】:

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

    看来您已经在课堂上导入了repackaged 版本的 Apache HttpClient。您不应该这样做:下载您自己的 HttpClient .jar,将其添加到依赖项并使用那个。

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

    【讨论】:

    • 我自己没有导入repackaged版本的Apache,我猜它在Ap​​pEngine库的某个地方。
    • -- 对不起,我按回车太快了-- 因为我使用 Maven,我添加了 Google HTTP Client dependency,但问题仍然存在。最后,我会更加努力地使用您给我的链接。它是旧的,有时是不推荐使用的代码,但如果它仍然有效,我接受它。感谢您的帮助!
    • @Felix 它确实很旧,但我多年来一直在生产中使用它,没有任何问题! fetch 服务有很多烦人的限制,除了迁移到 Compute Engine 之外,我们无能为力...
    【解决方案2】:

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

    再次感谢您的帮助,非常感谢!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-11
      • 1970-01-01
      相关资源
      最近更新 更多