Spring Java - Parameter 0 of constructor - java

I'm trying to write a simple CRUD program and I get this error. The program is based after codecademy project. Not sure why I doesn't work.
If I comment out the constructor the error disappears.I don't have anything in my properties.
Can someone give me a hand?
Description:
Parameter 0 of constructor in com.example.FitApp3.controller.FoodController required a bean of type 'com.example.FitApp3.repository.FoodRepository' that could not be found.
Action:
Consider defining a bean of type 'com.example.FitApp3.repository.FoodRepository' in your configuration.
Process finished with exit code 1
This is my code:
Entity/Food.java
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class Food extends com.example.FitApp3.model.Entity {
private String foodName;
private int foodKcal;
private int foodProtein;
private int foodCarb;
private int foodFat;
public String getFoodName() {
return foodName;
}
public void setFoodName(String foodName) {
this.foodName = foodName;
}
public int getFoodKcal() {
return foodKcal;
}
public void setFoodKcal(int foodKcal) {
this.foodKcal = foodKcal;
}
public int getFoodProtein() {
return foodProtein;
}
public void setFoodProtein(int foodProtein) {
this.foodProtein = foodProtein;
}
public int getFoodCarb() {
return foodCarb;
}
public void setFoodCarb(int foodCarb) {
this.foodCarb = foodCarb;
}
public int getFoodFat() {
return foodFat;
}
public void setFoodFat(int foodFat) {
this.foodFat = foodFat;
}
}
Repository/FoodRepository.java
public interface FoodRepository extends CrudRepository<Food, Integer> {}
Controller/FoodController.java
#RestController
public class FoodController {
private FoodRepository foodRepository;
public FoodController(FoodRepository foodRepository) {
this.foodRepository = foodRepository;
}
}
Mainclass
#SpringBootApplication
public class FitApp3Application {
public static void main(String[] args) {
SpringApplication.run(FitApp3Application.class, args);
System.out.println("hello world");
}
}
pom.xml
<?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.6.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>FitApp3</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>FitApp3</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
<version>2.5.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

Can you add #Repository annotation to FoodRepository interface.
#Repository
public interface FoodRepository extends CrudRepository<Food, Integer> {}

You need to replace spring-boot-starter-jdbc with spring-boot-starter-data-jpa as follows:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
You can have a look at the following links the difference between them, but basically, JPA helps you deal with your Database data by mapping it directly to Java objects:
https://www.baeldung.com/jpa-vs-jdbc
JPA or JDBC, how are they different?

I think you are just a little bit confused with spring-jdbc, spring-data and spring persistence interfaces abstraction, let me help. TL;DR solution is at the bottom:
In the constructor of FoodController you are declaring FoodRepository as a parameter, so spring have to find the bean of this time at runtime in order to create bean of FoodController. You have declared FoodRepository and extend it from CrudRepository. I guess, that you have done it with the assumption, that spring will create an implementation of FoodRepository at runtime (because it extends CrudRepository). But, unfortunately, it is not the spring-core module, that will create bean of FoodRepsitory, nor it is spring-jdbc. This interfaces are the part of spring-data project. So, for creation of the bean of the type FoodRepository is responsible current spring-data project in your classpath (I mean, it could be spring-data-jdbc, spring-data-jpa or whatever). This interfaces (CrudRepository, Repository e.t.c.) are common for all of the spring data projects, so they are shipped in spring-data-commons jar, this is why you have them available in classpath, because you have included spring-data-commons explicitly:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
<version>2.5.1</version>
</dependency>
Another thing is that this starter:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
does not do anything with spring-data project - it just brings spring-jdbc, Hikari connection pool, and some other spring-boot stuff. In other words, the problem is that you do not have any spring-data project in your classpath, thats why FoodRepository bean is not created.
Also note: #Entity does not make sense here, becuase you do not have any jpa persistence provider in classpath
Solution:
To solve the problem, I suggest you to
Remove spring-data-commons dependency from pom.xml
Include spring-boot-starter-data-jpa into your project (into pom.xml). It will bring the appropriate version of spring-data-commons dependency.
Hope it helped, have a nice day!

Add #Repository annotation to FoodRepository interface
and also #Autowired annotation to the FoodRepository in FoodController.

Related

Error on getting records by id using r2dbc

