who calls subscribe on Flux or Mono in reactive webapplication - reactive-programming

I am looking at some examples of reactive web applications and i am seeing them like this
#RequestMapping(value = "/{id}", method = RequestMethod.GET)
#ResponseBody
public Mono<Person> findById(...) {
return exampleService.findById(...);
}
#RequestMapping(method = RequestMethod.GET, produces = MediaType.TEXT_EVENT_STREAM_VALUE)
#ResponseBody
public Flux<Person> findAll() {
Flux<Person> persons = exampleService.findAll();
return persons;
}
When i am reading about the Mono and Flux in the documentation it mentioned subscribe has to be called for Mono or Flux to emit the data.
So when i run these reactive webapplications locally and using postman/chrome browser when i hit the endpoints i getting the results.
On the service side though endpoints are returning Mono or Flux, how i am seeing the actual results in the browser/postman.
Is the browser doing the part of calling the subscribe internally whenever i am hitting the endpoints that return Mono/Flux types?

Mono and Flux concepts exist only within your application, while HTTP protocol is used to communicate between your postman/chrome app and your application.
Internal classes of the Spring Webflux framework subscribe to Mono and Flux instances returned by your controller methods and map them to HTTP packets based on the MediaType that you specified in RequestMapping.

It depends on which server you use.
For instance, Tomcat, Jetty (Servlet 3.1 non-blocking I/O) - ServletHttpHandlerAdapter from org.springframework.http.server.reactive package.
Subscription happens in service method:
#Override
public void service(ServletRequest request, ServletResponse response) throws
ServletException, IOException {
...
HandlerResultSubscriber subscriber = new HandlerResultSubscriber(asyncContext,
isCompleted, httpRequest);
this.httpHandler.handle(httpRequest, httpResponse).subscribe(subscriber);
}

Related

RxJava disposing Observable/Flowable in a microservice Server project

I am using RxJava for a server microservice project, where using Jetty as HTTP Servlet server.
I am handling requests either from client or main server with Observable for different flows.
When a request hitting the api below, I will return a Response after Observable finishes the job.
#GET
#Path("{uuid}")
#Produces(MediaType.APPLICATION_JSON)
public Response doThingsForClient(#PathParam("uuid") String uuid) {
Worker worker = new Worker(uuid);
worker.run();
return Response.ok("Awesome").build();
}
class Worker {
String uuid = null;
public Worker(String uuid) {
this.uuid = uuid;
}
public void run() {
Observable.concat(Observable1,Observable2,Observable3);
}
}
I am wondering if I need to dispose these Observables or Flowables.
According to this: Does RxJava2 auto dispose observable when they call completed or error?
and the RxJava3 sourcecode, i don't think Flowable at least is disposed automatically?
If I need to manually dispose the resources,
Is it better to create a CompositeDisposable, then add disposable to the CompositeDisposable at each Observer(Observable1...Observable3)'s onSubscribe() being called, call compositeDisposable.dispose() after the concat finishes.
Should I also monitor the Jetty AbstractLifeCycle to dispose these Observables(It sounds similar as Android)? I am not sure how other people are using RxJava at the server side, open to any suggestions to these questions and general Rx approach at server projects.
Thanks!

Feign REST Client: How to get the HTTP status?

I have Feign client setup with Hystrix and I am trying to log all the HTTP status codes that I get from my API calls into a database. So this means, if one of my calls give me a 201, I would want to log that into DB. If my call results in a failure, my fallback handler can obviously log that but I want to do the DB inserts in one place. Does feign have a way to get access to responses or some kind of general callback?
You have to provide custom decoder to get your response in ResponseEntity<Object>.
NotificationClient notificationClient = Feign.builder()
.encoder(new JacksonEncoder())
.decoder(customDecoder())
.target(Target.EmptyTarget.create(NotificationClient.class));
Here you define your custom decoder bean. You can define your own by implementing Decoder but I'm using spring decoder.
#Bean
public Decoder customDecoder() {
HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(customObjectMapper());
ObjectFactory<HttpMessageConverters> objectFactory = () -> new HttpMessageConverters(jacksonConverter);
return new ResponseEntityDecoder(new SpringDecoder(objectFactory));
}
Now collect your response in ResponseEntity<Object>
ResponseEntity<Object> response = notificationClient.notify();
int status = response.getStatusCodeValue();
Another option is to create your own feign.Logger implementation, overriding the logAndRebufferResponse method:
protected Response logAndRebufferResponse(
String configKey, Level logLevel, Response response, long elapsedTime);
This may be simpler than creating a Decoder and is guaranteed to be called when a response is received regardless of status. Decoders are only called if the request does not trigger an error.

CometD Subscription Listeners

I’m having a problem processing Subscription Requests from Clients and carrying out some processing based on the request. I’d like to be able to invoke a method and carry out some processing when an incoming subscription request is received on the Server. I’ve had a look at the following CometD documentation and tried the example outlined in “Subscription Configuration Support” but I’m not having much luck.
http://www.cometd.org/documentation/2.x/cometd-java/server/services/annotated
I’ve already created the Bayeux Server using a Spring Bean and I’m able to publish data to other channel names I’ve created on the Server side. Any help or additional info. on the topic would be appreciated!
The code example I’m using:
#Service("CometDSubscriptionListener")
public class CometDSubscriptionListener {
private final String channel = "/subscription";
private static final Logger logger = Logger.getLogger(CometDSubscriptionListener.class);
private Heartbeat heartbeat;
#Inject
private BayeuxServer bayeuxserver;
#Session
private ServerSession sender;
public CometDSubscriptionListener(BayeuxServer bayeuxserver){
logger.info("CometDSubscriptionListener constructor called");
}
#Subscription(channel)
public void processClientRequest(Message message)
{
logger.info("Received request from client for channel " + channel);
PublishData();
}
Have a look at the documentation for annotated services, and also to the CometD concepts.
If I read your question correctly, you want to be able to perform some logic when clients subscribe to a channel, not when messages arrive to that channel.
You're confusing the meaning of the #Subscription annotation, so read the links above that should clarify its semantic.
To do what I understood you want to do it, you need this:
#Service
public class CometDSubscriptionListener
{
...
#Listener(Channel.META_SUBSCRIBE)
public void processSubscription(ServerSession remote, ServerMessage message)
{
// What channel the client wants to subscribe to ?
String channel = (String)message.get(Message.SUBSCRIPTION_FIELD);
// Do your logic here
}
}

web api XmlMediaTypeFormatter exception

I want to use IoC / the dependency resolver of the web api framework for decoupling.
The XmlFormatter cant serialize interfaces,... Ok. But what would be the purpose of IoC and the DependencyResolver if I cant return xml?
I cant even do this:
(Method in my ApiController)
public HttpResponseMessage Get()
{
IEnumerable<Project> projects = new List<IProject>() { new Project(), new Project() }.Select(p => p as Project);
HttpResponseMessage response = Request.CreateResponse<IEnumerable<Project>>(HttpStatusCode.OK, projects);
return response;
}
I create a list of IProjects and cast them to 'Project'. But while creating the response I get this:
The configured formatter
'System.Web.Http.Tracing.Tracers.XmlMediaTypeFormatterTracer' cannot
write an object of type 'WhereSelectListIterator`2'.
That is a XmlMediaTypeFormatterTracer? I dont want tracing that throws errors while serialization. (BTW: I replaced the standard XMLformatter with my own one. However "XmlMediaTypeFormatterTracer" throws the exception...
Info: I get the same error while using the standard formatter)
Why is this XmlMediaTypeFormatterTracer called even if I implement my own xmlformatter?
my problem solved with
config.Formatters.XmlFormatter.UseXmlSerializer = false;
Have you enabled Tracing in your application? If yes, the Tracing logic wraps formatters into its a wrapper tracer formatters.

GWT JSONPRequestBuilder - "Unknown Token :" error in browser console with Timeout exception at the end

I am trying to call a Restful WS from GWT using JSOPRequestBuilder. I have a similar issue which was reported in the link
http://groups.google.com/group/google-web-toolkit/browse_thread/thread/ef93383aca7a3dfc/d4dc5bad1a9110ea
But, I could not figure out the solution. Kindly help me at the earliest.
My JAX-WS resource code snippet from server
#GET
#Produces(MediaType.APPLICATION_JSON)
public DealerAddress getDealerAddress(#QueryParam("dealerId") String sDealerId) {
DealerAddress dlrAd = new DealerAddress("test", "test", "test", "test", 10, new Date(), new Date());
return dlrAd;
}
Jersey returns a JSON object of DealerAddress.
Now rest URL "https://127.0.0.1:8181/application/rest/OrderManagementResource?alt=json-in-script&dealerId=DLR1"
works absolutely fine when i tried request in browser.
It even works with RequestBuilder approach from GWT but not with JSONPRequestBuilder approach.
Code snippet to invoke WS from GWT using JSONPRequestBuilder
JsonpRequestBuilder jsonPReqBuilder = new JsonpRequestBuilder();
jsonPReqBuilder.setTimeout(100000);
jsonPReqBuilder.setCallbackParam("callback");
jsonPReqBuilder.requestObject("https://127.0.0.1:8181/application/rest/OrderManagementResource?alt=json-in-script&dealerId=DLR1" , new AsyncCallback<DealerAddressJSON>() {
#Override
public void onFailure(Throwable caught) {
// TODO Auto-generated method stub
caught.printStackTrace();
Window.alert("Inside error"+caught.getLocalizedMessage());
}
#Override
public void onSuccess(DealerAddressJSON result) {
// TODO Auto-generated method stub
Window.alert("Inside success"+result);
}
});
where as DealerAddressJSON is a JavaScriptObject type class.
I could see that my JAX Rest resource getting called and saying returning from server.
Also, I could see that in Firebug that the response comes in browser but fails with an exception "Unknown token :"
At the end I always get a Timeout exception.
Now I am in big question whether the way we return JSON from JAX-RS resource is a problem in server
or
JSONPRequestBuilder calling procedure is a problem? I could not understand the callback changes which some of the links explained on this issue.
Kindly help me.
You are probably sending back JSON, while the JSONPRequestBuilder expects JSONP. These are not the same thing.
JSON is just the data, as is - make the request using AJAX (i.e. the RequestBuilder), and the contents can be read directly. These requests can only be made to the same server. Example JSON data:
{"response":"success", "items":[{"id":1}, {"id":2}]}
In contrast, JSONP is designed for cross-origin requests, so instead of just containing the data, the data is wrapped up in a JavaScript. Since your JSON service isn't wrapping the a response in a js function call, this isn't working. Example JSONP data:
callback_1({"response":"success", "items":[{"id":1}, {"id":2}]})
The callback changes with each request, so the server is supposed to change that callback function based on what the client requested each time.