ScalaModules
   Scala and OSGi
OSGi Services


• The key to modularity
• Arguably, the key to OOP itself?
Dr Alan Kay
Dr Alan Kay

“Dude I
invented
friggin’ OOP.
Have you
heard of it?”
Dr Alan Kay

“OOP to me means only
messaging, local
retention and protection
and hiding of state-
process, and extreme
late-binding of all things.”
Late Binding with
         Services

• Services answer the question:where do I
  get an implementation of this interface?
• The registry decentralises the architecture.
Consuming Services
Harder than Expected!
Why...?
Slippery
Dynamics

• A service can come and go
• At any time
• On any thread
• Yes... even while you’re using it
Result


• Service usage code can be
 very complex
Service Consumption
        in Java
Consuming a Service

public void consumeService(BundleContext context) {
   ServiceReference ref = context.getServiceReference(Greeting.class.getName());
   Greeting greeting = (Greeting) context.getService(ref);
   System.out.println(greeting.getMessage());
}
Consuming a Service

public void consumeService(BundleContext context) {
   ServiceReference ref = context.getServiceReference(Greeting.class.getName());
   Greeting greeting = (Greeting) context.getService(ref);
   System.out.println(greeting.getMessage());
}




             WRONG
Consuming a Service

public void consumeService(BundleContext context) {
   ServiceReference ref = context.getServiceReference(Greeting.class.getName());
   if(ref != null) {
      Greeting greeting = (Greeting) context.getService(ref);
      System.out.println(greeting.getMessage());
   }
}
Consuming a Service

public void consumeService(BundleContext context) {
   ServiceReference ref = context.getServiceReference(Greeting.class.getName());
   if(ref != null) {
      Greeting greeting = (Greeting) context.getService(ref);
      System.out.println(greeting.getMessage());
   }
}




             WRONG
Consuming a Service

    public void consumeService(BundleContext context) {
       ServiceReference ref = context.getServiceReference(Greeting.class.getName());
       if(ref != null) {
          Greeting greeting = (Greeting) context.getService(ref);
          if(greeting != null) {
         	 System.out.println(greeting.getMessage());
          }
       }
    }
Consuming a Service

    public void consumeService(BundleContext context) {
       ServiceReference ref = context.getServiceReference(Greeting.class.getName());
       if(ref != null) {
          Greeting greeting = (Greeting) context.getService(ref);
          if(greeting != null) {
         	 System.out.println(greeting.getMessage());
          }
       }
    }
	




                 WRONG
Consuming a Service
public void consumeService(BundleContext context) {
   ServiceReference ref = context.getServiceReference(Greeting.class.getName());
   if(ref != null) {
      Greeting greeting = (Greeting) context.getService(ref);
      if(greeting != null) {
     	 System.out.println(greeting.getMessage());
      }
      context.ungetService(ref);
   }
}
Consuming a Service
public void consumeService(BundleContext context) {
   ServiceReference ref = context.getServiceReference(Greeting.class.getName());
   if(ref != null) {
      Greeting greeting = (Greeting) context.getService(ref);
      if(greeting != null) {
     	 System.out.println(greeting.getMessage());
      }
      context.ungetService(ref);
   }
}




             WRONG
Consuming a Service
public void consumeService(BundleContext context) {
   ServiceReference ref = context.getServiceReference(Greeting.class.getName());
   if(ref != null) {
      try {
         Greeting greeting = (Greeting) context.getService(ref);
         if(greeting != null) {
     	     System.out.println(greeting.getMessage());
         }
      } finally {
     	 context.ungetService(ref);
      }
   }
}
Consuming a Service
public void consumeService(BundleContext context) {
   ServiceReference ref = context.getServiceReference(Greeting.class.getName());
   if(ref != null) {
      try {
         Greeting greeting = (Greeting) context.getService(ref);
         if(greeting != null) {
     	     System.out.println(greeting.getMessage());
         }
      } finally {
     	 context.ungetService(ref);
      }
   }
}




NOT TYPE SAFE
Consuming a Service
public void consumeService(BundleContext context) {
   ServiceReference ref = context.getServiceReference(Greeting.class.getName());
   if(ref != null) {
      try {
         Greeting greeting = (Greeting) context.getService(ref);
         if(greeting != null) {
     	     System.out.println(greeting.getMessage());
         }
      } finally {
     	 context.ungetService(ref);
      }
   }
}




