OSGI Bundle vs jar dependency - maven

I'm trying to understand the difference between the following
<dependency>
<groupId>com.myspace.order</groupId>
<artifactId>dal</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
AND
<dependency>
<groupId>com.myspace.order</groupId>
<artifactId>dal</artifactId>
<version>1.0.0-SNAPSHOT</version>
<type>bundle</type>
</dependency>
The dal artifact itself has packaging specified as bundle as:
<packaging>bundle</packaging>
Now when I deploy the dal artifact, I see it published in the repo as a jar (with a manifest within it). In this case, what should my dependency on dal be. Should it be of type bundle or jar? If I am doing OSGI, I assume way would be to have the type specified as bundle. Is this correct? Or, can I just have a jar dependency here?

When you declare a dependency in Maven, you can only depend on a normal Jar, not a bundle, because Maven does not recognize the OSGi environment restrictions.
See this question:
Why can't maven find an osgi bundle dependency?
At the time you compile your project, you don't need to worry (but should!) about the OSGi environment yet... for example, it will not complain if you try to use packages not exported by the bundle you're depending upon....
When you try to deploy your bundle within a OSGi container, if you correctly declared your dependencies on the 'dal' packages you use, including of course the version (which usually you should leave for the maven-bundle-plugin to do for you based on your POM), it will only be resolved if there's a bundle within the container which exports the required packages in the right version (or version range).
Considering that 'dal' seems to be a bundle already, you just have to make sure to deploy the your bundle and 'dal' together and everything will work fine.
However, if you by mistake added a dependency on a private package of 'dal', although Maven will happily compile it for you, when you thrown it in OSGi you will be greeted by a nasty wiring exception :)
Notice that a bundle is just a normal jar which contains OSGi metadata in the manifest (Bundle-SymbolicName, Bundle-Version etc). So if you don't use OSGi, a bundle will work as any other jar.
But anyway, if you want some more info, check this question:
What is the meaning of type "bundle" in a maven dependency?

Related

Why third party dependency is required exclusively from OSGi container even if I have it in my maven dependencies?

I want to know why OSGi do not respect the maven dependenceis.
I want to create one app in OSGi(AEM). I want to communicate(CRUD) to the database with the help of JPA(eclipselink).
I created maven project with aem-archetype.
Added all required dependencies(of JPA) into my maven project's pom file.
No errors in Eclipse, I built the project via mvn clean install and installed it into AEM(CQ5) via mvn sling:install. All good till now. No Errors.
But when I go and see my bundle in the felix console, I see that it is not Active but in Installed state.The error reported is that it could not resolve the javax.persistence package.
I was puzzled, I searched and I read about it here -
You have to make sure that you place the same version in another
bundle and deploy first. https://forums.adobe.com/thread/2325007
I converted JPA jar to OSGi bundle and installed in my OSGi container, and the error was gone. Great!
But why OSGi is not watching out for the dependencies I wrote in pom.xml of my maven project. Why it needs JPA strictly from OSGi bundle?
Maybe this is due to any architectural benefit, but could anyone please explain me here about this behaviour of OSGi? And why/how this feature of OSGi is useful ?
The <dependency> section of your Maven POM only covers your compile time dependencies. That means when you run Maven to build your project those dependencies are used to compile the source code and build your bundle. Maven itself is not aware of AEM or OSGi or any other platform or framework (e.g. Spring).
Maven just compiles your code.
You, as a developer, are responsible that all those required compile time dependencies are also available at runtime.
What we usually do is to create an AEM content package Maven module and put all of our required third party dependencies (e.g. JPA bundles) into it. This content package is then deployed by Maven so that those dependencies are also available at runtime.
Reason is: what you are adding as dependency is getting added in build path of your project and being available for your classes.When you run mvn install,it checks presence of all dependency and creates a bundle/jar for you.By default this bundle has only your project classes not other dependencies.
You need to check in depfinder whether external dependencies are already there in OSGi container,if not you have to load them in OSGi container either by embedding external dependencies in your bundle with the help of maven-bundle-plugin present in pom.xml or by making a bundle of jar file(I wont recommend that)which you have done.
I hope this helps!

include jar of one module to another

