Camel recipientList 太长会导致 StackOverflow 错误

Camel recipientList so long it causes StackOverflow error

在后续步骤中将数据写入这些文件之前,我正在使用收件人列表初始化 30 多个带有 header 的文件。 (edit) 我正在按给定字段将文件拆分为大约 30 个文件,这些新文件需要与原始文件相同的 header。 header 和 split-by-type 是将使用文件的应用程序的要求。

超过 30 个,comma-separated,当 camel 尝试解析字符串时,一个字符串中的完整文件路径会导致 Whosebug 错误。我通过增加堆栈大小解决了这个问题(目前)。

但必须有更强大的解决方案,也许我可以以某种方式使用相对文件路径?

(编辑)代码:

@Component
public class SplitterRoutesBuilder extends SpringRouteBuilder {

   @Autowired
   private ApplicationConfig configuration;

   @Autowired
   private MyFileFormat fileFormat;

   @Override
   public void configure() throws Exception {

     from(configuration.getFrom())
     .to("bean:splitFileByProductType?method=initialize(*)")
     // split file
     .split(body().tokenize(fileFormat.getLineEnd())).streaming().to("bean:splitFileByProductType?method=processLine(*)")
     .recipientList(header(SplitFileByProductType.WRITE_FILENAME_HEADER))
     .end();
    }
}

然后,在 SplitFileByProductType 中:

   public void processLine(Exchange exchange) throws EmptyLineException {
       String line = exchange.getIn().getBody(String.class);
       String originalFileName = (String) exchange.getIn().getHeader(ORIGINAL_FILENAME_HEADER);
       // various checks and errorhandling omitted for clariry
       setoutputFileExchangeHeader(exchange, values[index].trim(), originalFileName, leftOversFileName);
       exchange.getIn().setBody(line + fileFormat.getLineEnd());
}

实际工作到这里:

private void setoutputFileExchangeHeader(Exchange exchange, String product, String originalFileName, String leftOversFileName) {
    if (isProductType(product)) {
        // a regular line, write to appropriate file
        exchange.getIn().setHeader(WRITE_FILENAME_HEADER,
                fileNameFormatter.getProductFileDestination(originalFileName, product));
    } else if (PRODUCT_COLUMN_NAME.equals(product)) {
        // this is the header line, write the header to all files
        exchange.getIn().setHeader(WRITE_FILENAME_HEADER, getAllFileNames(originalFileName, leftOversFileName));
    } else {
        // product not regognized, line goes to 'rest'
        exchange.getIn().setHeader(WRITE_FILENAME_HEADER, leftOversFileName);
    }
}

你是对的。我能够使用实际的 Apache Camel 2.21.1 通过以下测试重现它。 recipientListWhosebugError 上失败,端点列表以逗号分隔。但是,如果您传递 List<String> 个端点,该路由将按预期工作。因此,您可以修改 SplitFileByProductType 处理器以创建端点列表,而不是逗号分隔的字符串。


public class LongRecipientListCausesWhosebug extends CamelTestSupport {

    private static final int COUNT = 300;
    private static final String BASE_DIR = "D://temp/cameltest/";

    @Override
    protected RoutesBuilder createRouteBuilder() throws Exception {
        return new RouteBuilder() {
            @Override
            public void configure() throws Exception {
                from("direct:in")
                        .recipientList(header("to"))
                        .to("mock:done");
            }
        };
    }

    @Before
    public void clenup() throws Exception{
        FileUtils.deleteDirectory(new File(BASE_DIR));
    }

    @Test
    public void fails() throws Exception { //fails, throws WhosebugError with header("to") of type String
        MockEndpoint mockEndpoint = getMockEndpoint("mock:done");
        String recipientListString = IntStream.range(0,COUNT).mapToObj(subDir -> "file:"+BASE_DIR+subDir).collect(Collectors.joining(","));
        template.sendBodyAndHeader("direct:in","", "to", recipientListString);
        mockEndpoint.assertIsSatisfied();
        Assert.assertEquals(COUNT, new File(BASE_DIR).listFiles().length);
    }

    @Test
    public void passes() throws Exception { //pass with header("to") of type List<String>
        MockEndpoint mockEndpoint = getMockEndpoint("mock:done");
        List<String> recipientListList = IntStream.range(0,COUNT).mapToObj(subDir -> "file:"+BASE_DIR+subDir).collect(Collectors.toList());
        template.sendBodyAndHeader("direct:in","", "to", recipientListList);
        mockEndpoint.assertIsSatisfied();
        Assert.assertEquals(COUNT, new File(BASE_DIR).listFiles().length);
    }
}