Intellij IDEA complains cannot resolve spring boot properties but they work fine - spring

Can not resolve configuration property '...
I have no problem accessing my properties through the #Value annotation or through an autowired Evironment. But all of my own defined properties get this warning in IDEA. What should I be doing to get IDEA to recognize these and not bother me?

In order for IntelliJ IDEA to know your Spring Boot properties, you can define Spring Boot configuration metadata in your project.
Option 1:
If you can use a #ConfigurationProperties-annotated class for your properties, you can add the Spring Boot configuration annotation processor to your classpath and IntelliJ IDEA will generate the configuration metadata for you in target or out:
Maven:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
Gradle:
implementation 'org.springframework.boot:spring-boot-configuration-processor'
Option 2:
Create the configuration metadata file yourself src/main/resources/META-INF/spring-configuration-metadata.json:
Content:
{
"properties": [
{
"name": "myapp.someprop",
"type": "java.lang.String"
},
{
"name": "myapp.someintprop",
"type": "java.lang.Integer"
}
]
}
Options 1 and 2:
In the IntelliJ IDEA tool window of your build system (Maven/Gradle), click the "Refresh" button.
Select Build > Rebuild Project from the menu.
If the warning still appears, you can try to restart the IDE. Select File > Invalidate Caches / Restart and click on Invalidate and Restart.

