Spring 5 Rest Service Invocation Issue - java

I'm having an issue with consuming a REST service in Spring 5. The scenario: user updates a field or two on a screen and clicks a button. That calls a Spring controller which in turn makes two REST calls in series to gather information that is then returned to the browser. Our current production version uses Spring 4 and works great. But after upgrading to 5, the service invocations fail unless I put the server into debug mode and debug through the part of the code that does the two calls. If I debug, it works as expected. If I don't debug, I get a NullPointerException because the code uses information retrieved by the REST call that isn't there because it closed the connection before the REST service could return the information. Maybe there's a new dependency I missed or something I've overlooked when I upgraded to Spring 5 from 4, or something, but I've never seen anything like this.
Edit: Here's the code responsible for the REST service call:
ResponseEntity<String> entity = restTemplate.exchange(url, HttpMethod.GET, null, new ParameterizedTypeReference<String>(){});
restTemplate is an autowired instance of org.springframework.web.client.RestTemplate. Whether the call completes or not, I always get a ResponseEntity. But when the call terminates early, the body data is null, which is incorrect. There will always be body data returned by call, and Spring 4 always captures it correctly. Spring 5 only captures it correctly when I debug through the code, but fails during normal execution - I see this when I examine captured data.

Discovered a solution - the problem likely resides in the JDK version I have. I switched the request factory to HttpComponentsClientHttpRequestFactory, and voila, no more problem.

Related

MultipartHttpServletRequest is empty after first request

Since some days ago, my app started to have a very strange behavior on a spring boot #PostMapping request.
The code is as follows:
#PostMapping("/uploadFiles")
public ResponseEntity<Map<String,Object>> uploadFiles(MultipartHttpServletRequest request) throws IOException{
System.out.println(request.getParameterMap().keySet());
}
Pretty straigthfoward, nothing special here.
The problem is that the 'request' parameter only have parameters on the fist rest request the application receives. If other request is called before this, the request parameters will always be null. If the same request is sent twice to this endpoint, the fist one have all parameters / attached files, but the second is always empty.
Debugging the request parameter to identify what is going on, I identified the 'problem' occurs on 'MultipartStream.skipPreamble() (line 607 on 'tomcat-embed-core-9.0.27.jar'). When the method 'discardBodyData()' is called it is throwing the following exception, which make it never read the data from the stream:
org.apache.tomcat.util.http.fileupload.MultipartStream$MalformedStreamException: Stream ended unexpectedly
I have no idea what might be causing this. The toncat version wasn't updated (but its pretty old, I know), a new black project with this endpoint receive the parameter as many times as I pass it, other 'non-file' endpoints also receives the parameters and another colleague in the same project had the same problem (not a problem on my machine, it seems)
Any idea what might be causing this issue?

How to write AWS Lambda in Java, to consume query string parameters?

