I'm doing something like this in my Quickfix/J Application implementation:
public void toApp(Message message, SessionID sessionID) throws DoNotSend {
try {
Session.sendToTarget(message, sessionID);
} catch (SessionNotFound e) {
e.printStackTrace();
}
}
but the code in Session.Java itself calls application.toApp(message, sessionID);
in the method
private boolean sendRaw(Message message, int num) {
what is the correct way to send messages?
The toApp method is a callback function that is called whenever a message is sent to the counterparty. Looking at your code, I feel that your logic is recursive in itself. SendToTarget calls toApp and toApp calls sendToTarget. A simple way to send messages is to use the concrete session object, say mySession. Then you may do mySession.send(Message).
If you are trying to send a message in response to a received message, you'll want to do that in the fromApp callback method instead.
The toApp callback is for outgoing messages. This can be useful if you want to do some extra validation or risk management on outgoing messages. If you don't want to send the message, then throw a DoNotSend exception.
Related
I'm looking to respond to a REST endpoint with a Success/Failure response that dynamically accepts a topic as a query param. In Quarkus with smallrye reactive messaging the code would look something like below wrapping the payload with OutgoingKafkaRecordMetadata
i.e. https://myendpoint/publishToKafka?topic=myDynamicTopic
#Channel("test")
Emitter<byte []> kafkaEmitter;
#POST
#Path("/publishToKafka")
public CompletionStage<Void> publishRecord(#QueryParam("topic") String topic, byte [] payload){
kafkaEmitter.send(Message.of(payload).addMetadata(OutgoingKafkaRecordMetadata.<String>builder()
.withKey("my-key")
.withTopic("myDynamicTopic")
.build()));
}
From the Quarkus doco "If the endpoint does not return a CompletionStage, the HTTP response may be written before the message is sent to Kafka, and so failures won’t be reported to the user." The example here describes this process when you send a payload directly (i.e. emitter.send(payload) which returns a CompletionStage but emitter.send(message) returns void) but this requires configuring the topic in advance. Is it possible to specify metadata with a Message and still respond to the calling client with a success/failure response? (I don't mind if it's with Emitter and CompletionStage or MunityEmitter and Uni).
Any advice or suggestions would be appreciated.
Because you use a Message (as you need to specify the topic), you need something a bit more convoluted:
#Channel("test")
Emitter<byte []> kafkaEmitter;
#POST
#Path("/publishToKafka")
public CompletionStage<Void> publishRecord(#QueryParam("topic") String topic, byte [] payload){
CompletableFuture<Void> future = new CompletableFuture<>();
Message<byte[]> message = Message.of(payload).addMetadata(OutgoingKafkaRecordMetadata.
<String>builder()
.withKey("my-key")
.withTopic("myDynamicTopic")
.build()));
message = message.withAck(() -> {
future.complete(null));
return CompleteableFuture.completedFuture(null);
}
.withNack(t -> {
future.completeExceptionnaly(t));
return CompleteableFuture.completedFuture(null);
});
kafkaEmitter.send(message);
return future;
}
In this snippet, I also attach the ack and nack handlers called when the message is either acknowledged (accepted by the broker) or rejected (something wrong happened).
These callbacks report to future, a CompletableFuture created in the method. This is the object to return, as it will do what you want: indicate the outcome.
I know the callbacks are slightly complicated. This is mainly due to the spec: We have to return CompleteableFuture.completedFuture(...); to acknowledge that the nack-process was successful. If we were to return future; instead (which we have set to future.completeExceptionnaly(t));), this would be interpreted as a failure during the nack-process. This would basically be the equivalent to a throw within a catch-block in the imperative world.
Fortunately, an easier version will be available soonish (no worries, we won't break).
I have a verticle which accepts REST request, get data from other verticle through event bus and respond back to client.
vertx.exceptionHandler(event -> logger.error("Vertx exception ", event));
router.get("/api/v1/:param").handler(this::routerHandler);
public void routerHandler(RoutingContext rc) {
vertx.eventBus().request("data", param,
result -> {
if (result.succeeded()) {
logger.info("Request handled successfully");
// intentionally creating exception body() will return String
JsonObject jsonObject = (JsonObject) result.result().body();
rc.response().end(jsonObject)
}else{
logger.error("Request failed");
}
}
When a exception is raised it is printed in exception handler that I setup in vertx instance but after that the vertx is not reporting back the exception immediately to client instead it waits for timeout(30 secs) to occur.
I tried attaching error handler to router object and failure handler to route object but nothing helps to report the exception immediately to client. I know I can have a try catch and report the error in catch block. But I want know if there is any other way to handle this like Servlet or Spring MVC reports back to client even though the exception is not handled in code.
router.errorHandler(500,routingContext -> {
System.out.println(routingContext.failed());
routingContext.response().end("Exception ");
});
router.route().handler(BodyHandler.create()).failureHandler(routingContext -> {
Uncaught exceptions are reported to the context exceptionHandler. By default it prints the exception to the console.
You can configure it but you will not get a reference to the corresponding HTTP request anyway (the exception may come from different things).
Most problems like this are usually found during unit/integration/acceptance testing.
And for the remainders you could set a timeout handler on your router definition to make sure the request is ended before the default 30 seconds.
If you don't want to miss any uncaught exception, you should switch to the Vert.x Rxified API. When using RxJava, any exception thrown will be reported to the subscriber.
I have a project that does 2 RPC calls and then saves the data that the user provided in tha datastore. The first RPC call works ok, but from the second I always recieve the onFailure() message. How can I determine why the onFailure() is triggered? I tried caught.getCause() but it doesn't return anything.
feedbackService.saveFeedback(email,studentName,usedTemplates,
new AsyncCallback<String>() {
public void onFailure(Throwable caught) {
// Show the RPC error message to the user
caught.getCause();
Window.alert("Failure!");
}
public void onSuccess(String result) {
Window.alert("Saved!");
}
});
Throwable instance is instance of an Exception. You can check if it is a custom Exception like this:
if (caught instanceOf CustomException){
or if you want to show the message of exception you can use the getMessage():
Window.alert("Failure: " + caught.getMessage());
GWT-rpc is not not easy to ebug if an error occurs.
The easiest part is th check if the Exception is part of StatusCodeException.
A Statuscode of 404 means, you are pointing to a wrong endpoint
0 means, that
The searver is unreachable
You don't have permissions to check, if the server is available (X-domain-request)
You can use the Chrome-Web-Inspector to bedug GWT-RPC
You should be able to see all calls from the browser to you backend.
The most common failures are because of serialization of object. You have to ensure, that all dtransferred object implement java.io.Serializable
Most of the time it will just be a server side exception being raised which fires the onFailure() method.
Try putting breakpoints on your server side. That should help you pinpoint what's going wrong.
I've been implementing a GWT application that calls a REST-service (which we're also developing). When the REST-service returns anything with a HTTP-status other than 200 I would expect the onFailure method of AsyncCallback to be called. However I can't get this to happen.
To test it further I created a test GWT app and a test servlet. The part of the GWT app that calls the service looks like this:
JsonpRequestBuilder jsonp = new JsonpRequestBuilder();
jsonp.setCallbackParam("_jsonp");
jsonp.setFailureCallbackParam("_jsonp_failure");
jsonp.requestObject(url, new AsyncCallback<JavaScriptObject>()
{
#Override
public void onFailure(Throwable caught)
{
Window.alert("Failure: " + caught.getMessage());
}
#Override
public void onSuccess(JavaScriptObject result)
{
Window.alert("Success");
}
});
The servlet-code looks like this:
public class MyRestServlet extends HttpServlet
{
protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException
{
String padding = httpServletRequest.getParameter("_jsonp_failure");
httpServletResponse.setContentType("application/x+javascript");
httpServletResponse.setStatus(500);
PrintWriter out = httpServletResponse.getWriter();
out.println(padding + "({\"some\":\"json\"});");
out.close();
}
}
OnFailure eventually gets called when the request times out, but I would expect it to be called as soon as the http response arrives(if it's a failure). I guess there is something I haven't understood and I would really appreciate to get some help with this.
Thanks
According to HTML5, if there's an error loading the script, an error event should be dispatched, and GWT doesn't listen for it (because almost no browser actually fires it AFAICT).
For best browser compatibility, you'd better always send a 200 status, but then call the failure callback (or in other words, return an error state/condition, rather than throw an exception).
Also, the argument to the failure callback is expected to be a string (will be the message of the exception).
From the server code where you call the REST service, throw an exception yourself if the response is something other than 200 (by writing code to check the response yourself). This way it will persist to the client side as an error and onFailure will be called in client side.
In GWT's mind currently nothing went wrong. It sent a request, got some result did not matter what, the call was successful. It does call the onFailure on a timeout because something did go wrong with the request "physically", and GWT persisted the exception to the client side as a failure.
In Java, let's say I have a transaction that once it is committed, I want to do another action, in this case, send an email.
Therefore,
try {
transaction.begin()
...
transaction.commit()
// point 1
Utility.sendEmail(...)
} catch (Exception e) {
transaction.rollback();
}
Is it possible for the thread to die/get killed at point 1 and not send an email ?
Any way to minimize this ? JTA + JMS perhaps, where the action of sending a message is part of a transaction ?
I'm investigating an issue and exploring whether this is possible. JVM is still alive (no OOM). I do not know the inner working of the app server so not sure if this is possible.
I can't say for sure if the rollback() in the catch clause has any effect if the commit() was OK and sendEmail() threw an exception. The quickest way to test this is to throw an exception from the sendEmail() method and see if the transaction was actually committed.
The way I would put it though, is to move the sendEmail() call away from your try block:
try {
transaction.begin()
...
transaction.commit()
} catch (Exception e) {
transaction.rollback();
}
try {
// point 1
Utility.sendEmail(...)
} catch (Exception e) {
// handle it
}
This way you can control what will happen if a rollback was made.
Also, I think that sending the email to a JMS queue is in most cases a good idea. Doing it like that will give your DB code permission to continue and supposedly give feedback to your user that everything went OK and the email will be sent whenever it fits the email controller's schedule. For example, there might be a connection issue with your email server and the email sending would hang for say 30 seconds before throwing an exception and your user would see this as a very long button click.