I am trying to parse a request body into an object (I am using Java Spring boot).
This is how my controller looks like:
public class UserController {
@PutMapping("/lock/{id}")
public Optional<User> lockUser(@PathVariable Long id, @Validated @RequestBody UserLockRequest user) {
return userService.lockUser(id, user);
}
}
My UserService
looks like this:
public Optional<User> lockUser(Long userId, UserLockRequest userLockRequest) {
Optional<User> user = userRepository.findById(userId);
user.get().setLocker(userLockRequest.getLocker());
userRepository.save(user.get());
return user;
}
And my request class UserLockRequest
looks like this:
public class UserLockRequest {
@NotBlank
@NotNull
private Locker locker;
public Locker getLocker() {
return locker;
}
public void setLocker(Locker locker) {
this.locker = locker;
}
}
And my request looks like this:
curl --location --request PUT 'http://localhost:8081/user/lock/8' \
--header 'Content-Type: application/json' \
--data-raw '{
"locker_id": "1"
}'
My User
entity contains locker
field:
@OneToOne
@JoinColumn(name = "locker_id")
private Locker locker;
I can see that userLockRequest.getLocker()
in the UserService
is always null.
I am trying to assign a Locker
to a User
object and save it in the database.
I am not sure how to map locker_id
from the PUT request to UserLockRequest
which I use for accepting the request.
Any help is much appreciated :)
CodePudding user response:
You will need to get Locker
from the database and assign it to the User
. In order to achieve this you need a couple of changes:
public class UserLockRequest {
private long locker_id; // so that it matches your JSON, but it should really be "lockerId" and you should update your JSON
// getter / setter
}
Then you need to adjust your UserService
code as well to get the Locker
from the database:
public Optional<User> lockUser(Long userId, UserLockRequest userLockRequest) {
Optional<User> user = userRepository.findById(userId);
Locker locker = lockerService.getById(userLockRequest.getLockerId());
user.get().setLocker(locker);
userRepository.save(user.get());
return user;
}
I assumed you have a LockerService
with a method returning a Locker
given its ID.
Finally, avoid using Optional.get()
without checking that the Optional
is not empty, otherwise, you might get a NoSuchElementException
. You could do something along the following lines instead:
public User lockUser(Long userId, UserLockRequest userLockRequest) {
Optional<User> optionalUser = userRepository.findById(userId);
Locker locker = lockerService.getById(userLockRequest.getLockerId());
if (optionalUser.isPresent()) {
User user = optionalUser.get();
user.setLocker(locker);
userRepository.save(user.);
return user;
} else {
// throw some custom exception or just return null, it is your decision
}
}
CodePudding user response:
Alright, I assume
- you have a User entity and a Lock entity and you need to tag a Lock entity against an user entity
- You have JpaRepository interfaces for both User and Lock entity.
- You have lombok dependency in your project
If that's correct, below is a solution I would implement. This helps in better API design and separating the responsibilities between Controller and service classes.
- Define
UserLockRequest
request body class
@Getter
@Setter
public class UserLockRequest{
@NotNull
@NotBlank
private int userId;
@NotNull
@NotBlank
private long lockerId;
}
UserService
class. I use constructor based injection as recommended by spring.
@Service
public class UserService {
private final UserRepository userRepository;
private final LockerRepository lockerRepository;
public UserService(UserRepository userRepository, LockerRepository lockerRepository) {
this.userRepository = userRepository;
this.lockerRepository = lockerRepository;
}
public User lockUser(UserLockRequest userLockRequest) {
Optional<User> optionalUser =
userRepository.findById(userLockRequest.getUserId());
Optional<Locker> locker = lockerRepository.findById(userLockRequest.getLockerId());
if (optionalUser.isPresent() && locker.isPresent()) {
User user = optionalUser.get();
user.setLocker(locker.get());
userRepository.save(user);
return user;
} else {
// Error handling is upto you based on what requirement you have
}
}
}
UserController
class
public class UserController {
@PutMapping("/lock")
public Optional<User> lockUser(@Validated @RequestBody UserLockRequest userLockRequest) {
return userService.lockUser(userLockRequest);
}
}
- Now below is how your http call looks like
curl --location --request PUT 'http://localhost:8081/user/lock/ \
--header 'Content-Type: application/json' \
--data-raw '{
"user_id": 8,
"locker_id":"1"
}'