Should I use POM first or MANIFEST first when developing OSGi application with Maven? - maven

There are two main approaches when developing an OSGi application with Maven: POM-first and MANIFEST first.
I'm looking for an answer that is in a form of a table that shows pros and cons of each method.
To be more specific, I would also like to know how it relates to:
Maturity of toolset
Vendor independence
Development ease (which includes finding people who can do the development on the tooling)
Compatibility
Avoiding ClassNotFound
Avoiding manual work

At present this is what I can come up with
POM-First Pros (using maven-bundle-plugin)
Leverages existing Maven skills, repositories and tooling.
Likely easier to find people who know how to manage pom.xml rather than MANIFEST.MF along with pom.xml
Most of the information in MANIFEST.MF can be obtained from the pom.xml itself.
Can work with other IDEs not just Eclipse based ones.
Less invasive, just add the single plugin and change the packaging type to "bundle"
POM-First Cons
ClassNotFoundException more likely to occur at runtime. However, this can be mitigated using pax-exam (although it is very complicated to set up).
Still need to understand how the MANIFEST is setup to make sure the instructions configuration element is set correctly.
MANIFEST-first Pros (using tycho-maven-plugin)
Seems to be the recommended approach, or at least talked about as the recommended approach, but I can't really see why it has significant benefit. (Hence why this question was asked).
Good for developing Eclipse plugins and integrates well with PDE
Provides tooling for testing thus allowing ClassNotFoundException to appear during JUnit testing rather than runtime.
MANIFEST-first Cons
Seems to only work well on Eclipse based IDEs. You don't have to use Eclipse, but without the PDE would you want to?
Violates DRY principles since I have to do put keep the names and versions from the POM and MANIFEST.MF in sync.
Need to name things in a specific fashion
You cannot mix, meaning existing Maven multi-project installations cannot just tack on OSGi support
A lot more configuration compared to maven-bundle-plugin is needed to get less warnings: http://wiki.eclipse.org/Tycho/Reference_Card#Examplary_parent_POM
Have to make test cases a separate project. It won't run when built in src/test/java.
Seems that it will only test classes that are exposed, in other words those in ".internal." is not testable.
If I were asked for a recommendation for an enterprise that is using Maven already and want to move to OSGi then it would be POM first
If I were asked for a recommendation for someone who is doing Eclipse plugin development, then it is Manifest first -- with tycho

I think you should choose by use case. For server side OSGi projects I favour the pom first style. It nicely matches the maven builds and is much less error prone than Manifest first.
In fact bnd which is behind the maven bundle plugin gets the Manifest right for most cases without any additional config. The trick is to use some naming rules. For example if you name internal package impl or internal the will not be exported. Using this style you can not use the Eclipse plugin perspective (at least without bndtools which I do not like) but I did not yet miss this perspective. I am a developer in the Apache Karaf, CXF and Camel projects where we use this style and it works great. Especially for CXF and Camel it is great that we can support OSGi and non OSGi deployments with the same build and tools.
For Eclipse RCP applications Manifest first is the way to go as you need the plugin perspective and the Eclipse IDE tools. If you want to combine that with maven then tycho is probably the way to go.

