The groovyx.osgi module provides two packages to make working with OSGi easier. Additionally they are used by the Grails OSGi plugin from version 0.3 on.
This package contains helper classes to make OSGi programming easier. This package is inspired by ScalaModules.
Features:
- simplifies working with OSGi service registry
- safe access to OSGi services, without fear for OSGi dynamics
- Service finder DSL
- OSGi service filter DSL
Example:
import grooxy.osgi.OsgiCategory
List results
use(OsgiCategory) {
results = bundleContext.findServices(MyService).withEachService() { srv ->
srv.doSomething()
}
}
results.each { result -> println result }
See groovyx-osgi for details.
This package provides an OSGi builder class, grooxy.osgi.runtime.OsgiRuntimeBuilder, which can be used to assemble and run an OSGi runtime:
Features:
- provision bundles from filesystem, web, Maven repositories
- run Eclipse Equinox or Apache Felix OSGi runtimes
- flexible Groovy DSL, fully programmable
- lifecycle callback closures
Example:
import grooxy.osgi.runtime.OsgiRuntimeBuilder
OsgiRuntimeBuilder.run {
framework 'equinox'
bundle 'mvn:org.apache.felix:org.apache.felix.configadmin:1.2.4'
bundle 'mvn:org.apache.felix:org.apache.felix.fileinstall:3.0.2'
console(8023)
doRun = {
// wait one minute
println "stopping OSGi runtime after one minute"
Thread.sleep 60000
}
afterStop = {
println "stopped OSGi runtime"
}
}
See groovyx-osgi-runtime for details.
The Groovy OSGi module is released under the Apache License 2.0.
Simply run gradle build
. If Gradle >= 0.9-rc-2 is not installed, run ./gradlew build
from the top-level directory, in order to automatically download the correct Gradle version. The resulting jars can be found at the following locations:
groovyx-osgi/build/libs/groovyx-osgi-0.1.jar
groovyx-osgi-runtime/build/libs/groovyx-osgi-runtime-0.1.jar
Note: when performing test for groovyx.osgi, please re-create the bundle using gradle assemble
after changing any code before running the tests, as the tests simply load the jar into the OSGi framework. Changed code is NOT picked up automatically!
- Eclipse Equinox 3.6.1 and Apache Felix 3.0.2 OSGi frameworks
- Groovy (tested with 1.7.5)
- Apache Ivy (part of Groovy all-in-one package)
- Apache Commons Logging API
The filter support is derived from the filter4osgi project and was contributed by Hamlet D’Arcy. The code is also under the Apache License 2.0.
The dependency resolution code is derived from Grails and was written by Graeme Rocher. The code is also under the Apache License 2.0.
Simply drop groovyx-osgi-version.jar and/or groovyx-osgi-runtime-version.jar into your classpath. When using Grape, installation can be omitted altogether. See example below.
import grooxy.osgi.runtime.OsgiRuntimeBuilder
def osgi = new OsgiRuntimeBuilder()
osgi.configure {
// test alias
framework 'equinox'
runtimeDir 'system'
args {
resolverLogLevel = "warn"
}
bundle 'mvn:org.apache.felix:org.apache.felix.fileinstall:3.0.2'
bundle group: 'org.apache.felix', name:'org.apache.felix.configadmin', version:'1.2.4'
}
def runtime = osgi.build()
def bundleContext = runtime.start()
// do something
// shutdown OSGi runtime
runtime.stop()
This standalone script can be run as groovy myosgi.groovy
.
Note: groovyx.osgi.runtime is not yet available in a maven repository, so it must be included
in the classpath: groovy -cp path/to/groovyx.osgi.runtime-version.jar myosgi.groovy
.
// these are necessary for current version (3.6.1) of Equinox
@GrabResolver(name='ebrRelease', root='http://repository.springsource.com/maven/bundles/release')
@GrabResolver(name='ebrExternal', root='http://repository.springsource.com/maven/bundles/external')
@GrabResolver(name='githubJetztgradNet', root='https://github.com/jetztgradnet/repository/raw/master')
@Grapes([
@GrabConfig(systemClassLoader=true),
@Grab(group='groovyx.osgi', module='groovyx.osgi.runtime', version='0.1'),
@Grab(group='org.eclipse.osgi', module='org.eclipse.osgi', version='3.6.1.R36x_v20100806'),
@Grab(group='org.apache.commons', module='com.springsource.org.apache.commons.logging', version='1.1.1')
])
import groovyx.osgi.runtime.OsgiRuntimeBuilder
OsgiRuntimeBuilder.run {
framework 'equinox'
bundle 'mvn:org.apache.felix:org.apache.felix.configadmin:1.2.4'
bundle 'mvn:org.apache.felix:org.apache.felix.fileinstall:3.0.2'
beforeStart = {
println "starting OSGi runtime"
}
afterInstallBundles = { runtime ->
def bundleContext = runtime.bundleContext
if (bundleContext) {
println "installed bundles:"
bundleContext?.bundles?.each { bundle ->
println "[${bundle.bundleId}] ${bundle.symbolicName} ${bundle.version}"
}
}
else {
println "failed to list bundles"
}
}
doRun = {
// wait one minute
println "stopping OSGi runtime after one minute"
Thread.sleep 60000
}
afterStop = {
println "stopped OSGi runtime"
}
}
See groovyx-osgi-runtime/examples
for some more examples. They can be executed with the following command:
groovy -cp groovyx-osgi-runtime-version.jar groovyx.osgi.runtime.OsgiRuntimeBuilder path/to/script.groovy
All examples can be run in a fashion similar to the simple example above. For brevity,
only the configuration closure is included in the following snippets.
osgi.configure {
framework 'equinox'
}
osgi.configure {
framework 'felix'
}
osgi.configure {
framework MyRuntimeFactory.class
}
MyRuntimeFactory
should implement groovyx.osgi.runtime.OsgiRuntimeFactory
and create
instances of groovyx.osgi.runtime.OsgiRuntime
, which are usually derived from abstract
base class org.codehaus.groovy.osgi.runtime.AbstractOsgiRuntime
.
Provision an extisting OSGi runtime, like Eclipse Virgo, Apache Karaf, or SpringSource dmServer:
Configuration of an external OSGi runtime is performed by provisioning bundles into a drop-in
directory, which is monitored by the runtime. Bundles, which are dropped into the directory
are automatically installed and started. The directoy usually resides within the installation
directory and is called dropin
, load
, or pickup
.
osgi.configure {
framework 'external'
dropinsDir /path/to/dropins/dir
}
Note: an external runtime can neither be started nor stopped; the BundleContext
is not available.
osgi.configure {
bundle 'file:///path/to/bundle.jar'
bundle 'http://host.domain.com/path/to/bundle.jar'
}
Bundles from non-local locations are cached by the framework, until deleted with clean()
(see below).
Bundles with mvn:
URL scheme are resolved via built-in Ivy support, which is derived from Grails’ excellent Maven and Ivy support Grails dependency resolution.
The mvn:
URL consists of a group id, module name, and version. Transitive dependencies are not resolved,
as all artifacts must be valid OSGi bundles.
osgi.configure {
bundle 'mvn:group:module:version'
bundle 'mvn:org.apache.felix:org.apache.felix.configadmin:1.2.4'
bundle 'mvn:org.apache.felix:org.apache.felix.fileinstall:3.0.2'
bundle group:'org.apache.felix', name:'org.apache.felix.fileinstall', version:'3.0.2'
}
Note: at first start the bundles are stored in the disk cache in ~/.ivy2/cache
, which may take some time, while Ivy is downloading the Internet…
By default, all bundles are resolved against Maven Central, SpringSource Enterprise Bundle Repository (EBR), and some other Spring repos. Additional repos can be configured like this:
osgi.configure {
repositories {
mavenLocal()
ebr()
mavenCentral()
mavenRepo 'http://s3.amazonaws.com/maven.springframework.org/osgi'
mavenRepo 'http://s3.amazonaws.com/maven.springframework.org/milestone'
}
bundle 'mvn:group:module:version'
bundle 'mvn:org.apache.felix:org.apache.felix.configadmin:1.2.4'
bundle 'mvn:org.apache.felix:org.apache.felix.fileinstall:3.0.2'
bundle group:'org.apache.felix', name:'org.apache.felix.fileinstall', version:'3.0.2'
}
Please consult the Grails docs for repository configuration.
The OSGi runtime caches bundles, framework settings and user data. This can be cleaned on startup.
osgi.configure {
clean()
}
Additional the provisioned framework can be removed altogether before startup.
osgi.configure {
clean(true)
}
Note: don’t do this for an external framework, as this might delete the framework’s installation directory!
The OSGi console offers shell commands to inspect state and inner workings of the framework.
osgi.configure {
console()
}
osgi.configure {
console(8023)
}
The Felix Web Console offers great insight into the OSGi framework.
osgi.configure {
webConsole()
}
or with custom port number:
osgi.configure {
webConsole(8081)
}
The application can be accessed at http://localhost:8081/system/console with user “admin” and password “admin”.
NOTE: currently the required dependencies to run the web console need to be added manually (see examples/extended.groovy
for an example). Future releases will add all required bundles automatically.
The OsgiRuntimeBuilder
offers some lifecycle callback methods (or rather closures), which are called for certain events.
osgi.configure {
doRun = { runtime ->
def bundleContext = runtime.bundleContext
// do something
}
}
The following callback methods are provided:
- beforeStart: called before the framework is started.
- afterStart: called after the framework has been started.
- beforeInstallBundles: called before a bunch of bundles is installed.
- afterInstallBundles: called after a bunch of bundles has been installed.
- doRun: called after the framework has been started. When the closure returns, the framework is stopped.
- beforeStop: called before the framework is stopped.
- afterStop: called after the framework has been stopped.
All callbacks except beforeStart
and afterStop
are supplied with the OsgiRuntime
as argument. The BundleContext
can be obtained with runtime.bundleContext
.
OsgiRuntimeBuilder
’s configure()
method supports several source types:
- groovy.lang.Closure
The closure can use the OSGi runtime DSL. - groovy.lang.Script
The script is executed with a binding containing a builder instance as propertybuilder
and the builder’sconfigure()
method. - java.io.Reader
The reader’s content is loaded as Groovy Script - java.io.InputStream
The stream’s content is loaded as Groovy Script - java.io.File
The file’s content is loaded as Groovy Script - java.net.URL
The URL’s content is loaded as Groovy Script - java.lang.CharSequence (String, GString)
If the string is a URL, it is handled as URL (see above).
Otherwise, the string’s content is loaded as Groovy Script - Array or List containing any of the above
Each item is handled according to its type (see above)
OsgiRuntimeBuilder
can be called with a script as parameter:
groovy -cp groovyx-osgi-runtime-version.jar groovyx.osgi.runtime.OsgiRuntimeBuilder path/to/script.groovy
The script is executed with a Binding
containing a builder instance as property builder
and
the builder’s configure()
method.
OsgiRuntimeBuilder
also has a static run()
method which creates an instance if OsgiRuntimeBuilder
,
configures it with all arguments (which are either handled as URLs or as DSL script), starts the runtime
and waits for it to shutdown.
- implement OsgiCategory and extend
BundleContext
with some convenience methods and filter DSL - improve docs
- add support for pre-defined provisioning profiles
- add support for OSGi ConfigurationAdmin
- improve handling of external OSGi runtimes
- improve docs
- initial version
The OsgiRuntimeBuilder
collects bundles to be installed, runtime properties, and other information and delegates creation of the framework to an OsgiRuntimeFactory
, which creates an OsgiRuntime
, which in turn creates and starts the actual OSGi framework.
The Felix Web Management Console provides excellent insight into the inner workings. When using webConsole()
or webConsole(<port>)
in your configuration script, it can be accessed at http://localhost:8080/system/console/ with user “admin” and password “admin”.
(Note: the initial release is missing automatic inclusion of dependencies required to run Web Console. See script src/main/resources/extended.groovy
for an example with all dependencies)
When using console()
, the user is dropped into the Equinox or Felix Shell (press RETURN
if you don’t see the osgi>
prompt). Calling console(<port>)
opens a console with telnet access on the specified port or on port 8023
, if omitted. Only a single user can use the console at any time.
Typing help
shows the available commands:
osgi> help
---Controlling the OSGi framework---
launch - start the OSGi Framework
shutdown - shutdown the OSGi Framework
close - shutdown and exit
exit - exit immediately (System.exit)
init - uninstall all bundles
setprop <key>=<value> - set the OSGi property
---Controlling Bundles---
install - install and optionally start bundle from the given URL
uninstall - uninstall the specified bundle(s)
start - start the specified bundle(s)
stop - stop the specified bundle(s)
refresh - refresh the packages of the specified bundles
update - update the specified bundle(s)
---Displaying Status---
status [-s [<comma separated list of bundle states>] [<segment of bsn>]] - display installed bundles and registered services
ss [-s [<comma separated list of bundle states>] [<segment of bsn>]] - display installed bundles (short status)
services [filter] - display registered service details
packages [<pkgname>|<id>|<location>] - display imported/exported package details
bundles [-s [<comma separated list of bundle states>] [<segment of bsn>]] - display details for all installed bundles
bundle (<id>|<location>) - display details for the specified bundle(s)
headers (<id>|<location>) - print bundle headers
log (<id>|<location>) - display log entries
---Extras---
exec <command> - execute a command in a separate process and wait
fork <command> - execute a command in a separate process
gc - perform a garbage collection
getprop [ name ] - displays the system properties with the given name, or all of them.
---Controlling Start Level---
sl [<id>|<location>] - display the start level for the specified bundle, or for the framework if no bundle specified
setfwsl <start level> - set the framework start level
setbsl <start level> (<id>|<location>) - set the start level for the bundle(s)
setibsl <start level> - set the initial bundle start level
---Controlling the Profiling---
profilelog - Display & flush the profile log messages
---Eclipse Runtime commands---
diag - Displays unsatisfied constraints for the specified bundle(s).
enableBundle - enable the specified bundle(s)
disableBundle - disable the specified bundle(s)
disabledBundles - list disabled bundles in the system
---Controlling the Console---
more - More prompt for console output
The command ss
(for short status) shows all bundles with their respective state:
osgi> ss
Framework is launched.
id State Bundle
0 ACTIVE org.eclipse.osgi_3.6.0.v20100517
1 ACTIVE org.eclipse.osgi.util_3.2.100.v20100503
2 ACTIVE org.eclipse.osgi.services_3.2.100.v20100503
3 ACTIVE org.eclipse.equinox.common_3.6.0.v20100503
4 ACTIVE org.apache.felix.configadmin_1.2.4
5 ACTIVE org.apache.felix.fileinstall_2.0.8
6 ACTIVE com.springsource.org.apache.log4j_1.2.15
7 ACTIVE org.ops4j.pax.logging.pax-logging-api_1.4.0
8 ACTIVE org.ops4j.pax.logging.pax-logging-service_1.4.0
9 ACTIVE com.springsource.javax.annotation_1.0.0
10 ACTIVE com.springsource.javax.el_1.0.0
11 ACTIVE com.springsource.javax.ejb_3.0.0
12 ACTIVE com.springsource.javax.mail_1.4.1
13 ACTIVE com.springsource.javax.persistence_1.99.0
14 ACTIVE com.springsource.javax.transaction_1.1.0
15 ACTIVE com.springsource.javax.servlet_2.5.0
16 ACTIVE com.springsource.javax.servlet.jsp_2.1.0
17 ACTIVE com.springsource.javax.servlet.jsp.jstl_1.2.0
18 ACTIVE com.springsource.javax.jms_1.1.0
19 ACTIVE com.springsource.javax.xml.rpc_1.1.0
20 ACTIVE com.springsource.org.mortbay.jetty.server_6.1.9
21 ACTIVE com.springsource.org.mortbay.util_6.1.9
22 ACTIVE org.springframework.osgi.jetty.start.osgi_1.0.0
23 RESOLVED org.springframework.osgi.jetty.web.extender.fragment.osgi_1.0.1
Master=85
24 ACTIVE org.apache.felix.http.jetty_2.0.4
25 ACTIVE com.springsource.org.apache.commons.beanutils_1.8.0
26 ACTIVE com.springsource.org.apache.commons.collections_3.2.1
27 ACTIVE com.springsource.org.apache.commons.codec_1.3.0
28 ACTIVE com.springsource.org.apache.commons.dbcp_1.2.2.osgi
29 ACTIVE com.springsource.org.apache.commons.el_1.0.0
30 ACTIVE com.springsource.org.apache.commons.digester_1.8.1
31 ACTIVE com.springsource.org.apache.commons.fileupload_1.2.1
32 ACTIVE com.springsource.org.apache.commons.httpclient_3.1.0
33 ACTIVE com.springsource.org.apache.commons.io_1.4.0
34 ACTIVE com.springsource.org.apache.commons.lang_2.4.0
35 ACTIVE com.springsource.org.apache.commons.pool_1.5.3
36 ACTIVE com.springsource.org.apache.commons.validator_1.3.1
37 ACTIVE com.springsource.org.apache.oro_2.0.8
38 ACTIVE com.springsource.org.apache.ivy_2.1.0
39 ACTIVE com.springsource.org.apache.tools.ant_1.7.1
40 ACTIVE com.springsource.antlr_2.7.7
41 ACTIVE com.springsource.org.dom4j_1.6.1
42 ACTIVE com.springsource.org.aspectj.runtime_1.6.8.RELEASE
43 ACTIVE com.springsource.org.aspectj.weaver_1.6.8.RELEASE
44 ACTIVE com.springsource.com.opensymphony.sitemesh_2.4.1
45 ACTIVE com.springsource.javassist_3.9.0.GA
46 ACTIVE com.springsource.org.objectweb.asm_1.5.3
47 ACTIVE com.springsource.org.jboss.cache_3.2.0.GA
48 ACTIVE com.springsource.org.jboss.util_2.2.13.GA
49 ACTIVE com.springsource.org.jboss.logging_2.0.5.GA
50 ACTIVE com.springsource.org.jgroups_2.5.1
51 ACTIVE com.springsource.net.sf.ehcache_1.6.2
52 ACTIVE com.springsource.org.hibernate.annotations.common_3.3.0.ga
53 RESOLVED com.springsource.org.hibernate.annotations_3.4.0.GA
Master=54
54 ACTIVE com.springsource.org.hibernate_3.3.2.GA
Fragments=53
55 ACTIVE com.springsource.org.xmlpull_1.1.4.c
56 RESOLVED com.springsource.org.apache.xerces_2.9.1
Master=60
57 ACTIVE com.springsource.org.apache.xalan_2.7.1
58 ACTIVE com.springsource.org.apache.xml.serializer_2.7.1
59 ACTIVE com.springsource.org.apache.xml.resolver_1.2.0
60 ACTIVE com.springsource.org.apache.xmlcommons_1.3.4
Fragments=56
61 ACTIVE com.springsource.org.apache.xml.security_1.4.2
62 ACTIVE org.springframework.aop_3.0.3.RELEASE
63 ACTIVE org.springframework.asm_3.0.3.RELEASE
64 ACTIVE org.springframework.aspects_3.0.3.RELEASE
65 ACTIVE org.springframework.beans_3.0.3.RELEASE
66 ACTIVE org.springframework.context_3.0.3.RELEASE
67 ACTIVE org.springframework.context.support_3.0.3.RELEASE
68 ACTIVE org.springframework.core_3.0.3.RELEASE
69 ACTIVE org.springframework.expression_3.0.3.RELEASE
70 ACTIVE org.springframework.instrument_3.0.3.RELEASE
71 ACTIVE org.springframework.jdbc_3.0.3.RELEASE
72 ACTIVE org.springframework.jms_3.0.3.RELEASE
73 ACTIVE org.springframework.orm_3.0.3.RELEASE
74 ACTIVE org.springframework.oxm_3.0.3.RELEASE
75 ACTIVE org.springframework.transaction_3.0.3.RELEASE
76 ACTIVE org.springframework.web_3.0.3.RELEASE
77 ACTIVE org.springframework.web.servlet_3.0.3.RELEASE
78 ACTIVE com.springsource.org.aopalliance_1.0.0
79 ACTIVE com.springsource.net.sf.cglib_2.2.0
80 ACTIVE org.springframework.osgi.core_2.0.0.M1
81 ACTIVE org.springframework.osgi.extender_2.0.0.M1
82 ACTIVE org.springframework.osgi.io_2.0.0.M1
83 INSTALLED org.springframework.osgi.test_2.0.0.M1
84 ACTIVE org.springframework.osgi.web_2.0.0.M1
85 ACTIVE org.springframework.osgi.web.extender_2.0.0.M1
Fragments=23
86 INSTALLED org.grails.osgi_1.3.2
87 INSTALLED org.grails.crud_1.3.2
88 INSTALLED org.grails.gorm_1.3.2
89 INSTALLED org.grails.resources_1.3.2
90 INSTALLED org.grails.spring_1.3.2
91 INSTALLED org.grails.web_1.3.2
92 ACTIVE gant_1.9.1
93 ACTIVE groovy-all_1.7.3
94 ACTIVE gant_1.9.2
95 ACTIVE org.apache.felix.webconsole_2.0.2
96 ACTIVE tripper_0.1.0
osgi>