if i receive a HttpServerRequest in a Handler, is it somehow possible to publish the request?
I want to implement a small demo website with an index.html and an unknown number of sub sites. At first there should be a main vert.x module, which starts the HttpServer. In this main module it should be possible to add other dependent modules. I will call them submodules now. I don't know how many submodules i will have later, but each submodule should contain the logic to handle the http response for a specific URL (the sub html files). I guess i have to do the same for the WebSocketHandler...
A small example of the code inside the start():
//My Main Module:
vertx.createHttpServer().requestHandler(new Handler<HttpServerRequest>() {
public void handle(HttpServerRequest req) {
vertx.eventBus().publish("HTTP_REQUEST_CONSTANT", req);
}
}).listen(8080);
// My submodule 1
vertx.eventBus().registerHandler("HTTP_REQUEST_CONSTANT", new Handler<HttpServerRequest>() {
#Override
public void handle(HttpServerRequest req) {
if (req.uri().equals("/")) {
req.response();
}
}
});
// Other submodules which handles other URLs
Or any other solutions? I just don't wanna have the logic for sub sites in the main module.
Edit: Or could i call the vertx.createHttpServer() method in each submodule?
I have a similar Vert.x based application and I ended up doing the following:
I have a HttpServerVerticle that is started from the MainVerticle. There I created an HttpServer with several matchers. Each matcher receives a request and forwards it to a dedicated verticle through theEventBus. Upon getting the response from a dedicated verticle it writes the answer to the response.
Here is a code snippet:
RouteMatcher restMatcher = new RouteMatcher();
EventBus eventBus = vertx.eventBus();
HttpServer httpServer = vertx.createHttpServer();
restMatcher.post("/your/url",
r -> {
r.bodyHandler(requestBody -> {
final int length = requestBody.length();
if(length == 0) {
//return bad request
r.response().setStatusCode(HttpResponseStatus.BAD_REQUEST.code());
r.response().end();
return;
}
eventBus.send("your.address.here",
requestBody.getString(0, length),
new Handler<Message<JsonObject>>(){
#Override
public void handle(Message<JsonObject> message) {
//return the response from the other verticle
r.response().setStatusCode(HttpResponseStatus.OK.code());
if (message.body() != null) {
r.response().end(message.body().toString());
}
else{
r.response().end();
}
}
});
});
});
httpServer.requestHandler(restMatcher);
httpServer.listen(yourPort,yourHost);
In the dedicated verticle you register a listener to the address:
vertx.eventBus().registerHandler("your.address.here", this::yourHandlerMethod);
The handler method would look something like the following:
protected void yourHandlerMethod(Message<String> message){
// do your magic, produce an answer
message.reply(answer);
}
This way you separate your logic from your HTTP mappings and can have different pieces of logic in separate verticles using multiple event bus addresses.
Hope this helps.
Related
Gives a 500 response code when the cancel button is pressed multiple types by the users.
Not causing performance issues but just a lot of clutter in application insights.
Any way to filter this out would be helpful.
Nothing is shown in the telemetry to share too, only the API method that is been called with a 500 code and time. sharing the screenshot of that.
Since you know the response code is 500, you can use telemetry processor to filter out these kinds of request with code 500.
Assume you're using .NET core, you can follow the steps below:
Create a class which implements ITelemetryProcessor, then filter out the request whose response code is 500(or more conditions as per your need.). The sample code looks like below:
public class IgnoreCancelFilter : ITelemetryProcessor
{
private ITelemetryProcessor Next { get; set; }
// next will point to the next TelemetryProcessor in the chain.
public IgnoreCancelFilter(ITelemetryProcessor next)
{
this.Next = next;
}
public void Process(ITelemetry item)
{
var request = item as RequestTelemetry;
if (request != null &&
request.ResponseCode.Equals("500", StringComparison.OrdinalIgnoreCase))
{
// To filter out an item, return without calling the next processor.
return;
}
// Send everything else
this.Next.Process(item);
}
}
Then, register it in ConfigureServices method of your Startup.cs class.
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddApplicationInsightsTelemetry();
services.AddApplicationInsightsTelemetryProcessor<IgnoreCancelFilter>();
}
If the programming language is not .NET core, you can find the proper method for .NET framework / js etc. in this article.
I have implemented a custom receiver for Microsoft ASP.NET WebHooks by implementing WebHookHandler.
public class Web_WebHookHandler : WebHookHandler
{
public Web_WebHookHandler()
{
this.Receiver = CustomWebHookReceiver.ReceiverName;
}
public override Task ExecuteAsync(string generator, WebHookHandlerContext context)
{
SendNotification();
return Task.FromResult(true);
}
private void SendNotification()
{
Task.Factory.StartNew(() => {
// doing some processing
});
}
}
Whenever some event gets fired, it hits my above receiver 3 times. I have tried everything but nothing made any difference. Please help me sort it out.
Try adding bellow code in the ExecuteAsync before return. .i.e.
context.Response = new System.Net.Http.HttpResponseMessage (System.Net.HttpStatusCode.Gone);
return Task.FromResult(true);
Actually webhooks dispatcher inspects response from your receiver and retries if proper response is not sent back. So in order to tell dispatcher that request has been processed and everything is okay, you need to set context.Response and also return Task.FromResult(true).
Otherwise it will keep trying for 3 times atleast.
I m sending several retrofit calls via SyncAdapter onPerformSync and I m trying to regulate http calls by sending out via a try/catch sleep statement. However, this is blocking the UI and will be not responsive only after all calls are done.
What is a better way to regulate network calls (with a sleep timer) in background in onPerformSync without blocking UI?
#Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
String baseUrl = BuildConfig.API_BASE_URL;
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
service = retrofit.create(HTTPService.class);
Call<RetroFitModel> RetroFitModelCall = service.getRetroFit(apiKey, sortOrder);
RetroFitModelCall.enqueue(new Callback<RetroFitModel>() {
#Override
public void onResponse(Response<RetroFitModel> response) {
if (!response.isSuccess()) {
} else {
List<RetroFitResult> retrofitResultList = response.body().getResults();
Utility.storeList(getContext(), retrofitResultList);
for (final RetroFitResult result : retrofitResultList) {
RetroFitReview(result.getId(), service);
try {
// Sleep for SLEEP_TIME before running RetroFitReports & RetroFitTime
Thread.sleep(SLEEP_TIME);
} catch (InterruptedException e) {
}
RetroFitReports(result.getId(), service);
RetroFitTime(result.getId(), service);
}
}
}
#Override
public void onFailure(Throwable t) {
Log.e(LOG_TAG, "Error: " + t.getMessage());
}
});
}
}
The "onPerformSync" code is executed within the "SyncAdapterThread" thread, not within the Main UI thread. However this could change when making asynchronous calls with callbacks (which is our case here).
Here you are using an asynchronous call of the Retrofit "call.enqueue" method, and this has an impact on thread execution. The question we need to ask at this point:
Where callback methods are going to be executed?
To get the answer to this question, we have to determine which Looper is going to be used by the Handler that will post callbacks.
In case we are playing with handlers ourselves, we can define the looper, the handler and how to process messages/runnables between handlers. But this time it is different because we are using a third party framework (Retrofit). So we have to know which looper used by Retrofit?
Please note that if Retrofit didn't already define his looper, you
could have caught an exception saying that you need a looper to
process callbacks. In other words, an asynchronous call needs to be in
a looper thread in order to post callbacks back to the thread from
where it was executed.
According to the code source of Retrofit (Platform.java):
static class Android extends Platform {
#Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
if (callbackExecutor == null) {
callbackExecutor = new MainThreadExecutor();
}
return new ExecutorCallAdapterFactory(callbackExecutor);
}
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
#Override public void execute(Runnable r) {
handler.post(r);
}
}
}
You can notice "Looper.getMainLooper()", which means that Retrofit will post messages/runnables into the main thread message queue (you can do research on this for further detailed explanation). Thus the posted message/runnable will be handled by the main thread.
So that being said, the onResponse/onFailure callbacks will be executed in the main thread. And it's going to block the UI, if you are doing too much work (Thread.sleep(SLEEP_TIME);). You can check it by yourself: just make a breakpoint in "onResponse" callback and check in which thread it is running.
So how to handle this situation? (the answer to your question about Retrofit use)
Since we are already in a background thread (SyncAdapterThread), so there is no need to make asynchronous calls in your case. Just make a Retrofit synchronous call and then process the result, or log a failure. This way, you will not block the UI.
I have a Socket handler in Vert.x and I know how to send data through the EventBus in a client-to-server (from Web Browser to Web Server) and server-component-to-server-component fashions.
Now I have a JavaFX-Client connected to the Vert.x Socket handler through websockets:
public void start() {
vertx.createHttpClient()
.setHost(Main.SOCKET_SERVER)
.setPort(8080)
.connectWebsocket("/chat/service", new Handler<WebSocket>() {
#Override
public void handle(WebSocket websocket) {
ws = websocket;
websocket.dataHandler(new Handler<Buffer>() {
#Override
public void handle(Buffer data) {
System.out.println("Received Data");
}
});
//...
// use ws for authentification
ws.writeTextFrame("doAuthentification");
//...
}
}
}
The Socket is connected to "/chat/service".
Now I want to use this Websocket to call different Services from Vert.x. I know that EventBus is not working from JavaFX-Client.
On the server:
ws.dataHandler(new Handler<Buffer>() {
#Override
public void handle(final Buffer data) {
String text = data.toString();
if(text.contentEquals("doAuthentification")){
logger.info("doAuthentification()");
doAuthentification();
}
// ...
}
}
I can now send "commands" like doAuthentification through the WebSocket, then, on server side and when that command is received, I can use the EventBus to process it further.
What would be the correct way using it from a client. Ideas?
Since you application is packaged as a standalone application is not deployed as in a Vert.x instance, you won't be able to call the event-bus since it is a Vert.x specific feature.
Your method to go would be, as you already tyried, to communicate to your Vert.x application in a standard way, through socket, or http for example (I would recommend HTTP and a RESTful application style), and send messages through an entry point that will be later on transferred to the appropriate verticles.
You may need to configure many path based handlers, maybe using a regex capture group inside, and let each handler choose the appropriate schema to delegate events, instead of having a single handler based on hardcoded messages.
I want to make a service that notify the user in case there are some new messages sent to him. Thus I want to use some Comet framework that provide the server push ability. So I have looked into PokeIn.
Just wondering a thing. I have checked on the samples that they have on the website. None of them look into the database to retrieve new entries if there are some. But it is just a matter of modification to it I guess.
One of the sample implement this long polling by using a sleep on the server side. So if I use the same approach I can check the database, if there are any new entries, every 5 seconds. However this approach doesn't seem to be much different from when using polling on the client side with javascript.
This part is from a sample. As can be seen they put a sleep there for to update current time for everybody.
static void UpdateClients()
{
while (true)
{
//.. code to check database
if (CometWorker.ActiveClientCount > 0)
{
CometWorker.SendToAll(JSON.Method("UpdateTime", DateTime.Now));
}
Thread.Sleep(500);
}
}
So I wonder is this how I should implement the message notifier? It seems that the above approach is still going to push a huge load demand on the server side. The message notifier is intend to work same way as the one found Facebook.
You shouldn't implement this way, that sample is only implemented like that because the keep PokeIn related part is clear. You should implement SQL part as mentioned http://www.codeproject.com/Articles/12335/Using-SqlDependency-for-data-change-events
in order to track changes on database.
So, when you have something to send, call one of the PokeIn methods for the client side delivery. I don't know, how much your application is time critical because in addition to reverse ajax, PokeIn's internal websocket feature is very easy to activate and delivers messages to client quite fast.
You can do this with database as #Zuuum said, but I implemented it in a different way.
I'm using ASP.NET MVC with PokeIn and EF in a Windows Azure environment:
I have domain events similar to this approach: Strengthening your domain: Domain Events
When someone invokes an action, that's a Unit of Work
If that UOW succeeds then I raise a domain event (e.g. ChatMessageSent)
I have subscribers for these domain events so they can receive the event and forward the message to the PokeIn listeners
I use this pattern for all my real-time needs on my game site (making moves, actions etc in a game), I don't want to advertise it here, you can find it through me if you want.
I always use this pattern as a duplex communication solution so everybody gets their update via PokeIn, even the user who invoked the action so every client will behave the same. So when someone calls an action it won't return anything except the success signal.
The next examples are won't work because they are only snippets to demonstrate the flow
Here is an action snippet from my code:
[HttpPost]
[UnitOfWork]
[RestrictToAjax]
[ValidateAntiForgeryToken]
public JsonResult Post(SendMessageViewModel msg)
{
if (ModelState.IsValid)
{
var chatMessage = new ChatMessage
{
ContainerType = msg.ContainerType,
ContainerID = msg.ContainerID,
Message = _xssEncoder.Encode(msg.Message),
User = _profileService.CurrentUser
};
_chatRepository.AddMessage(chatMessage);
OnSuccessfulUoW = () => EventBroker.Current.Send(this, new ChatMessageSentPayload(chatMessage));
}
return Json(Constants.AjaxOk);
}
And the (simplified) EventBroker implementation:
public class UnityEventBroker : EventBroker
{
private readonly IUnityContainer _container;
public UnityEventBroker(IUnityContainer container)
{
_container = container;
}
public override void Send<TPayload>(object sender, TPayload payload)
{
var subscribers = _container.ResolveAll<IEventSubscriber<TPayload>>();
if (subscribers == null) return;
foreach (var subscriber in subscribers)
{
subscriber.Receive(sender, payload);
}
}
}
And the even more simplified subscriber:
public class ChatMessageSentSubscriber : IEventSubscriber<ChatMessageSentPayload>
{
public void Receive(object sender, ChatMessageSentPayload payload)
{
var message = payload.Message;
var content = SiteContent.Global;
var clients = Client.GetClients(c => c.ContentID == message.ContainerID && c.Content == content)
.Select(c => c.ClientID)
.ToArray();
var dto = ObjectMapper.Current.Map<ChatMessage, ChatMessageSentDto>(message);
var json = PokeIn.JSON.Method("pokein", dto);
CometWorker.SendToClients(clients, json);
}
}