This page explains how to convert your P2 app to use Spring Java configuration,
if it currently declares its components in .xml
files under src/main/resources/META-INF/spring
.
<Atlassian-Plugin-Key>
header to your AMPS <instructions>
, to indicate that your plugin should
not be transformed at runtime into an OSGi bundle. For example:1 2<project ...> <!-- ... --> <build> <plugins> <plugin> <groupId>com.atlassian.maven.plugins</groupId> <artifactId>amps-maven-plugin</artifactId> <!-- Or jira-maven-plugin, etc. --> <!-- For AMPS pre-8.0, use maven-amps-plugin, maven-jira-plugin, etc. --> <version>9.1.11</version> <configuration> <instructions> <!-- You may want to extract the plugin key to a POM property, for reuse elsewhere --> <Atlassian-Plugin-Key>my-plugin-key</Atlassian-Plugin-Key> <!-- You may need to import some packages whose usage is not detected by the maven-bundle-plugin, or mark some packages as optional, or add version ranges to them, etc. --> <Import-Package>*</Import-Package> <!-- Ensure the plugin is Spring-powered --> <Spring-Context>*</Spring-Context> <!-- ... --> </instructions> <!-- ... --> </configuration> </plugin> <!-- ... --> </plugins> </build> <!-- ... --> </project>
SpringBeans
, in a new package somewhere under
src/main/java
, for example com.example.myplugin.spring
.@org.springframework.context.annotation.Configuration
.You will currently have at least one Spring XML file under src/main/resources/META-INF/spring
(it could be called anything ending in
.xml
). Modify this file as follows:
osgi
namespace from the root element.xsi:schemaLocation
osgi
namespace with equivalent @Bean
methods in your Java config class.@Configuration
classes.For each service you’re importing via an osgi:reference
element in your Spring XML files (if any) which would look like:
1 2<osgi:reference id="foo"> <osgi:interfaces> <beans:value>com.example.FooService</beans:value> </osgi:interfaces> </osgi:reference>
Replace it with a method like this in your Spring config class:
1 2@Bean public FooService fooService() { return OsgiServices.importOsgiService(FooService.class); }
Note that since version 0.2.0 of this helper library, you can optionally specify an LDAP filter,
just as you could add a filter
attribute to <component-import>
. Here's an example that works with 0.3.1 and later:
1 2@Bean public FooService fooService() { return importOsgiService(FooService.class, ImportOptions.defaultOptions().withFilter("(some.key=some.value)")); }
Here, the FooService
will be imported only if it has a some.key
property with the value some.value
.
Since 0.6.0 it's possible to replace importing a collection of OSGi services (i.e. using osgi:list
or osgi:set
) in XML like:
1 2<osgi:list id="fooServices" interface="com.example.FooService" cardinality="0..N" />
The equivalent with Java config is:
1 2@Bean public List<FooService> fooServices() { return OsgiServices.importOsgiServiceCollection(list(FooService.class)); }
In Spring XML, exporting an existing bean to an OSGi service looked like:
1 2<bean id="foo" class="com.example.FooService" /> <osgi:service id="foo_osgiService" ref="foo"> <osgi:interfaces> <value>com.example.FooService</value> <value>com.example.BarService</value> </osgi:interfaces> <osgi:service-properties> <beans:entry key="baz" value="qux"/> </osgi:service-properties> </osgi:service>
where each interface is what the service is exposed to OSGi with and where the ref
attribute refers to the existing bean name to expose as an OSGi service.
Replace it like so:
1 2@Bean public FooService foo() { return new FooService(); } @Bean public FactoryBean<ServiceRegistration> exportFooService(FooService foo) { return OsgiServices.exportOsgiService(foo, ExportOptions.as(FooService.class, BarService.class).withProperty("baz", "qux")); }
If the exported service was a module type where the interface was ListableModuleDescriptorFactory.class
there is shorthand for this:
1 2@Bean public FactoryBean<ServiceRegistration> exportMyModuleType( final ListableModuleDescriptorFactory moduleDescriptorFactory) { return OsgiServices.exportAsModuleType(moduleDescriptorFactory); }
If your @Configuration
class has become too big or messy, you can easily split it up as follows:
MyWebBeans.class
, or split up the beans by feature, etc).@Import
annotation that lists these subsidiary config classes,
for example:1 2@Configuration @Import({ MyPersistenceBeans.class, MyServiceBeans.class, MyWebBeans.class }) public class MainSpringConfig {}
Not every case is covered with this library, if you run into this please create a ticket.
In the meantime it's very likely that it's possible to achieve whatever is missing by using the Gemini Blueprint API directly.
Feel free to poke inside the decompiled OsgiServices
class for examples.
Rate this page: