Flux not returning any response SPRING BOOT / MONGO - spring

I am doing the typical chat application with mongodb and spring boot, I declared a tailable cursor and all that stuff, I followed this tutorial https://jskim1991.medium.com/spring-boot-making-a-chat-application-with-webflux-and-mongodb-part-1-5ad09c88f2ce
but the problem is that my controller is not showing any response
Status is 200 but nothing there even if I add another message, I can't get it meanwhile I can see it on the console
this is my code
#GetMapping(value = "/chat/id/{chatId}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<Chat> getMessages(#PathVariable Integer chatId) {
return chatRepository.findByChatId(chatId).doOnNext(System.out::println)
.subscribeOn(Schedulers.boundedElastic());
}
Does anyone have a clue on what is going on ?

Related

Spring webClient getResponseBodyAsString() is empty(over spring 5.3.13)

I'm using spring webClient for call some Rest API.
try {
webClient.post().uri("apiUrl")
.bodyValue(someParams)
.retrive()
.awaitBody<SomeResponseClass>()
} catch (ex: WebCleintResponseException) {
ex.reponseBodyAsString
}
This is work right on under spring 5.3.12.
I can take response body in ex.
but over spring 5.3.13. is not work.
resposeBody is empty.
webClient.post().uri("apiUrl")
.bodyValue(someParams)
.awaitExchange { response: ClientResponse ->
if (response.satusCode().is2xxSuccessful)
response.awatieBody<SomeResponseClass>
else if (response.statusCodes().isError)
response.awatieBody<SomeResponseClass>
else throw response.createExceptionAndAwaite
}
This working one over spring 5.3.13.
So...What is different from this? I don't find anything on release note.
https://github.com/spring-projects/spring-framework/releases/tag/v5.3.13
I want to know what is changed.
Thanks guys.
Updated
I found this commit on github.
https://github.com/spring-projects/spring-framework/commit/9197f15a306a497b3aa10c6ed48c581b3e938f58

How to process Observable<Response>

I have one local spring boot application which is hitting another PCF deployed application. The PCF application is giving me list of Student.
I am hitting the same using:
Observable<Response> result = RxObservable.newClient()
.target(url)
.request()
.rx()
.get();
Now I am not able to get my List<Student> back from result Observable.
Tried lots of approaches but nothing really working i.e. subscribing to result etc etc.
So after struggling for few hours below is the solution for now.
Observable observable = result.map(response -> response.readEntity(List.class));
DeferredResult<ResponseEntity<Response>> deferredResult = new DeferredResult(Duration.ofMillis(10000L).toMillis());
observable.subscribe((response) -> {
ResponseEntity<Response> responseData = new ResonseEntity(response, HttpStatus.OK);
deferredResult.setResult(responseData);
}, deferredResult::setErrorResult);
Please suggest, if it can be improved.
Thanks

How to set content-type for a spring boot test case which returns PDF file

