Intellij maven dependency prefer local code - maven

i'm working on a project in which i have an android application project which has pom dependencies on other projects
something like this:
<dependencies>
<dependency>
<groupId>some.project/groupId>
<artifactId>some.artifact<artifactId>
<version>1.0.0</version>
<type>apklib</type>
</dependency>
</dependencies>
while developing i always want Intellij to use the local source code from the some.project library i have in the project.
the problem is it will pull version 1.0.0 from the server and use that.
i tried using LATEST as version, this works fine as long as my some.project library version is updated to the latest version on the server.
since we have automated builds that will increment the version for some.project when changes are made i will have a scenario in which my source says 1.0.0 but the server has 1.0.1 and again intellij will pull the server apklib
Any suggestions how to achieve this? if i could use a dev profile to somehow define this for development only and a prod profile to use exact version numbers (which it should) that will be amazing.
Thanks!

You can add a module dependency in IntelliJ:
File->Project Settings->Modules click on the module -> click Dependencies tab and then click the green '+' sign and choose '3. Module dependency'.. add the module on which you want to depend locally and click the blue arrows to bring the module above the Maven dependencies.

There is a checkbox "resolve Workspace artifacts" under Maven Run/Debug Configuration, select it then it'll work as expected.

We are dealing with the same problem...
"IDEA should resolve dependencies as a module dependency type (rather than a local jar Maven library) if this Maven project is opened in IDE and it's version matches the version, installed in a local Maven repository."
https://intellij-support.jetbrains.com/hc/en-us/community/posts/206836605-Always-prefer-local-module-source-over-Maven-dependencies
Our solution was to add local Maven profile in pom.xml and specify local dependency version. To make it work, you have to turn on local profile.
<profiles>
<profile>
<id>local</id>
<properties>
<dependency.version>x.x.x</dependency.version>
</properties>
</profile>
</profiles>
When local dependency is updated, you have to take care to update this version too, but currently this is the best solution we found and it's working for us.

Assuming that you have the project organised as a multi-module project, and that you're talking about a dependency on a library that's one of the project's modules, then you need to use a snapshot dependency, and you need to use the full maven release process. As it is, you're depending on a pre-built, static version of the given library, but you need IntelliJ to look at the source and class you compile instead, and snapshot dependencies are used exactly for this purpose.

This works for Maven projects in the following way:
Add the dependencies that you want to work with to the Maven Projects tab.
Navigate to the implementation of the class for which you are looking.
Once you are in the implementation, you can navigate back to the Super Method for the declaration.
That's either Navigate -> Implementation(s) or ALT+COMMAND+B (on the Mac map). Intellij will then present you with the option of decompiling the class from the JAR in the dependency list or the source code in the attached Maven project.
For example, I am in project bank of the Rooskie Bank, and I want to view the code for the Account class in bank-domain. I click on an Account object declaration and press ALT+COMMAND+B. From the popup menu, I choose the definition from the list of sources that does not have "(Maven: com.rooskiebank.bank-domain.jar)" in the choice.
IMO this is an awkward way of doing things. As much as I like it, I find Intellij is difficult to use in enterprise-sized systems with multiple in-house libraries, and I still use Eclipse a lot for them. Intellij works better with Git and is great for stand-alone microservices.
I imagine Gradle works in a similar way.

Just a small hint how to do the same with Gradle. Supposing you have two workspaces with lib and app. The lib is deployed to some maven repo and needs to be described in the following way:
// build.gradle
group 'lib.group'
version 'lib.version'
// settings.gradle
rootProject.name = 'lib.name'
While app dependencies are the following:
// build.gradle
compile "lib.group:lib.name:lib.version"
So, the app module uses lib as a maven dependency. Now, you can import lib sources into app workspace using File | New | Module from existing sources. After refreshing the project from Gradle tool window, you will get two modules lib and app in the app workspace. However, even after reimporting Gradle the lib dependency will still point to the maven repository, what you can check in File | Project Structure.
The trick to be done here is to click with the right mouse button on app module in the Gradle tool window, and select Composite Build Configuration option. Then, on the popup window just select the local lib module to include it in the app module build. Now, after reimporting Gradle deps again for the whole workspace you will get the maven dependencies for lib replaced with the local dependency.

Related

How to trigger IntelliJ to reimport single Maven dependency?

