MongodbReactive what to do when you have empty result - spring

In case no email was found in the database the findByEmail returns null, so it breaks all the process
public Mono<UserDto> findByEmail(String email) {
return this.userRepository.findByEmail(email) // <---- ERROR HERE
.map(userEntity -> userMapper.toDto(userEntity)) // <---- ERROR HERE
.switchIfEmpty(Mono.empty());
}
#Override
public Mono<String> authenticate(String accessToken) {
return this.facebookService.verifyAccessToken(accessToken)
.flatMap(userFacebookDto ->
this.findByEmail(userFacebookDto.getEmail())
.map(userDbDto -> {
String token = "";
if (isNull(userDbDto)) {
UserEntity userEntity = this.userFacebookMapper.toEntity(userFacebookDto);
this.userRepository.save(userEntity)
.map(ue -> this.jwtTokenUtil.generateToken(ue));
} else {
token = jwtTokenUtil.generateToken(this.userMapper.toEntity(null));
}
return token;
})
);
}
What is on your opinion a good chaining strategy for this case in order to continue the execution of the rest of the code ?
The error :
"The mapper returned a null Mono"

Related

How to write custom insert Query Spring Webflux, and return custom response class?

I am new to Reactive programming and I got stuck writing a custom Insert query.
So far I have a FriendshipRepository.java class.
public interface FriendshipRepository extends R2dbcRepository<Friendship, String> {
#Query(value = "INSERT INTO public.friendship(requester_id, addressee_id) values (:requesterid::uuid, :addresseeid::uuid)")
public Mono<Void> insertFriendRequest(
#Param("requesterid") String requesterId,
#Param("addresseeid") String addresseeId
);
}
And a FriendshipController.java class.
#RestController
public class FriendsController {
private final FriendshipRepository friendshipRepository;
public FriendsController(FriendshipRepository friendshipRepository) {
this.friendshipRepository = friendshipRepository;
}
#PostMapping(value = "/request", produces = "application/json")
public Mono<ResponseEntity<RequestResponse>> sendFriendRequest(#RequestBody FriendRequest friendRequest, #AuthenticationPrincipal Mono<User> principal) throws Exception {
String id = principal.map(User::getId).toFuture().get();
return friendshipRepository.insertFriendRequest(id, friendRequest.getUserId()).log()
.then(Mono.just("NEXT"))
.map(e -> {
return ResponseEntity.status(HttpStatus.CREATED).body(new RequestResponse("Success", ResponseCode.SUCCESS));
}).onErrorResume(e -> {
return Mono.just(ResponseEntity.status(HttpStatus.FORBIDDEN).body(new RequestResponse("Friend request was unsuccessful ", ResponseCode.REFUSED)));
});
}
}
This is a working example.
But I dont understand why I have to call .then(Mono.just("NEXT")) and create a new Mono to be able to return a custom ResponseEntity<RequestResponse>>. I also tried merge the the whole process. I meen by this at the begining when I get the Id from the ReactiveSpringSecutiryContext that is a blocking line of code and If I know it correctly that is a bad approach in Reactive programming.
I tried this approach but in this case, I can only retrun the Id of the user.
Mono<String> userId = principal.map(User::getId);
return userId.doOnNext(id -> {
friendshipRepository.insertFriendRequest(id, friendRequest.getUserId()).log()
.map(e -> {
return ResponseEntity.status(HttpStatus.CREATED).body(new RequestResponse("SIKER", ResponseCode.SUCCESS));
})
.onErrorResume(e -> {
return Mono.just(ResponseEntity.status(HttpStatus.FORBIDDEN).body(new RequestResponse("Friend request was unsuccessful ", ResponseCode.REFUSED)));
}).subscribe();
// .doOnSuccess(e -> ServerResponse.noContent().build((new RequestResponse("SIKER", ResponseCode.SUCCESS)), Void.class));
});
How could I rewrite this endpoint? Or does my whole approach inaproptirate?
Thank you in advance for your help.
Probably not the nicest solution, but better then it was.
My query:
public interface FriendshipRepository extends R2dbcRepository<Friendship, String> {
#Query(value = "INSERT INTO public.friendship(requester_id, addressee_id) values (:requesterid::uuid, :addresseeid::uuid) RETURNING id")
public Mono<String> insertFriendRequest(
#Param("requesterid") String requesterId,
#Param("addresseeid") String addresseeId
);
}
My api:
#PostMapping(value = "/request", produces = "application/json")
public Mono<ResponseEntity<RequestResponse>> sendFriendRequest(#RequestBody FriendRequest friendRequest, #AuthenticationPrincipal Mono<User> principal) throws Exception {
String id = principal.map(User::getId).toFuture().get();
return friendshipRepository.insertFriendRequest(id, friendRequest.getUserId()).log()
.map(e -> {
return ResponseEntity.status(HttpStatus.CREATED).body(new RequestResponse("Success", ResponseCode.SUCCESS));
}).onErrorResume(e -> {
return Mono.just(ResponseEntity.status(HttpStatus.FORBIDDEN).body(new RequestResponse("Friend request was unsuccessful ", ResponseCode.REFUSED)));
});
}