NOT TYPE SAFE
An Answer:
Stop Writing Code!
Declarative Services
              (DS)
@Reference
public void setGreeting(Greeting greeting) {
   this.greeting = greeting;
}

public void consumeService() {
   System.out.println(greeting.getMessage());
}
Blueprint
   public void setGreeting(Greeting greeting) {
      this.greeting = greeting;
   }

   public void consumeService() {
      System.out.println(greeting.getMessage());
   }


<blueprint>

   <reference id="greeting" interface="org.example.Greeting"/>

   <bean id="foo" class="com.foo.Foo"/>
      <property name="greeting" ref="greeting"/>
   </bean>

</blueprint>
Problem

• These frameworks provide abstractions
• Abstraction hide detail
• Sometimes we need the detail
Example: Cardinality?
                  Service



                  Service

      Component

                  Service



                  Service
Single
            Service



            Service

Component

            Service



            Service
Multiple
            Service



            Service

Component

            Service



            Service
???
  Component         Service



  Component         Service



  Component         Service



  Component         Service




Not supported by DS
Declarative
I    Services
       (and Blueprint)
Declarative
I    Services
       (and Blueprint)
The “80%” Solution
              “Normal” Users
The “80%” Solution
              “Normal” Users
              DS support
The “80%” Solution
              “Normal” Users
              DS support
The “80%” Solution
              “Normal” Users
              DS support
              “Power” Users
The “80%” Solution
              “Normal” Users
              DS support
              “Power” Users
The “80%” Solution
              “Normal” Users
              DS support
              “Power” Users
              Easy in Java
The “80%” Solution
              “Normal” Users
              DS support
              “Power” Users
              Easy in Java
The “80%” Solution
              “Normal” Users
              DS support
              “Power” Users
              Easy in Java
              Easy in Scala
The “80%” Solution
              “Normal” Users
              DS support
              “Power” Users
              Easy in Java
              Easy in Scala
Java
ServiceTracker tracker = new ServiceTracker(context, Greeting.class.getName(),
                                            new ServiceTrackerCustomizer() {

      public Object addingService(ServiceReference reference) {
         Greeting greeting = (Greeting) context.getService(reference);	
         ServiceRegistration reg = context.registerService(IFoo.class.getName(),
                                                           new Foo(greeting), null);
         return reg;
      }

      public void modifiedService(ServiceReference reference, Object service) {
      }

      public void removedService(ServiceReference reference, Object service) {
         ServiceRegistration reg = (ServiceRegistration) service;
         reg.unregister();
      }
});
Java
ServiceTracker tracker = new ServiceTracker(context, Greeting.class.getName(),
                                            new ServiceTrackerCustomizer() {

      public Object addingService(ServiceReference reference) {
         Greeting greeting = (Greeting) context.getService(reference);	
         ServiceRegistration reg = context.registerService(IFoo.class.getName(),
                                                           new Foo(greeting), null);
         return reg;
      }

      public void modifiedService(ServiceReference reference, Object service) {
      }

      public void removedService(ServiceReference reference, Object service) {
         ServiceRegistration reg = (ServiceRegistration) service;
         reg.unregister();
      }
});



                                                               Type Safety???
What is ScalaModules?
NOT Another Module
  System (phew!)
“A Scala internal DSL to ease
    OSGi development”
• Now:
 • Services
• Future:
 • Extender Pattern?
 • Resources?
An Eclipse Project!
Examples
Java
ServiceTracker tracker = new ServiceTracker(context, Greeting.class.getName(),
                                            new ServiceTrackerCustomizer() {

      public Object addingService(ServiceReference reference) {
         Greeting greeting = (Greeting) context.getService(reference);	
         ServiceRegistration reg = context.registerService(IFoo.class.getName(),
                                                           new Foo(greeting), null);
         return reg;
      }

      public void modifiedService(ServiceReference reference, Object service) {
      }

      public void removedService(ServiceReference reference, Object service) {
         ServiceRegistration reg = (ServiceRegistration) service;
         reg.unregister();
      }
});
ScalaModules


val greetingTrack = context track classOf[Greeting] on {
   case Adding(greeting) => context createService (classOf[IFoo],
                                                   new Foo(greeting))
   case Removed(_, reg) => reg unregister
}
Plan
• Started moving the code & docs to Eclipse
• 19 March: M1
• 7 May: M2
• 28 May: RC1
• 11 June: RC2
• 23 June: ScalaModules 2.0 Release &
  Graduation
