Why refresh of Maven repository is not enough for IntelliJ? - maven

I had a NoClassDefFoundError problem with some test, launched from IntelliJ. In order to repair the situation, I had to make several changes in many poms of the project - adding new packages and excluding some old ones for to escape the overlapping of them. Also, I reapired the situation with different versions. But the situation did not improve. Again, some package, declared in pom, was not found where it should be.
I refreshed the maven repository by
mvn -e clean install -U
, as is advised in https://stackoverflow.com/a/9697970/715269 - so old and upvoted answer, that it surely looks as Santa.
The problem remained unchanged.
I output the maven map. It was correct and it contained all needed.
I looked at the list of the External Libraries of the project. It was the old uncorrected list of overlapping jars with same names and different versions, and without good packages I added just now, and well seen in maven tree output!
Already hapless,
I reimported packages in IntelliJ
by:
Ctrl+Shift+A, Reimport All Maven Projects.
Ho! The list of libraries got repaired. And the problem, mentioned in subj, disappeared.
The question is: How it could happen, that the same project has that very pom for everything, but gets packages differently being launched in maven and in IntelliJ?
I know about that feature "delegate IDE build to Maven". And I keep it turned off. But I am NOT talking about the different SW for building. Whether they are different or not, they should be up to the actual pom's. And whereas maven, if turned off from the automatic building won't know about changes in poms, IntelliJ KNOWS about them. It could have jars up to pom, or up to maven - it has sense, but it simply has some old rubbish. Was there some deep thought under that construction?

Every time you manually change the pom.xml file, including the dependencies you need to load these changes into IDE. IDE does it on Reload from Maven action. See also Import Maven dependencies.