WebClient: Waiting for blocking call in API to perform a new call

I am currently making a microservice to create test users for our automated test environment. The database is reachable through another API, so in order to create a test user, I need to perform a call to this API.
The test users should be created and then later disposed of when the test has been executed. The identifier of the test users is the SSN (national identifier digit), and it is unique to each citizen. My API/microservice generates a new user with a generated SSN and should post it to a DB over the API to the backend service controlling the database. This backend service is not reactive.
The problem is that in the database, there are already many existing users which are used by other tests executed manually. The existing test users cannot be tampered with, so I need to verify that the generated SSN is not already existing in the DB.
My approach is as follows:
generate a new ssn
while(ssn exists in db){
generate new ssn
}
post generated user to db
However, when placing a .block() on the check if the user exists (bad practice, I know...) the program halts in a deadlock and nothing happens.
My controller:
#ResponseBody
#PostMapping("normal")
public Mono<User> createNormalUser() throws Exception {
return userService.createNormalUser();
}
#ResponseBody
#GetMapping("{ssn}")
public Mono<User> getUserBySSN(#PathVariable String ssn){
return userService.getUserBySsn(ssn);
}
My service:
public Mono<User> createNormalUser(){
String ssn = generateNewSsnNotInDB();
Mono<UserResource> newUserMono = Mono.just(
UserResource.builder()
.ssn(ssn)
.email(ssn + "-test#somedomain.com")
.state("NORMAL")
.preferred2FaMethod("some2FAMethod")
.build()
);
return postUser(newUserMono)
.then(updatePassword(ssn))
.then(setState(ssn, "NORMAL"));
}
private String generateNewSsnNotInDB() {
String ssn;
boolean userExists = false;
do {
ssn = ssnGenerator.generateOneValidSsnOnDate(ssnGenerator.generateRandomSsnDate());
userExists = checkIfUserExists(ssn);
} while (userExists);
return ssn;
}
private boolean checkIfUserExists(String ssn) {
User user;
try {
user = getUserBySsn(ssn).share().block();
return true;
} catch (WebClientResponseException.NotFound exception) {
return false;
}
}
public Mono<User> getUserBySsn(String ssn) {
return webClient.get()
.uri(userBySsnURI(ssn))
.retrieve()
.bodyToMono(User.class);
}
public Mono<User> postUser(Mono<UserResource> userMono) {
return webClient.post()
.uri(setUserURI())
.body(userMono, UserResource.class)
.retrieve()
.bodyToMono(User.class);
}
public Mono<User> postUser(User user) {
user.setPid(generateNewSsnNotInDB());
UserResource res = UserResource.builder()
.ssn(user.getPid())
.email(user.getEmail())
.phoneNumber(user.getPhoneNumber())
.state(user.getState())
.preferred2FaMethod(user.getPreferred2FaMethod())
.password(user.getPassword())
.build();
log.info("Resource generated in post-user is: " + res.toString());
return postUser(Mono.just(res));
}
public Mono<User> updatePassword(String ssn) {
Mono<User> user = Mono.just(User.builder()
.pid(ssn)
.password("password01")
.build());
return webClient.patch()
.uri(setUpdatePasswordURI())
.body(user, User.class)
.retrieve()
.bodyToMono(User.class);
}
private Mono<User> setState(String ssn, String state) {
return webClient.put()
.uri(updateStateURI(ssn, state))
.retrieve()
.bodyToMono(User.class);
}
I have chained the calls in the createNormalUser function because the backend requires this sequence in order to set the required attributes for the user. I am not sure why this is the required sequence, and changing this is not part of my scope.
I have also omitted some functions which probably aren't relevant for this question.
Can somebody please help me in the right direction on how to perform the calls with checkIfUsersExist and then post the user? I have been trying to wrap my head around this for a week now with no luck.
The strangest thing is that if I first call getUser with a valid ssn, then postUser works fine. If I try to call postUser without calling getUser first, it deadlocks on the .block().
Avoid the block() call and user chained calls instead as follows (createNormalUser() and generateNewSsnNotInDB() were updated and checkIfUserExists() deleted):
public Mono<User> createNormalUser(){
Mono<UserResource> newUserMono = generateNewSsnNotInDB().map( ssn ->
UserResource.builder()
.ssn(ssn)
.email(ssn + "-test#somedomain.com")
.state("NORMAL")
.preferred2FaMethod("some2FAMethod")
.build()
);
return postUser(newUserMono)
.then(updatePassword(ssn))
.then(setState(ssn, "NORMAL"));
}
private Mono<String> generateNewSsnNotInDB() {
return Mono.just(ssnGenerator.generateOneValidSsnOnDate(ssnGenerator.generateRandomSsnDate()))
.flatMap(ssn -> getUserBySsn(ssn))
.switchIfEmpty(Mono.defer(() -> generateNewSsnNotInDB()));
}
public Mono<User> getUserBySsn(String ssn) {
return webClient.get()
.uri(userBySsnURI(ssn))
.retrieve()
.bodyToMono(User.class);
}
public Mono<User> postUser(Mono<UserResource> userMono) {
return webClient.post()
.uri(setUserURI())
.body(userMono, UserResource.class)
.retrieve()
.bodyToMono(User.class);
}
public Mono<User> postUser(User user) {
user.setPid(generateNewSsnNotInDB());
UserResource res = UserResource.builder()
.ssn(user.getPid())
.email(user.getEmail())
.phoneNumber(user.getPhoneNumber())
.state(user.getState())
.preferred2FaMethod(user.getPreferred2FaMethod())
.password(user.getPassword())
.build();
log.info("Resource generated in post-user is: " + res.toString());
return postUser(Mono.just(res));
}
public Mono<User> updatePassword(String ssn) {
Mono<User> user = Mono.just(User.builder()
.pid(ssn)
.password("password01")
.build());
return webClient.patch()
.uri(setUpdatePasswordURI())
.body(user, User.class)
.retrieve()
.bodyToMono(User.class);
}
private Mono<User> setState(String ssn, String state) {
return webClient.put()
.uri(updateStateURI(ssn, state))
.retrieve()
.bodyToMono(User.class);
}

