This is an automated email from the ASF dual-hosted git repository.

reta pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cxf.git


The following commit(s) were added to refs/heads/main by this push:
     new d6842c9aa6 [CXF-8925] Prevent double logging on fault in out chain 
(#1426)
d6842c9aa6 is described below

commit d6842c9aa6fd15d5a9a64286dceed303e9829e1c
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]>
---
 .../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;
     }
 
 }

Reply via email to