Communication between Spring boot micro services fail When trying to call from .map - spring-boot

I want to write a Rest API using reactive and achieve the below result. I've 2 microservices for this.
Service 1: Receives a post Object and retrieves some data from its database. The process something then communicate to the second Micro Service. Then return the Service 2 response as a Mono to the client.
Service 2: Receives the Data passed from Service 1 and save it to database and returns the Object with the generated primary key.
Here is my code look like.
#PostMapping("/submitData")
public Mono<Object> submitScore(#RequestBody SomeObject someObject){
//Some Operations
return contestGiftInfoRepository.findAllDataById(id)
.filter(c -> {
if(condition) {
return true;
} else {
return false;
}
}).reduce((item1,item2) -> {
if(condition) {
return item1;
}else {
return item2;
}
})
.defaultIfEmpty(emptyObj)
.map(resultObj->{
//DoSome OPeration
WebClient client = WebClient.create("my service Url 2");
Mono<Obj> response = client.post().uri("/ExecutionPath")
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.body(Mono.just(resultObj), ResultObj.class)
.retrieve()
.bodyToMono(ResponseObj.class);
return response;
});
}
Now When I call the web service 1 everything works fine. When I call the second web service individually that works as well. However, when I call the second web service from the first service it returns a result reactor.core.Exceptions$ErrorCallbackNotImplemented: org.springframework.web.reactive.function.client.WebClientResponseException$InternalServerError: 500 Internal Server Error from POST http://localhost:8085/path Caused by: org.springframework.web.reactive.function.client.WebClientResponseException$InternalServerError: 500 Internal Server Error from POST http://localhost:8085/path at org.springframework.web.reactive.function.client.WebClientResponseException.create(WebClientResponseException.java:218) ~[spring-webflux-5.3.16.jar:5.3.16] Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: Error has been observed at the following site(s):
I don't understand the actual issue from the error message. What I'm missing here?

Related

Why is the log statement in Spring WebClient subscribe() block not invoked?

I am playing around with the spring webclient to send emails via an api. The mails get send, however I am trying to do this without blocking and I want to log the successful response (or error). As I understood it so far, I could do this in the subscribe block. However, I do not manage to get the logging (or anything else) within the subscribe block to work.
MailClient.kt
fun sendMail(mail: Mail): Mono<String> {
return getWebClient()
.post()
.uri("uri")
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(..)
.retrieve()
.bodyToMono(String::class.java)
//.timeout(Duration.ofSeconds(10))
}
Service function which uses MailClient:
logger.info("Sending mail due to failure with id = ${failure.id}, error: $errorMessage")
mailClient.sendMail(
Mail(..)
)
.subscribe(
{ response -> logger.info("success: $response") },
{ error -> logger.error("error: $error") })

Service failing to correctly return status code to UI

Maybe this is silly question but I'm trying to learn Spring MVC and I have everything working except for the exceptions. So I have a simple form application where the user can register, if the user already exists I'd like to send an error code to the UI so that it knows why it failed. Heres my code:
#ResponseBody
#PostMapping("users")
public ResponseEntity addUser(#RequestBody User user) {
List<User> users = usersService.addUser(user);
if(users == null) return new ResponseEntity(HttpStatus.EXPECTATION_FAILED);
else return new ResponseEntity<>(users, HttpStatus.ACCEPTED);
}
It works fine, as in it returns a status code to the UI but the exception returns it in this string format:
Error: Request failed with status code 417
at createError (createError.js:17)
at settle (settle.js:19)
at XMLHttpRequest.handleLoad (xhr.js:69)
The log above is from a console log from the UI, right after the catch below:
function register(user) {
return dispatch => {
axios.post(`${BASE_URL}/users`, user).then((response) => {
console.log(response);
dispatch(resetError());
dispatch(success(user));
}).catch((e) => {
console.log('e', e);
dispatch(error(e.status));
})
};
function success(user) { return { type: userConstants.REGISTER, payload: user } };
};
Funny enough it actually prints exactly what I'm looking for if the http call succeeds. Here's what it prints on the happy path of the promise (ACCEPTED):
Notice that it has a status property. I'd very much not like to parse a string on the UI side just to get the error code from the service. Why is the response object different? The only thing I've changed is the status code. How can I make the error status give the UI a nice object instead of a string?
If you'd like to pull the branch here is the URL: https://github.com/MatTaNg/react-form
The code snippets are in the UsersResource file
Instead of console.log('e', e) try console.log('e', e.response.status).
Source:
https://github.com/axios/axios#handling-errors

How to return instance of Error using Spring REST call

In my front end application, I have to handle the error response of the HTTP REST call.
Front end:
restservice.check().subscribe(
response => {
if (response != null) {
},
error => {
if (error instanceof Error) {
}}
});
Controller.java
public ResponseEntity updateEstablishment
{
return new ResponseEntity<>(obj, HttpStatus.OK);
}
How can I return an instance of Error here.
REST services should catch and handle internal exception. And should return meaningful error code and message back to client. Please find below link to best way to handle exception in REST
https://www.baeldung.com/rest-api-error-handling-best-practices

Sending appropriate error responses on web actions

I have some web-enabled actions that are exposed through API Connect in IBM Cloud Serverless Functions.
Some of my actions use request-promises to call external REST services and I need to be able to catch an error and respond with an appropriate status-code to the caller.
Since the actions are web-enabled, the documentation indicates that I can use an annotated JSON to set the headers, status-code and body of the response. But it seems that, seems the API expects to always get a Content-Type=application/json, the response processor is failing to understand my annotations in the case of an error.
I tried the following without success:
let rp = require('request-promise');
function main(params){
//setup options
return rp(options).then(
res => {
return res;
}
).catch(
err => {
return { error: { statusCode:err.statusCode } }
}
);
}
Another variation:
let rp = require('request-promise');
function main(params){
//setup options
return rp(options).then(
res => {
return res;
}
).catch(
err => {
return { statusCode:err.statusCode }
}
);
}
The problem is that the status-code I always get is 200... I also tried to change the runtime to node8.0 without success.
Thanks!
I found the answer myself :)
In order to get the status-code and headers, one must set the field Response Content Type to `Use "Content-Type" header from action", while setting up the mapping between the API call and the action....

Spring WebClient async callback not called when http server response 404

A problem I encountered is as titled, and the code is below:
Mono<Account> accountMono = client.get()
.uri("accounturl")
.accept(MediaType.APPLICATION_JSON)
.exchange()
.flatMap(response -> {
if (response.statusCode().equals(HttpStatus.OK)) {
return response.bodyToMono(Account.class);
} else {
return Mono.empty();
}
});
accountMono.subscribe(result -> callback(result));
```
Server response 404. I try to create an empty Account, but the callback() is not called. It looks like the empty Mono is not emitted.
Server response 404, I try to create a empty Account
You're not creating an empty Account. You're returning an empty Mono, i.e. a Mono that will never emit anything.
If you want to return a Mono which emits an empty Account, then you need
return Mono.just(new Account());

Resources