How to return Mono<ServerResponse>

Please see my question embedded in the comments section of the code below -
// This should return a list of all ids and their name and status info, e.g. as json
public Mono<ServerResponse> f1(String originalId) {
// this gives list of ids which are comma separated
Mono<String> ids = f2(originalId);
ids.flatMapIterable(line -> Arrays.asList(line.split(COMMA)))
.doOnNext(id -> {
Mono<String> idName = f3(id);
Mono<String> idStatus = f4(id);
Mono<Tuple2<String, String>> combined = Mono.zip(idName, idStatus);
// How do i return all the combined Mono tuples as Mono<ServerResponse>
}).subscribe();
// Need to return proper Mono - not empty
return Mono.empty();
}
Also I am not sure whether I should return a Flux or a Mono as return type of f1() as its a list of ids and their respective values
You need to return Mono<ServerResponse>.
public Mono<ServerResponse> f1(String key) {
Mono<String> ids = f2(key);
Flux<IdInfo> idInfoFlux = ids.flatMapIterable(line -> Arrays.asList(line.split(",")))
.flatMap(id -> {
Mono<String> idName = getIdName(id);
Mono<String> idStatus = getIdStatus(id);
return Mono.zip(idName, idStatus, (name, status) -> new IdInfo(name, status));
})
.doOnNext(id -> System.out.println(id));
return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(idInfoFlux, IdInfo.class);
}
// your DTO class that you would like to pass in response as json
public static class IdInfo {
String idName;
String idStatus;
public IdInfo(String idName, String idStatus) {
this.idName = idName;
this.idStatus = idStatus;
}
public String toString() {
return String.format("IdInfo [idName=%s, idStatus=%s]", idName, idStatus);
}
}

