I have a Spring/Boot REST controller which I inject a repository into like so:
package com.example.schooltimetable.controllers;
import com.example.schooltimetable.models.entities.StudentEntity;
import com.example.schooltimetable.repository.StudentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@CrossOrigin
@RequestMapping("student")
public class StudentController {
private final StudentRepository studentRepository;
@Autowired
public StudentController(StudentRepository studentRepository) {
this.studentRepository = studentRepository;
}
@RequestMapping(value = "/getAll", method = RequestMethod.GET)
public Iterable<StudentEntity> getAllStudents() {
return this.studentRepository.findAll();
}
}
The problem I'm facing is that whenever i start my application it throws the following error:
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in com.example.schooltimetable.controllers.StudentController required a bean of type 'com.example.schooltimetable.repository.StudentsRepository' that could not be found.
Action:
Consider defining a bean of type 'com.example.schooltimetable.repository.StudentsRepository' in your configuration.
Process finished with exit code 1
I faced this issue before when trying to find an Entity in another class, I fixed this by using the @ComponentScan() annotation in Application.java, however, it doesn't work to fix this issue.
My main application file looks like this:
SchoolTimetableApplication
package com.example.schooltimetable;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan({
"com.example.schooltimetable.controllers",
"org.springframework.stereotype",
"com.example.schooltimetable.repository",
})
public class SchoolTimetableApplication {
public static void main(String[] args) {
SpringApplication.run(SchoolTimetableApplication.class, args);
}
}
And my repository looks like this: StudentRepository
package com.example.schooltimetable.repository;
import com.example.schooltimetable.models.entities.StudentEntity;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
@Repository
@Component
public interface StudentRepository extends CrudRepository<StudentEntity, Long> { }
The StudentEntity referenced in the repository:
package com.example.schooltimetable.models.entities;
import com.example.schooltimetable.models.constants.StudentEntityConstants;
import com.example.schooltimetable.models.constants.TimetableEntityConstants;
import org.springframework.lang.NonNull;
import javax.persistence.*;
import java.util.UUID;
@Entity
@Table(name = StudentEntityConstants.TABLE_NAME)
public class StudentEntity {
@Id
@Column(name = StudentEntityConstants.ID)
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column(name = StudentEntityConstants.FIRST_NAME)
@NonNull
private String firstName;
@Column(name = StudentEntityConstants.LAST_NAME)
@NonNull
private String lastName;
@Column(name = StudentEntityConstants.REFERENCE)
@NonNull
@GeneratedValue(strategy = GenerationType.AUTO)
private UUID reference;
@OneToOne(targetEntity = TimeTableEntity.class)
@JoinColumn(name = TimetableEntityConstants.REFERENCE)
private TimeTableEntity timeTable;
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return this.lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public UUID getReference() {
return this.reference;
}
public void setReference(UUID reference) {
this.reference = reference;
}
public TimeTableEntity getTimeTable() {
return this.timeTable;
}
}
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.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>school-timetable</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>school-timetable</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-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.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</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>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
<version>2.3.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Is there something I've done wrong? I'm very new to Spring/Boot. An interesting note with this issue is that if I remove
@ComponentScan({
"com.example.schooltimetable.controllers", <---- This
"org.springframework.stereotype",
"com.example.schooltimetable.repository",
})
Then the application loads but the controller will throw a 404 when trying to hit: http://localhost:8080/student/getAll
EDIT!!!
There was a few things wrong with the application at this point. Firstly, the POM file needed updating
<?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.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>school-timetable</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>school-timetable</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-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.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</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>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
<version>1.9</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Secondly, the MAIN CLASS
package com.example.schooltimetable;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@SpringBootApplication
@PropertySource("classpath:application.properties")
@EntityScan("com.example.schooltimetable.models.entities")
@EnableJpaRepositories("com.example.schooltimetable.repository")
public class SchoolTimetableApplication {
public static void main(String[] args) {
SpringApplication.run(SchoolTimetableApplication.class, args);
}
}
There were also things wrong with the entities when joining columns: They should be set to read and write: false
package com.example.schooltimetable.models.entities;
import com.example.schooltimetable.models.constants.StudentEntityConstants;
import com.example.schooltimetable.models.constants.TimetableEntityConstants;
import org.springframework.lang.NonNull;
import javax.persistence.*;
import java.util.UUID;
@Entity
@Table(name = StudentEntityConstants.TABLE_NAME)
public class StudentEntity {
@Id
@Column(name = StudentEntityConstants.ID)
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column(name = StudentEntityConstants.FIRST_NAME)
@NonNull
private String firstName;
@Column(name = StudentEntityConstants.LAST_NAME)
@NonNull
private String lastName;
@Column(name = StudentEntityConstants.REFERENCE)
@GeneratedValue(strategy = GenerationType.AUTO)
private UUID reference;
@OneToOne(targetEntity = TimeTableEntity.class)
@JoinColumn(name = TimetableEntityConstants.REFERENCE, updatable = false, insertable = false)
private TimeTableEntity timeTable;
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return this.lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public UUID getReference() {
return this.reference;
}
public void setReference(UUID reference) {
this.reference = reference;
}
public TimeTableEntity getTimeTable() {
return this.timeTable;
}
}
Thanks to @Abhinaba Chakraborty for pointing me in the right direction
