Maven: including utils in Java project - java

The case is quite simple, but I still can't solve it:
INFO: All 'projects' I am talking about are Maven projects.
I have certain Java project that I am working on right now. Recently, I have written a lot of general-purpose code in this project. I also have an 'utils' project with some Java utils in it, so I decided to move the general-purpose code from my main project (let's call it 'A') to the utils project. This would be practical because:
I have less clutter in A
I can reuse the code in other projects without bringing the unrelated content of 'A' in scope.
The problem is that utils is, of course, an utility project, a library if you want. And it does not have a main class. When I try to install (mvn install) it, no sources are included because there is no proper entry point.
So, after trying a lot of things, I have the concern that I am approaching this problem completely wrong and that's why I came here. I do not have any experience with Maven except the simple use case (e.g. including external libraries from Maven Central). Therefore my question is:
Which steps are required to make my utils library available in project 'A'?
I am not aiming to install my project on Maven Central or any other remote repository. I just want it available in my local mvnrepo. I am aware that this means that I'll have to clone my utils project and install it everywhere where I try to use project 'A'.
EDIT 1: I am using Java 11 (openjdk11), Maven 3.6.0, IntelliJ IDEA Ultimate with Maven Helper plugin and also GitHub in order to make my projects available anywhere.
Also, I have just checked that project 'A' correctly includes the jar from the utils project and actually adds it to the classpath (but the jar is empty). So, the problem really seems to be in the utils project.

A maven install would place your compiled code in the local maven repository (.m2/repository).
Sources are packaged by the source plugin.
mvn source:jar

Related

Maven Eclipse plugin bug? failing to auto-add in-workspace dependency JAR to Run Configuration module-path

So here is a quick rundown of my situation:
I have two Java projects: one in Java 8 (so not modular) and one in Java 11 that is modular.
The modular/not-modular issue may not be relevant but for the sake of clarity, I've stated it.
For reference, the Java 8 is a game library I made, and the Java 11 is the game implementation I'm making.
I need to reference the Java 8 library from my Java 11 game project.
Both projects are Maven projects, and I have my dependency defined in my game's POM file.
I'm using latest version of Eclipse (2020-03 4.15.0) and Maven 3.6.3 with Java version 11.0.7 OracleJDK.
My Problem:
My understanding is that my Java 8 library project becomes an automatic module. Adding it into my Java 11 game project module-info file works (with a warning about the name being unstable, but no issue) and I can compile my game project code with no issues in Eclipse.
When I attempt to run the game, I get Module <my-library> not found, required by <my-game>. Now, since Maven is managing the dependencies, it should just work.
How can I get my game to run?
I Can Fix It Three Ways...
First I can simply manually add the library project's JAR file (in it's target folder) to the Run Configuration module-path of my game project.
Second, I can delete the library project from my workspace. This means Maven then goes and gets the JAR from the local m2 repo (it's been installed with mvn install). In this situation Maven DOES automatically add the JAR to the Run Configuration module-path correctly.
Third, I can change the version of the library project in it's POM file and like option two, this means it no longer satisfies the dependency and Maven then looks for the JAR in the local m2 repo.
But...
All three of these options seem to me like they should be unnecessary. This feels like a bug with Maven failing to add the in-workspace project dependency to the module path in the Run Configuration in Eclipse.
To be fair, it is a Maven Eclipse plugin feature that automatically detects when one of the in-workspace projects is a dependency and uses that "live" version instead of the m2 repo version. This is very handy for these situations where development on a library is happening in parallel.
But until this bug is fixed (or unless it's not a bug and I'm missing something), this caused me a ton of frustration. I've posted this in hopes of helping anyone else who may be facing the same issue.

Test dependencies for white-box unit testing Java modules with Maven and Eclipse

I'm trying to convert existing Java projects with Maven and Eclipse into Java 9+ modules. The projects have unit tests and the unit tests have test dependencies. I need the test dependencies to be available in the test code, but I don't want them exposed to the rest of the world in the published modules.
I think Testing in the Modular World describes the Maven solutions well. In summary one solution is to create one module-info.java in the main source folder and another in the testing folder. The file in the main folder has the real dependencies. The file in the test folder adds the test dependencies.
The solution works well in Maven and I can build and run tests from the command line. However, when I import the project into Eclipse as a Maven project it balks. Eclipse complains that "build path contains duplicate entry module-info" and refuses to build the project at all.
Using the other suggested solution in the article with a module-info.test containing --add-reads has no effect and the build fails in both Maven and Eclipse as the tests can't find their dependencies.
To make matters more complex I need to import the test dependencies from Maven, but I also need to import standard Java modules that are not used by the main code. For example one unit test relies on the built-in web server provided by java.httpserver and as it is part of the JDK any magic done on the test dependencies will miss it.
Is there a solution for this that works in Maven and Eclipse (latest versions)? It sounds like a very common problem and the module system has been around for a while by now.
Note that I really don't want to change the project settings in Eclipse. I can fiddle with plugins in the pom files, but adding a manual routine where all developers need to edit the generated/imported project settings manually is not an option.
EDIT:
There is an open Eclipse bug report for this, see Eclipse bug 536847. It seems it is not supported yet, but perhaps someone can suggest a workaround?
The Eclipse emulation of the multiple-classpaths-per-project feature in Maven has been broken for very long. The symptom is that you can have non-test classes using test dependencies just fine.
Essentially Eclipse just considers each project to have a single classpath instead of two parallel ones which causes things like this to ... not do the right thing.
I would suggest splitting each of the problematic projects into two. One with the actual sources and one with the test sources (depending on the actual source). This will avoid the Eclipse bug and also allow you to use the newest version of Java for your tests while having your application built for an older version of Java.

Including .jar files in Github for consistency

I am new to using github and have been trying to figure out this question by looking at other people's repositories, but I cannot figure it out. When people fork/clone repositories in github to their local computers to develop on the project, is it expected that the cloned project is complete (ie. it has all of the files that it needs to run properly). For example, if I were to use a third-party library in the form of a .jar file, should I include that .jar file in the repository so that my code is ready to run when someone clones it, or is it better to just make a note that you are using such-and-such third-party libraries and the user will need to download those libraries elsewhere before they begin work. I am just trying to figure at the best practices for my code commits.
Thanks!
Basically it is as Chris said.
You should use a build system that has a package manager. This way you specify which dependencies you need and it downloads them automatically. Personally I have worked with maven and ant. So, here is my experience:
Apache Maven:
First word about maven, it is not a package manager. It is a build system. It just includes a package manager, because for java folks downloading the dependencies is part of the build process.
Maven comes with a nice set of defaults. This means you just use the archtype plugin to create a project ("mvn archetype:create" on the cli). Think of an archetype as a template for your project. You can choose what ever archetype suits your needs best. In case you use some framework, there is probably an archetype for it. Otherwise the simple-project archetype will be your choice. Afterwards your code goes to src/main/java, your test cases go to src/test/java and "mvn install" will build everything. Dependencies can be added to the pom in maven's dependency format. http://search.maven.org/ is the place to look for dependencies. If you find it there, you can simply copy the xml snippet to your pom.xml (which has been created by maven's archetype system for you).
In my experience, maven is the fastest way to get a project with dependencies and test execution set up. Also I never experienced that a maven build which worked on my machine failed somewhere else (except for computers which had year-old java versions). The charm is that maven's default lifecycle (or build cycle) covers all your needs. Also there are a lot of plugins for almost everything. However, you have a big problem if you want to do something that is not covered by maven's lifecycle. However, I only ever encountered that in mixed-language projects. As soon as you need anything but java, you're screwed.
Apache Ivy:
I've only ever used it together with Apache Ant. However, Ivy is a package manager, ant provides a build system. Ivy is integrated into ant as a plugin. While maven usually works out of the box, Ant requires you to write your build file manually. This allows for greater flexibility than maven, but comes with the prize of yet another file to write and maintain. Basically Ant files are as complicated as any source code, which means you should comment and document them. Otherwise you will not be able to maintain your build process later on.
Ivy itself is as easy as maven's dependency system. You have an xml file which defines your dependencies. As for maven, you can find the appropriate xml snippets on maven central http://search.maven.org/.
As a summary, I recommend Maven in case you have a simple Java Project. Ant is for cases where you need to do something special in your build.