WebClient is not successfully invoking "POST" operation

I am playing with Spring's WebClient. The primary implementation of the REST endpoints (in DemoPOJORouter and DemoPOJOHandler) seem to work. Also, the http.Get endpoint in DemoClientRouter and DemoClientHandler seems to work.
But, the http.Post for the DemoClient implementation "does nothing". It returns success (200), but nothing gets added to the dummy repo. I have a feeling that I need to do something in DemoClient to cause the http.Post endpoint in DemoPOJOHandler to actually execute (i.e., I believe neither the statements in DemoPOJOService.add() nor DemoPOJORepo.add() are being executed).
Based on prior pratfalls in WebFlux/reactive/functional efforts, I have a feeling that I'm not successfully subscribing, and so the statements never are invoked. But, I'm having difficulty identifying the "why".
Test code follows...
DemoClient router...
#Configuration
public class DemoClientRouter {
#Bean
public RouterFunction<ServerResponse> clientRoutes(DemoClientHandler requestHandler) {
return nest(path("/v2"),
nest(accept(APPLICATION_JSON),
RouterFunctions.route(RequestPredicates.GET("/DemoClient/{id}"), requestHandler::getById)
.andRoute(RequestPredicates.POST("/DemoClient"), requestHandler::add)));
}
}
DemoClient handler...
#Component
public class DemoClientHandler {
public static final String PATH_VAR_ID = "id";
#Autowired
DemoClient demoClient;
public Mono<ServerResponse> getById(ServerRequest request) {
Mono<DemoPOJO> monoDemoPOJO;
int id;
// short-circuit if bad request or invalid value for id
id = getIdFromServerRequest(request);
if (id < 1) {
return ServerResponse.badRequest().build();
}
// non-blocking mechanism for either returning the Mono<DemoPOJO>
// or an empty response if Mono<Void> was returned by repo.getById()
return demoClient.getById(id).flatMap(demoPOJO -> ServerResponse.ok()
.contentType(MediaType.APPLICATION_JSON)
.body(Mono.just(demoPOJO), DemoPOJO.class))
.switchIfEmpty(ServerResponse.notFound().build());
}
public Mono<ServerResponse> add(ServerRequest request) {
return request.bodyToMono(DemoPOJO.class).doOnSuccess( demoPOJO -> demoClient.add(demoPOJO))
.then(ServerResponse.ok().build())
.onErrorResume(e -> simpleErrorReporter(e))
.switchIfEmpty(ServerResponse.badRequest().build());
}
private int getIdFromServerRequest(ServerRequest request) {
Map<String, String> pathVariables = request.pathVariables();
int id = -1;
// short-circuit if bad request
// should never happen, but if this method is ever called directly (vice via DemoPOJORouter)
if ((pathVariables == null)
|| (!pathVariables.containsKey(PATH_VAR_ID))) {
return id;
}
try {
id = Integer.parseInt(pathVariables.get(PATH_VAR_ID));
} catch (NumberFormatException e) {
// swallow the error, return value <0 to signal error
id = -1;
}
return id;
}
private Mono<ServerResponse> simpleErrorReporter(Throwable e) {
return ServerResponse.badRequest()
.contentType(MediaType.TEXT_PLAIN)
.syncBody(e.getMessage());
}
}
DemoClient impl...
#Component
public class DemoClient {
private final WebClient client;
public DemoClient() {
client = WebClient.create();
}
public Mono<DemoPOJO> getById(int id) {
return client.get().uri("http://localhost:8080/v2/DemoPOJO/" + id)
.accept(MediaType.APPLICATION_JSON)
.exchange()
.flatMap(response -> response.bodyToMono(DemoPOJO.class));
}
public Mono<Boolean> add(DemoPOJO demoPOJO) {
return client.post().uri("http://localhost:8080/v2/DemoPOJO")
.syncBody(demoPOJO)
.exchange()
.flatMap(response -> response.bodyToMono(Boolean.class));
}
}
And, the DemoPOJO stuff, starting with DemoPOJORouter...
#Configuration
public class DemoPOJORouter {
#Bean
public RouterFunction<ServerResponse> demoPOJORoute(DemoPOJOHandler requestHandler) {
return nest(path("/v2"),
nest(accept(APPLICATION_JSON),
RouterFunctions.route(RequestPredicates.GET("/DemoPOJO/{id}"), requestHandler::getById)
.andRoute(RequestPredicates.POST("/DemoPOJO"), requestHandler::add)));
}
}
DemoPOJOHandler...
#Component
public class DemoPOJOHandler {
public static final String PATH_VAR_ID = "id";
#Autowired
private DemoPOJOService service;
public Mono<ServerResponse> getById(ServerRequest request) {
Mono<DemoPOJO> monoDemoPOJO;
int id;
// short-circuit if bad request or invalid value for id
id = getIdFromServerRequest(request);
if (id < 1) {
return ServerResponse.badRequest().build();
}
// non-blocking mechanism for either returning the Mono<DemoPOJO>
// or an empty response if Mono<Void> was returned by repo.getById()
return service.getById(id).flatMap(demoPOJO -> ServerResponse.ok()
.contentType(MediaType.APPLICATION_JSON)
.body(Mono.just(demoPOJO), DemoPOJO.class))
.switchIfEmpty(ServerResponse.notFound().build());
}
public Mono<ServerResponse> add(ServerRequest request) {
return request.bodyToMono(DemoPOJO.class).doOnSuccess( demoPOJO -> service.add(demoPOJO))
.then(ServerResponse.ok().build())
.onErrorResume(e -> simpleErrorReporter(e))
.switchIfEmpty(ServerResponse.badRequest().build());
}
private int getIdFromServerRequest(ServerRequest request) {
Map<String, String> pathVariables = request.pathVariables();
int id = -1;
// short-circuit if bad request
// should never happen, but if this method is ever called directly (vice via DemoPOJORouter)
if ((pathVariables == null)
|| (!pathVariables.containsKey(PATH_VAR_ID))) {
return id;
}
try {
id = Integer.parseInt(pathVariables.get(PATH_VAR_ID));
} catch (NumberFormatException e) {
// swallow the exception, return illegal value to signal error
id = -1;
}
return id;
}
private Mono<ServerResponse> simpleErrorReporter(Throwable e) {
return ServerResponse.badRequest()
.contentType(MediaType.TEXT_PLAIN)
.syncBody(e.getMessage());
}
}
DemoPOJOService...
#Component
public class DemoPOJOService {
#Autowired
private DemoPOJORepo demoPOJORepo;
public Mono<DemoPOJO> getById(int id) {
DemoPOJO demoPOJO = demoPOJORepo.getById(id);
return (demoPOJO == null) ? Mono.empty()
: Mono.just(demoPOJO);
}
public Mono<Boolean> add(DemoPOJO demoPOJO) {
return Mono.just(demoPOJORepo.add(demoPOJO));
}
}
DemoPOJORepo...
#Component
public class DemoPOJORepo {
private static final int NUM_OBJS = 5;
private static DemoPOJORepo demoRepo = null;
private Map<Integer, DemoPOJO> demoPOJOMap;
private DemoPOJORepo() {
initMap();
}
public static DemoPOJORepo getInstance() {
if (demoRepo == null) {
demoRepo = new DemoPOJORepo();
}
return demoRepo;
}
public DemoPOJO getById(int id) {
return demoPOJOMap.get(id);
}
public boolean add(DemoPOJO demoPOJO) throws InvalidParameterException {
// short-circuit on null pointer or duplicate id
if (demoPOJO == null) {
throw new InvalidParameterException("Add failed, null object detected...");
} else if (demoPOJOMap.containsKey(demoPOJO.getId())) {
throw new InvalidParameterException("Add failed, duplicate id detected...");
}
demoPOJOMap.put(demoPOJO.getId(), demoPOJO);
// if the return statement is reached, then the new demoPOJO was added
return true;
}
}
Finally, DemoPOJO...
public class DemoPOJO {
public static final String DEF_NAME = "DEFAULT NAME";
public static final int DEF_VALUE = 99;
private int id;
private String name;
private int value;
public DemoPOJO(int id) {
this(id, DEF_NAME, DEF_VALUE);
}
public DemoPOJO(#JsonProperty("id") int id, #JsonProperty("name") String name, #JsonProperty("value") int value) {
this.id = id;
this.name = name;
this.value = value;
}
/*
* setters and getters go here
*/
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append(id);
builder.append(" :: ");
builder.append(name);
builder.append(" :: ");
builder.append(value);
return builder.toString();
}
}
Here is probably your problem.
DemoPOJOHandler.class
request.bodyToMono(DemoPOJO.class).doOnSuccess(demoPOJO -> service.add(demoPOJO))
DemoPOJOService.class
public Mono<Boolean> add(DemoPOJO demoPOJO) {
return Mono.just(demoPOJORepo.add(demoPOJO));
}
doOnSuccess returns Void, but you are calling a method that wraps the "action" in a returning Mono. So the demoPOJORepo#add function will never be triggered because you have broken the event chain here. The easiest fix is to just remove the wrapping Mono and return void.
public void add(DemoPOJO demoPOJO) {
demoPOJORepo.add(demoPOJO);
}
This took me way to long to find so here are some pointers when asking a question.
The names of your classes are too like each other, it was hard to follow the codeflow.
DemoPOJOService service your names are so alike so when i saw service was it the DemoPOJOService or the DemoClientService? clear names please.
There is nothing called http.POST when you wrote that i had no idea what you where talking about.
you had problems with the POST part but you posted everything, even the working GET parts, please only post code you suspect is relevant and are part of the problem.
Explain the question more clearly, what you have done, how you do it, what your application structure is and so fourth
Your endpoint urls say nothing "/DemoClient"?
How this question could have been asked to be more clear:
I have two endpoints in two routers in the same spring reactive
application.
When I do a POST request to the "/add" endpoint, this endpoint in turn
makes an a POST call using a WebClient to the same application just on
another endpoint called "/addToMap".
When this first call returns, it returns me a 200 OK status but when i
check the map (that the second endpoint is supposed to add the posted
data to) nothing gets added.
So please, next time asking a question, be clear, very clear, a lot clearer than you think. make sure your code is clear too with good variable and class names and clear url names. If you have messy names on your own computer its fine but when posting here be polite and clean up the code .It takes 5 minutes to add good names to classes and parameters so that we understand your code quicker.
take the time to read the "how to ask a good question" please.
How to ask a good question