In sandbox project trying reactive webflux with springboot and postgres. I added r2dbc, created endpoints - get all records and post endpoints work, but appeared problem with requests which use path variable (get one record, or delete by id)
Here is my code:
#SpringBootApplication
#EnableR2dbcAuditing
public class Springboot2Application {
public static void main(String[] args) {
SpringApplication.run(Springboot2Application.class, args);
}
}
Controller:
#RequiredArgsConstructor
#RestController
#RequestMapping("/api/v1")
public class ToDoController {
private final ToDoRepository repository;
#GetMapping(value = "/to-do/{toDoId}", produces = {
MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE})
public Mono<ResponseEntity<ToDo>> getToDo(#Valid #PathVariable Long toDoId) {
return repository.findById(toDoId)
.map(ResponseEntity::ok);
}
}
repository:
#Repository
public interface ToDoRepository extends R2dbcRepository<ToDo,Long> {
}
entity:
#Data
#RequiredArgsConstructor
#Table(name = "to_do")
public class ToDo {
#Id
private Long id;
#Version
private Long version;
#NotNull
#NotBlank
private String description;
#CreatedDate
private Timestamp created;
#LastModifiedDate
private Timestamp modified;
private boolean completed;
}
r2dbc config:
#Configuration
#EnableR2dbcRepositories(basePackages = "com.springboot2.repository")
public class R2DBCConfig extends AbstractR2dbcConfiguration {
#Bean
public ConnectionFactory connectionFactory() {
return ConnectionFactories.get(
ConnectionFactoryOptions.builder()
.option(DRIVER, "postgresql")
.option(HOST, "localhost")
.option(PORT, 5432)
.option(USER, "admin")
.option(PASSWORD, "admin")
.option(DATABASE, "springdb")
.build());
}
#Bean
ReactiveTransactionManager transactionManager(ConnectionFactory connectionFactory) {
return new R2dbcTransactionManager(connectionFactory);
}
}
And my pom file:
<?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.7.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.springboot</groupId>
<artifactId>springboot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot2</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>8</java.version>
<spring-cloud.version>2021.0.3</spring-cloud.version>
</properties>
<dependencies>
<!-- DB,ORM, and plugins-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-r2dbc</artifactId>
</dependency>
<dependency>
<groupId>io.r2dbc</groupId>
<artifactId>r2dbc-postgresql</artifactId>
<version>0.8.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!-- Reactive libs-->
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
table creation sql:
CREATE TABLE to_do
(
ID SERIAL primary key ,
version bigint,
description char(255),
created timestamp,
modified timestamp,
completed boolean
);
So when I execute GET http://localhost:8080/api/v1/to-do/3 I get:
java.lang.IllegalStateException: Required identifier property not found for class com.springboot2.domain.ToDo
I tried to define this using #Query in repository, but got same result. I suppose problem can be either in my table, or in entity, but I can't see it. And also seems #Version does not work(every time writes null to table)
The problem may be in wrong import of #Id annotation in your domain.
It should be from package
org.springframework.data.annotation.Id
But in your case it is from package
javax.persistence
Also, consider the naming of fields. As in your domain id is declared as "id", I can see in your create script id as "ID" (in uppercase).

Class is not found from jar from dependency jar

