Date post: | 30-Jun-2015 |
Category: |
Technology |
Upload: | heiko-seeberger |
View: | 1,534 times |
Download: | 1 times |
OSGi on ScalaBindForge & ScalaModules: Scala DSLs to ease OSGi development
Roman Roelofsen (ProSyst), Heiko Seeberger (WeigleWilczek)
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
What?
• BindForge - Module Framework
• ScalaModules - DSL for OSGi development in 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
OSGi Log Service Bundle
Customer Bundle
Example Scenario
CustomerRepository
CustomerRep.Impl
CustomerService
CustomerServiceImpl
LogService
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) { ... }
}
Bundle Configuration
• MANIFEST.MF
• /OSGI-INF/bindforge/config.scalapackage com.acme.app
class MyConfig extends org.bindforge.Config { ...}
BindForge-Config: com.acme.app.MyConfig
Customer Bundle
Binding Interfaces to Implementations
CustomerRepository
CustomerRep.Impl
CustomerService
CustomerServiceImpl
Binding Interfaces to Implementations
package com.acme.app
class MyConfig extends org.bindforge.Config {
bind [CustomerRepository, impl.CustomerRepositoryImpl]
bind [CustomerService, impl.CustomerServiceImpl]
}
Customer Bundle
Inject Bindings
CustomerRepository
CustomerRep.Impl
CustomerService
CustomerServiceImpl
Inject Bindings(by type)
bind [CustomerRepository, impl.CustomerRepositoryImpl]
bind [CustomerService, impl.CustomerServiceImpl] spec { property(“customerRepository”)}
Inject Bindings(by name)
“customerRepository” :: bind [impl.CustomerRepositoryImpl]
bind [CustomerService, impl.CustomerServiceImpl] spec { property(“customerRepository”) = ref(“customerRepository”)}
Customer Bundle
Export Customer Service
CustomerRepository
CustomerRep.Impl
CustomerService
CustomerServiceImpl
Export Customer Service
bind [CustomerRepository, impl.CustomerRepositoryImpl]
bind [CustomerService, impl.CustomerServiceImpl] spec { exportService property(“customerRepository”)}
Export Customer Service(with Properties)
bind [CustomerRepository, impl.CustomerRepositoryImpl]
bind [CustomerService, impl.CustomerServiceImpl] spec { exportService(“vendor” -> “acme”, “security” -> “none”) property(“customerRepository”)}
OSGi Log Service Bundle
Customer Bundle
Import LogService
CustomerRepository
CustomerRep.Impl
CustomerService
CustomerServiceImpl
LogService
Import LogService
bind [LogService] importService
bind [CustomerRepository, impl.CustomerRepositoryImpl]
bind [CustomerService, impl.CustomerServiceImpl] spec { exportService property(“customerRepository”) property(“logService”)}
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”) }
}
What?
• BindForge - Module Framework
• ScalaModules - DSL for OSGi development in Scala
ScalaModules
• For Scala developers (and Java geeks)
• General OSGi concepts, e.g. service handling
• Compendium services, e.g. Configuration Admin
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
Register a Service
context registerAs classOf[Greeting] theService new Greeting { override def welcome = "Hello!" override def goodbye = "See you!";}
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
Register a Servicewith Properties
context registerAs classOf[Greeting] withProperties Map("name" -> "welcome") theService new Greeting { override def welcome = "Welcome!" override def goodbye = "Goodbye!" }
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
Consume a single Service
context getOne classOf[Greeting] andApply { _.welcome} match { case None => noGreetingService() case Some(welcome) => println(welcome)}
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
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 }}
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
Consume Servicesusing a Filter
context getMany classOf[Greeting] withFilter "(name=*)" andApply { _.welcome} match { case None => noGreetingService() case Some(welcomes) => welcomes.foreach { println }}
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
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)}
Service Dependencies
context registerAs classOf[Command] dependOn classOf[Greeting] theService { greeting => new Command { ... }}
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?