gnodet commented on code in PR #26207: URL: https://github.com/apache/camel/pull/26207#discussion_r3958857771
########## components/camel-as2/camel-as2-component/src/test/java/org/apache/camel/component/as2/AS2AsyncMdnContextReuseTest.java: ########## @@ -0,0 +1,127 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.as2; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.as2.api.AS2MediaType; +import org.apache.camel.component.as2.api.AS2MessageStructure; +import org.apache.camel.component.as2.api.AS2ServerConnection; +import org.apache.camel.component.as2.api.AS2SignatureAlgorithm; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.test.AvailablePortFinder; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +/** + * The AS2 request handler creates its {@code HttpContext} once per connection and reuses it for every request handled + * on that connection. A request that asks for an asynchronous MDN leaves the recipient address and the report on that + * context; a later request on the same connection that does not ask for one must not inherit them and trigger a second + * delivery (CAMEL-24435). + */ +public class AS2AsyncMdnContextReuseTest extends AbstractAS2ITSupport { + + @RegisterExtension + AvailablePortFinder.Port jettyPort = AvailablePortFinder.find(); + + private static final String EDI_MESSAGE = """ + UNB+UNOA:1+005435656:1+006415160:1+060515:1434+00000000000778' + UNH+00000000000117+INVOIC:D:97B:UN' + BGM+380+342459+9' + UNT+23+00000000000117' + UNZ+1+00000000000778' + """; + + private AS2ServerConnection serverConnection; + private int targetPort; + + @Override + public void setupResources() throws Exception { + serverConnection = new AS2ServerConnection( + "1.1", "AS2AsyncMdnContextReuseTest Server", "server.example.com", 0, + AS2SignatureAlgorithm.SHA256WITHRSA, null, null, null, "TBD", null, null, + null, null, null, "localhost"); + targetPort = serverConnection.getLocalPort(); + serverConnection.listen("/", new AS2AsyncMDNServerManagerIT.RequestHandler()); + } + + @Override + public void cleanupResources() { + if (serverConnection != null) { + serverConnection.close(); + } + } + + @Test + public void asyncMdnStateDoesNotLeakToTheNextRequestOnTheSameConnection() throws Exception { + MockEndpoint receipts = getMockEndpoint("mock:receipts"); + + // the first message asks for an asynchronous receipt, so exactly one MDN must be delivered + receipts.expectedMessageCount(1); + requestBodyAndHeaders("direct://SEND", EDI_MESSAGE, + as2Headers("http://localhost:" + jettyPort.getPort() + "/handle-receipts")); + receipts.setResultWaitTime(TimeUnit.SECONDS.toMillis(10)); Review Comment: ⚠️ **Test ordering hazard:** `setResultWaitTime` is set _after_ the `requestBodyAndHeaders` call that triggers the MDN. If the MDN arrives and the latch reaches zero between line 79 and line 80, `assertIsSatisfied` on line 81 will still work (latch is already at zero, so it returns immediately without waiting), but the wait-time guarantee is meaningless from a correctness standpoint. It cannot cause a false positive here — `expectedMessageCount(1)` is already satisfied by that point — but the conventional pattern is to configure the endpoint before triggering the action: ```suggestion receipts.setResultWaitTime(TimeUnit.SECONDS.toMillis(10)); requestBodyAndHeaders("direct://SEND", EDI_MESSAGE, as2Headers("http://localhost:" + jettyPort.getPort() + "/handle-receipts")); receipts.assertIsSatisfied(); ``` ########## components/camel-as2/camel-as2-component/src/test/java/org/apache/camel/component/as2/AS2AsyncMdnContextReuseTest.java: ########## @@ -0,0 +1,127 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.as2; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.as2.api.AS2MediaType; +import org.apache.camel.component.as2.api.AS2MessageStructure; +import org.apache.camel.component.as2.api.AS2ServerConnection; +import org.apache.camel.component.as2.api.AS2SignatureAlgorithm; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.test.AvailablePortFinder; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +/** + * The AS2 request handler creates its {@code HttpContext} once per connection and reuses it for every request handled + * on that connection. A request that asks for an asynchronous MDN leaves the recipient address and the report on that + * context; a later request on the same connection that does not ask for one must not inherit them and trigger a second + * delivery (CAMEL-24435). + */ +public class AS2AsyncMdnContextReuseTest extends AbstractAS2ITSupport { + + @RegisterExtension + AvailablePortFinder.Port jettyPort = AvailablePortFinder.find(); + + private static final String EDI_MESSAGE = """ + UNB+UNOA:1+005435656:1+006415160:1+060515:1434+00000000000778' + UNH+00000000000117+INVOIC:D:97B:UN' + BGM+380+342459+9' + UNT+23+00000000000117' + UNZ+1+00000000000778' + """; + + private AS2ServerConnection serverConnection; + private int targetPort; + + @Override + public void setupResources() throws Exception { + serverConnection = new AS2ServerConnection( + "1.1", "AS2AsyncMdnContextReuseTest Server", "server.example.com", 0, + AS2SignatureAlgorithm.SHA256WITHRSA, null, null, null, "TBD", null, null, + null, null, null, "localhost"); + targetPort = serverConnection.getLocalPort(); + serverConnection.listen("/", new AS2AsyncMDNServerManagerIT.RequestHandler()); + } + + @Override + public void cleanupResources() { + if (serverConnection != null) { + serverConnection.close(); + } + } + + @Test + public void asyncMdnStateDoesNotLeakToTheNextRequestOnTheSameConnection() throws Exception { Review Comment: ℹ️ **Test classification:** The class name ends in `Test`, so it runs under maven-surefire as a unit test. The parent POM excludes `**/*IT.java` from surefire and routes those to failsafe. Other AS2 async MDN tests (`AS2AsyncMDNServerManagerIT`) use the `IT` suffix. Since this test is self-contained (sets up its own `AS2ServerConnection` in `setupResources`), running under surefire is fine — the test does not require the failsafe lifecycle. Just confirming this is intentional and not a naming oversight. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
