I need methodA2 also gets executed even though there is an exception by methodA1(). Here I have added only two methods as methodA1() and methodA2(). Let's say there are many methods. In that case also, the solution should be able to applicable.
class A {
String methodA1() throws ExceptionE {
// do something
}
String methodA2() throws ExceptionE {
// do something
}
}
class C extends A {
String methodC() throws ExceptionE2 {
try {
methodA1();
methodA2();
} catch (ExceptionE e) {
throw new ExceptionE2();
}
}
}
Please note that there can be many methods invoked with methodA1, methodA2. In that case having multiple try, catch, finally will look ugly.. So are there any other methods to do that?
I need to store error information in a log file. In methodA1(), methodA2() ... information in each tag is get validated. what I want is having all the error information in log file. Once exception throws it will generate log file. So I will miss validation information from other tags. So we can't go for finally approach.
You can use a loop with Java 8 lambdas:
interface RunnableE {
void run() throws Exception;
}
class Example {
public static void main(String[] args) {
List<RunnableE> methods = Arrays.asList(
() -> methodA1(),
() -> methodA2(),
() -> methodA3()
);
for (RunnableE method : methods) {
try {
method.run();
} catch (Exception e) {
// log the exception
}
}
}
private static void methodA1() throws Exception {
System.out.println("A1");
}
private static void methodA2() throws Exception {
System.out.println("A2");
}
private static void methodA3() throws Exception {
System.out.println("A3");
}
}
Please note that the interface is needed only when methods throw checked exception. If they were throwing only runtime exceptions, you could use java.lang.Runnable instead.
No other way. If each method can throw exception, but you want to continue execution of remaining methods anyway, then each method call must be in its own try-catch block.
Example:
List<Exception> exceptions = new ArrayList<>();
try {
methodA1();
} catch (Exception e) {
exceptions.add(e);
}
try {
methodA2();
} catch (Exception e) {
exceptions.add(e);
}
try {
methodA3();
} catch (Exception e) {
exceptions.add(e);
}
if (! exceptions.isEmpty()) {
if (exceptions.size() == 1)
throw exceptions.get(0);
throw new CompoundException(exceptions);
}
You will of course have to implement the CompoundException yourself.
Related
I have two methods. Method A calls method B. I cannot change the exceptions of neither (homework demands). However, the 2 exceptions mean the exact same thing, so when I call method B on A, I already know that B's exception is not getting thrown. However, I still get the "unhandled exception" error from Eclipse. How can I avoid it?
Here are the methods
public void createProfile(Profile user) throws PEException {
Vector<Profile> p = new Vector<Perfil>();
try{
if (repository.search(user.getUsername()) == null) {
repository.register(user); //error on this line when I call the method on main
}
else {
throw new PEException(user.getUsername());
}
} catch (PEException e){
e.printStackTrace();
}
}
public void register(Profile user) throws UJCException {
try {
if (this.search(user.getUsername()) == null) {
this.users.add(user);
}
else {
throw new UJCException(user.getUsername());
}
} catch (UJCException e) {
e.printStackTrace();
}
}
I MUST NOT change the definitions of the methods (I can't throw UJCException on createProfile). Thanks in advance
You shouldn't be throwing the exceptions and then catching them inside the same method. That defeats the purpose of throwing the exception in the first place. the methods which calls your 2 methods should expect nothing (void) or the exception in the event that something went wrong. Make sure your methods createProfile() and register() can actually throw their exception so methods calling them can catch the exception and do whatever it is they need to when the exception is thrown.
public void createProfile(Profile user) throws PEException {
Vector<Profile> p = new Vector<Perfil>(); //not being used...
if (repository.search(user.getUsername()) == null) {
try{
repository.register(user);
}catch(UJCException e){
e.printStackTrace();
throw new PEException(user.getUsername());
}
}
else {
throw new PEException(user.getUsername());
}
}
public void register(Profile user) throws UJCException
{
if (this.search(user.getUsername()) == null) {
this.users.add(user);
}
else {
throw new UJCException(user.getUsername());
}
}
Now when you call these methods wrap the call in a try catch and catch the appropriate exception depending on which method was called
I have the following insert/update methods in my service:
#Override
public void insertEntity(Entity entity) {
try {
entityDao.insert(entityMapper.entityToEntityDO(entity));
} catch (DataIntegrityViolationException ex){
if(ex.getCause() instanceof SQLIntegrityConstraintViolationException) {
SQLIntegrityConstraintViolationException violationEx = (SQLIntegrityConstraintViolationException) ex.getCause();
if(violationEx.getErrorCode() == 1048 && "23000".equals(violationEx.getSQLState())) {
throw new FieldCannotBeNullException(violationEx.getMessage());
}
}
throw ex;
}
}
#Override
public void updateEntity(Entity entity) {
try {
entityDao.update(entityMapper.entityToEntityDO(entity));
} catch (DataIntegrityViolationException ex){
if(ex.getCause() instanceof SQLIntegrityConstraintViolationException) {
SQLIntegrityConstraintViolationException violationEx = (SQLIntegrityConstraintViolationException) ex.getCause();
if(violationEx.getErrorCode() == 1048 && "23000".equals(violationEx.getSQLState())) {
throw new FieldCannotBeNullException(violationEx.getMessage());
}
}
throw ex;
}
}
As you can see, the actual logic of insertEntity and updateEntity is very simple. In order to throw a custom Exception, I did some database error code check. Since the two methods all need this kind of checking, the code duplicated in both methods, which is obviously a code smell.
How can I eliminate this kind of code duplication?
Extract the common catch-block to a method which throws DataIntegrityViolationException.
You can create Interface like this:
public interface ConsumerWithException<T, V extends Exception> {
/**
* Performs this operation on the given argument.
*
* #param t the input argument
*/
void accept(T t) throws V;
}
Use it a private method like:
private void action(ConsumerWithException<Entity, DataIntegrityViolationException> doAction, Entity entity){
try {
doAction.accept(entity);
} catch (DataIntegrityViolationException ex){
if(ex.getCause() instanceof SQLIntegrityConstraintViolationException) {
SQLIntegrityConstraintViolationException violationEx = (SQLIntegrityConstraintViolationException) ex.getCause();
if(violationEx.getErrorCode() == 1048 && "23000".equals(violationEx.getSQLState())) {
throw new FieldCannotBeNullException(violationEx.getMessage());
}
}
throw ex;
}
}
You can put the code inside the catch block into a separate method.
Alternatively, You can catch Exception and write a handler method to handle the exceptions if in future you expect to handle multiple exceptions there.
You can declare your methods to throw the exception, then try/catch in one place where your methods are called. For example:
public void insertEntity(Entity entity) throws DataIntegrityViolationException {}
public void updateEntity(Entity entity) throws DataIntegrityViolationException {}
try {
insertEntity(entity);
updateEntity(entity);
catch (DataIntegrityViolationException e) {
// handle exception
}
Here's the code.
public class TestTest {
public static void main (String[] args) throws Exception {
try {
run();
} catch(Exception e) {
printSuppressedExceptions(e);
}
}
public static void printSuppressedExceptions(Throwable t) {
System.out.println(t);
System.out.println("suppressed exceptions: " + t.getSuppressed().length);
}
public static void run() throws Exception {
try(MyResource r = new MyResource("resource");) {
System.out.println("try");
System.getProperty("").length(); // throws illegalArgumentException
} catch(Exception e) {
printSuppressedExceptions(e);
throw e;
} finally {
new MyResource("finally").close();
}
}
}
class MyResource implements AutoCloseable {
private final String name;
public MyResource(String name) {
this.name = name;
}
#Override
public void close() throws Exception {
throw new Exception("exception" + " from " + this.name);
}
}
Since exception thrown from try block suppressed the exception from resource, I got "suppressed exceptions: 1" at first which was understandable. But when an exception was thrown from finally, it seemed like all suppressed exceptions disappeared because I got "java.lang.Exception: exception from finally" followed by "suppressed exceptions: 0" which I think it should be 1.
I browsed the Java tutorials and it definitely says
However, in this example, if the methods readLine and close both throw exceptions, then the method readFirstLineFromFileWithFinallyBlock throws the exception thrown from the finally block; the exception thrown from the try block is suppressed.
From The try-with-resources Statement
How could it happen?
Here is code that does what you would expect:
public class TestTest {
public static void main (String[] args) throws Exception {
try {
run();
} catch(Exception e) {
printSuppressedExceptions(e);
}
}
public static void printSuppressedExceptions(Throwable t) {
System.out.println(t);
System.out.println("suppressed exceptions (" + t.getSuppressed().length + "):");
for (Throwable suppressed : t.getSuppressed()) {
System.out.println(" - " + suppressed);
}
}
public static void run() throws Exception {
Exception exceptionFromCatch = null;
try(MyResource r = new MyResource("resource");) {
System.out.println("try");
System.getProperty("").length(); // throws illegalArgumentException
} catch(Exception e) {
exceptionFromCatch = e;
printSuppressedExceptions(e);
throw e;
} finally {
try {
new MyResource("finally").close();
} catch (Exception e) {
if (exceptionFromCatch!=null) {
e.addSuppressed(exceptionFromCatch);
}
throw e;
}
}
}
}
class MyResource implements AutoCloseable {
private final String name;
public MyResource(String name) {
this.name = name;
}
#Override
public void close() throws Exception {
throw new Exception("exception" + " from " + this.name);
}
}
So lets go trough the try-with-resource part of your code (as introduced in JDK 1.7.0) and see what happens (see What is the Java 7 try-with-resources bytecode equivalent using try-catch-finally? for more details):
the try-with-resource block MyResource r = new MyResource("resource") is executed
the try block is executed and throws an IllegalArgumentException
the try-with-resource block calls close() for all resources (in your example only one)
close() throws an exception, but since the exception from the try block has priority the exception from thrown by close() is suppressed and added via addSuppressed(..)
So that part works like you expected from reading the tutorial.
And now the try-catch-finally part of your code (as in JDK 1.6 and earlier):
the try block is executed and throws an IllegalArgumentException
(the catch block behaves the same way as if there was no catch block)
the finally block is executed and throws an Exception
the exception from the finally block has priority and the one from the try block is suppressed
But this time the word suppressed used in the java tutorial does not stand for "suppressed and added to the actually thrown exception" but "suppressed and lost to nirvana". So it still behaves as in JDK 1.6 and earlier and does not make use of the newly introduced addSuppressed(..) getSuppressed() functionality. That's the reason it doesn't behave like you expected.
I would argue the behaviour you expected wouldn't be logical either. I would like it to behave like this:
...
} finally {
try {
new MyResource("finally").close();
} catch (Exception e) {
if (exceptionFromCatch!=null) {
exceptionFromCatch.addSuppressed(e);
} else {
throw e;
}
}
}
...
That would always give priority to the exception from the try block (as implemented with the new try-with-resource feature) and add the exception from the catch block as suppressed to the list. But that would break compatibility with JDK 1.6, so I guess that's the reason why it doesn't behave like that.
The method processExceptions() should call the method BEAN.methodThrowExceptions and handle exceptions:
1.1. if an exception FileSystemException occurs, then log it by calling the method BEAN.log and throw forward
1.2. if an exception CharConversionException or any other IOException occurs, just log it by calling the method BEAN.log
Add the class/type of the exception you are forwarding in 2.1. to the processExceptions() method signature.
Handle the remaining exception in the method main() and log it. Use try..catch
I tried different solutions. It works but not as it should. What is the correct placement of throws in methods. Or maybe i shouldnt use them at all? And if I don't place them I can't make use of throw. Please help, I would really appreciate your time.
public class Solution {
public static StatelessBean BEAN = new StatelessBean();
public static void main(String[] args) {
try{
processExceptions();
}
catch (CharConversionException e){
BEAN.log(e);
}
}
public static void processExceptions()throws CharConversionException {
try{
BEAN.methodThrowExceptions();
}
catch (CharConversionException e){
BEAN.log(e);
throw e;
}
catch (FileSystemException e){
BEAN.log(e);
}
catch (IOException e){
BEAN.log(e);
}
}
public static class StatelessBean {
public void log(Exception exception) {
System.out.println(exception.getMessage() + ", " + exception.getClass().getSimpleName());
}
public void methodThrowExceptions() throws CharConversionException, FileSystemException, IOException {
int i = (int) (Math.random() * 3);
if (i == 0)
throw new CharConversionException();
if (i == 1)
throw new FileSystemException("");
if (i == 2)
throw new IOException();
}
}
}
If a method is capable of throwing an exception which IS NOT RuntimeException (either directly throwing or invoking a method which can throw an exception), it should either handle the exception or declare that it throws the exception, so that any other method which calls this method would know that it can encounter an exception and can either handle it or declare it that it throws (and so on).
Since you are dealing with checked exception, there is no clean way to avoid declaring throws, but there is a (messy) workaround. You can wrap the exception in a RuntimeException and can throw it and when you want to handle it, you can get the actual exception from the re.getCause();
public class Solution {
public static StatelessBean BEAN = new StatelessBean();
public static void main(String[] args) {
try{
processExceptions();
}
catch (RuntimeException re){
if (!(re.getCause() instanceof CharConversationException)) {
//handle the case in which the exception was not CCE and not FSE not IOException
}
}
}
public static void processExceptions() {
try{
BEAN.methodThrowExceptions();
} catch (CharConversionException cce){
BEAN.log(e);
throw new RuntimeException(cce);
} catch (FileSystemException fse){
BEAN.log(e);
} catch (IOException e){
BEAN.log(e);
}
}
public static class StatelessBean {
public void log(Exception exception) {
System.out.println(exception.getMessage() + ", " + exception.getClass().getSimpleName());
}
public void methodThrowExceptions() throws CharConversionException, FileSystemException, IOException {
int i = (int) (Math.random() * 3);
if (i == 0)
throw new CharConversionException();
if (i == 1)
throw new FileSystemException("");
if (i == 2)
throw new IOException();
}
}
}
I am not sure whether I understood your question correctly and this is what you wanted :)
I think that the order:
Handle the remaining exception in the method main()
means that you should catch not only CharConversionException, but all other Exceptions by:
catch (Exception e)
Besides, you should ask it on help.javarush.net I think :>
Example (<Expected Exception> for assert 1 & assert 2 is same) :
#junit.framework.Test // or #org.testng.annotations.Test
public void testCase() {
try {
// assert 1
fail();
} catch (<Expected Exception>) {
}
try {
// assert 2
fail();
} catch (<Expected Exception>) {
}
}
If you're feeling adventurous, you can also try out assertThrows:
https://github.com/dsaff/junit.contrib
Feel free to ask if you have any problems.
If it's too hard to break this up into individual test methods, here's what's worked for me in the past.
Create a method expectsException() that expects a Callback.
interface Callback {
void call() throws Exception;
}
void expectsException(Callback callback) {
try {
callback.call();
fail("ExpectedException was not thrown!");
} catch (Exception e) {
if (!(e instanceof ExpectedException)) {
fail("Expecting ExpectedException, got " + e.getClass());
}
assertEquals("Expected exception message", e.getMessage());
}
}
Then, wrap up the code inside your try {...} catch blocks in the Callback:
#Test
public void testSomething() {
expectsException(new Callback() {
public void call() throws Exception {
// assert 1
}
});
expectsException(new Callback() {
public void call() throws Exception {
// assert 2
}
});
}
Note however, that depending on what you're doing in the catch block, this may or may not end up less verbose than a straightforward try {...} catch.
(When Java gets proper closures, then this approach will make a lot more sense.)
You should probably break your method into two separate methods that will each throw:
#Test(expectedExceptions = NullPointerException.class)
public void testCase1() {
// assert 1
}
#Test(expectedExceptions = NullPointerException.class)
public void testCase2() {
// assert 2
}
catch-exception might help:
public void testCase() {
// assert 1
verifyException(obj, MyException.class).do(1);
// assert 2
verifyException(obj, MyException.class).do(2);
}