Get Involved

http://www.eclipse.org/forums/
      eclipse.scalamodules

Scala modules

  • 1.
    ScalaModules Scala and OSGi
  • 2.
    OSGi Services • Thekey to modularity • Arguably, the key to OOP itself?
  • 3.
  • 4.
    Dr Alan Kay “DudeI invented friggin’ OOP. Have you heard of it?”
  • 5.
    Dr Alan Kay “OOPto me means only messaging, local retention and protection and hiding of state- process, and extreme late-binding of all things.”
  • 6.
    Late Binding with Services • Services answer the question:where do I get an implementation of this interface? • The registry decentralises the architecture.
  • 7.
  • 8.
  • 9.
  • 11.
  • 12.
    Dynamics • A servicecan come and go • At any time • On any thread • Yes... even while you’re using it
  • 13.
    Result • Service usagecode can be very complex
  • 14.
  • 15.
    Consuming a Service publicvoid consumeService(BundleContext context) { ServiceReference ref = context.getServiceReference(Greeting.class.getName()); Greeting greeting = (Greeting) context.getService(ref); System.out.println(greeting.getMessage()); }
  • 16.
    Consuming a Service publicvoid consumeService(BundleContext context) { ServiceReference ref = context.getServiceReference(Greeting.class.getName()); Greeting greeting = (Greeting) context.getService(ref); System.out.println(greeting.getMessage()); } WRONG
  • 17.
    Consuming a Service publicvoid consumeService(BundleContext context) { ServiceReference ref = context.getServiceReference(Greeting.class.getName()); if(ref != null) { Greeting greeting = (Greeting) context.getService(ref); System.out.println(greeting.getMessage()); } }
  • 18.
    Consuming a Service publicvoid consumeService(BundleContext context) { ServiceReference ref = context.getServiceReference(Greeting.class.getName()); if(ref != null) { Greeting greeting = (Greeting) context.getService(ref); System.out.println(greeting.getMessage()); } } WRONG
  • 19.
    Consuming a Service public void consumeService(BundleContext context) { ServiceReference ref = context.getServiceReference(Greeting.class.getName()); if(ref != null) { Greeting greeting = (Greeting) context.getService(ref); if(greeting != null) { System.out.println(greeting.getMessage()); } } }
  • 20.
    Consuming a Service public void consumeService(BundleContext context) { ServiceReference ref = context.getServiceReference(Greeting.class.getName()); if(ref != null) { Greeting greeting = (Greeting) context.getService(ref); if(greeting != null) { System.out.println(greeting.getMessage()); } } } WRONG
  • 21.
    Consuming a Service publicvoid consumeService(BundleContext context) { ServiceReference ref = context.getServiceReference(Greeting.class.getName()); if(ref != null) { Greeting greeting = (Greeting) context.getService(ref); if(greeting != null) { System.out.println(greeting.getMessage()); } context.ungetService(ref); } }
  • 22.
    Consuming a Service publicvoid consumeService(BundleContext context) { ServiceReference ref = context.getServiceReference(Greeting.class.getName()); if(ref != null) { Greeting greeting = (Greeting) context.getService(ref); if(greeting != null) { System.out.println(greeting.getMessage()); } context.ungetService(ref); } } WRONG
  • 23.
    Consuming a Service publicvoid consumeService(BundleContext context) { ServiceReference ref = context.getServiceReference(Greeting.class.getName()); if(ref != null) { try { Greeting greeting = (Greeting) context.getService(ref); if(greeting != null) { System.out.println(greeting.getMessage()); } } finally { context.ungetService(ref); } } }
  • 24.
    Consuming a Service publicvoid consumeService(BundleContext context) { ServiceReference ref = context.getServiceReference(Greeting.class.getName()); if(ref != null) { try { Greeting greeting = (Greeting) context.getService(ref); if(greeting != null) { System.out.println(greeting.getMessage()); } } finally { context.ungetService(ref); } } } NOT TYPE SAFE
  • 25.
    Consuming a Service publicvoid consumeService(BundleContext context) { ServiceReference ref = context.getServiceReference(Greeting.class.getName()); if(ref != null) { try { Greeting greeting = (Greeting) context.getService(ref); if(greeting != null) { System.out.println(greeting.getMessage()); } } finally { context.ungetService(ref); } } } NOT TYPE SAFE
  • 26.
  • 27.
    Declarative Services (DS) @Reference public void setGreeting(Greeting greeting) { this.greeting = greeting; } public void consumeService() { System.out.println(greeting.getMessage()); }
  • 28.
    Blueprint public void setGreeting(Greeting greeting) { this.greeting = greeting; } public void consumeService() { System.out.println(greeting.getMessage()); } <blueprint> <reference id="greeting" interface="org.example.Greeting"/> <bean id="foo" class="com.foo.Foo"/> <property name="greeting" ref="greeting"/> </bean> </blueprint>
  • 29.
    Problem • These frameworksprovide abstractions • Abstraction hide detail • Sometimes we need the detail
  • 30.
    Example: Cardinality? Service Service Component Service Service
  • 31.
    Single Service Service Component Service Service
  • 32.
    Multiple Service Service Component Service Service
  • 33.
    ??? Component Service Component Service Component Service Component Service Not supported by DS
  • 34.
    Declarative I Services (and Blueprint)
  • 35.
    Declarative I Services (and Blueprint)
  • 36.
    The “80%” Solution “Normal” Users
  • 37.
    The “80%” Solution “Normal” Users DS support
  • 38.
    The “80%” Solution “Normal” Users DS support
  • 39.
    The “80%” Solution “Normal” Users DS support “Power” Users
  • 40.
    The “80%” Solution “Normal” Users DS support “Power” Users
  • 41.
    The “80%” Solution “Normal” Users DS support “Power” Users Easy in Java
  • 42.
    The “80%” Solution “Normal” Users DS support “Power” Users Easy in Java
  • 43.
    The “80%” Solution “Normal” Users DS support “Power” Users Easy in Java Easy in Scala
  • 44.
    The “80%” Solution “Normal” Users DS support “Power” Users Easy in Java Easy in Scala
  • 45.
    Java ServiceTracker tracker =new ServiceTracker(context, Greeting.class.getName(), new ServiceTrackerCustomizer() { public Object addingService(ServiceReference reference) { Greeting greeting = (Greeting) context.getService(reference); ServiceRegistration reg = context.registerService(IFoo.class.getName(), new Foo(greeting), null); return reg; } public void modifiedService(ServiceReference reference, Object service) { } public void removedService(ServiceReference reference, Object service) { ServiceRegistration reg = (ServiceRegistration) service; reg.unregister(); } });
  • 46.
    Java ServiceTracker tracker =new ServiceTracker(context, Greeting.class.getName(), new ServiceTrackerCustomizer() { public Object addingService(ServiceReference reference) { Greeting greeting = (Greeting) context.getService(reference); ServiceRegistration reg = context.registerService(IFoo.class.getName(), new Foo(greeting), null); return reg; } public void modifiedService(ServiceReference reference, Object service) { } public void removedService(ServiceReference reference, Object service) { ServiceRegistration reg = (ServiceRegistration) service; reg.unregister(); } }); Type Safety???
  • 47.
  • 48.
    NOT Another Module System (phew!)
  • 51.
    “A Scala internalDSL to ease OSGi development”
  • 52.
    • Now: •Services • Future: • Extender Pattern? • Resources?
  • 53.
  • 54.
  • 55.
    Java ServiceTracker tracker =new ServiceTracker(context, Greeting.class.getName(), new ServiceTrackerCustomizer() { public Object addingService(ServiceReference reference) { Greeting greeting = (Greeting) context.getService(reference); ServiceRegistration reg = context.registerService(IFoo.class.getName(), new Foo(greeting), null); return reg; } public void modifiedService(ServiceReference reference, Object service) { } public void removedService(ServiceReference reference, Object service) { ServiceRegistration reg = (ServiceRegistration) service; reg.unregister(); } });
  • 56.
    ScalaModules val greetingTrack =context track classOf[Greeting] on { case Adding(greeting) => context createService (classOf[IFoo], new Foo(greeting)) case Removed(_, reg) => reg unregister }
  • 57.
    Plan • Started movingthe code & docs to Eclipse • 19 March: M1 • 7 May: M2 • 28 May: RC1 • 11 June: RC2 • 23 June: ScalaModules 2.0 Release & Graduation
  • 58.