Maven2: use ${basedir} in jar path - java

I am using an external, proprietary jar in my project. When I hard-code the path as follows in my pom.xml, it works fine:
<dependency>
<groupId>com.foo.bar</groupId>
<artifactId>bar</artifactId>
<version>5.2</version>
<scope>system</scope>
<type>jar</type>
<systemPath>D:\workspace\myproj\external\companyname\lib\proprietary_api.jar</systemPath>
</dependency>
However, when I try to use the ${basedir} variable, maven can't find the jar:
<dependency>
<groupId>com.foo.bar</groupId>
<artifactId>bar</artifactId>
<version>5.2</version>
<scope>system</scope>
<type>jar</type>
<systemPath>${basedir}\external\companyname\lib\proprietary_api.jar</systemPath>
</dependency>
The pom is located in D:\workspace\myproj
This also needs to be cross-platform compatible (dev on Windows, deploy on Linux).
Thanks!

It is wrong to use system scope for your proprietary JARs. You should deploy or install it into the local/central repository.

I'm not sure this will help, but try using forward (/) instead of backward (\) slashes. Also, try running it with mvn -e and mvn -X (the latter will produce a lot of debugging lines) - this might help you pinpoint the problem.
Here's an example:
http://jmonkeyengine.org/groups/contribution-depot-jme3/forum/topic/maven-2-pomxml
of using ${basedir} in the same way you want.
Btw, why don't you mvn install:install-file the dependency instead of using systemPath? See:
http://maven.apache.org/plugins/maven-install-plugin/usage.html

In order to be cross-platform compatible use ${file.separator} instead of the slashes..
so that will automatically convert to OS specified format

To make it work both on windows and linux, you have to start using profiles. In that way, a particular profile will get activated based on the OS and the build will become portable.
In each profile, you can define a property called jarPath (just an example) and refer that property in your dependency.
Maven Profiles Introduction
Look into the OS tag and configuration tag of the profile. Make sure your build are always portable and less manual steps needs to be done.involved.

Use forward slashes in the path.
The ${basedir} placeholder is extrapolated only once per Maven run. If this project is not the topmost project in your project hierarchy, then ${basedir} will be extrapolated to the location of the topmost project (i.e. the project where Maven started), not the current project.

Related

Incorporate javadoc URL for external jar dependency in Maven