I have some project trying to build a microservices architecture. Some of the projects are used producing jar files (I refer these projects as "library projects".) for the callable microservices. One of these microservices are responsible for user/customer registration and lookup. All the data is persisted in a Cassandra cluster. One of the library projects are responsible for providing various Cassandra based services/value objects, etc...
In the microservice pom file, I include the jar produced by the library
project. It compiles, but when I start the customer service the classes from that jar are not found.
***************************
APPLICATION FAILED TO START
***************************
Description:
Field repository in com.besztercekk.tao.customer.handler.PostUserHandler required a bean of type 'com.besztercekk.tao.cassandra.repository.ReactiveUserRepository' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.besztercekk.tao.cassandra.repository.ReactiveUserRepository' in your configuration.
Here are some code snippets, but I can attach anything else you need.
This is the pom file for the microservice. The class what is not found is in this dependency: tao-elszamolas-cassandra.
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>tao-elszamolas-customer-service</artifactId>
<packaging>jar</packaging>
<name>tao-elszamolas-customer-service</name>
<description>TAO elszamolas customer backend service</description>
<parent>
<groupId>com.besztercekk.tao</groupId>
<artifactId>tao-elszamolas-spring</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
<!-- Spring Cloud Eureka client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- Spring Cloud config client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
</dependency>
<!-- Webflux -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Reactive cassandra -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-cassandra-reactive</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>27.1-jre</version>
</dependency>
<!-- TAO elszamolas dependencies -->
<dependency>
<groupId>com.besztercekk.tao</groupId>
<artifactId>tao-elszamolas-cassandra</artifactId>
</dependency>
<dependency>
<groupId>com.besztercekk.tao</groupId>
<artifactId>tao-elszamolas-jwt</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<release>11</release>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
This is the pom file for the project what contains the missing class:
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>tao-elszamolas-cassandra</artifactId>
<packaging>jar</packaging>
<name>tao-elszamolas-cassandra</name>
<description>TAO elszámolás Spring alapú több projektben használt komponensek gyűjtő projektje</description>
<parent>
<groupId>com.besztercekk.tao</groupId>
<artifactId>tao-elszamolas-spring</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<dependencies>
<!-- Reactive cassandra -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-cassandra-reactive</artifactId>
</dependency>
</dependencies>
</project>
Here the class where the error is coming from:
#Component
#Validator(UserDataValidator.class)
public class PostUserHandler extends AbstractValidationHandler<User, ChainableValidator> {
#Autowired
private ReactiveUserRepository repository;
#Autowired
private PasswordEncoder passwordEncoder;
public PostUserHandler() {
super(User.class);
}
#Override
protected Mono<ServerResponse> processRequest(User body, ServerRequest request) {
return repository.save(enrichUser(body, UUIDs.random().toString()))
.flatMap(updatedUser -> {
sendRegistrationCode();
return ok(updatedUser);
})
.onErrorResume(IllegalArgumentException.class, e -> ServerResponse.badRequest().build())
.switchIfEmpty(ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR).build());
}
#Override
protected Mono<User> extractContent(ServerRequest request) {
return request.bodyToMono(User.class);
}
private void sendRegistrationCode() {
//TODO: Send Kafka message to email component
}
private Mono<ServerResponse> ok(User c) {
return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromPublisher(Mono.just(c), User.class));
}
private User enrichUser(User user, String activationCode) {
return User.builder()
.authorities(user.getAuthorities())
.email(user.getEmail())
.enabled(user.isEnabled())
.firstName(user.getFirstName())
.id(UUIDs.timeBased())
.lastName(user.getLastName())
.middleName(user.getMiddleName())
.password(passwordEncoder.encode(user.getPassword()))
.registrationTime(LocalDateTime.now())
.passwordExpiryTime(LocalDateTime.now())
.roles(user.getRoles())
.username(user.getUsername())
.accountExpired(false)
.accountLocked(false)
.activationCode(activationCode)
.build();
}
}
Any help would be appreciated!
UPDATE (SOME EXTRA INFO ADDED):
Here is the main class containing the component scan.
#SpringBootApplication
#EnableEurekaClient
#ComponentScan(basePackages = {"com.besztercekk.tao.customer", "com.besztercekk.tao.cassandra"})
public class CustomerBackendApplication {
public static void main(String[] args) {
SpringApplication.run(CustomerBackendApplication.class, args);
}
}
Here is the repository class:
package com.besztercekk.tao.cassandra.repository;
import java.util.UUID;
import org.springframework.data.cassandra.repository.ReactiveCassandraRepository;
import org.springframework.stereotype.Component;
import com.besztercekk.tao.cassandra.model.User;
import reactor.core.publisher.Mono;
/**
* This interface provides reactive {#link User} services.
*/
public interface ReactiveUserRepository extends ReactiveCassandraRepository<User, UUID> {
Mono<User> findByUsername(String username);
Mono<User> findByEmail(String email);
}
Also tried to add #Component and #Repository annotations to this interface, just to see its effect. :-)
My other idea was add the bean programatically to the context after restart. But this is just an interface, so not sure if it works out at all.
The third idea was wrap this interface into a service class and that is easy to add programatically.
But I really want it to be added automatically, without writing code.
Try adding the following annotation to any of the #Configuration classes:
#EnableReactiveCassandraRepositories
#Configuration
class MyConfiguration() {
//code
}
The above code enables spring to automatically scan and create the default implementation bean for your interface ReactiveUserRepository .
Also annotate the interface like :
#Repository
public interface ReactiveUserRepository extends ReactiveCassandraRepository<User, UUID> {
Mono<User> findByUsername(String username);
Mono<User> findByEmail(String email);
}
For more details read :
https://dzone.com/articles/reactive-streams-with-spring-data-cassandra
Also, if you would like more details on the annotations read a similar post :
how annotation #Repository in java spring work?

#QuerydslPredicate throwing exception

