OSGi DevCon 09 - OSGi on Scala

34
OSGi on Scala BindForge & ScalaModules: Scala DSLs to ease OSGi development Roman Roelofsen (ProSyst), Heiko Seeberger (WeigleWilczek)

description

BindForge & ScalaModules: Scala DSLs to ease OSGi development.

Transcript of OSGi DevCon 09 - OSGi on Scala

Page 1: OSGi DevCon 09 - OSGi on Scala

OSGi on ScalaBindForge & ScalaModules: Scala DSLs to ease OSGi development

Roman Roelofsen (ProSyst), Heiko Seeberger (WeigleWilczek)

Page 2: OSGi DevCon 09 - OSGi on Scala

Why?

• OSGi is a great module system

• Scala is a great language

• Compiles to Java bytecode

• Object-functional programming style

• Why wait for Java 7 (or 8)? Use Scala now!

• Let’s combine them to ease OSGi development

Page 3: OSGi DevCon 09 - OSGi on Scala

What?

• BindForge - Module Framework

• ScalaModules - DSL for OSGi development in Scala

Page 4: OSGi DevCon 09 - OSGi on Scala

BindForge

• Module Framework

• Dependency Injection, OSGi service abstraction, etc.

• Useful for Java and Scala development

• Configuration is written in Scala

• Based on

• Scala

• Guice

• Peaberry

Page 5: OSGi DevCon 09 - OSGi on Scala

OSGi Log Service Bundle

Customer Bundle

Example Scenario

CustomerRepository

CustomerRep.Impl

CustomerService

CustomerServiceImpl

LogService

Page 6: OSGi DevCon 09 - OSGi on Scala

Example Scenario

// repository interface CustomerRepository class CustomerRepositoryImpl implements CustomerRepository

// service interface CustomerService class CustomerServiceImpl implements CustomerService {

public void setCustomerRepository(CustomerRepository cr) { ... }

public void setLogService(LogService ls) { ... }

}

Page 7: OSGi DevCon 09 - OSGi on Scala

Bundle Configuration

• MANIFEST.MF

• /OSGI-INF/bindforge/config.scalapackage com.acme.app

class MyConfig extends org.bindforge.Config { ...}

BindForge-Config: com.acme.app.MyConfig

Page 8: OSGi DevCon 09 - OSGi on Scala

Customer Bundle

Binding Interfaces to Implementations

CustomerRepository

CustomerRep.Impl

CustomerService

CustomerServiceImpl

Page 9: OSGi DevCon 09 - OSGi on Scala

Binding Interfaces to Implementations

package com.acme.app

class MyConfig extends org.bindforge.Config {

bind [CustomerRepository, impl.CustomerRepositoryImpl]

bind [CustomerService, impl.CustomerServiceImpl]

}

Page 10: OSGi DevCon 09 - OSGi on Scala

Customer Bundle

Inject Bindings

CustomerRepository

CustomerRep.Impl

CustomerService

CustomerServiceImpl

Page 11: OSGi DevCon 09 - OSGi on Scala

Inject Bindings(by type)

bind [CustomerRepository, impl.CustomerRepositoryImpl]

bind [CustomerService, impl.CustomerServiceImpl] spec { property(“customerRepository”)}

Page 12: OSGi DevCon 09 - OSGi on Scala

Inject Bindings(by name)

“customerRepository” :: bind [impl.CustomerRepositoryImpl]

bind [CustomerService, impl.CustomerServiceImpl] spec { property(“customerRepository”) = ref(“customerRepository”)}

Page 13: OSGi DevCon 09 - OSGi on Scala

Customer Bundle

Export Customer Service

CustomerRepository

CustomerRep.Impl

CustomerService

CustomerServiceImpl

Page 14: OSGi DevCon 09 - OSGi on Scala

Export Customer Service

bind [CustomerRepository, impl.CustomerRepositoryImpl]

bind [CustomerService, impl.CustomerServiceImpl] spec { exportService property(“customerRepository”)}

Page 15: OSGi DevCon 09 - OSGi on Scala

Export Customer Service(with Properties)

bind [CustomerRepository, impl.CustomerRepositoryImpl]

bind [CustomerService, impl.CustomerServiceImpl] spec { exportService(“vendor” -> “acme”, “security” -> “none”) property(“customerRepository”)}

Page 16: OSGi DevCon 09 - OSGi on Scala

OSGi Log Service Bundle

Customer Bundle

Import LogService

CustomerRepository

CustomerRep.Impl

CustomerService

CustomerServiceImpl

LogService

Page 17: OSGi DevCon 09 - OSGi on Scala

Import LogService

bind [LogService] importService

bind [CustomerRepository, impl.CustomerRepositoryImpl]

bind [CustomerService, impl.CustomerServiceImpl] spec { exportService property(“customerRepository”) property(“logService”)}

Page 18: OSGi DevCon 09 - OSGi on Scala

Full Configuration

package com.acme.app

class MyConfig extends org.bindforge.Config {

bind [LogService] importService

bind [CustomerRepository, impl.CustomerRepositoryImpl]

bind [CustomerService, impl.CustomerServiceImpl] spec { exportService property(“customerRepository”) property(“logService”) }

}

Page 19: OSGi DevCon 09 - OSGi on Scala

