I am making a new springboot- maven project. The compiler is unable to resolve #RestController when I use below pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
However, when I change the version to 1.5.13, the compiler is able to resolve #RestController
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.13.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
I want to be using the latest version of spring boot, and use #RestController.
#RestController doesn't come from org.springframework.boot:spring-boot-starter-web, it comes from org.springframework:spring-web. Different versions of spring-boot-starter-web must probably have some transient dependency that provides it, but it's a bad practice to rely on it. If you use #RestController in your code, you should explicitly require the artifact that provides it:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>
since i can't add a comment, i think the maven config is not your problem, check your #Configuration and #SpringBootApplication classes and their path scanning settings
another problem you could have: maybe one of your other dependencies still depends on springboot 1.5, you have to have a clean springboot 2.0 classpath
i run in problems like this as well, so keep on diggin, you'll find it ;-)
I had somewhat a similar issue and it was because I named my class RestController. Once I renamed it Controller, I could import the #RestController packages without issues.
Related
We have a Spring Boot based project that uses Maven as the build tool. We recently encountered that the Spring-Beans(5.2.13) which is a transitive dependency has been reported to have the vulnerability CVE-22-2965
The parent pom contains the spring-boot-starter-parent
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.9.RELEASE</version>
</parent>
The transitive dependency of Spring-Beans(5.2.13.RELEASE) is getting added by spring-boot-starter-web-2.3.9.RELEASE.jar
To fix the vulnerability we have tried following two approach :
1) Added a new spring-beans version in the dependency section of parent pom.xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.2.22.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.20</version>
</dependency>
Also, we had to update the Spring-core to 5.3.20 from 5.2.13 as we were getting
incompatibility issues
2) Updating the spring-boot-starter-parent to latest version
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
<type>pom</type>
</parent>
In the second approach we are facing following error and build failure
java.lang.NoSuchMethodError: org.mockito.Answers.get()Lorg/mockito/stubbing/Answer;
java.lang.NoClassDefFoundError: Could not initialize class org.mockito.Mockito
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:365)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:273)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:238)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:159)
Which is the better approach and is there another way in which we can update the version and remove the Vulnerability .What is the correct method to do it?
I've migrated a Spring Boot project from 2.2.5 to 2.3.0 and after that, Validations stopped to work (they aren't invoked at all).
I read in changelog documentation (https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.3.0-M1-Release-Notes), that spring-boot-starter-validation now needs to be added manually as a dependency.
So, I added it to my pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
My pom parent is:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.0.RELEASE</version>
<relativePath></relativePath>
</parent>
My Controller looks like this:
#PostMapping( value = "/signup", consumes = MediaType.APPLICATION_JSON_VALUE )
#ResponseStatus( value = HttpStatus.OK )
public void signUp( #Valid #RequestBody ClientDto clientDto )
{
onboardingService.signUp( clientDto );
}
EDIT:
I WAS ABLE TO FOUND THE ISSUE, CHECK MY ANSWER BELOW!
Thanks everybody for the help!
Validation starter not included in web starters anymore.
The spring-boot-starter-validation is not a transitive dependency of spring-boot-starter-web and spring-boot-starter-webflux anymore.
Add this dependency for validations work.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
According to spring boot 2.3.1 release
there is no longer contains spring-boot-starter-validation with spring starter
how to add starter validation on
maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
Gradle
dependencies {
...
implementation 'org.springframework.boot:spring-boot-starter-validation'
}
referee the release note
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.3-Release-Notes#validation-starter-no-longer-included-in-web-starters
If your experiencing the issue of for example: not being able to see the validation errors (default-messages) returned back to the client, this is what you could do:
Top Solution 1:
Simply add devtools. This should solve the issue. After I did this, all my binding-results were returned back to the client. I recommend you to test this out first:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
Solution 2:
I found out that this is due to using Spring Boot 2.3+
So if youre using Spring Boot 2.3 or higher, add this dependency in your pom.xml file as its no longer included within the 'web'-dependency itself.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
Now its necessary to set 'include binding errors' in java/resources/application.properties to "always". Same goes for 'message' as well although I think this is optional.
server.error.include-message=always
server.error.include-binding-errors=always
Solution 3: (before I discovered solution 2 which could be helpful as well)
So I found out that this is due to having Spring boot 2.3+. But I could not find caution-messages on the new updated usage of #Valid in Spring Boot v2.3+.
So I ended up switching back to Spring boot v2.2.10 (latest version of 2.2) by adjusting the release version in the pom.xml file like so:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.10.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
This worked perfectly for me by rolling back to an older version. Although id like to update my Spring Boot version some day. (Revisit solution 1 & 2)
Actually there error was in the unit tests. The validation was working well.
For those who came here with the same issue, it's very likely that you are missing to add the following dependency to the pom.xml as Braian Silva suggested above:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
Thanks for your help guys!
Hi You have to annotate you controller class with #Validated annotation see example below:
For testing purpose please try commenting #Validated annotation you won't notice javax.validation.ConstraintViolationException: hello.name: size must be between 4 and 10
but once you place it back its works again.
More technical info here Difference between #Valid and #Validated in Spring
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Validated
#RestController
#RequestMapping("/hello")
class HelloController {
#GetMapping
public String hello(#Valid
#NotNull(message = "Name cannot be empty")
#Size(min = 4, max = 10) #RequestParam("name") String name) {
return "Hello, " + name + "!";
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
I've got a similar issue here. But in my case, the validation is warning me that a sequence is missed in oracle schema, but it is there. I think that is a bug.. I will follow with the 2.4.0 version for while..
No one actually solves the same problem. For me, I also added the dependency as instructed above.
The true solution:
Add the dependency
mvn clean install
mvn clean spring-boot:run
Everything works
A simple solution to the above issue is to add:
<repositories>
<repository>
<id>Central Maven repository</id>
<name>Central Maven repository https</name>
<url>https://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
to your POM.xml file.
This will fix the issue with this version
Vipul.
Im looking to create a Spring library project to share across an internal team.
At a very basic concept level The library will send message events to a queue and my plan is to standardise this within a team across several Spring Boot Microservices send messages the same way.
My pom in the library project looks something like this
<artifactId>my-library</artifactId>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
etc...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.16.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.2.Final</version>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>2.2.6</version>
</dependency>
I have a service in the library project that looks like this
public class EventService {
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
public void sendAuditEvent(AuditMessage auditMessage){
Set<ConstraintViolation<AuditMessage>> violations = validator.validate(auditMessage);
if(!isEmpty(violations)){
log.error("Unable to send audit message");
violations.stream().forEach( v-> log.error(v.getMessage()));
}
log.info("Found {} violations", violations.size());
// etc blah blah
return;
}
}
When I import the library into another project my thinking is that I can Autowire the EventService. By adding it in the pom and then
#ComponentScan({"my.library.package.eventlibrary.service"})
How do I prevent spring version locking? If the library is using spring 2.1.5.RELEASE today and the project that imports the library uses a different version would I not end up with potentially maven conflicts?
Also lets say the project that imports the library uses a lower version of hibernate api and the library has 6.0.16.Final. How would I prevent the project from using the newer one found one in the library classpath?
To clarify my question further is there a way I can separate the dependencies in the library from the project that uses it.
Pre Java 9. You can exclude the spring dependencies using maven when you declare the dependency to your module, same goes on for Hibernate. But you can't tell to your module to use a different hibernate version in a WAR.
If you want to work around this you can develop your library as independent micro service expose interface in the form of REST or Websocket if you want full duplex communication or something else JMS whatever....
Post Java 9 you can use java modularity to define the exact dependencies for your jar module. Check Project Jigsaw https://www.baeldung.com/project-jigsaw-java-modularity.
In your case in order to have different versions of the same library (hibernate). You would need two separate class loaders. To achieve this you would need to use layering read here http://openjdk.java.net/projects/jigsaw/spec/sotms/#layers
And here is the source code of many examples including ones that use layers. Focus on them : https://github.com/accso/java9-jigsaw-examples/tree/master/jigsaw-examples
You can try to exclude all transitive dependencies that your library can bring to projects that will use it.
To do this you should replace spring-boot-starter-parent with spring-boot-dependencies in dependencyManagement section and use provided scope for all dependencies which the library needs to work with and which will be exactly used by the projects, that will work with the library.
For example, a pom.xml of your library can be looks like this:
<!-- ... -->
<groupId>com.example</groupId>
<artifactId>library</artifactId>
<version>0.1.0</version>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<spring-boot.version>2.1.5.RELEASE</spring-boot.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<!-- ... -->
Then you will be able to use your library in the different projects, that use for example the old Spring Boot:
<!-- ... -->
<groupId>com.example</groupId>
<artifactId>old-project</artifactId>
<version>0.13.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.19.RELEASE</version>
<relativePath/>
</parent>
<!-- ... -->
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>library</artifactId>
<version>0.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<!-- ... -->
So this project will use hibernate-validator:5.3.6.Final from its spring-boot-starter-web.
Important notes - the code of your library should be 'compatible' with this version of Spring Boot. In other words, you should test your library with different versions of Spring Boot in which you are interested.
See my project as an example.
Might be not what you are looking for, but you can distribute your library as a spring-boot-starter auto configuration module (of course, if the clients are spring boot applications).
This way you can control your dependencies in an agile way and you give your clients more freedom in using the library.
In your particular case, if you need to send a message to a queue you for sure need to have a corresponding classes in classpath. With auto configuration you can have Class Conditions or Been Conditions based on which you can track if your clients have correct configurations in runtime. You can also fail the context loading if something is wrong (providing a meaningful error message).
Spring also provides tracking mechanisms of what could happen if a particular class/library is missing.
In my Spring Boot(2.0.5) project I was using Elasticsearch(5.6.9). However, due to some bugs in testing environment we are moving to Spring boot(2.1.0).
When I run the application the following message comes up:
***************************
APPLICATION FAILED TO START
***************************
Description:
An attempt was made to call the method org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequestBuilder.execute()Lorg/elasticsearch/action/ActionFuture; but it does not exist. Its class, org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequestBuilder, is available from the following locations:
jar:file:/C:/Users/User/.m2/repository/org/elasticsearch/elasticsearch/5.6.9/elasticsearch-5.6.9.jar!/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestBuilder.class
It was loaded from the following location:
file:/C:/Users/User/.m2/repository/org/elasticsearch/elasticsearch/5.6.9/elasticsearch-5.6.9.jar
Action:
Correct the classpath of your application so that it contains a single, compatible version of org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequestBuilder
Process finished with exit code 0
Current pom.xml file
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
<relativePath/>
</parent>
<properties>
<elasticsearch.version>5.6.9</elasticsearch.version>
</properties>
<dependencies>
<!--...others...-->
<!--ELASTICSEARCH-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>transport-netty4-client</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
</dependencies>
Previous pom.xml file which worked fine:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
<relativePath/>
</parent>
<properties>
<elasticsearch.version>5.6.9</elasticsearch.version>
</properties>
<dependencies>
<!--...others...-->
<!--ELASTICSEARCH-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>transport-netty4-client</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
</dependencies>
Can someone tell which version of elasticsearch is compatible with Spring Boot 2.1.0?
I read through similar questions which were outdated.
Compatible versions of Spring boot,elasticsearch and spring data elasticsearch
You can go to Spring Boot project Github repository and check any dependency version:
In Spring Boot 2.0.x Elasticsearch version is defined as 5.6.16 (link)
In Spring Boot 2.1.x Elasticsearch version is defined as 6.4.3
(link)
Not sure if it's still actual, but the first thing you need to try is to add core Elasticsearch library, because REST client depends on it.
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>6.7.0</version>
</dependency>
I'm using Spring boot and want to use the starter pom for Spring Integration.
In my POM I have:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.3.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-integration</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
This pulls in 4.3.6 versions of Spring Integration jars and 4.3.5 of Spring Framework jars. In one of my own classes I'm trying to use Message:
import org.springframework.integration.Message;
public Object doThings(Message<?> message) {
}
but I can't seem to locate Message. In an older version of Spring integration it was in spring-integration-core.jar but it's not there in this version. Has it moved or has something changed? I've checked the docs and it's still referenced so I assume I'm looking in the wrong place - but core sounds like the place it should be in to me! What am I doing wrong?
A few core concepts of Spring Integration have been merged inside Spring Core between versions 3.0 and 4.0, and org.springframework.integration.Message is one of them.
In your code sample, replacing
import org.springframework.integration.Message;
public Object doThings(Message<?> message) {
}
by
import org.springframework.messaging.Message;
public Object doThings(Message<?> message) {
}
will do the trick.
For a more exhaustive list of affected classes and interfaces, have a look at the 3.0 to 4.0 Spring Integration migration guide
It ok for me with using this version
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>4.1.9.RELEASE</version>
</dependency>
and
import org.springframework.messaging.Message;