IntelliJ IDEA with Kotlin cannot access class required by another module - gradle

I'm creating a new Kotlin project with multiple modules and there are issues when I try to run one of the modules from IntelliJ IDEA.
To leave the structure simple, I got module A and module B.
module B configures and returns log4j2 Logger instance.
module A is calling module B method to get logger and uses Logger directly after this.
When I create a fat jar and launch methods from module A everything works fine and logging is working but when I try to launch module A method from IntelliJ IDEA I'm receiving an error from Kotlin:
Error:(6, 29) Kotlin: Cannot access class 'org.apache.logging.log4j.Logger'. Check your module classpath for missing or conflicting dependencies
Both modules are configured using Gradle and module A got module B as dependency:
dependencies {
implementation(project(":moduleB"))
}
From my understanding, IDEA should be able to understand the requirements of module B and load them automatically when executing the code that uses module B, no?
Am I missing something?

The problem turned out to be with log4j declaration in module B.
Initially, it was declared as:
implementation("org.apache.logging.log4j:log4j-api:2.11.1")
So, this dependency was not exposed to module A.
After changing to:
compile("org.apache.logging.log4j:log4j-api:2.11.1")
No more error is produced.
Strange thing is that using api configuration instead of compile doesn't work (though, according to documentation, these are the same configurations). Looks like current IDEA Gradle plugin duoesn't support new configuration naming.

Related

adding other modules in classpath for a Gradle plugin task

I have a Gradle plugin that works well so far, however, I am facing an issue in a multi-module project.
The plugin runs its task in every module of the project, but sometimes, I need to access classes from other modules to analyze them - typically, in the context of hexagonal architecture, I want to perform some checks on classes in infrastructure that implement an interface defined in domain module.
So, when the task runs (after the tests) within infrastructure module, it finds the class. But it's not able to load the interface (from domain) that the class implements. When I do :
Object interfaceLoadedDynamically = Class.forName(i.getName());
I clearly see it can't be loaded, and that prevents me from performing the checks I need to do.
here are :
the plugin
the task
Is there a way to configure one of them to say : "when you run within a module, make sure all the other project modules that have been compiled before are available in the classpath" ?
I've seen maybe I could use Gradle's Configuration , but I am really not sure where/how to start.

maven test dependencies of dependencies

I have a large project and i want to add an integration tests module which will depend on every thing and validate interaction between modules.
The issue is that during the test I'm missing the dependency classes
module A uses module B
I have a test on module A testing something that uses module B, and I'm getting an error stating it can't find classes in module B.
I tried surefire but there is no difference.
I know I can and I should mock the classes in B which aren't part of the test but I want a full test that will test everything.
As official Maven documentation declares test scope is not transitive. You need to declare required dependencies explicitly in the pom file(s).
You cannot change this behaviour, but there is usually no need to change this behaviour.
If you want to write a library that is used for testing, then this library should have compile dependencies, but when you use it, declare it with scope test.

Gradle with Java 10 (Spring able to scan module classes even when package not exported)

So I am playing around with Spring and Java 10 along with Gradle.
In my application, I created 2 modules
UI
Application
The application module's gradle file looks like this
dependencies {
compile project (':ui')
}
And module-info file looks like this
module application {
requires spring.context;
requires spring.boot.autoconfigure;
requires spring.boot;
}
In my UI module, the build.gradle looks like this
dependencies {
compile('com.vaadin:vaadin-spring-boot-starter')
}
dependencyManagement {
imports {
mavenBom "com.vaadin:vaadin-bom:${vaadinVersion}"
}
}
And module-info looks like this
module ui {
requires vaadin.server;
requires vaadin.spring;
}
So my UI code lives inside ui module. As you can see, I am not exporting any package outside from the ui module and application's module-info also doesn't require ui.
In the main class I added
#ComponentScan("com.factory_manager")
And magically it's able to scan the UI module and the vaadin UI classes and I am able to access them via their respective endpoints.
From my understanding, the application module should not be able to read ui module's classes as I am not exporting any package outside.
Does anyone has any idea on how spring is magically able to scan the ui module and find the ui classes?
And yes, I am unable to access UI module's classes inside my application module but spring somehow is able to..
Not very gradle specific, yet a probable reason for this could be your dependency code -
dependencies {
compile project (':ui')
}
Due to which the ui module classes are present on the classpath instead of the module path and are under the unnamed module.
To correlate further, the unnamed module exports all of its packages and hence you're able to access those classes without exporting them.
Top of my mind, one way you can confirm this is, by trying out something like -
<yourClassFromUIModule>.class.getModule().isNamed(); //should return false

Maven, NetBeans Platform, Wrapper Modules and Annotation Processors on dependencies

I have a Maven NetBeans platform application. One of its modules is a wrapper to a java project (jar) that exposes some services to the Lookup. In the wrapped project I use the maven-processor-plugin to process the annotations so everything gets registered in the Lookup. I’m unable to see the exposed classes on the wrapped module. I tried running the maven-processor-plugin but it is skipped since there are no source files in the wrapped module. Even if there were it wouldn’t fix the problem.
You can get the code here, in the Marauroa Server Manager project, Module: jWrestling Wrapper.
The code for the wrapped module can be found here. Annotated classes within the modules work fine.
Is there a way to execute the annotation processors on the dependencies of a project? Am I missing something obvious?
the wrapped jar project cannot contain nb.org annotations. these generate META_INF/generated-layer.xml file that is only read from a MODULE jar, not the wrapped non-module jar
the binary dependency contains some netbeans-originating annotations? and you want to process it through the maven plugin? that won't work. Most if not all netbeans annotations are compile-time only, meaning that they are processed at compile time and not retained in the bytecode. so only su
Besides for Netbeans annotations (which are based on jdk 1.6 annotation processors, you don't need the processor plugin, compile plugin should be sufficient.

Multiple reusable modules in maven

I have a couple of java modules set up in IDEA and I am wanting to mavenize them. These java modules use classes from one another.
I was not quite sure how I should take up this and I decide to add modules on a maven project using IDEA. Hence first I created a maven project, let's name it pm1 which has a class let's name it TempClass1. Now this class can be used in other maven project. Hence I added another maven module - pm11 and tried to use TempClass1 with in pm11. It worked and I notices that IDEA had added module dependency of pm1 in pm11. So whole structure looks as -
But now when I do mvn test from pm11 then it fails with error message package package1 does not exist and it looks to me that it is because package1 is in a different maven project. And I am not sure how I could use classes which reside in a different maven project. I hope I am clear in my question.
You can use classes of other maven projects, as long as there's a proper maven dependency defined in pom.xml. Ensure that the dependency is defined and its' scope is either undefined or relevant (You may have problems if the scope is provided for example).

Resources