You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by di...@apache.org on 2008/06/08 01:05:15 UTC

svn commit: r664411 - in /webservices/axis2/trunk/java/modules: jaxws/src/org/apache/axis2/jaxws/spi/ jaxws/test/org/apache/axis2/jaxws/client/dispatch/ metadata/src/org/apache/axis2/jaxws/description/ metadata/src/org/apache/axis2/jaxws/description/impl/

Author: dims
Date: Sat Jun  7 16:05:15 2008
New Revision: 664411

URL: http://svn.apache.org/viewvc?rev=664411&view=rev
Log:
Fix for Out-Of-Memory error in a simple client that calls addPort to dynamically add ports. Each addPort causing a new EndpointDescription and AxisService to be created. And, since each call to Service.create() creates a new service delegate, this can cause a problem in a server environment where the client AxisConfiguration is cached.

Added logic to re-use the EndpointDescriptionImpl objects across identical addPorts on the same service. We are caching them in the AxisConfiguration as that is the only common location. Also using WeakReferences to allow the jvm to clean up the instances that are no longer used.


Added:
    webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/client/dispatch/DynamicPortCachingTests.java
Modified:
    webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/spi/ServiceDelegate.java
    webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/DescriptionFactory.java
    webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/impl/DescriptionFactoryImpl.java
    webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/impl/ServiceDescriptionImpl.java

Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/spi/ServiceDelegate.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/spi/ServiceDelegate.java?rev=664411&r1=664410&r2=664411&view=diff
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/spi/ServiceDelegate.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/spi/ServiceDelegate.java Sat Jun  7 16:05:15 2008
@@ -241,7 +241,7 @@
     	}
         EndpointDescription endpointDesc =
                 DescriptionFactory.updateEndpoint(serviceDescription, null, portName,
-                                                  DescriptionFactory.UpdateType.ADD_PORT, this);
+                                                  DescriptionFactory.UpdateType.ADD_PORT, this, bindingId, endpointAddress);
         // TODO: Need to set endpointAddress and set or check bindingId on the EndpointDesc
         endpointDesc.setEndpointAddress(endpointAddress);
         endpointDesc.setClientBindingID(bindingId);

