Поэтому я создал следующий API для отдыха, используя Spring 5.
http://localhost:8080/restful-webservices/users/DtvQLbP5uUXaJr4y5n2yxch3BODQCd
{
"userId": "DtvQLbP5uUXaJr4y5n2yxch3BODQCd",
"firstName": "T",
"lastName": "T",
"email": "[email protected]",
"addresses": [
{
"id": 158,
"addressId": "yRK81aJUn2Sfh4JSaWU4svr2YtWgZj",
"city": "Larissa",
"country": "Greece",
"streetName": "Iasonos 33",
"postalCode": "41223",
"type": "billing"
},
{
"id": 157,
"addressId": "ajyPnC75jQ2G5aqfDY4sqBYk5BUE9X",
"city": "Larissa",
"country": "Greece",
"streetName": "Palaiologou 11",
"postalCode": "41223",
"type": "shipping"
}
]
}
Я могу обновить данные пользователя, но теперь я также хочу обновить данные адреса. http://localhost:8080/restful-webservices/users/DtvQLbP5uUXaJr4y5n2yxch3BODQCd/addresses/yRK81aJUn2Sfh4JSaWU4svr2YtWgZj
{
"addressId": "yRK81aJUn2Sfh4JSaWU4svr2YtWgZj",
"city": "Larissa",
"country": "Greece",
"streetName": "Iasonos 33",
"postalCode": "41223",
"type": "billing"
}
Тем не менее, я получаю это
{
"timestamp": "2019-03-24T08:53:27.986+0000",
"message": "Missing URI template variable 'id' for method parameter of type String"
}
Вот мой класс АдресСервисИмпл
@Service
public class AddressServiceImpl implements AddressService {
@Autowired
UserRepository userRepository;
@Autowired
AddressRepository addressRepository;
@Override
public List<AddressDTO> getAddresses(String userId) {
List<AddressDTO> returnValue = new ArrayList<>();
ModelMapper modelMapper = new ModelMapper();
UserEntity userEntity = userRepository.findByUserId(userId);
if (userEntity == null) return returnValue;
Iterable<AddressEntity> addresses = addressRepository.findAllByUserDetails(userEntity);
for(AddressEntity addressEntity : addresses){
returnValue.add(modelMapper.map(addressEntity, AddressDTO.class));
}
return returnValue;
}
@Override
public AddressDTO getAddress(String addressId) {
AddressDTO returnValue = null;
AddressEntity addressEntity = addressRepository.findByAddressId(addressId);
if (addressEntity != null){
returnValue = new ModelMapper().map(addressEntity, AddressDTO.class);
}
return returnValue;
}
@Override
public AddressDTO updateAddress(String addressId, AddressDTO address) {
AddressDTO returnValue = new AddressDTO();
AddressEntity addressEntity = addressRepository.findByAddressId(addressId);
if (addressEntity == null){
throw new UserServiceException(ErrorMessages.NO_RECORD_FOUND.getErrorMessage());
}
addressEntity.setCity(address.getCity());
addressEntity.setCountry(address.getCountry());
addressEntity.setPostalCode(address.getPostalCode());
addressEntity.setStreetName(address.getType());
AddressEntity updatedUserEntity = addressRepository.save(addressEntity);
BeanUtils.copyProperties(updatedUserEntity,returnValue);
return returnValue;
}
}
и мой контроллер.
@RestController
@RequestMapping("users")
public class UserController {
@Autowired
UserService userService;
@Autowired
AddressService addressService;
@Autowired
AddressService addressesService;
@GetMapping(path = "/{id}",
produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE} )
public UserRest getUser(@PathVariable String id){
UserRest returnValue = new UserRest();
UserDto userDto = userService.getUserByUserId(id);
BeanUtils.copyProperties(userDto, returnValue);
return returnValue;
}
@PostMapping(
consumes = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE},
produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE})
public UserRest createUser(@RequestBody UsersDetailsRequestModel userDetails) throws Exception{
UserRest returnValue = new UserRest();
if (userDetails.getFirstName().isEmpty()) throw new NullPointerException("The object is null");
// UserDto userDto = new UserDto();
// BeanUtils.copyProperties(userDetails,userDto);
ModelMapper modelMapper = new ModelMapper();
UserDto userDto = modelMapper.map(userDetails, UserDto.class);
UserDto createUser = userService.createUser(userDto);
// BeanUtils.copyProperties(createUser,returnValue);
returnValue = modelMapper.map(createUser, UserRest.class);
return returnValue;
}
@PutMapping(path = "/{id}",
consumes = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE},
produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE})
public UserRest updateUser(@PathVariable String id, @RequestBody UsersDetailsRequestModel userDetails){
UserRest returnValue = new UserRest();
if (userDetails.getFirstName().isEmpty()) throw new NullPointerException("The object is null");
UserDto userDto = new UserDto();
BeanUtils.copyProperties(userDetails,userDto);
UserDto updatedUser = userService.updateUser(id, userDto);
BeanUtils.copyProperties(updatedUser,returnValue);
return returnValue;
}
@DeleteMapping(path = "/{id}", produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE })
public OperationStatusModel deleteUser(@PathVariable String id){
OperationStatusModel returnValue = new OperationStatusModel();
returnValue.setOperationName(RequestOperationName.DELETE.name());
userService.deleteUser(id);
returnValue.setOperationResult(RequestOperationStatus.SUCCESS.name());
return returnValue;
}
@GetMapping(produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE })
public List<UserRest> getUsers(@RequestParam(value = "page", defaultValue = "0") int page,
@RequestParam(value = "limit", defaultValue = "25") int limit){
List<UserRest> returnValue = new ArrayList<>();
List<UserDto> users = userService.getUsers(page,limit);
for(UserDto userDto : users){
UserRest userModel = new UserRest();
BeanUtils.copyProperties(userDto, userModel);
returnValue.add(userModel);
}
return returnValue;
}
//http://localhost:8080/restful-webservices/users/id/addresses
@GetMapping(path = "/{id}/addresses",
produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE} )
public List<AddressesRest> getUserAddresses(@PathVariable String id){
List<AddressesRest> returnValue = new ArrayList<>();
List<AddressDTO> addressesDTO = addressesService.getAddresses(id);
if (addressesDTO != null && !addressesDTO.isEmpty()){
Type listType = new TypeToken<List<AddressesRest>>(){}.getType();
returnValue = new ModelMapper().map(addressesDTO, listType);
}
return returnValue;
}
@GetMapping(path = "/{userId}/addresses/{addressId}",
produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE} )
public AddressesRest getUserAddress(@PathVariable String addressId){
AddressDTO addressesDto = addressService.getAddress(addressId);
ModelMapper modelMapper = new ModelMapper();
return modelMapper.map(addressesDto, AddressesRest.class);
}
@PutMapping(path = "/{userId}/addresses/{addressId}",
consumes = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE},
produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE})
public AddressesRest updateAddress(@PathVariable String id, @RequestBody AddressesRequestModel addressDetails){
AddressesRest returnValue = new AddressesRest();
if (addressDetails.getCity().isEmpty()
|| addressDetails.getCountry().isEmpty()
|| addressDetails.getPostalCode().isEmpty()
|| addressDetails.getStreetName().isEmpty()
|| addressDetails.getType().isEmpty()) throw new NullPointerException("The object is null");
AddressDTO addressDto = new AddressDTO();
BeanUtils.copyProperties(addressDetails, addressDto);
AddressDTO updatedAddress = addressService.updateAddress(id, addressDto);
BeanUtils.copyProperties(updatedAddress,returnValue);
return returnValue;
}
}
Это мой репо
Как можно исправить эту ошибку? Есть идеи?
Спасибо,
Тео.




