OSGi: Apache Felix Maven Bundle Plugin and Javadoc - java

I'm using the Apache Felix Maven Bundle Plugin to generate the OSGi metadata.
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
You can configure which packages are exported or you can use the default, which excludes packages such as *.impl.* and *.internal.*.
Is there a way to generate Javadoc only for the exported packages without having to duplicate this information?
Edit:
My current approach is that I set the excludePackageNames property (a Maven Javadoc Plugin property) manually and thus duplicate this information:
<excludePackageNames>*.internal.*:*.impl.*</excludePackageNames> <!-- used by Javadoc plugin --><!-- TODO: get this from OSGi meta data-->
http://sourceforge.net/p/drombler/drombler-oss-parent/ci/default/tree/pom.xml#l64

The Apache Maven bundle plugin is based on bndlib, which has its own plugin model. If a maven plugin model has class visibility to other maven plugins then it is easy to get this information. In the instructions in the pom register a plugin:
<instructions>
<_plugin>com.example.MyPlugin</_plugin>
</instruction>
In this bnd plugin, implement the AnalyzerPlugin interface
boolean analyzeJar(Analyzer analyzer) throws Exception {
doJavadoc( analyzer.getExportedPackages().keySet() );
}
I am not that familiar with maven plugins, since bnd will do dynamic class loader (yuck), it must be able to see your code.

I guess the best thing would be, if the Maven Bundle Plugin would provide a goal to generate the needed information.
I filed a new issue: https://issues.apache.org/jira/browse/FELIX-4181

Related

Which lifecycle for a Java annotation that generates documentation?

I would like to be able to document the dependencies of my services directly in my code, using Java annotations. Those annotations could bear the information about the target system, whether the connection is incoming/outgoing/2-ways, and the type of connection (REST, RabbitMQ...).
It could look like this:
#Dependency(target = "Twitter API", type = "Outgoing", medium = "REST")
The idea would be to generate a DOT file from all the annotations inside the project.
I have a fair idea on how to create my own annotation, with the required attributes. However, i am not sure at which part of the lifecycle of the compilation/processing i should handle those annotations.
I understand that the annotation processors generate source files, but in my case the generated files are not at all required by the compiler nor the application itself.
Ideally i would like to be able to trigger the annotation processing, and DOT file generation, by a dedicated Maven or Gradle task.
Is it something that is easily doable when writing my own annotations?
If you want to create documentation via maven than you need add the bellow two dependencies as plugins and then execute site maven goal.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
If you just want to document REST endpoints than you can use swagger.
If your project uses spring than the integration of swagger is pretty easy. You can use this tutorial.
If you want to save in a file the dependency graph of your project you can simply execute the following maven command.
mvn dependency:tree -Doutput=/path/to/file
Annotations are processed by the Java compiler directly.
For Maven, one can use the maven-compiler-plugin. It is also possible to perform the compilation in 2 steps, as explained here.
For Gradle, one can add the processors in the dependencies block under the annotationProcessor configuration, as explained here.
Annotation retention can be specified as SOURCE, so they won't be kept after compilation.

Import package can not be resolved in maven bundle

I am getting problem when tried to start bundle.
Project structure:
--Main project
- sub project 1
- sub project 2
src/main/java/util
- sub project 3
- bundle project 1
- bundle project 2
- bundle project 3
When I compiled main project using Maven install command in eclipse, it's successfully compiled. So, for testing bundle, I have downloaded felix distribution package. I am install bundle successfully but I am not able to start. I getting error dependency cannot be resolved
here is my bundle pom file
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Export-Package>
com.test.sub_project_3.step,
com.test.sub_project_3.step2
</Export-Package>
<Import-Package>*
org.osgi.framework,
org.osgi.util.tracker,
com.test.sub_project_2.util
</Import-Package>
<Embed-Dependency>
slf4j-api;scope=compile
</Embed-Dependency>
<Bundle-Activator>com.test.sub_project_3.osgi.Activator</Bundle-Activator>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
I am getting error for "com.test.sub_project_2.util cannot be resolved". com.test.sub_project_2 it'sussfully compiled and packag name it's also correct but still I don't understand why I am getting error.
You must understand that OSGi and Maven are different tools with different strategies concerning package resolution.
At design time, maven strategy is used. You indicate your dependency in your POM file. Moreover in your case you used the maven bundle plug in , so you can constrain which package needs to be imported at runtime by your bundle (your import-package section). So in your case, all dependencies are present at design time because your project compiles. But it not implies that the runtime resolution will work, because at runtime OSGi resolution is used.
In your case the error message indicates that your deployed bundle cannot find at runtime the com.test.sub_project_2.util in order to be executed. This is because no bundle present in the OSGi distribution provides the package. So you can bundlify the project that contains the package and deploy it in your OSGi distrib. If you do that the package is now available at runtime.
In a simplistic way you can think as this problem in this way: The classpath used for your bundle is different at design and runtime. And you cannot assume a causality relation between them.
Regards

How to include FMPP as a maven dependency not as a plugin

