Is filter the right place to handle service calls based on header values in Spring? - spring-boot

Looking to make a service call based on a header value.
I can see two options:
1) Do it from the controller which is mainly used for a different service.
2) Add a filter which will do this by reading the request context.
Want to know what's the best way to handle this in a Spring application.

I guess it depends on your requirements.
Controller:
If you have to make service calls for preparing the response of a specific controller. For example, you have a controller say:
/employee
fand or preparing the response of this endpoint you need to call say staff service.
In this case, it's better to handle such calls in controllers.
Filter:
If you want to intercept each request and perform some operation on the request before sending it to the controller or before sending the response to the client.
A use case here can be checking the roles of the user by intercepting all requests.
As we know by using the filter, we can perform two operations at two instances −
Before sending the request to the controller
Before sending a response to the client.
In this case, OncePerRequestFilter is quite useful from the spring web module.
Quoting the documentation :
Filter base class that aims to guarantee a single execution per request dispatch, on any servlet container.

Related

How to implement async in spring boot for getting response over asynchronous call?

How can i call 3 different GET rest apis asynchronously in Spring Boot? Currently its taking alot of time to execute this apis sequentially. Let me know how to do this asynchronously?
You can use async-http-client as given in the following url : https://www.baeldung.com/async-http-client
2.You can use AsyncRestTemplate. In AsyncRestTemplate object you need to send the following three parameters.
* endpoint uri,
* request entity with headers,
*and response object.
Catch all those in to a ListenableFuture object where implement the override methods of callback in the case of failure and success.
For both of these approach, you have to create request objects and call the services. And the call backmethod will capture the result in the response objects. You can merge responses together and then do your business.
You can use #EnableAsync annotation at the configuration level to enable async processing and #Async at the method level which needs to be invoked asynchronously.
For further details please refer to the below link
https://www.baeldung.com/spring-async

Split request - Send to either one or diff end points - combine the response

I am using spring boot 2 and apache camel 2.24 to build an api gateway which exposes REST end points to receive JSON/XML request and do the following
Validate incoming JSON/XML
Convert incoming request to downstream expected format.
Push the request to a camel route which invokes the downstream REST end point and returns back the response.
Convert response to expected format and return back to client.
Currently I have route configured as below
from("direct::camel").process(preprocessor).process(httpClientProcessor).process(postprocessor);
httpClientProcessor - This does the main job of invoking downstream end point and return the response.
preprocessor - splits the request for configured requests, puts them in a list before passing to httpClientProcessor.
postprocessor - does the following based on content type
XML - Remove "xml" tag from individual responses and combine to form one single response under one root element
JSON - Combine json response under one parent array element.
There can be cases where the multiple requests need to be sent to the same end point or each to be sent to a unique end point. Currently I have that logic in httpClientProcessor. One issue with this approach is that I can invoke the downstream end points only one after another rather than in parallel (unless I add thread pool executor in httpClientProcessor)
I am new to apache camel and hence started with this basis route configuration. Based on going through the documentation, I came across camel components like split(), parallelProcessing(), multicast and aggregator components of camel but I am not sure how to plug these all together to achieve my requirement -
Split the incoming request using a pre configured delimiter to create multiple requests. The incoming request may or may not have multiple requests.
Based on endpoint url configuration, either post all split requests to same end point or each request to a unique endpoint.
Combine responses from all to form one master response (XML or JSON) as output from the route.
Please advise.
This sounds like you should have a look a the Camel Split EIP.
Especially
How to split a request into parts and re-aggregate the parts later
How to process each part in parallel
For the dynamic downstream endpoints, you can use a dynamic To (.toD(...)) or the Recipient List EIP. The latter can even send a message to multiple or no endpoint.

What is the difference between metadata.FromOutgoingContext and metadata.FromIncomingContext?

If you are in a middle-ware that both receives the context and maybe append some data to context to send it to the next interceptor, then which of the two methods i.e. metadata.FromOutgoingContext and metadata.FromIncomingContext shall be called?
If you are writing that middle-ware in the server, then you are receiving that metadata in the incoming request.
You should then use metadata.FromIncomingContext to get the metadata at that point.
The metadata in the "outgoing context" is the one generated by the client when sending an outgoing request to the server.
See here for examples of both:
https://github.com/grpc/grpc-go/blob/master/Documentation/grpc-metadata.md

Blocking message pending 10000 for BLOCKING..using spring websockets

