Vertx: passing additional variable between verticles - java

I have a service which mostly proxies another server adding some business logic to its responses. So it just receives a requests, sends similar request to another server(should be sent with specific user cookie which comes with request), applies some changes to response, and sends it back to user.
I am using vertx with rx-java, and currently I have two verticles.
One of them accepts rest requests and as a part of processing this requests calls a method on another verticle via evenBus:
router.route().handler(routingContext -> {
someService.handleRequest()
.subscribe(res -> ...send response...);
}
And somewhere in handleRequest there is a call to another verticle:
eventBus.rxSend(address, message, deliveryOptions);
Another verticle listens to this address and send request to another server:
eventBus.consumer(address)
.toObservable()
.subscribe(message -> {
response = anotherService.handleMessage(message);
message.reply(response.body());
});
And somewhere in handleMessage it calls vertx httpclient making a request to another server:
response = client.get(...);
This request should contain cookie value from initial request received in first verticle with routing context.
What is the right way to pass the cookie value from routingContext to vertx httpclient in another verticle? (I don't want to change interfaces by adding new method parameter everywhere, it should be handled implicitly)
As far as I understand the best way to pass some additional value between verticles is using headers in DeliveryOptions.
But what is the right and safe way to store it between service calls(e.g. pass it to handleRequest/handleMessage without modyfing method signature)?(possibly storing it in verticle context?)

Related

How to call multiple services (in sequence) for each request using ZUUL API Gateway?

I want to call a service to Validate(Validation service) before routing the actual request to desired service.
Lets consider two different scenarios:
If the Validation service returns Valid, then call respective service (In this case service A).
If Validation service returns Invalid, then return response bad request to user (No need to call service A)
Please help me finding correct configuration (or coding in which filter) to be done, to call validation service for every request.

Asynchronous Lambda Proxy integration

I'm trying to invoke a AWS Lambda function asynchronous from the AWS API Gateway.
I have a long running (2-3min) Lambda function and I want to invoke this Lambda function asynchronous from a HTTP Post request. I configured the API Gateway as a Lambda Proxy Integration (because I want to pass the body unmodified to the function) This is working fine, but after 30s I get a 504 due the API Gateway execution time restriction.
But I can't manage to call the function async. According to the AWS docs it should be possible if I set the haeder "X-Amz-Invocation-Type", but this doesn't make any difference.
Does anybody know if it is possible to invoke a function async and using the proxy integration?
AWS says it's possible if you set the X-Amz-Invocation-Type header to Event, but I ran into the same necessity a few months ago and this did not work for me, so I am not sure this is still the case or if it was just me who misconfigured it. Maybe you are missing the same thing as me back then: I did not add an InvocationType header on the Integration Request as the docs suggests, so this very likely is the case for you, but still, I can't guarantee it works)
The documentation says:
Configure Lambda asynchronous invocation in the API Gateway console
In Integration Request, add an X-Amz-Invocation-Type header.
In Method Request, add an InvocationType header and map it to the
X-Amz-Invocation-Type header in the Integration Request with either a
static value of 'Event' or the header mapping expression of
method.request.header.InvocationType. For the latter, the client must
include the InvocationType:Event header when making a request to the
API method.
If this works, then you are good to go.
What I did back then, however, was to create an intermediate Lambda which literally acted as proxy to the actual Lambda.
There are a wide range of options to execute your function asynchronously, but you will need two Lambda functions regardless.
One option is to invoke another function (which will actually execute the task you want) asynchronously via the function invoked by API Gateway.
const params = {
FunctionName: 'YOUR_FUNCTIONS_NAME',
InvocationType: 'Event',
Payload: JSON.parse(event.body) // this is the event coming from API Gateway
};
await lambda.invoke(params).promise(); // await here is only going to wait for the HTTP request to be successful. Once the 2nd Lambda is invoked, it will return immediately
Another option is to put a message in SQS and configure a trigger for your Lambda to be invoked when there's a new message in the SQS queue. Same thing applies for a SNS notification.
Other options include Kinesis, DynamoDB Streams, etc. but the idea is the same: the function invoked via API Gateway must be nothing but a proxy to the other Lambda. How this proxy is going to work (be it sending a message to SQS, SNS, invoking the other function asynchronously directly, etc.) does not matter, what matters is the concept to get around API Gateway's 30 seconds request limit.

Need to create javax.ws.rs.client.Client for each webservcie call

Create a javax.ws.rs-ap.jar client and send the request to the server:
javax.ws.rs.client.Client client = ClientBuilder.newBuilder().build();
I have writtten the above code to call multiple api(get user by id, get all users and deleteUser).
My question is here.
I am creating a new Client for each api cal.
Just wanted to know i can create a single instance of Client and make multiple calls ?
Yes, a Client can be reused as long as it's lifecycle is managed properly. This means when a client instance is created, it should be closed properly as well using the close() method, once it's purpose is served. Refer to the Client API documentation.
Note that multiple client instances would be needed if each client has a different client configuration.

How to identify if a request type is synchronous or asynchronous

Actually, my requirement is, client can call my rest based services in both synchronous (request-response) or in asynchronous (request-acknowledgment-response) mode. Now, based on the request type, I have to follow the mode.
Now, my question is, is there any way, from the request itself, by default, is there any indicator, which will tells the clients desire request-response model.
Service protocol is http.
if not possible, then what will be the best practice, to handle this type of scenario.
You can have the client specify its preference to receive an asynchronous response via a header:
Prefer: respond-async
You can find details here: https://www.rfc-editor.org/rfc/rfc7240#section-4.1.
I am not aware of any way to explicitly request the opposite, a synchronous response.
To differentiate between two request you can pass the attributes in the header along with the request.
If it is Sync Request
Set Header : RequestType : Sync
If it is Async Request
Set Header : RequestType : ASync
This is the easiest way you can use.

How to respond to client when the server is busy processing a long transaction

I use Servlet/EJB model. When the user requests for a statement report for his past transactions, it takes hours for the server to generate the report. So the response is not sent from the server till the request is processed.
For eg.
Client requests report -> Servlet receives request -> Calls EJB to process it , EJB generates the report after hours -> sends response to servlet -> responds to Client.
But is it possible to respond to the user as soon as the request is received in the servlet.
For eg.
Client requests report -> Servlet receives request -> Servlet responds
'Report will be available soon'
Servlet -> Calls EJB to process it , EJB generates the report
after hours -> sends response to servlet ->responds to Client when
client requests the report again.
That is , can I create a thread from Servlet and use that for calling the EJB, while the Servlet responds to the user stating that the request will be processed soon
Your scenario screams for the asynchronous communication. That is, you should rewrite your application to have three different methods:
first one receives a request, generates unique ID which is immediately returned to the client and invokes EJB to generate the report; its signature would be something like:
public String generateReportRequest(Object requestParameter) { .. }
second one receives a unique ID and checks with EJB whether the report generation is done; its signature would be:
public boolean isReportGenerated(String uniqueID) { .. }
third one actually returns the report, but it should be invoked only when the second one returned that the report is ready:
public Object returnReport(String uniqueID) { .. }
Since we are dealing with three methods, I would not recommend mixing servlets and EJBs, but instead turning EJBs into Web services, if that's suitable (just annotate your stateless bean with #WebService annotation and adjust the client).
In case that you need to have Servlets for some reason, don't create a new thread - read this answer to see why it is highly discouraged in Java EE application server. Instead, you can use message-driven beans - just put the request on the message queue and return the answer to the client; MDB will process it asynchronously.
Third option is to check asynchronous method invocation in Java EE.

Categories