I have a workflow working on an application and one of its libraries that somewhat looks like this:
Make changes to library -> Push library jar to remote Maven repository with no version change -> Pull updated library jar from the remote repo to the downstream app -> Test and make changes to the app and library
But seems like the way IntelliJ indexes and/or caches Maven dependencies is not affected by me running a clean install from the Maven interface. Is there a surefire way to force IntelliJ to discard any cached dependency and reimport, or possibly do it only for a desired library?
Very likely this has nothing to do with IntelliJ. Since the version number is the same, maven won't re-download your dependency. Try to just delete the dependency locally from the maven repository:
rm -rf ~/.m2/repository/<..path to your library package..>
You could also avoid pushing the library to the remote repository, and test completely locally, by using the library as a local dependency. For this approach, see answers here: How to add local jar files to a Maven project?
Or since you are not effectively changes the library version the right approach would be to use the library project sources as a direct dependency for IDE maven project. For this - add this Maven library project as a new module to existing Maven project: File | New... | Module from Existing Sources... and select pom.xml file of this library project.

can't find my maven artifacts

I'm working in eclipse and I have a problem that I can't import my personal java libraries.
I created the libraries and 'installed' them into my local maven repo (using mvn install). This created a subdirectory related to the 'version' name that was in the POM file from when I ran the command. Which seemed fine.
So in this directory there where the usual jar files and other stuff.
When I released this file I manually changed the name of the version in the POM. going from 0.0.1-SNAPSHOT to 0.0.1-RELEASE
This seems to have worked as I would have expected.
However I can't seem to find import the new release jar.
Using the maven repositories browser in eclipse I can see that the new artifact is in the 'local' repository.
I try to add the dependency in the following methods:
Select the main project -> Maven -> add dependency.
This adds the dependency details into the pom but with a type value detail of <type>pom.lastUpdated</type>
Select the project pom.xml file -> Maven -> add dependency.
This time the artifact for the 0.0.1-RELEASE is greyed out I can select it, but I guess nothing is actually happening.
The original 0.0.1-SNAPSHOT it selectable, and if I use this I do not have a <type> detail in the pom.
I don't understand why there is a difference in the RELEASE and SNAPSHOT artifacts, as they have both been generated in the same way, and clearly they are both visible in the browser, the contents of the directory on disk are the same. The file names and contents are identical with the exception of the word RELEASE or SNAPSHOT.
I know that I can simply add in the RELEASE jar to my build path, but this seems to be a ridiculous thing to have to do if I intend to use maven (or do I need to do this).
I don't want to use an external repo for storing my artifacts, and I'm not too keen to go to the trouble of installing nexus (or similar) on my local machine (just because I've had trouble with it in the past).
What am I missing so as I can get my maven project to see my local repository and all its artifacts.
Thanks in advance.
David
ps I've already tried things such as mvn dependency:purge-local-repository which definitely pulled in / updated all the local jar dependencies.
So I've managed to work around my problem.
As such this solution is ridiculous, and breaks all the purpose of maven.
So I found (from running maven from the cli) that there was an error in the parent of the project I was attempting to use.
The parent was missing a direct link to the scm plugin (version error).
Once I solved this problem, I then returned to the sub project, and got a lot of errors from missing stuff from the parent.
Essentially it was not 'seeing' all the log4j dependencies.
The solution (well non-solution really).
Add all the log4j dependencies to the sub project.
Edit in SCM and surefire test plugins (as it also started to fail the test code due to missing junit).
So this is great.
I have to define all my dependencies on log4j and in my sub / child project's pom.xml file.
I also need to define them all in my parent's pom.
As it then still refused to run tests in my new project (that used the above as a dependency), and refused to find log4j also. I then decided to add all of these as dependencies for my current project.
Great.
I thought the whole point of maven was I could define my dependency on log4j in my my logging library that I use (which is the dependency), and then it would 'automagically' pull in all the required from this dependency.
Clearly not.
As stated at the start. This is NOT AN ANSWER it is a crazy work around.
My logging library that I use should be able to define its own requirement on a specific log4j version (such as moving from log4j to log4j2), and then when I include this as a maven dependency any change to the required dependency should be seen automatically.
But No : I have to import the dependency on log4j in my other projects also. So now if I had updated my logging library from log4j to log4j2 I would need to go to all my project that use this library and update their pom's to ensure that I have the correct version of log4j.
Seems the whole point of maven has just been lost!
Can someone please tell me where I am going wrong!
David.

Using maven and Intellij IDEA, how can I modify a dependency without needing to manually install it every time?

I'm using Intellij-IDEA 11. If there's a solution that works in 12, I'd be willing to upgrade for that.
I built a library that many projects depend on but the library changes often. This library is added to my project's pom.xml as a normal dependency:
<dependency>
<groupId>my.company</groupId>
<artifactId>MyLibrary</artifactId>
</dependency>
This is a typical series of steps I need to take when I add a feature to my project:
Modify some code in my project
Modify some code in the library I depend on
Check to see if the feature works
If not, repeat
Outside of my IDE (which happens to be Intellij-IDEA), this is a straight forward process: I add step 2.5 which is to cd into the dependency's project folder and then mvn install the library.
But I don't know a convenient way to do this in Intellij-IDEA. Ideally, I'd modify the source of the library inside Intellij, click the green play button and the IDE would figure out to use the modified sources of the library.
Right now, since the library is a dependency, it just uses what's already in my local repo. So modifying the source of the library doesn't have an affect until I manually mvn install it.
Note: I've figured out a trick that seems to work. If I modify the project's parent pom to include the library as a maven module and then include the same library as an intellij module, it uses that source instead of the jar in my local repo. But I don't like this solution because I'd never want to commit that modified pom (because the module has to point to a file system path that only exists on my local file system).
I've found a bug in the Intellij-IDEA bug tracker that seems to relate to this: http://youtrack.jetbrains.com/issue/IDEA-25146
I found out a way to do this. First, you add the library's pom.xml in the Maven Projects tool window. Then you Edit your configurations so that they run the install goal of your library. And image of how to do this is provided below.
Click here for a full sized link
Open module setting (F4 on a module), go to Modules, select the dependencies tab in module that depepends on your library.
If the library is a module add a module dependency
If the library isn't a module, I assume it gets built and put somewhere, add that directory to the module dependencies.
The higher up the list the higher its priority
I've similar architecture and here is what I do (and it works very well).
Create an IDEA maven project based on the pom.xml of my main project (the project using the frequently changing library).
Add maven project to my main project (click on the "+" icon in the maven projects tab and choose the pom.xml of my frequently changing library)
EDIT
note: all the modules (from the library and from the main project) have a *-SNAPSHOT version
In more details, the pom.xml of my library project :
<groupId>com.company</groupId>
<artifactId>mylibrary</artifactId>
<version>2.0.1-SNAPSHOT</version>
And the pom.xml of my main project
<groupId>com.company</groupId>
<artifactId>myproject</artifactId>
<version>1.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.company</groupId>
<artifactId>mylibrary</artifactId>
<version>2.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
I think that IDEA is smart enough to see that the dependency is a SNAPSHOT and that this library is in the current IDEA project (i.e. same IDEA window)... and so IDEA don't look in the local repo since the SNAPSHOT is in the current "workspace".
Hope it clarify the situation.
If I need to run something, I have different options either
defining a new maven run configuration in IDEA to run any maven goal (from any pom.xml in my IDEA project) with any profile.
defining a simple unit test configuration in IDEA (not directly linked with maven except that the classpath is derived from the classpath defined in pom.xml)
defining a new Tomcat/JBoss configuration in IDEA and deploying some artifact in it. (IDEA detect deployable artifacts -like war or ejb- from the pom.xml)
I have the same scenario than you and I am using Intellij 2016.02.
Here is how I solved it:
1 - On Intellij open the maven panel going to View -> Tool Windows -> Maven Projects, then click at the plus green button (add maven project) and select the pom.xml file from the dependency project
2 - On Run/Debug configuration settings, add a before launch task as a maven goal, choosing the Working Directory of the dependency project and in command line just type "install".
3 - Now edit anything in your dependency project, and redeploy your main application, and the changes may affect.
EDITED:
I found a new solution, and it's solved the "update classes and resources" downside, here is what I did:
1 - Do the first step from the previous solution, but remove the install goal from before launch task if you add it on step 2.
2 - Edit the exploded artifact, and add the dependency project "compiled output" element from "Available elements" panel to output left panel.
Changes may work without need to install, and now my "Update classes and resources" works like a charm :)