Added: webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/client/dispatch/DynamicPortCachingTests.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/client/dispatch/DynamicPortCachingTests.java?rev=664411&view=auto
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/client/dispatch/DynamicPortCachingTests.java (added)
+++ webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/client/dispatch/DynamicPortCachingTests.java Sat Jun  7 16:05:15 2008
@@ -0,0 +1,219 @@
+/*
+ * 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 org.apache.axis2.context.ConfigurationContext;
+import org.apache.axis2.context.ConfigurationContextFactory;
+import org.apache.axis2.jaxws.ClientConfigurationFactory;
+import org.apache.axis2.jaxws.description.DescriptionTestUtils2;
+import org.apache.axis2.jaxws.description.ServiceDescription;
+import org.apache.axis2.jaxws.spi.ServiceDelegate;
+import org.apache.axis2.metadata.registry.MetadataFactoryRegistry;
+import org.apache.axis2.engine.AxisConfigurator;
+import org.apache.axis2.engine.AxisConfiguration;
+import org.apache.axis2.AxisFault;
+
+import javax.xml.namespace.QName;
+import javax.xml.ws.Service;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests the caching and isolation of dynamic ports,i.e. those created with
+ * Service.addPort(...).  Dynamic ports should
+ * 1) Only be visible to services on which an addPort was done
+ * 2) Share instances of the description objects (e.g. AxisService) for ports
+ * added to different instances of the same service that use the same client
+ * configuration
+ * 3) Identical ports on services using different client configuration should
+ * not be shared 
+ */
+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;
+
+    /**
+     * Two different instances of the same service should share the same
+     * description information (e.g. AxisService) if the same port is added
+     * to both 
+     */
+    public void _testSamePortsSameService() {
+        try {
+            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());
+            
+            
+            
+            
+        } finally {
+            restoreOriginalFactory();
+        }
+        
+    }
+    
+    public void testAddPortOOM() {
+        System.out.println("testAddPortOOM");
+
+        ClientConfigurationFactory oldFactory = setClientConfigurationFactory();
+        QName svcQN = new QName(namespaceURI, svcLocalPart);
+        
+        try {
+            for (int i = 0; i < 5000 ; i++) {
+                Service svc1 = Service.create(svcQN);
+                System.out.println("Port number " + i);
+                svc1.addPort(new QName(namespaceURI, dynamicPort1 + "_" /*+ i*/),
+                             bindingID1,
+                             epr1);
+            }
+        } catch (Throwable t) {
+            fail("Caught throwable " + t);
+        } finally {
+            MetadataFactoryRegistry.setFactory(ClientConfigurationFactory.class, oldFactory);
+        }
+    }
+
+    private ClientConfigurationFactory setClientConfigurationFactory() {
+        ClientConfigurationFactory oldFactory = (ClientConfigurationFactory) MetadataFactoryRegistry.getFactory(ClientConfigurationFactory.class);
+        ClientConfigurationFactory factory = new ClientConfigurationFactory(new AxisConfigurator() {
+            public AxisConfiguration getAxisConfiguration()  {
+                try {
+                    return ConfigurationContextFactory.createDefaultConfigurationContext().getAxisConfiguration();
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+            }
+            public void loadServices() {
+            }
+            public void engageGlobalModules() throws AxisFault {
+            }
+            public void cleanup() {
+            }
+        });
+        MetadataFactoryRegistry.setFactory(ClientConfigurationFactory.class, factory);
+        return oldFactory;
+    }
+
+    private List getList(Iterator it) {
+        List returnList = new ArrayList();
+        while (it != null && it.hasNext()) {
+            returnList.add(it.next());
+        }
+        return returnList;
+    }
+    
+    /**
+     * Methods to install a client configuration factory that will return the same AxisConfiguration
+     * each time.  This is used so that the ServiceDescriptions will be cached in the DescriptionFactory.
+     * 
+     * IMPORTANT!!!
+     * If you install a caching factory, you MUST restore the original factory before your test
+     * exits, otherwise it will remain installed when subsequent tests run and cause REALLY STRANGE
+     * failures.  Use restoreOriginalFactory() INSIDE A finally() block to restore the factory.
+     */
+    static private ClientConfigurationFactory originalFactory = null;
+    static void installCachingFactory() {
+        // install caching factory
+        if (originalFactory != null) {
+            throw new UnsupportedOperationException("Attempt to install the caching factory when the original factory has already been overwritten");
+        }
+        originalFactory = 
+            (ClientConfigurationFactory)MetadataFactoryRegistry.getFactory(ClientConfigurationFactory.class);
+        DynamicPortCachingClientContextFactory newFactory = new DynamicPortCachingClientContextFactory();
+        MetadataFactoryRegistry.setFactory(ClientConfigurationFactory.class, newFactory);
+        resetClientConfigFactory();
+    }
+    static void restoreOriginalFactory() {
+        if (originalFactory == null) {
+            throw new UnsupportedOperationException("Attempt to restore original factory to a null value");
+        }
+        MetadataFactoryRegistry.setFactory(ClientConfigurationFactory.class, originalFactory);
+        resetClientConfigFactory();
+        originalFactory = null;
+    }
+    static void resetClientConfigFactory() {
+//        Field field;
+//        try {
+//            field = DescriptionFactoryImpl.class.getDeclaredField("clientConfigFactory");
+//            field.setAccessible(true);
+//            field.set(null, null);
+//        } catch (Exception e) {
+//            throw new UnsupportedOperationException("Unable to reset client config factory; caught " + e);
+//        }
+    }
+    
+}
+
+class DynamicPortCachingClientContextFactory extends ClientConfigurationFactory {
+    ConfigurationContext context;
+    
+    public ConfigurationContext getClientConfigurationContext() {
+        if (context == null) {
+            context = super.getClientConfigurationContext();
+        }
+        System.out.println("Test version of DynamicPortCachingClientContextFactory: " + context);
+        return context;
+    }
+    
+    public void reset() {
+        context = null;
+    }
+}
+
+

