Spring RestController endpoint that consumes and produces a String value returning "HTTP Status 415 – Unsupported Media Type" - spring

I'm trying to setup a fairly simple endpoint that takes in String and produces a String. I've simplified it down to:
#RequestMapping(value="/foo",
method = RequestMethod.GET,
consumes = MediaType.TEXT_PLAIN_VALUE,
produces= MediaType.TEXT_PLAIN_VALUE)
public String foo(#RequestBody String data) {
return data;
}
I'm testing with Postman and am just getting "HTTP Status 415 – Unsupported Media Type" back. This app is running on Spring 4.1.3. I copied this endpoint into another project I have in Spring Boot, using my same Postman request (just modified the host), and it works there. So there appears to be some issue with the version of Spring this project uses. As a work-around I created a simple wrapper entity (POJO that only consists of a single String) and changed the endpoint to consume JSON/this POJO. Does anyone know specifically why it doesn't work as above and/or know of a workaround that'll let me send and receive a plain text String with this version of Spring?

Related

Classcastexception for CloudEventMessageConverter to AbstractMessageConverter

when using spring cloud stream latest version with cloud events spring sdk
Facing classcastexception in below scenario.
Message has contentType = application/*+avro.
SmartcompositeMessageConverter contains converter list like below -
CloudEventMessageConverter
AvroSchemaRegisteryClientMessageConverter
and some ootb converters.
While converting to message from producer..
SmartcompositeMessageConverter has this line of code for wildcard contentType
((AbstractMessageConverter) converter).getSupportedMimeTypes()
But CloudEventMessageConverter is not an instance of AbstractMessageConverter, hence it throws an exception.
Please guide what should be overridden in this case.
If I create a new CloudEventMessageConverter which extends AbstractMessageConverter, I cann't add headers as only method allowed to override is convertFromInternal which returns just the payload.

URI Spring Encoding Issue

I have a query param that contains "+" sign, I encoded it and pass it to a Spring Controller but the controller interprets it as space thus failing the API.
Sample
Name = test+fetch
URI passed from browser: abc.org/fetch?name=test%2Bfetch
How Controller receives it
name = test fetch
there is nothing with test fetch and thus the API fails
Is there a way we can solve this issue, decoding the param after spring resolves it doesn't solve the issue
Edit:
Updated Controller Code
#GetMapping("fetch")
public String fetch(#RequestParam("name") String name){
return something;
}
I created an application using https://start.spring.io/ and your controller, and the encoding works as it's supposed to.
https://www.dropbox.com/s/z9rbe2gtpvzebqv/url-encoding.zip?dl=1
I think there's something before your application, may be a proxy, web server or Spring Gateway, that's decoding the parameter. Otherwise, download the app I created and prove that the problem exists.

How to log 415 errors in Spring

My service is currently experiencing 415 errors, but I'm not getting any logs to find out what errors they are.
Will I be able to add logging in some kind of filter so that I can know what's going on?
#RequiresHttps
#RequestMapping(value = "/test", method = RequestMethod.POST)
public ResponseEntity<String> doAction(#NonNull #RequestBody CustomRequest[] requests) {
It looks like the 415 is happening inside spring mvc engine and it doesn't event reach your controller so that you can't really place the logs in our code (in doAction method for example).
Try to enable tomcat embedded access logs and you'll see the file with all the requests and return status. These are disabled by default so you should add the following into application.properties or yaml:
server.tomcat.accesslog.enabled=true
There are some configurations / customizations you can do with that, you can read about them in this tutorial for example

How to post multipart content type in single request body using spring and restful service

We have a requirement to post a multiformats request type to send to a resful api..I am a beginer and need help with a sample program hiw to post multiple requests with different format like json and pdf in single http request so that I can get a response back?can anyone please post a sample code how to implement multi part content type?
I've had already developed an upload microservice using multipart/form-data requests. The example bellow is a simple endpoint that accepts multiple files using multipart/form-data. You only need to use the spring MultipartFile class as the argument.
#PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity upload(
#RequestPart(value = "files") MultipartFile[] files) {
return ResponseEntity.ok().build();
}
For more details I highly recommend reading the spring official guide in uploading files: https://spring.io/guides/gs/uploading-files/

SpringBoot get InputStream and OutputStream from websocket

we want to integrate third party library(Eclipse XText LSP) into our SpringBoot webapp.
This library works "interactively" with the user (like chat). XText API requires input and output stream to work. We want to use WebSocket to let users interact with this library smoothly (send/retrieve json messages).
We have a problem with SpringBoot because SpringBoot support for WebSocket doesn't expose input/output streams. We wrote custom TextWebSocketHandler (subclass) but none of it's methods provide access to in/out streams.
We also tried with HandshakeInterceptor (to obtain in/out streams after handshake ) but with no success.
Can we use SpringBoot WebSocket API in this scenario or should we use some lower level (Servlet?) API ?
Regards Daniel
I am not sure if this will fit your architecture or not, but I have achieved this by using Spring Boot's STOMP support and wiring it into a custom org.eclipse.lsp4j.jsonrpc.RemoteEndpoint, rather than using a lower level API.
The approach was inspired by reading through the code provided in org.eclipse.lsp4j.launch.LSPLauncher.
JSON handler
Marhalling and unmarshalling the JSON needs to be done with the API provided with the xtext language server, rather than Jackson (which would be used by the Spring STOMP integration)
Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<String, JsonRpcMethod>();
supportedMethods.putAll(ServiceEndpoints.getSupportedMethods(LanguageClient.class));
supportedMethods.putAll(languageServer.supportedMethods());
jsonHandler = new MessageJsonHandler(supportedMethods);
jsonHandler.setMethodProvider(remoteEndpoint);
Response / notifications
Responses and notifications are sent by a message consumer which is passed to the remoteEndpoint when constructed. The message must be marshalled by the jsonHandler so as to prevent Jackson doing it.
remoteEndpoint = new RemoteEndpoint(new MessageConsumer() {
#Override
public void consume(Message message) {
simpMessagingTemplate.convertAndSendToUser('user', '/lang/message',
jsonHandler.serialize(message));
}
}, ServiceEndpoints.toEndpoint(languageServer));
Requests
Requests can be received by using a #MessageMapping method that takes the whole #Payload as a String to avoid Jackson unmarshalling it. You can then unmarshall yourself and pass the message to the remoteEndpoint.
#MessageMapping("/lang/message")
public void incoming(#Payload String message) {
remoteEndpoint.consume(jsonHandler.parseMessage(message));
}
There may be a better way to do this, and I'll watch this question with interest, but this is an approach that I have found to work.

Resources