Maven compile dependency instead of taking it out of the local repo

I am sorry i don't know maven good enough for the complex environment i am currently working in (1k+ applications, most of them are Java EE). I still give it a try to describe what i want to archive:
0.) There is a company framework that abstracts the Java EE World a bit and is used in all the Java EE components
1.) I checked out the maven project of the Java EE component i am working with
during the build it downloads the dependencys of other components out of the companys repository and stores it inside my local repo for compilation. So i can see the jar-files of the companys framework inside my local repo.
2.) I now want to change some of the frameworks functionality for a local test so i checked out their sources from another SVN repository. I made the changes and build that framework component with maven "clean install".
3.) I rebuild the component i am working with as well.
Inside eclipse i can now click on one of a frameworks classes method and it opens the according source. But this only happens because the local repo is meant to contain source-jars for any dependency as well. So in my editor i can see this source is from the jar of the framework in my local repo and i cant change anything.
Could someone please give me a hint how i can archive the following:
I can make changes to the framework (and build the frameworks jars with "clean install")
I can build my component and it uses the above compiled framework jars rather than the "old" ones from the local repo.
I will right now start to read the entire maven documentation and each and every section (i try to understand that dependency management since 1 year and still don't get it) but i would really appreciate if you could help me out a bit here.
I don't know how Eclipse manages maven dependencies, but
In IntelliJ IDEA this is simple - if maven dependency is in project then IDEA uses it instead of dependency from local repo.
So if u want to edit framework source code and use this changes immidiately - i think that framework should be in your Eclipse Workspace. And your module in Eclipse should reference framework artifacts directly - not over Maven dependency mechanism.
I think that this is a Eclipse Maven plugin responsibility. Do u have any installed Maven plugin for Eclipse? (M2Eclipse for example)

Maven requires manual dependency update?

I'm new to Maven, using the m2e plugin for Eclipse. I'm still wrapping my head around Maven, but it seems like whenever I need to import a new library, like java.util.List, now I have to manually go through the hassle of finding the right repository for the jar and adding it to the dependencies in the POM. This seems like a major hassle, especially since some jars can't be found in public repositories, so they have to be uploaded into the local repository.
Am I missing something about Maven in Eclipse? Is there a way to automatically update the POM when Eclipse automatically imports a new library?
I'm trying to understand how using Maven saves time/effort...
You picked a bad example. Portions of the actual Java Library that come with the Java Standard Runtime are there regardless of Maven configuration.
With that in mind, if you wanted to add something external, say Log4j, then you would need to add a project dependency on Log4j. Maven would then take the dependency information and create a "signature" to search for, first in the local cache, and then in the external repositories.
Such a signature might look like
groupId:artifactId:version
or perhaps
groupId:artifactId:version:classifier
This identifies a maven "module" which will then be downloaded and configured into your system. Once in place it adds all of the classes within the module to your configured project.
Maven principally saves time in downloading and organizing JAR files in your build. By defining a "standard" project layout and a "standard" build order, Maven eliminates a lot of the guesswork in the "why isn't my project building" sweepstakes. Also, you can use neat commands like "mvn dependency:tree" to print out a list of all the JARs your project depends on, recursively.
Warning note: If you are using the M2E plugin and Eclipse, you may also run into problems with the plugin itself. The 1.0 version (hosted at eclipse.org) was much less friendly than the previous 0.12 version (hosted at Sonatype). You can get around this to some extent by downloading and installing the "standalone" version of Maven from apache (maven.apache.org) and running Maven from the command line. This is actually much more stable than trying to run Maven inside Eclipse (in my personal experience) and may save you some pain as you try to learn about Maven.

Categories