How to eliminate the duplicate try-catch code in similar methods? - java

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
}

Related

How to overwrite custom exception over ValidationException?

I have written some logic and custom validation in Validator initialize method.
But when exception occurs , custom exception was thrown but override by ValidationException
eg. HV000032: Unable to initialize ........
public class CustomValidator implements ConstraintValidator<CustomClass, CharSequence> {
#Override
public void initialize(CustomClass annota) {
try {
//code
} catch (Exception e) {
throw new CustomException("custom error ", e); <-- this exception is override by javax.validation.ValidationException...
}
}
I want to get my custom exception and message . How can I implement that ...
In order to get your custom exception and message, you can catch the ValidationException thrown by the validation framework and extract your custom exception and message from it.
Something like this should work.
public class CustomValidator implements ConstraintValidator<CustomClass, CharSequence> {
#Override
public void initialize(CustomClass annota) {
try {
// code
} catch (ValidationException e) {
/* if an exception is thrown in the initialize method, the validation framework will not execute the isValid method. */
throw new CustomException("validation error", e);
} catch (Exception e) {
throw new CustomException("custom error", e);
}
}
#Override
public boolean isValid(CharSequence value, ConstraintValidatorContext context) {
try {
// validation logic
return true;
} catch (CustomException e) {
// catch and rethrow your custom exception
throw e;
} catch (ValidationException e) {
// catch and extract your custom exception and message
Throwable cause = e.getCause();
if (cause instanceof CustomException) {
CustomException customException = (CustomException) cause;
String message = customException.getMessage();
// do something with customException and message
}
throw e;
}
}
}
the isValid method is the main method used by the validation framework to determine if an object is valid or not, and it is necessary to implement it in order to define the validation logic. Even if an exception is thrown in the initialize method, the isValid method is still necessary and will be executed for valid objects.
That is expected behaviour for the validator. If you want to get other exception type then ValidationException, you can throw ConstraintDeclarationException out of your init method, which was somewhat designed to be used when the constraint declaration is wrong. Any other exceptions are wrapped into ValidationException, where a cause would be a thrown exception. So you could catch ValidationException in a place you are calling the validator and it's failing and then access your exception/message through getCause(). Something along next lines:
try {
validator.validate( object );
}
catch (ValidationException e) {
Throwable cause = e.getCause(); // <- your CustomException
}
Ideally, your initialize method should not throw any exceptions. The same is for the isValid - instead of throwing an exception, return false and a custom message explaining what failed:
#Override
public boolean isValid(CharSequence object, ConstraintValidatorContext constraintContext) {
if ( object == null ) {
return true;
}
boolean isValid = true;
try {
// some potentially failing logic:
}
catch (Exception e) {
isValid = false;
constraintContext.disableDefaultConstraintViolation();
constraintContext.buildConstraintViolationWithTemplate(
e.getMessage()
)
.addConstraintViolation();
}
return isValid;
}

Trouble with unhandled exceptions

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

Handle Exception after all lines have been finished execution without finally

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.

Why does a method require return statement in catch even though catch is re-throwing exception

I have written a method which is returning some value in try statement. Inside catch I am calling handleException which will have conversion logic of understanding the exception and rethrowing new exception. Here handleException is always throwing exception, still the getXYZ() gives compile time error expecting return statement. I am not handling the exception, I am just throwing new exception so why does the method wants return statement.
public String getXYZ(String input) {
try {
return getFromDAO(input);
} catch (Exception e) {
handleException(e);
}
}
private void handleException(Exception e) {
try {
throw e;
} catch(SomeException se) {
throw new MyRuntimeException("MyException message", se);
} catch(SomeOtherException soe) {
throw new MyRuntimeException("MyException message", soe);
}
}
The other version of this method compiles.
public String getXYZ(String input) {
try {
return getFromDAO(input);
} catch (Exception e) {
throw e;
}
}
You are not throwing anything in the catch block, you're calling your handle function, which ultimately will result in a new exception being thrown, but the actual code in getXYZ is doing a function call in catch. What if you change handleException to later not throw an exception in some circumstances, what would getXYZ return then?
One way to solving this is making it clear to the compiler that you expect an exception to be thrown.
public String getXYZ(String input) {
try {
return getFromDAO(input);
} catch (Exception e) {
throw handleException(e); // compiles ok.
}
}
private RuntimeException handleException(Exception e) {
try {
throw e;
} catch(SomeException se) {
return new MyRuntimeException("MyException message", se);
} catch(SomeOtherException soe) {
return new MyRuntimeException("MyException message", soe);
} catch(RuntimeException re) {
return re;
} catch(Exception e2) {
return new MyRuntimeException("MyException message", e2);
}
}
BTW an alternative approach is to not wrap the Exception at all and leave the exception as it was.
public String getXYZ(String input) {
try {
return getFromDAO(input);
} catch (Exception e) {
throw rethrow(e); // compiles ok.
}
}
/**
* Cast a CheckedException as an unchecked one.
*
* #param throwable to cast
* #param <T> the type of the Throwable
* #return this method will never return a Throwable instance, it will just throw it.
* #throws T the throwable as an unchecked throwable
*/
#SuppressWarnings("unchecked")
public static <T extends Throwable> RuntimeException rethrow(Throwable throwable) throws T {
throw (T) throwable; // rely on vacuous cast
}
You may want to consider using the new java 8 lambda features to solve your problem as well. You will have to create a functional interface to declare the signature of the lambdas (with the relevant exceptions). Your handleException method will now be the one who runs the lambda and handles the exceptions.
public String getXYZ(String input) {
return handleKnownExceptions(() -> getFromDAO(input));
}
private <T> T handleKnownExceptions(ThrowingCode<T> throwingCode)
{
try {
return throwingCode.get();
} catch(SomeException se) {
throw new MyRuntimeException("MyException message", se);
} catch(SomeOtherException soe) {
throw new MyRuntimeException("MyException message", soe);
}
}
#FunctionalInterface
public interface ThrowingCode<T>
{
T get() throws SomeException, SomeOtherException;
}
There is a pattern I have seen a few times to handle this situation. You let the handleException method declare that it returns an exception. This is only indicative though, it will never return anything, it will always throw, just as before. The declared return type will allow the caller to use a throw handleException() statement, which will keep the compiler happy. The resulting code will be:
public String getXYZ(String input) throws Exception {
try {
return getFromDAO(input);
} catch (Exception e) {
throw handleException(e);
}
}
/**
* This method will never return normally, always throws.
*/
private Exception handleException(Exception e) throws Exception
{
try {
throw e;
} catch(SomeException se) {
throw new MyRuntimeException("MyException message", se);
} catch(SomeOtherException soe) {
throw new MyRuntimeException("MyException message", soe);
}
}

Exceptions works correct but not how its must

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 :>

Categories

Resources