Please use the following for Gradle Kotlin Script for Kotlin project:
plugins {
kotlin("jvm")
kotlin("kapt")
}
/* ... */
dependencies {
val configurationProcessor ="org.springframework.boot:spring-boot-configuration-processor:${BuildConstants.springBootVersion}"
kapt(configurationProcessor) // for jar
kaptTest(configurationProcessor) // for jar
annotationProcessor(configurationProcessor) // for IntelliJ Idea
}
/* ... */
kapt {
annotationProcessor("org.springframework.boot.configurationprocessor.ConfigurationMetadataAnnotationProcessor")
}
/* ... */
tasks {
withType<KotlinCompile> {
dependsOn(processResources)
}
}
Kotlin Kapt is needed to work with metadata and memory.
From official Spring documentation, Spring Boot Configuration Processor generates special json file with properties metadata.
Therefore, to distribute jar with property syntax highlight you need:
Ask Gradle to generate this file
Update task sequence to generate file before jar packaging by using dependsOn (not sure, that my code above is the most effective solution, however problem is solved)
However IntelliJ Idea works with annotationProcessor Gradle configuration (unfortunately, I don't have exact answer, why it requires exact it). Therefore you need add the same processor into the annotationProcessor configuration as well.

I had the same problem plus not showing auto completion found out that it works with IntelliJ Ultimate edition and not community version. link
couple of useful steps to take would be:
adding Maven dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
refresh Maven to download dependencies.
coping exact name of property from target/classes/META-INF/spring-configuration-metadata.js to prevent errors.
making sure that your config class is annotated with #ConfigurationProperties("name-here") and that you have enabled it by #EnableConfigurationProperties(NameOfTheConfigClass.class)

A Gradle-based workaround is this:
afterEvaluate {
val kaptKotlinTasks = tasks.named("kaptKotlin") {
doLast {
val kaptKotlin = this
tasks.named<ProcessResources>("processResources") {
from(kaptKotlin.outputs) {
include("META-INF/spring-configuration-metadata.json")
}
}
}
}
tasks.named("processResources") {
this.dependsOn(kaptKotlinTasks)
}
}
After running a build (or just the processResources task) from the Intellij Gradle panel, the warnings about the properties should disappear.
Not ideal, but IntelliJ not supporting kapt is not ideal either :-/

As an additional requirement for the answers above. After Spring-boot 2.2 you can use final keyword on the attributes together with the annotation #ConstructorBinding in order to see IntelliJ auto-complete the property name on the application.properties file. IntelliJ also recognizes if you add a java docs on the attribute.
#ConfigurationProperties(prefix = "my-config")
#ConstructorBinding
public class ConfigImportService {
/**
* the name of the bucket
* (IntelliJ shows this comment on the application.properties file)
*/
private final String bucketName;
private final String databaseName;
#Autowired
public ConfigImportService(
#Value("${bucket.name}") String bucketName,
#Value("${db.name}") String databaseName
) {
this.bucketName = bucketName;
this.databaseName = databaseName;
}
}
And still necessary the dependency, of course.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>

Related

Can I pull the version for the Gradle org.springframework.boot plugin from my Gradle platform definition

I really like the Gradle java-platform feature. I've created my own platform that bundles spring-boot-dependencies along with other things. Now I have (shortened for clarity):
plugins {
id 'org.springframework.boot' version '2.4.1'
}
dependencies {
implementation platform("my-group:my-base-bom:1.0.0")
}
And I'd like the spring boot plugin version to automatically adjust to match the version of spring-boot-dependencies that is bundled in my platform (so if the platform went to SB 2.5.0 then plugin would do the same without my needing to change the build.gradle.
I can't figure out how to do it though without resorting to external variables. Is it possible?
Not possible. Currently, there are (3) ways to define versions for plugins:
In the Gradle file directly:
// build.gradle.kts
plugins {
id("org.springframework.boot") version "2.4.1"
}
In the plugins dependencies spec:
// settings.gradle.kts
pluginManagement {
plugins {
id("org.springframework.boot") version "2.4.1"
}
}
or with a resolution rule:
// settings.gradle.kts
pluginManagement {
resolutionStrategy {
eachPlugin {
if (requested.id.id == "org.springframework.boot") {
useVersion("2.4.1")
}
}
}
}
All of which do not accept a platform, only a single version variable.
Another way I tested, but ultimately did not work was utilizing the buildscript:
// build.gradle.kts
buildscript {
dependencies {
classpath(platform("io.mateo.sample:platform-bom:1.0.0-SNAPSHOT"))
classpath("org.springframework.boot:spring-boot-gradle-plugin")
}
}
As mentioned at the start, it's not possible.
Your custom platform can provide an opinion about which version of the Spring Boot Gradle plugin you want clients to use (especially since it's not included in the spring-boot-dependencies BOM).
Here are the relevant parts of an example platform's build.gradle.kts file, for example:
plugins {
`java-platform`
}
javaPlatform {
allowDependencies()
}
dependencies {
// This platform extends the Spring Boot platform.
api(platform("org.springframework.boot:spring-boot-dependencies:2.7.6"))
constraints {
// Provide an opinion about which version of the Spring Boot Gradle plugin clients
// should use since it's not included in the standard spring-boot-dependencies BOM.
api("org.springframework.boot:spring-boot-gradle-plugin:2.7.6")
}
}
That will generate a BOM that aligns both spring-boot-gradle-plugin and spring-boot-dependencies:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-gradle-plugin</artifactId>
<version>2.7.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.7.6</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Your client projects can then just depend upon your platform and inherit its opinion about the Spring Boot version using something like this:
buildSrc/build.gradle.kts:
// Pull in the version of the Spring Boot Gradle plugin specified by your
// platform, making it available to your regular build script.
dependencies {
implementation(enforcedPlatform("my-group:my-base-bom:1.0.0"))
implementation("org.springframework.boot:spring-boot-gradle-plugin")
}
build.gradle.kts:
plugins {
id("org.springframework.boot") // version inherited from your platform
}
dependencies {
// It's necessary to specify it for each configuration.
implementation(enforcedPlatform("my-group:my-base-bom:1.0.0"))
// Pull in any normal Spring Boot-managed dependencies you need (versions come from platform).
implementation("org.springframework.boot:spring-boot-starter-web")
}
Of course, you could also use Gradle version catalogs to centralize versions, which are inlined for clarity in the examples.

Implements Jmeter java request : ClassNotFoundException

I use dependency of jmeter 5.0 in my custom project pom .
<!-- https://mvnrepository.com/artifact/org.apache.jmeter/ApacheJMeter_core -->
<dependency>
<groupId>org.apache.jmeter</groupId>
<artifactId>ApacheJMeter_core</artifactId>
<version>5.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.jmeter/ApacheJMeter_java -->
<dependency>
<groupId>org.apache.jmeter</groupId>
<artifactId>ApacheJMeter_java</artifactId>
<version>5.0</version>
</dependency>
After compiling I copy jar to lib/ext in jmeter5.0 source project pulling from github , and debug by runing NewDriver, then i found the function org.apache.jorphan.reflect.ClassFinder.ExtendsClassFilter#isChildOf at Class.forName(strClassName, false, contextClassLoader) throw exception java.lang.ClassNotFoundException: com.xxxx.xxxx, strClassName has printed my own classs, so it means my class has been scaned?
private final ClassLoader contextClassLoader
= Thread.currentThread().getContextClassLoader(); // Potentially expensive; do it once
private boolean isChildOf(
Class<?>[] parentClasses, String strClassName, ClassLoader contextClassLoader) {
try {
// Here is exception line
Class<?> targetClass = Class.forName(strClassName, false, contextClassLoader);
if (!targetClass.isInterface()
&& !Modifier.isAbstract(targetClass.getModifiers())) {
return Arrays.stream(parentClasses)
.anyMatch(parent -> parent.isAssignableFrom(targetClass));
}
} catch (UnsupportedClassVersionError | ClassNotFoundException
| NoClassDefFoundError | VerifyError e) {
log.debug(e.getLocalizedMessage(), e);
}
return false;
}
My code
public class JmeterSupportTest extends AbstractJavaSamplerClient {
xxxx;
}
Anyone can help!
It is ok now. Couse of plugin compile which did not add depend jars , and config pom add maven-assembly-plugin will solve
If there are any extra libraries which are being used in your Java Request sampler implementation - they should go to "lib" folder of your JMeter installation (see JMeter Classpath user manual entry for more details) or you can think of using i.e. Maven Shade plugin to create "uber" or "fat" .jar containing all the dependencies
According to JMeter Best Practices you should always be using the latest version of JMeter so consider upgrading to JMeter 5.4 (or whatever is the latest stable version available at JMeter Downloads page) on next available opportunity
In addition to point 2 what you're pulling from Github is master (unless you switch to the v5_0 tag so make sure that the source is matching JMeter dependencies, just in case sources for each respective version can be found at JMeter Archives page

Thymeleaf Configuration - Not able to import org.thymeleaf.spring4.*

I am using Thymeleaf in my spring-boot web-application, and I am trying to use the already provided functionalities of the Thymelief for a Spring Boot project. But, I am not able to import the org.thymeleaf.spring4.* - actually, spring4 is not recognized at all. I am using Thymeleaf 3.0.11.
Actually, in my project, gradle is used as a build automation tool, and Thymeleaf is added as in the following (in a multi-module Spring Boot application, and this gradle file corresponds to the module where the Thymeleaf template engine is configured):
configurations.all {
resolutionStrategy {
...
dependencySubstitution {
...
substitute module('org.thymeleaf:thymeleaf') with module('org.thymeleaf:thymeleaf:3.0.11.RELEASE')
}
}
}
I would appreciate any idea about the reason of this is happening?
Ensure that you have added dependency in pom.xml
<!-- https://mvnrepository.com/artifact/org.thymeleaf/thymeleaf-spring4 -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring4</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>

Spring boot, JSP file as view not loading when run in IntelliJ

I've created a simple Spring Boot Web Application in intelliJ. I've placed a simple .jsp file in the /src/main/resources/templates/ folder which contains some basic HTML.
I'm trying to return this in a controller but I'm getting this error;
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Fri Sep 09 10:37:46 BST 2016
There was an unexpected error (type=Not Found, status=404).
No message available
I'm assuming that Spring is unable to find the .jsp file, but there's no other errors appearing in the console to give me any further information.
Here's my simple controller;
#Controller
#RequestMapping("/test")
public class TestController {
#RequestMapping("")
public ModelAndView index() {
return new ModelAndView("test");
}
}
I've included the following in my application.properties file;
spring.mvc.view.prefix = /templates/
spring.mvc.view.suffix = .jsp
My POM file includes the following dependencies;
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
I'm using Spring Boot with embedded tomcat.
I've tried changing the path to the views inside application.properties to;
classpath:/templates/ but that also didn't make any difference.
Finally, here is the structure of my project;
When running the application, I'm just using the 'Run' option in IntelliJ.
I have recently experienced the same situation with below dependency:-
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
If I change the "scope" to "default", run the application with Intellij, it works fine.
But if I want to keep the "scope" as "provided", I have to use the command line (terminal) and execute the following:-
mvn clean spring-boot:run
It works for me.
Setting working directory helped me --- by default, it was empty.
Edit your configuration for Spring boot application in Idea.
Set up the working directory, like it's done on a screenshot below:
If I make the tomcat-embed-jasper dependency default scope (not marked "provided") then everything works ... with spring boot 1.5.2 and idea 2017.1. Otherwise, it's kind of difficult to change this - if you change it in the IDEA project structure, it just gets lost the next time it updates the project from maven or gradle. I haven't figured out a way to otherwise make it work.
Things are further complicated if you use the Spring runner in IDEA -- though I recommend that regardless. It makes things nicer when IDEA fully knows your project is Spring.
There is a special hint for IntelliJ user in the Spring Boot reference documentation Chapter 27.1.7 Template engines:
IntelliJ IDEA orders the classpath differently depending on how you
run your application. Running your application in the IDE via its main
method will result in a different ordering to when you run your
application using Maven or Gradle or from its packaged jar. This can
cause Spring Boot to fail to find the templates on the classpath. If
you’re affected by this problem you can reorder the classpath in the
IDE to place the module’s classes and resources first. Alternatively,
you can configure the template prefix to search every templates
directory on the classpath: classpath*:/templates/.
After banging head here and there I figured out how to fix this problem. keep in mind I am using Windows 10 machine and IntelliJ version is 2021.2.2. Here are the steps:
In IntelliJ IDE Click on Run -> Edit Configurations...
In the Working Directory text field put %MODULE_WORKING_DIR%, I guess for linux it may be $MODULE_WORKING_DIR
Click Apply button
Click OK button
Run your Application
It will work.
A bit late but this worked for me.
Add your .jsp files at this path:
src/main/resources/META-INF/resources/
And if you want to configure the configure.properties file, add these lines in it:
spring.mvc.view.prefix= /WEB-INF/views/
spring.mvc.view.suffix= .jsp
Credit : https://www.logicbig.com/tutorials/spring-framework/spring-boot/boot-serve-dynamic.html
The following will make the application work with IntelliJ:
Under main, create the folder structure webapp/WEB-INF/jsps/ - the last part of the folder structure can be named anything, but it is where the jsps will reside.
Remove the properties:
spring.mvc.view.prefix = /templates/
spring.mvc.view.suffix = .jsp
from your application.properties file, and in a Configuration class explicitly create an InternalResourceViewResolver bean, and set these properties there.
This is what your Configuration class will look like:
#Configuration
#EnableWebMvc
public class WebMvcConfig {
#Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/jsps/");
resolver.setSuffix(".jsp");
return resolver;
}
}
Give that a try - it should work in IntelliJ
After many trials, it worked for me. Its the combination of 2 steps.
1) Maven packaging must be set to 'war', then only it puts everything under 'webapp' into the target war file.
If packaging is 'jar', its omitting the 'webapp' directory.
2) Running spring boot main class from IntelliJ is not working.
Run the application from command prompt using command: 'mvn spring-boot:run'
In IntelliJ you CAN NOT put provided under tomcat-embed-jasper!
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
After many trails, I was able to fix the issue:
In IntelliJ 2019.02.04, Spring Boot configuration, select workspace $MODULE_WRK_DIR.
Controller:
#Controller
public class TestController {
#RequestMapping("/")
public String index() {
return "test.jsp";
}
}
Add this to application.properties:
spring.mvc.view.prefix=WEB-INF/
And put your jsp file in src/main/webapp/WEB-INF
if someone is still facing this issue on IntelliJ IDEA then just invalidate cache & restart the IDE. It will clear all downloaded dependencies & re-download all of them again. Hope this should solve your problem.

