BoolQueryBuilder toString问题

线上环境,因为一个 toString 问题,导致了页面查询导出功能不可用。

一开始,很是纳闷,不就是打印个对象嘛,咋还能报错呢?查看错误日志:

BAD_REQUEST_ERROR:org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.StackOverflowError
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:982)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    .......

Caused by: java.lang.StackOverflowError
    at com.fasterxml.jackson.core.json.UTF8JsonGenerator._flushBuffer(UTF8JsonGenerator.java:2085)
    at com.fasterxml.jackson.core.json.UTF8JsonGenerator.writeRaw(UTF8JsonGenerator.java:684)
    at com.fasterxml.jackson.core.util.DefaultIndenter.writeIndentation(DefaultIndenter.java:91)
    at com.fasterxml.jackson.core.util.DefaultPrettyPrinter.beforeObjectEntries(DefaultPrettyPrinter.java:284)
    at com.fasterxml.jackson.core.json.UTF8JsonGenerator._writePPFieldName(UTF8JsonGenerator.java:377)
    at com.fasterxml.jackson.core.json.UTF8JsonGenerator.writeFieldName(UTF8JsonGenerator.java:183)
    at org.elasticsearch.common.xcontent.json.JsonXContentGenerator.writeFieldName(JsonXContentGenerator.java:147)
    at org.elasticsearch.common.xcontent.XContentBuilder.field(XContentBuilder.java:288)
    at org.elasticsearch.common.xcontent.XContentBuilder.field(XContentBuilder.java:270)
    at org.elasticsearch.common.xcontent.XContentBuilder.startArray(XContentBuilder.java:233)
    at org.elasticsearch.index.query.BoolQueryBuilder.doXArrayContent(BoolQueryBuilder.java:194)
    at org.elasticsearch.index.query.BoolQueryBuilder.doXContent(BoolQueryBuilder.java:165)
    at org.elasticsearch.index.query.QueryBuilder.toXContent(QueryBuilder.java:37)
    at org.elasticsearch.index.query.BoolQueryBuilder.doXArrayContent(BoolQueryBuilder.java:196)
    at org.elasticsearch.index.query.BoolQueryBuilder.doXContent(BoolQueryBuilder.java:165)
    at org.elasticsearch.index.query.QueryBuilder.toXContent(QueryBuilder.java:37)
    at org.elasticsearch.index.query.BoolQueryBuilder.doXArrayContent(BoolQueryBuilder.java:196)
    at org.elasticsearch.index.query.BoolQueryBuilder.doXContent(BoolQueryBuilder.java:165)
    at org.elasticsearch.index.query.QueryBuilder.toXContent(QueryBuilder.java:37)
    at org.elasticsearch.index.query.BoolQueryBuilder.doXArrayContent(BoolQueryBuilder.java:196)
    at org.elasticsearch.index.query.BoolQueryBuilder.doXContent(BoolQueryBuilder.java:165)
    at org.elasticsearch.index.query.QueryBuilder.toXContent(QueryBuilder.java:37)
    at org.elasticsearch.index.query.BoolQueryBuilder.doXArrayContent(BoolQueryBuilder.java:196)
    at org.elasticsearch.index.query.BoolQueryBuilder.doXContent(BoolQueryBuilder.java:165)
    at org.elasticsearch.index.query.QueryBuilder.toXContent(QueryBuilder.java:37)
    at org.elasticsearch.index.query.BoolQueryBuilder.doXArrayContent(BoolQueryBuilder.java:196)
    at org.elasticsearch.index.query.BoolQueryBuilder.doXContent(BoolQueryBuilder.java:165)
    ......

居然发生了堆栈溢出异常!按照之前的经验,StackOverflowError 异常一般都是死循环导致的。继续看下面的日志,可以看到 BoolQueryBuilder.doXArrayContent 一直在循环输出,这样势必会占用大量的堆栈信息,也就导致了我们上面看到的栈溢出异常了。


为什么会出现这样的问题?

发现组装 ES查询条件的时候,有下面的代码:

private BoolQueryBuilder buildQueryDsl(CollectTransferReq req) {
    BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
    // 仓库
    if (ObjectUtil.isNotNull(req.getWarehouseId())) {
        boolQuery.filter(QueryBuilders.termQuery("warehouseId", req.getWarehouseId()));
    }
    if (CollectionUtils.isNotEmpty(req.getNationalLineTypes())) {
        boolQuery.filter(QueryBuilders.termsQuery("nationalLineType", req.getNationalLineTypes()));
    }
    // 车牌号
    if (StringUtils.equals(req.getLicenseNumber(), WmsMagicValue.ONE_STR)) {
        boolQuery.filter(boolQuery.mustNot(QueryBuilders.termQuery("licenseNumber", "")));
        // boolQuery.mustNot(QueryBuilders.termQuery("licenseNumber", ""));
    }
    logger.info("集货转运查询组装dsl出参:{}", boolQuery);
    return boolQuery;
}

这就相当于是在 BoolQueryBuilder 对象中,引入了 BoolQueryBuilder 属性,导致在 toString的时候,循环调用,从来发生栈溢出!

修改后的代码:

if (StringUtils.equals(req.getLicenseNumber(), WmsMagicValue.ONE_STR)) {
    boolQuery.mustNot(QueryBuilders.termQuery("licenseNumber", ""));
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容