There are many similar threads out there, so I'll try to be simple and specific.
My API Gateway has GET method, without "Use Lambda Proxy integration" check marked. (Yes, to make my life little bit more difficult)
My assumption is that I have API Gateway portion working correctly, with query string parameters.
It has been deployed through Deploy API button
I also have mapping template written, as exactly said by this instruction provided by AWS.
Now, in java, I have the following:
public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent event, Context context) {
The concern is that event object is empty. Have I not been using the correct request event object?
ADDITIONAL NOTE
Per request, here's my lambda function below:
LambdaLogger logger = context.getLogger();
logger.log("EVENT: " + gson.toJson(event));
And here's what CloudWatch prints:
EVENT: {}
Did you configured this under GET - > Method Request?
After doublechecking, did you press the deploy button ?

Spring boot - Threads / Feign-Client / Messaging / Streamlistener

We struggle to find a solution for the following scenario:
Situation
Receive a message via Spring Cloud Streamlistener
Invoke a REST-Service via Feign-Client
We have configured several Feign-RequestInterceptor to enrich
request header data.
We want to avoid passing every request header on the method call and like the central configuration approach of the request interceptors.
Problem:
How to access data from a specific message, which contains informations, that need to be added to every request call via the Feign-RequestInterceptor.
We don't have a Request-Context, as we come from a message.
Can we be sure , that the message consumption and the REST call is happening on the same thread? If yes, we could use the NamedThreadLocal to store the information.
Yes, unless you hand off to another thread in your StreamListener, the rest call will be made on the same thread (assuming you are using RestTemplate and not the reactive web client).

WebClient Spring 5 IllegalStateException

I am receiving a MonoError caused by an IllegalStateException with the cause 'The underlying HTTP client completed without emitting a response.'.
NetworkList is a class contains lists of a network topology and has a setList which is called from within the method convertJsonToPojo.
client is a WebClient (spring-webflux) in Spring 5 (5.0.4.RELEASE) using reactor-netty (0.7.5.RELEASE).
The following snippet shows how I am using WebClient to make asynchronous calls to type = BOARDS, CARDS, PORTS, ROUTERS, etc where the network name is passed in as projectName and the topology type is passed in as type.
NetworkList netList = new NetworkList();
client.get().uri("/{project}/{type}",projectName,type).retrieve().bodyToMono(String.class).subscribe(json -> this.convertJsonToPojo(Type.BOARD, json, netList));
The rest service I am hitting against is a singular service which returns json representing the components asked for.
This seems similar to Reactive WebClient Not Emitting A Response but a response within points to the following reactor-netty issue Issue 138. That issue indicates fixed as of 0.6.6.RELEASE.
So my question is am I using WebClient wrong unknowingly or should I submit this as an unfixed bug? I am fairly new to Spring 5 and the Reactive library so do not want to naively submit a bug.
Thank you for your time in advance!
PS - I have this working with RestTemplate and CompletableFuture so no need to offer that suggestion as an alternative. My tasking is to begin the migration to a reactive architecture. Thank you!
UPDATE - I believe I understand now what is going on but would like a confirmation from someone. The rest service I am hitting against is a traditional one and not a Reactive Stream. Thus, there are no 'stage' updates being shared during the call. .subscribe() is expecting a reactive stream and thus never received the complete stage. replacing .subscribe() with .block() forced a completion and the code works now. So my learning from this is that when dealing with traditional rest services a block is required. Can someone confirm that please? Thank you!

Spring REST #Validated getting a "JBWEB000065: The request sent by the client was syntactically incorrect."

I have something like the following in a Spring project:
#RequestMapping(value = "/someRestUrl", method = RequestMethod.POST)
public SomeSo doSomeWork(#Validated #RequestBody SomeSo someSo) {
...
}
I recently changed SomeSo to have an additional parameter that was required:
#NotNull
private String someParameterThatNeedsToBeProvided;
Then I promptly left for the evening and when I got back to work the next day, my requests that were working before I made this change were no longer working. It took me forever to figure out why because I can't remember what I did less than 24 hours ago and, more importantly, because the error message sent to the client was only the following with no further details:
How can I get more information on what the issue is by either logging or sending this information back to the client? Is there some configuration I can do to get either more detailed logging for errors like this (I'd like to NOT include all of Spring's logging at DEBUG level, though) or provide this information to the client?
Note: I'd like to clarify that the request was parseable but was just missing the new parameter. It wasn't poorly formatted JSON.
You would want to check out the Errors class or the BindingResult class. Those give you details on what problems occurred due to #Validated. You can include them in the method parameters to interact with them. They are also available to templates. You would want to make a custom error page to output the details of the errors if that is something you want to expose.
I have faced this same error, and it was due to the incoming JSON not matching the object it is being mapped to.
Most probable cause is an empty collection, a single item mapped to a collection or some incorrect data type conversion.
You should enable DEBUG for Spring to detect the failure. Usually this errors are caused by inner exceptions from Jackson Mapper... So take a look at the log to find it, and you'll get an idea of what is the cause for your particular error.

Categories

Resources