Gradle build ignores Jetbrains annotations - java

Let's say we have the following test code:
import org.jetbrains.annotations.NotNull;
import org.junit.Test;
public class NullTest {
#Test
public void testNull() {
doNothing(null);
}
private #NotNull String doNothing(#NotNull String value) {
return value;
}
}
The test will pass when running gradle test directly or if IDEA delegates the action to gradle.
But it will fail with IllegalArgumentException: Argument for #NotNull parameter 'value' must not be null exception if it runs using IDEA runner (not delegated to gradle).
The question is: how to fail the test running it with gradle?

The easiest solution I have found is to apply org.jetbrains.intellij plugin.
Because among other things this plugin "patches compile tasks to instrument code with nullability assertions".
apply plugin: 'org.jetbrains.intellij'
intellij {
instrumentCode = true
downloadSources = false
}

Try adding the following to your dependencies. It worked for me.
compile 'org.jetbrains:annotations:13.0'

With this code - no way, because you use annotations from org.jetbrains.annotations.*, that use only in intellij idea tests runner. For gradle, annotation #NotNull (or #Nullable) says nothing. Maven also doesn't see this annotation. I can advise you use Objects.requireNonNull(T obj) for null checking.

We found that Lombok's #NonNull works better. But you need to configure IDEA to prefer this one during nullability-related analysis and generation

Adding the following dependency worked for me:
compile group: 'org.jetbrains', name: 'annotations', version: '15.0'
Run the 'dependencies' task & push the refresh button in Gradle.

Related

can't figure out the java annotation processor