I have maven projet with this architecture:
++parent-project
+module-a
+module-b
module-b is a web application. it will be run on Jboss AS 7.1.1. I'm using netbeans IDE.
Now module-b depend on module-a. this is a porm section of module-b:
<dependency>
<groupId>groupid</groupId>
<artifactId>module-a</artifactId>
<scope>compile</scope>
</dependency>
When i build the war file of module-b, module-a is not present to lib folder ( in war file. i open it with archive explorer ). therefore JBoss return ClassNotFoundException.
I'm tried differends scope ( compile , provided , runtime , test ). But nothing.
Please how can i solve this.
First of all, I think you should try to see how does it work in "pure" maven, without the IDE at all (NetBeans). So my answer will be based only on maven knowledge:
A couple of facts:
Module b has to have the following in pom: <packaging>war</packaging> This will instruct maven that you really want to get a war from this module.
When packaging WAR is specified in some pom, maven will take all the dependencies defined in this pom and will put them into the WEB-INF/lib folder of the war. Automatically. Of course, you can customize the output, but its more advanced stuff (see Maven WAR plugin if required)
All the dependencies have to be defined with group id, artifact id, and version at least. So make sure that you have the dependency on module a with version. There is no need to fiddle with scopes in this case. The default scope (if you don't specify a scope at all) is 'compile' which is fine.
Go to the directory of module b and from within the directory type: mvn dependency:tree. Once its done, please carefully observe the output, especially make sure that module a is listed (with a correct version) in a tree.
Sometime to make sure that no stale artifacts reside in the local m2 repository you might want to delete all the jars of your project from there and then execute the mvn package command again. The war has to be created in module b/target - and this is the WAR you should check out.
Note, all these steps are done without any interaction with NetBeans at all.

ejb-client Maven dependencies in Eclipse

I use a dependency with ejb-client type in a Maven project:
<dependency>
<groupId>mygroup</groupId>
<artifactId>foo</artifactId>
<type>ejb-client</type>
</dependency>
It works properly when I build the project with Maven: it includes a version of the dependency that has remote EJB interfaces only (no implementations).
However, when I export the project to Eclipse Luna, and deploy it from Eclipse to jBoss/WildFly, Eclipse copies the full version of the dependency as if I used <type>ejb</type>.
Eclipse also gives me a warning:
Dependency to project foo with type ejb-client is not fully
supported. Classpath and/or deployment issues might arise. Try
Maven->Disable Workspace Resolution...
Is there a way to make ejb-client dependencies to work in Eclipse? Or is there any workaround?
In the past I've found that ejb-client jars are not a very good idea. They share the same dependencies as the full ejb-jar and you normally don't want that. You will also find that IDE support for these is a little weak.
You're far better off hand building your remote EJB API as a separate jar artefact and including it where needed.

Maven build order

I have a multi-module maven build and I need one particular module (lets call it project-A) to be build at the end. It depends on a module (lets call it project-B) that holds native code that gets compiled to a dll and installed into the maven repository as a zip file using some maven trickery. As it doesn't depends on it directly because the native code is not a java jar, I use Maven Dependency Plugin to unpack the zip file and place the native dll in my build directory. Everything is working fine except for the building order. It builds first project-A in spite of being declared the other way around in the tag in the parent. I would like to tell maven that project-A depends on project-B. I tried to add project-B as a dependency, but as it builds no jar it throws an ERROR, also this seemed hacky to me. Any help would be appreciated.
Just declare dependency in project A to project B and it will work fine. It does not matter if the project B is a native rather than a java project. Just make sure you declare the dependency correctly taking the packaging into account as type.. (which is probably pom so you would have
<dependency>
<groupId>...</groupId>
<artifactId>B</artifactId>
<version>...</version>
<type>pom</type>
</dependency>
in Project A)
The order in which you specify the modules in the parent Pom is also relevant. Maven actually builds in this order unless it has to build a module out of sequence due to direct dependencies.

How can Maven building depend on jar files which are inside another jar file?

We have an OSGi application:
Bundle A --> nothing but refers 10 jar files, export all the packages of those 10 jar files to satisfy the runtime calling.
Bundle B --> import packages which exported from Bundle A. Runtime OK.
But when I use Maven to build Bundle B, question appeared. Here is a piece of pom.xml of Bundle B:
<dependency>
<groupId>com.mycom.id</groupId>
<artifactId>com.mycom.BundleA</artifactId>
<version>${version.range}</version>
<scope>provided</scope>
</dependency>
When I refer the artifactID: Bundle A, build failed. Maven cannot refer to the jar files inside the project.
I cannot find a way to refer to the jar files which inside another project, so can anyone provide a solution to fix this dependency issues when on building-time?
You should not bundle your components this way. It is rarely advisable to bundle one jar inside of another in OSGi, and if you do it should NOT export the packages of that jar. If the packages need to be available to other bundles, then that jar should be an OSGi bundle.
See this question about your approach.
Did you set the 10 jars as dependency of Bundle A? If so Maven should be able to find the transitive dependencies when referencing Bundle A.

Resources