Modified: webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/DescriptionFactory.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/DescriptionFactory.java?rev=664411&r1=664410&r2=664411&view=diff
==============================================================================
--- webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/DescriptionFactory.java (original)
+++ webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/DescriptionFactory.java Sat Jun  7 16:05:15 2008
@@ -123,7 +123,7 @@
                                                      Class sei, QName portQName,
                                                      DescriptionFactory.UpdateType updateType) {
         return DescriptionFactoryImpl
-                   .updateEndpoint(serviceDescription, sei, portQName, updateType);
+                   .updateEndpoint(serviceDescription, sei, portQName, updateType, null, null);
     }    
     
     /**
@@ -151,7 +151,7 @@
                                                      DescriptionFactory.UpdateType updateType,
                                                      Object serviceDelegateKey) {
         return DescriptionFactoryImpl
-                   .updateEndpoint(serviceDescription, sei, portQName, updateType, serviceDelegateKey);
+                   .updateEndpoint(serviceDescription, sei, portQName, updateType, serviceDelegateKey, null, null);
     }    
     
     /**
@@ -175,7 +175,7 @@
             DescriptionBuilderComposite composite,
             Object sparseCompositeKey) {
         return DescriptionFactoryImpl
-                   .updateEndpoint(serviceDescription, sei, portQName, updateType, composite, sparseCompositeKey);
+                   .updateEndpoint(serviceDescription, sei, portQName, updateType, composite, sparseCompositeKey, null, null);
     }
 
     /**
@@ -204,7 +204,7 @@
                                                      String addressingNamespace,
                                                      DescriptionFactory.UpdateType updateType) {
         return DescriptionFactoryImpl
-                .updateEndpoint(serviceDescription, sei, epr, addressingNamespace, updateType);
+                .updateEndpoint(serviceDescription, sei, epr, addressingNamespace, updateType, null, null);
     }
     
     /**
@@ -232,7 +232,7 @@
                                                      DescriptionFactory.UpdateType updateType,
                                                      Object serviceDelegateKey) {
         return DescriptionFactoryImpl
-                   .updateEndpoint(serviceDescription, sei, epr, addressingNamespace, updateType, serviceDelegateKey);
+                   .updateEndpoint(serviceDescription, sei, epr, addressingNamespace, updateType, serviceDelegateKey, null, null);
     }    
 
     /**
@@ -257,7 +257,178 @@
             DescriptionBuilderComposite composite,
             Object sparseCompositeKey) {
         return DescriptionFactoryImpl
-        .updateEndpoint(serviceDescription, sei, epr, addressingNamespace, updateType, composite, sparseCompositeKey);
+        .updateEndpoint(serviceDescription, sei, epr, addressingNamespace, updateType, composite, sparseCompositeKey, null, null);
+    }
+    
+    /**
+     * Retrieve or create the EndpointDescription hierarchy associated with an existing CLIENT side
+     * ServiceDescription for a particular port.  If an EndpointDescritption already exists, it will
+     * be returned; if one does not already exist, it will be created.  Note that if the SEI is null
+     * then the EndpointDescription returned will be for a Dispatch client only and it will not have
+     * an EndpointInterfaceDescription hierarchy associated with it.  If, at a later point, the same
+     * port is requested and an SEI is provided, the existing EndpointDescription will be updated
+     * with a newly-created EndpointInterfaceDescription hierarchy.
+     *
+     * @param serviceDescription An existing client-side ServiceDescription.  This must not be
+     *                           null.
+     * @param sei                The ServiceInterface class.  This can be null for adding a port or
+     *                           creating a Dispatch; it can not be null when getting a port.
+     * @param portQName          The QName of the port.  If this is null, the runtime will attempt
+     *                           to to select an appropriate port to use.
+     * @param updateType         The type of the update: adding a port, creating a dispatch, or
+     *                           getting an SEI-based port.
+     * @return An EndpointDescription corresponding to the port.
+     * @see #createServiceDescription(URL, QName, Class)
+     * @see DescriptionFactory.UpdateType
+     */
+    public static EndpointDescription updateEndpoint(ServiceDescription serviceDescription,
+                                                     Class sei, QName portQName,
+                                                     DescriptionFactory.UpdateType updateType,
+                                                     String bindingId, 
+                                                     String endpointAddress) {
+        return DescriptionFactoryImpl
+                   .updateEndpoint(serviceDescription, sei, portQName, updateType, bindingId, endpointAddress);
+    }    
+    
+    /**
+     * Retrieve or create the EndpointDescription hierarchy associated with an existing CLIENT side
+     * ServiceDescription for a particular port.  This is identical to above, but this method has a 
+     * reference back to the ServiceDelegate (which invoked it) for purposes of properly caching 
+     * ServiceDescriptions that contain dynamic ports
+     *
+     * @param serviceDescription An existing client-side ServiceDescription.  This must not be
+     *                           null.
+     * @param sei                The ServiceInterface class.  This can be null for adding a port or
+     *                           creating a Dispatch; it can not be null when getting a port.
+     * @param portQName          The QName of the port.  If this is null, the runtime will attempt
+     *                           to to select an appropriate port to use.
+     * @param updateType         The type of the update: adding a port, creating a dispatch, or
+     *                           getting an SEI-based port.
+     * @param serviceDelegateKey A reference back to the ServiceDelegate that called it
+     * @return An EndpointDescription corresponding to the port.
+     * @see #createServiceDescription(URL, QName, Class)
+     * @see DescriptionFactory.UpdateType
+     */
+    public static EndpointDescription updateEndpoint(ServiceDescription serviceDescription,
+                                                     Class sei, 
+                                                     QName portQName,
+                                                     DescriptionFactory.UpdateType updateType,
+                                                     Object serviceDelegateKey,
+                                                     String bindingId, 
+                                                     String endpointAddress) {
+        return DescriptionFactoryImpl
+                   .updateEndpoint(serviceDescription, sei, portQName, updateType, serviceDelegateKey, bindingId, endpointAddress);
+    }    
+    
+    /**
+     * Retrieve or create an EndpointDescription hierarchy associated with an existing CLIENT side
+     * ServiceDescription for a particular port.  Additional metadata may be specified in a sparse
+     * composite.  That metadata may come from a JSR-109 client deployment descriptor, for example,
+     * or from resource injection of an WebServiceRef or other Resource annotation.
+     * 
+     * @see #updateEndpoint(ServiceDescription, Class, QName, org.apache.axis2.jaxws.description.DescriptionFactory.UpdateType)
+     *  
+     * @param serviceDescription
+     * @param sei
+     * @param portQName
+     * @param updateType
+     * @param composite
+     * @return
+     */
+    public static EndpointDescription updateEndpoint(ServiceDescription serviceDescription,
+            Class sei, QName portQName,
+            DescriptionFactory.UpdateType updateType,
+            DescriptionBuilderComposite composite,
+            Object sparseCompositeKey,
+            String bindingId, String endpointAddress) {
+        return DescriptionFactoryImpl
+                   .updateEndpoint(serviceDescription, sei, portQName, updateType, composite, sparseCompositeKey, bindingId, endpointAddress);
+    }
+
+    /**
+     * Retrieve or create the EndpointDescription hierachy associated with an existing CLIENT side
+     * ServiceDescription for a particular port.  If an EndpointDescritption already exists, it will
+     * be returned; if one does not already exist, it will be created.  Note that if the SEI is null
+     * then the EndpointDescription returned will be for a Dispatch client only and it will not have
+     * an EndpointInterfaceDescription hierachy associated with it.  If, at a later point, the same
+     * port is requested and an SEI is provided, the existing EndpointDescription will be updated
+     * with a newly-created EndpointInterfaceDescription hieracy.
+     *
+     * @param serviceDescription  An existing client-side ServiceDescription.  This must not be
+     *                            null.
+     * @param sei                 The ServiceInterface class.  This can be null for adding a port or
+     *                            creating a Dispatch; it can not be null when getting a port.
+     * @param epr                 The endpoint reference to the target port.
+     * @param addressingNamespace The addressing namespace of the endpoint reference.
+     * @param updateType          The type of the update: adding a port, creating a dispatch, or
+     *                            getting an SEI-based port.
+     * @return An EndpointDescription corresponding to the port.
+     * @see #createServiceDescription(URL, QName, Class)
+     * @see DescriptionFactory.UpdateType
+     */
+    public static EndpointDescription updateEndpoint(ServiceDescription serviceDescription,
+                                                     Class sei, EndpointReference epr,
+                                                     String addressingNamespace,
+                                                     DescriptionFactory.UpdateType updateType,
+                                                     String bindingId, String endpointAddress) {
+        return DescriptionFactoryImpl
+                .updateEndpoint(serviceDescription, sei, epr, addressingNamespace, updateType, bindingId, endpointAddress);
+    }
+    
+    /**
+     * Retrieve or create the EndpointDescription hierarchy associated with an existing CLIENT side
+     * ServiceDescription for a particular port.  This is identical to above, but this method has a 
+     * reference back to the ServiceDelegate (which invoked it) for purposes of properly caching 
+     * ServiceDescriptions that contain dynamic ports
+     *
+     * @param serviceDescription An existing client-side ServiceDescription.  This must not be
+     *                           null.
+     * @param sei                The ServiceInterface class.  This can be null for adding a port or
+     *                           creating a Dispatch; it can not be null when getting a port.
+     * @param epr                 The endpoint reference to the target port.
+     * @param addressingNamespace The addressing namespace of the endpoint reference.
+     * @param updateType         The type of the update: adding a port, creating a dispatch, or
+     *                           getting an SEI-based port.
+     * @param serviceDelegateKey A reference back to the ServiceDelegate that called it
+     * @return An EndpointDescription corresponding to the port.
+     * @see #createServiceDescription(URL, QName, Class)
+     * @see DescriptionFactory.UpdateType
+     */
+    public static EndpointDescription updateEndpoint(ServiceDescription serviceDescription,
+                                                     Class sei, EndpointReference epr,
+                                                     String addressingNamespace,
+                                                     DescriptionFactory.UpdateType updateType,
+                                                     Object serviceDelegateKey,
+                                                     String bindingId, 
+                                                     String endpointAddress) {
+        return DescriptionFactoryImpl
+                   .updateEndpoint(serviceDescription, sei, epr, addressingNamespace, updateType, serviceDelegateKey, bindingId, endpointAddress);
+    }    
+
+    /**
+     * Retrieve or create an EndpointDescription hierachy associated with an existing CLIENT side
+     * ServiceDescription for a particular port.  Additonal metdata may be specified in a sparse
+     * composite.  That metadata may come from a JSR-109 client deployment descriptor, for example,
+     * or from resource injection of an WebServiceRef or other Resource annotation.
+     * 
+     * @see #updateEndpoint(ServiceDescription, Class, QName, org.apache.axis2.jaxws.description.DescriptionFactory.UpdateType)
+     *  
+     * @param serviceDescription
+     * @param sei
+     * @param portQName
+     * @param updateType
+     * @param composite
+     * @return
+     */
+    public static EndpointDescription updateEndpoint(ServiceDescription serviceDescription,
+            Class sei, EndpointReference epr,
+            String addressingNamespace,
+            DescriptionFactory.UpdateType updateType,
+            DescriptionBuilderComposite composite,
+            Object sparseCompositeKey,
+            String bindingId, String endpointAddress) {
+        return DescriptionFactoryImpl
+        .updateEndpoint(serviceDescription, sei, epr, addressingNamespace, updateType, composite, sparseCompositeKey, bindingId, endpointAddress);
     }
     
     /**

Modified: webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/impl/DescriptionFactoryImpl.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/impl/DescriptionFactoryImpl.java?rev=664411&r1=664410&r2=664411&view=diff
==============================================================================
--- webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/impl/DescriptionFactoryImpl.java (original)
+++ webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/impl/DescriptionFactoryImpl.java Sat Jun  7 16:05:15 2008
@@ -277,8 +277,9 @@
      */
     public static EndpointDescription updateEndpoint(
             ServiceDescription serviceDescription, Class sei, QName portQName,
-            DescriptionFactory.UpdateType updateType) {
-        return updateEndpoint(serviceDescription, sei, portQName, updateType, null, null);
+            DescriptionFactory.UpdateType updateType,
+            String bindingId, String endpointAddress) {
+        return updateEndpoint(serviceDescription, sei, portQName, updateType, null, null, bindingId, endpointAddress);
     }
     
     /**
@@ -287,8 +288,8 @@
      */
     public static EndpointDescription updateEndpoint(
             ServiceDescription serviceDescription, Class sei, QName portQName,
-            DescriptionFactory.UpdateType updateType, Object serviceDelegateKey ) {
-        return updateEndpoint(serviceDescription, sei, portQName, updateType, null, serviceDelegateKey);
+            DescriptionFactory.UpdateType updateType, Object serviceDelegateKey, String bindingId, String endpointAddress) {
+        return updateEndpoint(serviceDescription, sei, portQName, updateType, null, serviceDelegateKey, bindingId, endpointAddress);
     }
     
     /**
@@ -298,12 +299,14 @@
             ServiceDescription serviceDescription, Class sei, QName portQName,
             DescriptionFactory.UpdateType updateType, 
             DescriptionBuilderComposite composite,
-            Object serviceDelegateKey) {
+            Object serviceDelegateKey,
+            String bindingId, 
+            String endpointAddress) {
         EndpointDescription endpointDesc = null;
         synchronized(serviceDescription) {
                 endpointDesc = 
                 ((ServiceDescriptionImpl)serviceDescription)
-                        .updateEndpointDescription(sei, portQName, updateType, composite, serviceDelegateKey);
+                        .updateEndpointDescription(sei, portQName, updateType, composite, serviceDelegateKey, bindingId, endpointAddress);
         }
         EndpointDescriptionValidator endpointValidator = new EndpointDescriptionValidator(endpointDesc);
         
@@ -330,8 +333,8 @@
     public static EndpointDescription updateEndpoint(
             ServiceDescription serviceDescription, Class sei, EndpointReference epr,
             String addressingNamespace,
-            DescriptionFactory.UpdateType updateType) {
-        return updateEndpoint(serviceDescription, sei, epr, addressingNamespace, updateType, null, null);
+            DescriptionFactory.UpdateType updateType, String bindingId, String endpointAddress) {
+        return updateEndpoint(serviceDescription, sei, epr, addressingNamespace, updateType, null, null, bindingId, endpointAddress);
     }
 
     /**
@@ -342,8 +345,8 @@
             ServiceDescription serviceDescription, Class sei, EndpointReference epr,
             String addressingNamespace,
             DescriptionFactory.UpdateType updateType,
-            Object sparseCompositeKey) {
-        return updateEndpoint(serviceDescription, sei, epr, addressingNamespace, updateType, null, sparseCompositeKey);
+            Object sparseCompositeKey, String bindingId, String endpointAddress) {
+        return updateEndpoint(serviceDescription, sei, epr, addressingNamespace, updateType, null, sparseCompositeKey, bindingId, endpointAddress);
     }
 
     /**
@@ -355,7 +358,7 @@
             String addressingNamespace,
             DescriptionFactory.UpdateType updateType,
             DescriptionBuilderComposite composite,
-            Object sparseCompositeKey) {
+            Object sparseCompositeKey, String bindingId, String endpointAddress) {
         QName portQName = null;
         
         try {
@@ -381,7 +384,7 @@
                  Messages.getMessage("updateEndpointError", e.getMessage()));
         }
         
-        return updateEndpoint(serviceDescription, sei, portQName, updateType, composite, sparseCompositeKey);
+        return updateEndpoint(serviceDescription, sei, portQName, updateType, composite, sparseCompositeKey, bindingId, endpointAddress);
     }
 
     public static ClientConfigurationFactory getClientConfigurationFactory() {

Modified: webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/impl/ServiceDescriptionImpl.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/impl/ServiceDescriptionImpl.java?rev=664411&r1=664410&r2=664411&view=diff
==============================================================================
--- webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/impl/ServiceDescriptionImpl.java (original)
+++ webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/impl/ServiceDescriptionImpl.java Sat Jun  7 16:05:15 2008
@@ -22,6 +22,7 @@
 import org.apache.axis2.client.ServiceClient;
 import org.apache.axis2.context.ConfigurationContext;
 import org.apache.axis2.description.AxisService;
+import org.apache.axis2.description.Parameter;
 import org.apache.axis2.java.security.AccessController;
 import org.apache.axis2.jaxws.ClientConfigurationFactory;
 import org.apache.axis2.jaxws.ExceptionFactory;
@@ -47,6 +48,7 @@
 import org.apache.axis2.jaxws.i18n.Messages;
 import org.apache.axis2.jaxws.util.WSDL4JWrapper;
 import org.apache.axis2.jaxws.util.WSDLWrapper;
+import org.apache.axis2.AxisFault;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.xml.resolver.Catalog;
@@ -371,7 +373,9 @@
                                                   QName portQName,
                                                   DescriptionFactory.UpdateType updateType,
                                                   DescriptionBuilderComposite composite,
-                                                  Object serviceDelegateKey) {
+                                                  Object serviceDelegateKey,
+                                                  String bindingId,
+                                                  String endpointAddress) {
 
 	
     	EndpointDescriptionImpl endpointDescription = getEndpointDescriptionImpl(portQName);
@@ -419,8 +423,7 @@
                                  Messages.getMessage("serviceDescriptionImplAddPortErr"));
                     }
 
-                    endpointDescription = new EndpointDescriptionImpl(sei, portQName, true, this);
-
+                    endpointDescription = createEndpointDescriptionImpl(sei, portQName, bindingId, endpointAddress);    
                     addDynamicEndpointDescriptionImpl(endpointDescription, serviceDelegateKey);
 
                 } else {
@@ -525,6 +528,39 @@
         return endpointDescription;
     }
 
+    private EndpointDescriptionImpl createEndpointDescriptionImpl(Class sei, QName portQName, String bindingId, String endpointAddress) {
+        EndpointDescriptionImpl endpointDescription;
+        Parameter parameter = configContext.getAxisConfiguration().getParameter("jaxws.dynamic.endpoints");
+        WeakHashMap<String, EndpointDescriptionImpl> cachedDescriptions = (WeakHashMap<String, EndpointDescriptionImpl>)
+                ((parameter == null) ? null : parameter.getValue());
+        if(cachedDescriptions == null) {
+            cachedDescriptions = new WeakHashMap<String, EndpointDescriptionImpl>();
+            try {
+                configContext.getAxisConfiguration().addParameter("jaxws.dynamic.endpoints", cachedDescriptions);
+            } catch (AxisFault axisFault) {
+                throw new RuntimeException(axisFault);
+            }
+            configContext.setProperty("jaxws.dynamic.endpoints", cachedDescriptions);
+        }
+
+        StringBuffer key = new StringBuffer();
+        key.append(portQName == null ? "NULL" : portQName.toString());
+        key.append(':');
+        key.append(bindingId == null ? "NULL" : bindingId);
+        key.append(':');
+        key.append(endpointAddress == null ? "NULL" : endpointAddress);
+        synchronized(cachedDescriptions) {
+            endpointDescription = cachedDescriptions.get(key.toString());
+        }
+        if(endpointDescription == null) {
+            endpointDescription = new EndpointDescriptionImpl(sei, portQName, true, this);
+            synchronized(cachedDescriptions) {
+                cachedDescriptions.put(key.toString(), endpointDescription);
+            }
+        }
+        return endpointDescription;
+    }
+
     private Class getEndpointSEI(QName portQName) {
         Class endpointSEI = null;
         EndpointDescription endpointDesc = getEndpointDescription(portQName);