How does the Intellij Idea change the scope of dependencies? - maven

I found this function in Project Structure in Intellij Idea:
It seems that this UI can manually change the scope of the dependencies. However I found that it does not change the pom.xml file, so how can it manages to change the scope?
Besides, what is the corresponding operation in Linux?

That particular view is geared more towards projects which lack dependency management from something like Maven or Gradle, and will not interfere with either. In fact, this particular listing is built based on those dependencies and exclusions.
If you want to change the scope of your dependencies in a project that already contains Maven and Gradle, look to do so in their respective files (pom.xml / build.gradle).

Related

How can i publish just a build script in gradle?

I want to publish a common build script which i will include across various projects in my application.
This will contain only the common set of dependencies, i.e dependencies with particular versions that will be common across all the artifacts in my enterprise application..
My applications will refer to this file from the url.
How can i achieve this?
EDIT1: my exploration in this direction is based on this answer on SO:
How to share a common build.gradle via a repository?
There are a few different options for this.
One is to publish a project with the dependencies you want to share defined as API dependencies. Projects that depend on this will inherit the dependencies.
Or you could write and publish a Gradle plugin that will configure your projects with the common dependencies. Projects can apply the plugin, and will automatically be configured in a certain way. (You don't need to publish a plugin to do this - first try creating a project-local buildSrc convention plugin.)
I would actually recommend neither of these approaches.
It's easy to get into a tangled web of dependency hell when transitive dependencies are inherited. It's likely that at some point some dependency will clash, and excluding dependencies can be a big headache, and will easily cancel out any benefit in trying to reduce a little duplication.
Additionally, it's nice when a project is explicit about its dependencies. Being able to look at a build.gradle.kts and understand exactly what dependencies are set is very convenient.
Instead, what I would recommend is controlling the versions of common dependencies in a central location. This can be achieved with the Java Platform plugin. This plugin can be applied to a single build.gradle.kts file, and it lists all versions of all possible dependencies. (It can also import existing Maven BOMs, like the Spring Boot BOM).
Now, all subprojects can add a platform dependency on the 'Java Platform' project.
dependencies {
// import the platform from a Maven repo
implementation(platform("my.company:my-shared-platform:1.2.3"))
// or import a platform from a local project
implementation(platform(":my-project:version-platform"))
// no need to define a version, if it's defined in the platform
implementation("com.fasterxml.jackson.core:jackson-databind")
}
This is the best of both worlds. Projects can be explicit about their dependencies, retain autonomy, while the versions can be aligned across independent projects.

How to correctly import a Maven dependency that I altered and re-built into an existing project?

I have a Maven dependency, pulsar-log4j2-appender, which I forked and changed the source code because it was throwing exceptions in my project.
After changing the source code, I ran the maven package command to build the jar and imported it into my project (in Intellij: Project Structure | Modules | Dependencies | Add JARs or directories...).
However, when I run the application, it seems like it's not able to find that dependency because the Pulsar appender which I declared in my log4j2.xml file isn't being configured.
Am I importing the JAR properly? I'm wondering if the JAR needs to be within the org.apache.pulsar namespace to be imported properly.
For example,
This is what the dependency looks like unaltered:
And this is what it looks like when I modify and build it myself:
If you modify the code from an open source project you should change both the groupId and the artifact id. If you do not you will have problems and future developers will say your name in ways you do not want to hear.
Changing these are necessary so that Maven knows to use your version instead of the publicly available version. Also, when people look at your project and see the groupId and artifactId from the "real" project they will naturally assume that is what is being used (which is why they will curse you if that is not the case). In addition, you will have to do something convoluted to get Maven to use your dependency reliably.
The practice I have followed is the prepend "com.mycorp", where mycorp is my employer's name, to the groupId and add mycorp into the artifactId. The only downside to this is that you must ensure that the "real" artifact's coordinates are not referenced as a dependency or as a transitive dependency or else you will have duplicate classes on the class path.
Finally, your best bet is to create a pull request for Apache Pulsar with your fix so that other people experiencing the same problem you are get the benefit of it.

Is it possible to force a Maven plugin to be included in a project from a dependency of that project?

I have three Java projects. The first is an application, com.foo:foo-application:1.0.0, and the second is a module used as a dependency to that application, com.foo:foo-framework:1.0.0. The third is a Maven plugin authored by our team, com.foo:foo-plugin:1.0.0.
My intention is that any project, e.g. foo-application, which uses classes available in foo-framework must also validate that it has used those classes correctly, where said validation is enforced by foo-plugin.
Is there a way to enforce this behaviour within foo-framework's POM.xml, whereby any Maven module which declares it as a dependency in its own POM will have foo-plugin executed as part of its build lifecycle?
No (at least no way that I'm aware of).
when you declare a dependency on something, youre declaring a dependency on its output artifacts (and transitively their dependencies as optionally described in that artifact's pom.xml file). There's no place in a pom file to force anything on the build importing it - the build importing it may not even be a maven build.
it appears you may be able to do something similar via other tools though - for example checkstyle supports discovering rules from dependencies on the classpath (not exactly what you want and depends on users of your library running checkstyle configured just right)

Gradle share dependencies in a cascade manner between related projects

I have the following Java projects structure:
Util
|
-- Core
|
-- Services
|
-- Tools
The projects: Tools and Services references to Core and Util projects, the thing is that I ended up writing the same dependency over each project, there must be a better way to inherit the dependencies of the referenced projects and add new ones if needed.
I know about multi projects in Gradle, but this is not like a multi project, since I can basically take the Core library, compile it (which will then contain Core + Util libs) and use it in another project.
I wonder what would be the best way to approach this?
Repeating the same dependencies in every project is usually reasonable because in a bigger project you'll never know when they become different, and you don't want to deal with compilation/runtime problems when someone changes common dependencies list.
I believe that it is more pragmatic to add dependency analyser plugin to your build. It will help you to remove unnecessary dependencies and explicitly add transitive dependencies. And if you add this plugin to your build chain, it will help you to keep your dependencies healthy in the future. Pick this plugin here gradle-dependency-analyze, or maybe there is a better fork or equivalent somewhere.
You are actually out of options in your case because there are only two kinds of dependencies: (1) external (some other jar artefact) or (2) internal (another module in a multimodule build).
2.1 When you use an external maven-like dependency it will come to you with own dependencies (they are named "transitive dependencies"). It means that if you do compile 'yourgroup:Core:1.0' then you will get Util as a transitive dependency. But as I mentioned above, it is better to list transitive dependencies explicitly if they are used during compilation or to prevent them from being accidentally removed and crash your application in runtime.
2.2. If your projects live in the same version control repository and usually change and build together, then the multimodule layout is your best choice. In this case, you will refer to Core dependency like compile project(':Util:Core') and it will grab Util as a transitive dependency as well. And you will be able to do what you asked for and define dependencies for Services and Tools once - inside subprojects {} closure in the Core/build.gradle.
Having multimodule built doesn't limit you from using Core library elsewhere. No matter if it is a multimodule build or not, you can always add maven-publish plugin to Core/build.gradle, execute publishToMavenLocal task and reference to Core.jar from another project the same way you do for external dependencies.
You can always put your common code (like the one which will add common dependencies) in the external gradle file or custom plugin and apply it in Services and Tools.

POM files to use

I'm going to be building a project from the Spring Examples package. Specifically, I am going to be building onto the Simple JPA Example. When I view the POM file however I notice that it references a parent, which contains pretty much every Spring project you can imagine.
Is there a way to tell which POM files I need in order to have the 'Simple JPA Example' project work?
EDIT:
This is why Maven needs to go away!
You can move all the dependencies into the project's pom, remove the reference to the parent pom, then use the maven dependency plugin's analyze goal to sort out what you need. There are examples and a rather nifty script referenced from this popular SO question.
Which parent pom is it (and which sample)? If it's this one have another look at the parent - it doesn't define any dependencies, only dependency management, so that you get a consistent set of versions of everything without having the specify versions in your own dependencies. It's quite a common pattern (look for a blog on "bill of materials" configuration). See also docs on how to use your own parent.

Resources