有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java多文件上载到Box失败,HTTP客户端错误“连接仍已分配”

我正在运行Box java SDK v3。0.5(最新版本)。在我的应用程序中,我实现了与远程用户框的同步,当用户在本地创建多个文件时,我应该在框侧创建它们

我的客户端由以下代码创建:

this.client = new BoxClient(key, clientSecret, hub, parser, config);

使用单文件上传,一切正常。但当多个文件在单线程中逐个提交并使用此代码时:

BoxFileUploadRequestObject obj = BoxFileUploadRequestObject.uploadFileRequestObject(parentId,                                                              name,data);
  obj.setLocalFileCreatedAt(created.getTime());
  obj.put("created_at", formatDate(created));
  return client.getFilesManager().uploadFile(obj);

在我的应用程序中,我面临以下例外情况:

java.lang.IllegalStateException: Invalid use of SingleClientConnManager: connection still allocated.
Make sure to release the connection before allocating another one.
    at org.apache.http.impl.conn.SingleClientConnManager.getConnection(SingleClientConnManager.java:216) ~[httpclient-4.1.2.jar:4.1.2]
    at org.apache.http.impl.conn.SingleClientConnManager$1.getConnection(SingleClientConnManager.java:190) ~[httpclient-4.1.2.jar:4.1.2]
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:401) ~[httpclient-4.1.2.jar:4.1.2]
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820) ~[httpclient-4.1.2.jar:4.1.2]
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:754) ~[httpclient-4.1.2.jar:4.1.2]
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:732) ~[httpclient-4.1.2.jar:4.1.2]
    at com.box.boxjavalibv2.BoxRESTClient.getResponse(BoxRESTClient.java:148) ~[boxjavalibv2-3.0.5.jar:na]
    at com.box.boxjavalibv2.BoxRESTClient.execute(BoxRESTClient.java:98) ~[boxjavalibv2-3.0.5.jar:na]
    at com.box.boxjavalibv2.BoxRESTClient.execute(BoxRESTClient.java:72) ~[boxjavalibv2-3.0.5.jar:na]
    at com.box.boxjavalibv2.resourcemanagers.AbstractBoxResourceManager.getResponseAndParse(AbstractBoxResourceManager.java:118) ~[boxjavalibv2-3.0.5.jar:na]
    at com.box.boxjavalibv2.filetransfer.BoxFileUpload.execute(BoxFileUpload.java:58) ~[boxjavalibv2-3.0.5.jar:na]
    at com.box.boxjavalibv2.resourcemanagers.BoxFilesManagerImpl.uploadFile(BoxFilesManagerImpl.java:134) ~[boxjavalibv2-3.0.5.jar:na]
    at org.exoplatform.clouddrive.box.BoxAPI.createFile(BoxAPI.java:745) ~[exo-clouddrive-services-core-1.1.0-SNAPSHOT.jar:1.1.0-SNAPSHOT]
.........

最后只有第一个文件上传成功

在谷歌搜索这个错误后,我发现使用线程安全连接可能会有所帮助。但是,由于这些代码都在Box SDK中,我能够尝试的一件事是在客户端创建中使用BoxConnectionManager(它提供线程安全):

BoxConnectionManagerBuilder connManager = new BoxConnectionManagerBuilder();
this.client = new BoxClient(key, clientSecret, hub, parser, config, connManager.build());

实际上,当我尝试访问Box API服务时,在将连接管理器发布到客户端时,会出现另一个问题:

