I am trying to figure out the use of Maven and I got many articles describing its features and uses. But I am just not able to understand the actual use of Maven from productivity standpoint.
From what I am used to in our school projects was just create a new Java project in Eclipse, write your Code, create a .war (if web-based) and paste the code to the webapps folder of Tomcat and start the server!
So,
Where does Maven come into picture? I have used Ant and I understand Ants benefit of a standardized build process. But why do we need an advanced Ant in form of Maven?
In any case, I need to use it, so where do I get started - basic flow, some good tutorials?
Thanks
Maven is used to manage the build, testing, and deployment processes. It can separate the unit tests and integration tests so you only run them when necessary and cut down on build time.
It is also a dependency manager, which means when you realize the server piece of your project needs apache commons-logging 1.0.4 but the client conflicts with anything past 0.7.9, you can just add a couple lines to the respective pom.xml files, and Maven handles all of that (downloading, installing, and keeping track of the different versions of those dependencies).
I was not a believer before my current task, but after 2 years using it for large enterprise applications, I definitely respect what Maven brings to the table. There are a lot of online resources but if you are going to be the lead on this and really feel uncomfortable, I recommend getting a book -- the O'Reilly one is helpful.
Forgot to mention that there is an Eclipse plugin which makes it almost painless to use with Eclipse: m2Eclipse.
Second update for example pom.xml segment to answer OP question:
Your pom.xml will contain XML code such as:
<dependencies>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.0.4</version>
<scope>provided</scope>
</dependency>
</dependencies>
These are downloaded from the central Maven repository (google "maven nexus") or you can configure your own additional repositories (like for your own projects, or if you are not Internet-connected).
I had exactly the same perception as you and for years I avoided Maven.
The thing is, it allows you to easily get the required jars your application may need( called dependencies - jars and other things - ) . So the next time somebody else run your project he will get the jars automatically.
I know that's a bit hard to grasp, until you work with an existing projects using it.
For instance I downloaded an open source project recently, which depended on 10 or 12 different on different jar versions. After downloading the source code and executing Maven, all those jars ( and a lot more others ) were downloaded for me.
The problem with Maven ( as a friend of mine told me ) is that to perform a "Hello world" program, it first downloads the world to greet him. :P
for all those wondering where the maven downloads the dependency jars, check out a folder named .m2 in the user root directory. eg. for me it is the c:\documentsand settings\myUserName.m2\
also i have researched a bit on maven and i have made some small scribbling like reminders. If it is worth a read then here it is ::
/*
mvn generate
mvn install downloads all necessary jars
mvn test tests the application made...
mvn site builds the site downloading dependencies
to deploy the site, we need to declare a location to distribute to in your pom.xml,
similar to the repository for deployment.
...
website
scp://www.mycompany.com/www/docs/project/
...
mvn site-deploy deploys the site
how to build structure of site :
The site.xml file is used to describe the layout of the site, and replaces the navigation.xml file used in Maven
A sample is given below:
Maven
http://maven.apache.org/images/apache-maven-project.png
http://maven.apache.org/
http://maven.apache.org/images/maven-small.gif
<menu name="Maven 2.0">
<item name="Introduction" href="index.html"/>
<item name="Download" href="download.html"/>
<item name="Release Notes" href="release-notes.html" />
<item name="General Information" href="about.html"/>
<item name="For Maven 1.x Users" href="maven1.html"/>
<item name="Road Map" href="roadmap.html" />
</menu>
<menu ref="reports"/>
...
so in effect, we need to link our html to this structure format to make the website layout
also in order for us to add any new css or such stuff, all we need to do is to put them into the resources part of the
src folder
then we can create a war file of our project and lay it out in the httpd folder of apache or such similar folder ofour web server
In case we need to generate projects, we need to add a few lines of code to our pom.xml file and that is:
...
org.apache.maven.plugins
maven-project-info-reports-plugin
2.0.1
...
also, site descriptors are to be set in site.xml
the details can be seen in the documentation of maven
maven structure with their importance:
project/
pom.xml - Defines the project
src/
main/
java/ - Contains all java code that will go in your final artifact.
See maven-compiler-plugin for details
scala/ - Contains all scala code that will go in your final artifact. ////not needed for our current project as of yet
See maven-scala-plugin for details
resources/ - Contains all static files that should be available on the classpath
in the final artifact. See maven-resources-plugin for details
webapp/ - Contains all content for a web application (jsps, css, images, etc.)
See maven-war-plugin for details
site/ - Contains all apt or xdoc files used to create a project website.
See maven-site-plugin for details
test/
java/ - Contains all java code used for testing.
See maven-compiler-plugin for details
scala/ - Contains all scala code used for testing.
See maven-scala-plugin for details
resources/ - Contains all static content that should be available on the
classpath during testing. See maven-resources-plugin for details
mvn validate this will validate that all the dependencies are satisfied and nothing is missing
mvn compile this will compile the project
mvn verify checks whether the package is valid or not
also in the project, the dependencies are to be inserted into the xml file
the example of dependencies injection is given below::
org.scala-lang
scala-library
2.7.2-rc2
junit
junit
3.8.1
test
Each dependency consists of several items:
* groupId - The group of the dependency to rely on
* artifactId - The artifact in the group to rely on
* version - The version of the dependency to rely on
* scope - The "scope" of the dependency. Defaults to compile (more details later)
* packaging - The packaging for the dependency. Defaults to jar (e.g. jar, war, ear)
You can integrate your static pages by following these steps:
* Put your static pages in the resources directory, ${basedir}/src/site/resources
* Create your site.xml and put it in ${basedir}/src/site
* Link to the static pages by modifying the menu section, create items and map them to the filenames of the static pages
mvn tomcat:deploy to deploy to tomcat or apache, you can go for this command
Free books about Maven can be downloaded from Sonatype (where the original developers of Maven come from).
Also see the documentation on the Apache Maven website.
Where does Maven come into picture? I
have used Ant and I understand Ants
benefit of a standardized build
process. But why do we need an
advanced Ant in form of Maven?
Maven introduced "convention over configuration" this helps if some colleagues write bigger ant scipts than code. plus dependency management, the only trouble is to convert monolithic projects with many artifacts.
In any case, I need to use it, so
where do I get started - basic flow,
some good tutorials?
I found these tutorials
And Maven: The Definitive Guide
helpful.
The latest netbeans also has a pretty good maven integration.
If you are within an organization, try to build a maven repository proxy. Artifactory is a good option.
Related
why use Maven when you have such quantity of local jars?
So we have a client that have a lot of private jars and custom jars.
For example commons-langMyCompanyCustom.jar which is commons-lang.jar with 10 more classes in it.
So on their environment we use 100% Maven without local dependencies.
But on our site we have the jars for development in Eclipse and have Maven build with the public ones, but we do not have permission to add their jars in our organizational repository.
So we want to use the Maven good things like: compile,test, build uber-jar, add static code analysis, generate java-docs, sources-jars etc. not to do this thinks one by one with the help of Eclipse.
So we have 70 jar some of them are public if I get the effective pom on their environment I found 50 of them in Maven Central, but the other 20 are as I called "custom" jars. I searched for decision of course but found this:
<dependency>
<groupId>sample</groupId>
<artifactId>com.sample</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/yourJar.jar</systemPath>
</dependency>
So for all 20 of them I have to add this in the development maven profile??
Is there a easy way like in Gradle where you can add all folder with its dependencies to the existing ones?
Also installing one by one in every developer's repo is not acceptable.
Please forget the system scope as mentioned before! Too problematic...
Ideally:
Ideally, all your developers have access to Repository Manager in your or their organization (if possible).
A central environment for your System Integration Testing, maybe?
Alternatively, you may have a central environment for testing where all the dependencies are provided. This approach can be used to simulate how a compilation would work as if it's in your client's environment. Plus you only setup jars once.
So on their environment we use 100% Maven without local dependencies.
But on our site we have the jars for development in Eclipse and have
Maven build with the public ones, but we do not have permission to add
their jars in our organizational repository.
According to what you're saying in the above-quoted excerpt I believe you want to have set in your build's pom.xml assuming that in the client setup the dependencies will be present.
Especially, as you indicate that the organization doesn't give you permission to add their jars in your repository, I would use the provided scope.
As stated in the Maven docs, the definition of a provided dependency is as followed:
This is much like compile, but indicates you expect the JDK or a container to provide the dependency at runtime. For example, when building a web application for the Java Enterprise Edition, you would set the dependency on the Servlet API and related Java EE APIs to scope provided because the web container provides those classes. This scope is only available on the compilation and test classpath, and is not transitive.
So basically you assume that these dependencies will be present at your client's setup. However, this has some limitations. Meaning you can build solutions independently but cannot test it locally because you won't have the dependencies on your workstation.
If you won't even have access to the jars to configure your central environment ask if your client can provide a DEV/SIT environment.
None of the above? Inherit a parent pom.
To avoid the whole constant copy-paste process for every single (related) project, maven has the tools to centralize dependency and plugin configurations, one of such is by inheriting the configuration of a parent pom. As is explaining in the following documentation it is quite simple:
First you create a project with just a pom.xml where you define everything you wish to centralize (watch out, certain items have slight differences in their constructs);
Use as property of packaging tag the option pom: <packaging>pom</packaging>;
In the pom's that have to inherit these configurations set the parent configuration tags in <parent> ... </parent> (documentation is very clear with this);
Now everytime you update any "global" pom configuration only the parent version has to be updated on every project. As a result of this, you only need to configure everything once.
You can also apply this together with the abovementioned solutions, this way combining to find a solution that fits best to your needs.
But there is a big Maven world out there, so I advise a good read in its doc's to further acknowledge your possibilities. I remembered these situations because I've been in a similar situation you seem to be now.
Good luck!
Another alternative is the project RepoTree.
This one creates a Maven repository directory (not a server) from another directory which contains just the .jars. In other words, it creates the necessary .pom files and directory structure. It takes into account only the precise information from metadata contained in the archives (MANIFEST.MF, pom.xml).
Utility to recursively install artifacts from a directory into a local
Maven repository Based on Aether 1.7
This is 5 years old, but still should work fine.
TL;DR: MavenHoe creates a Maven repository server (not a directory) which serves the artefacts from a directory, guessing what you ask for if needed. The purpose is to avoid complicated version synchronizing - it simply takes whatever is closest to the requested G:A:V.
I have moved the MavenHoe project, which almost got lost with the decline of Google Code, to Github. Therefore I put it here for availability in the form of a full answer:
One of the options you have when dealing with conditions like that is to take whatever comes in form of a directory with .jar's and treat it as a repository.
Some time ago I have written a tool for that purpose. My situation was that we were building JBoss EAP and recompiled every single dependency.
That resulted in thousands of .jars which were most often the same as their Central counterpart (plus security and bug fixes).
I needed the tests to run against these artifacts rather than the Central ones. However, the Maven coordinates were the same.
Therefore, I wrote this "Maven repository/proxy" which provided the artifact if it found something that could be it, and if not, it proxied the request to Central.
It can derive the G:A:V from three sources:
MANIFEST.MF
META-INF/.../pom.xml
Location of the file in the directory, in combination with a configuration file like this:
jboss-managed.jar org/jboss/man/ jboss-managed 2.1.0.SP1 jboss-managed-2.1.0.SP1.jar
getopt.jar gnu-getopt/ getopt 1.0.12-brew getopt-1.0.12-brew.jar
jboss-kernel.jar org/jboss/microcontainer/ jboss-kernel 2.0.6.GA jboss-kernel-2.0.6.GA.jar
jboss-logging-spi.jar org/jboss/logging/ jboss-logging-spi 2.1.0.GA jboss-logging-spi-2.1.0.GA.jar
...
The first column is the filename in the .zip; Then groupId (with either slashes or dots), artifactId, version, artifact file name, respectively.
Your 70 files would be listed in this file.
See more information at this page:
https://rawgit.com/OndraZizka/MavenHoe/master/docs/README.html
The project is available here.
Feel free to fork and push further, if you don't find anything better.
I am new to using github and have been trying to figure out this question by looking at other people's repositories, but I cannot figure it out. When people fork/clone repositories in github to their local computers to develop on the project, is it expected that the cloned project is complete (ie. it has all of the files that it needs to run properly). For example, if I were to use a third-party library in the form of a .jar file, should I include that .jar file in the repository so that my code is ready to run when someone clones it, or is it better to just make a note that you are using such-and-such third-party libraries and the user will need to download those libraries elsewhere before they begin work. I am just trying to figure at the best practices for my code commits.
Thanks!
Basically it is as Chris said.
You should use a build system that has a package manager. This way you specify which dependencies you need and it downloads them automatically. Personally I have worked with maven and ant. So, here is my experience:
Apache Maven:
First word about maven, it is not a package manager. It is a build system. It just includes a package manager, because for java folks downloading the dependencies is part of the build process.
Maven comes with a nice set of defaults. This means you just use the archtype plugin to create a project ("mvn archetype:create" on the cli). Think of an archetype as a template for your project. You can choose what ever archetype suits your needs best. In case you use some framework, there is probably an archetype for it. Otherwise the simple-project archetype will be your choice. Afterwards your code goes to src/main/java, your test cases go to src/test/java and "mvn install" will build everything. Dependencies can be added to the pom in maven's dependency format. http://search.maven.org/ is the place to look for dependencies. If you find it there, you can simply copy the xml snippet to your pom.xml (which has been created by maven's archetype system for you).
In my experience, maven is the fastest way to get a project with dependencies and test execution set up. Also I never experienced that a maven build which worked on my machine failed somewhere else (except for computers which had year-old java versions). The charm is that maven's default lifecycle (or build cycle) covers all your needs. Also there are a lot of plugins for almost everything. However, you have a big problem if you want to do something that is not covered by maven's lifecycle. However, I only ever encountered that in mixed-language projects. As soon as you need anything but java, you're screwed.
Apache Ivy:
I've only ever used it together with Apache Ant. However, Ivy is a package manager, ant provides a build system. Ivy is integrated into ant as a plugin. While maven usually works out of the box, Ant requires you to write your build file manually. This allows for greater flexibility than maven, but comes with the prize of yet another file to write and maintain. Basically Ant files are as complicated as any source code, which means you should comment and document them. Otherwise you will not be able to maintain your build process later on.
Ivy itself is as easy as maven's dependency system. You have an xml file which defines your dependencies. As for maven, you can find the appropriate xml snippets on maven central http://search.maven.org/.
As a summary, I recommend Maven in case you have a simple Java Project. Ant is for cases where you need to do something special in your build.
I am converting a large Java project to use maven. I have a LOT of inter dependencies to work out, but I would like to get it off the ground with maven before I do the real cleanup work. I have broken it up into a few modules plus one giant module; let's call that module monolith.
Monolith has regular Java classes and some gwt classes (with interdependencies). I separated the two parts to have a directory structure like this:
./src/main/java/...
./src/client/gwt/...
So, I can easily get this to compile in eclipse with m2eclipse, but then I can't seem to find how to get it to compile with maven. I saw that the pom file has a build section where you can specify an alternate source and target, but I think it is not a repeatable attribute in the pom:
<build>
<sourceDirectory>${basedir}/src/main/java</sourceDirectory>
</build>
In eclipse, I can adjust the project's .classpath file (in the project properties) to add additional source files (and output dirs) to accomplish what I am looking to do.
Is there any way to do this, or do I need to work out the dependencies first, and separate into separate modules?
If you go against the grain with maven it will be an uphill battle all the way.
Maven doesn't lean towards multiple main source directories, they would do better in maven environment as separate modules.
I've looked at a number of maven gwt projects and archetypes, and none of them seem to take the approach you've suggested.
Have a look at the source structure used by Hupa, also see the archetypes from the Ham and Eggs blog
http://hamandeggs.wordpress.com/2010/01/26/how-to-gae-eclipse-maven/
http://hamandeggs.wordpress.com/2010/07/25/gae-eclipse-maven-update-for-helios/
These also cater for App Engine.
If you really need to separate your java server source from your gwt client source, then monolith needs to be split into more modules.
It is quite common to see gwt projects with a package structure as follows:
com.company.project
.client
.server
.shared
And then specify the source paths in your gwt.xml to include client and shared
What you have is called a maven multi-module project. Take a look at this tutorial on the maven book.
So, I can easily get this to compile
in eclipse with m2eclipse, but then I
can't seem to find how to get it to
compile with maven.
-- I am not sure what you meant by this. M2Eclipse plugin is using maven to build your modules. Perhaps you can clarify this section. Hope the tutorial link helps you.
try to follow this tutorial http://maven.apache.org/plugins/maven-eclipse-plugin/reactor.html
main idea- start from creation of empty project from maven mvn archetype:create and then put you sources to created by maven structure...
also i can strongly recommend to check your dependency tree and effective pom with eclipse plugin tool when you perform this task (for avoid duplicate in dep. & other bad things)
I have a project I need to release the source for. The problem I have is that I need to create a source release for all code that we have developed. The code is across multiple projects, but I want to leverage maven so that only the source for the jars we are actually using is released.
For example:
core code project (multi module maven project)
web app project (multi module maven project). Contains we app module plus some supporting jar modules. Depends on some jars from core code project.
Now I want to release all the source for the web app project but only the source for the core code project that the web app uses.
Can I do this with maven?
I have a feeling it is possible with assembly plugin and source plugin but it is not clear to me how to put this together.
First of all your question is bit unclear. let me assume certain things and proceed.
I believe that following is your folder structure.
web app project
some source code folder
pom.xml
core code project
some source code folder
pom.xml
Take the core code project and change the version from previous version in pom.xml.
let 's say if it was 1.0 change it to 1.1
<groupId>core code project related</groupId>
<artifactId>core code project</artifactId>
<name>core code</name>
<version>1.1</version>
Make your changes to accomodate the web app project in core code project.
later,
in web app project add dependency for core code project in pom.xml
<dependency>
<groupId>core code project related</groupId>
<artifactId>core code project</artifactId>
<name>core code</name>
<version>1.1</version>
</dependency>
In this way, 1.1 version of core project will have only web app related code.
Currently we are using this method. Hope it helps. let me know if you want something else.
I have a feeling it is possible with assembly plugin and source plugin but it is not clear to me how to put this together.
If I understood the question correctly, one solution would be to create an "aggregator" project listing all wanted modules (the relevant modules from the webapp and the relevant modules from the core) and to use the source:aggregate goal from the Maven Source Plugin.
I'm unsure why you want to do this, the pom from your web app project will explicitly list the versions of your code dependencies used, so you can find the source easily. It sounds like you want to store the same artifact twice. So if your web app uses core-x-1.2.3.jar and core-y-4.5.6.jar you would produce a web app sources artifact containing the source from both those core jars in addition to the actual web app source?
You can use the maven versions plugin to update your web app pom to use the latest versions of your core dependencies, I've automated that by running a shell script in a CI server in the past. That means whenever you release a new version of your web app you will be using the latest release of your core code, and all you need to do is update your web app pom from version control.
I'm in the process of learning maven (and java packaging & distribution) with a new oss project I'm making as practice. Here's my situation, all java of course:
My main project is ProjectA, maven-based in a github repository. I have also created one utility project, maven-based, in github: ProjectB. ProjectA depends on a project I have heavily modified that originally was from a google-code ant-based repository, ProjectC.
So, how do I set up the build for ProjectA such that someone can download ProjectA.jar and use it without needing to install jars for ProjectB and ProjectC, and also how do I set up the build such that someone could check out ProjectA and run only 'mvn package' for a full compile?
(Additionally, what should I do with my modified version of ProjectC? include the class files directly into ProjectA, or fork the project into something that could then be used by as a maven dependency?)
I've been reading around, links such as this SO question and this SO question, but I'm unclear how those relate to my particular circumstance. So, any help would be appreciated. Thanks!
So, how do I set up the build for ProjectA such that someone can download ProjectA.jar and use it without needing to install jars for ProjectB and ProjectC
Assuming ProjectA is a JAR, you can create an executable JAR that bundles the dependencies with the Maven Assembly Plugin (and the predefined jar-with-dependencies descriptor) or with the Maven Shade Plugin.
how do I set up the build such that someone could check out ProjectA and run only 'mvn package' for a full compile?
You have to deploy the dependencies to a repository that can be read over HTTP and to declare this repository in your pom.xml. AFAIK, git-hub doesn't offer any facility for that. But any web hosting service with FTP access (or better, scp) should do the trick. If your project is open source, another option would be to use Sonatype's OSS Repository Hosting service.
Just in case, you might want to read this blog post but you won't learn much more things.
The easiest would still be to organize the 3 projects as a multi-modules maven project and to build all modules.
Additionally, what should I do with my modified version of ProjectC?
From a modularization point of view (assuming you found a solution for the above part about repository), it would certainly make sense to have it as a separate module, especially if there is an opportunity someone can use ProjectC outside your project.
You have to publish the code from the additional dependencies. Two options:
Use the maven-shade-plugin to create a maven artifact containing all the content of the B and C jars, and publish that under your own G/A/V coordinates.
Publish copies of B and C under your own G/A/V coordinates using the maven-deploy-plugin to your forge just as you will publish your own code. Different forges have different policies; but if you abide by the licenses of B and C you should be OK.