I have implemented a Spring Boot project:
ETLproject, the application name is ETLprojectApplication.
A POST request in Postman (url: http://localhost:8080/project/api/json/users/save)
releases this error code:
{
"type": "about:blank",
"title": "Not Found",
"status": 404,
"detail": "No static resource project/api/json/users/save.",
"instance": "/project/api/json/users/save"
}
the code of pom.xml is the following:
<?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>3.2.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>it.projects</groupId>
<artifactId>ETLproject</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>H2Project</name>
<description>H2Project</description>
<properties>
<java.version>17</java.version>
</properties>
<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-jdbc</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-web-services</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</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>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<scope>runtime</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>
I try to show the structure the project and the relative package:
package dto
JsonPlaceholderUser
package it.projects.SQLserverProject.dto;
import jakarta.persistence.*;
import lombok.*;
@Data
public class JsonPlaceholderUser {
private int id;
private String name;
private String username;
private String email;
private JsonPlaceholderAddress address;
private String phone;
private String website;
private JsonPlaceholderCompany company;
}
package dto
JsonPlaceholderAddress:
package it.projects.SQLserverProject.dto;
import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.*;
import lombok.*;
import java.util.ArrayList;
import java.util.*;
@Data
public class JsonPlaceholderAddress {
private Integer id;
private String street;
private String suite;
private String city;
private String zipcode;
private JsonPlaceholderGeo geo;
private List<JsonPlaceholderUser> user = new ArrayList<>();
}
package dto
JsonPlaceholderGeo
package it.projects.SQLserverProject.dto;
import com.fasterxml.jackson.annotation.*;
import jakarta.persistence.*;
import lombok.*;
import java.util.*;
@Data
public class JsonPlaceholderGeo {
private int geo;
private String lat;
private String lng;
private List < JsonPlaceholderAddress > address = new ArrayList<>();
}
package dto
JsonPlaceholderCompany
package it.projects.SQLserverProject.dto;
import com.fasterxml.jackson.annotation.*;
import jakarta.persistence.*;
import lombok.*;
import java.util.*;
@Data
public class JsonPlaceholderCompany {
private int id;
private String name;
private String catchPhrase;
private String bs;
private List<JsonPlaceholderUser> user = new ArrayList<>();
}
package entity
ProfileUser
package it.projects.SQLserverProject.entity;
import jakarta.persistence.*;
import lombok.*;
@Data
@Entity
@Table(name = "userProfile")
public class ProfileUser {
@Id
@Column(name="id")
private Integer id;
@Column(name="username")
private String username;
@Column(name="email")
private String email;
@Column(name="street")
private String street;
@Column(name="suite")
private String suite;
@Column(name="city")
private String city;
@Column(name="zipcode")
private String zipcode;
@Column(name="phone")
private String phone;
@Column(name="website")
private String website;
@Column(name="lat")
private String lat;
@Column(name="lng")
private String lng;
@Column(name="companyName")
private String companyName;
@Column(name="companyCatchPhrase")
private String companyCatchPhrase;
@Column(name="companyBs")
private String companyBs;
}
package service
FetchJsonPlaceholderUserService
package it.projects.SQLserverProject.service;
import it.projects.SQLserverProject.dto.*;
import it.projects.SQLserverProject.exception.*;
import it.projects.SQLserverProject.config.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.http.*;
import org.springframework.stereotype.*;
import org.springframework.web.client.*;
import com.fasterxml.jackson.databind.*;
import java.util.*;
@Service
public class FetchJsonPlaceholderUserService {
@Autowired
private RestTemplate restTemplate;
public List< JsonPlaceholderUser > fetchUserList() {
String url = "https://jsonplaceholder.typicode.com/users";
// rest call
ResponseEntity< Object[] > response = restTemplate.getForEntity(url, Object[].class);
// Tempory Varables
Object[] objects = response.getBody();
// Mapping
ObjectMapper mapper = new ObjectMapper();
// Return data variables
try {
if (objects == null || objects.length == 0) {
throw new JsonPlaceholderUserListNotFoundException("Json placeholder users list not found");
}
List< JsonPlaceholderUser > jsonPlaceholderUserList = new ArrayList<>();
for (int i = 0; i < objects.length; i++) {
jsonPlaceholderUserList.add(mapper.convertValue(objects[i], JsonPlaceholderUser.class));
}
return jsonPlaceholderUserList;
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
public List< Map< String, Object > > getListPeople() {
// Build an URL with user id
String url = "https://jsonplaceholder.typicode.com/users/";
try{
ResponseEntity< JsonPlaceholderUser[] > response = restTemplate.getForEntity(url, JsonPlaceholderUser[].class);
// Retrieve the array of users from the response
Object[] objects = response.getBody();
// Mapping
ObjectMapper mapper = new ObjectMapper();
// List for containing results
List <Map <String, Object>> peopleList = new ArrayList<>();
// Checking if the user list is void
if (objects == null || objects.length == 0){
throw new JsonPlaceholderUserListNotFoundException("Json placeholder users list not found");
}
// Iterating users
for (Object obj : objects){
// Converting the object to a JsonPlaceholderUser
JsonPlaceholderUser user = mapper.convertValue(obj, JsonPlaceholderUser.class);
// Mapping for rappresenting the current user
Map<String, Object> userMap = new LinkedHashMap<>();
// Adding the name of the user as key
userMap.put(("id"), user.getId());
userMap.put("name", user.getName());
userMap.put("username", user.getUsername());
userMap.put("email", user.getEmail());
userMap.put("phone", user.getPhone());
userMap.put("website", user.getWebsite());
// Mapping for rappresenting the address user
Map<String, Object> addressMap = new LinkedHashMap<>();
JsonPlaceholderAddress address = user.getAddress();
// Adding the user address as key
addressMap.put(("street"), address.getStreet());
addressMap.put(("suite"), address.getSuite());
addressMap.put(("city"), address.getCity());
addressMap.put(("zipcode"), address.getZipcode());
// Mapping for rappresenting the geo of the street as key
Map<String, Object> geoMap = new LinkedHashMap<>();
JsonPlaceholderGeo geo = user.getAddress().getGeo();
// Adding the street geo as key
geoMap.put(("lat"), geo.getLat());
geoMap.put(("lng"), geo.getLng());
// Mapping for rappresenting the company of the user as key
Map<String, Object> companyMap = new LinkedHashMap<>();
JsonPlaceholderCompany company = user.getCompany();
// Adding the company user as key
companyMap.put(("name"), company.getName());
companyMap.put(("catchPhrase"), company.getCatchPhrase());
companyMap.put(("bs"), company.getBs());
// Adding object maps nested in the user's map
userMap.put("address", addressMap);
userMap.put("geo", geoMap);
userMap.put("company", companyMap);
// Adding the user map to the results list
peopleList.add(userMap);
}
return peopleList;
}catch(HttpClientErrorException.NotFound e){
throw new JsonPlaceholderUserNotFoundException("Failed to fetch users from JSONPlaceholder API", e);
}catch(Exception e){
e.printStackTrace();
throw e;
}
}
public JsonPlaceholderUser fetchUserById(int id) {
// Build an URL with user id
String url = "https://jsonplaceholder.typicode.com/users/" + id;
try {
ResponseEntity< JsonPlaceholderUser > response = restTemplate.getForEntity(url, JsonPlaceholderUser.class);
if (response.getStatusCode().is2xxSuccessful()) {
return response.getBody();
} else {
throw new JsonPlaceholderUserNotFoundException("Json placeholder user with id " + id + " not found");
}
} catch (HttpClientErrorException.NotFound e) {
throw new JsonPlaceholderUserNotFoundException("Json placeholder user with id " + id + " not found", e);
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
public List< JsonPlaceholderUser > findUserByName(String name) {
// Build an URL with user id
String url = "https://jsonplaceholder.typicode.com/users/";
try {
ResponseEntity< JsonPlaceholderUser[] > response = restTemplate.getForEntity(url, JsonPlaceholderUser[].class);
if (response.getStatusCode().is2xxSuccessful()) {
// Retrieve the array of users from response
JsonPlaceholderUser[] users = response.getBody();
// Convert the search name to lowercase
String searchName = name.toLowerCase();
// Filter users by name
List< JsonPlaceholderUser > matchedUsers = new ArrayList<>();
for (JsonPlaceholderUser user : users) {
// Convert the user name to lowercase for case-insensitive comparison
String userNameLowerCase = user.getName().toLowerCase();
if (userNameLowerCase.contains(searchName)) {
matchedUsers.add(user);
}
}
return matchedUsers;
} else {
throw new JsonPlaceholderUserNotFoundException("Failed to fetch users from JSONPlaceholder API");
}
} catch (HttpClientErrorException.NotFound e) {
throw new JsonPlaceholderUserNotFoundException("Failed to fetch users from JSONPlaceholder API", e");
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
}
package service
ProfileUserService
package it.projects.SQLserverProject.service;
import it.projects.SQLserverProject.dto.*;
import it.projects.SQLserverProject.repository.*;
import it.projects.SQLserverProject.entity.*;
import it.projects.SQLserverProject.config.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.http.*;
import org.springframework.stereotype.*;
import org.springframework.web.client.*;
import java.util.*;
@Service
public class ProfileUserService {
@Autowired
private ProfileUserRepository profileUserRepository;
FetchJsonPlaceholderUserService fetchJsonPlaceholderUserService = new FetchJsonPlaceholderUserService();
public void saveUsersToProfile() {
try {
// Ottieni la lista delle persone dalla chiamata API
List< Map< String, Object > > peopleList = fetchJsonPlaceholderUserService.getListPeople();
// Itera attraverso ogni mappa di persona
for (Map< String, Object > userMap : peopleList) {
ProfileUser profileUser = new ProfileUser();
// Imposta i campi del profilo utente dai dati della mappa
profileUser.setUsername((String) userMap.get("username"));
profileUser.setEmail((String) userMap.get("email"));
profileUser.setStreet((String) userMap.get("street"));
profileUser.setSuite((String) userMap.get("suite"));
profileUser.setCity((String) userMap.get("city"));
profileUser.setZipcode((String) userMap.get("zipcode"));
profileUser.setPhone((String) userMap.get("phone"));
profileUser.setWebsite((String) userMap.get("website"));
profileUser.setLat((String) userMap.get("lat"));
profileUser.setLng((String) userMap.get("lng"));
profileUser.setCompanyName((String) userMap.get("companyName"));
profileUser.setCompanyCatchPhrase((String) userMap.get("companyCatchPhrase"));
profileUser.setCompanyBs((String) userMap.get("companyBs"));
// Salva il profilo utente nel database
profileUserRepository.save(profileUser);
}
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
}
package repository
ProfileUserRepository
package it.projects.SQLserverProject.repository;
import it.projects.SQLserverProject.dto.*;
import it.projects.SQLserverProject.entity.*;
import org.springframework.data.jpa.repository.*;
import java.util.*;
public interface ProfileUserRepository extends JpaRepository< ProfileUser, Integer> {
}
package config
CustomExceptionHandler
package it.projects.SQLserverProject.config;
import it.projects.SQLserverProject.entity.*;
import it.projects.SQLserverProject.exception.*;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import java.util.ArrayList;
import java.util.List;
@ControllerAdvice
public class CustomExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(DuplicateProductCodeException.class)
public ResponseEntity<String> handleDuplicateProductCodeException(DuplicateProductCodeException e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage());
}
@ExceptionHandler(ProductIllegalArgumentException.class)
public ResponseEntity<String> handleProductIllegalArgumentException(ProductIllegalArgumentException e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage());
}
@ExceptionHandler(ProductNotFoundException.class)
public ResponseEntity<String> handleProductNotFoundException(ProductNotFoundException e) {
List<Product> emptyProductList = new ArrayList<>();
emptyProductList.add(new Product());
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(e.getMessage() + "n" + emptyProductList);
}
@ExceptionHandler(ProductSaveException.class)
public ResponseEntity<String> handleProductSaveException(ProductSaveException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
}
@ExceptionHandler(JsonPlaceholderUserListNotFoundException.class)
public ResponseEntity<String> handleJsonPlaceholderUserListNotFoundException(JsonPlaceholderUserListNotFoundException e){
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
}
@ExceptionHandler(JsonPlaceholderUserNotFoundException.class)
public ResponseEntity<String> handleJsonPlaceholderUserNotFoundException(JsonPlaceholderUserNotFoundException e){
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
}
}
package config
AppConfig
package it.projects.SQLserverProject.config;
import org.springframework.context.annotation.*;
import org.springframework.web.client.*;
@Configuration
public class AppConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
package controller
FetchJsonPlaceholderUserService
package it.projects.SQLserverProject.controller;
import it.projects.SQLserverProject.service.*;
import it.projects.SQLserverProject.dto.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;
import com.fasterxml.jackson.core.*;
import java.util.*;
@RestController
@RequestMapping("/project/api/json")
public class JsonPlaceholderUserController {
@Autowired
private FetchJsonPlaceholderUserService fetchJsonPlaceholderUserService;
@GetMapping(value = "/user/list", produces = "application/json")
@ResponseBody
public ResponseEntity< ? > getList() throws JsonProcessingException {
List< JsonPlaceholderUser > jsonList = fetchJsonPlaceholderUserService.fetchUserList();
return ResponseEntity.accepted().body(jsonList);
}
@GetMapping(value = "/user/get/{id}", produces = "application/json")
@ResponseBody
public JsonPlaceholderUser getUserById(@PathVariable("id") int id) throws JsonProcessingException {
JsonPlaceholderUser jsonUser = fetchJsonPlaceholderUserService.fetchUserById(id);
return jsonUser;
}
@GetMapping(value = "/user/search/{name}", produces = "application/json")
@ResponseBody
public ResponseEntity< ? > searchName(@PathVariable("name") String searchName) throws JsonProcessingException {
List< JsonPlaceholderUser > jsonNameSearch = fetchJsonPlaceholderUserService.findUserByName(searchName);
return ResponseEntity.accepted().body(jsonNameSearch);
}
@GetMapping(value = "/user/get/people", produces = "application/json")
@ResponseBody
public ResponseEntity< ? > getPeople() throws JsonProcessingException{
List< Map< String, Object > > people = fetchJsonPlaceholderUserService.getListPeople();
return ResponseEntity.accepted().body(people);
}
}
package controller
ProfileUserController
package it.projects.SQLserverProject.controller;
import it.projects.SQLserverProject.service.*;
import it.projects.SQLserverProject.dto.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;
import java.util.*;
@RestController
@RequestMapping("/project/api/json")
public class ProfileUserController {
private final ProfileUserService profileUserService;
@Autowired
public ProfileUserController(ProfileUserService profileUserService) {
this.profileUserService = profileUserService;
}
@PostMapping(value = "/users/save", produces = "application/json")
@ResponseBody
public ResponseEntity<String> saveJsonUser() {
profileUserService.saveUsersToProfile();
return ResponseEntity.ok("Users saved to profile successfully");
}
}
application.yml
# Main Database
spring:
datasource:
url: jdbc:sqlserver://192.168.178.50SQLEXPRESS:1433;databaseName=ETLprojectDB;encrypt=false
driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
username: sa
password: Andreas.1974
jpa:
database-platform: org.hibernate.dialect.SQLServerDialect
hibernate:
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
Can you tell me the cause of the error?
Thank you
Andrea