MANIFEST first does not lock you to Eclipse (although I'd be surprised if more than a tiny minority would use anything else). The MANIFEST is the file that counts, and needs to be added to a jar, regardless how you do that.
On the other hand, POM first completely locks you to Maven, you lose the advantage that an OSGi bundle is a regular jar you can make any way you want.
I've tried both, I really prefer MANIFEST first. The MANIFEST file is a really important file, I prefer to craft that file over crafting a file that produces that file. If something weird happens, (and it will at some point) the MANIFEST file is the first to check, it's just easier if it's your own file. Besides, you will have to be familiar with it anyway.
So, if Maven is your alpha and omega, POM first will suit you best, but you'll still need to have in-depth understanding of the MANIFEST file.

Related

The idea behind using maven to compile source code

I am currently starting my adventure with Maven, and I actually don't understand the idea behind using it to automate compilation of my source code. For the time being I am working on small projects with up to 15-20 classes, and 1 main method in the "app" class. Could someone please give me the explanation with examples, when it's necesarry (or recommended) to use build automatation tool to compile the source code and how could I benefit from using it regarding source code compilation?
Thank you very much in advance!
I was looking for different answers and I have a lot of work to do but since I've seen this question, as a Maven fanboy, I couldn't resist anymore and this below is my answer.
First of all, I agree with JF Meier which answered before me, but I think the answer can be improved.
IMO you have to consider Maven not just as a build tool, but as a multi-purpose tool which can help you to do very different things. The best 3, for me are:
Compiler. Obviously. Maven allows you to easily compile giant projects with a lot of submodules, even if some of these modules are interdependent one with each other.
Dependency and repository manager. Maven allows you to automatically download third party software and bind this downlaod to the build. This is immediately understandable if you think to framework or api dependencies from big corps (Apache found., Spark, Spring, Hibernate and so on ...) but it's really powerful in every enterprise context.
Example: you have a Maven project (let's say project A) which manages requests coming from a webservice and provides responses. This Maven project relys on another Maven project (let's say project B) which actually generates webservice jar and uploads it to a company repository. Well, when you have to add a field or a method to the webservice you just have to implements new software in project B, upload it the repo and change the version in Maven poms in both project A and B. VoilĂ : now EVERY developer of the company just have to "mvn clean install" project A to have the new version.
Sources and code automatic generator. Since Maven 2.x are available a lot of plugins (from Apache found. and others) which allow you to generate code and sources (tipically xml files) starting from little to none implementations.
Example 1: CXF plugin is commonly used to generate java classes from xml or xsd files.
Example 2: JAXWS plugin is commonly used to generate wsdl from SOAP webservice implementations or implementation starting from wsdl file.
Do you feel the power now?
-Andrea
The question is not very specific, but I will try to answer.
Usually, you want your source code to end up in a jar or war, so that you can use it as a library or run it somewhere (e.g. on an application server).
Maven not only compiles the classes you have and creates the final artifact (jar, war), but also handles your dependencies, e.g. the libraries your project depends upon.

What'll change about maven extensions according to this line in apache doc?

I found this note in the Maven's documentation:
You can add elements to this classloader by extensions. These are loaded into the same place as ${maven.home}/lib and hence are available to the Maven core and all plugins for the current project and subsequent projects (in future, we plan to remove it from subsequent projects).
I couldn't understand what they mean by "subsequent projects" here. As far as I understand, extensions are enhancements to lifecycle phases of Maven and are not project specific. So it makes sense to work for all the Maven projects.
Question: Can anyone explain what this statement means "in future, we plan to remove it from subsequent projects"
First an extensions can be extensions of a life cycle but not need to. You can implement an extensions also as an EventSpy for example.
This documentation is related to the Core Classloader which is available within such extensions and makes it also possible to enhance it via an extensions. This classloader contains those files from ${maven.home}/lib which is not a good idea and not necessary. It would be better having only the Maven Plugin API there and it's instances which are currently used and not more...
There existing some extensions like Wagon which are using to make a transport in special cases possible which could be project specific.
Starting with Maven 3.3.1 the core extensions mechanism has been improved to make loading project specific extensions more simpler which means they are located into ${maven.projectBasedir}/.mvn/extensions.xml file and also being loading from an repository. Before 3.3.1 you need to do that manually via mvn -Dmaven.ext.class.path=extension.jar.

OSGI vs Maven which is better packaging tool

We have a very big web application containing many features.Now for maintainability we want to split the application in components so that can remove / add particular components (jars). For that one suggestion is coming is to use OSGI. I think converting jars into bundle will take huge effort. I think same functionality can be achieved by Maven. According to my understanding OSGI is packaging tool. If I can make Maven plug-in for each component then any particular component can be included or removed at compile as opposed to run time as in case of OSGI.
Modularizing the application using Maven will be simpler than OSGI. I have read similar post on this site and it commented that OSGI and Maven are like comparing apple with orange. But I think in one sense both are same as they both meant for packaging difference is one is used at run time and one for compile time
Looking forward for well though answer :)
best wishes
Shailesh
As you already hinted at yourself: you're comparing apple with orange.
OSGi is not a packaging tool.
OSGi bundles are plain JAR files with some OSGi-specific metadata in the Manifest file.
You can create OSGi bundles using Maven e.g. using the Maven Bundle Plugin (I can recommend this approach). So regardless if you're using OSGi or not I strongly recommend using Maven.
Here some use cases for OSGi:
You want to create different versions of your application e.g. for different customers. With OSGi you can just add/ remove bundles without having to touch any other configuration.
You need a plugin system so 3rd parties can provide plugins to your application
You want your application to be truely modular
You want to share some code with other applications but want to hide some internal classes
...
OSGI is much much more than a packaging tool. You could say that OSGI has a packaging tool inside. Maven is a packaging tool and a dependency manager. I'd say that, given the level of complexity and the use you say you'll make of this technology, go with Maven.

Imperative vs Declarative build systems

I have recently started using Gradle as a build system.
They first comparison that Gradle makes with the likes of Ant and Maven is that,
Ant is an imperative build system, whereas Maven is a declarative build system.
While Gradle is a declarative build system without the rigidity enforced by Maven.
I wanted to understand these terms declarative and imperative better when it comes to talking about build systems.
In short, an ant script tells the ant tool what to do - "compile these files and then copy them to that folder. Then take the contents of this folder and create an archive."
While a maven pom declares what we would like to have as the result - "here are the names of the libraries the project depends upon, and we would like to generate a web archive". Maven knows how to fetch the libraries and where to find the source classes on it's own.
While ant gives you more flexibility, it also forces you to constantly reinvent the wheel.
Maven on the other side requires less configuration, but may feel too constraining, especially if you are used to a different workflow.
EDIT: An important aspect of the ant-maven comparison is that maven has a convention, describing where the files should lie, where the dependencies are found, where to put the resulting artifact, while ant does not.
So you can think of using maven like riding a bus - you select the stop where you enter and the one where you leave. Using ant is like driving a car - you have to do it yourself. You dont have to tell the bus driver what to do, but the stops may be too far from where you want to go.
EDIT2: 'Reinventing the wheel' metaphor seems to be less clear than I had hoped. This is what I mean:
Without sensible defaults/conventions, you have to define the project structure and the build lifecycle explicitly for each project, often making it a matter of taste and opinion. As preferences vary between teams and companies, so do build processes. This requires more cognitive effort for new project members and later maintainers. Depending on the experience and expertise of the developers, the final solution may be hard to extend and use.
As I said in a comment below, while best practices for ant builds exist, they still have to be implemented for each project, or copy-pasted from project to project, instead of becoming an out-of-the-box default of the build tool itself.
Maven is a bit too far on the other side of the trade-off for my taste. Changing the defaults is not as easy as it could and should be.