Caused by: com.box.restclientv2.exceptions.BoxRestException: null
at com.box.boxjavalibv2.BoxRESTClient.handleException(BoxRESTClient.java:183) ~[boxjavalibv2-3.0.5.jar:na]
at com.box.boxjavalibv2.BoxRESTClient.execute(BoxRESTClient.java:118) ~[boxjavalibv2-3.0.5.jar:na]
at com.box.boxjavalibv2.BoxRESTClient.execute(BoxRESTClient.java:72) ~[boxjavalibv2-3.0.5.jar:na]
at com.box.boxjavalibv2.resourcemanagers.AbstractBoxResourceManager.getResponseAndParse(AbstractBoxResourceManager.java:118) ~[boxjavalibv2-3.0.5.jar:na]
at com.box.boxjavalibv2.resourcemanagers.AbstractBoxResourceManager.getResponseAndParseAndTryCast(AbstractBoxResourceManager.java:108) ~[boxjavalibv2-3.0.5.jar:na]
at com.box.boxjavalibv2.resourcemanagers.BoxEventsManagerImpl.getEventOptions(BoxEventsManagerImpl.java:60) ~[boxjavalibv2-3.0.5.jar:na]
at org.exoplatform.clouddrive.box.BoxAPI.updateChangesLink(BoxAPI.java:671) ~[exo-clouddrive-services-core-1.1.0-SNAPSHOT.jar:1.1.0-SNAPSHOT]
... 76 common frames omitted
Caused by: javax.net.ssl.SSLException: hostname in certificate didn't match: <api.box.com/74.112.185.97> != <*.box.com> OR <*.box.com> OR <box.com>
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:228) ~[httpclient-4.1.2.jar:4.1.2]
at org.apache.http.conn.ssl.BrowserCompatHostnameVerifier.verify(BrowserCompatHostnameVerifier.java:54) ~[httpclient-4.1.2.jar:4.1.2]
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:149) ~[httpclient-4.1.2.jar:4.1.2]
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:130) ~[httpclient-4.1.2.jar:4.1.2]
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:397) ~[httpclient-4.1.2.jar:4.1.2]
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:495) ~[httpclient-4.1.2.jar:4.1.2]
at org.apache.http.conn.scheme.SchemeSocketFactoryAdaptor.connectSocket(SchemeSocketFactoryAdaptor.java:62) ~[httpclient-4.1.2.jar:4.1.2]
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:148) ~[httpclient-4.1.2.jar:4.1.2]
at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:149) ~[httpclient-4.1.2.jar:4.1.2]
at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:121) ~[httpclient-4.1.2.jar:4.1.2]
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:573) ~[httpclient-4.1.2.jar:4.1.2]
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:425) ~[httpclient-4.1.2.jar:4.1.2]
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820) ~[httpclient-4.1.2.jar:4.1.2]
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:754) ~[httpclient-4.1.2.jar:4.1.2]
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:732) ~[httpclient-4.1.2.jar:4.1.2]
at com.box.boxjavalibv2.BoxRESTClient.getResponse(BoxRESTClient.java:148) ~[boxjavalibv2-3.0.5.jar:na]
at com.box.boxjavalibv2.BoxRESTClient.execute(BoxRESTClient.java:98) ~[boxjavalibv2-3.0.5.jar:na]
... 81 common frames omitted

仅供参考,在我的开发环境中,我正在8443端口上运行Tomcat。但是对于默认的REST客户机(不向客户机构造函数发布连接管理器),所有这些都工作得很好

我可以应用什么解决方案来执行多个文件上传到Box


共 (2) 个答案

  1. # 1 楼答案

    我自己回答我的问题

    最初的问题“连接仍然被分配”是真实的,正如上面问题中所假设的那样。根本原因是需要

    thread-safe connection (for HTTP client in Box SDK)... But as this code are in the Box SDK, the single thing that I was able to try it's use of BoxConnectionManager (which provides thread-safe).

    但是当我使用BoxConnectionManager时,我遇到了提到的第二个错误:证书中的主机名不匹配。此错误是由于类路径上的Apache HTTP客户端版本不同造成的。我的服务器(eXo平台4.0)提供Apache HTTP客户端4.1.2,但Box SDK需要4.2.5。安装my app后,服务器库中同时包含这两个JAR,4.1.2显示为已加载。如果删除4.1.2中的JAR,那么一切都会按预期进行,能够这样做的人将不会像我那样面临SSL证书错误。但我不能这样做,因为eXo的其他部分已通过HTTP client 4.1.2认证,我不想让它们冒风险

    我的解决方案是在BoxClient中使用自定义BoxRESTClient。多亏了Box团队,我们才有可能创建一个具有底层细节的客户机实例,比如REST客户机。BoxConnectionManager通过提供自己的BoxRESTClient来隐藏这一点,但也可以从外部代码创建这个REST客户机,而无需使用管理器。我的自定义REST客户端采用HTTP客户端4.1.2,并具有“allow all”主机名验证程序

    到目前为止,我的解决方案是可以接受的,而且效果很好。下面是我使用的代码片段:

    如何创建Box客户端:

    BoxResourceHub hub = new BoxResourceHub();
    BoxJSONParser parser = new BoxJSONParser(hub);
    this.client = new BoxClient(key,
                                clientSecret,
                                hub,
                                parser,
                                new RESTClient(),
                                new BoxConfigBuilder().build());
    

    和定制RESTClient

    class RESTClient extends BoxRESTClient {
    
      final HttpClient httpClient;
    
      @SuppressWarnings("deprecation")
      RESTClient() {
        super();
        SchemeRegistry schemeReg = new SchemeRegistry();
        schemeReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        SSLSocketFactory socketFactory;
        try {
          socketFactory = new SSLSocketFactory(SSLSocketFactory.TLS,
                                             null,
                                             null,
                                             null,
                                             null,
                                             null,
                                             SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        } catch (Exception ex) {
          throw new IllegalStateException("Failure initializing default SSL context for Box REST client", ex);
        }
        schemeReg.register(new Scheme("https", socketFactory, 443));
        ClientConnectionManager connectionManager = new ThreadSafeClientConnManager(new BasicHttpParams(), schemeReg);
        this.httpClient = new DefaultHttpClient(connectionManager);
      }
    
      @Override
      public HttpClient getRawHttpClient() {
        return httpClient;
      }
    }
    

    通过这种方式,Box SDK运行良好,可以将多个文件上传到用户Box

  2. # 2 楼答案

    从堆栈跟踪来看,似乎未安装ssl证书。你能试着在同一台机器上运行这两个代码(有和没有ConnectionManager)吗?一个失败,一个成功吗