I'm trying to understand how to use #QuerydslPredicate but my test API fails when it is called:
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalStateException: No primary or default constructor found for interface com.querydsl.core.types.Predicate] with root cause
java.lang.NoSuchMethodException: com.querydsl.core.types.Predicate.< init >()
This is the method in my Controller class:
#ResponseBody
#RequestMapping(value = "/user/query", method = RequestMethod.GET)
public Iterable<User> getByCriteria(#QuerydslPredicate(root = User.class) Predicate predicate)
{
return this.userDao.getByCriteria(predicate);
}
I've used this spring blog post and this example to try and implement my API but I don't understand what I am doing wrong.
Edit #1
pom.xml:
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>email-encrypt</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.2.RELEASE</version>
</parent>
<name>email-encrypt</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<querydsl.version>4.1.4</querydsl.version>
<springfox.version>2.6.1</springfox.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-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.59</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.59</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcmail-jdk15on</artifactId>
<version>1.59</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>${querydsl.version}</version>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<version>${querydsl.version}</version>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<version>10.14.1.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${springfox.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.20</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.20</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>${build.directory}/generated-sources/java</outputDirectory>
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Edit #2
I've create a sample project here.
If you comment out the #Configuration on the swagger configuration class it will work. I'm still trying to understand why, I guess that with that annotation the way spring loads the configuration is different and this is causing the issue.
//#Configuration
#EnableSwagger2
public class SwaggerConfiguration extends WebMvcConfigurationSupport
I think your problem lies in your pom.xml. Be sure you are using compatible version of query-dsl. For instance if you use spring-data-jpa 2.0.8, you should use querydsl-* 4.1.4+
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>2.0.8.RELEASE</version>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-*</artifactId>
<version>4.1.4</version>
</dependency>
you can check in maven repository which version you need
Edit 1 try to add the querydsl-core to your maven:
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-core</artifactId>
<version>4.1.4</version>
</dependency>
Extending on #cristobalrosa's answer, this might be due to web application not being configured by Spring Boot. For instance my project also had a SwaggerConfig extending WebMvcConfigurationSupport:
#Configuration
#EnableSwagger2
public class SwaggerConfig extends WebMvcConfigurationSupport {
// Docket bean
#Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
}
}
I removed the inheritance and manual resource handlers, and it works fine now.
Note: In addition to WebMvcConfigurationSupport, things like #EnableWebMvc & WebMvcConfigurer might also lead to Spring Boot's web autoconfiguration not being used.
Sources: Swagger Issue comment
Same error with me.
I just want to share the situation to may give some hints. So look at my config and dependencies and read articles that I linked. try #EnableWebMvc instead of 'WebMvcConfigurationSupport'
Error
java.lang.IllegalStateException: No primary or default constructor found for interface com.querydsl.core.types.Predicate
Caused by: java.lang.NoSuchMethodException: com.querydsl.core.types.Predicate.<init>()
at java.base/java.lang.Class.getConstructor0(Class.java:3427)
at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2631)
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.createAttribute(ModelAttributeMethodProcessor.java:216)
dependencies
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation "org.springframework.data:spring-data-commons"
implementation "com.querydsl:querydsl-apt:4.3.1"
implementation "com.querydsl:querydsl-jpa:4.3.1"
}
Querydsl web support is available in spring-data-commons since 1.11
from https://www.baeldung.com/rest-api-search-querydsl-web-in-spring-data-jpa
Web Mvc Config
In my case, I have to implements WebMvcConfigurer and add #EnableWebMvc instead of WebMvcConfigurationSupport. I don't know why #EnableWebMvc is needed even I had extended WebMvcConfigurationSupport with #Configuration. I just guess WebMvcConfigurationSupport doesn't implements init() of Predicate.
#Configuration
//#EnableSpringDataWebSupport // <-- doesn't necessary for me
#EnableSwagger2
#EnableWebMvc // <-- add
public class SwaggerConfig implements WebMvcConfigurer { //<-- instead of 'WebMvcConfigurationSupport'
...
}
QueryDSL web support From Spring document
The feature will be automatically enabled along #EnableSpringDataWebSupport when Querydsl is found on the classpath.
https://docs.spring.io/spring-data/jpa/docs/1.9.0.RELEASE/reference/html/#core.web.type-safe
Controller
#GetMapping
public List<InputMethodDto.Response> getInputMethodTypeList(
#QuerydslPredicate(root = InputMethod.class) Predicate predicate) {
return service.getInputMethodList(predicate);
}
Repository
public interface InputMethodRepository extends JpaRepository<yourEntity, Long>, QuerydslPredicateExecutor<yourEntity>, QuerydslBinderCustomizer<QyourEntity> {
#Override
default void customize(final QuerydslBindings bindings, final QyourEntity root) {
bindings.bind(String.class).first((StringPath path, String value)-> path.eq(value));
}
}

