When the phrase "is on the classpath" is used in boot documentation, can I get a precise meaning for this for a linux person building a spring boot maven project?
it is not clear about the context in time: is it talking about compile or run time or repackage time or what?
does it mean that a jar/manifest is in a subdirectory of the current project directory such as the target/...classes
does it mean that the jar is in the pom
for a newbie, I read the wikipedia and oracle explanations but this seems to mean something different or it means that i should be born with the knowledge of some sort of modifications to the classpath made by maven during the build process.
or what about during run time for a repackaged jar?
Is there anybody who would have mercy on a newbie and help me on the term?
I try to answer your questions:
You can have a compile classpath as well a runtime classpath (Maven also has a test classpath). They can be different, so it depends on the context, which one is meant.
Technically it doesn't matter, what the directory structure is, since you can add every directory on your disk to your classpath.
If you use Maven, then only JARs, that are defined in the POM, are automatically added to the compile classpath (which is also used for packaging).
Maven uses different classpaths during the build. E.g. for compiling it uses all dependencies in provided or compile scope and adds them to the classpath. For testing, additional dependencies in the test scope are added to the classpath to compile and execute tests.
Related
We are running our Java EE applications in WAS 8.5 and Gradle 5.* to build them.
In the past we packaged our .war application in an .ear archive, which we then deployed on our server. We had to separate our libraries from our applications and include them as shared libraries, because in our experience it made deploying much slower and in some cases used up all system memory, crashing the server.
After some experimentation, we realized that we don't need to extract the dependencies into shared libraries, because we can include them in the lib folder of our .ear archive.
Currently, we get this done by defining the dependencies of our .war application as compileOnly and redefining them as earlib in the root project (which generates the .ear archive). I'm looking for a way to automate this procedure.
The script I used looks something like this:
project.configurations.named('deploy').getAllDependencies().withType(ProjectDependency.class).forEach({dependency ->
project.configurations.named('earlib').getAllDependencies()
.addAll(dependency.dependentProject.configurations.named('earlib').getAllDependencies())
})
// This loosely resembles the actual code I used. The thought process is right, it just might have a couple syntax errors.
// Obviously, I defined an `earlib` configuration in the subproject
I tried running this code in the configuration phase, as well as in the doFirst{} section of the ear task. They all had different problems.
The former didn't work, because it seems like in the configuration phase when this code ran, the dependencies weren't configured yet.
The latter didn't work, because I can't just add dependencies during runtime (thinking back, it sounds ridiculous that I even tried it).
My question is: Can I find a phase in the build lifecycle, where I can find and modify the dependencies? Is there another workaround to solve my problem?
The technical answer to your questions is that you can use either:
A configuration.incoming.beforeResolve hook to do it last minute, only when the configuration really needs to be resolved.
Use an afterEvaluate block, assuming all the other dependencies are not defined in an afterEvaluate themselves.
However, the right solution would be to leverage the dependency management engine of Gradle and effectively declare that your root project, the one building the EAR, has dependencies on the specific configurations of the subprojects.
Not knowing your full setup and details, I believe the above would still be the more correct solution, though you may have to filter the subproject artifacts from the resulting graph.
Ideas on how this works in recent Gradle version: https://docs.gradle.org/6.2/userguide/cross_project_publications.html Most of the things explained there should work with the latest 5.x versions.
I use both Intellij IDEA (2018.3.5) & Eclipse IDEs, but I prefer Intellij. I have a maven based Java project with multiple poms. I added some dependencies to one of the pom files. I need to find out if there are any dependency conflicts which could prevent the build from running when its deployed, and then exclude them. I tried the steps given below to find conflicts which could cause problems. Are they enough or do I need to do more ?
Check if there are any compile time dependency conflicts with mvn clean install -DskipTests. Build was successful with no errors.
Check if Intellij shows no problems under File > Project Structure > Problems. There are no problems.
I also saw the dependency tree with mvn dependency:tree -Dverbose. It has a lot of "omitted for duplicate" and "omitted for conflict with" items, but the build was successful. I don't see any errors though. Does this mean that everything is okay or do I have to do something more about these conflicts ?
The best way to tell if everything is fine with your application is to have good tests.
However normally one doesn't exclude transitive dependencies from project's <dependency> libraries. Doing it can potentially break the dependency in a subtle and hard to notice way. It's usually safer to remove the whole <dependency>.
There are few scenario when one should use <exclude>:
Dealing with incompatible transitive dependencies between different libraries e.g. A requires library C-1.0 but library B requires library C-2.0 while C-1.0 and C-2.0 can't coexist on the classpath.
Having transitive dependencies already provided by system e.g. deploying to Tomcat with additional JARs in the TOMCAT_HOME/lib directory.
If you decide to exclude a dependency it's important that you check the final artifact because sometimes plugins do weird things e.g. there were versions of maven-assembly-plugin affected by a bug that resulted in different dependencies being resolved during shaded JAR creation than maven-dependency-plugin used for compilation.
I experimented with webservices and jboss4 for the last couple of days, and I stumbled over the following problem:
I included this dependency in my pom.xml:
<dependency>
<groupId>org.jboss</groupId>
<artifactId>jboss-jaxws</artifactId>
<version>4.2.2</version>
</dependency>
As it turned out, this caused JBoss4 to fail with the error message
java.lang.IllegalStateException: Cannot find endpoint meta data
Until I added the tiny little line
<scope>provided</scope>
to the dependency. I now understand that this problem was caused by the fact, that JBoss4 brings this library himself, and that it is the double inclusion of the same library (probably 2 different versions) that caused this. But now, when I look into the JBoss lib folder I see the following files:
commons-codec.jar
commons-httpclient.jar
commons-logging.jar
concurrent.jar
endorsed
getopt.jar
jboss-common.jar
jboss-jmx.jar
jboss-system.jar
jboss-xml-binding.jar
log4j-boot.jar
How do I know which jars correspond to which maven artifact? How do I know for any of the million files in my .m2/repository folder which groupid, artifactid and version number they belong to?
All the jar files in provided/included by Jboss are not related to maven. They are there just for the sake for jboss it self to run. Other application who wants to run in the container need to provide they own sets of library. BUT, some time, some of the library provided by JBoss is enough for the application (since they will live on the same VM), so you dont need to provide your own. You use those provided library for your development purpose, and later, when you deploy, you dont include them in your deployment.
So, there are no telling which Jar, provided by JBOSS should relate to which artifactId or groupId or version in the maven repositories, unless for some hint on their names.
For example, if you see that Jboss brings "commons-codec.jar" with it. There are no telling that the jar comes from which artifactId or groupId or version in Maven. You may guess that "commons-codec" should be a name of some artifact. Sites like http://mvnrepository.com/ helps you to find what related maven artifact that may relate to the jar you are investigating.
The artefact name is always ${artifactId}-${version}.${type}
in your case : jboss-jaxws-4.2.2.jar.
You're just looking for it in the bad place, the lib folder you're talking about must be the one of the unified classloader, the library you're looking for must be loaded by the server classloader i.e. it must reside in JBOSS_HOME/modules
[edit]
Ferdinand Neman is right when he says that jboss is not related to maven. Dependencies declaration in pom just allows maven to build and package your project. The runtime behavior depends on your targeted environment, the only things to ensure is that your dependencies must be resolved during classloading whether because they are packaged with your project or provided by the runtime environment.
Anyway the jar jboss-jaxws-4.2.2.jar will necessary be present on your workstation (in the local maven repository) to allow class linkage during maven compilation, as the jar is marked as provided it will not be included in the resulting build artefact.
Maybe you find useful this maven command
mvn dependency:tree -Dverbose
It shows you jar dependencies, classified by group-artifact and it also represents dependencies between them as a tree.
I have a web project and a pom.xml file. It has enough dependencies to compile and package but not enough to start the project. In my IDE it's shown that everything is ok, but when a start the application it has errors. When i add external pom.xml from another app, my application launches.
So is there any way i can find out which dependencies are missing and how in future i can determine which dependencies are needed for using this or that?
You can use mvn dependency:analyze for determining which dependencies are used and declared or used and undeclared or unused and declared.
For more information refer to: http://maven.apache.org/plugins/maven-dependency-plugin/analyze-mojo.html.
Hope this helps.
There's no maven command to accomplish this. You need to check which classes are causing NoClassDefFoundError, figure out the dependency (Google) - which JARs they are shipped in, and add them with the runtime scope in your pom.xml.
In web projects specifically you oftentimes compile against servlets or Java EE specification JARs (they would only contain interfaces), but you need actual implementation JARs to be present in runtime. These JARs are typically and presumed to be available in the container you are running in (like Tomcat or JBoss), in this case they would be marked as provided scope in your pom.xml.
You need to check the NoClassDefFoundError in your output logs and add dependencies accordingly.
The best resource to search for missing dependencies is Maven Central Repository
To get a detailed debug log of your build, use -X in the command line.
You can check The dependency tree of your project by following command - mvn dependency:tree. This will only list the information about the deoendencies listed in your pom.xml More on it here
should be able to do it with :
maven dependency resolve
I am new to Hibernate 3 and I don't understand the difference between
1) *http://sourceforge.net/projects/hibernate/files/hibernate3/
and
2) *https://repository.jboss.org/nexus/content/groups/public/
when it comes to compiling Hibernate tutorial files.
I am following Hibernate tutorial from *http://docs.jboss.org/hibernate/core/3.6/quickstart/en-US/html_single/
As I understand there is no setup.exe for Hibernate 3. I assume that instead of having setup.exe I need to set classpaths to get my Hibernate 3 installed.
I have downloaded release of Hibernate from the list at *http://sourceforge.net/projects/hibernate/files/hibernate3/. It's more than 140 MB. After having unzipped this 140 MB file I didn't set any classpaths. I downloaded tutorial code from *http://docs.jboss.org/hibernate/core/3.6/quickstart/en-US/html_single/files/hibernate-tutorials.zip, unzipped it and edited pom.xml in this way that this tutorial would use two repositories like
1) *http://repo1.maven.org/maven2/
and
2) *https://repository.jboss.org/nexus/content/groups/public/
Then I typed mvn compile and build was succesful!
How is it possible that this build was succesful? I didn't set any classpaths which means that Hibernate 3 (that 140 MB file) was not included in my project's classpath. Moreover I don't understand what means to include in my project's classpath? Does it mean that under Windows XP I should set environment variables like:
1) path/to/hibernate3.jar
2) path/to/lib/required/
3) path/to/lib/jpa/
When I added these three paths to environment variables it didn't change anything - mvn compile worked the same way as before. Did I set this classpath in the wrong way?
In my point of view it seems to me that it is not necessary to download Hibernate 3 (140 MB) at all and all the files that were necessary to build this hibernate application (tutorial file) successfully were downloaded from repositories.
What do I misunderstand?
Thanks in advance!
You need to read up on how Maven works. There is an excellent free PDF called Better Builds with Maven that will explain it all in some detail, however here is a quick overview to help you along.
Maven is a build system
So it manages how to build your project. This comes from the configuration details you put in the pom.xml. You defined dependencies and Maven knows how to find them as a result either you configuring those locations, or Maven relying on it's own default locations. (This is where the http://repo1.maven.org/maven2/ is coming from).
Maven builds in defined phases, with each phase relying on the one before it. In order these are (simplified for easy presentation):
Clean - wipe out any previous compilation work (usually in "target") and start afresh
Copy resources - copy everything under src/main/resources to target/classes
Compile - compile everything under src/main/java to target/classes
Test - run the tests under src/test/java (using src/test/resources if required)
Package - build the target artifact (JAR, WAR, EAR etc)
Install - put the artifact into the local repository (to share with other local projects)
Deploy - put the artifact into the team repository (to share with everyone else)
From the above, it should be clear that specifying Hibernate3 as a dependency in your Maven pom.xml will instruct Maven to go off and look in your local repository for the necessary JAR files that make up Hibernate. If it can't find them there it'll look in the team repository (if mentioned in your .m2/settings.xml file). If not there then it'll download them from Maven central (http://repo1.maven.org/maven2/).
Maven uses the concept of transitive dependencies meaning that your project depends on Hibernate, but Hibernate depends on CGLIB which in turn depends on, say, ANTLR or something. You don't have to think about that, Maven takes care of bringing in all the relevant JARs you need to make your project work.