I'm developing several services on Java that communicate with each other through HTTP. Logback is used as logging framework.
In case of error within one service it's not difficult to define error reason looking through the service logs. But if we have a downstream call that affects a number of services:
Service A -> Service B -> Service C -> Service D
and the last service failed with an error, I need some means to trace the call up to Service A to troubleshoot the issue.
Are there any ready solutions for the problem? Should I add some additional attribute to log message that is unique for each downstream call?
If you want to trace the flow of execution you need some sort of tag on each message. You will need:
a request identifier
a service identifier.
When a flow is started you tag the first call with the request identifier and the service identifier. On each service that handles the call and needs to make other calls, to other services, you keep the request identifier and add the current service identifier to the one of the request you received.
Basically the request identifier allows you to identify a flow of calls, while the service identifiers allow you to see the hops in the flow.
For your example, Service A -> Service B -> Service C -> Service D, you might have something like this:
Service A starts a call "123-A";
service B receives this and needs to make a call to service C, so it uses "123-A" and ads his identifier: "123-A,B";
service C receives this and needs to make a call to service D, so it uses "123-A,B" and ads his identifier: "123-A,B,C";
if something happens with the request in service D, you know on what service logs to look (A,B,C) and what to look for (123).
You can have these in the HTTP message or as HTTP headers, the idea is to somehow add them to the log message whenever you log something.
Of course the above is for a simple case as the one you gave an example of, so it can be extended for other cases. The idea is to treat the calls as a sort of stack. On each hop you "push" some identification into the message.
There is actually a solution for spring-based services: request correlation spring cloud starter.
The filter adds unique request identifier as a header (if there is no such header) to each request. One can put the id to MDC and add it to log entries with service id.
Related
I'm using Vert.x for my web service, where a part of it required authorization. I've set an AuthenticationHandler (using the OAuth2 implementation from vertx-auth-oath2) to listen on the protected paths (lets say "/*") and it is correct called, sends a redirect to the authentication provider, which redirects back and then correctly to the real handler. This works fine.
But the next time we call the protected endpoint - it does the whole thing again. I see that in the abstract AuthenticationHandlerImpl class it checks if the context already has a user() and if so - will not run the actual auth handler, which is the behavior I need - but it obviously doesn't happen because every call is a new request with a new RoutingContext.
What is the "correct" way to retain the User object across requests, so that the auth handler will be happy?
I'm guessing it has something to do with session storage but I've never used that - up until now I was using a custom "API key" style solution, and I'm trying to do this "The Right Way(tm)" in this new project.
I'm using the latest Vert.x 4.3.5.
You will need CookieHandler and SessionHandler to store and handle session with user. This will work out of the box with provided vertx-auth-oath2.
Here is a simple example to get you started:
https://github.com/vert-x3/vertx-examples/blob/master/web-examples/src/main/java/io/vertx/example/web/auth/Server.java
I try to use Websocket with spring boot backend (as an API) and Vuejs frontend.
I take a simple use case to expose my question. Some users are logged on my website, and there is a messaging feature. User A send a message to User B. User B is actually logged, and I want to notify User B that a new message is arrived.
I see 3 ways to do it with websockets :
1 - When User A send message, an Axios post is call to the API for saving message, and, if the Axios response is success, I call something like
this.stompClient.send("/app/foo", JSON.stringify(bar), {})
2 - When User A send message, I only call something like
this.stompClient.send("/app/foo", JSON.stringify(bar), {})
and it's my controller's method (annotated with #MessageMapping("/xxxx") #SendTo("/topic/yyyy")) that call facade, service, dao to first, save message, then return message to subscribers
3 - I keep my actuals controllers, facade, services and DAO, and juste add when save is successfull something like :
#Autowired SimpMessagingTemplate webSocket;
...
#GetMapping("/send-message")
public ResponseEntity sendMessage(#AuthenticationPrincipal User user, ....) {
service.saveMessage(....);
webSocket.convertAndSend("/ws/message-from", message);
without a new controller contains #MessageMapping("/xxxx") #SendTo("/topic/yyyy"). User B is just subscibed to "/ws/message-from"
Could you help me.
In the 3 way there is a good method ?
Thanks you.
The one and two method has no much difference as you use axios from npm for sending request and the other one you can directly,while the third one you use controller,and facade dao at single place.it is about architecture and how you wanna send your requests for your framework,as a requirement.
They serve best at their level,till you come with specific requirement.
The suggestion would be to use axios.
It has advantages:
supports older browsers (Fetch needs a polyfill)
has a way to abort a request
has a way to set a response timeout
has built-in CSRF protection
supports upload progress
performs automatic JSON data transformation
works in Node.js
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).
I need to implement RPC over STOMP, where the client runs with javascript in a browser, and the server side is implemented using Spring messaging capabilities.
While using #MessageMapping is fine for normal messaging, I find using #SendToUser quite limitating for implementing RPC because the client has an hard time to understand which reply is associated with which request in a scenario when multiple simultaneous requests are being made from the client.
Of course there is no problem when just only one request is made, and the client waits for its reply, but problems arise when the client has to keep track of multiple "open" rpc calls.
I've managed to make the system mostly fine by associating an ID with every request, i.e.: the client sends an id together with the message, and the server replies with a special message wrapper that contains this id, so the client is able to associate asynchronous replies with requests.
This works fine but has several limitations:
I have to develop code that needs to understand this structure, and that defies the uitlity to have simple annotated methods
when the server side code generates an Exception the Spring #MessageExceptionHandler get called and the correct Exception is returned to the client, but the request id is lost because the handler has no (easy) way to access it.
I know that with rabbitmq we can add "reply-to" header to every request that needs to be associated with a special reply (the rpc response), and this is implemented by creating a special temporary queue that the user is automatically subscribed to, but how may I use this scheme in Spring? Also, that would tie me a specific broker.
How may I elegantly implement a correct RPC call in Spring that correctly handles server side exceptions?
I find this a general problem and I think Spring could benefit greatly to implement it natively.
This not exactly what you demand, but maybe you can attempt something like this :
Path variables in Spring WebSockets #SendTo mapping
You define an ID on your client and send id to the queue /user/queue/{myid}
On the serveur side you will have a class who looks like this :
#MessageMapping("/user/queue/{myid}")
public void simple(#DestinationVariable String id, Object requestDto) {
simpMessagingTemplate.convertAndSendToUser(userId, "/user/queue/" + id, responseDto);
}
This solution can work with the same principle as the rabbit mq solution you mention.
Hope this helps.
If you do not need the exception/reason on the client, but only want to know which message failed you could send ack messages for successful messages. For successful messages you always have easy access to the message id / headers. By the absence of the ack message the client knows which message has failed.
Of course this comes at the costs of sending all the ack messages and knowing the timout of requests. Also additional code is required to keep track on the client side, but this can be done using a middleware and would end up in an ok-ish dev experience for the business logic.
I need to create the dynamic client to call web services, which can call web services with Service Mode as Service.Mode.PAYLOAD as well as Service.Mode.MESSAGE. I have created the Dispatcher as:
Dispatch<Source> sourceDispatch =service.createDispatch(portName, Source.class, Service.Mode.PAYLOAD);
But this can invoke the services with Service Mode PAYLOAD only. Please suggest me the way how can I previously determine the Service Mode from WSDL link (service Mode parser code) before creating Dispatch instance?
The mode does not depend on the WSDL.
If you want to pass to sourceDispatch.invoke(T msg) an entire SOAP message use mode.MESSAGE. If you only want to pass the PAYLOAD (the body) use mode.PAYLOAD, and invoke will wrap it in a message for you.
The mode also determines wether invoke returns you a message or the payload.