bosschaert / weld-osgi

This project aims to provide an OSGi integration for Weld

Home Page:http://mathieuancelin.github.com/weld-osgi/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

You can find actual documentation at : http://mathieuancelin.github.com/weld-osgi/

Weld OSGi integration

This project aims to provide an OSGi integration for Weld.
This project will take full advantage of OSGi like frameworks such as iPojo, Blueprint, SCR, Peaberry, etc …

How does it works

How to use it

First of all, you will need to install and start the Weld/OSGi bundle in your OSGi environment.
Then you can write a standard OSGi bundle with a valid manifest (You don’t need to write an activator or anything else). To enable Weld for this
bundle, you need to create a beans.xml file in the META-INF folder.

  • to make an auto startable bean, just catch the BundleContainerInitialized event :
    
    public void onStartup(@Observes BundleContainerInitialized event) {}
    
  • to do stuff on bundle shutdown, just catch the BundleContainerShutdown event :
    
    public void onShutdown(@Observes BundleContainerShutdown event) {}
    
  • to publish a bean as an OSGi service, add the @Publish annotation on it.
    
    @Publish
    @ApplicationScoped
    public class MyServiceImpl implements MyService {
    	@Overrides
    	public void doSomething() { ... }
    }
    
  • to inject an OSGi service, use the @OSGiService qualifier. You can also use the OSGi service provider :
    
    // direct injection	
    @Inject @OSGiService MyService service;
    ...
    service.doSomething();
    ...	
    // provider injection
    @Inject Service<MyService> myService;
    ...
    myService.get().doSomething();
    

    you can also filter service with :
    
    @Inject @OSGiService @Filter("(&(lang=EN)(country=US))") MyService service;
    ...
    @Inject @Filter("(&(lang=EN)(country=US))") Service<MyService> service;
    ...	
    
  • to inject multiple OSGi services (whiteboard pattern), also use the OSGi service provider :
    
    @Inject Service<MyService> myServices;
    ...	
    // print number of available services
    logger.log(myServices.size());
    ...
    for (MyService myService : myServices) {
    	myService.doSomething();
    }
    

    you can also filter services with :
    
    @Inject @Filter("(&(lang=EN)(country=US))") Service<MyService> myServices;
    ...	
    
  • if you absolutely need certain OSGi services to run your application, you can mark them as Required. Then when the required services will be registered in OSGi service registry, the Valid event will be raised so you can catch it and launch your app. When the required services will be unregistered from OSGi service registry, the Invalid event will be raised.
    
    @Inject @OSGiService @Required MyService service;
    ...
    @Inject @Required Service<MyService> myService;
    ...
    public void validate(@Observes Valid event) {
    	// start application here
    }
    ...
    public void invalidate(@Observes Invalid event) {
    	// stop application here
    }
    
  • to deal with the dynamism of OSGi bundles, you can catch bundle events (extender pattern) :
    
    public void bindBundle(@Observes BundleInstalled event) {}
    public void unbindBundle(@Observes BundleUninstalled event) {}
    ...
    

    you can also filter event for specific bundles :
    	
    public void bindService(@Observes @BundleName("com.sample.gui") BundleInstalled event) {}
    public void bindService(@Observes @BundleVersion("4.2.1") BundleInstalled event) {}
    public void bindService(@Observes @BundleName("com.sample.gui") @BundleVersion("4.2.1") BundleInstalled event) {}
    
  • to deal with the dynamism of OSGi services, you can catch services events (whiteboard pattern) :
    
    public void bindService(@Observes ServiceArrival event) {}
    public void unbindService(@Observes ServiceDeparture event) {}
    public void changeService(@Observes ServiceChange event) {}
    ...
    

    you can also filter event for specific services types :
    	
    public void bindService(@Observes @Specification(MyService.class) ServiceArrival event) {}
    

    or filter with native OSGi filters;
    	
    public void bindService(@Observes @Specification(MyService.class) @Filter("(&(lang=EN)(country=US))") ServiceArrival event) {}
    
  • to manipulate the OSGi service registry and register/unregister dynamically services inside your application you can use the ServiceRegistry bean :
    	
    @Inject Instance<Object> instance;
    @Inject ServiceRegistry registry;
    ...
    // get a bean instance
    MyService mySuperServiceInstance = instance.select(MySuperServiceImpl.class).get();
    ...
    // register dynamically a new service
    Registration<MyService> registeredService = registry.registerService(MyService.class, mySuperServiceInstance);
    ...
    // get an existing service
    Service<MyService> service = registry.getServiceReference(MyService.class);
    service.get().doSomething();
    ...
    logger.log(services.size());
    ...
    for (MyService service : services) {
    	service.doSomething();
    }
    ...
    // unregister dynamically previously registered service
    registeredService.unregister();
    
  • to deal with existing services registrations (managed by the Weld container, not directly by OSGi), you can use :
    	
    @Inject Registration<MyService> registeredServices;
    ...
    logger.log(registeredServices.size());
    ...		
    for (Registration registredService : registeredServices) {
    	registredService.unregister();
    }
    
  • you can also propagate events between bundle with the InterBundleEvent :
    	
    @Inject Event<InterBundleEvent> event;
    ...
    event.fire(new InterBundleEvent("Hello bundles));
    

    In another bundle :
    	
    // listen to all InterBundleEvent even from your own bundle
    public void listenAllEvents(@Observes InterBundleEvent event) {}
    ...
    // listen to all InterBundleEvent from other bundles
    public void listenAllEventsFromOtherBundles(@Observes @Sent InterBundleEvent event) {}
    ...
    // listen to all InterBundleEvent containing String object from other bundles
    public void listenStringEventsFromOtherBundles(
    				@Observes @Sent @Specification(String.class) InterBundleEvent event) {}
    
  • to deal with current bundle, you can use :
    	
    @Inject Bundle bundle;
    @Inject BundleContext context;
    
  • to get the Bundle metadata just write :
    	
    @Inject  @BundleHeaders Map<String, String> metadata;
    

    You can also inject only one specific metadata with :
    	
    @Inject @BundleHeader("Bundle-SymbolicName") String symbolicName;
    
  • to deal with bundles dataFiles you can use :
    	
    @Inject @BundleDataFile("test.txt") File file;
    
  • if you want to boostrap a weld container manually inside an OSGi bundle, you need to do something like :
    
    public class MyApp implements BundleActivator {
        private WeldEmbedded weld;
        @Override
        public void start(BundleContext bc) throws Exception {
            weld = WeldEmbedded.startFor(bc);
            ...
            MyService service = weld.instance().select(MyService.class).get();
        }
        @Override
        public void stop(BundleContext bc) throws Exception {
            weld.shutdown();
        }
    }
    

    Just be careful here, to make this exemple work, the Weld/OSGi bundle must not be started. You also won’t be able to use certain features such as inter bundle events.

Play with samples

This project provide a small sample project that shows how to use Weld integration with OSGi.
The sample is actually a small shapes drawing software in which you can add new shapes.

To use the sample, first build the entire Weld OSGi project with :

mvn clean install

then launch the sample with :

./run-sample-container.sh

this script will launch an Apache Felix container with the right bundles within. A swing window should be displayed :

You can play with it by clicking on the red shape and drawing circles in the white area.

Now if you want more shape, you need to find out the id of the shape bundle. In your Felix terminal type the “ps” command.
You should get something like that :


> ps

...
[   4] [Installed  ] [    1] Weld OSGi :: Samples :: Paint :: Triangle (1.0.0.SNAPSHOT)
[   5] [Installed  ] [    1] Weld OSGi :: Samples :: Paint :: Square (1.0.0.SNAPSHOT)
...

Now you can start the “triangle bundle” by typing in the Felix terminal :

start 4

and the “square bundle” :

start 5

you can also stop bundles. When a bundle is stopped, existing shapes of this bundle are deleted :

stop 4

Other samples are available in the sample container (calculator, webapp), don’t hesitate to try them :)

About

This project aims to provide an OSGi integration for Weld

http://mathieuancelin.github.com/weld-osgi/