上传多个文件到Box失败,出现HTTP客户端错误“连接仍在分配中”。

4

我正在运行Box java SDK v3.0.5 (最新版本)。在我的应用程序中,我使用远程用户Box实现同步,当一个用户在本地创建多个文件时,我需要在Box端创建它们。

我的客户端是通过以下代码创建的:

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个回答

3

我自己回答了我的问题。

原始问题“连接仍然被分配”确实如上面的问题所假设的那样真实。根本原因是需要一个线程安全的连接(用于Box SDK中的HTTP客户端)......但由于这段代码在Box SDK中,因此我唯一能够尝试的事情就是使用BoxConnectionManager(它提供线程安全性)。

但是当我使用BoxConnectionManager时,我遇到了上述第二个错误:证书中的主机名不匹配。这个错误是由于类路径上有不同版本的Apache HTTP客户端引起的。我的服务器(eXo Platform 4.0)提供了Apache HTTP客户端4.1.2,但Box SDK需要4.2.5。在安装我的应用程序后,服务器库同时拥有这些JAR文件,并且4.1.2出现为Box加载。如果删除4.1.2的JAR,则一切都按预期工作,那些可以这样做的人将不会像我一样遇到SSL证书错误。但是我不能这样做,因为eXo的其他部分已经认证了HTTP客户端4.1.2,我不想为它们冒险。

我的解决方案是在BoxClient中使用自定义的BoxRESTClient。感谢Box团队,他们可以创建一个实例,其中包括低级细节,例如REST客户端。BoxConnectionManager通过提供自己的BoxRESTClient来隐藏这一点,但也可以从外部代码创建此REST客户端,而不使用管理器。我的自定义REST客户端适用于HTTP客户端4.1.2,并具有“允许所有”主机名验证器。

到目前为止,我的解决方案是可接受的,并且运行良好。以下是我使用的代码片段:

如何创建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。


0

从堆栈跟踪来看,这似乎是SSL证书未安装。您可以尝试在同一台机器上运行两个代码(使用和不使用ConnectionManager),看看一个是否失败,一个是否成功?


如果没有_ConnectionManager_运行,则会出现此问题的原始问题:连接仍然被分配。使用管理器会因SSL证书错误而失败。 - Peter Nedonosko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接