Author: ay
Date: Tue Aug 20 13:36:39 2013
New Revision: 1515822
URL: http://svn.apache.org/r1515822
Log:
[CXF-5218] WS-RM destination's fault handling to distinguish protocol related
faults from other faults
Added:
cxf/trunk/systests/ws-rm/src/test/java/org/apache/cxf/systest/ws/rm/RobustServiceWithFaultTest.java
Modified:
cxf/trunk/rt/ws/rm/src/main/java/org/apache/cxf/ws/rm/RMInInterceptor.java
cxf/trunk/rt/ws/rm/src/test/java/org/apache/cxf/ws/rm/RMInInterceptorTest.java
Modified:
cxf/trunk/rt/ws/rm/src/main/java/org/apache/cxf/ws/rm/RMInInterceptor.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/ws/rm/src/main/java/org/apache/cxf/ws/rm/RMInInterceptor.java?rev=1515822&r1=1515821&r2=1515822&view=diff
==============================================================================
--- cxf/trunk/rt/ws/rm/src/main/java/org/apache/cxf/ws/rm/RMInInterceptor.java
(original)
+++ cxf/trunk/rt/ws/rm/src/main/java/org/apache/cxf/ws/rm/RMInInterceptor.java
Tue Aug 20 13:36:39 2013
@@ -59,9 +59,11 @@ public class RMInInterceptor extends Abs
} catch (RMException e) {
LOG.log(Level.WARNING, "Failed to revert the delivering
status");
}
- }
- if (!ContextUtils.isRequestor(message)) {
- // force the fault to be returned.
+ }
+ // make sure the fault is returned for an ws-rm related fault or an
invalid ws-rm message
+ // note that OneWayProcessingInterceptor handles the robust case,
hence not handled here.
+ if (isProtocolFault(message)
+ &&
!MessageUtils.isTrue(message.get(RMMessageConstants.DELIVERING_ROBUST_ONEWAY)))
{
Exchange exchange = message.getExchange();
exchange.setOneWay(false);
@@ -73,6 +75,12 @@ public class RMInInterceptor extends Abs
}
}
+ private boolean isProtocolFault(Message message) {
+ return !ContextUtils.isRequestor(message)
+ && (RMContextUtils.getProtocolVariation(message) == null
+ || message.getContent(Exception.class) instanceof
SequenceFault);
+ }
+
protected void handle(Message message) throws SequenceFault, RMException {
LOG.entering(getClass().getName(), "handleMessage");
Modified:
cxf/trunk/rt/ws/rm/src/test/java/org/apache/cxf/ws/rm/RMInInterceptorTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/ws/rm/src/test/java/org/apache/cxf/ws/rm/RMInInterceptorTest.java?rev=1515822&r1=1515821&r2=1515822&view=diff
==============================================================================
---
cxf/trunk/rt/ws/rm/src/test/java/org/apache/cxf/ws/rm/RMInInterceptorTest.java
(original)
+++
cxf/trunk/rt/ws/rm/src/test/java/org/apache/cxf/ws/rm/RMInInterceptorTest.java
Tue Aug 20 13:36:39 2013
@@ -379,10 +379,12 @@ public class RMInInterceptorTest extends
interceptor.setManager(manager);
+ // test 1. a normal sequence fault case without non-anonymous faultTo
EasyMock.expect(message.get(JAXWSAConstants.SERVER_ADDRESSING_PROPERTIES_INBOUND)).andReturn(maps);
EasyMock.expect(message.getExchange()).andReturn(exchange).anyTimes();
EasyMock.expect(message.get(RMMessageConstants.RM_PROTOCOL_VARIATION))
.andReturn(ProtocolVariation.RM10WSA200408).anyTimes();
+ EasyMock.expect(message.getContent(Exception.class)).andReturn(new
SequenceFault("test")).anyTimes();
exchange.setOneWay(false);
EasyMock.expectLastCall();
control.replay();
@@ -395,6 +397,7 @@ public class RMInInterceptorTest extends
control.verify();
+ // 2. a sequence fault case with non anonymous faultTo
control.reset();
Destination d = control.createMock(Destination.class);
Endpoint ep = control.createMock(Endpoint.class);
@@ -407,6 +410,7 @@ public class RMInInterceptorTest extends
EasyMock.expect(message.getExchange()).andReturn(exchange).anyTimes();
EasyMock.expect(message.get(RMMessageConstants.RM_PROTOCOL_VARIATION))
.andReturn(ProtocolVariation.RM10WSA200408).anyTimes();
+ EasyMock.expect(message.getContent(Exception.class)).andReturn(new
SequenceFault("test")).anyTimes();
exchange.setOneWay(false);
EasyMock.expectLastCall();
exchange.setDestination(EasyMock.anyObject(org.apache.cxf.transport.Destination.class));
@@ -420,17 +424,16 @@ public class RMInInterceptorTest extends
}
control.verify();
+ // 3. a robust oneway case
control.reset();
EasyMock.expect(maps.getFaultTo())
.andReturn(RMUtils.createAnonymousReference()).anyTimes();
-
EasyMock.expect(message.get(JAXWSAConstants.SERVER_ADDRESSING_PROPERTIES_INBOUND)).andReturn(maps);
+
EasyMock.expect(message.get(JAXWSAConstants.SERVER_ADDRESSING_PROPERTIES_INBOUND)).andReturn(maps).anyTimes();
EasyMock.expect(manager.getDestination(message)).andReturn(d);
EasyMock.expect(message.getExchange()).andReturn(exchange).anyTimes();
EasyMock.expect(message.get(RMMessageConstants.DELIVERING_ROBUST_ONEWAY)).andReturn(true).anyTimes();
EasyMock.expect(message.get(RMMessageConstants.RM_PROTOCOL_VARIATION))
.andReturn(ProtocolVariation.RM10WSA200408).anyTimes();
- exchange.setOneWay(false);
- EasyMock.expectLastCall();
control.replay();
try {
@@ -438,7 +441,24 @@ public class RMInInterceptorTest extends
} catch (Exception e) {
fail("unexpected exception thrown from handleFault: " + e);
}
- // verified in tearDown
+
+ // 4. a runtime exception case
+ control.reset();
+ EasyMock.expect(maps.getFaultTo())
+ .andReturn(RMUtils.createAnonymousReference()).anyTimes();
+
EasyMock.expect(message.get(JAXWSAConstants.SERVER_ADDRESSING_PROPERTIES_INBOUND)).andReturn(maps).anyTimes();
+ EasyMock.expect(message.getExchange()).andReturn(exchange).anyTimes();
+ EasyMock.expect(message.get(RMMessageConstants.RM_PROTOCOL_VARIATION))
+ .andReturn(ProtocolVariation.RM10WSA200408).anyTimes();
+ EasyMock.expect(message.getContent(Exception.class)).andReturn(new
RuntimeException("test")).anyTimes();
+ control.replay();
+
+ try {
+ interceptor.handleFault(message);
+ } catch (Exception e) {
+ fail("unexpected exception thrown from handleFault: " + e);
+ }
+// verified in tearDown
}
private Message setupInboundMessage(String action, boolean serverSide)
throws RMException {
Added:
cxf/trunk/systests/ws-rm/src/test/java/org/apache/cxf/systest/ws/rm/RobustServiceWithFaultTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/ws-rm/src/test/java/org/apache/cxf/systest/ws/rm/RobustServiceWithFaultTest.java?rev=1515822&view=auto
==============================================================================
---
cxf/trunk/systests/ws-rm/src/test/java/org/apache/cxf/systest/ws/rm/RobustServiceWithFaultTest.java
(added)
+++
cxf/trunk/systests/ws-rm/src/test/java/org/apache/cxf/systest/ws/rm/RobustServiceWithFaultTest.java
Tue Aug 20 13:36:39 2013
@@ -0,0 +1,182 @@
+/**
+ * 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.systest.ws.rm;
+
+import java.util.logging.Logger;
+
+import javax.xml.ws.Endpoint;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.bus.spring.SpringBusFactory;
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.greeter_control.Greeter;
+import org.apache.cxf.greeter_control.GreeterService;
+import org.apache.cxf.interceptor.Fault;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.AbstractPhaseInterceptor;
+import org.apache.cxf.phase.Phase;
+import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
+import org.apache.cxf.testutil.common.AbstractBusTestServerBase;
+import org.apache.cxf.ws.rm.RMManager;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Tests the addition of WS-RM properties to application messages and the
+ * exchange of WS-RM protocol messages.
+ */
+public class RobustServiceWithFaultTest extends
AbstractBusClientServerTestBase {
+ public static final String PORT = allocatePort(Server.class);
+ public static final String GREETMEONEWAY_ACTION
+ = "http://cxf.apache.org/greeter_control/Greeter/greetMeOneWayRequest";
+ private static final Logger LOG =
LogUtils.getLogger(RobustServiceWithFaultTest.class);
+
+ private static RobustOneWayPropertySetter robustSetter;
+ private static GreeterCounterImpl serverGreeter;
+ private Greeter greeter;
+
+
+ public static class Server extends AbstractBusTestServerBase {
+ Endpoint ep;
+ protected void run() {
+ SpringBusFactory bf = new SpringBusFactory();
+ // use a at-most-once server with sync ack processing
+ Bus bus =
bf.createBus("/org/apache/cxf/systest/ws/rm/atmostonce.xml");
+ BusFactory.setDefaultBus(bus);
+ setBus(bus);
+
bus.getExtension(RMManager.class).getConfiguration().setAcknowledgementInterval(new
Long(0));
+
+ serverGreeter = new GreeterCounterImpl();
+ String address = "http://localhost:" + PORT +
"/SoapContext/GreeterPort";
+
+ robustSetter = new RobustOneWayPropertySetter();
+ bus.getInInterceptors().add(robustSetter);
+
+ // publish this robust oneway endpoint
+ ep = Endpoint.create(serverGreeter);
+ // leave the robust prop untouched, as it will be set per call
later
+
+ ep.publish(address);
+ LOG.info("Published greeter endpoint.");
+ }
+ public void tearDown() {
+ ep.stop();
+ ep = null;
+ }
+
+ }
+
+ @BeforeClass
+ public static void startServers() throws Exception {
+ assertTrue("server did not launch correctly",
launchServer(Server.class, true));
+ }
+
+ @Test
+ public void testRobustWithSomeFaults() throws Exception {
+ LOG.fine("Creating greeter client");
+ SpringBusFactory bf = new SpringBusFactory();
+ bus = bf.createBus("/org/apache/cxf/systest/ws/rm/seqlength1.xml");
+ // set the client retry interval much shorter than the slow processing
delay
+ RMManager manager = bus.getExtension(RMManager.class);
+ manager.getConfiguration().setBaseRetransmissionInterval(new
Long(5000));
+
+ BusFactory.setDefaultBus(bus);
+ GreeterService gs = new GreeterService();
+ greeter = gs.getGreeterPort();
+ updateAddressPort(greeter, PORT);
+
+ LOG.fine("Invoking greeter");
+ greeter.greetMeOneWay("one");
+ Thread.sleep(3000);
+
+ // invoked once
+ assertEquals("not invoked once", 1, serverGreeter.getCount());
+ assertTrue("still in retransmission",
manager.getRetransmissionQueue().isEmpty());
+
+ LOG.fine("Invoking greeter and raising a fault");
+ serverGreeter.setThrowAlways(true);
+
+ greeter.greetMeOneWay("two");
+ Thread.sleep(3000);
+
+ // still invoked once
+ assertEquals("not invoked once", 1, serverGreeter.getCount());
+ assertTrue("still in retransmission",
manager.getRetransmissionQueue().isEmpty());
+
+ LOG.fine("Invoking robust greeter and raising a fault");
+ robustSetter.setRobust(true);
+ greeter.greetMeOneWay("three");
+ Thread.sleep(3000);
+
+ // still invoked once
+ assertEquals("not invoked once", 1, serverGreeter.getCount());
+ assertFalse("no message in retransmission",
manager.getRetransmissionQueue().isEmpty());
+
+ LOG.fine("Stop raising a fault and let the retransmission succeeds");
+ serverGreeter.setThrowAlways(false);
+ Thread.sleep(8000);
+
+ // invoked twice
+ assertEquals("not invoked twice", 2, serverGreeter.getCount());
+ assertTrue("still in retransmission",
manager.getRetransmissionQueue().isEmpty());
+ }
+
+ private static class GreeterCounterImpl extends GreeterImpl {
+ private int count;
+ private boolean throwAlways;
+
+ public void greetMeOneWay(String arg0) {
+ if (throwAlways) {
+ throw new RuntimeException("invocation exception");
+ }
+ super.greetMeOneWay(arg0);
+ count++;
+ }
+
+ public int getCount() {
+ return count;
+ }
+
+ @Override
+ public void setThrowAlways(boolean t) {
+ throwAlways = t;
+ super.setThrowAlways(t);
+ }
+ }
+
+ static class RobustOneWayPropertySetter extends
AbstractPhaseInterceptor<Message> {
+ private boolean robust;
+
+ public RobustOneWayPropertySetter() {
+ super(Phase.RECEIVE);
+ }
+
+ public void setRobust(boolean robust) {
+ this.robust = robust;
+ }
+
+ @Override
+ public void handleMessage(Message message) throws Fault {
+ message.setContextualProperty(Message.ROBUST_ONEWAY, robust);
+ }
+ }
+}