/** * 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.clustering; import java.net.ConnectException; import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; import org.apache.cxf.Bus; import org.apache.cxf.BusFactory; import org.apache.cxf.bus.spring.SpringBusFactory; import org.apache.cxf.clustering.AbstractStaticFailoverStrategy; import org.apache.cxf.clustering.FailoverTargetSelector; import org.apache.cxf.clustering.RandomStrategy; import org.apache.cxf.clustering.SequentialStrategy; import org.apache.cxf.common.logging.LogUtils; import org.apache.cxf.endpoint.ConduitSelector; import org.apache.cxf.endpoint.Endpoint; import org.apache.cxf.frontend.ClientProxy; import org.apache.cxf.greeter_control.ClusteredGreeterService; import org.apache.cxf.greeter_control.Control; import org.apache.cxf.greeter_control.ControlService; import org.apache.cxf.greeter_control.Greeter; import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase; import org.apache.cxf.ws.addressing.MAPAggregator; import org.apache.cxf.ws.addressing.soap.MAPCodec; import org.junit.After; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; /** * Tests failover within a static cluster. */ public class FailoverAddressOverrideTest extends AbstractBusClientServerTestBase { public static final String PORT_0 = allocatePort(Server.class, 0); public static final String PORT_A = allocatePort(Server.class, 1); public static final String PORT_B = allocatePort(Server.class, 2); public static final String PORT_C = allocatePort(Server.class, 3); public static final String PORT_D = allocatePort(Server.class, 4); public static final String PORT_EXTRA = allocatePort(Server.class, 99); protected static final String REPLICA_A = "http://localhost:" + PORT_A + "/SoapContext/ReplicatedPortA"; protected static final String REPLICA_B = "http://localhost:" + PORT_B + "/SoapContext/ReplicatedPortB"; protected static final String REPLICA_C = "http://localhost:" + PORT_C + "/SoapContext/ReplicatedPortC"; protected static final String REPLICA_D = "http://localhost:" + PORT_D + "/SoapContext/ReplicatedPortD"; private static final Logger LOG = LogUtils.getLogger(FailoverAddressOverrideTest.class); private static final String FAILOVER_CONFIG = "org/apache/cxf/systest/clustering/failover_address_override.xml"; protected Bus bus; protected Greeter greeter; protected List<String> targets; private Control control; private MAPAggregator mapAggregator; private MAPCodec mapCodec; @BeforeClass public static void startServers() throws Exception { assertTrue("server did not launch correctly", launchServer(Server.class)); } protected String getConfig() { return FAILOVER_CONFIG; } @Before public void setUp() { SpringBusFactory bf = new SpringBusFactory(); bus = bf.createBus(getConfig()); BusFactory.setDefaultBus(bus); targets = new ArrayList<>(); } @After public void tearDown() { if (null != control) { for (String address : targets) { assertTrue("Failed to stop greeter", control.stopGreeter(address)); } } targets = null; if (bus != null) { bus.shutdown(true); bus = null; } } @Test public void testOverriddenSequentialStrategy() throws Exception { startTarget(REPLICA_C); setupGreeterA(); verifyStrategy(greeter, SequentialStrategy.class, 3); String response = greeter.greetMe("fred"); assertNotNull("expected non-null response", response); assertTrue("response from unexpected target: " + response, response.endsWith(REPLICA_C)); verifyCurrentEndpoint(REPLICA_C); stopTarget(REPLICA_C); } @Test public void testOverriddenRandomStrategy() throws Exception { startTarget(REPLICA_B); setupGreeterC(); verifyStrategy(greeter, RandomStrategy.class, 3); String response = greeter.greetMe("fred"); assertNotNull("expected non-null response", response); assertTrue("response from unexpected target: " + response, response.endsWith(REPLICA_B)); verifyCurrentEndpoint(REPLICA_B); stopTarget(REPLICA_B); } @Test public void testUnreachableAddresses() throws Exception { startTarget(REPLICA_A); setupGreeterB(); verifyStrategy(greeter, SequentialStrategy.class, 2); try { greeter.greetMe("fred"); fail("expected exception"); } catch (Exception e) { Throwable cause = e; while (cause.getCause() != null) { cause = cause.getCause(); } if (!(cause instanceof ConnectException)) { if (cause.getMessage() != null && cause.getMessage().contains("404")) { return; } throw e; } } stopTarget(REPLICA_A); } protected void startTarget(String address) throws Exception { ControlService cs = new ControlService(); control = cs.getControlPort(); updateAddressPort(control, PORT_0); LOG.info("starting replicated target: " + address); assertTrue("Failed to start greeter", control.startGreeter(address)); targets.add(address); } protected void stopTarget(String address) { if (control != null && targets.contains(address)) { LOG.info("starting replicated target: " + address); assertTrue("Failed to start greeter", control.stopGreeter(address)); targets.remove(address); } } protected void verifyCurrentEndpoint(String replica) { assertEquals("unexpected current endpoint", replica, getCurrentEndpoint(greeter)); } protected String getCurrentEndpoint(Object proxy) { return ClientProxy.getClient(proxy).getEndpoint().getEndpointInfo().getAddress(); } protected void setupGreeterA() throws Exception { greeter = new ClusteredGreeterService().getReplicatedPortA(); updateAddressPort(greeter, PORT_A); verifyConduitSelector(greeter); } protected void setupGreeterB() throws Exception { greeter = new ClusteredGreeterService().getReplicatedPortB(); updateAddressPort(greeter, PORT_B); verifyConduitSelector(greeter); } protected void setupGreeterC() throws Exception { greeter = new ClusteredGreeterService().getReplicatedPortC(); updateAddressPort(greeter, PORT_C); verifyConduitSelector(greeter); } protected void verifyConduitSelector(Greeter g) { assertTrue("unexpected conduit slector", ClientProxy.getClient(g).getConduitSelector() instanceof FailoverTargetSelector); } protected void verifyStrategy(Object proxy, Class<?> clz, int count) { ConduitSelector conduitSelector = ClientProxy.getClient(proxy).getConduitSelector(); if (conduitSelector instanceof FailoverTargetSelector) { AbstractStaticFailoverStrategy strategy = (AbstractStaticFailoverStrategy) ((FailoverTargetSelector)conduitSelector).getStrategy(); assertTrue("unexpected strategy", clz.isInstance(strategy)); List<String> alternates = strategy.getAlternateAddresses(null); assertNotNull("expected alternate addresses", alternates); assertEquals("unexpected alternate addresses", count, alternates.size()); } else { fail("unexpected conduit selector: " + conduitSelector); } } protected void enableWSAForCurrentEndpoint() { Endpoint provider = ClientProxy.getClient(greeter).getEndpoint(); mapAggregator = new MAPAggregator(); mapCodec = new MAPCodec(); provider.getInInterceptors().add(mapAggregator); provider.getInInterceptors().add(mapCodec); provider.getOutInterceptors().add(mapAggregator); provider.getOutInterceptors().add(mapCodec); provider.getInFaultInterceptors().add(mapAggregator); provider.getInFaultInterceptors().add(mapCodec); provider.getOutFaultInterceptors().add(mapAggregator); provider.getOutFaultInterceptors().add(mapCodec); } protected boolean isWSAEnabledForCurrentEndpoint() { Endpoint provider = ClientProxy.getClient(greeter).getEndpoint(); boolean enabledIn = provider.getInInterceptors().contains(mapAggregator) && provider.getInInterceptors().contains(mapCodec) && provider.getInFaultInterceptors().contains(mapAggregator) && provider.getInFaultInterceptors().contains(mapCodec); boolean enabledOut = provider.getOutInterceptors().contains(mapAggregator) && provider.getOutInterceptors().contains(mapCodec) && provider.getOutFaultInterceptors().contains(mapAggregator) && provider.getOutFaultInterceptors().contains(mapCodec); return enabledIn && enabledOut; } }