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:schemaLocationosgi 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: