4 Replies Latest reply on May 10, 2010 5:05 AM by alesj

    MC service does not maintain properties

    thomas.diesler

      Currently there are multiple failures when the testsuite is run against the AS.

       

      https://jira.jboss.org/jira/browse/JBOSGI-326

       

      In this particular case the client API uses

       

      context.getServiceReferences("javax.management.MBeanServer", null)
      

       

      which discovers multiple MBeanServers one of which it cannot obtain the properties from.

       

      -------------------------------------------------------------------------------
      Test set: org.jboss.test.osgi.example.simple.husky.SimpleHuskyTestCase
      -------------------------------------------------------------------------------
      Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 1.834 sec <<< FAILURE!
      testSimpleBundle(org.jboss.test.osgi.example.simple.husky.SimpleHuskyTestCase)  Time elapsed: 1.761 sec  <<< ERROR!
      java.lang.IllegalArgumentException: Service with id [171959] Not Found
          at org.apache.aries.jmx.util.FrameworkUtils.resolveService(FrameworkUtils.java:106)
          at org.apache.aries.jmx.framework.ServiceState.getProperties(ServiceState.java:101)
          ...
          at $Proxy125.getProperties(Unknown Source)
          at org.jboss.osgi.jmx.internal.ServiceStateExt.getProperties(ServiceStateExt.java:194)
          ...
          at $Proxy7.getProperties(Unknown Source)
          at org.jboss.osgi.testing.internal.RemoteRuntime.getServiceReferences(RemoteRuntime.java:200)
          at org.jboss.osgi.testing.internal.OSGiRuntimeImpl.addCapability(OSGiRuntimeImpl.java:92)
          at org.jboss.osgi.testing.internal.OSGiRuntimeImpl.addCapability(OSGiRuntimeImpl.java:85)
          at org.jboss.test.osgi.example.simple.husky.SimpleHuskyTestCase.setUp(SimpleHuskyTestCase.java:68)
      
      asdf
      

       

      2010-05-07 09:46:59,567 TRACE [org.jboss.osgi.jmx.internal.ServiceStateExt] (RMI TCP Connection(4)-127.0.0.1) getServices [clazz=javax.management.MBeanServer,filter=null]
      2010-05-07 09:46:59,575 TRACE [org.jboss.osgi.jmx.internal.ServiceStateExt] (RMI TCP Connection(4)-127.0.0.1) Added service: javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=SERVICE,items=((itemName=BundleIdentifier,itemType=javax.management.openmbean.SimpleType(name=java.lang.Long)),(itemName=Identifier,itemType=javax.management.openmbean.SimpleType(name=java.lang.Long)),(itemName=UsingBundles,itemType=javax.management.openmbean.ArrayType(name=[Ljava.lang.Long;,dimension=1,elementType=javax.management.openmbean.SimpleType(name=java.lang.Long),primitiveArray=false)),(itemName=objectClass,itemType=javax.management.openmbean.ArrayType(name=[Ljava.lang.String;,dimension=1,elementType=javax.management.openmbean.SimpleType(name=java.lang.String),primitiveArray=false)))),contents={BundleIdentifier=0, Identifier=171959, UsingBundles=[Ljava.lang.Long;@149650, objectClass=[Ljava.lang.String;@1986b90})
      2010-05-07 09:46:59,575 TRACE [org.jboss.osgi.jmx.internal.ServiceStateExt] (RMI TCP Connection(4)-127.0.0.1) Added service: javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=SERVICE,items=((itemName=BundleIdentifier,itemType=javax.management.openmbean.SimpleType(name=java.lang.Long)),(itemName=Identifier,itemType=javax.management.openmbean.SimpleType(name=java.lang.Long)),(itemName=UsingBundles,itemType=javax.management.openmbean.ArrayType(name=[Ljava.lang.Long;,dimension=1,elementType=javax.management.openmbean.SimpleType(name=java.lang.Long),primitiveArray=false)),(itemName=objectClass,itemType=javax.management.openmbean.ArrayType(name=[Ljava.lang.String;,dimension=1,elementType=javax.management.openmbean.SimpleType(name=java.lang.String),primitiveArray=false)))),contents={BundleIdentifier=7, Identifier=76690, UsingBundles=[Ljava.lang.Long;@1bdda87, objectClass=[Ljava.lang.String;@1560732})
      

       

      I suppose it is ok that multiple services are discovered, one of which is non-osgi. What needs to get fixed here is that the MC service provides properties in the same way as the OSGi service. The getServiceReference("javax.management.MBeanServer") API however needs to choose a single instance however. More generally the sorting of multiple service references needs to be defined in the context of service mix.

       

      I suggest we provide/generate proper service metadata (i.e. service id) that can be used by the standard OSGi algorithms. The service ranking has higher priority than the service id. Should we perhaps register MC services with lower ranking than OSGi services instead of relying on service id.

       

      This is related to http://community.jboss.org/thread/151237

        • 1. Re: Handling the service mix in AS
          thomas.diesler

          The underlying issue seems to be that OSGi service metadata are currently not associated with the ControllerContext. Can this be done at the MC level i.e. how do I associate arbitrary data with a CC without having to cache that CC?

          • 2. Re: Handling the service mix in AS
            thomas.diesler

            I changed MDRUtils to maintain the service properties there

             

            http://github.com/jbosgi/jbosgi-framework/blob/3688c3e6ec91d685aa531dd3cfefb137da406fdb/core/src/main/java/org/jboss/osgi/framework/bundle/MDRUtils.java

             

               // Maps controller context to properties.
               // [TODO] Can this be moved to the MC metadata layer?
               private static Map<ControllerContext, Dictionary<String, Object>> propertiesCache = new WeakHashMap<ControllerContext, Dictionary<String, Object>>();



               static Dictionary<String, Object> getProperties(ControllerContext context)
               {
                  MetaData metaData = getMetaData(context, CommonLevels.INSTANCE);
                  Dictionary<String, Object> properties = metaData.getMetaData(Dictionary.class);
                  if (properties != null)
                     return properties;
                 
                  properties = propertiesCache.get(context);
                  if (properties == null)
                  {
                     properties = new Hashtable<String, Object>();
                     propertiesCache.put(context, properties);
                  }
                 
                  return properties;
               }

            The GenericServiceWrapper sets thes properties

                  // The Framework adds the following service properties to the service properties
                  // * A property named Constants.SERVICE_ID identifying the registration number of the service
                  // * A property named Constants.OBJECTCLASS containing all the specified classes.
                 
                  Dictionary<String, Object> properties = MDRUtils.getProperties(context);
                  if (properties.get(Constants.SERVICE_ID) == null)
                  {
                     Long serviceId = OSGiServiceState.getNextServiceId();
                     properties.put(Constants.SERVICE_ID, serviceId);
                  }
                  if (properties.get(Constants.OBJECTCLASS) == null)
                  {
                     String[] objectClass = MDRUtils.getClasses(context);
                     if (objectClass == null)
                     {
                        BeanMetaData bmd = context.getBeanMetaData();
                        objectClass = new String[] { bmd.getBean() };
                     }
                     properties.put(Constants.OBJECTCLASS, objectClass);
                  }
                  // By default assign the lowest possible ranking
                  if (properties.get(Constants.SERVICE_RANKING) == null)
                     properties.put(Constants.SERVICE_RANKING, Integer.MIN_VALUE);

            • 3. Re: Handling the service mix in AS
              alesj
              The underlying issue seems to be that OSGi service metadata are currently not associated with the ControllerContext. Can this be done at the MC level i.e. how do I associate arbitrary data with a CC without having to cache that CC?

              That's exactly what MDR does - it takes any possible metadata and properly "caches" it in the MDR repository (under right scope level keys).

              The glue between MDR and ControllerContext is the unique scope key that belongs to the ControllerContext.

              • 4. Re: Handling the service mix in AS
                alesj
                I changed MDRUtils to maintain the service properties there

                 

                http://github.com/jbosgi/jbosgi-framework/blob/3688c3e6ec91d685aa531dd3cfefb137da406fdb/core/src/main/java/org/jboss/osgi/framework/bundle/MDRUtils.java

                 

                   // Maps controller context to properties.
                   // [TODO] Can this be moved to the MC metadata layer?
                   private static Map<ControllerContext, Dictionary<String, Object>> propertiesCache = new WeakHashMap<ControllerContext, Dictionary<String, Object>>();

                   static Dictionary<String, Object> getProperties(ControllerContext context)
                   {
                      MetaData metaData = getMetaData(context, CommonLevels.INSTANCE);
                      Dictionary<String, Object> properties = metaData.getMetaData(Dictionary.class);
                      if (properties != null)
                         return properties;
                     
                      properties = propertiesCache.get(context);
                      if (properties == null)
                      {
                         properties = new Hashtable<String, Object>();
                         propertiesCache.put(context, properties);
                      }
                     
                      return properties;

                There should be no need for this custom cache, MDR should already do this.

                 

                I think the problem is what we briefly discussed in MV (USA), it's the order in which InstanceMetaDataRetrievalFactory kicks in.

                The factory should be in place before any potential OSGi service is installed.

                Failing to do so, potential OSGi services will already move past Describe state, avoiding the usage of this factory ==> no Dictionary in MDR.

                 

                The GenericServiceWrapper sets thes properties

                      // The Framework adds the following service properties to the service properties
                      // * A property named Constants.SERVICE_ID identifying the registration number of the service
                      // * A property named Constants.OBJECTCLASS containing all the specified classes.
                     
                      Dictionary<String, Object> properties = MDRUtils.getProperties(context);
                      if (properties.get(Constants.SERVICE_ID) == null)
                      {
                         Long serviceId = OSGiServiceState.getNextServiceId();
                         properties.put(Constants.SERVICE_ID, serviceId);
                      }
                      if (properties.get(Constants.OBJECTCLASS) == null)
                      {
                         String[] objectClass = MDRUtils.getClasses(context);
                         if (objectClass == null)
                         {
                            BeanMetaData bmd = context.getBeanMetaData();
                            objectClass = new String[] { bmd.getBean() };
                         }
                         properties.put(Constants.OBJECTCLASS, objectClass);
                      }
                      // By default assign the lowest possible ranking
                      if (properties.get(Constants.SERVICE_RANKING) == null)
                         properties.put(Constants.SERVICE_RANKING, Integer.MIN_VALUE)

                Make this lookups lazy, as there is a lot of usecases where we don't need this properties.

                e.g. single matching service doesn't need id and ranking to be ordered