SSE implementation in Spring REST - java

Can anybody provide an example for SSE ( Server sent events) using Spring Rest ? Basically i have a request and the response for it would be sent by the server in multiple chunks. I would like to have the server and client implementation in Spring REST Api without third party rest api like jersey.

There isn't any direct support for SSE in Spring currently but it looks like it will be available in 4.2 which is in RC2 right now
You can see the details here
https://jira.spring.io/browse/SPR-12212
This works via returning an SseEmitter or a ResponseBodyEmitter from the controller methods.
#RequestMapping(value="/stream", method=RequestMethod.GET)
public ResponseBodyEmitter handle() {
ResponseBodyEmitter emitter = new ResponseBodyEmitter();
// Pass the emitter to another component...
return emitter;
}
// in another thread
emitter.send(foo1);
// and again
emitter.send(foo2);
// and done
emitter.complete();
You can see the Reference documentation here
http://docs.spring.io/spring/docs/4.2.0.RC2/spring-framework-reference/htmlsingle/#mvc-ann-async-http-streaming

Related

Microservice feign infinite loop of invocations?

I am confused about how an infinite loop of feign calls might behave.
An example:
Assume I have 2 APIs, A & B.
if I call API A, which in turn calls API B via a feign HTTP call, which in turn calls API A again via feign, will it recognize this and break the call chain?
Quick flowchart of calls:
A -> B -> A -> B ... Repeat infinitely?
I have not tried this code, it is just an idea。
But I am assuming that spring-cloud-starter-feign will provide some methods to resolve this problem? Is this assumption correct?
#PostMapping(RestJsonPath.API_A)
ResponseEntity<byte[]> apiA();
#PostMapping(RestJsonPath.API_B)
ResponseEntity<byte[]> apiB();
Will it execute until it times out or hystrix will stop it?
TL;DR:
Feign will keep the connection open on the initial request from A to B until the pre-configured timeout kicks in. At this point, Feign will time out the request and if you have specified a Hystrix fallback, Spring will use your Hystrix fallback as the response.
Explanation:
spring-boot-starter-feign provides an abstraction layer for writing the HTTP request code. It will not handle potential loops or cycles in your code.
Here is an example spring boot feign client from their tutorials website for demonstration:
#FeignClient(value = "jplaceholder",
url = "https://jsonplaceholder.typicode.com/",
configuration = ClientConfiguration.class,
fallback = JSONPlaceHolderFallback.class)
public interface JSONPlaceHolderClient {
#RequestMapping(method = RequestMethod.GET, value = "/posts")
List<Post> getPosts();
#RequestMapping(method = RequestMethod.GET, value = "/posts/{postId}", produces = "application/json")
Post getPostById(#PathVariable("postId") Long postId);
}
Notice first that this is an interface - all the code is auto generated by Spring at startup time, and that code will make RESTful requests to the urls configured via the annotations. For instance, the 2nd request allows us to pass in a path variable, which Spring will ensure makes it on the URL path of the outbound request.
The important thing to stress here is that this interface is only responsible for the HTTP calls, not any potential loops. Logic using this interface (which I can inject to any other Spring Bean as I would any other Spring Bean), is up to you the developer.
Github repo where this example came from.
Spring Boot Docs on spring-boot-starter-openfeign.
Hope this helps you understand the purpose of the openfeign project, and helps you understand that it's up to you to deal with cycles and infinite loops in your application code.
As for Hystrix, that framework comes in to play (if it is enabled) only if one of these generated HTTP requests fails, whether it's a timeout, 4xx error, 5xx error, or a response deserialization error. You configure Hystrix, as a sensible default or fallback for when the HTTP request fails.
This is a decent tutorial on Hystrix.
Some points to call out is that a Hystrix fallback must implement your Feign client interface, and you must specify this class as your Hysterix fallback in the #FeignClient annotation. Spring and Hystrix will call your Hystrix class automatically if a Feign request fails.

Spring REST API - direct activation of API(No Webserver)

I have a Java application that gets information on a general purpose channel.
I cannot listen on another port, and the application does not have(or implements) a webserver.
I want to activate some of the application's functionalities via REST API.
I already have the requested URI and parameters(of a single client request), but they are not in an HTTPRequest class.
How can I directly call the Spring REST API, using the data I have?
To illustrate what I want to do:
In myREST.java:
class myREST {
#RequestMapping(value = "/foos", method = RequestMethod.GET)
#ResponseBody
public List<Foo> getAllFoos {
return foos;
}
}
and in another file:
JSONObject restAPICaller(String uri, JSONObject params) {
JSONObject response = springRestAPI.call(uri, "GET", params);
return response;
}
where for instance, my uri is /foos/ , and params is {} (will have content for other examples)
How can I directly call the Spring REST API, using the data I have?
You cannot use an API via an HTTP client without an HTTP server.
I guess you can either:
Embed a server in your app and have it listen on some network port (you can bind to 127.0.0.1, so that the service is not accessible from other machines).
Directly call into the REST API classes (eg: new myREST(). getAllFoos())
Call into the business logic layer your API classes call into (iff you properly structured your code there)

Spring MVC like processing of AMQP messages

What I want to do is process AMQP messages in a very similar way the Http Requests are processed using spring-webmvc annotations such as #RequestMapping, #RequestParam etc. But, instead of the Http Request my source object will be an AMQP message. The AMQP message request will have two headers, for example -
method="POST"
url="/api/myobjects/{someParam}"
and the payload will contain data in json format.
If you have noticed, this is nothing but HTTP REST api mapped to AMQP message.
I want to be able to write a controller like handler, for example -
#Controller
public class MyObjectHandler {
#RequestMapping(value="/api/myobjects/{someParam}", method="POST")
public MyObject createMyObject(#Payload MyObject myObj, #PathParam String someParam) {
//... some processing
return myObj;
}
// ...more handlers
}
I have looked at spring-amqp/rabbitmq annotations and also spring integration annotations. They are close to what I want, but would not allow routing to handler methods based on header parameters, especially the REST url.
I don't expect that a readymade solution would be available for this. Just want to make sure I choose the best possible option. Some of the options I think are (in order of precedence)
If the spring-webmvc annotation processing mechanism is extensible, just extend it to use AMQP message as source instead of Http Request
Modify the spring-webmvc annotation processing mechanism to take the AMQP message as input instead of Http Request
Write your own solution with custom annotaions and their processors, which I think is a very involving task
Or any other possible approach than above?
Any guidance/direction is appreciated.
I think the starting point is likely AbstractMethodMessageHandler in spring-messaging.
There's currently a SimpAnnotationMethodMessageHandler implementation for websockets which invokes #Controllers.
You could use a #RabbisListener method that has a Message<?> parameter (Spring AMQP will convert the underlying Rabbit message to a spring-messaging message, including the headers). Then, invoke the message handler to route to the appropriate controller method.
If you come up with a robust implementation, please consider contributing it.

Calling a micro service

I looked for the similar question but could not find any . I have a micro service created with drop-wizard which is running in localhost:9000.
I am working in another project(with spring mvc) running in 8080. I wan to call the above service which gives me string back from any of my controllers in main project .lets say the path is "localhost:9000/giveMeString" .
You can use Apache's HTTP Client. See this example borrowed from their documentation:
// Create an instance of HttpClient.
HttpClient client = new HttpClient();
// Create a method instance.
GetMethod method = new GetMethod("http://localhost:9000/giveMeString");
// Execute the method.
int statusCode = client.executeMethod(method);
// Read the response body.
byte[] responseBody = method.getResponseBody();
//Print the response
System.out.println(new String(responseBody));
If you're really going down the microservice path, note that creating an HTTP client for every request and making synchronous, blocking requests won't really scale.
Here are a few ideas, if you're using Spring:
Create a single RestTemplate instance
You can create a single RestTemplate instance and inject it in multiple places in your application.
#Configuration
public class MyConfiguration {
#Bean
public RestTemplate restTemplate() {
return new RestTemplate(new HttpComponentsClientHttpRequestFactory());
}
}
Better, wrap that REST client with a Cache
Check out Sagan's take on this.
Even better, go asynchronous
You can use an AsyncRestTemplate; very useful, especially if your Controllers need to make multiple requests and if you don't want to block your webapp thread. Your Controller can even return a DeferredResult or a ListenableFuture, which will make your webapp more scalable.
And Spring Cloud + Netflix
You can also check Spring Cloud and Spring Cloud Netflix.
You'll see there interesting features: load-balancing, recovery, circuit breakers, etc.

Google Web Toolkit Asynchronous Call from a Service Implementation

I'm writing a simple Google Web Toolkit service which acts as a proxy, which will basically exist to allow the client to make a POST to a different server. The client essentially uses this service to request an HTTP call. The service has only one asynchronous method call, called ajax(), which should just forward the server response. My code for implementing the call looks like this:
class ProxyServiceImpl extends RemoteServiceServlet implements ProxyService {
#Override
public Response ajax(String data) {
RequestBuilder rb = /*make a request builder*/
RequestCallback rc = new RequestCallback() {
#Override
public void onResponseReceived(Response response) {
/* Forward this response back to the client as the return value of
the ajax method... somehow... */
}
};
rb.sendRequest(data, requestCallback);
return /* The response above... except I can't */;
}
}
You can see the basic form of my problem, of course. The ajax() method is used asynchronously, but GWT decides to be smart and hide that from the dumb old developer, so they can just write normal Java code without callbacks. GWT services basically just do magic instead of accepting a callback parameter.
The trouble arises, then, because GWT is hiding the callback object from me. I'm trying to make my own asynchronous call from the service implementation, but I can't, because GWT services assume that you behave synchronously in service implementations. How can I work around this and make an asynchronous call from my service method implementation?
You are mixing up client and server side code. In ProxyServiceImpl, you CANNOT use RequestBuilder. RequestBuilder is a client side class which will only execute in the browser.
A server-to-server http call is always synchronous. Instead of using RequestBuilder, you should make use of a library like HttpClient, get the results and then send it back to the client. That would solve the problem you are facing.
But I should add, you DO NOT want to build a proxy at the application level. You could just as well use a http proxy such as apache's mod_proxy.

Categories