I've searched for similar questions already asked, but most have been related to generating new java documentation using javadoc for all of the included dependencies.
My question is more basic - I just want to be able to view the javadoc documentation for an external library in Eclipse when using the "Ctrl+Space" or hovering over an object/method.
For example:
I have a dependency for the "commons-cli" library
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.3</version>
</dependency>
By default though, I am not able to view the API documentation for the classes located in this library. I can do this manually, by using the Project Explorer to navigating to the "commons-cli-1.3.jar" file located in Java Resources->Library->Maven Dependencies and then specifying the URL (https://commons.apache.org/proper/commons-cli/apidocs/) for the javadoc in its property dialog box.
Is there a way to incorporate this information into the maven pom.xml file? That way, I don't have to do this manually for every dependency and also it works for anyone checking out my project to their own computer.
Thanks in advance.
Run mvn dependency:sources which downloads the sources for the libraries. Check Maven repo dir (normally ~/.m2 ) if you have sources there - there should be jar with the same name as the lib artifact but appended with -sources. Like this:
If this is the case and you still don't see the javadocs in IDE then you should setup your IDE to use Maven repo as a source for sources.

Maven dependency for javax.ejb.jar into .m2 directory

I cant find javax.ejb.jar in my .m2 dirctory, I need this jar for import javax.ejb.Schedule; , here is my pom file entry.
<dependency>
<groupId>javax.ejb</groupId>
<artifactId>ejb-api</artifactId>
<version>3.0</version>
<scope>provided</scope>
</dependency>
I am not sure if it will work or not, or its a right way to do things. Can some one please help to make a change in the POM file so that it downloads javax.ejb.jar into the .m2 directory.
Updated
by .m2 I mean in the repository directory in the correct folder
hierarchy (What ever it is).
Why? We have multiple sub projects (In eclipse workspace), In order to resolve dependency we use M2_REPO/path/to/the/required_library_file.jar, Now theses projects are part of code bases, Every developer download the source code, Maven download all jar to the repository directory(of the developer using any OS/Platform). This relative path from M2_REPO helps developer to have consitenat code (for eclipse project). Otherwise everyone will be adding their own path.
If it still doesn't make sense, here is what I want, Please give me an entry for POM file which download the javax.ejb.jar file into .m2 directory what ever the sub path is.
I have to include this jar in every project manually (And every developer needs to them as well from what ever directory have glassfish (C: , D:, E:, or /home/glassfish/modules/)
D:\servers\glassfish-3.1.2\glassfish3\glassfish\modules\javax.ejb.jar
where rest of the jars in each project are included as M2_REPO/path/to/jar which makes less no changes in the code base to commit.
M2_REPO/javax/ejb/ejb-api/3.0/ejb-api-3.0.jar
M2_REPO/javax/enterprise/cdi-api/1.0-SP1/cdi-api-1.0-SP1.jar
M2_REPO/javax/inject/javax.inject/1/javax.inject-1.jar
etc etc
I think I hear what you mean now :)
The maven dependency you specify
<dependency>
<groupId>javax.ejb</groupId>
<artifactId>ejb-api</artifactId>
<version>3.0</version>
<scope>provided</scope>
</dependency>
which you have in .m2/repository/javax/ueb/ejb-api/3.0/ejb-api-3.0.jar does not contain the class/interface javax.ejb.Schedule.
But you found the jar-file in your glassfish server, which does contain javax.ejb.Scheduleand its name is D:\servers\glassfish-3.1.2\glassfish3\glassfish\modules\javax.ejb.jar and now you ask how to get that into the pom?
Well, the Java EE APIs and their official jars in maven are somewhat a study in disharmony.
If you run a search on maven central you will find multiple jars containing exactly that class. You will probably note that all appserver vendors provide their own edition of every aspect of every api in every version.
You should be able to find a jar with the javax.ejb module from glassfish in version 3.1.2
http://search.maven.org/#artifactdetails|org.glassfish|javax.ejb|3.1.2|jar
in which case the dependency would be
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.ejb</artifactId>
<version>3.1.2</version>
<scope>provided</scope>
</dependency>
I found another artifactId here, though maven has your version too.
A (very) weird maven caching problem? Then it might work tomorrow.
<dependency>
<groupId>javax.ejb</groupId>
<artifactId>javax.ejb-api</artifactId>
<version>3.2</version>
</dependency>
Though this is a new version, for compilation it should do.
You may need to provide the repository location in your pom.xml file or in .m2/settings.xml file for the required jar to get downloaded into .m2 directory.
The dependency is declared as provided what means that the container will provide it.
What container are you using? I think Tomcat/Jetty won't provide that jar as it seems so Java EE. In that case just change the scope to compile.
<dependency>
<groupId>javax.ejb</groupId>
<artifactId>ejb-api</artifactId>
<version>3.0</version>
<scope>compile</scope>
</dependency>
More info about dependency scopes:
http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Scope

Dynamically change maven dependencies

I have a POM file with one dependency on Freemarker.jar. In the library folder there are several versions of the freemarker jar. I am wondering if there is an easier way to update which freemarker jar is being used without having to open the pom and change the name of the jar or having to find the jar and rename it manually. A JComboBox with the different freemarker jars would be the best but I have no idea how to make it change during runtime. I would be fine with having to restart the application as long as all I have to do is change the selection of the combobox and restart.
I have read a few similar questions and I believe it might not be possible.
Here's my dependency:
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.19</version>
</dependency>
You can use the exec-maven-plugin to start the application together with a dependency management in maven. The version of the freemarker dependency must be overridable by the command line. For that you can use maven properties.
Then your user can restart the application with a different freemarker version by choosing it through a command line parameter.
For example something like this:
mvn exec:java -D=freemarker.version=2.3.19
But there are 3 limitiations:
Your users need to restart the application
This solution is only possible if the freemarker versions are binary compatible
If the freemarker versions are only source compatible, your users additionally need to re-compile the application before starting it.
If you try this solution you should begin with 2 freemarker version that are very close, e.g. 2.3.19. 2.3.18 and try if they are compatible.
Step 1: Add the freemarker dependency to the dependency management.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>${freemarker.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
Step 2 Add a default version property for the case that the user does not specify one at the command line.
<properties>
<freemarker.version>2.3.19</freemarker.version>
</properties>
Step 3 Configure the exec-maven-plugin
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<mainClass>org.your.full.quallified.MainClass/mainClass>
</configuration>
</plugin>
Step 4 Try to execute it with the default freemarker version
mvn exec:java
Step 5 Try to execute it with another freemarker version
mvn exec:java -D=freemarker.version=2.3.18
I don't think you could use maven for this, since maven is (normally) not used during runtime, only during compile/build. You could change the scope of your dependency to "provided", and then tweak the mechanism you're using to start your application, to add the correct jar to your classpath. However, with more details on how you run your application, it's hard to give more details.
EDIT: changed to the correct scope.

Cannot load classes from Guava r08 running in Tomcat. Cannot compile from source. Missing javax.annotations

I'm trying to use RichFaces in my learning JSF application. I have set up Maven using
https://repository.jboss.org/nexus/content/groups/public-jboss/
I have included the dependencies
<dependency>
<groupId>org.richfaces.ui</groupId>
<artifactId>richfaces-components-ui</artifactId>
<version>4.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.richfaces.core</groupId>
<artifactId>richfaces-core-impl</artifactId>
<version>4.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.richfaces.ui</groupId>
<artifactId>richfaces-components-api</artifactId>
<version>4.0.0.Final</version>
<type>pom</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.richfaces.core</groupId>
<artifactId>richfaces-core-api</artifactId>
<version>4.0.0.Final</version>
<type>pom</type>
<scope>compile</scope>
</dependency>
This has fetched guava-r08.jar.
When I try to run the project in Tomcat7 I see a lot of class load exceptions - failing to load classes that I can see exist within guava-r08.jar along with sac-1.3 and cssparser-0.9.5.
If I try to use the source instead - taking source from guava-r09 - Eclipse tells me that it cannot find classes such as javax.annotation.Nullable. Problem is neither can I!
Where can I find these classes, or am I taking the wrong approach from the start?
Thanks
Richard
Maven configuration for RichFaces dependencies
Tomcat fails to load these classes, because RichFaces' dependency on Guava has a runtime scope. Contrary to the compile scope, these dependencies are not added to the classpath when compiling. You must include them yourself.
To achieve this, you should include richfaces-bom in the dependency management section of your POM, as explained in this JBoss wiki article. This will include Guava and all other required dependencies RichFaces might need.
This is the "Bill of Materials" (BOM) pattern. The JBoss wiki explains this pattern far better than I would, and links to other articles on the subject.
javax.annotation.Nullable warnings in the Guava source
These occur because Guava uses JSR 305 annotations. It is not required to depend on the JSR 305 jar when using Guava, because annotations do not require to be present on the classpath once compiled. Of course, if you want to use #Nullable and other such annotations in your code (you definitely should), you'll need to add a dependency on the JSR 305 jar.
I have started from scratch using instructions at jboss.org
I installed Maven 3.0.3
I copied the supplied settings.xml to my .m2 directory and added the JBOSS section from 1
I used the command line to create the project:
mvn archetype:generate -DarchetypeGroupId=org.richfaces.archetypes \
-DarchetypeArtifactId=richfaces-archetype-simpleapp \
-DarchetypeVersion=4.0.0-SNAPSHOT \
-DgroupId=uk.m0rjc \
-DartifactId=jsfplay
I then built the project. I had to remove the previously downloaded guava jars from my m2 repository because they were corrupt - perhaps my initial problem.
mvn clean package
I copied the WAR file it produced to Tomcat and navigated to the sample page at localhost:8080/jsfplay-1.0-SNAPSHOT/
I had some issues making the project work in Eclipse. These may be due to my setup from previous experiments.
I used the "Import -> Maven -> Existing Maven Project" to import it
I had to switch the project to JDK 1.6 and 1.6 compatibility mode.
I was unable to use the JavaServer Faces facet. This does not seem to matter.
I had to set my Server Profile to use the right JDK
I had to map *.xhtml to the Faces Servlet in web.xml. It may have been corrupted when I pressed a wrong button to accept a JSF addin.
Then it worked!!
Now to try porting my existing code to the new project.

Add a dependency in Maven

How do I take a jar file that I have and add it to the dependency system in maven 2? I will be the maintainer of this dependency and my code needs this jar in the class path so that it will compile.
You'll have to do this in two steps:
1. Give your JAR a groupId, artifactId and version and add it to your repository.
If you don't have an internal repository, and you're just trying to add your JAR to your local repository, you can install it as follows, using any arbitrary groupId/artifactIds:
mvn install:install-file -DgroupId=com.stackoverflow... -DartifactId=yourartifactid... -Dversion=1.0 -Dpackaging=jar -Dfile=/path/to/jarfile
You can also deploy it to your internal repository if you have one, and want to make this available to other developers in your organization. I just use my repository's web based interface to add artifacts, but you should be able to accomplish the same thing using mvn deploy:deploy-file ....
2. Update dependent projects to reference this JAR.
Then update the dependency in the pom.xml of the projects that use the JAR by adding the following to the element:
<dependencies>
...
<dependency>
<groupId>com.stackoverflow...</groupId>
<artifactId>artifactId...</artifactId>
<version>1.0</version>
</dependency>
...
</dependencies>
You can also specify a dependency not in a maven repository. Could be usefull when no central maven repository for your team exist or if you have a CI server
<dependency>
<groupId>com.stackoverflow</groupId>
<artifactId>commons-utils</artifactId>
<version>1.3</version>
<scope>system</scope>
<systemPath>${basedir}/lib/commons-utils.jar</systemPath>
</dependency>
Actually, on investigating this, I think all these answers are incorrect. Your question is misleading because of our level of understanding of maven. And I say our because I'm just getting introduced to maven.
In Eclipse, when you want to add a jar file to your project, normally you download the jar manually and then drop it into the lib directory. With maven, you don't do it this way. Here's what you do:
Go to mvnrepository
Search for the library you want to add
Copy the dependency statement into your pom.xml
rebuild via mvn
Now, maven will connect and download the jar along with the list of dependencies, and automatically resolve any additional dependencies that jar may have had. So if the jar also needed commons-logging, that will be downloaded as well.
I'd do this:
add the dependency as you like in your pom:
<dependency>
<groupId>com.stackoverflow...</groupId>
<artifactId>artifactId...</artifactId>
<version>1.0</version>
</dependency>
run mvn install it will try to download the jar and fail. On the process, it
will give you the complete command of installing the jar with the error message. Copy that command and run it! easy huh?!
I'll assume that you're asking how to push a dependency out to a "well-known repository," and not simply asking how to update your POM.
If yes, then this is what you want to read.
And for anyone looking to set up an internal repository server, look here (half of the problem with using Maven 2 is finding the docs)

Categories