I am facing the following error while using spring websockets:
Use case: On our server side code we have a fucntionality to search values in data base..if the values are not present in database..it will hit a servlet and get the data..The second part i.e., hitting servlet and getting the data is asynchronous call.
So for one request there are multiple things we have to search for in data base..
Example: In request we got a some parameter channel: 1
This channel is mapped to multiple ids say 1 is mapped to 1,2,3,4,5
In websocket once the request comes to server i will extract the channel and get all the id's mapped and run a loop over id's as follows:
for(int i=0;i<ids.length;i++)
{
SomeObject databaseRespObj=callToDatabase(i); //SomeObject contains two fields value exists and string values
if(!databaseRespObj.valuesExists)
{
AsynchronouscallToServelt(i);
//once response received it will send message immediately using session
}
}
While execution of above server side code,some times only i am facing the below error.
java.lang.IllegalStateException: Blocking message pending 10000 for BLOCKING
at org.eclipse.jetty.websocket.common.WebSocketRemoteEndpoint.lockMsg(WebSocketRemoteEndpoint.java:130) ~[websocket-common-9.3.8.v20160314.jar:9.3.8.v20160314]
at org.eclipse.jetty.websocket.common.WebSocketRemoteEndpoint.sendString(WebSocketRemoteEndpoint.java:379) ~[websocket-common-9.3.8.v20160314.jar:9.3.8.v20160314]
at org.springframework.web.socket.adapter.jetty.JettyWebSocketSession.sendTextMessage(JettyWebSocketSession.java:188) ~[spring-websocket-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.socket.adapter.AbstractWebSocketSession.sendMessage(AbstractWebSocketSession.java:105) ~[spring-websocket-4.2.4.RELEASE.jar:4.2.4.RELEASE]
Sorry if the above framing of the question is not clear.Will spring support sending asynchronous messages like normal javax websocket does Session.getAsyncRemote().sendText(String text)
What is the configuration made in spring to send asynchronous messages using websocket session
From what I understand, you have multiple threads sending messages on the same RemoteEndpoint when the asynchronous technique kicks in.
Seems very similar to this :
WebSocket async send can result in blocked send once queue filled
I don't thing you necessarily have to use Futures or mechanisms described in the above post.
What I don't really get is : why doing asynchronous call to servlets ? Ofcourse several could send messages on the same RemoteEndPoint..
But can't you simply make synchronous calls to the relevant classes and keep the same request-response flow that you use when records are found in your database ? :)
UPDATE
Since you added in comments the fact that you need to focus on speed, and since it seems that your current solution is not applicable, let's maybe have a look at the problem from a different angle.
I'm not a websocket expert but as far as I understand what you try to achieve with the asynch servlet calls is not possible.
However, if you change the design/config of your project, this should be achievable.
Personally I use Websockets to be able to send a message to an arbitrary user that did not necessarily made a request - as long as he is connected, he must get the message.
To do this, I simply use the SimpMessagingTemplate class offered by Spring in their websocket support. To send a message to ANY USER THAT I WANT, I do this :
#Autowired
SimpMessagingTemplate smt;
(.......)
smt.convertAndSendToUser(recipient.getUsername(), "/queue/notify", payload);
So in your case, you could, in your loop :
make class instance method calls (instead of a servlet, no network transit, you cannot be faster ! Just a call to your biz-logic / service / whatever)
every time a method returns data, use the SimpMessagingTemplate like in the snippet here above :)
you can still do it asynchronously if you want ! :)
By doing this, you reduce latency (calling servlets adds alot), and have a reliable technique.
You can easily and quickly send thousands of messages to one user or to several users, at your own discretion, without stumbling upon the "10000 for BLOCKING" problem, which probably comes from more than 1 servlet "answering the same question" ;)
To obtain a SimpMessagingTemplate from Spring, you will need to use the <websocket:message-broker> tag or the equivalent non-xml-java-config.
I suggest to check this doc which has more info :
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/websocket.html
and the following post I created on SO where I am using it (I've got another problem in the post, related to spring configuration and context hierarchies, but at least you have some template code to look at, the code is working) :
Spring Websocket : receiving nothing from SimpMessagingTemplate
Spring : how to expose SimpMessagingTemplate bean to root context ?

What is OncePerRequestFilter?

Documentation says org.springframework.web.filter.OncePerRequestFilter "guarantees to be just executed once per request". Under what circumstances a Filter may possibly be executed more than once per request?
Under what circumstances a Filter may possibly be executed more than once per request?
You could have the filter on the filter chain more than once.
The request could be dispatched to a different (or the same) servlet using the request dispatcher.
A common use-case is in Spring Security, where authentication and access control functionality is typically implemented as filters that sit in front of the main application servlets. When a request is dispatched using a request dispatcher, it has to go through the filter chain again (or possibly a different one) before it gets to the servlet that is going to deal with it. The problem is that some of the security filter actions should only be performed once for a request. Hence the need for this filter.
To understand the role of OncePerRequestFilter, we need to first clearly understand how a normal filter behaves.
When you want some specific code to execute just before or after servlet execution, you create a filter which works as:
code1 ===> servlet execution (using chain.doFilter()) ===> code2
So code1 executes before servlet and code2 after servlet execution.
But here, while servlet execution, there can be some other request to a different servlet and that different servlet is also having this same filter. In this case, this filter will execute again.
OncePerRequestFilter prevents this behavior. For our one request, this filter will execute exactly one time (no more no less). This behavior is very useful while working with security authentication.
A special kind of GenericFilterBean was introduced to live in Servlet 3.0 environment. This version added a possibility to treat the requests in separate threads. To avoid multiple filters execution for this case, Spring Web project defines a special kind of filter, OncePerRequestFilter. It extends directly GenericFilterBean and, as this class, is located in org.springframework.web.filter package. OncePerRequestFilter defines doFilter method. Inside it checks if given filter was already applied by looking for "${className}.FILTER" attribute corresponding to true in request's parameters. In additionally, it defines an abstract doFilterInternal((HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) method. Its implementations will contain the code to execute by given filter if the filter hasn't been applied.
Under what circumstances a Filter may possibly be executed more than once per request?
A filter may be invoked as part of a REQUEST or ASYNC dispatches that occur in separate threads. We should use OncePerRequestFilter since we are doing a database call to retrieve the principal or the authenticated user, there is no point in doing this more than once. After that, we set the principal to the security context.
Authentication auth = jwtTokenProvider.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(auth);
where jwtTokenProvider is your service for getting authentication from the jwt token.
OncePerRequestFilter implements logic to make sure that the filter’s doFilter() method is executed only one time per request.

Resources