the project has moved to https://github.com/weld/core on the master (environments/osgi) branch.
This project is only used for wiki and issues tracker about Weld-OSGi.
If you want to use and hack Weld-OSGi, please fork https://github.com/weld/core
You can find actual documentation at : http://mathieuancelin.github.com/weld-osgi/
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 …
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.
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 :)