I am currently testing one of my services with Spring boot test.The service exports all user data and produces a CSV or PDF after successful completion. A file is downloade in browser.
Below is the code i have wrote in my test class
MvcResult result = MockMvc.perform(post("/api/user-accounts/export").param("query","id=='123'")
.contentType(MediaType.APPLICATION_JSON_VALUE)
.accept(MediaType.APPLICATION_PDF_VALUE)
.content(TestUtil.convertObjectToJsonBytes(userObjectDTO)))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_PDF_VALUE))
.andReturn();
String content = result.getResponse().getContentAsString(); // verify the response string.
Below is my resource class code (call comes to this place)-
#PostMapping("/user-accounts/export")
#Timed
public ResponseEntity<byte[]> exportAllUsers(#RequestParam Optional<String> query, #ApiParam Pageable pageable,
#RequestBody UserObjectDTO userObjectDTO) {
HttpHeaders headers = new HttpHeaders();
.
.
.
return new ResponseEntity<>(outputContents, headers, HttpStatus.OK);
}
While I debug my service, and place debug just before the exit, I get content Type as 'application/pdf' and status as 200.I have tried to replicate the same content type in my test case. Somehow it always throws below error during execution -
java.lang.AssertionError: Status
Expected :200
Actual :406
I would like to know, how should i inspect my response (ResponseEntity). Also what should be the desired content-type for response.
You have problem some where else. It appears that an exception/error occurred as noted by application/problem+json content type. This is probably set in the exception handler. As your client is only expecting application/pdf 406 is returned.
You can add a test case to read the error details to know what exactly the error is.
Something like
MvcResult result = MockMvc.perform(post("/api/user-accounts/export").param("query","id=='123'")
.contentType(MediaType.APPLICATION_JSON_VALUE)
.accept(MediaType.APPLICATION_PROBLEM_JSON_VALUE)
.content(TestUtil.convertObjectToJsonBytes(userObjectDTO)))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON_VALUE))
.andReturn();
String content = result.getResponse().getContentAsString(); // This should show you what the error is and you can adjust your code accordingly.
Going forward if you are expecting the error you can change the accept type to include both pdf and problem json type.
Note - This behaviors is dependent on the spring web mvc version you have.
The latest spring mvc version takes into account the content type header set in the response entity and ignores what is provided in the accept header and parses the response to format possible. So the same test you have will not return 406 code instead would return the content with application json problem content type.
I found the answer with help of #veeram and came to understand that my configuration for MappingJackson2HttpMessageConverter were lacking as per my requirement. I override its default supported Mediatype and it resolved the issue.
Default Supported -
implication/json
application*/json
Code change done to fix this case -
#Autowired
private MappingJackson2HttpMessageConverter jacksonMessageConverter;
List<MediaType> mediaTypes = new ArrayList<>();
mediaTypes.add(MediaType.ALL);
jacksonMessageConverter.setSupportedMediaTypes(mediaTypes);
406 means your client is asking for a contentType (probably pdf) that the server doesn't think it can provide.
I'm guessing the reason your code is working when you debug is that your rest client is not adding the ACCEPT header that asks for a pdf like the test code is.
To fix the issue, add to your #PostMapping annotation produces = MediaType.APPLICATION_PDF_VALUE see https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/PostMapping.html#produces--

SseEmitter MessageBodyWriter not found for media type=text/event-stream

I am trying to get server-sent events working with a JavaScript web client and a Spring Boot 1.5.7 application. I get the following error in the server log when the SseEmitter is returned from the REST endpoint when the client initially connects:
o.g.j.m.i.WriterInterceptorExecutor :
MessageBodyWriter not found for media type=text/event-stream,
type=class org.springframework.web.servlet.mvc.method.annotation.SseEmitter,
genericType=class org.springframework.web.servlet.mvc.method.annotation.SseEmitter
The REST method gets called fine and I create and save the emitter for later. When the emitter is returned from the REST method, the above exception gets thrown.
I only get this when using EventSource in the web clients (Chrome and Firefox), not when using curl. I can even enter the URL in the browser and get a response without getting an error on the server.
I'm following pretty much every example I could find.
JavaScript:
const es = new EventSource('https://localhost:8443/sse');
es.onmessage = e => {console.log(e.data);};
es.onerror = e => {console.log('onerror:' + e);};
es.onopen = e => {console.log('onopen');};
Server:
#GET
#Path("/sse")
#Produces({"text/event-stream"})
public SseEmitter sse() {
SseEmitter emitter = new SseEmitter();
... save for later ...
return emitter;
}
Any ideas?
Thank You.

Calling Micro-service using WebClient Sprint 5 reactor web

I am calling a micro-service in my rest controller. It works fine when ever there is a successful response from the Micro-service but if there is some error response I fails to pass on the error response back to user. Below is the sample code.
#GetMapping("/{id}/users/all")
public Mono<Employee> findAllProfiles(#PathVariable("id") UUID organisationId,
#RequestHeader(name = "Authorization", required = false) String oauthJwt) {
return webClient.get().uri(prepareUrl("{id}/users/all"), organisationId)
.header("Authorization", oauthJwt).accept(MediaType.APPLICATION_JSON)
.exchange().then(response -> response.bodyToMono(Employee.class));
}
Now if there is any JSON response with error code then web client does not pass on the error response to the controller due to which no information is propagated to the api end user.
You should be able to chain methods from the Mono API. Look for "onError" to see a number of options which allow you to define the behavior when there is an error.
For example, if you wanted to return an "empty" Employee, you could do the following:
.exchange()
.then(response -> response.bodyToMono(Employee.class))
.onErrorReturn(new Employee());

Resources