Hello Camel community,

I'm encountering a StackOverflowError when running a Camel test that worked 
perfectly fine with the older (unmaintained – 2.x) Camel version. However, 
after migrating to Camel 3.14 and Camel 4.8, the same test fails:


  *   In (unmaintained) Camel 3.14.7 the process hangs for a long time with the 
following error message and finally terminates with a StackOverflowError.

*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message 
transform method call failed at 
s\src\java.instrument\share\native\libinstrument\JPLISAgent.c line: 876

  *   In Camel 4.8, the test is terminated more quickly, but with the same 
error.
Here is a simplified test setup for reference:
The route uses a loop of 2000 iterations. Each iteration calls a subroute which 
is marked as transacted and contains a split step using XPath.


public class JdbcLoopSplitterTransactedTest extends CamelTestSupport {

    private static final String DSNAME = "ds";
    private static EmbeddedDataSource ds;
    private static PlatformTransactionManager txManager;
    private static SpringTransactionPolicy txPolicy;

    private final String xmlBody = "<messages>" +
            "<message><name>John</name></message>" +
            "<message><name>Jane</name></message>" +
            "<message><name>Jim</name></message>" +
            "<message><name>Jack</name></message>" +
            "<message><name>Jill</name></message>" +
            "</messages>";

    @Override
    protected void bindToRegistry(Registry registry) throws Exception {

        ds = Derby.init(DSNAME);

        txManager = new DataSourceTransactionManager(ds);

        TransactionTemplate txTemplate = new TransactionTemplate(txManager);
        txTemplate.setPropagationBehaviorName("PROPAGATION_REQUIRED");
        txTemplate.setIsolationLevelName("ISOLATION_READ_COMMITTED");
        txTemplate.setTimeout(1800);

        txPolicy = new SpringTransactionPolicy();
        txPolicy.setTransactionManager(txManager);
        txPolicy.setTransactionTemplate(txTemplate);

        registry.bind("txPolicy", txPolicy);
    }

    @AfterAll
    public static void tearDownOnce() {
        Derby.close(DSNAME);
    }


    @Test
    public void testIfLoopCompleted() throws Exception {

        MockEndpoint mock = getMockEndpoint("mock:out");
        mock.expectedMessageCount(1);

        template.sendBody("direct:start", "");

        assertIsSatisfied(context);

    }

    @Override
    protected RouteBuilder createRouteBuilder() {
        return new RouteBuilder() {
            @Override
            public void configure() {
                from("direct:start")
                        .loop(2000)
                        .process(e -> 
System.out.println(e.getIn().getExchange().getProperty("CamelLoopIndex")))
                        .setBody(simple(xmlBody))
                        .to("direct:subroute")
                        .end()
                        .process(e -> System.out.println("completed 
successfully   " + e.getExchangeId()))
                        .to("mock:out");

                from("direct:subroute")
                        .transacted("txPolicy")
                        .split(xpath("/messages/message"))
                        .streaming()
                        .stopOnException()
                        .process(e -> System.out.println("body === " + 
e.getIn().getBody(String.class)))
                        .end();

            }
        };
    }

    private static class Derby {

        public static EmbeddedDataSource init(String db) {
            deleteDatabaseFiles(db);
            EmbeddedDataSource ds = new EmbeddedDataSource();
            ds.setDataSourceName(db);
            ds.setDatabaseName(db);
            ds.setConnectionAttributes("create=true");
            return ds;
        }

        public static void close(String dbName) {
            // unload the driver
            try {
                DriverManager.getConnection("jdbc:derby:;shutdown=true");
            } catch (SQLException e) {
                // it was worth a try...
            }
            deleteDatabaseFiles(dbName);
        }

        private static void deleteDatabaseFiles(String dbName) {
            File root = null;
            File log = null;
            log = new File("derby.log");
            root = new File(dbName);
            if (log.exists()) {
                log.delete();
            }
            if (root.exists()) {
                recursiveDelete(root);
            }

        }

        private static void recursiveDelete(File dir) {
            for (File f : dir.listFiles()) {
                if (f.isDirectory()) {
                    recursiveDelete(f);
                } else {
                    f.delete();
                }
            }
            dir.delete();
        }
    }
}

The issue seems to be related to transaction boundaries and route recursion or 
resource handling in Camel 3+. There is no explicit recursion in the route, but 
internally Camel may be building a deep call stack due to how it handles loop 
combined with transacted and splitter. The StackOverflowError may indicate that 
each loop iteration adds to the call stack without releasing previous frames.

Could you please confirm if this is a known issue or if there are specific 
configurations needed in newer Camel versions to achieve the expected behavior? 
Any guidance or suggestions would be highly appreciated.

Thank you for your support, and I look forward to hearing from you.
Best Regards,

Soheila Esmaeili
Pronouns: She
Senior Developer, TI SAP CP INT CPI (SE)
SAP SE Dietmar-Hopp-Allee 16, 69190 Walldorf, Germany
E: .soheila.esmae...@sap.com<mailto:.soheila.esmae...@sap.com>
T: +49 6227 7-46596<tel:%20%20+49%206227%207-67287>



[cid:image001.png@01DBD622.46A19BB0]

Pflichtangaben/Mandatory Disclosure Statement: www.sap.com/impressum
Diese E-Mail kann Betriebs- oder Geschäftsgeheimnisse oder sonstige 
vertrauliche Informationen enthalten. Sollten Sie diese E-Mail irrtümlich 
erhalten haben, ist Ihnen eine Kenntnisnahme des Inhalts, eine Vervielfältigung 
oder Weitergabe der E-Mail ausdrücklich untersagt. Bitte benachrichtigen Sie 
uns und vernichten Sie die empfangene E-Mail. Vielen Dank.
This e-mail may contain trade secrets or privileged, undisclosed, or otherwise 
confidential information. If you have received this e-mail in error, you are 
hereby notified that any review, copying, or distribution of it is strictly 
prohibited. Please inform us immediately and destroy the original transmittal. 
Thank you for your cooperation.




Reply via email to