Is there a simple way to use a different Spring version?

I want to use latest Spring 4.1.x snapshot in my Spring Boot project.
Is there a simple way to override the version of all Spring dependencies, or should I include all required Spring dependencies with it's desired version manually?
Reason is I want experiment with Spring 4.1 #JsonView annotation in REST services.
If you're using Maven with spring-boot-starter-parent as the parent, you can override the spring.version property in your pom to change the version of Spring that you're using:
<properties>
<spring.version>4.1.0.BUILD-SNAPSHOT</spring.version>
</properties>
If you're using Gradle, you can achieve the same effect by using a resolution strategy to override the version of everything with the org.springframework group id:
configurations.all {
resolutionStrategy {
eachDependency {
if (it.requested.group == 'org.springframework') {
it.useVersion '4.1.0.BUILD-SNAPSHOT'
}
}
}
}
I once again needed this and previous block doesn't work anymore, causing already dependencies to be failed.
Anyway this works:
configurations.all {
resolutionStrategy {
eachDependency { DependencyResolveDetails details ->
if (details.requested.group == "org.springframework") {
details.useVersion "4.1.0.RC1"
}
}
}
}
Given that you're using Spring Boot, I'm guessing that you must be using either Maven or Gradle, but you don't say which. For Maven, you have a couple of things you might be able to do.
First, you could have a go at just forcing the Spring version in your pom.xml:
<properties>
<spring.version>4.1.0.BUILD-SNAPSHOT</spring.version>
</properties>
That ought to override the property which is defined in the spring-boot-dependencies project.
For more fine-grained control, use dependency management:
<dependencyManagement>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.1.0.BUILD-SNAPSHOT</version>
</dependency>
</dependencyManagement>

Resources