Unresolvable circular reference in SpringBoot

I am learning Spring Framework and now I am trying to make a simple Spring Boot application that would list all entries from a database (using Hibernate).
First I had a problem when SessionFactory would not be defined, but I managed to define it in Config Class. However, when I try to run the app now, I get the following error:
Description:
The dependencies of some of the beans in the application context form a cycle:
indexController (field private com.prvi.dao.CustomerDAO com.prvi.controllers.IndexController.customerDAO)
↓
customerDAOImpl (field private org.hibernate.SessionFactory com.prvi.dao.CustomerDAOImpl.sessionFactory)
┌─────┐
| sessionFactory defined in class path resource [com/prvi/ConfigPrvi.class]
└─────┘
Basically, I have IndexController, who gets GET / request, then it calls customerDAO to get list of customers and customerDAO uses sessionFactory to get Session and performs a query on DB. (I have omitted Service layer from the app for sake of simplicity)
Now, I have read that this error happens when a bean is dependent on a bean that is dependent on a first bean, making cyclical dependency. However, I do not understand where I made this cycle and how to fix it. Also, other answers on this topic have not provided me enough information to correct the error. They were mostly oversimplifies where cycle is clear, which is not the case here.
Here is what I have tried so far:
PrviApplication.java - entry point for Spring Boot
#SpringBootApplication
public class PrviApplication {
public static void main(String[] args) {
SpringApplication.run(PrviApplication.class, args);
}
}
ConfigPrvi.java - My Configuration file
#Configuration
#EnableAutoConfiguration
public class ConfigPrvi {
#Bean
public HibernateJpaSessionFactoryBean sessionFactory(EntityManagerFactory emf){
HibernateJpaSessionFactoryBean factory = new HibernateJpaSessionFactoryBean();
factory.setEntityManagerFactory(emf);
return factory;
}
}
IndexController.java - my Controller class, which handles GET /
#Controller
#RequestMapping("/")
public class IndexController {
#Autowired
private CustomerDAO customerDAO;
#GetMapping("/")
public String listCustomers(Model model){
model.addAttribute("customers", customerDAO.getAllCustomers());
return "index";
}
}
CustomerDAO.java - just an interface
public interface CustomerDAO {
public List<Customer> getAllCustomers();
}
CustomerDAOImpl.java - implementation, retrieves data from database
#Repository
public class CustomerDAOImpl implements CustomerDAO {
#Autowired
private SessionFactory sessionFactory;
#Transactional
public List<Customer> getAllCustomers(){
Session session = sessionFactory.getCurrentSession();
Query<Customer> query = session.createQuery("from Customer order by lastName", Customer.class);
List<Customer> customers = query.getResultList();
return customers;
}
}
Is it perhaps that cycle was made here:
main --> controller --> dao --> sessionFactory --> config --> main
If so, how can I rewrite the code so that I get rid of it?
EDIT: Added pom.xml:
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.prvi</groupId>
<artifactId>prvi</artifactId>
<version>0.0.1</version>
<packaging>jar</packaging>
<name>prvi</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.4.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.10.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.2.10.Final</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

#RepositoryRestController makes REST API not available

I have created simple Spring BOOT application with Spring Data Rest. It works fine with repositories. However, I need to add some extra functionality and for that purpose would like to use controller class annotated with #RepositoryRestController. The issue is when I use #RestController annotation GET method is available for calling but when I switch annotation to #RepositoryRestController browser says the method is not available.
POM file:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-mockmvc</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Controller class:
#RepositoryRestController
public class HelloContoller {
#RequestMapping("/test")
#ResponseBody
public String sayHello() {
return "Hi, there!";
}
#RequestMapping(value = "test", method = RequestMethod.POST)
public String postHello() {
return "POST!";
}
#RequestMapping(value = "/test", method = RequestMethod.PUT)
public String putHello() {
return "PUT!";
}
}
Configuration class:
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
I am new to Spring Data Rest and would appreciate any help!
Thanks!
In case of overriding just some methods of the ones generated by spring-data-rest's RepositoryEntityController I also had problems that you ran into.
It seems that in such cases you cannot use the class level #RequestMapping annotation on a RepositoryRestController.
So remove #RequestMapping("/test") from the class and repeat the /test path on each method.
Finally, I have managed to find answer with help from Vladimir Tsukur. In order to use #RepositoryRestController properly you must create repository interface first and then use its URL as base path for #RequestMapping on each method of the controller.
Now everything works fine. Just be careful about the URLs :)

Categories