Intellij doesn't use maven to bulid and run a project except you are delegating build and run action to maven:
Since, IDEA doen't really use maven to run and build, it uses the pom.xml to import the project structure and "tries" to build the project the same way was maven does.
Actually, there are quite a few differences between these to build processes.
Generating sources or filtering resources (don't know if this is still an issue) aren't done during building the project with Intellij IDEA.
In case you are using code generation you have to build the project via maven first and then - when all the resouces are filtered and additional sources are generated - you are able to run, debug aso. the project with Inellij IDEA.
That's an important thing to be aware of and that's the reason why maven and IntelliJ IDEA project structures might get out of sync.
You can enable the "Reload project after changes in build scripts" feature and select the Any changes checkbox to keep your project structure updated:
Why should you disable this feature anyway
If you are working on a build file (gradle or maven is not important) reloading the structure on any change can be very anoying. It's cpu intense, dependcies are fetched aso.
Therefore, I prefer to reload project structure only in case of an external change. This happens when pulling an updated version of the build file for example.

Related

Ant to maven conversion

I need to convert few projects from ant to maven. I know the basics of both, also read a lot of articles on how to. However, is it a good idea to write a pom using eclipse? Or is it better to write it without using eclipse? The M2Eclipse plugin needs maven to be tweaked more, will the changes related to M2Eclipse cause problems when the war is built on jenkins?
Pros of using Eclipse IDE:
The formatting of pom.xml will be taken care, when you add the 'maven-eclipse-codestyle.xml' to the code formatter, as mentioned here. Formatting will be harder when you do it without an IDE.
The auto-completion feature of eclipse will make your coding easier, since it will automatically sense the open tags and close them. You need to close all the open tags manually, if you don`t use an IDE.
You can view the dependency hierarchy of the dependencies added and hence it might be a bit helpful while managing the dependencies.This can be extremely useful ,when you have transitive dependencies (Dependencies within other dependencies). You can find more about transitive dependencies here.
An IDE will warn you of common mistakes that may occur while coding (something like, 'forgetting to close an open tag','placing a tag in an incorrect location'). This will save a whole lot of time. If you don`t use an IDE, you need to correct the mistakes only when you get an exception after executing a maven command.
Eclipse will warn of missing artifacts (when the dependencies are not present in the local repository), which can help you to fix it before executing the maven goal.
Cons of using Eclipse IDE:
m2e plugin will throw 'Plugin execution not covered by lifecycle configuration' errors all over your pom.xml files. These errors won`t affect your build, but may be quite annoying.
I personally have done migration from Ant to Maven2. IMO it is better to write pom.xml on your own so that you wont face any last minute surprises as well as you will get complete overall knowledge on what you are exactly doing with your pom file.
However if you still want to go with m2e, from my experience it did not create any problems at all. Regarding the build - I guess there shouldn't be any issue. You can refer this link if you need more info about m2e and jekins - m2e and jenkins

Maven module dependency source instead of repository jars

I have a multi-module project, i.e.
parent
module1
module2
In one dev cycle, I added a class mod1.A to module1. Class mod2.B in module2 depends on it.
I do not have the artifacts in my local .m2/repository. Running this:
$ cd prj/module2
$ mvn -o exec:java -Dexec.mainClass=mod2.B
results in an error along the lines of:
The following artifacts could not be resolved: com.example:module1:jar:1.0-SNAPSHOT
After I install the artifacts via mvn install while in the prj folder, it all works as expected.
However, this presents an issue in at least two ways:
I have to go through the slower install phase instead of the faster compile phase
I have two versions of the same project and conflicting modifications in these. I cannot run the same Java class with their respective modifications, only the currently installed modifications, considering they are both the same SNAPSHOT version
There are workaround for both (skip parts of the build for the first, different snapshot versions for the second), but they are far from usable in practice.
Is there a way to make maven use the local modules, instead of using artifacts from local maven repository?
If I understand your question correctly, it seems like you are living a bit outside the norm here: you have two local "copies" of the project with different modifications, that you want to work with alternately when running "exec:java". And Maven is getting in your way: it expects your local .m2 repository area to be in play, but the version strings in each copy are the same, so you end up with the changes interfering among the copies.
To me, it sounds like what you are trying to do is to test your changes. I suggest you just write an actual JUnit or TestNG test in module2 that tests what you want (it can just call mod2.B Main if you want). Then, from your chosen project directory, you can run mvn test -Dtest=MyTestName. It won't "install" anything and it will find the dependencies the way you want it to.
Otherwise, I can see three options.
Change the version string locally in one of the copies (mvn versions:set -DnewVersion=B-SNAPSHOT can do this for you). That way any "installed" jars from your work on that copy will not be considered by the other copy, and vice-versa. You refer to this as being "far from usable" ... I think it should be fine? These are different versions of the project! They should have different version strings! I strongly recommend this option out of the three. (You can do mvn versions:revert when done if you used :set, or you can rely on version control to undo the change.)
Select a different local repository used by Maven when working on one of the projects, with a command-line flag as per https://stackoverflow.com/a/7071791/58549. I don't really think this is a good solution, since you would have to be very careful about using the right flags every time with both projects. Also you'd end up having to re-download Maven plugins and any other dependencies into your new local repository anyway, which is kind of a waste of time.
Try to avoid using any local repository at all. You seem to be trying to make this option work. I don't think this is a great approach either; you're fighting against Maven's expectations, and it limits your flexibility a lot. Maven will indeed find dependencies from the "reactor" (i.e., the executing mvn process) first, but this means all of the required modules must be available in the reactor to be found, which means you can only run mvn at the top level. So if instead you want to just do "mvn exec:java" inside a single module, mvn needs to find that module's dependencies somewhere ... and that's what the local repo is generally used for.
If you're dead set on going with option 3 (instead of option 1), then I suggest you follow the comments on your question and create a profile that runs your exec selectively against module2 and binds it to a lifecycle phase. But this is in practice very close to just wrapping it with a test.
For IntelliJ users:
I solved this problem using IntelliJ's Run configuration. It has the options Resolve workspace artifacts and Add before launch task -> Build. See this picture for clarification:
Run configuration example
The whole point of modules in Maven is to create decoupling between them. You either build each module independently, so that you can work on one module without touching the other, or include both modules as sub-modules in the parent pom and build the parent, which will resolve dependencies between its sub-modules and trigger their builds.
It looks like you have two options here:
Review the structure of your project. Do you really need to split it into two separate modules, if you change code in both of them simultaneously?
Import the project into a Maven-aware IDE (IntelliJ IDEA is very good at working with Maven), and let the IDE handle the compilation. Once finished and stabilized the code-base, build normally with Maven.

using pom.xml instead of iml files in idea

We are using IntelliJ idea in order to develop our product.
till now, we saved the iml/ipr files in a version control in order to share the same configuration among developers (and also between different versions of our product).
however, since idea changes those iml files a lot, it is an exhausted task to resolve its conflicts, and actually feels a bit wrong.
Moreover, idea 15 is no longer checks-out iml/ipr automatically.
I tried the maven-idea-plugin which suppose to generate the iml/ipr based on the pom.xml and it looks promising (except for some minor issues) but it's obsolete and there many stackoverflow posts advise against it.
I also undestand that the "correct way" to load our project is by loading the e pom.xml directly in idea.
The problem with that loading the pom.xml is that each user has to reconfigure idea (such as exclude directories, set the run configuration, plugins, maven version, JDK location etc.)
every time he download the code from the version control, which happens quite often.
So, my question is what is the best way to use intellij idea with our project.
my goal is that once a developer download the code he will be able run idea without manually configure a thing.
Thanks,
Meir
I am using Intellij 15.0.3 Community edition.
In our current project we do not add *.iml to Git.
For shure we do add pom.xml to Git.
I did not add any special plugins or configure idea in the way you described
(such as exclude directories, set the run configuration, plugins, maven version, JDK location etc.)
So I am using Idea out of the box, only the plugin 'Maven integration' is activated. I initially cloned the Git repository in a new folder.
In Idea I choosed File| New | 'Project from existing sources '
and selected the folder with the pom.xml.
Thats all, works perfectly. I can build in Idea or on the command line.
I can use Git in Idea or on the command line.
Everything works perfect.
So I can asure you that its absolutely possible without having *.iml under version controle.

Maven multi-project depths

I was trying to build Maven pom in something similar to the following hierarchical form:
root
+-- A-POM
+-- B-POM
+-- C-POM
+---D-POM
I was hoping that this could take care of my changed module problem. That is, if C is changed, then A must be rebuilt, etc.
But I ran into the issue that it seems the packaging at root is "pom," and after that I can't have A as packaging "war" then continue to drill in to have A include B, C as its modules. It seems to me that any POM which does not have "pom" in the then it can't have child modules. Is my understanding correct? Is there a way to do what I wanted to do?
In addition, I don't seem about to chain the "changed" mechanism in Maven (must due to my lack of knowledge). I like to have Maven detect a dependent project has changed and rebuild all the affected projects.
Thanks so much!
the reactor project (the root of the multimodule project) must have pom packaging. So your nested structure is invalid since A is not of type pom and I'm pretty sure you won't get it to work this way.
Second point is that Maven is a modularized build system and uses repository mechanisms to locate pre-built artifacts instead of checking out all modules from version control and building them in a monolithic way like in the old days ;) This means that Maven cannot know what to rebuild when you change something at your module since it simple does not have all the other module there at this time.
I think this is more a CI task than that should be handled by the build system itself. I know that your can achieve such a behavior with an appropriate build/CI Server like Jenkins that supports upstream and downstream projects. This means it is able to detect dependencies between the projects and trigger other builds as soon as a dependency has been built. This comes close to the behavior you are trying to achieve.
Btw. rebuilding other projects is only required for SNAPSHOT dependencies. Jenkins with the maven plugin supports this behavior but, depending on the number of SNAPSHOT dependencies of your project, this can cause long chains of project builds on the server. Some folks are of the opinion that in general SNAPSHOT versions are hell for CI tasks since these artifacts can change over time and are not reproducible. You could think over completely omitting SNAPSHOT versions and building final versions each time. This would also obviate your requirement to rebuild other modules as soon as a module changes. There are simply no changes until you upgrade dependency versions.

Intellij Debugging picking up old version project files

I am debugging code in Intellij. I use maven to build the project and there are various versions of the project sitting in the local .m2 repository. Intellij keeps on picking the old version of the code from the previous snapshot of the project when I start debugging. How do I make IntelliJ debug the latest code from the local repository?
You can tell Intellij 2016 to ask you each time which source code to step through.
File->Settings->Debugger
Show alternative source switcher
Try removing .jar and .war files that contain your code from your ~/.m2/repository/
For me the issue is that I built something and it is now registered in Maven under what Maven considers a newer version, but isn't what I was currently working on. I compiled, say, version "2.1" to debug something and then went back to working on "sand-box-idea-SNAPSHOT". I keep thinking why isn't Intellij picking up my latest sand box change but it's because it's deferring to the Maven version 2.1 which Maven assumes is better than 'sand-box-SNAPSHOT'.
It may be that you have some plug-ins interfering with IntelliJ's build process. I know that the Google Protocol Buffers Plugin can cause my Intellij to be unable to detect dirty classes that need to be re-compiled.
I've met similar behavior, maybe it can help you :-)
I developed app (using maven) and during the time I change output packaging from jar to war. Maven repository than contained both versions, jar and war, because maven does not remove old jar when you change it. As project pointed to mvn repository, it still used old reference to jar but new version within war was updated.
I was really upset as maven compilation and tests worked fine but Idea used me old version. I've had rebuild idea project and it worked later fine.
I have seen this very recently after upgrading from IDEA 13 to IDEA 14. It seems like launching configurations created in IDEA 13 are no longer automatically triggering a mvn package prior to launch.
In order to fix this I manually added a mvn goal in the "Before Launch" dialog.

Resources