Is Maven mandatory for Clojure on the JVM?

I'm a bit surprised at the sheer number of articles / blogs / questions / answers about Clojure mentioning Maven.
In about ten years working as a Java dev, working on both desktop apps and webapps, I've never ever used Maven once (typically --and that's a personal opinion but I know some people do think the same-- the projects I've seen using Maven where including the "kitchen sink" whereas the ones built with a more "controlled" build process where way "cleaner" and producing smaller jars, faster build time, etc.).
Is Maven a requirement when you want to build a Clojure app?
Is Maven mandatory when you want to use Leiningen? For example, can I add external jars as dependencies to a leiningen project "manually", without needing Maven?
I think my question boils down to this: can you, in the Clojure/JVM world get away without ever using Maven, just like you can build, test, package and ship both Java desktop, webapps and Android apps without ever needing Maven?
Short answer: No. Clojure's just a jar and you can use it as "raw" as you like, just like any other Java library.
Longer answer: Maven's not a requirement, but the tooling around Clojure, especially Leiningen, is highly Maven-aligned so your life will be easier if you just submit to Maven's will. But, with a little work, it's not that hard to get along without Maven. At work, I use a mix of Leiningen and our existing Ant/Ivy-based build infrastructure. I use Ant to resolve dependencies (from our curated internal repo) and then use a hack of Leiningen's :resource-paths to get it to pick up the non-Maven jars. At some point I'll make a true plugin to do this stuff, but it's been working fine for me so far.
Also, if you're an Eclipse person and use CounterClockwise, you can treat your project like any other Java project in Eclipse, managing the classpath manually. It just happens that you've got some Clojure code in there as well.
Of course, the drawback in either approach is that if you want to grab something that's available from either Maven central or Clojars, you'll either have to set up some kind of mirror for your infrastructure, or manually pull down the transitive dependencies and add them to your project.
You do not have to use maven, or leiningen, for that matter. You can run the clojure REPL with
java -jar clojure-1.3.0.jar
and it will work just fine. I know where you're coming from, because a year ago, I was in the same boat as you. never used maven, seen a couple of less than great projects that used it poorly, and generally distrusted maven. Ant+ivy works great, who needs maven?
As a result of using leiningen, and starting a new job where we have a very well setup maven config, I've changed my tune completely; I now think maven is great, and far prefer it to ant, which I've used for a long time.
Specifically with clojure, some advantages of leiningen are:
automagic project scaffolding: "lein new" sets up a new project for you. convention is important, it helps other developers understand your project and quickly ramp up on it.
dependency and plugin management. adding a dependency is trivial, and there isn't a great way that I am aware of to do non-maven dependency management that is tightly integrated with clojure.
"lein repl" sets up your classpath and everything correctly, so you don't have to fool with it, you can just start and run a REPL.
artifact creation: building a fat jar (lein uberjar) is straightforward, and already set up for you.
So, while it's definitely possible to use clojure without leiningen, I honestly don't see why you would want to. There are too many niceities for day to day development not to use it, in my opinion.
regarding "Is Maven mandatory when you want to use Leiningen?"
leiningen uses and wraps Maven so you can't truly avoid it, though you don't ever need to touch any XML
Maven is not mandatory for Clojure as others have rightly pointed out.
However, I would like to encourage you to embrace Maven (either directly or via leiningen). It has some big advantages in the Clojure world:
You will be more productive in the long run - once you've got it set up, it is pretty impressive to see a complex build, test and deployment execute in a single command. Do you really want to be manually setting classpaths, downloading dependencies, incrementing version numbers, uploading to FTP sites etc.?
One of the biggest advantages of using Clojure on the JVM is access to the Java library ecosystem. Maven is the tool of choice for automatically managing dependencies on Java libraries. Nearly everything you are likely to need will be in either the Maven Central or Clojars repositories.
Clojure tends to have small focused libraries - this is good because they are "simple" and you can pick and choose the functionality you like. At the same time, it also means that you are likely to have numerically more library dependencies. Hence a build management system is going to be more useful.
You can make Maven builds as "lean" as you like. Obviously you can pull in every dependency under the sun if you like, but you can also create very lean jars by excluding the unnecessary cruft. That's your choice.
It is the de-facto standard in the Clojure world. If nothing else, using it means that you will be able to collaborate with others more easily.
P.S. Like you, I didn't really see the point of Maven 5 years ago. Then I gave it a go and saw how powerful it could be for my workflow. Now I'm a convert :-)

Resources