This is an automated email from the ASF dual-hosted git repository. reta pushed a commit to branch 3.5.x-fixes in repository https://gitbox.apache.org/repos/asf/cxf.git
commit f2d318ccacce27e6d77d3344393cf2cf4a69ec05 Author: Rand Hillerøe <[email protected]> AuthorDate: Thu Sep 7 22:53:24 2023 +0200 [CXF-8925] Prevent double logging on fault in out chain (#1426) Signed-off-by: Randi H <[email protected]> (cherry picked from commit d6842c9aa6fd15d5a9a64286dceed303e9829e1c) (cherry picked from commit 1c785dfb906da4767bc09f79143ec5f761168742) --- .../cxf/ext/logging/LoggingOutInterceptor.java | 5 ++ .../java/org/apache/cxf/ext/logging/FaultTest.java | 69 ++++++++++++++++++++++ .../apache/cxf/ext/logging/LogEventSenderMock.java | 13 +++- 3 files changed, 84 insertions(+), 3 deletions(-) diff --git a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingOutInterceptor.java b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingOutInterceptor.java index c6673c06dc..7e68a7c5cc 100644 --- a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingOutInterceptor.java +++ b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingOutInterceptor.java @@ -61,6 +61,11 @@ public class LoggingOutInterceptor extends AbstractLoggingInterceptor { public void handleMessage(Message message) throws Fault { if (isLoggingDisabledNow(message)) { return; + } else { + //ensure only logging once for a certain message + //this can prevent message logging again when fault + //happen after PRE_STREAM phase(LoggingOutInterceptor is called both in out chain and fault out chain) + message.put(LIVE_LOGGING_PROP, Boolean.FALSE); } createExchangeId(message); final OutputStream os = message.getContent(OutputStream.class); diff --git a/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/FaultTest.java b/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/FaultTest.java new file mode 100644 index 0000000000..dd99dcebfa --- /dev/null +++ b/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/FaultTest.java @@ -0,0 +1,69 @@ +/** + * 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.cxf.ext.logging; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; + +import org.apache.cxf.message.Exchange; +import org.apache.cxf.message.ExchangeImpl; +import org.apache.cxf.message.Message; +import org.apache.cxf.message.MessageImpl; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class FaultTest { + @Test + public void logOnceForFaultsOccurringAfterLoggingOutPhase() throws IOException { + + Message message = new MessageImpl(); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + message.setContent(OutputStream.class, outputStream); + Exchange exchange = new ExchangeImpl(); + message.setExchange(exchange); + LogEventSenderMock logEventSender = new LogEventSenderMock(); + LoggingOutInterceptor interceptor = new LoggingOutInterceptor(logEventSender); + + interceptor.handleMessage(message); + OutputStream preFaultOut = message.getContent(OutputStream.class); + + // simulate fault happening after message is already handled in out chain + interceptor.handleFault(message); // first we unwind + interceptor.handleMessage(message); // then we handle in the fault chain + + byte[] payload = "TestMessage".getBytes(StandardCharsets.UTF_8); + // simulate writing that is setup based on the pre-fault output stream on message + // this is what happens when StaxOutInterceptor is in use + // StaxOutInterceptor sets XmlStreamWriter content wrapping the OutputStream in the message at that time + // it does not recreate XmlStreamWriter during out fault chain, as it is already set during out chain + preFaultOut.write(payload); + + // Then close is called through close on Conduit, + // which means close is called on the OutputStream in message at the time of close + OutputStream postFaultOut = message.getContent(OutputStream.class); + postFaultOut.close(); + + assertEquals(1, logEventSender.getLogEvents().size()); + assertEquals("TestMessage", logEventSender.getLogEvents().get(0).getPayload()); + } +} diff --git a/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/LogEventSenderMock.java b/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/LogEventSenderMock.java index 8f723be169..645faefb74 100644 --- a/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/LogEventSenderMock.java +++ b/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/LogEventSenderMock.java @@ -18,20 +18,27 @@ */ package org.apache.cxf.ext.logging; +import java.util.ArrayList; +import java.util.List; + import org.apache.cxf.ext.logging.event.LogEvent; import org.apache.cxf.ext.logging.event.LogEventSender; public class LogEventSenderMock implements LogEventSender { - private LogEvent logEvent; + private List<LogEvent> logEvents = new ArrayList<>(); @Override public void send(LogEvent event) { - logEvent = event; + logEvents.add(event); } public LogEvent getLogEvent() { - return logEvent; + return logEvents.isEmpty() ? null : logEvents.get(0); + } + + public List<LogEvent> getLogEvents() { + return logEvents; } }
