This is an automated email from the ASF dual-hosted git repository. coheigea pushed a commit to branch coheigea/CXF-7214 in repository https://gitbox.apache.org/repos/asf/cxf.git
commit 59a38299e5355b0dfa6c92556a71ca4f1880e022 Author: Colm O hEigeartaigh <[email protected]> AuthorDate: Wed Oct 14 14:22:50 2026 +0100 CXF-7214: Throw a Fault instead of an NPE when no conduit is available --- .../cxf/interceptor/MessageSenderInterceptor.java | 6 +- .../org/apache/cxf/interceptor/Messages.properties | 1 + .../interceptor/MessageSenderInterceptorTest.java | 100 +++++++++++++++++++++ 3 files changed, 106 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/apache/cxf/interceptor/MessageSenderInterceptor.java b/core/src/main/java/org/apache/cxf/interceptor/MessageSenderInterceptor.java index ad4a09835d9..ef4bc9c69f0 100644 --- a/core/src/main/java/org/apache/cxf/interceptor/MessageSenderInterceptor.java +++ b/core/src/main/java/org/apache/cxf/interceptor/MessageSenderInterceptor.java @@ -44,7 +44,11 @@ public class MessageSenderInterceptor extends AbstractPhaseInterceptor<Message> public void handleMessage(Message message) { try { - getConduit(message).prepare(message); + Conduit conduit = getConduit(message); + if (conduit == null) { + throw new Fault(new org.apache.cxf.common.i18n.Message("NO_CONDUIT", BUNDLE)); + } + conduit.prepare(message); } catch (IOException ex) { throw new Fault(new org.apache.cxf.common.i18n.Message("COULD_NOT_SEND", BUNDLE), ex); } diff --git a/core/src/main/java/org/apache/cxf/interceptor/Messages.properties b/core/src/main/java/org/apache/cxf/interceptor/Messages.properties index 487243982f2..4bd651ec382 100644 --- a/core/src/main/java/org/apache/cxf/interceptor/Messages.properties +++ b/core/src/main/java/org/apache/cxf/interceptor/Messages.properties @@ -30,6 +30,7 @@ NO_DATAWRITER=No DataWriter is available for Service: {0} COULD_NOT_UNRWAP=Could not unwrap message parts. COULD_NOT_SEND=Could not send Message. COULD_NOT_RECEIVE=Could not receive Message. +NO_CONDUIT=Could not send Message: no conduit or back channel is available for the exchange. NO_PART_FOUND=Message part {0} was not recognized. (Does it exist in service WSDL?) ORDERED_PARAM_REQUIRED=Parameter should be ordered in the following sequence: {0} WRITE_ATTACHMENTS=Could not write attachments. diff --git a/core/src/test/java/org/apache/cxf/interceptor/MessageSenderInterceptorTest.java b/core/src/test/java/org/apache/cxf/interceptor/MessageSenderInterceptorTest.java new file mode 100644 index 00000000000..ff55f6e49c0 --- /dev/null +++ b/core/src/test/java/org/apache/cxf/interceptor/MessageSenderInterceptorTest.java @@ -0,0 +1,100 @@ +/** + * 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.interceptor; + +import org.apache.cxf.endpoint.ConduitSelector; +import org.apache.cxf.endpoint.PreexistingConduitSelector; +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.apache.cxf.phase.PhaseInterceptorChain; +import org.apache.cxf.transport.Conduit; +import org.apache.cxf.transport.Destination; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; + +public class MessageSenderInterceptorTest { + + private Exchange exchange; + private Message inMessage; + private Message outMessage; + private PhaseInterceptorChain chain; + + @Before + public void setUp() { + exchange = new ExchangeImpl(); + inMessage = new MessageImpl(); + outMessage = new MessageImpl(); + exchange.setInMessage(inMessage); + exchange.setOutMessage(outMessage); + chain = mock(PhaseInterceptorChain.class); + outMessage.setInterceptorChain(chain); + } + + @Test + public void testConduitIsPrepared() throws Exception { + Conduit conduit = mock(Conduit.class); + exchange.put(ConduitSelector.class, new PreexistingConduitSelector(conduit)); + + new MessageSenderInterceptor().handleMessage(outMessage); + + verify(conduit).prepare(outMessage); + verify(chain).add(any( + MessageSenderInterceptor.MessageSenderEndingInterceptor.class)); + } + + @Test + public void testNoConduitOrDestination() { + assertNoConduitFault(); + } + + @Test + public void testNullBackChannel() throws Exception { + Destination destination = mock(Destination.class); + when(destination.getBackChannel(inMessage)).thenReturn(null); + exchange.setDestination(destination); + + assertNoConduitFault(); + verify(destination).getBackChannel(inMessage); + } + + private void assertNoConduitFault() { + try { + new MessageSenderInterceptor().handleMessage(outMessage); + fail("Expected a Fault when no conduit is available"); + } catch (Fault f) { + assertFalse(f.getCause() instanceof NullPointerException); + assertTrue(f.getMessage().contains("no conduit")); + verifyNoInteractions(chain); + } + } +}
