KNOX-1339 - Ability to specify dispatch within a service element in a topology, this...
authorSandeep More <more@apache.org>
Wed, 5 Sep 2018 16:32:10 +0000 (12:32 -0400)
committerSandeep More <more@apache.org>
Wed, 5 Sep 2018 16:32:10 +0000 (12:32 -0400)
gateway-server/src/main/java/org/apache/knox/gateway/deploy/impl/ServiceDefinitionDeploymentContributor.java
gateway-server/src/main/java/org/apache/knox/gateway/topology/builder/BeanPropertyTopologyBuilder.java
gateway-server/src/main/java/org/apache/knox/gateway/topology/xml/KnoxFormatXmlTopologyRules.java
gateway-server/src/main/resources/conf/topology-v1.xsd
gateway-server/src/test/java/org/apache/knox/gateway/deploy/impl/ServiceDefinitionDeploymentContributorTest.java
gateway-server/src/test/java/org/apache/knox/gateway/topology/xml/TopologyRulesModuleTest.java
gateway-server/src/test/resources/org/apache/knox/gateway/topology/xml/TopologyRulesModuleTest/topology-with-dispatch.xml
gateway-spi/src/main/java/org/apache/knox/gateway/topology/Service.java
gateway-spi/src/main/java/org/apache/knox/gateway/topology/Topology.java

