The problem: You want Maven to stop making all those network calls when you issue it commands like clean, build, test, package etc. You might want to work on a project while you have no network connection.
The solution: You can use the off line mode for Maven to keep it from making any network calls. You can do so by issuing the -o flag to the mvn command. When using this mode Maven will need to have all the jars it needs in your local repository (~/.m2/repository by default). To make this easier you can use a trick provided by the dependency plugin. Imagine we just checked out a project. Now we want to work on this project off line. To get all the dependencies needed by the project you can issue the command "mvn dependency:go-offline". This will download the dependencies you need. Now note it will not make sure you have all the plugins you need. Say you want to run "mvn -o site:run", creating a site for your project and making it available via Jetty. You will need to have used this plugin before so that it is in your local repo. The same goes for compile, package, test and the like.
The million dollar question is why use off line mode? Well it could be that it makes quicker the process you are doing with Maven, since Maven will not try to call out to any network repos. I've timed the difference between using it and not using it for some fairly large projects and found it doesn't make a huge difference. For really big projects (I cannot really name one) it might shed enough seconds to make it worth using often, maybe even creating an alias. This 'huge' project mind you would probably have upwards of 200 jar (dependencies) or more being managed. Another reason one might use off line is as follows: you have a local network repository used by the developers at work. One day the person you administers this repository is going to move it somewhere new. This going to take a few hours. Using off line mode you could weather this time if prepared without noticing too much that the repository is down. This could also be helpful in situations where you are going to not be able to reach the repository, like working at home with no network connection, or the server hosting the repo crashed.
Showing posts with label tricks. Show all posts
Showing posts with label tricks. Show all posts
Thursday, December 20, 2007
Sunday, December 16, 2007
Using Maven for Bash Script Projects
I recently created a Maven project unlike any I have ever created. This project contained no Java sources! No it was not a Groovy project ;) It was a project that contained only bash scripts. Read up for the why and the how.
I created a set of bash scripts that allow invoking SOAP services, returning the XML response. The SOAP services provide information on email distribution lists, such as which addresses are on a list and which lists a user's email address is subscribed to. These scripts are likely to change and grow over time so I made sure to put them into Subversion. Not too shabby. But what about distributing the scripts? What about managing versions of the scripts? I have become accustomed to having the aforementioned handled in my projects via Maven. Maven makes such things simple to set up and automate. I determined I could move these bash scripts into a Maven project to cultivate these benefits.
Now the how. For packaging I use the Maven assembly plugin. It allows created automated creation of zip tar.gz and gzip archives. These archives work great work distributing a project. I started my work by creating a skeleton Maven project. I put the scripts and related files into the src/main/scripts folder of the project. Next I created a xml file used by the assembly plugin to direct how files will be structured in the created compressed archive or archives. Here my file:
I'll write up a more thorough article on using the assembly plugin later. For now suffice to say this file will instruct Maven to create a zip archive containing the files listed above. The last thing we want to do is configure the assembly plugin in the project's POM file. I used the following XML in my projects pom:
In the above config I also bind the assembly goal to the package phase. This means when I execute "mvn package" the assembly plugin will fire off and create the zip archive. Nice! Otherwise you can also use "mvn assembly:assembly" should do the job. Now so that I could use the scm and release plugins to check in changes to SVN and create tagged releases of the project I added the following to the POM:
Now to release the current version of the project I can type "mvn release:prepare". This will tag the current version in SVN, then update the POM to the new version number and check those changes into the SVN trunk. This saves me the hassle and reduces the chances of user error in this boring, repetitive process. In the vein of the SCM configuration you could now use other plugins such as the JIRA reporting plugin, site plugin etc. to bolster this simple bash script project.
I created a set of bash scripts that allow invoking SOAP services, returning the XML response. The SOAP services provide information on email distribution lists, such as which addresses are on a list and which lists a user's email address is subscribed to. These scripts are likely to change and grow over time so I made sure to put them into Subversion. Not too shabby. But what about distributing the scripts? What about managing versions of the scripts? I have become accustomed to having the aforementioned handled in my projects via Maven. Maven makes such things simple to set up and automate. I determined I could move these bash scripts into a Maven project to cultivate these benefits.
Now the how. For packaging I use the Maven assembly plugin. It allows created automated creation of zip tar.gz and gzip archives. These archives work great work distributing a project. I started my work by creating a skeleton Maven project. I put the scripts and related files into the src/main/scripts folder of the project. Next I created a xml file used by the assembly plugin to direct how files will be structured in the created compressed archive or archives. Here my file:
<?xml version="1.0"?>
<assembly>
<id>zimbrascripts</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<outputDirectory>hacksdb/lib</outputDirectory>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>src/main/scriptapp/bin</directory>
<outputDirectory>zimbrascripts/bin</outputDirectory>
<fileMode>0755</fileMode>
<directoryMode>0755</directoryMode>
</fileSet>
<fileSet>
<directory>src/main/scriptapp/etc</directory>
<outputDirectory>zimbrascripts/etc</outputDirectory>
<fileMode>0644</fileMode>
<directoryMode>0755</directoryMode>
</fileSet>
<fileSet>
<directory>src/main/scriptapp/tokens</directory>
<outputDirectory>zimbrascripts/tokens</outputDirectory>
<fileMode>0600</fileMode>
<directoryMode>0777</directoryMode>
</fileSet>
<fileSet>
<directory>src/main/scriptapp/xml</directory>
<outputDirectory>zimbrascripts/xml</outputDirectory>
<fileMode>0644</fileMode>
<directoryMode>0755</directoryMode>
</fileSet>
</fileSets>
<files>
<file>
<source>src/main/scriptapp/README.txt</source>
<outputDirectory>zimbrascripts</outputDirectory>
</file>
</files>
</assembly>
I'll write up a more thorough article on using the assembly plugin later. For now suffice to say this file will instruct Maven to create a zip archive containing the files listed above. The last thing we want to do is configure the assembly plugin in the project's POM file. I used the following XML in my projects pom:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make</id>
<phase>package</phase>
<goals>
<goal>assembly</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
In the above config I also bind the assembly goal to the package phase. This means when I execute "mvn package" the assembly plugin will fire off and create the zip archive. Nice! Otherwise you can also use "mvn assembly:assembly" should do the job. Now so that I could use the scm and release plugins to check in changes to SVN and create tagged releases of the project I added the following to the POM:
<scm>
<connection>scm:svn:https://svn.com/DistributionLists/DistListScriptsMaven/trunk/</connection>
<developerConnection>scm:svn:https://svn.com/DistributionLists/DistListScriptsMaven/trunk/</developerConnection>
<url>https://svn.com/DistributionLists/DistListScriptsMaven/</url>
</scm>
Now to release the current version of the project I can type "mvn release:prepare". This will tag the current version in SVN, then update the POM to the new version number and check those changes into the SVN trunk. This saves me the hassle and reduces the chances of user error in this boring, repetitive process. In the vein of the SCM configuration you could now use other plugins such as the JIRA reporting plugin, site plugin etc. to bolster this simple bash script project.
Saturday, December 1, 2007
Big Project Troubleshooting Pt. 1: Transitive Dependencies
Maven is complex, but so is Ant or Make once a project passes a certain size. With Maven many things are done in a standard way, so that when a project becomes large you still should be able to work with it easily. With Ant or Make a large project will likely have many arbitrarily named targets which you will have to study and learn. With Maven all those named targets are pretty much standardized by the plugins which provide all functionality. Large projects in Maven commonly have the same sorts of issues. These can be pretty nasty to for the uninitiated. So to help you out I'm going to write a series of articles tackling the problems faced in big Maven projects. In this article I'm going to give you some information on issues related to dependencies.
The dependency mechanism is the main reason many people become interested in Maven. It sure makes life easy... but everything cannot always be automated. Sometimes you will need to give Maven some help. It will try to correctly resolve the dependencies needed by your project by creating a graph. More on this in a second.
Maven has what is called a 'transitive dependency'. Let me explain transitive dependencies for those who don't know. A dependency of a project is defined via a project's pom.xml. Every dependency has a pom.xml (in the repository with the dependency) which is used by Maven to find the dependencies relied upon by a dependency. These 'relied upon' dependencies are also known as transitive dependencies. They are included into your projects class path automatically. Now you can have any number of levels of transitive dependencies because Maven also will get the each transitive dependency's dependencies. In Maven this forms what is called the dependency graph. Yes this is the same graph I spoke of earlier. It looks like a tree, with your project as the root node, tree level one as the dependencies of your project and subsequent levels being transitive dependencies.
Now lets talk about the sticky points. If there are two or more versions of the same dependency in the graph of the dependencies for your project then Maven will need to make a choice as to which one to use. By default Maven will use the version that is the closest to the top node of the tree. If this version is older than the other version(s) you may have a problem. Likely a NoClassDef where a class from the new dependency cannot be found, because it does not exist in the older version. When you get this error it should be obvious which dependency the error is being caused by. The stack trace should give the full package path to the class. We can use this to figure out how to fix the problem.
At this time you probably could open a terminal session and cd to your local repository location (~/.m2/repository by default) and then cd into the dependency's folder in the repository. This can be helpful since it will allow you to see which versions of the dependency are being used and which classes are in each dependency. You could execute a "jar -tf {jarname} | grep {ClassName}" command on each jar to search it for the given class.
Let us discuss troubleshooting. First you will want to run the mvn dependency:resolve command. This will print out a listing of the resolved dependencies for your project. Resolved dependencies are those calculated by Maven via the dependency graph to be used in the project. You should be able to see which version of the troubled dependency is being used. I had you cd to the dependencies repo location. Check now which versions you have in your repository. You should be able to use the "jar -tf" command to check if the class causing the NoClassDef exists in one of the newer version jars (if you have newer version jars). Once you have found a jar that contains the class make note of the version.
Now for some debugging. This is where you get waist deep in it. We are going to use the -X option to Maven, which enables debugging. We also want to run just the compile phase which will give us all the info we need on the dependency graph. You might want to do something like "mvn -X compiler:compile > junk.txt" just so that you can use a text editor like Vi to search about the file. Now when you view this output you will be able to find a listing of the absolute classpath, including with jars are being used. You also will get a printout of the dependency graph including info on what ended up making it in. It is pretty easy to find the version of a dependency being used: find the one with the least amount of indent. If one or more versions share the least amount of indent then the newest version will be selected.
To get around version problems you can do a number of things. The easiest thing to do is define the newer version of the dependency directly in the pom.xml of the project. This will make sure that the newer version is used because it is 1) at the top of the dependency tree 2) the version is highest. You can also use excludes for a dependency definition in the pom.xml file for the old version of the dependency. Since the old version is excluded the newer (yet further down the graph) version will be used. When using excludes you will need to figure out which dependency in the pom.xml file has the transitive dependency to be excluded. Neither of these fixes are tough to perform, and will become easy to do in time.
The dependency mechanism is the main reason many people become interested in Maven. It sure makes life easy... but everything cannot always be automated. Sometimes you will need to give Maven some help. It will try to correctly resolve the dependencies needed by your project by creating a graph. More on this in a second.
Maven has what is called a 'transitive dependency'. Let me explain transitive dependencies for those who don't know. A dependency of a project is defined via a project's pom.xml. Every dependency has a pom.xml (in the repository with the dependency) which is used by Maven to find the dependencies relied upon by a dependency. These 'relied upon' dependencies are also known as transitive dependencies. They are included into your projects class path automatically. Now you can have any number of levels of transitive dependencies because Maven also will get the each transitive dependency's dependencies. In Maven this forms what is called the dependency graph. Yes this is the same graph I spoke of earlier. It looks like a tree, with your project as the root node, tree level one as the dependencies of your project and subsequent levels being transitive dependencies.
Now lets talk about the sticky points. If there are two or more versions of the same dependency in the graph of the dependencies for your project then Maven will need to make a choice as to which one to use. By default Maven will use the version that is the closest to the top node of the tree. If this version is older than the other version(s) you may have a problem. Likely a NoClassDef where a class from the new dependency cannot be found, because it does not exist in the older version. When you get this error it should be obvious which dependency the error is being caused by. The stack trace should give the full package path to the class. We can use this to figure out how to fix the problem.
At this time you probably could open a terminal session and cd to your local repository location (~/.m2/repository by default) and then cd into the dependency's folder in the repository. This can be helpful since it will allow you to see which versions of the dependency are being used and which classes are in each dependency. You could execute a "jar -tf {jarname} | grep {ClassName}" command on each jar to search it for the given class.
Let us discuss troubleshooting. First you will want to run the mvn dependency:resolve command. This will print out a listing of the resolved dependencies for your project. Resolved dependencies are those calculated by Maven via the dependency graph to be used in the project. You should be able to see which version of the troubled dependency is being used. I had you cd to the dependencies repo location. Check now which versions you have in your repository. You should be able to use the "jar -tf
Now for some debugging. This is where you get waist deep in it. We are going to use the -X option to Maven, which enables debugging. We also want to run just the compile phase which will give us all the info we need on the dependency graph. You might want to do something like "mvn -X compiler:compile > junk.txt" just so that you can use a text editor like Vi to search about the file. Now when you view this output you will be able to find a listing of the absolute classpath, including with jars are being used. You also will get a printout of the dependency graph including info on what ended up making it in. It is pretty easy to find the version of a dependency being used: find the one with the least amount of indent. If one or more versions share the least amount of indent then the newest version will be selected.
To get around version problems you can do a number of things. The easiest thing to do is define the newer version of the dependency directly in the pom.xml of the project. This will make sure that the newer version is used because it is 1) at the top of the dependency tree 2) the version is highest. You can also use excludes for a dependency definition in the pom.xml file for the old version of the dependency. Since the old version is excluded the newer (yet further down the graph) version will be used. When using excludes you will need to figure out which dependency in the pom.xml file has the transitive dependency to be excluded. Neither of these fixes are tough to perform, and will become easy to do in time.
Monday, July 2, 2007
Setting Command Line Arguments for JVM in Maven
The problem:
You want to set JVM args for the Maven application (such heap memory).
The solution:
On a Linux/Unix machine the "mvn" command will use a shell variable "MAVEN_OPTS" to pass in options. This is useful if you want to give Maven more memory. In your .profile or .bash_profile put a line like this in:
You want to set JVM args for the Maven application (such heap memory).
The solution:
On a Linux/Unix machine the "mvn" command will use a shell variable "MAVEN_OPTS" to pass in options. This is useful if you want to give Maven more memory. In your .profile or .bash_profile put a line like this in:
export MAVEN_OPTS=-Xmx1024mNow every time you run "mvn" you will have up to 1024 megs of heap space! Use this to set other JVM arguments.
Run a specific test
The problem:
You have a group of unit tests that you run through the Maven Surefire plugin. You do not want Surefire to run all the tests, rather you want only one specific test to run.
The solution:
This one is easy, all you need to do is put a little something into your command to tell the Surefire plugin "run just this one test". What does this look like? Here is an example: "mvn -Dtest=FunTest package". Here you want to package your applicaiton, but you are going to run the FunTest first. Notice you don't put a ".java" or ".class" extension onto the name. Thats it, you can use the "-Dtest=..." to run a single test anytime that the Surefire plugin will be run.
You have a group of unit tests that you run through the Maven Surefire plugin. You do not want Surefire to run all the tests, rather you want only one specific test to run.
The solution:
This one is easy, all you need to do is put a little something into your command to tell the Surefire plugin "run just this one test". What does this look like? Here is an example: "mvn -Dtest=FunTest package". Here you want to package your applicaiton, but you are going to run the FunTest first. Notice you don't put a ".java" or ".class" extension onto the name. Thats it, you can use the "-Dtest=..." to run a single test anytime that the Surefire plugin will be run.
Import Maven Project into Eclipse w/ Style (Maven + Eclipse pt. 3)
The problem:
You have a Maven 2 project, and would like to work on it in Eclipse. Oh, and you want the Maven plug in for Eclipse configured on this project too!
The solution:
The first thing I do when I check out a Maven project is generate the Eclipse project files. Start by going to the project's root folder and typing:
This will create the files Eclipse uses to understand the project, .project and .classpath. There are links to the jars configured via the pom in the .classpath file. You will want to get rid of these, because the Maven plug in will handle dependency configuration. Go into the .classpath file and delete all "classpathentry" nodes that have "M2_REPO" in the path attribute value. Now save this file.
At this point your project should have errors. Eclipse cannot find the jars needed to build properly. Worry not. Now we will enable the Maven plug in. Right click on the project root node in the package explorer to bring up the menu. Select "Maven" and then "enable". After a bit of processing your project should rebuild. Now you have the benefits of the Maven plug in!
You have a Maven 2 project, and would like to work on it in Eclipse. Oh, and you want the Maven plug in for Eclipse configured on this project too!
The solution:
The first thing I do when I check out a Maven project is generate the Eclipse project files. Start by going to the project's root folder and typing:
mvn eclipse:eclipse
This will create the files Eclipse uses to understand the project, .project and .classpath. There are links to the jars configured via the pom in the .classpath file. You will want to get rid of these, because the Maven plug in will handle dependency configuration. Go into the .classpath file and delete all "classpathentry" nodes that have "M2_REPO" in the path attribute value. Now save this file.
At this point your project should have errors. Eclipse cannot find the jars needed to build properly. Worry not. Now we will enable the Maven plug in. Right click on the project root node in the package explorer to bring up the menu. Select "Maven" and then "enable". After a bit of processing your project should rebuild. Now you have the benefits of the Maven plug in!
Labels:
eclipse,
eclipse plugin,
integration,
intermediate,
maven + eclipse,
tricks
Generate Website and View It Locally
The problem:
You are using Maven to create documentation on your project. You want to use the site plug in to generate this documentation into a website. What you need is a quick way to proof your changes, seeing how they look on the website.
The solution:
This one blew me away. When you are working on your documentation you can easily view changes, just run this command:
If a project is configured with the Javadoc report there are some nice uses here. you can pop up a site while working on a project and view the Javadoc. This is a useful technique when first checking out a project, so that you may better familiarize yourself with it.
You are using Maven to create documentation on your project. You want to use the site plug in to generate this documentation into a website. What you need is a quick way to proof your changes, seeing how they look on the website.
The solution:
This one blew me away. When you are working on your documentation you can easily view changes, just run this command:
mvn site:runThis will get a Jetty web server going with your web site running on it. Now just go to localhost:8080 to see your site. This technique is really helpful when configuring reports, as you can quickly test them out.
If a project is configured with the Javadoc report there are some nice uses here. you can pop up a site while working on a project and view the Javadoc. This is a useful technique when first checking out a project, so that you may better familiarize yourself with it.
Monday, June 25, 2007
Dependency Management, WTF?
The problem:
You want to standardize versions of a set of dependencies used in a group of project.
The solution:
A set of projects may use a given dependency. I know that I often use both Hibernate 3.x and Spring 2.x in my projects. It can make a lot of sense to use the same versions of dependencies across multiple projects. This may be especially important when you have a set of projects that are very closely related, maybe with dependencies to one another. Enter the dependency management function of the Maven pom. I put WTF in the title because thats what I thought when I discovered this feature for myself. It really is a well thought addition to the Maven platform.
So how do you do this? First you will want to put a dependency management section in a pom. Likely this is a parent pom which is inherited by many projects, otherwise what is the point? I MEAN DEPENDENCY MANAGEMENT IS MEANT FOR MANAGING DEPENDENCIES ACROSS MANY POMS. Sorry that was the main point you should take away from this session.
Here is what the dependency management section will look like:
So that will set the version of the shown spring artifact to 2.1. Now how will this make a difference? You will not include a version when adding this dependency in a project which has this dependency management section. You will simply add this dependency config:
It is pretty simple, Eh? Also note that when you want to upgrade to a new version of a dependency it is as simple as changing the version in the parent pom's dependency management section. Hows that for simple management of your dependencies?
You want to standardize versions of a set of dependencies used in a group of project.
The solution:
A set of projects may use a given dependency. I know that I often use both Hibernate 3.x and Spring 2.x in my projects. It can make a lot of sense to use the same versions of dependencies across multiple projects. This may be especially important when you have a set of projects that are very closely related, maybe with dependencies to one another. Enter the dependency management function of the Maven pom. I put WTF in the title because thats what I thought when I discovered this feature for myself. It really is a well thought addition to the Maven platform.
So how do you do this? First you will want to put a dependency management section in a pom. Likely this is a parent pom which is inherited by many projects, otherwise what is the point? I MEAN DEPENDENCY MANAGEMENT IS MEANT FOR MANAGING DEPENDENCIES ACROSS MANY POMS. Sorry that was the main point you should take away from this session.
Here is what the dependency management section will look like:
<dependencyManagement>
<dependencies>
<dependency>
<groupdId>org.springframework</groupId>
<artifactId>spring</artifactId>
<version>2.1</version>
</dependency>
<dependencies>
</dependencyManagement>
So that will set the version of the shown spring artifact to 2.1. Now how will this make a difference? You will not include a version when adding this dependency in a project which has this dependency management section. You will simply add this dependency config:
<dependency>
<groupdId>org.springframework</groupId>
<artifactId>spring</artifactId>
</dependency>
It is pretty simple, Eh? Also note that when you want to upgrade to a new version of a dependency it is as simple as changing the version in the parent pom's dependency management section. Hows that for simple management of your dependencies?
Maven Plugin for Generating Eclipse projects (Maven + Eclipse Pt. 1)
The problem:
You want to use the ubiquitous IDE, Eclipse, with your Maven project.
The solution:
Just because you use Maven doesn't mean that you are going to jump through hoops to make it work with Eclipse; all you need to do is type "mvn eclipse:eclipse". This command will generate the .classpath and .project files that Eclipse needs so that it can understand your project.
Once you run this command in your project boot up Eclipse and click File -> import -> General -> Existing projects into workspace -> next, now use the enabled browse button to find the project's root directory. Once you do this click OK. You should see your project in the projects window. Make sure it is selected and press the "Finish" button.
Right now you probably see all sorts of errors. LOL. One last thing. You must create an Eclipse classpath variable that points to your local Maven repository. Click the following: "Window -> Preferences... -> Java -> Build Path -> Classpath Variables". You now shall click "new" button and create a variable with name "M2_REPO" and value being where your local Maven repo is found. Usually this is ${HOME_DIR}/.m2/repository. On my OS X machine this is "/Users/ottaway/.m2/repository". On my Windows machine it is "C:\Documents and Settings\rob\.m2\repository". Once you set this press the "OK" button.
Your projects dependencies should now be loaded. Note that if you add new dependencies to your project you will need to run the "mvn eclipse:eclipse" command again. This will regenerate the .classpath file that contains the dependencies.
You want to use the ubiquitous IDE, Eclipse, with your Maven project.
The solution:
Just because you use Maven doesn't mean that you are going to jump through hoops to make it work with Eclipse; all you need to do is type "mvn eclipse:eclipse". This command will generate the .classpath and .project files that Eclipse needs so that it can understand your project.
Once you run this command in your project boot up Eclipse and click File -> import -> General -> Existing projects into workspace -> next, now use the enabled browse button to find the project's root directory. Once you do this click OK. You should see your project in the projects window. Make sure it is selected and press the "Finish" button.
Right now you probably see all sorts of errors. LOL. One last thing. You must create an Eclipse classpath variable that points to your local Maven repository. Click the following: "Window -> Preferences... -> Java -> Build Path -> Classpath Variables". You now shall click "new" button and create a variable with name "M2_REPO" and value being where your local Maven repo is found. Usually this is ${HOME_DIR}/.m2/repository. On my OS X machine this is "/Users/ottaway/.m2/repository". On my Windows machine it is "C:\Documents and Settings\rob\.m2\repository". Once you set this press the "OK" button.
Your projects dependencies should now be loaded. Note that if you add new dependencies to your project you will need to run the "mvn eclipse:eclipse" command again. This will regenerate the .classpath file that contains the dependencies.
Labels:
eclipse,
eclipse plugin,
intermediate,
maven + eclipse,
plugins,
tricks
Exclude Transitive Dependencies
The problem:
You have a dependency in your project, that brings with it other dependencies. Some of these you do not want added to your project.
The solution:
First off if you don't know, transitive dependencies are those which are depended on by dependencies in your project. If you have dependency A in your pom, and it depends on dependencies B and C, then B and C are referred to as transitive dependencies. If B relies on D then it will also be referred to as a transitive dependency. In this scenario dependencies A, B, C and D are added to your project.
What if you load a newer version of B? Now you have two versions of B in your project. This may cause you pain. Well worry not. You can easily exclude dependency B from your project. Just use this example, but plug in your dependency details and those of the transitive dependency to exclude:
There you go, thats all there is to it! Note that you likely will not have to do this all too often, but it's good to know what to do when you experience this problem.
You have a dependency in your project, that brings with it other dependencies. Some of these you do not want added to your project.
The solution:
First off if you don't know, transitive dependencies are those which are depended on by dependencies in your project. If you have dependency A in your pom, and it depends on dependencies B and C, then B and C are referred to as transitive dependencies. If B relies on D then it will also be referred to as a transitive dependency. In this scenario dependencies A, B, C and D are added to your project.
What if you load a newer version of B? Now you have two versions of B in your project. This may cause you pain. Well worry not. You can easily exclude dependency B from your project. Just use this example, but plug in your dependency details and those of the transitive dependency to exclude:
<dependency>
<groupId>group-a</groupId>
<artifactId>A</artifactId>
<version>2.0</version>
<exclusions>
<exclusion>
<groupId>group-b</groupId>
<artifactId>B</artifactId>
</exclusion>
</exclusions>
</dependency>
There you go, thats all there is to it! Note that you likely will not have to do this all too often, but it's good to know what to do when you experience this problem.
Friday, June 15, 2007
Do Not Test!!!
The problem:
You would like to skip unit testing when using Maven.
The solution:
You can very easily tell Surefire, the plugin in Maven that handles testing, to not run tests. All you need to do is specify the system property 'maven.test.skip. Here is an example:
The above command will clean and package your project and will do so without running your tests. This is a very useful command in Maven. It comes in especially handy when trying to build someone else's project that contains non-portable test that run by default. These may keep you from building their project. Use this command to build the project and maybe install or deploy it.
You would like to skip unit testing when using Maven.
The solution:
You can very easily tell Surefire, the plugin in Maven that handles testing, to not run tests. All you need to do is specify the system property 'maven.test.skip. Here is an example:
mvn -Dmaven.test.skip clean package
The above command will clean and package your project and will do so without running your tests. This is a very useful command in Maven. It comes in especially handy when trying to build someone else's project that contains non-portable test that run by default. These may keep you from building their project. Use this command to build the project and maybe install or deploy it.
Monday, June 4, 2007
Output Your Effective Pom to disk
The problem:
You would like to have a copy of the effective pom file used in your project. The effective pom is your current projects pom merged with any inherited poms.
The solution:
If you have read the post "Seeing the Big Picture with Inherited Poms" you know that by type "mvn help:effective-pom" a copy of the effective pom will be outputted to your screen. This is nice but what if you want a copy of this on file? Maybe you would like to attach it to an email, or use it to cut and paste together a new file. Well Maven has this one covered. Use the following command
is the name of the file you would like the effective pom written to.
You would like to have a copy of the effective pom file used in your project. The effective pom is your current projects pom merged with any inherited poms.
The solution:
If you have read the post "Seeing the Big Picture with Inherited Poms" you know that by type "mvn help:effective-pom" a copy of the effective pom will be outputted to your screen. This is nice but what if you want a copy of this on file? Maybe you would like to attach it to an email, or use it to cut and paste together a new file. Well Maven has this one covered. Use the following command
mvn -Doutput=Where <filename><filename> help:effective-pom
Saturday, June 2, 2007
Seeing the Big Picture with Inherited Poms
The problem:
You have a child pom that inherits from a parent pom, which may inherit from another and then some. You are not sure exactly what all is going on in the child pom.
The solution:
When you use inheritance in a pom it makes life easier. You don't need to know about all the stuff that was defined in the higher level POM, it just works. Then there are times when you get into some fancy Maven configuration and you really need to troubleshoot a problem that could be inheritance related. This one is dirt simple:
By typing this on the command line you can get the full configuration that is being used in your project. This is done by merging all the parent configuration with your projects configuration, and then displaying it in the terminal.
You have a child pom that inherits from a parent pom, which may inherit from another and then some. You are not sure exactly what all is going on in the child pom.
The solution:
When you use inheritance in a pom it makes life easier. You don't need to know about all the stuff that was defined in the higher level POM, it just works. Then there are times when you get into some fancy Maven configuration and you really need to troubleshoot a problem that could be inheritance related. This one is dirt simple:
mvn help:effective-pom
By typing this on the command line you can get the full configuration that is being used in your project. This is done by merging all the parent configuration with your projects configuration, and then displaying it in the terminal.
Maven 2 + Hibernate + HSQLDB (project contained integration testing for Hibernate)
The problem:
You must check your Hibernate objects against a database for testing purposes. This database is somewhere on your network, and accessible to many of your fellow co-workers. You cannot expect anything to stay static in this db, which means eventually your tests will fail.
A solution:
Maven can make projects very portable. Hibernate makes working with persistent objects simple. HSQLDB is a Java database that you can run embeded in other programs.
A problem with using Hibernate is it can take away some of the portability of your project. This happens because you must provide a database for making your objects persistent. In doing so your test configuration files will be spec'd to a single database. What happens when someone runs the project's tests and does not have access to the test database? The tests will fail :( We want to have unit tests be used for all our hibernate objects. It is especially important to thoroughly test them, as they will be a central part of your projects functioning properly (especially web projects!).
Luckily Maven makes it easy to use one database for testing, and another for production. This is where HSQLDB can come in handy. You can create a hibernate config just for testing which connects to an in memory HSQL database. You will need the proper files in src/test/resources folder of your Maven 2 project. The files include the test version of your hibernate config file. I put the hibernate mapping files into folders that mirror the packaging of the POJO object classes. When you run '
So you can see that there are a hibernate configuration file for the build and the test phase. Now in the test hibernate.cfg.xml file you will need to have the following properties set:
These entries should have you now set up to use a in memory database for all your testing with hibernate. But before this will work you need to do one more thing.
Set up you Maven 2 project so that HSQLDB is a dependency. Added this dependency section to your project:
Note that you will not need to make any specific JDBC driver available. The HSQLDB dependency contains the proper driver!
Using this recipe you will be able to make very portable Maven/Hibernate projects. Users any place in the world will be able to check out your project and test it immediately. If they would like to test using their own database it is not hard for them to overwrite what is in the src/test/hibernate.cfg.xml file.
You must check your Hibernate objects against a database for testing purposes. This database is somewhere on your network, and accessible to many of your fellow co-workers. You cannot expect anything to stay static in this db, which means eventually your tests will fail.
A solution:
Maven can make projects very portable. Hibernate makes working with persistent objects simple. HSQLDB is a Java database that you can run embeded in other programs.
A problem with using Hibernate is it can take away some of the portability of your project. This happens because you must provide a database for making your objects persistent. In doing so your test configuration files will be spec'd to a single database. What happens when someone runs the project's tests and does not have access to the test database? The tests will fail :( We want to have unit tests be used for all our hibernate objects. It is especially important to thoroughly test them, as they will be a central part of your projects functioning properly (especially web projects!).
Luckily Maven makes it easy to use one database for testing, and another for production. This is where HSQLDB can come in handy. You can create a hibernate config just for testing which connects to an in memory HSQL database. You will need the proper files in src/test/resources folder of your Maven 2 project. The files include the test version of your hibernate config file. I put the hibernate mapping files into folders that mirror the packaging of the POJO object classes. When you run '
mvn package' the .hbm files will be placed in the same folder as the POJO class they belong to. Here is an example of my Maven 2 project's structure:/project
pom.xml
...other files
/src
/main
/java
/some
/package
Foo.java
/resources
hibernate.cfg.xml
/some
/package
Foo.hbm.xml
/test
/java
/some
/testpackage
TestFoo.java
/resources
hibernate.cfg.xm
So you can see that there are a hibernate configuration file for the build and the test phase. Now in the test hibernate.cfg.xml file you will need to have the following properties set:
<!-- Database connection settings -->
<!-- HSQL DB -->
<property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
<property name="connection.url">jdbc:hsqldb:mem:aname</property>
<property name="connection.username">sa</property>
<property name="connection.password"></property>
and...
<property name="dialect">org.hibernate.dialect.HSQLDialect</property>
<mapping resource="some/package/Foo.hbm.xml" />
These entries should have you now set up to use a in memory database for all your testing with hibernate. But before this will work you need to do one more thing.
Set up you Maven 2 project so that HSQLDB is a dependency. Added this dependency section to your project:
<dependency>
<groupId>hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>1.8.0.1</version>
</dependency>
Note that you will not need to make any specific JDBC driver available. The HSQLDB dependency contains the proper driver!
Using this recipe you will be able to make very portable Maven/Hibernate projects. Users any place in the world will be able to check out your project and test it immediately. If they would like to test using their own database it is not hard for them to overwrite what is in the src/test/hibernate.cfg.xml file.
Subscribe to:
Posts (Atom)
