/* * 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.axis2.jaxws.client.dispatch; import junit.framework.TestCase; import org.apache.axis2.AxisFault; import org.apache.axis2.description.Parameter; import org.apache.axis2.engine.AxisConfiguration; import org.apache.axis2.jaxws.Constants; import org.apache.axis2.jaxws.description.DescriptionTestUtils2; import org.apache.axis2.jaxws.description.EndpointDescription; import org.apache.axis2.jaxws.description.ServiceDescription; import org.apache.axis2.jaxws.description.builder.MDQConstants; import org.apache.axis2.jaxws.description.impl.ServiceDescriptionImpl; import org.apache.axis2.jaxws.spi.ClientMetadataTest; import org.apache.axis2.jaxws.spi.ServiceDelegate; import javax.xml.namespace.QName; import javax.xml.ws.Service; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; /** * Tests the caching and isolation of dynamic ports,i.e. those created with * Service.addPort(...). Dynamic ports should * 1) Only be visible to the service instances on which an addPort was done * 2) Share instances of the description objects (e.g. AxisService) for ports * added to the same instance of a service * 3) Different service instances of the same-named service should not share the * the list of added dynamic ports. Even if the same named port is added to each * service, they should not share metadata objects (e.g. EndpointDescription, AxisService) * * Also validate the property that enables the previous behavior that allowed * sharing of dyamic ports across services on the same AxisConfiguration. With * that property enabled, Dynamic ports should * 1) Be shared across all services on the AxisConfiguration based on the key * (PortQName, BindingId, EndpointAddress). */ public class DynamicPortCachingTests extends TestCase { static final String namespaceURI = "http://dispatch.client.jaxws.axis2.apache.org"; static final String svcLocalPart = "svcLocalPart"; static final String dynamicPort1 = "dynamicPort1"; static final String bindingID1 = null; static final String epr1 = null; /** * Validate setting the property enables the old behavior, which is that dynamic ports are * shared across all services on an AxisConfiguration based on the key * (PortQName, BindingId, EndpointAddress). This test validates that two ports that share the * same Service QName will be share the same dynamic port objects. * * NOTE!!! This test exists for validating backwards compatability. This behavior was NOT * intended in the runtime, but since it existed that way, customers could be depending on it. */ public void testSamePortsSameServiceName_AxisConfig_PropertyTrue() { try { ClientMetadataTest.installCachingFactory(); QName svcQN = new QName(namespaceURI, svcLocalPart); Service svc1 = Service.create(svcQN); assertNotNull(svc1); ServiceDelegate svcDlg1 = DescriptionTestUtils2.getServiceDelegate(svc1); assertNotNull(svcDlg1); ServiceDescription svcDesc1 = svcDlg1.getServiceDescription(); assertNotNull(svcDesc1); // Set the property to revert the behavior. Note that although we are passing ni // a particular service, the property is set on the AxisConfig shared by all // services. setAxisConfigParameter(svc1, MDQConstants.SHARE_DYNAMIC_PORTS_ACROSS_SERVICES, "true"); Service svc2 = Service.create(svcQN); assertNotNull(svc2); ServiceDelegate svcDlg2 = DescriptionTestUtils2.getServiceDelegate(svc2); assertNotNull(svcDlg2); ServiceDescription svcDesc2 = svcDlg2.getServiceDescription(); assertNotNull(svcDesc2); assertNotSame("Service instances should not be the same", svc1, svc2); assertNotSame("Service delegates should not be the same", svcDlg1, svcDlg2); assertSame("Instance of ServiceDescription should be the same", svcDesc1, svcDesc2); // Add a port to 1st service, should not be visible under the 2nd service svc1.addPort(new QName(namespaceURI, dynamicPort1), bindingID1, epr1); assertEquals(1, getList(svc1.getPorts()).size()); assertEquals(0, getList(svc2.getPorts()).size()); // Add the same port to 2nd service, should now have same ports and description // objects svc2.addPort(new QName(namespaceURI, dynamicPort1), bindingID1, epr1); assertEquals(1, getList(svc1.getPorts()).size()); assertEquals(1, getList(svc2.getPorts()).size()); // Make sure the EndpointDescription objects are shared. Collection<?> epDesc1Collection = ((ServiceDescriptionImpl) svcDesc1).getDynamicEndpointDescriptions_AsCollection(svcDlg1); Collection<?> epDesc2Collection = ((ServiceDescriptionImpl) svcDesc2).getDynamicEndpointDescriptions_AsCollection(svcDlg2); assertEquals("Wrong number of dynamic endpoints", 1, epDesc1Collection.size()); assertEquals("Wrong number of dynamic endpoints", 1, epDesc2Collection.size()); EndpointDescription epDesc1 = (EndpointDescription) epDesc1Collection.toArray()[0]; EndpointDescription epDesc2 = (EndpointDescription) epDesc2Collection.toArray()[0]; assertSame("EndpointDescriptions not shared", epDesc1, epDesc2); } finally { ClientMetadataTest.restoreOriginalFactory(); } } /** * Validate setting the property enables the old behavior, which is that dynamic ports are * shared across all services on an AxisConfiguration based on the key * (PortQName, BindingId, EndpointAddress). This test validates that two ports that have * different Service QNames will still share the same dynamic port objects. * * NOTE!!! This test exists for validating backwards compatability. This behavior was NOT * intended in the runtime, but since it existed that way, customers could be depending on it. */ public void testSamePortsDifferentServiceName_AxisConfig_PropertyTrue() { try { ClientMetadataTest.installCachingFactory(); QName svcQN = new QName(namespaceURI, svcLocalPart); Service svc1 = Service.create(svcQN); assertNotNull(svc1); ServiceDelegate svcDlg1 = DescriptionTestUtils2.getServiceDelegate(svc1); assertNotNull(svcDlg1); ServiceDescription svcDesc1 = svcDlg1.getServiceDescription(); assertNotNull(svcDesc1); // Set the property to revert the behavior. Note that although we are passing ni // a particular service, the property is set on the AxisConfig shared by all // services. setAxisConfigParameter(svc1, MDQConstants.SHARE_DYNAMIC_PORTS_ACROSS_SERVICES, "true"); QName svcQN2 = new QName(namespaceURI, svcLocalPart + "2"); Service svc2 = Service.create(svcQN2); assertNotNull(svc2); ServiceDelegate svcDlg2 = DescriptionTestUtils2.getServiceDelegate(svc2); assertNotNull(svcDlg2); ServiceDescription svcDesc2 = svcDlg2.getServiceDescription(); assertNotNull(svcDesc2); assertNotSame("Service instances should not be the same", svc1, svc2); assertNotSame("Service delegates should not be the same", svcDlg1, svcDlg2); assertNotSame("Instance of ServiceDescription should be the same", svcDesc1, svcDesc2); // Add a port to 1st service, should not be visible under the 2nd service svc1.addPort(new QName(namespaceURI, dynamicPort1), bindingID1, epr1); assertEquals(1, getList(svc1.getPorts()).size()); assertEquals(0, getList(svc2.getPorts()).size()); // Add the same port to 2nd service, should now have same ports and description // objects svc2.addPort(new QName(namespaceURI, dynamicPort1), bindingID1, epr1); assertEquals(1, getList(svc1.getPorts()).size()); assertEquals(1, getList(svc2.getPorts()).size()); // Make sure the EndpointDescription objects are shared. Collection<?> epDesc1Collection = ((ServiceDescriptionImpl) svcDesc1).getDynamicEndpointDescriptions_AsCollection(svcDlg1); Collection<?> epDesc2Collection = ((ServiceDescriptionImpl) svcDesc2).getDynamicEndpointDescriptions_AsCollection(svcDlg2); assertEquals("Wrong number of dynamic endpoints", 1, epDesc1Collection.size()); assertEquals("Wrong number of dynamic endpoints", 1, epDesc2Collection.size()); EndpointDescription epDesc1 = (EndpointDescription) epDesc1Collection.toArray()[0]; EndpointDescription epDesc2 = (EndpointDescription) epDesc2Collection.toArray()[0]; assertSame("EndpointDescriptions not shared", epDesc1, epDesc2); } finally { ClientMetadataTest.restoreOriginalFactory(); } } /** * Validate that without the property set to revert the behavior, the default is that the ports are * NOT shared across different instances of services with the same name */ public void testSamePortsSameServiceNameDifferentInstances() { try { ClientMetadataTest.installCachingFactory(); QName svcQN = new QName(namespaceURI, svcLocalPart); Service svc1 = Service.create(svcQN); assertNotNull(svc1); ServiceDelegate svcDlg1 = DescriptionTestUtils2.getServiceDelegate(svc1); assertNotNull(svcDlg1); ServiceDescription svcDesc1 = svcDlg1.getServiceDescription(); assertNotNull(svcDesc1); Service svc2 = Service.create(svcQN); assertNotNull(svc2); ServiceDelegate svcDlg2 = DescriptionTestUtils2.getServiceDelegate(svc2); assertNotNull(svcDlg2); ServiceDescription svcDesc2 = svcDlg2.getServiceDescription(); assertNotNull(svcDesc2); assertNotSame("Service instances should not be the same", svc1, svc2); assertNotSame("Service delegates should not be the same", svcDlg1, svcDlg2); assertSame("Instance of ServiceDescription should be the same", svcDesc1, svcDesc2); // Add a port to 1st service, should not be visible under the 2nd service svc1.addPort(new QName(namespaceURI, dynamicPort1), bindingID1, epr1); assertEquals(1, getList(svc1.getPorts()).size()); assertEquals(0, getList(svc2.getPorts()).size()); // Add the same port to 2nd service, should now have same ports and description // objects svc2.addPort(new QName(namespaceURI, dynamicPort1), bindingID1, epr1); assertEquals(1, getList(svc1.getPorts()).size()); assertEquals(1, getList(svc2.getPorts()).size()); // Make sure the EndpointDescription objects are not shared. Collection<?> epDesc1Collection = ((ServiceDescriptionImpl) svcDesc1).getDynamicEndpointDescriptions_AsCollection(svcDlg1); Collection<?> epDesc2Collection = ((ServiceDescriptionImpl) svcDesc2).getDynamicEndpointDescriptions_AsCollection(svcDlg2); assertEquals("Wrong number of dynamic endpoints", 1, epDesc1Collection.size()); assertEquals("Wrong number of dynamic endpoints", 1, epDesc2Collection.size()); EndpointDescription epDesc1 = (EndpointDescription) epDesc1Collection.toArray()[0]; EndpointDescription epDesc2 = (EndpointDescription) epDesc2Collection.toArray()[0]; assertNotSame("EndpointDescriptions not shared", epDesc1, epDesc2); } finally { ClientMetadataTest.restoreOriginalFactory(); } } /** * Validate that adding the same dynamic port to the same service instance re-uses the same * description objects (e.g. EndpointDescription) */ public void testSamePortsSameServiceInstance() { try { ClientMetadataTest.installCachingFactory(); QName svcQN = new QName(namespaceURI, svcLocalPart); Service svc1 = Service.create(svcQN); assertNotNull(svc1); ServiceDelegate svcDlg1 = DescriptionTestUtils2.getServiceDelegate(svc1); assertNotNull(svcDlg1); ServiceDescription svcDesc1 = svcDlg1.getServiceDescription(); assertNotNull(svcDesc1); // Add a port to service, save off the metadata to validate later svc1.addPort(new QName(namespaceURI, dynamicPort1), bindingID1, epr1); assertEquals(1, getList(svc1.getPorts()).size()); Collection<?> epDesc1Collection = ((ServiceDescriptionImpl) svcDesc1).getDynamicEndpointDescriptions_AsCollection(svcDlg1); assertEquals("Wrong number of dynamic endpoints", 1, epDesc1Collection.size()); EndpointDescription epDescFirstAddPort = (EndpointDescription) epDesc1Collection.toArray()[0]; // Add the same port to the same service instance, should use the same description objects svc1.addPort(new QName(namespaceURI, dynamicPort1), bindingID1, epr1); assertEquals(1, getList(svc1.getPorts()).size()); // Make sure the EndpointDescription object is reused for second port. Collection<?> epDesc2Collection = ((ServiceDescriptionImpl) svcDesc1).getDynamicEndpointDescriptions_AsCollection(svcDlg1); assertEquals("Wrong number of dynamic endpoints", 1, epDesc2Collection.size()); EndpointDescription epDescSecondAddPort = (EndpointDescription) epDesc1Collection.toArray()[0]; assertSame("EndpointDescriptions not reused", epDescFirstAddPort, epDescSecondAddPort); } finally { ClientMetadataTest.restoreOriginalFactory(); } } /** * Validate that ports added to services with different service names (and thus different service instances) * are not shared. */ public void testSamePortsDifferentServiceNames() { try { ClientMetadataTest.installCachingFactory(); QName svcQN = new QName(namespaceURI, svcLocalPart); Service svc1 = Service.create(svcQN); assertNotNull(svc1); ServiceDelegate svcDlg1 = DescriptionTestUtils2.getServiceDelegate(svc1); assertNotNull(svcDlg1); ServiceDescription svcDesc1 = svcDlg1.getServiceDescription(); assertNotNull(svcDesc1); QName svcQN2 = new QName(namespaceURI, svcLocalPart + "2"); Service svc2 = Service.create(svcQN2); assertNotNull(svc2); ServiceDelegate svcDlg2 = DescriptionTestUtils2.getServiceDelegate(svc2); assertNotNull(svcDlg2); ServiceDescription svcDesc2 = svcDlg2.getServiceDescription(); assertNotNull(svcDesc2); assertNotSame("Service instances should not be the same", svc1, svc2); assertNotSame("Service delegates should not be the same", svcDlg1, svcDlg2); assertNotSame("Instance of ServiceDescription should not be the same", svcDesc1, svcDesc2); // Add a port to 1st service, should not be visible under the 2nd service svc1.addPort(new QName(namespaceURI, dynamicPort1), bindingID1, epr1); assertEquals(1, getList(svc1.getPorts()).size()); assertEquals(0, getList(svc2.getPorts()).size()); // Add the same port to 2nd service, should now have same ports and description // objects svc2.addPort(new QName(namespaceURI, dynamicPort1), bindingID1, epr1); assertEquals(1, getList(svc1.getPorts()).size()); assertEquals(1, getList(svc2.getPorts()).size()); // Make sure the EndpointDescription objects are NOT shared. Collection<?> epDesc1Collection = ((ServiceDescriptionImpl) svcDesc1).getDynamicEndpointDescriptions_AsCollection(svcDlg1); Collection<?> epDesc2Collection = ((ServiceDescriptionImpl) svcDesc2).getDynamicEndpointDescriptions_AsCollection(svcDlg2); assertEquals("Wrong number of dynamic endpoints", 1, epDesc1Collection.size()); assertEquals("Wrong number of dynamic endpoints", 1, epDesc2Collection.size()); EndpointDescription epDesc1 = (EndpointDescription) epDesc1Collection.toArray().clone()[0]; EndpointDescription epDesc2 = (EndpointDescription) epDesc2Collection.toArray().clone()[0]; assertNotSame("EndpointDescriptions should not be shared across different services", epDesc1, epDesc2); } finally { ClientMetadataTest.restoreOriginalFactory(); } } public void testAddPortOOM() { QName svcQN = new QName(namespaceURI, svcLocalPart); try { ClientMetadataTest.installCachingFactory(); for (int i = 0; i < 5000 ; i++) { Service svc1 = Service.create(svcQN); svc1.addPort(new QName(namespaceURI, dynamicPort1 + "_" /*+ i*/), bindingID1, epr1); } } catch (Throwable t) { fail("Caught throwable " + t); } finally { ClientMetadataTest.restoreOriginalFactory(); } } private List getList(Iterator it) { List returnList = new ArrayList(); while (it != null && it.hasNext()) { returnList.add(it.next()); } return returnList; } private void setAxisConfigParameter(Service service, String key, String value) { ServiceDelegate delegate = DescriptionTestUtils2.getServiceDelegate(service); ServiceDescription svcDesc = delegate.getServiceDescription(); AxisConfiguration axisConfig = svcDesc.getAxisConfigContext().getAxisConfiguration(); Parameter parameter = new Parameter(key, value); try { axisConfig.addParameter(parameter); } catch (AxisFault e) { fail("Unable to set Parameter on AxisConfig due to exception " + e); } } }