I'm trying to deal with annotation processors. I followed tutorials. Here is my code:
#ExampleAnnotation
private void someMethod(){
System.out.println("hi");
}
#Retention(RetentionPolicy.SOURCE)
#Target(ElementType.METHOD)
public #interface ExampleAnnotation {
}
#SupportedAnnotationTypes("org.example.ExampleAnnotation")
public class Processor extends AbstractProcessor {
#Override
public boolean process(Set<? extends TypeElement> anots, RoundEnvironment roundEnvironment) {
anots.forEach(System.out::println);
return true;
}
}
I created META-INF/SERVICES/javax.annotation.processing.Processor
and registered my processor: org.example.Processor. It seems like everything is OK, but block of code in the processor just dont start. I have no idea what is wrong. P.S.: I use Gradle and Java 11.
i fixed my issue and decided to make a little step-by-step tutorial to create simple JAP:
Java-Annotation-Processor-guide
This is guide for annotation processing using gradle
I spent 3 days trying to deal with it, but with this little tutorial you will made JAP in 5 minutes.
sorry for bad english :)
So, first you should do is create gradle subproject for your project:
create project itself with gradle init or intellij
add to your main project's settings.gradle file this line include "*your subproject name, lets say:*annotation-processor"
Congrats, now let go to the processor itself
here is so much tutorials on the web about this part, so you can read something like this https://www.baeldung.com/java-annotation-processing-builde,
or this (Если ты русский): https://habr.com/ru/company/e-legion/blog/206208/
Final step is very easy - you will add your annotation processor to main project.
!!! instead of annotation-processor you should use your subproject name !!!
kotlin (or java + kotlin) -> {
add this plugin to your plugins: id "org.jetbrains.kotlin.kapt" version "1.7.21"
add this to your dependencies:
kapt project('annotation-processor')
compileOnly project('annotation-processor')
}
java -> {
add this to your dependencies:
annotationProcessor project('annotation-processor')
compileOnly project('annotation-processor')
}
(or you can read this on github: https://github.com/Blu3cr0ss/Java-Annotation-Processor-guide)

Conditional dependencies based on command line arguments

Not sure if this is a VSCode Java extension issue or not. We're trying to have conditional dependencies included depending on a specific Spring Boot profile we're passing in as a command line argument. It seems that when conditions are statically analysable, the Java language server is able to correctly provide intellisense, but when they are not, it fails. Here's an example, where when we use true/false, intellisense works, but when we use the commented out lines, it doesn't. I imagine this is the expected behaviour, and it still compiles fine, I'm just wondering if there's a way around making it work.
def profiles = (project.hasProperty('profiles')
? project.property('profiles')
: "local,https").split(",")
dependencies {
// if (profiles.contains("local") && !profiles.contains("tc")) {
if (false) {
runtimeOnly "com.h2database:h2"
}
else {
implementation "org.postgresql:postgresql:$DB_DRIVER_VERSION"
// if (profiles.contains("tc")) {
if (true) {
implementation "org.testcontainers:postgresql:$TESTCONTAINERS_VERSION"
runtimeOnly "org.testcontainers:testcontainers:$TESTCONTAINERS_VERSION"
testCompile "org.testcontainers:junit-jupiter:$TESTCONTAINERS_VERSION"
}
}
}
Here's an example of what happens in a test file
// this import fails with intellisense, since the dependency is
// not included when using conditional dependencies based on CLI arguments
import org.testcontainers.junit.jupiter.Testcontainers;
#Profile("tc")
// #Testcontainers
public class SampleIntegrationTest {
I should reiterate though, that this isn't a problem during normal build/run, it's just intellisense that doesn't work very well.

Is there anyway in Idea to recognize a getter/setter generated by lombok in the same module

So looking at my class files the getters/setters are being generated just fine, but I'm trying to write a copy method that looks like this in the same jar.
#Data
public class SoftwareVersions {
private String applicationVersion;
void copyTo( MonitorFoleyConnection mfc ) {
mfc.setApplicationVersion( applicationVersion );
}
}
in gradle
annotationProcessor("org.projectlombok:lombok:1.+")
compileOnly("org.projectlombok:lombok:1.+")
is it possible to get intellij to recognize the existance of this method?
Yes, you have. You just need to do two things:
Install the Lombok Plugin for Intellij:
Enable the annotation processing:

IntelliJ suggests wrong #NotNull annotation

IntelliJ is suggesting to import com.sun.istack.internal.NotNull the #NotNull annotation (which is wrong) in the following program:
public class Test implements Comparable<Test> {
#Override
public int compareTo(#NotNull Test o) {
return 0;
}
}
When trying the correct import com.intellij.annotations.NotNull (I think) it looks like it can't find the class:
You can Alt+Enter on the warning before you add the annotation, press Right, choose Edit Inspection Settings, then Configure Annotations and specify the annotation you want to be inserted there.
Remove the import from the code. IntelliJ will ask you to import it again. It should suggest that there are multiple choices available. The annotation you want should be in the list.
I found I had to add the following dependency declaration to my Java project's build.gradle file before I was able to import the org.jetbrains.annotations.NotNull and org.jetbrains.annotations.Nullable annotations rather than the com.sun.istack.internal.NotNull and com.sun.istack.internal.Nullable annotations:
repositories {
mavenCentral()
}
dependencies {
compile 'org.jetbrains:annotations:15.0'
}
For later versions of Intellij, use Cmd+Shift+A (on MacOS) to bring up the Find Actions menu, then type Configure annotations, select the suggestion to bring up the Compiler preference window.
Then click on the Configure annotations button next to the option Add runtime assertions for notnull-annotated methods and parameters. It will then bring up the list of NonNull and Nullable configuration defaults. Select the one you want as default then set it as default with the check button.

Unable to run JUnit test with PowerMockRunner

I have a Gradle based Java project were I now want to mock a private method using PowerMock. The problem is that I am not able to use the PowerMockRunner as I always get the following exception when I add the #RunWith(org.powermock.modules.junit4.PowerMockRunner.class) annotation.
Error:
org.powermock.reflect.exceptions.FieldNotFoundException: Field 'fTestClass' was not found in class org.junit.internal.runners.MethodValidator.
at org.powermock.reflect.internal.WhiteboxImpl.getInternalState(WhiteboxImpl.java:581)
at org.powermock.reflect.Whitebox.getInternalState(Whitebox.java:308)
at org.powermock.modules.junit4.internal.impl.testcaseworkaround.PowerMockJUnit4MethodValidator.validate TestMethods(PowerMockJUnit4MethodValidator.java:79)
at org.powermock.modules.junit4.internal.impl.testcaseworkaround.PowerMockJUnit4MethodValidator.validate InstanceMethods(PowerMockJUnit4MethodValidator.java:49)
at org.junit.internal.runners.MethodValidator.validateMethodsForDefaultRunner(MethodValidator.java:51)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.validate(PowerMockJUnit44RunnerDelegateImpl.java:108)
...
This are my test dependencies:
testCompile 'junit:junit:4.+',
'org.powermock:powermock-core:1.5.6',
'org.powermock:powermock-module-junit4:1.5.6',
'org.powermock:powermock-api-mockito:1.5.6'
The test itself fails also when completely empty (initialization error):
#RunWith(PowerMockRunner.class)
public class SomeTest {
#Test
public void testSomething() {
}
}
Any ideas what might be wrong? Other tests using PowerMock are working fine (none of them uses the PowerMockRunner).
Greetings and thanks for any help!
Ben
This is a bug that occurs when you use JUnit 4.12 and PowerMock < 1.6.1. The problem is solved in PowerMock 1.6.1. Please update your dependencies accordingly
testCompile 'junit:junit:4.12',
'org.powermock:powermock-core:1.6.1',
'org.powermock:powermock-module-junit4:1.6.1',
'org.powermock:powermock-api-mockito:1.6.1'
If you cannot upgrade PowerMock then you can use JUnit 4.11.
testCompile 'junit:junit:4.11',
'org.powermock:powermock-core:1.5.6',
'org.powermock:powermock-module-junit4:1.5.6',
'org.powermock:powermock-api-mockito:1.5.6'
Could you please add further lines of the stacktrace, which uncover more details about the problem.
There has been a bug logged against PowerMock: https://code.google.com/p/powermock/issues/detail?id=531
It appears that JUnit changed some of its internal field names that PowerMock was accessing via reflection, thus breaking the ability for PowerMock to properly inject itself.
Check what Stefan said, and above that you also need to add
#PrepareForTest({<The class/es you are Mocking>, ...})
without the prepare for test, PowerMockRunner won't know which class is mocked.
There may also exist dependencies on classpath that override a JUnit specific class which contains JUnit's version. This leads to incorrect version comparison results in PowerMock. For instance, I had com.google.android.tools:dx:1.7 on classpath (came from hunspell library). It overrides following method return result:
junit.runner.Version.id() => "3.8.1"
Usually it should return something like "4.12" or "4.11" etc.

Categories

Resources