Here is my code:
private static void testExceptionInHandle() {
try {
var handler = future().onSuccess(v -> {
throw new RuntimeException("hello exception");
}).onFailure(e -> {
System.out.println("onFailure:" + e.getMessage());
});
} catch (Exception e) {
System.out.println("catch:" + e.getMessage());
}
}
I wonder what happened with an unpredictable exception but get nothing.
This causes the route processing method to not end properly.
This kind of runtime issues normally bubble up to the exception handler of the Vert.x context or of Vert.x itself (by default, it simply logs the exception).
To make sure the routing process finishes, you should setup a TimeoutHandler on your routes.
Otherwise, you can try using another programming model like Mutiny or RxJava. Any runtime exception will be reported to the subscriber (and then of course terminate the subscription).
You can define failureHandler on your route and catch all runtime exeptions. More details: https://vertx.io/docs/apidocs/io/vertx/ext/web/Route.html#failureHandler-io.vertx.core.Handler-
Related
I have some repository classes added as scoped service and I retrieve a particular repository using:
var rep = HttpContext.RequestServices.GetService(typeof(interface));
That's ok... but when I call:
rep.Save();
Inside, in some validations, I throw Exceptions... And the problem is that I can't catch this Exception in the call, like:
try
{
rep.Save();
}
catch (Excpetion ex)
{
// unreachable code
}
The exception also causes a stop of current running project.
I don't want a global error handler, I just want to catch this exception to determine what should I do right after.
In DI:
svc.AddScoped<IExtratoRepository, ExtratoRepository>();
exception in action
Considering the scenario that one of the verticles throws an uncaught exception.
What happens next?
If the verticle state is removed from the system is there some mechanism similar to erlang supervisors to restart the verticle?
Documentation is not very clear about this aspect.
Update based on comments:
What interest me the most is the situation when an exception is thrown from the processing handlers of a received message (through the bus)
Regards
I have answered part of my own question (with the help of a test program)
When exception is thrown in a event handler then the exception is caught by vert.x and swallowed (ignored). The event handler will process the next message.
Update: The app can register an exception handler and have all the uncaught Throwable delivered to this handler. There you can perform additional general processing
Update2: Use Vertx.exceptionHandler to register the handler
Vert.x is all about the same style, asynchronous programming, which is mainly highlighted by callback handlers.
To handle the deployment failure case, you have first to go the programmatic way, i.e. you have to deploy your verticle programmatically through let's say a deployment verticle providing a completion handler that will be populated with deployment result, here down a sample using Java (since your haven't opt for a specific language, I will go with my best) where:
MainVerticle: is your deployment verticle (used mainly to deploy other verticles)
some.package.MyVerticle: is your real verticle, note that I used the id here and not an instance.
public class MainVerticle extends AbstractVerticle {
public void start() {
vertx.deployVerticle("some.package.MyVerticle", res -> {
if (res.succeeded()) {
// Do whatever if deployment succeeded
} else {
// Handle deployment failure here...
}
});
}
}
Now when it comes to 'messaging failures', it would be harder to highlight a specific case since it can occur at many places and on behalf of both messaging ends.
If you want to register a failure case handler when sending a message, you can instantiate a MessageProducer<T> representing the stream it can be written to, then register an exception handler on it:
EventBus eb = vertx.eventBus();
MessageProducer<String> sender = eb.sender("someAddress");
sender.exceptionHandler(e -> {
System.out.println("An error occured" + e.getCause());
});
sender.write("Hello...");
On the other side, you can handle failure case when reading the received messages pretty much the same way, but using a MessageConsumer<T> this time:
EventBus eb = vertx.eventBus();
MessageConsumer<String> receiver = eb.consumer("someAddress");
receiver.exceptionHandler(e -> {
System.out.println("An error occured while readeing data" + e.getCause());
}).handler(msg -> {
System.out.println("A message has been received: " + msg.body());
});
To add a bit to the previous answer, if you want to react to all uncaught exceptions, register handler on vertx object, as follows:
vertx.exceptionHandler(new Handler<Throwable>() {
#Override
public void handle(Throwable event) {
// do what you meant to do on uncaught exception, e.g.:
System.err.println("Error");
someLogger.error(event + " throws exception: " + event.getStackTrace());
}
});
I ran into something similar to this. When an exception happens as part of processing a message in a Verticle, I just wanted to reply with the Exception.
The idea is to just bubble up the exceptions all the way back to the entry point in the app where a decision can be made about what to do with the failure, while capturing the entire stack along the way.
To accomplish it I wrote this function:
protected ReplyException buildReplyException(Throwable cause, String message)
{
ReplyException ex = new ReplyException(ReplyFailure.RECIPIENT_FAILURE, -1, message);
ex.initCause(cause);
return ex;
}
Which I then use to build handlers, or reply handlers, like this:
reply -> {
if (reply.succeeded()) {
message.reply(true);
} else {
message.reply(buildReplyException(reply.cause(), ""));
}
});
This way the guy that sent the original message will get a failed response which contains a cause that's an exception which has a full stack trace populated on it.
This approach worked very well for me to handle errors while processing messages.
I have some tests where i am checking for parameter name in exception.
How do i write this in MS TEST?
ArgumentNullException exception =
Assert.Throws<ArgumentNullException>(
() => new NHibernateLawbaseCaseDataLoader(
null,
_mockExRepository,
_mockBenRepository));
Assert.AreEqual("lawbaseFixedContactRepository", exception.ParamName);
I have been hoping for neater way so i can avoid using try catch block in the tests.
public static class ExceptionAssert
{
public static T Throws<T>(Action action) where T : Exception
{
try
{
action();
}
catch (T ex)
{
return ex;
}
Assert.Fail("Expected exception of type {0}.", typeof(T));
return null;
}
}
You can use the extension method above as a test helper. Here is an example of how to use it:
// test method
var exception = ExceptionAssert.Throws<ArgumentNullException>(
() => organizations.GetOrganization());
Assert.AreEqual("lawbaseFixedContactRepository", exception.ParamName);
Shameless plug, but I wrote a simple assembly that makes asserting exceptions and exception messages a little easier and more readable in MSTest using Assert.Throws() syntax in the style of nUnit/xUnit.
You can download the package from Nuget using: PM> Install-Package MSTestExtensions
Or you can see the full source code here: https://github.com/bbraithwaite/MSTestExtensions
High level instructions, download the assembly and inherit from BaseTest and you can use the Assert.Throws() syntax.
The main method for the Throws implementation looks as follows:
public static void Throws<T>(Action task, string expectedMessage, ExceptionMessageCompareOptions options) where T : Exception
{
try
{
task();
}
catch (Exception ex)
{
AssertExceptionType<T>(ex);
AssertExceptionMessage(ex, expectedMessage, options);
return;
}
if (typeof(T).Equals(new Exception().GetType()))
{
Assert.Fail("Expected exception but no exception was thrown.");
}
else
{
Assert.Fail(string.Format("Expected exception of type {0} but no exception was thrown.", typeof(T)));
}
}
More info here.
Since the MSTest [ExpectedException] attribute doesn't check the text in the message, your best bet is to try...catch and set an Assert on the exception Message / ParamName property.
I am using EclipseLink in my web application, and I am having a hard time gracefully catching and handling Exceptions it generates. I see from this thread what seems to be a similar problem, but I don't see how to work around or fix it.
My code looks like this:
public void persist(Category category) {
try {
utx.begin();
em.persist(category);
utx.commit();
} catch (RollbackException ex) {
// Log something
} catch (HeuristicMixedException ex) {
// Log something
} catch (HeuristicRollbackException ex) {
// Log something
} catch (SecurityException ex) {
// Log something
} catch (IllegalStateException ex) {
// Log something
} catch (NotSupportedException ex) {
// Log something
} catch (SystemException ex) {
// Log something
}
}
When persist() is called with an entity that violates a uniqueness constraint, I get an explosion of exceptions that are caught and logged by the container.
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.0.v20110604-r9504):
org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: The statement
was aborted because it would have caused a duplicate key value in a unique or
primary key constraint or unique index identified by 'SQL110911125638570'
defined on 'CATEGORY'.
Error Code: -1
(etc)
I have tried the following:
try {
cc.persist(newCategory);
} catch (PersistenceException eee) {
// Never gets here
System.out.println("MaintCategory.doNewCateogry(): caught: " + eee);
} catch (DatabaseException dbe) {
// Never gets here neither
System.out.println("MaintCategory.doNewCateogry(): caught: " + dbe);
}
I realize that using DataBaseException is not portable, but I need to start somewhere. The exceptions never get caught. Any suggestions?
It looks like I won't get any more activity on this question, so I will post my work-around and leave it at that. A number of web searches haven't found much of anything that is helpful. I would have thought this is a textbook case but none of the tutorials I have found covers it.
As it turns out in this condition with EclipseLink, the Exception you can catch when the SQL constraint is violated is the RollBackException that is the result of the em.commit() call. So I have modified my persist method like this:
public void persist(Category category) throws EntityExistsException {
try {
utx.begin();
em.persist(category);
utx.commit();
} catch (RollbackException ex) {
Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
throw new EntityExistsException(ex);
} catch (HeuristicMixedException ex) {
Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
} catch (HeuristicRollbackException ex) {
Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
} catch (SecurityException ex) {
Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalStateException ex) {
Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
} catch (NotSupportedException ex) {
Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
} catch (SystemException ex) {
Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
}
}
So the caller catches the EntityExistsException and takes the appropriate action. The log still fills up with the internal exceptions but that can be shut off later.
I realize that this is a bit of an abuse of the intent of the EntityExistsException that is normally only used when an entity ID field is re-used, but for the purposes of the user application it doesn't matter.
If anyone has a better approach please post a new answer or comment.
Edit your persistence.xml adding the following property:
property name="eclipselink.exception-handler" value="your.own.package.path.YourOwnExceptionHandler"
Now create the class YourOwnExceptionHandler (on the correct package). It requires to implement org.eclipse.persistence.exceptions.ExceptionHandler.
Create a non argument constructor and the required method handleException(...).
Inside this method, you can catch the exceptions!
EclipseLink should only be throwing either a PersitenceException or a RollbackException depending on the environment and the order of operations you are calling on the EntityManager.
What is your logging level? It is likely that you are seeing these exceptions logged by EclipseLink but only thrown as causes of the RollbackException.
You can turn off exception logging with the PU property but for diagnostic purposes it is generally better to allow EclipseLink to log the exceptions.
2019-12-18
As its a very well viewed question and I just had a very similar issue with EclipseLink, in a Maven multi module web application running on Weblogic 12c server and using JTA, I am going to post my solution here, hoping to save a couple hours for someone.
In the persistence.xml we are having:
< property name="eclipselink.persistence-context.flush-mode"
value="commit" />
The REST resource class was marked with #Transactional, meaning that the transaction starts at the point when the request has been received by the related method of the resource class, and it ends when this method returns.
JTA used for managing the transactions.
Now, JTA commit time happens to occur AFTER the resource class's method returns (with a response to the REST client).
Which subsequently means that:
Even though you had a very proper setup to catch the Exception, you
cannot, as exceptions like SQLIntegrityConstraintViolationException
occur only AFTER your INSERT/UPDATE/DELETE query
--that has been sitting all this time in your JPA provider cache--,
now finally sent to the database.
Which happens just after the resource class's method returns, and at that point, all the exceptions has been skipped already.
Since no query sent == no exception occured at the time when the execution ran through the try{...}catch(Exception e){...} lines, you were not able to catch it,
but at the end, you will see the exception in the server's log.
Solution:
I had to manually call flush() on EntityManager to force flush and the exception to occur at the proper time and line (basically in the try block) to be able to catch it, handle it, and allow my REST method to return with my intended response.
The final caught exception in the log (I have masked some not related info):
javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - x.x.x.v00000000-0000000): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: ORA-00001: unique constraint (XXXXX.UNIQUE_KEY_NAME) violated
Related pseudo code:
try {
repository.update(entity);
repository.getEntityManager().flush();
} catch (Exception e ) {
log.info(e.toString());
...
}
I'm using Spring Boot 1.1.9 + EclipseLink 2.5.2. This is the only way I can catch ConstraintViolationException. Note that my handleError(ConstraintViolationException) is a very simple implementation which just returns the first violation it finds.
Note that this code was also required when I switched to Hibernate 4.3.7 and Hibernate Validator 5.1.3.
It seems that adding PersistenceExceptionTranslationPostProcessor exceptionTranslation() to my persistence JavaConfig class also has no effect.
import javax.persistence.RollbackException;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.TransactionSystemException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
#ControllerAdvice
class GlobalExceptionHandler
{
#ExceptionHandler(TransactionSystemException.class)
public ResponseEntity<Object> handleError(final TransactionSystemException tse)
{
if(tse.getCause() != null && tse.getCause() instanceof RollbackException)
{
final RollbackException re = (RollbackException) tse.getCause();
if(re.getCause() != null && re.getCause() instanceof ConstraintViolationException)
{
return handleError((ConstraintViolationException) re.getCause());
}
}
throw tse;
}
#ExceptionHandler(ConstraintViolationException.class)
#SuppressWarnings("unused")
public ResponseEntity<Object> handleError(final ConstraintViolationException cve)
{
for(final ConstraintViolation<?> v : cve.getConstraintViolations())
{
return new ResponseEntity<Object>(new Object()
{
public String getErrorCode()
{
return "VALIDATION_ERROR";
}
public String getMessage()
{
return v.getMessage();
}
}, HttpStatus.BAD_REQUEST);
}
throw cve;
}
}
I use this.
if (!ejbGuardia.findByPkCompuestaSiExiste(bean.getSipreTmpGuardiaPK())) {
ejbGuardia.persist(bean);
showMessage(ConstantesUtil.MENSAJE_RESPUESTA_CORRECTA, SEVERITY_INFO);
} else {
showMessage("Excel : El registro ya existe. (" + bean.toString() + ") ", SEVERITY_ERROR);
}
and my function from above:
public boolean findByPkCompuestaSiExiste(Object clasePkHija) throws ClassNotFoundException {
if (null != em.find(this.clazz, clasePkHija)) {
return true;
}
return false;
}
With that I dont need to program a validation for each Persist, its common in the my DAO Classes.
Is there anyway one can output to the console the message of an exception that may be throw during an NUnit test? Currently I use the ExpectedExceptionAttribute but that doesn't output the message itself, only checks it.
If Method doesn't throw test fails. If it throws it additionally writes exception message to the console.
[Test]
public void Method_throws_exception()
{
var ex = Assert.Throws<InvalidOperationException>(sut.Method);
Console.WriteLine(ex.Message);
}
That assert is only at tab tab with http://nuget.org/List/Packages/NUnit.Snippets
I use:
[Test]
public void SomeTest(){
try {
... stuff ...
Assert.Fail("ExpectedExceptionType should have been thrown");
} catch (ExpectedExceptionType ex) {
Console.WriteLine(ex);
// Assert.Stuff about the exception
}
}
However I've just noticed NUnit 2.6 and it's Exception Assertion helpers.