I have the following problem. I have a simple Spring Boot Application that is supposed to process the debts of users. The service does compile, but neither a PostRequest to insert a new record nor a GetRequest to display the debt of a user works. When the service is started, the application automatically creates the appropriate table for the entity. Therefore I assume that the database connection will not be the problem. It looks like my service does not recognize the RestController. With Postman I keep getting the error code "404 Not Found".
Does anyone have any idea what I am doing wrong?
My Entity
package Entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
@Entity
@Table(name= "debts")
@EnableAutoConfiguration
public class DebtsEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@Column(name = "user_id")
private String userId;
@Column(name = "invoice_id")
private int invoiceId ;
@Column(name = "creditor")
private String creditor;
@Column(name = "amount")
private double amount;
@Column(name = "deadline")
private String deadline;
@Column(name = "installment")
private double installment;
public DebtsEntity(){
}
public DebtsEntity(int id, String userId, int invoiceId, String creditor, double amount, String deadline,
double installment) {
super();
this.id = id;
this.userId = userId;
this.invoiceId = invoiceId;
this.creditor = creditor;
this.amount = amount;
this.deadline = deadline;
this.installment = installment;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public int getInvoiceId() {
return invoiceId;
}
public void setInvoiceId(int invoiceId) {
this.invoiceId = invoiceId;
}
public String getCreditor() {
return creditor;
}
public void setCreditor(String creditor) {
this.creditor = creditor;
}
public double getAmount() {
return amount;
}
public void setAmount(double amount) {
this.amount = amount;
}
public String getDeadline() {
return deadline;
}
public void setDeadline(String deadline) {
this.deadline = deadline;
}
public double getInstallment() {
return installment;
}
public void setInstallment(double installment) {
this.installment = installment;
}
@Override
public String toString() {
return "debtsEntity [id=" id ", userId=" userId ", invoiceId=" invoiceId ", creditor=" creditor
", amount=" amount ", deadline=" deadline ", installment=" installment "]";
}
}
My RestController
package Controller;
import java.net.URI;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import DAO.DebtsDAO;
import Entity.DebtsEntity;
@RestController
public class DebtsController {
@Autowired
DebtsDAO debtsDAO;
@GetMapping("/{userId}/debts")
public List<DebtsEntity> retrieveDebtsByUserId(@PathVariable String userId)
{
List<DebtsEntity> debts = debtsDAO.findByUserId(userId);
return debts;
}
@PostMapping("/debts")
public ResponseEntity<Object> createInvoice(@RequestBody DebtsEntity debtsEntity)
{
DebtsEntity savedUser =debtsDAO.save(debtsEntity);
URI location= ServletUriComponentsBuilder.fromCurrentRequest()
.path("path/{id}")
.buildAndExpand(savedUser.getId()).toUri();
return ResponseEntity.created(location).build();
}
}
My DAO
package DAO;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Component;
import Entity.DebtsEntity;
@Component
public interface DebtsDAO extends JpaRepository<DebtsEntity, Integer>{
List<DebtsEntity> findByUserId(String user_id);
}
My application.properties
## Database konfiguration
spring.datasource.url=jdbc:postgresql://localhost:5432/Test
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.jpa.hibernate.ddl-auto=create
# define if Database Queries should be written in logfile
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.default_schema=public
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL81Dialect
server.port=8000
spring.application.name=Debts
My dependencies
<?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.5.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>LifeOps</groupId>
<artifactId>Service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Service</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.postgresql/postgresql -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</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>
<scope>runtime</scope>
<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>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
UPDATE 1
Get-Request
URL: http://localhost:8000/1000/depts
PostRequest
URL: http://localhost:8000/depts RequestBody:
{
"id":1000,
"user_id": "ABC1234",
"invoice_id":100001,
"creator": "A12L",
"amount": 123012.56,
"deadline": "20.10.12",
"installment": 50.00
}
package Service;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
@EntityScan(basePackages = "entity")
@SpringBootApplication
public class ServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceApplication.class, args);
}
}
UPDATE 2
Class package
DebtsApplication service.debts
DebtsController service.debts.controller
DebtsEntity service.debts.entity
DebtsDAO service.debts.dao
CodePudding user response:
I would suggest you add a base package (something like "com.doncarlito") and put ServiceApplication
in it.
package com.doncarlito;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
@EntityScan(basePackages = "entity")
@SpringBootApplication
public class ServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceApplication.class, args);
}
}
Then move all the other existent packages to be sub-packages of this one:
- com.doncarlito.entity
- com.doncarlito.dao
- com.doncarlito.controller
- com.doncarlito.service
The reason being that @SpringBootApplication
encapsulates @Configuration
, @EnableAutoConfiguration
, and @ComponentScan
annotations with their default attributes. The default value for @ComponentScan
means that all the sub-packages on the package the @ComponentScan
is used are scanned. That is why it is usually a good practice to include the main class in the base package of the project.
CodePudding user response:
You are running your app from x.y.z.ApplicationService
but your components are in different pacage like x.y.a.YourComponent
which will NOT be picked up by the spring.
By default, spring scans package (and descendants) of your @SpringApplication
class. In reference to the above it would be x.y.z.*.....
To solve your problem (alternatives)
- Move your
ApplicationService
next toDebtsApplication
so it will be "on top" of all required components (@RestController
for example) - Add
@ComponentScan(basePackgages={'service.debts'})
toApplicationService
so you will "manually" show spring where to look for components. - There are other ways, but you should be fine with those 2