I'm calling GRPC endpoints from Ruby.
The proto endpoints are for example rpc SayHello (HelloRequest) returns (HelloReply), and implemented in Go, so they take context when calling from Go. The generated client supports client.SayHello(ctx context.Context, request *HelloRequest).
However when calling from Ruby it's just client.SayHello(request), where request's type is HelloRequest. How do I pass in the context? I want to do this because the Go endpoint implementations use the context in a variety of ways such as logging.
Related
I'm working on a Microservice that receives webhooks, the idea is to use path variables for some processing down stream,
/webhooks/{foo}/{bar}/{baz}
for example
/webhooks/sony/pony/tony would populate foo=sony; bar=pony; baz=tony.
Can't figure how to make it work in spring cloud function web.
This was never the purpose of spring-cloud-function to replace spring-mvc etc.
Also, Function has only one argument, so what you can do is have Function<Message, ...> and we translate HTTP request into Message where body will turn into payload and HTTP headers will turn into Message headers.
I am working on a few gRPC micro services and using context to pass in any headers and metadata. I am using opentracing for tracing purposes and one of my gRPC services calls other gRPC service at which point I am having issues with propagating the context as it is not retaining the metadata and also traceID.
My code is as below
func A(ctx context.Context) {
metadata:=extractMetadata(ctx)
conn := &grpc.ClientConn{}
zipkinCtx := opentracing.SpanFromContext(ctx).Context().(gozipkin.SpanContext)
client := pb.NewDClient(conn)
reply, err := client.LookupProperty(metadata.NewOutgoingContext(context.Background(), metadata.New(metadata)))
}
In the above code I am calling the service D for which I had to recreate a new context with the metadata which I am ok with but I am not sure how I can propagate the tracIds to the service D
Not knowing your frameworks, I think propagating this on GRPC metadata requires your server to explicitly parse the metadata on the receiving call. GRPC documentation shows an example of this:
func (s *server) LookupProperty(ctx context.Context, in *pb.SomeRequest) (*pb.SomeResponse, err) {
md, ok := metadata.FromIncomingContext(ctx)
// do something with metadata
}
Using this the server should now have access to the Traceid; contained in ‘md’.
I'm not absolutely sure, but it seems like traceID must be a custom field in GRPC Metadata. Also have a look at GRPC Interceptors that enable Opentracing support both for server and client side: https://github.com/grpc-ecosystem/go-grpc-middleware/tree/master/tracing/opentracing. Perhaps you won't have to write your own.
I have setup a Spring Integration flow configuration to send messages to an external web service and then unmarshalling the response and then doing some post processing based on the response object type.
I have the following outbound-gateway configuration:
<int:channel id="sendRequestChannel"/>
<ws:outbound-gateway request-channel="sendRequestChannel" uri="${send.ws.uri}" reply-channel="responseTransformer" >
<ws:request-handler-advice-chain>
<ref bean="retryAdviceUserUpdateWs" />
</ws:request-handler-advice-chain>
</ws:outbound-gateway>
Now, I want to test the flow and check that the correct post processing is triggered based on the response object.
Is there anyway in my integration test to mock the Endpoint response based on the message I'm sending?
Actually you should understand from which part of your flow it would be better to mock and return the desired response.
You can inject ChannelInterceptor to the sendRequestChannel with preSend which returns null, to prevent the further process and send a message with desired response to the responseTransformer.
Another powerful option is to add one more Advice to the <ws:request-handler-advice-chain> and implement it as extension of AbstractRequestHandlerAdvice.
And the last option which I see via Java code is a mock for WebServiceTemplate.sendAndReceive and inject it to the <ws:outbound-gateway>.
From other side I know that SoapUI has a tool to mock target service, so, you even don't need to do anything in Java, unless tests.
So, it up to you to choose the proper way to test you flow.
I'm working with embedded Jetty websockets and what I see in the examples is passing the Class of the handler to the container instead of an instance. I would to know if it's possible to pass an instance instead of a class and how that works.
ServerContainer wscontainer = webSocketServerContainerInitializer.configureContext(context);
// Add WebSocket endpoint to javax.websocket layer
wscontainer.addEndpoint(EventSocket.class);
I would like to be able to do
wscontainer.addEndpoint(new EventSocket());
of course this method is not supported.
I see that on the client side you can provide an instance of a handler
Session session = container.connectToServer(new ClientSocket(), uri);
I'm curious why the api was designed to accept a class instead of an instance, which is unlike how servlets work.
Update:
The following solution works:
// contains ServerEndpoint annotation and onMessage, onOpen etc
final EventSocket eventSocket = new EventSocket();
ServerEndpointConfig config = ServerEndpointConfig.Builder.create(eventSocket.getClass(), eventSocket.getClass().getAnnotation(ServerEndpoint.class).value())
.configurator(new Configurator() {
#Override
public <T> T getEndpointInstance(Class<T> endpointClass) throws InstantiationException {
return (T) eventSocket;
}
})
.build();
wscontainer.addEndpoint(config);
In servlets, you have 1 instance for all requests to the same servlet.
In a websocket server, you have long lived connections, and the normal technique is to have a new websocket endpoint instance per connection. In websocket clients, you don't have to worry about this. You are just 1 instance to start with. If you want multiple connections, you have multiple instances of that websocket endpoint that you created yourself.
ServerContainer is a javax.websocket.server.ServerContainer (aka JSR-356).
It has 2 addEndpoint() mechanisms:
addEndpoint(Class<?> endpointClass) assumes that the class either extends from Endpoint or is annotated with #ServerEndpoint (yes, you can have server that doesn't initialize via annotation scanning, but still uses annotations and this addEndpoint mechanism to programatically add endpoints). It assumes that the server will instantiate a new Endpoint on each incoming websocket upgrade request.
addEndpoint(ServerEndpointConfig serverConfig) takes a ServerEndpointConfig that declares how you want your endpoint to bound. It too assumes that the server will instantiate a new Endpoint on each incoming websocket upgrade request. However, there is way out using this technique. Define your own Configurator object that overrides the getEndpointInstance(Class<?> endpointClass) method, returning the same object over and over again. Just note that the instance you return must be of the class type that was passed into that method (otherwise its an error).
If you choose to use the jetty native websocket implementation, then you can also use the WebSocketCreator to handle the creation of websocket instances, even singletons.
I am new to spring and want to implement long polling for a website to display admin message immediately when it becomes available to all clients,i searched google for hours and could only find out deferredresult(spring 3.2) can be used to implement it.my question is how i can achieve long polling with deferredresult, I would appreciate it if anyone could refer me to such a tutorial.
Another option is to use AsyncContext. This will keep the initial GET request "open" and enable you to send multiple messages as part of the response, unlike DeferredResult which allows to send only ONE response message. Here is a good-link that explains how !
Straight from the horses mouth.
You have two basic options: Option 1 is a Callable
, where the Callable returns the String view name (you may also be able to use #ResponseBody or some of the other normal Spring return types like ModelAndView, but I have never investigated that).
Option two is to return DeferredResult, which is like Callable. except you can pass that off to a separate thread and fill in the results there. Again, not sure if you can return a ModelAndView or use #ResponseBody to return XML/JSON, but I am sure you can.
Short background about DeferredResult:
Your controller is eventually a function executed by the servlet container (for that matter, let's assume that the server container is Tomcat) worker thread. Your service flow start with Tomcat and ends with Tomcat. Tomcat gets the request from the client, holds the connection, and eventually returns a response to the client. Your code (controller or servlet) is somewhere in the middle.
Consider this flow:
Tomcat get client request.
Tomcat executes your controller.
Release Tomcat thread but keep the client connection (don't return response) and run heavy processing on different thread.
When your heavy processing complete, update Tomcat with its response and return it to the client (by Tomcat).
Because the servlet (your code) and the servlet container (Tomcat) are different entities, then to allow this flow (releasing tomcat thread but keep the client connection) we need to have this support in their contract, the package javax.servlet, which introduced in Servlet 3.0 . Spring MVC use this new Servlet 3.0 capability when the return value of the controller is DeferredResult or Callable, although they are two different things. Callable is an interface that is part of java.util, and it is an improvement for the Runnable interface. DeferredResult is a class designed by Spring to allow more options (that I will describe) for asynchronous request processing in Spring MVC, and this class just holds the result (as implied by its name) while your Callable implementation holds the async code. So it means you can use both in your controller, run your async code with Callable and set the result in DeferredResult, which will be the controller return value. So what do you get by using DeferredResult as the return value instead of Callable? DeferredResult has built-in callbacks like onError, onTimeout, and onCompletion. It makes error handling very easy. In addition, as it is just the result container, you can choose any thread (or thread pool) to run on your async code. With Callable, you don't have this choice.
Here you can find a simple working examples I created with both options, Callable and DeferredResult.