I want to write a FMPP Front End application but the official documentation do not explains how to include the FMPP library in a maven project, but the plugin. So i want to know how to include the library so i can extend the fmpp.setting.Settings; object.
I found it in the fmpp-maven-plugin dependencies :), so just include something like this in the dependencies' block in the pom.xml
<dependency>
<groupId>net.sourceforge.fmpp</groupId>
<artifactId>fmpp</artifactId>
<version>0.9.15</version>
</dependency>
Then use Clean and Build and try using in any java file:
import fmpp.setting.Settings;
Thats it!

How to dynamically load Java classes at Runtime in OSGI framework?

We are performing a POC in our project, where in we send SOAP based request and correspondingly get a SOAP response from a web service. We aim to leverage webservices template (client side API) provided by spring framework in our application. As per our architecture, we create an OSGI compliant bundle (for our code that uses webservices template API to interact with the web service) which is then deployed into the Apache Felix container. We have also installed all the dependent OSGI compliant bundles in the Felix container so that all the dependencies are resolved.
As per the webservices template, the default Web Service Message sender is HttpUrlConnectionMessageSender which is dynamically loaded at run time by the class loader. As per my understanding, we are getting the below exception because the Felix container is not able to load the class from the dependent OSGI bundle (web services bundle contains the HttpUrlConnectionMessageSender).Please refer to the exception logs below.
* org.springframework.beans.factory.BeanInitializationException: Could not find default strategy class for interface [org.springframework.ws.transport.WebServiceMessageSender]; nested exception is java.lang.ClassNotFoundException:org.springframework.ws.transport.http.HttpUrlConnectionMessageSender at org.springframework.ws.support.DefaultStrategiesHelper.getDefaultStrategies(DefaultStrategiesHelper.java:126)
at org.springframework.ws.support.DefaultStrategiesHelper.getDefaultStrategies(DefaultStrategiesHelper.java:90)
at org.springframework.ws.client.core.WebServiceTemplate.initMessageSenders(WebServiceTemplate.java:320)
at org.springframework.ws.client.core.WebServiceTemplate.initDefaultStrategies(WebServiceTemplate.java:306)
at org.springframework.ws.client.core.WebServiceTemplate.<init>(WebServiceTemplate.java:143)
at test.soapservice.service.SOAPServiceImpl.<init>(SOAPServiceImpl.java:40)
at test.soapservice.service.SOAPServiceActivator.start(SOAPServiceActivator.java:17)
at org.apache.felix.framework.util.SecureAction.startActivator(SecureAction.java:641)
at org.apache.felix.framework.Felix.activateBundle(Felix.java:1977)
at org.apache.felix.framework.Felix.startBundle(Felix.java:1895)
at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:944)
at org.apache.felix.gogo.command.Basic.start(Basic.java:729)
Caused by: java.lang.ClassNotFoundException: org.springframework.ws.transport.http.HttpUrlConnectionMessageSender
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:268)
at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
at org.springframework.util.ClassUtils.forName(ClassUtils.java:211)
at org.springframework.util.ClassUtils.forName(ClassUtils.java:164)
at org.springframework.ws.support.DefaultStrategiesHelper.getDefaultStrategies(DefaultStrategiesHelper.java:114)
As per my understanding,Felix container is unable to dynamically load the class using ClassUtils.forName() which exists in another bundle. I see this as a collaboration issue where the current bundle has a different class loader as opposed to class loader of dependent bundle.
Did someone from this community have encountered the same exception? If yes, then what were steps taken by you to resolve the run time class dependency? Please share your thoughts/pointers to resolve the above issue.A quick response would be highly appreciated and may help us to make our POC successful.
Thanks in advance,
Mridul Chopra
Classloading in the form of Class.forName() is not a problem in any OSGi container. You problem here is that the MANIFEST.MF file does not contain the right import declarations. One bundle should export the org.springframework.ws.transport package, while your bundle should import the same package.
If you are using Maven to build your bundle, you can use the Felix Bundle Plugin to generate the right manifest information.
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Private-Package>my.private.package.*</Private-Package>
</instructions>
</configuration>
</plugin>
</plugins>
This should inspect your code and add imports for anything that is not inside your "private" package scope. One other thing you should do to make this work is to set the packaging type to bundle.
<packaging>bundle</packaging>
But, the examples above is when you are using Maven as a build tool. If you are using Gradle, you can use the Gradle OSGi plugin to build manifest. Or, if using Ant you can use SpringSource Bundlor project (btw, which also has a Maven plugin).

How can I force maven to leave the version number out of dependency file names?

I'm using maven to build a ".ear" project that resolves dependencies from a maven repository, and then packages them into an ear (that's probably a redundant sentence...).
When the dependencies show up in the ear file, they're named according to this format:
<artifactId>-<version>.<type>
I'd like them to be named:
<artifactId>.<type>
Can someone point me in the right direction?
If you're using the maven-assembly-plugin to build your ear, you can use the outputFileNameMapping property in your descriptor: http://maven.apache.org/plugins/maven-assembly-plugin/assembly.html#class_dependencySet
However, you're probably better off using the maven-ear-plugin, in which case you can customize the bundleFileName, as described here.
Set the finalName property. See http://maven.apache.org/plugins/maven-assembly-plugin/assembly-mojo.html for more details

Categories

Resources