Add blueprint wiring to the toaster sample 67/35867/26
authorTom Pantelis <tpanteli@brocade.com>
Mon, 7 Mar 2016 01:46:38 +0000 (20:46 -0500)
committerAnil Vishnoi <vishnoianil@gmail.com>
Wed, 13 Apr 2016 20:09:48 +0000 (20:09 +0000)
Change-Id: I79922dd24847fd8682a0f2133e6effae9b608a0c
Signed-off-by: Tom Pantelis <tpanteli@brocade.com>
opendaylight/md-sal/samples/toaster-config/src/main/resources/initial/03-toaster-sample.xml
opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/sample/kitchen/impl/KitchenServiceImpl.java
opendaylight/md-sal/samples/toaster-consumer/src/main/resources/org/opendaylight/blueprint/toaster-consumer.xml [new file with mode: 0644]
opendaylight/md-sal/samples/toaster-consumer/src/main/yang/kitchen-service-impl.yang
opendaylight/md-sal/samples/toaster-provider/src/main/java/org/opendaylight/controller/config/yang/config/toaster_provider/impl/ToasterProviderModule.java
opendaylight/md-sal/samples/toaster-provider/src/main/java/org/opendaylight/controller/sample/toaster/provider/OpendaylightToaster.java
opendaylight/md-sal/samples/toaster-provider/src/main/resources/org/opendaylight/blueprint/toaster-provider.xml [new file with mode: 0644]
opendaylight/md-sal/samples/toaster-provider/src/main/yang/toaster-provider-impl.yang
opendaylight/md-sal/samples/toaster-provider/src/test/java/org/opendaylight/controller/sample/toaster/provider/OpenDaylightToasterTest.java

index 2e8c7d5ce6ee3f2093f6bc0340bda56e634d2d63..df07caa067ef2d16659923b8277cbf7cf7e89934 100644 (file)
                     </data-broker>
 
                     <notification-service>
-                        <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
-                            binding:binding-notification-service
+                        <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+                            binding:binding-new-notification-publish-service
                         </type>
-                        <name>binding-notification-broker</name>
+                        <name>binding-notification-publish-adapter</name>
                     </notification-service>
                 </module>
 
                     </rpc-registry>
 
                     <notification-service>
-                        <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
-                            binding:binding-notification-service
+                        <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+                            binding:binding-new-notification-service
                         </type>
-                        <name>binding-notification-broker</name>
+                        <name>binding-notification-adapter</name>
                     </notification-service>
                 </module>
             </modules>
index 3ea7b45f02afc02387d709e3b20b11038bc7b364..563b45ab77e50b6bb605da68a6921ce35ddab78c 100644 (file)
@@ -8,13 +8,21 @@
 
 package org.opendaylight.controller.sample.kitchen.impl;
 
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableList.Builder;
+import com.google.common.util.concurrent.AsyncFunction;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.JdkFutureAdapters;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
 import java.util.List;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
-
 import org.opendaylight.controller.config.yang.config.kitchen_service.impl.KitchenServiceRuntimeMXBean;
+import org.opendaylight.controller.md.sal.common.util.jmx.AbstractMXBean;
 import org.opendaylight.controller.sample.kitchen.api.EggsType;
 import org.opendaylight.controller.sample.kitchen.api.KitchenService;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.MakeToastInput;
@@ -26,22 +34,14 @@ import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterService;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.WheatBread;
 import org.opendaylight.yangtools.yang.common.RpcError;
-import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
+import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableList.Builder;
-import com.google.common.util.concurrent.AsyncFunction;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.JdkFutureAdapters;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
-
-public class KitchenServiceImpl implements KitchenService, KitchenServiceRuntimeMXBean, ToasterListener {
+public class KitchenServiceImpl extends AbstractMXBean
+        implements KitchenService, KitchenServiceRuntimeMXBean, ToasterListener {
 
     private static final Logger log = LoggerFactory.getLogger( KitchenServiceImpl.class );
 
@@ -53,6 +53,7 @@ public class KitchenServiceImpl implements KitchenService, KitchenServiceRuntime
     private volatile boolean toasterOutOfBread;
 
     public KitchenServiceImpl(ToasterService toaster) {
+        super("KitchenService", "toaster-consumer", null);
         this.toaster = toaster;
     }
 
diff --git a/opendaylight/md-sal/samples/toaster-consumer/src/main/resources/org/opendaylight/blueprint/toaster-consumer.xml b/opendaylight/md-sal/samples/toaster-consumer/src/main/resources/org/opendaylight/blueprint/toaster-consumer.xml
new file mode 100644 (file)
index 0000000..6b9bf35
--- /dev/null
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+           xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+    odl:use-default-for-reference-types="true">
+
+   <!-- Retrieves the RPC service for the ToasterService interface -->
+  <odl:rpc-service id="toasterService" interface="org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterService"/>
+
+  <!-- Create the KitchenServiceImpl instance and inject the RPC service identified by "toasterService" -->
+  <bean id="kitchenService" class="org.opendaylight.controller.sample.kitchen.impl.KitchenServiceImpl"
+          init-method="register" destroy-method="unregister">
+    <argument ref="toasterService"/>
+  </bean>
+
+  <!-- Register the KitchenServiceImpl to receive yang notifications -->
+  <odl:notification-listener ref="kitchenService"/>
+
+   <!-- Advertise the KitchenServiceImpl with the OSGi registry with the type property set to "default" . The
+       type property is optional but can be used to distinguish this implementation from any other potential
+       KitchenService implementations (if there were any). Clients consuming the KitchenService can pick the
+       desired implementation via the particular type.
+  -->
+  <service ref="kitchenService" interface="org.opendaylight.controller.sample.kitchen.api.KitchenService"
+          odl:type="default"/>
+</blueprint>
\ No newline at end of file
index d22dfc619a30327612e7e72b76e3bfb22786f97f..fd25878949ca5df366a65d041846ddbfbfd8813e 100644 (file)
@@ -9,6 +9,7 @@ module kitchen-service-impl {
     import rpc-context { prefix rpcx; revision-date 2013-06-17; }
 
     import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
+    import opendaylight-sal-binding-broker-impl { prefix binding-impl; revision-date 2013-10-28; }
 
     description
         "This module contains the base YANG definitions for
@@ -49,7 +50,7 @@ module kitchen-service-impl {
                 uses config:service-ref {
                     refine type {
                         mandatory true;
-                        config:required-identity mdsal:binding-notification-service;
+                        config:required-identity binding-impl:binding-new-notification-service;
                     }
                 }
             }
index 97e0a6bcf77dd5c35afe70330bc48976bce0ac61..47c5692564c056c509d63a045d5c7dc1781cbbd0 100644 (file)
 package org.opendaylight.controller.config.yang.config.toaster_provider.impl;
 
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
 import org.opendaylight.controller.sample.toaster.provider.OpendaylightToaster;
-import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.Toaster;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterService;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -64,10 +60,6 @@ public final class ToasterProviderModule extends
         DataBroker dataBrokerService = getDataBrokerDependency();
         opendaylightToaster.setDataProvider(dataBrokerService);
 
-        final ListenerRegistration<OpendaylightToaster> dataTreeChangeListenerRegistration = dataBrokerService
-                .registerDataTreeChangeListener(new DataTreeIdentifier<Toaster>(LogicalDatastoreType.CONFIGURATION,
-                        OpendaylightToaster.TOASTER_IID), opendaylightToaster);
-
         final BindingAwareBroker.RpcRegistration<ToasterService> rpcRegistration = getRpcRegistryDependency()
                 .addRpcImplementation(ToasterService.class, opendaylightToaster);
 
@@ -81,7 +73,6 @@ public final class ToasterProviderModule extends
 
             @Override
             public void close() throws Exception {
-                dataTreeChangeListenerRegistration.close();
                 rpcRegistration.close();
                 runtimeReg.close();
                 closeQuietly(opendaylightToaster);
index e39ac2baff36836df38392ea2d0f4ee659c50bf0..ef2bfb690454c4c411c6a19f4006e8957fe67e62 100644 (file)
@@ -26,13 +26,15 @@ import org.opendaylight.controller.config.yang.config.toaster_provider.impl.Toas
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedException;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.controller.md.sal.common.util.jmx.AbstractMXBean;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.DisplayString;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.MakeToastInput;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.RestockToasterInput;
@@ -43,6 +45,7 @@ import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterRestocked;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterRestockedBuilder;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
@@ -51,7 +54,7 @@ import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class OpendaylightToaster implements ToasterService, ToasterProviderRuntimeMXBean,
+public class OpendaylightToaster extends AbstractMXBean implements ToasterService, ToasterProviderRuntimeMXBean,
                                             DataTreeChangeListener<Toaster>, AutoCloseable {
 
     private static final Logger LOG = LoggerFactory.getLogger(OpendaylightToaster.class);
@@ -61,8 +64,9 @@ public class OpendaylightToaster implements ToasterService, ToasterProviderRunti
     private static final DisplayString TOASTER_MANUFACTURER = new DisplayString("Opendaylight");
     private static final DisplayString TOASTER_MODEL_NUMBER = new DisplayString("Model 1 - Binding Aware");
 
-    private NotificationProviderService notificationProvider;
+    private NotificationPublishService notificationProvider;
     private DataBroker dataProvider;
+    private ListenerRegistration<OpendaylightToaster> dataTreeChangeListenerRegistration;
 
     private final ExecutorService executor;
 
@@ -78,15 +82,20 @@ public class OpendaylightToaster implements ToasterService, ToasterProviderRunti
     private final AtomicLong darknessFactor = new AtomicLong( 1000 );
 
     public OpendaylightToaster() {
+        super("OpendaylightToaster", "toaster-provider", null);
         executor = Executors.newFixedThreadPool(1);
     }
 
-    public void setNotificationProvider(final NotificationProviderService salService) {
-        this.notificationProvider = salService;
+    public void setNotificationProvider(final NotificationPublishService notificationPublishService) {
+        this.notificationProvider = notificationPublishService;
     }
 
     public void setDataProvider(final DataBroker salDataProvider) {
         this.dataProvider = salDataProvider;
+
+        dataProvider.registerDataTreeChangeListener(new DataTreeIdentifier<Toaster>(
+                LogicalDatastoreType.CONFIGURATION, OpendaylightToaster.TOASTER_IID), this);
+
         setToasterStatusUp( null );
     }
 
@@ -99,6 +108,8 @@ public class OpendaylightToaster implements ToasterService, ToasterProviderRunti
         executor.shutdown();
 
         if (dataProvider != null) {
+            dataTreeChangeListenerRegistration.close();
+
             WriteTransaction tx = dataProvider.newWriteOnlyTransaction();
             tx.delete(LogicalDatastoreType.OPERATIONAL,TOASTER_IID);
             Futures.addCallback( tx.submit(), new FutureCallback<Void>() {
@@ -297,7 +308,7 @@ public class OpendaylightToaster implements ToasterService, ToasterProviderRunti
         if( amountOfBreadInStock.get() > 0 ) {
             ToasterRestocked reStockedNotification = new ToasterRestockedBuilder()
                 .setAmountOfBread( input.getAmountOfBreadToStock() ).build();
-            notificationProvider.publish( reStockedNotification );
+            notificationProvider.offerNotification( reStockedNotification );
         }
 
         return Futures.immediateFuture( RpcResultBuilder.<Void> success().build() );
@@ -383,7 +394,7 @@ public class OpendaylightToaster implements ToasterService, ToasterProviderRunti
             if( outOfBread() ) {
                 LOG.info( "Toaster is out of bread!" );
 
-                notificationProvider.publish( new ToasterOutOfBreadBuilder().build() );
+                notificationProvider.offerNotification( new ToasterOutOfBreadBuilder().build() );
             }
 
             // Set the Toaster status back to up - this essentially releases the toasting lock.
diff --git a/opendaylight/md-sal/samples/toaster-provider/src/main/resources/org/opendaylight/blueprint/toaster-provider.xml b/opendaylight/md-sal/samples/toaster-provider/src/main/resources/org/opendaylight/blueprint/toaster-provider.xml
new file mode 100644 (file)
index 0000000..01cb313
--- /dev/null
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+           xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+           xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
+    odl:restart-dependents-on-updates="true" odl:use-default-for-reference-types="true">
+
+  <!-- "restart-dependents-on-updates" is an ODL extension attribute that processes any "property-placeholder"
+       elements and reacts to updates to the corresponding cfg file by restarting this blueprint container any
+       dependent containers that consume OSGi services provided by this container in an atomic and orderly
+       manner.
+
+       "use-default-for-reference-types" is an ODL extension attribute that adds a filter to all services
+       imported via "reference" elements where the "type" property is either not set or set to "default" if
+       the odl:type attribute isn't explicitly specified. This ensures the default implementation is imported
+       if there are other implementations advertised with other types.
+  -->
+
+  <!-- Accesses properties via the etc/org.opendaylight.toaster.cfg file. The properties are made available
+       as variables that can be referenced. The variables are substituted with the actual values read from
+       the cfg file, if present, or the default-properties.
+   -->
+  <cm:property-placeholder persistent-id="org.opendaylight.toaster" update-strategy="none">
+    <cm:default-properties>
+      <cm:property name="databroker-type" value="default"/>
+    </cm:default-properties>
+  </cm:property-placeholder>
+
+  <!-- Import MD-SAL services. For the DataBroker, we explicitly specify the odl:type which is configurable
+       via the cfg file. In this manner the toaster can be configured to use the default clustered DataBroker
+       or the specialized "pingpong" DataBroker (or any other DataBroker implementation).
+   -->
+  <reference id="dataBroker" interface="org.opendaylight.controller.md.sal.binding.api.DataBroker" odl:type="${databroker-type}" />
+  <reference id="notificationService" interface="org.opendaylight.controller.md.sal.binding.api.NotificationPublishService"/>
+
+  <!-- Create the OpendaylightToaster instance and inject its dependencies -->
+  <bean id="toaster" class="org.opendaylight.controller.sample.toaster.provider.OpendaylightToaster"
+          init-method="register" destroy-method="unregister">
+    <property name="dataProvider" ref="dataBroker"/>
+    <property name="notificationProvider" ref="notificationService"/>
+  </bean>
+
+  <!-- Register the OpendaylightToaster instance as an RPC implementation provider. The "rpc-implementation"
+       element automatically figures out the RpcService interface although it can be explicitly specified.
+   -->
+  <odl:rpc-implementation ref="toaster"/>
+</blueprint>
\ No newline at end of file
index 8de0c98c63e98f136ac91c98b1792fb040e0be63..f978e49b47351187e09df0e1ea8f144ab5c14985 100644 (file)
@@ -8,6 +8,7 @@ module toaster-provider-impl {
     import config { prefix config; revision-date 2013-04-05; }
     import rpc-context { prefix rpcx; revision-date 2013-06-17; }
     import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
+    import opendaylight-sal-binding-broker-impl { prefix binding-impl; revision-date 2013-10-28; }
 
     description
         "This module contains the base YANG definitions for
@@ -44,7 +45,7 @@ module toaster-provider-impl {
                 uses config:service-ref {
                     refine type {
                         mandatory true;
-                        config:required-identity mdsal:binding-notification-service;
+                        config:required-identity binding-impl:binding-new-notification-publish-service;
                     }
                 }
             }
index 287b012425a84d977c5178d7ddb7cd68e3c82a1e..b189e461cc00e52fbacdeb658171db635ec119cb 100644 (file)
@@ -13,16 +13,15 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
-
+import com.google.common.base.Optional;
 import java.util.concurrent.Future;
-
 import org.junit.Ignore;
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.DisplayString;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.MakeToastInput;
 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.MakeToastInputBuilder;
@@ -31,8 +30,6 @@ import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 
-import com.google.common.base.Optional;
-
 public class OpenDaylightToasterTest extends AbstractDataBrokerTest{
 
     private static InstanceIdentifier<Toaster> TOASTER_IID =
@@ -48,7 +45,7 @@ public class OpenDaylightToasterTest extends AbstractDataBrokerTest{
          * Doesn't look like we have support for the NotificationProviderService yet, so mock it
          * for now.
          */
-        NotificationProviderService mockNotification = mock( NotificationProviderService.class );
+        NotificationPublishService mockNotification = mock( NotificationPublishService.class );
         toaster.setNotificationProvider( mockNotification );
     }