Missing URI template variable 'id' for method parameter of type String
Сообщение ясно. В нем говорится, что вы определили переменную пути с именем «id», но в URI нет такой переменной шаблона. И действительно:
@PutMapping(path = "/{userId}/addresses/{addressId}", // there is no {id} in the path
...)
public AddressesRest updateAddress(@PathVariable String id, // there should be an {id} in the path
...
Вы объявили две переменные пути с именами userId и addressId, но есть только один аргумент метода с аннотацией @PathVariable с именем id. Вы можете исправить аргументы метода:
@PutMapping(path = "/{userId}/addresses/{addressId}",
consumes = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE},
produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE})
public AddressesRest updateAddress(@PathVariable String userId, @PathVariable String addressId, @RequestBody AddressesRequestModel addressDetails){
// ...
}
Если идентификаторы адресов уникальны, тогда идентификатор пользователя является избыточным, поэтому вы также можете изменить URI:
@PutMapping(path = "/address/{id}",
consumes = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE},
produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE})
public AddressesRest updateAddress(@PathVariable String id, @RequestBody AddressesRequestModel addressDetails){
// ...
}
В вашем методе updateAddress вы должны передать переменную пути с двумя параметрами.
@PutMapping(path = "/{userId}/addresses/{addressId}",
consumes = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE},
produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE})
public AddressesRest updateAddress(@PathVariable String userId, @PathVariable String addressId, @RequestBody AddressesRequestModel addressDetails){
AddressesRest returnValue = new AddressesRest();
if (addressDetails.getCity().isEmpty()
|| addressDetails.getCountry().isEmpty()
|| addressDetails.getPostalCode().isEmpty()
|| addressDetails.getStreetName().isEmpty()
|| addressDetails.getType().isEmpty()) throw new NullPointerException("The object is null");
AddressDTO addressDto = new AddressDTO();
BeanUtils.copyProperties(addressDetails, addressDto);
AddressDTO updatedAddress = addressService.updateAddress(addressId, addressDto);
BeanUtils.copyProperties(updatedAddress,returnValue);
return returnValue;
}