index 1aa54fb..8064846 100644 (file)
@@ -184,8 +184,9 @@ public class ServiceDefinitionDeploymentContributor extends ServiceDeploymentCon
   private void addDispatchFilter(DeploymentContext context, Service service, ResourceDescriptor resource, Route binding) {
     CustomDispatch customDispatch = binding.getDispatch();
 
-    if(context.getTopology().getDispatch() != null) {
-      customDispatch = context.getTopology().getDispatch();
+    /* Override dispatch specified in the topology <service> element */
+    if(service.getDispatch() != null) {
+      customDispatch = service.getDispatch();
     }
 
     if ( customDispatch == null ) {
index 1a54f44..11016b0 100644 (file)
@@ -33,7 +33,6 @@ public class BeanPropertyTopologyBuilder implements TopologyBuilder {
     private List<Provider> providers;
     private List<Service> services;
     private List<Application> applications;
-    private CustomDispatch dispatch;
 
     public BeanPropertyTopologyBuilder() {
         providers = new ArrayList<Provider>();
@@ -86,14 +85,6 @@ public class BeanPropertyTopologyBuilder implements TopologyBuilder {
         return services;
     }
 
-    public void addDispatch(final CustomDispatch dispatch) {
-        this.dispatch = dispatch;
-    }
-
-    public CustomDispatch getDispatch() {
-        return this.dispatch;
-    }
-
     public BeanPropertyTopologyBuilder addApplication( Application application ) {
         applications.add(application);
         return this;
@@ -109,8 +100,6 @@ public class BeanPropertyTopologyBuilder implements TopologyBuilder {
         topology.setDefaultServicePath(defaultService);
         topology.setGenerated(isGenerated);
 
-        topology.addDispatch(dispatch);
-
         for (Provider provider : providers) {
             topology.addProvider(provider);
         }
index 8cf5b9f..1905610 100644 (file)
@@ -45,7 +45,7 @@ public class KnoxFormatXmlTopologyRules extends AbstractRulesModule {
   private static final String VALUE_TAG = "value";
 
   /* topology dispatch tags */
-  private static final String DISPATCH_TAG = "gateway/dispatch";
+  private static final String DISPATCH_TAG = "dispatch";
   private static final String CONTRIBUTOR_NAME = "contributor-name";
   private static final String HA_CONTRIBUTOR_NAME = "ha-contributor-name";
   private static final String CLASSNAME = "classname";
@@ -80,6 +80,14 @@ public class KnoxFormatXmlTopologyRules extends AbstractRulesModule {
     forPattern( ROOT_TAG + "/" + SERVICE_TAG + "/" + PARAM_TAG ).createObject().ofType( Param.class ).then().addRule( paramRule ).then().setNext( "addParam" );
     forPattern( ROOT_TAG + "/" + SERVICE_TAG + "/" + PARAM_TAG + "/" + NAME_TAG ).setBeanProperty();
     forPattern( ROOT_TAG + "/" + SERVICE_TAG + "/" + PARAM_TAG + "/" + VALUE_TAG ).setBeanProperty();
+    /* topology service dispatch */
+    forPattern( ROOT_TAG + "/" + SERVICE_TAG + "/" + DISPATCH_TAG).createObject().ofType( CustomDispatch.class ).then().setNext( "addDispatch" );
+    forPattern( ROOT_TAG + "/" + SERVICE_TAG + "/" + DISPATCH_TAG + "/" + CONTRIBUTOR_NAME ).callMethod( "setContributorName" ).usingElementBodyAsArgument();
+    forPattern( ROOT_TAG + "/" + SERVICE_TAG + "/" + DISPATCH_TAG + "/" + HA_CONTRIBUTOR_NAME ).callMethod( "setHaContributorName" ).usingElementBodyAsArgument();
+    forPattern( ROOT_TAG + "/" + SERVICE_TAG + "/" + DISPATCH_TAG + "/" + CLASSNAME ).callMethod( "setClassName" ).usingElementBodyAsArgument();
+    forPattern( ROOT_TAG + "/" + SERVICE_TAG + "/" + DISPATCH_TAG + "/" + HA_CLASSNAME ).callMethod( "setHaClassName" ).usingElementBodyAsArgument();
+    forPattern( ROOT_TAG + "/" + SERVICE_TAG + "/" + DISPATCH_TAG + "/" + HTTP_CLIENT_FACTORY ).callMethod( "setHttpClientFactory" ).usingElementBodyAsArgument();
+    forPattern( ROOT_TAG + "/" + SERVICE_TAG + "/" + DISPATCH_TAG + "/" + USE_TWO_WAY_SSL ).callMethod( "setUseTwoWaySsl" ).usingElementBodyAsArgument();
 
     forPattern( ROOT_TAG + "/" + PROVIDER_TAG ).createObject().ofType( Provider.class ).then().setNext( "addProvider" );
     forPattern( ROOT_TAG + "/" + PROVIDER_TAG + "/" + ROLE_TAG ).setBeanProperty();
@@ -89,14 +97,6 @@ public class KnoxFormatXmlTopologyRules extends AbstractRulesModule {
     forPattern( ROOT_TAG + "/" + PROVIDER_TAG + "/" + PARAM_TAG + "/" + NAME_TAG ).setBeanProperty();
     forPattern( ROOT_TAG + "/" + PROVIDER_TAG + "/" + PARAM_TAG + "/" + VALUE_TAG ).setBeanProperty();
 
-    /* topology dispatch */
-    forPattern( ROOT_TAG + "/" + DISPATCH_TAG ).createObject().ofType( CustomDispatch.class ).then().setNext( "addDispatch" );
-    forPattern( ROOT_TAG + "/" + DISPATCH_TAG + "/" + CONTRIBUTOR_NAME ).callMethod( "setContributorName" ).usingElementBodyAsArgument();
-    forPattern( ROOT_TAG + "/" + DISPATCH_TAG + "/" + HA_CONTRIBUTOR_NAME ).callMethod( "setHaContributorName" ).usingElementBodyAsArgument();
-    forPattern( ROOT_TAG + "/" + DISPATCH_TAG + "/" + CLASSNAME ).callMethod( "setClassName" ).usingElementBodyAsArgument();
-    forPattern( ROOT_TAG + "/" + DISPATCH_TAG + "/" + HA_CLASSNAME ).callMethod( "setHaClassName" ).usingElementBodyAsArgument();
-    forPattern( ROOT_TAG + "/" + DISPATCH_TAG + "/" + HTTP_CLIENT_FACTORY ).callMethod( "setHttpClientFactory" ).usingElementBodyAsArgument();
-    forPattern( ROOT_TAG + "/" + DISPATCH_TAG + "/" + USE_TWO_WAY_SSL ).callMethod( "setUseTwoWaySsl" ).usingElementBodyAsArgument();
   }
 
   private static class ParamRule extends Rule {
index 04f673b..42d5433 100644 (file)
@@ -26,7 +26,7 @@ limitations under the License.
 
                 <h:element name="gateway" minOccurs="0" maxOccurs="1">
                     <h:complexType>
-                        <h:sequence minOccurs="1" maxOccurs="unbounded">
+                        <h:choice minOccurs="1" maxOccurs="unbounded">
 
                             <h:element name="provider" maxOccurs="unbounded">
                                 <h:complexType>
@@ -49,20 +49,7 @@ limitations under the License.
                                 </h:complexType>
                             </h:element>
 
-                            <h:element name="dispatch" minOccurs="0" maxOccurs="1">
-                                <h:complexType>
-                                    <h:all>
-                                        <h:element name="contributor-name" type="h:string" minOccurs="0" maxOccurs="1"/>
-                                        <h:element name="ha-contributor-name" type="h:string" minOccurs="0" maxOccurs="1"/>
-                                        <h:element name="classname" type="h:string" minOccurs="0" maxOccurs="1"/>
-                                        <h:element name="ha-classname" type="h:string" minOccurs="0" maxOccurs="1"/>
-                                        <h:element name="http-client-factory" type="h:string" minOccurs="0" maxOccurs="1"/>
-                                        <h:element name="use-two-way-ssl" type="h:string" minOccurs="0" maxOccurs="1"/>
-                                    </h:all>
-                                </h:complexType>
-                            </h:element>
-
-                        </h:sequence>
+                        </h:choice>
 
                     </h:complexType>
                 </h:element>
@@ -83,6 +70,18 @@ limitations under the License.
                                     <h:attribute name="value" type="h:string" use="optional" />
                                 </h:complexType>
                             </h:element>
+                            <h:element name="dispatch" minOccurs="0" maxOccurs="1">
+                                <h:complexType>
+                                    <h:all>
+                                        <h:element name="contributor-name" type="h:string" minOccurs="0" maxOccurs="1"/>
+                                        <h:element name="ha-contributor-name" type="h:string" minOccurs="0" maxOccurs="1"/>
+                                        <h:element name="classname" type="h:string" minOccurs="0" maxOccurs="1"/>
+                                        <h:element name="ha-classname" type="h:string" minOccurs="0" maxOccurs="1"/>
+                                        <h:element name="http-client-factory" type="h:string" minOccurs="0" maxOccurs="1"/>
+                                        <h:element name="use-two-way-ssl" type="h:string" minOccurs="0" maxOccurs="1"/>
+                                    </h:all>
+                                </h:complexType>
+                            </h:element>
                         </h:sequence>
                     </h:complexType>
                 </h:element>
index 9a69625..3e08fc2 100644 (file)
@@ -164,9 +164,8 @@ public class ServiceDefinitionDeploymentContributorTest {
   }
 
   /**
-   * Test for a feature that sets dispatch for all the services defined in a
-   * topology. The dispatch is defined just once in the topology inside the
-   * <gateway> </gateway> tag.
+   * Test for a feature that sets dispatch the services defined in a
+   * topology. The dispatch is defined per service in a topology.
    * @since 1.2.0
    */
   @Test
@@ -235,7 +234,7 @@ public class ServiceDefinitionDeploymentContributorTest {
     providers.add(haProvider);
     EasyMock.expect(topology.getProviders()).andReturn(providers).anyTimes();
     /* mock topology dispatch */
-    EasyMock.expect(topology.getDispatch()).andReturn(topologyDispatch).anyTimes();
+    //EasyMock.expect(topology.getDispatch()).andReturn(topologyDispatch).anyTimes();
     EasyMock.replay(topology);
     EasyMock.expect(context.getTopology()).andReturn(topology).anyTimes();
 
@@ -248,6 +247,8 @@ public class ServiceDefinitionDeploymentContributorTest {
     Map<String, String> svcParams = new HashMap<>();
     EasyMock.expect(service.getParams()).andReturn(svcParams).anyTimes();
     EasyMock.expect(service.getRole()).andReturn(TEST_SERVICE_ROLE).anyTimes();
+    EasyMock.expect(service.getUrl()).andReturn("http://localhost:8081").anyTimes();
+    EasyMock.expect(service.getDispatch()).andReturn(topologyDispatch).anyTimes();
     EasyMock.replay(service);
 
     sddc.contributeService(context, service);
index cbcd302..0f88093 100644 (file)
@@ -36,6 +36,7 @@ import java.io.File;
 import java.io.IOException;
 import java.net.URISyntaxException;
 import java.net.URL;
+import java.util.Collection;
 
 import static org.apache.commons.digester3.binder.DigesterLoader.newLoader;
 import static org.hamcrest.collection.IsMapContaining.hasEntry;
@@ -262,17 +263,19 @@ public class TopologyRulesModuleTest {
 
   @Test
   public void testParseTopologyWithDispatch() throws IOException, SAXException {
-    Digester digester = loader.newDigester();
-    String name = "topology-with-dispatch.xml";
-    URL url = TestUtils.getResourceUrl( TopologyRulesModuleTest.class, name );
+    final Digester digester = loader.newDigester();
+    final String name = "topology-with-dispatch.xml";
+    final URL url = TestUtils.getResourceUrl( TopologyRulesModuleTest.class, name );
     assertThat( "Failed to find URL for resource " + name, url, notNullValue() );
-    File file = new File( url.getFile() );
-    TopologyBuilder topologyBuilder = digester.parse( url );
-    Topology topology = topologyBuilder.build();
+    final File file = new File( url.getFile() );
+    final TopologyBuilder topologyBuilder = digester.parse( url );
+    final Topology topology = topologyBuilder.build();
     assertThat( "Failed to parse resource " + name, topology, notNullValue() );
     topology.setTimestamp( file.lastModified() );
 
-    CustomDispatch dispatch = topology.getDispatch();
+    final Collection<Service> services =  topology.getServices();
+    final CustomDispatch dispatch = services.iterator().next().getDispatch();
+
     assertThat( "Failed to find dispatch", dispatch, notNullValue() );
     assertThat( dispatch.getContributorName(), is("testContributor") );
     assertThat( dispatch.getHaContributorName(), is("testHAContributor") );
index 5224726..a73f03d 100644 (file)
@@ -16,7 +16,9 @@
 -->
 <topology>
     <name>test-topology-name</name>
-    <gateway>
+    <service>
+        <role>TestRole</role>
+        <url>http://localhost:8081</url>
         <dispatch>
             <contributor-name>testContributor</contributor-name>
             <ha-contributor-name>testHAContributor</ha-contributor-name>
@@ -25,5 +27,5 @@
             <http-client-factory>testHttpClientFactory</http-client-factory>
             <use-two-way-ssl>true</use-two-way-ssl>
         </dispatch>
-    </gateway>
+    </service>
 </topology>
\ No newline at end of file
index faa8165..d30eb17 100644 (file)
@@ -17,6 +17,8 @@
  */
 package org.apache.knox.gateway.topology;
 
+import org.apache.knox.gateway.service.definition.CustomDispatch;
+
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.LinkedHashMap;
@@ -32,6 +34,7 @@ public class Service {
   private Version version;
   private Map<String, String> params = new LinkedHashMap<String, String>();
   private List<String> urls;
+  private CustomDispatch dispatch = null;
 
   public String getRole() {
     return role;
@@ -149,4 +152,24 @@ public class Service {
 
     return hashCode;
   }
+
+  /**
+   * Dispatch configured in topology service.
+   * Returns null if none configured.
+   * @since 1.2.0
+   * @return dispatch
+   */
+  public CustomDispatch getDispatch() {
+    return dispatch;
+  }
+
+  /**
+   * Add a custom dispatch that overrides the dispatch
+   * specified in service definition.
+   * @since 1.2.0
+   * @param dispatch
+   */
+  public void addDispatch(CustomDispatch dispatch) {
+    this.dispatch = dispatch;
+  }
 }
index bbbd129..e773c79 100644 (file)
@@ -114,25 +114,6 @@ public class Topology {
     return url;
   }
 
-  /**
-   * Add dispatch to be used by all the services
-   * deployed in this topology
-   * @since 1.2.0
-   * @param dispatch
-   */
-  public void addDispatch(final CustomDispatch dispatch) {
-    this.dispatch = dispatch;
-  }
-
-  /**
-   * Get the dispatch to be used by all the services
-   * deployed in this topology
-   * @return dispatch
-   */
-  public CustomDispatch getDispatch() {
-    return dispatch;
-  }
-
   public Application getApplication(String url) {
     return applicationMap.get( fixApplicationUrl( url ) );
   }