How to correctly handle exceptions from the service (spring boot rest)

When building a rest api using spring boot what is the best way to handle exceptions from the service level and pass them to the controller, so the client gets a custom json error message.
{
"message": "some error"
}
Endpoint from controller
#PostMapping("/login")
public String login(#RequestBody #Valid LoginDto loginDto) {
return gson.toJson(userService.login(loginDto.getUsername(), loginDto.getPassword()));
}
Service level code
public LoginResponseDto login(String username, String password) {
try {
//performs some checks
...
return new LoginResponseDto(token.get());
} catch (AuthenticationException e){
LOGGER.info("Log in failed for user {}", username);
}
return new LoginResponseDto("login failed");
}
LoginResponseDto class
String token;
String message;
public LoginResponseDto(String message) {
this.message = message;
}
Currently it is obviously returning the correctly message but not the correct status code, it will show status 200 with the error message in json.
You have some options:
1) Returning a message:
If you want to return a message something like this,
{
"message": "some error"
}
What you can do is:
Option 1: Create a custom POJO class for error message and return the reference to the object of that POJO class.
Something like this:
ErrorMessage.java
package org.example;
public class ErrorMessage {
private String message;
public ErrorMessage(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
Request Handler Method in Controller:
#GetMapping("/login{?username, password}")
public ErrorMessage isUserAuthenticated(#RequestParam String username, #RequestParam String password) {
if (username.toLowerCase().contentEquals("root") && password.contentEquals("system")) {
return new ErrorMessage("authenticated");
}
return null;
}
Option 2: Create a Map and insert key-value pairs that you want to have in the message.
Like this:
#GetMapping("/login{?username, password}")
public Map<String, String> isUserAuthenticated(#RequestParam String username, #RequestParam String password) {
Map<String, String> message = new HashMap<>();
if (username.toLowerCase().contentEquals("root") && password.contentEquals("system")) {
message.put("message", "authenticated");
}
return message;
}
2) Returning an error status code (highly recommended by me):
You may use ResponseEntity for this purpose.
#GetMapping("/login{?username, password}")
public ResponseEntity<?> isUserAuthenticated(#RequestParam String username, #RequestParam String password) {
if (username.toLowerCase().contentEquals("root") && password.contentEquals("system")) {
return new ResponseEntity<>(HttpStatus.OK);
}
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}

Resources