首页 > 解决方案 > 来自 http-builder 的二进制内容的 NoSuchMethodError

问题描述

我正在使用 http-builder 0.7.1 来获取二进制内容。这在 Groovy 2/Spock 1 上运行良好,但NoSuchMethodError在 Groovy 3/Spock 2 上会产生 a:

java.lang.NoSuchMethodError: org.codehaus.groovy.runtime.DefaultGroovyMethods.leftShift(Ljava/io/OutputStream;Ljava/io/InputStream;)Ljava/io/OutputStream;
    at groovyx.net.http.HTTPBuilder.defaultSuccessHandler(HTTPBuilder.java:620)
    at groovyx.net.http.RESTClient.defaultSuccessHandler(RESTClient.java:246)
...

其余客户端以非常基本的方式初始化:

restClient = new RESTClient(baseUrl)
restClient.handler.failure = restClient.handler.success

获取二进制内容也很简单:

def response = restClient.get(path: theUrl)

返回的内容带有以下标头:

Content-Disposition: form-data; name="file"; filename="MyPhoto.jpg"
Content-Type: image/jpeg
Content-Transfer-Encoding: binary

此代码适用于 Groovy 2.5.14 和 Spock 1.3-groovy-2.5,但不适用于 Groovy 3.0.8 和 Spock 2.0-groovy-3.0。

任何想法?

标签: groovy

解决方案


正如您所提到的,我相信这是升级到 Groovy 3 的结果。快速浏览一下 DefaultGroovyMethodsleftShift(OutputStream self, InputStream in)之前被标记为已弃用,并且它看起来好像在 3.0 的更改期间被删除(尽管我无法找到确切的位置)。但是,您仍然可以在 IOGroovyMethods 中找到相同的方法。

您的问题是 RESTClient/HttpBuilder 库尚未更新以反映 Groovy 的更改。但是,您可以轻松扩展 RESTClient 并为该defaultSuccessHandler方法提供覆盖,将处理程序指向正确的位置:

@Override
HttpResponseDecorator defaultSuccessHandler(HttpResponseDecorator resp, Object parsedData)
        throws ResponseParseException
{
    try
    {
        //If response is streaming, buffer it in a byte array:
        if (parsedData instanceof InputStream)
        {
            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
            // we've updated the below line
            IOGroovyMethods.leftShift(buffer, (InputStream) parsedData);
            resp.setData(new ByteArrayInputStream(buffer.toByteArray()))
            return resp;
        }
        if (parsedData instanceof Reader)
        {
            StringWriter buffer = new StringWriter();
            // we've updated the below line
            IOGroovyMethods.leftShift(buffer, (Reader) parsedData);
            resp.setData(new StringReader(buffer.toString()))
            return resp;
        }
        return super.defaultSuccessHandler(resp, parsedData)
    }
    catch (IOException ex)
    {
        throw new ResponseParseException(resp, ex);
    }
}

请注意,Groovy 3 还更改了某些 XML 实用程序的位置,这可能会成为 RESTClient 未来的问题。如果需要,您可以在自定义 RESTClient 中覆盖 ParserRegistry 中现有的 XML 条目。


推荐阅读