Maven can't discover workspace projects, junit, other libraries

so I have started using maven (with eclipse, and a local implementation of Sonatype) not that long ago, after getting through the initial pain I though everything was working.... apparently not !
I have my main project POM and all my child POM (I am using a 'flat' hierarchy, so all the sub projects are in the same folder as the parent POM). This seems to be working OK.
The sub project where all started and 'released' and tested before I started using Maven. I went to maven to solve my 'dependencies' problems... or rather make them more complicated in this instance.
Most of the 'Maven' stuff seems to work fine, but I can't resolve the dependencies of my 'sub projects' that have been released into my local ms/repository
Each day I start up eclipse and have the same problems, I have 'unable to resolve imports' on all my personal libraries, and all those that I use for them (such as Log4j, DDlUtils etc).
I thought the whole point of maven was that I would be able to put in an import declaration for a library, add the 'groupID' and other stuff to the child POM (or parent POM). And then have all the jars downloaded automagically when I run
mvn install
against the parent.
However each day I find I have to re-insert the build path to the libraries (internal and external) via the eclipse workspace and point them to the location of the libraries that I have downloaded as maven can't seem to find them anywhere.
Specifically with running Junit test, I can run them from the workspace (using run as junit) and they all pass fine. But if I try to run them with
mvn test
I get an message saying
java.lang;NoClassDefFoundError: org/junit/Assert
(and this is the same from within eclipse running the mvn test or from CLI)
with an error message in the output of
failed to execute goal org.apache.maven.plugins:maven.surfire-plugin:2.10:test
the POM and jar are in my M2_REPO, and I can find it when I search in sonatype, why can't maven find something that is part of its own system, exists in its repo.
but this obviously works just fine when I run via eclipse and point it to an independently downloaded junit library.
I don't know what extra info you may require, and I'm obviously missing something in either the m2e plugin, my maven install or in sonatype.
please help I'm begining to loose my hair!
and may soon be forced to return to an ant/ivy solution (but don't want to have to learn 'yet another tool' (in this case ivy).
Thanks in advance
David.
ps. i'm on a windows XP platform
edit...
can I get maven to build and release the jar and pom even though it thinks it is failing the tests (which is itn't as I'm doing them manually, and they pass just fine).
If I look in the 'effective POM' tab of my parent POM, the plugin stated above is not in there. I guess this means it is a maven config setting, but where do I add it, and why isn't it automatic when I run my first set of maven tests?
edit 2....
I just found this on the apache plugin comments page (http://maven.apache.org/plugins/maven-surefire-plugin/plugin-info.html), so I ran the code on the CLI, mvn surefire:help -Ddetail=true -Dgoal=test lots of stuff was downloaded, and now the tests run, but they fail within maven ? (remember they pass when run from eclipse using 'run as junit test)... so this is nearly a solution...
It sounds like you need make eclipse aware that the projects in question are Maven projects. You may have POMs set up for your projects, but for the m2e plugin to work you need to have either created the project as a Maven project ('New' -> 'Project...' -> 'Maven' -> 'Maven Project...'), or converted it into a Maven project by right clicking it then selecting 'Configure' -> 'Convert to Maven Project'. You will know that a project has been recognised as a Maven project because there will be a little blue 'M' in the top left of its icon, as shown in the screenshot below:
The main thing to note in the above picture is the 'Maven Dependencies' library. This is set up automatically by the m2e plugin. Whenever you add a dependency to a POM then the project's build path will be configured automatically, although sometimes you may need to force it to do so by right clicking the project and selecting 'Maven' -> 'Update Maven Configuration'. The important thing is that if everything is working then you should never have to update the build path yourself. Moveover, if you do update it yourself then any changes you make will likely get overwritten the next time you run the 'Update Maven Configuration' command.
Also worth noting from the picture is that the two dependencies 'mavenProjectTest' and 'primes' have folder icons next to them. This means that they have been picked up as workspace projects. For this to work the project must have 'workspace resolution' enabled, and the projects to be picked up need to be configured as m2e Maven projects as well.
You mention downloading external libraries. You shouldn't need to download any libraries yourself - by adding the right dependency declaration for an external library then Maven will download it from your configured remote repository (the first time anyway - afterwards it will then be able to get it from your local repository). By default, this is the Maven Central repository. To add an external library to your project just follow that link, enter the library in the search box, click on the version link for the version you require, then you will be taken to a page where there will be the dependency XML declaration that you can just copy and paste into your POM.
One more thing that may help is that you should make sure that your source folders follow the Maven default directory structure. That is, your test packages should be contained in a source folder called 'src/test/java', and the main project packages should go in 'src/main/java'. Otherwise Maven will not know where to find your source code. It is possible to configure a POM to tell Maven to expect your source code to be in different source folders, but it is highly recommended that you follow the standard Maven directory structure.
Since you have child modules, my suggestion would be to simplify things by creating a new Maven project from scratch that you can have a play around with. Once you are comfortable with that then try getting m2e to work for your multi-module project.
I remember your pain when first getting to grips with Maven, but it's great once you understand what it's doing and everything is working. I highly recommend reading through the free online book Maven: The Complete Reference - it helped me out a lot when I was getting started with Maven.
I have experienced the same messages and have found a working solution, thanks to one of my organization's Maven experts.
Here was my pom.xml that reproduces your error:
<dependencies>
<dependency>
<groupId>org.junit4</groupId>
<artifactId>org.junit4</artifactId>
<version>4.3.1</version>
</dependency>
</dependencies>
With it, I would get package org.junit does not exist messages and NoClassDefFoundError: org/junit/Assert. Similar to your experience, it worked great from Eclipse, green bars and all.
Here is the pom.xml that works:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
I copied this from the example at the top of this Using JUnit page.

How do I create/use a class library with Netbeans on top of Maven?

This seems like a stupid question, but I am sort of dependent on Netbeans 7.1 wizards. There doesn't seem to be an option to do this.
My web-app is built with Maven and I want to break out some of its packages into an independently built and maintained class library (specifically, the JPA part but that shouldn't matter.) Then I want to delete those packages out of the original web application and then create a dependency to the artifact that I create.
So how do I get started? The Netbeans New-Project wizard doesn't seem have an option for "Java Class Library" like it does for ANT-built projects. The closest choice I can see is "Java Application." Is that what I use and just ignore the main class or is there some other path I don't see?
I am usually pretty good at picking this stuff up but my web searches aren't yielding much. Much thanks for any help.
You can use the wizard for "Maven" -> "Java Application (A simple Java SE application using Maven)", as far as maven is concerned there is no difference between a libary and an application. I think netbeans will create a sample App.java that you can simply delete.
For your usecase it would make sense to also create a parent project for the library and the webapplication. Building the parent would then also build both the library and web application. It also allows you to use "build with dependencies" on the web application and have the library rebuilt first.
To create a parent project you can use the "POM Project" entry. The directory structure ideally looks like this:
- pom.xml (for parent project)
- library (folder)
- pom.xml (for library module)
- webapp (folder)
- pom.xml (for webapp module)
The parent project should then contain module elements containing the relative path of your other projects:
<modules>
<module>library</module>
<module>webapp</module>
</modules>
The library and web application reference the parent like this, the groupId and version are defaulted to be the same as the parent:
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>myGroupId</groupId>
<artifactId>parentArtifactId</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>libraryArtifactId</artifactId>
You can begin with Maven > POM Project. Which is suitable for Class Libraries.
Also you can make your Maven project "modular". Good tutorial can be found http://sonatype.com/books/mvnex-book/reference/index.html in Chapters 8 and 9.
The following works perfectly for class libraries in NetBeans8.1.
You will have to upgrade major plugin versions in the Maven file (and you want to remove JUnit if you are not using it, see bottom).
DO NOT use New Project -> Maven -> Java Application, it does NOT integrate with the Maven Dependency menu system in NetBeans-8.1.
Follow these steps:
Step1: Create a New Project -> Maven -> Project from Archtype then in the archetype search filter choose maven-archetype-quickstart.
Step2: Click Next and then enter your project/module name (MyLib or MyAPI) then Finish.
Step3: Immediately (before you forget) under Project Settings > Sources change the Source/Binary format from 1.5 to 1.8 (or other).
Step4: Immediately (before you forget) under Project Settings > Licence Headers choose a licence.
Step5: Create new (or copy from old project) Java class or interface files etc. under Source Packages in the project browser.
Step6: (optional) delete the public class App if you don't want to have a simple standalone module run/test class.
Step7: (Highly recommended): Upgrade the major Maven plugins to latest versions by editing the version numbers in the pom.xml ! The best place to find the latest versions is by inspecting the folders under the main plugins repository: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/
Under any other NetBeans Maven-based project the new "upstream" library or API project will be offered via Dependendies -> Add Dependency .. (Open Projects subtab). It will also be offered via the repository management system when you search for Maven library via Add as Dependency.
If you want to add common/shared libraries, just add them via your MyLib or MyAPI module using the Maven Dependencies feature; they will propagate to any module "downstream" that adds your MyLib or MyAPI module as a Dependency.
Optional: Also, your pom.xml will by default include JUnit:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
Just delete it if you don't want it.
I found a faster way of upgrading the versions of your plugins in pom.xml using NetBeans.
Locate the plugins -> plugin -> version tag in your pom.xml
Doubleclick the version number so that it becomes highlighted
Press CTRL+SPACE to toggle autocompletion
The popup menue lets you select the versions available.

Resources