Я создаю REST API с использованием Spring Boot Starter Web, Spring Data JPA и HATEOAS (не использую Spring Data REST), как в этом уроке https://spring.io/guides/tutorials/rest/.
Первое, что нужно упомянуть, это то, что моей проблемы нет, когда Spring Data REST добавляется в зависимости.
Это приложение для планирования поездки, и есть «Пользователи», которые могут иметь несколько «Поездок», но для добавления «Поездки» необходимо также указать его «Пользователя».
Вообще говоря, я пытаюсь сделать POST-запрос с json body, как показано ниже (я подключил Trip и User Entities и POST-метод к Trip Controller тоже)
//JSON THAT PRODUCES AN ERROR
{
"name" : "ExampleTrip",
"user" : "/users/1" <-this produces an error
}
// BASE ENTITY
@MappedSuperclass
public class BaseEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
protected BaseEntity() {}
//ID GETTER AND SETTER
}
// USER ENTITY
@Entity
@Table(name = "users")
public class User extends BaseEntity {
public static final PasswordEncoder PASSWORD_ENCODER = new BCryptPasswordEncoder();
@Size(min = 3, max = 15, message = "Username must be between 3 and 15 characters long")
private String username;
private String firstName;
private String lastName;
@Size(min = 5, max= 20 message = "Password must be between 5 and 20 characters
long")
private String password;
@NotNull(message = "User must have role attached")
private String [] roles;
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private List <Trip> userTrips;
protected User() {
super();
};
public User(String username, String password, String firstName, String
lastName, String [] roles) {
this.username = username;
setPassword(password);
this.firstName = firstName;
this.lastName = lastName;
this.roles = roles;
}
public void addTrip(Trip trip) {
trip.setUser(this);
userTrips.add(trip);
}
// TRIP ENTITY
@Entity
@Table(name = "trips")
public class Trip extends BaseEntity {
@NotNull(message = "Trip must have its name")
@Size(max = 40, message = "Trip name must be up to 40 characters long")
private String name;
private int length = 0;
@OneToMany(mappedBy = "trip", cascade = CascadeType.ALL)
private List <TripDay> tripDays;
@ManyToOne
@NotNull
private User user;
protected Trip() {
super();
}
public Trip(String name, User user) {
this.name = name;
this.user = user;
}
//Getters and setters
}
//TRIP CONTROLLER POST METHOD
@RestController
public class TripController {
@PostMapping("/trips")
public ResponseEntity <?> createTrip(@Valid @RequestBody Resource<Trip> trip) throws URISyntaxException {
Resource <Trip> resource = tripResourceAssembler.toResource(tripRepository.save(trip.getContent()));
return ResponseEntity
.created(new URI(resource.getId().expand().getHref()))
.body(resource);
}
}
Итак, отправка почтового запроса приводит к ошибке:
Решено [org.springframework.http.converter.HttpMessageNotReadableException: ошибка синтаксического анализа JSON: Невозможно создать экземпляр ***.tripplanner.user.User
(хотя существует хотя бы один создатель): нет конструктора аргумента строки / метода фабрики для десериализации из значения String ('/ users / 1' ); вложенным исключением является com.fasterxml.jackson.databind.exc.MismatchedInputException: невозможно создать экземпляр ***.tripplanner.user.User
(хотя существует хотя бы один создатель): отсутствует конструктор аргумента строки / метод фабрики для десериализации из значения String ('/ users / 1 «)
в [Источник: (PushbackInputStream); строка: 4, столбец: 1] (через цепочку ссылок: ***. tripplanner.trip.Trip ["user"])]
Чего не хватает в Spring Boot Starter Web, комбинации JPA и HATEOAS по сравнению с Spring Data REST, что вызывает эту ошибку? Я хотел бы создать целую структуру конечных точек самостоятельно и узнать, поэтому я не хочу использовать Spring Data REST. Или это что-то не так с моим кодом?
Конечно, есть пользователь в /users/1.
Я пробовал подобные решения https://jira.spring.io/browse/DATAREST-687, но они предназначены для Spring Data Rest (как я сказал, я им не пользуюсь) и они не работают.
Спасибо!