What?

• BindForge - Module Framework

• ScalaModules - DSL for OSGi development in Scala

Page 20: OSGi DevCon 09 - OSGi on Scala

ScalaModules

• For Scala developers (and Java geeks)

• General OSGi concepts, e.g. service handling

• Compendium services, e.g. Configuration Admin

Page 21: OSGi DevCon 09 - OSGi on Scala

Register a Service

Greeting hello = new Greeting() { public String welcome() { return "Hello!"; } public String goodbye() { return "See you!"; }};context.registerService(Greeting.class.getName(), hello, null);

not type sa

fe

Page 22: OSGi DevCon 09 - OSGi on Scala

Register a Service

context registerAs classOf[Greeting] theService new Greeting { override def welcome = "Hello!" override def goodbye = "See you!";}

Page 23: OSGi DevCon 09 - OSGi on Scala

Register a Servicewith Properties

Greeting welcome = new Greeting() { public String welcome() { return "Welcome!"; } public String goodbye() { return "Good bye!"; }};Dictionary<String, Object> properties = new Hashtable<String, Object>();properties.put("name", "welcome");context.registerService(Greeting.class.getName(), welcome, properties);

verbose

Page 24: OSGi DevCon 09 - OSGi on Scala

Register a Servicewith Properties

context registerAs classOf[Greeting] withProperties Map("name" -> "welcome") theService new Greeting { override def welcome = "Welcome!" override def goodbye = "Goodbye!" }

Page 25: OSGi DevCon 09 - OSGi on Scala

Consume a single Service

ServiceReference reference = context.getServiceReference(Greeting.class.getName());if (reference != null) { try { Object service = context.getService(reference); Greeting greeting = (Greeting) service; if (greeting != null) { System.out.println(greeting.welcome()); } else { noGreetingService(); } } finally { context.ungetService(reference); }} else { noGreetingService();}

involved

Page 26: OSGi DevCon 09 - OSGi on Scala

Consume a single Service

context getOne classOf[Greeting] andApply { _.welcome} match { case None => noGreetingService() case Some(welcome) => println(welcome)}

Page 27: OSGi DevCon 09 - OSGi on Scala

Consume many Services with their Properties

try { ServiceReference[] refs = context.getServiceReferences( Greeting.class.getName(), null); if (refs != null) { for (ServiceReference ref : refs) { Object service = context.getService(ref); Greeting greeting = (Greeting) service; if (greeting != null) { Object name = (ref.getProperty("name") != null) ? ref.getProperty("name") : "UNKNOWN"; String message = name + " says: " + greeting.welcome(); System.out.println(message); } } } else { noGreetingService(); }} catch (InvalidSyntaxException e) { // Do something meaningful ...}

very involved

Page 28: OSGi DevCon 09 - OSGi on Scala

Consume many Services with their Properties

context getMany classOf[Greeting] andApply { (greeting, properties) => { val name = properties.get("name") match { case None => "UNKNOWN" case Some(s) => s } name + " sais: " + greeting.welcome }} match { case None => noGreetingService() case Some(welcomes) => welcomes.foreach { println }}

Page 29: OSGi DevCon 09 - OSGi on Scala

Consume Servicesusing a Filter

try { ServiceReference[] refs = context.getServiceReferences( Greeting.class.getName(), "(name=*)"); if (refs != null) { for (ServiceReference ref : refs) { Object service = context.getService(ref); Greeting greeting = (Greeting) service; if (greeting != null) { System.out.println(greeting.welcome()); } } } else { noGreetingService(); }} catch (InvalidSyntaxException e) { // Do something meaningful ...}

very involved again

Page 30: OSGi DevCon 09 - OSGi on Scala

Consume Servicesusing a Filter

context getMany classOf[Greeting] withFilter "(name=*)" andApply { _.welcome} match { case None => noGreetingService() case Some(welcomes) => welcomes.foreach { println }}

Page 31: OSGi DevCon 09 - OSGi on Scala

Track ServicesServiceTracker tracker = new ServiceTracker(context, Greeting.class.getName(), null) { @Override public Object addingService(ServiceReference reference) { Object service = super.addingService(reference); Greeting greeting = (Greeting)service; System.out.println("Adding Greeting: " + greeting.welcome()); return service; } @Override public void removedService(ServiceReference reference, Object service) { Greeting greeting = (Greeting)service; System.out.println("Removed Greeting: " + greeting.welcome()); super.removedService(reference, service); }};tracker.open();

and again

Page 32: OSGi DevCon 09 - OSGi on Scala

Track Services

greetingTrack = context track classOf[Greeting] on { case Adding(greeting, _) => println("Adding Greeting: " + greeting.welcome) case Modified(greeting, _) => case Removed(greeting, _) => println("Removed Greeting: " + greeting.goodbye)}

Page 33: OSGi DevCon 09 - OSGi on Scala

Service Dependencies

context registerAs classOf[Command] dependOn classOf[Greeting] theService { greeting => new Command { ... }}

Page 34: OSGi DevCon 09 - OSGi on Scala

And now?

• Forge ahead at www.bindforge.org

• And get fluent at www.scalamodules.org

• Please give feedback:

• What do you like?

• What do you not like?

• What feature would you like to see implemented?