I have a very curious situation.
I'm trying to execute EJB's method and returns the result with JAX-RS
public Service readSingle(...) {
try {
service.query(...);
} catch (final NoResultException nre) {
throw new NotFoundException(...);
} catch (final NonUniqueResultException nure) {
throw new BadRequstException(...);
}
}
The query method requires some values and a BiFuction and a Function.
The actual call looks like this.
try {
return serviceService.<Service>query(
id,
ofNullable(matrixParameters.getFirst("onid"))
.map(Integer::parseInt).orElse(null),
ofNullable(matrixParameters.getFirst("tsid"))
.map(Integer::parseInt).orElse(null),
ofNullable(matrixParameters.getFirst("sid"))
.map(Integer::parseInt).orElse(null),
ofNullable(matrixParameters.getFirst("number"))
.map(Integer::parseInt).orElse(null),
ofNullable(matrixParameters.getFirst("programId"))
.orElse(null),
operatorId,
(builder, root) -> emptyList(),
TypedQuery::getSingleResult);
} catch (final NoResultException nre) {
throw new NotFoundException(
"no entity idnetified by " + serviceIdSegment.getPath()
+ " with " + matrixParameters.toString());
} catch (final NonUniqueResultException nure) {
throw new BadRequestException("multiple entities identified");
}
Ok I passed TypedQuery::getSingleResult and I expect NonUniqueResultException should be caught when it has to be thrown.
But Payara keep responding with 500 and the log shows that the NonUniqueResultException has never caught by the code.
I disabled my ExceptionMappers the the results are same.
Ok. I figured it out. I had to do this.
try {
// execute EJB
} catch (final EJBTransactionRolledbackException ejbtre) {
Exception leaf = ejbtre;
try {
for (Exception c;
(c = ((EJBException) leaf).getCausedByException()) != null;
leaf = c);
} catch (final ClassCastException cce) {
}
logger.severe("causedByException: " + leaf);
if (leaf instanceof NoResultException) {
throw new NotFoundException(
"no entity idnetified by " + serviceIdSegment.getPath()
+ " with " + matrixParameters.toString());
} else if (leaf instanceof NonUniqueResultException) {
throw new BadRequestException(
"multiple entities identified by "
+ serviceIdSegment.getPath()
+ " with " + matrixParameters.toString());
}
throw new InternalServerErrorException(ejbtre);
}
This is far nasty beyond I've expected. The EJB's method design is not good.
Is there any way to do this more simply?
Let me introduce one of my utility class I used to justify myself.
public final class EJBExceptions {
private static final Logger logger
= getLogger(EJBExceptions.class.getName());
public static Stream<Exception> causedByExceptions(EJBException ejbe) {
final Stream.Builder<Exception> builder = Stream.builder();
while (ejbe != null) {
final Exception causedByException = ejbe.getCausedByException();
if (causedByException != null) {
builder.add(causedByException);
} else {
break;
}
if (causedByException instanceof EJBException) {
ejbe = (EJBException) causedByException;
} else {
break;
}
}
return builder.build();
}
public static Optional<Exception> lastCausedByException(
final EJBException ejbe) {
return causedByExceptions(ejbe).reduce((first, second) -> second);
}
private EJBExceptions() {
super();
}
}
Related
public class CatchingExceptions {
private int erroneousMethod(int p) {
if (p == 0) {
throw new IllegalArgumentException();
}
int x = 0x01;
return p / (x >> Math.abs(p)); // this line will throw!
}
The task is to implement the following method to catch and print the two exceptions.
public void catchExceptions(int passthrough) {
erroneousMethod(passthrough); // will throw!
try{
????
} catch (IllegalArgumentException e){
System.out.println("???? ");
}
}
Call the method inside the try block:
public void catchExceptions(int passthrough) {
try{
erroneousMethod(passthrough);
} catch (RuntimeException e) { // catches all unchecked exceptions
String message = e.getMessage() == null ? "" : (": " + e.getMessage());
System.out.println(e.getClass().getSimpleName() + ": " + message);
}
}
In flux whenever there is OOM the whole process is getting stuck until we kill it manually. I have created an example to simulate it. Please refer the following code:
#Test
public void test_Flux() {
Flux.range(1, 30)
.parallel(6)
.runOn(Schedulers.fromExecutor(Executors.newFixedThreadPool(6)))
.doOnNext(this::writeValues)
.sequential()
.blockLast();
}
private void writeValues(int val) {
if (val == 10) {
throw new OutOfMemoryError("failed here");
// throw new RuntimeException("failed here");
}
System.out.println("the thread name is :" + Thread.currentThread().getName() + " val is :" + val);
sleep(3);
}
private void sleep(int i) {
try {
Thread.sleep(i * 1000L);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
}
}
Can we crash here instead of getting stuck?
I have this code where I execute sets of callables, I need one set to finish all it's work before triggering the next set. This code seems to work fine but sometimes next set would start running before time. What is wrong here?
private void executeSubGraph(QuestExecutionContext ctx, Set<Activity> subGraph, int progressAfterRan) {
ExecutorService pool = Executors.newFixedThreadPool(16);
subGraph.forEach(a -> {
ActivityRunner<? extends Activity> runner = activityRunnerFactory.getRunner(ctx, a);
if (runner != null) {
Callable<List<PortValuePart>> runnerCallable = () -> {
try {
LOG.info("Running {} in {}", a, a.getClass() );
List<PortValuePart> result = runner.call();
LOG.info("Result of {} in {} is {}", a, a.getClass(), result);
if (result != null) {
result.forEach(r -> resultProcessor.processResult(new PortValuePartEnvelope(r)));
}
return result;
} catch (Exception e) {
LOG.warn("Exception for {} in {}", a, runner.getClass(), e);
resultProcessor.processResult(Progress.failed(ctx.getId(), e));
throw new RuntimeException(e);
}
};
Future<List<PortValuePart>> p = pool.submit(runnerCallable);
} else {
LOG.warn("No runner found for activity {}", a);
resultProcessor.processResult(Progress.failed(ctx.getId(), new RuntimeException("No runner found for activity " + a)));
throw new RuntimeException("No runner found for activity " + a);
}
});
pool.shutdown();
try {
pool.awaitTermination(WAIT_TIME_MILLIS, TimeUnit.MILLISECONDS);
resultProcessor.processResult(Progress.running(ctx.getId(), progressAfterRan));
} catch (InterruptedException e) {
throw new PlatformException("Execution interrupted.");
}
}
Note that ExecutorService.awaitTermination doesn't throw an exception if it times out; it just returns false. If you want to make sure that the next calls don't run concurrently with these ones, you should probably use the return value, and maybe throw an exception (and kill the tasks) if it's taking way too long.
I'm doing something like this:
try {
client.restoreFromClusterSnapshot(req);
} catch (AmazonRedshiftException e) {
txUtils.execute((ts) -> {
redshiftDto.setStatus(ResourceStatus.FAILED);
redshiftDto.setStatusDetails(e.getMessage());
redshiftDto.setUpdatedOn(Timestamp.from(Instant.now()));
this.rdao.merge(redshiftDto);
return null;
});
LOGGER.error("CANNOT START REDSHIFT- " + e.getErrorMessage());
throw new AmazonRedshiftException( "CANNOT START REDSHIFT- "
+ e.getErrorMessage());
}
In this code, I'm not able to set database variable if I'm throwing an error because it is terminating my transaction. If I'll comment that throw it will work and my database value will be set. But I'll not able to throw anything. How can I do both- (throwing and setting value in DB)
What I'd do is make use of the finally clause.
AmazonRedshiftException exception = null;
try {
cluster = client.restoreFromClusterSnapshot(req);
} catch (AmazonRedshiftException e) {
exception = e;
LOGGER.error("CANNOT START REDSHIFT- " + e.getErrorMessage());
throw new AmazonRedshiftException( "CANNOT START REDSHIFT- "
+ e.getErrorMessage());
} finally {
if(exception != null) {
txUtils.execute((ts) -> {
redshiftDto.setStatus(ResourceStatus.FAILED);
redshiftDto.setStatusDetails(exception.getMessage());
redshiftDto.setUpdatedOn(Timestamp.from(Instant.now()));
this.rdao.merge(redshiftDto);
return null;
});
}
}
I have a java app that try to insert a row into the table and com.ibatis.common.jdbc.exception.NestedSQLException is thrown with the Cause com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException
When I try to insert dublicate data for a unique-key constraint.
How do I catch that exception?
To get to the root cause you can do something like this:
try {
//insert
} catch (NestedSQLException e) {
Throwable t = e;
while(t.getCause() != null) {
t = t.getCause();
}
//in your situation, now t should be MySQLIntegrityConstraintViolationException
if (t instanceOf MySQLIntegrityConstraintViolationException) {
//do something
}
}
In case it helps someone. #tibtof's is correct and got me to:
public int insert(MyObject myObject) {
int recCount = -1;
try {
recCount = insert(myObject, MyObjectMapper.class);
} catch (Throwable e) {
Throwable t = e;
while (t.getCause() != null) {
t = t.getCause();
if (t instanceof SQLIntegrityConstraintViolationException) {
// get out gracefully.
recCount = -1;
return recCount;
}
}
//Something else wicked wrong happened.
LogUtils.error(log, e.getMessage(), e);
throw new RuntimeException(e.getMessage(), e);
}
return webGroup.getWebGroupId().intValue();
}