Factory pattern for creating exceptions dynamically

I threw an Exception xml and dynamically throws and throws an exception.

<exception-mappings> <exception-mapping key="exceptionkey1"> <class-name>com.package.CheckedException</class-name> <message>Checked Exception Message</message> </exception-mapping> <exception-mapping key="exceptionkey2"> <class-name>com.package.UnCheckedException</class-name> <message>UnChecked Exception Message</message> </exception-mapping> 

I create an exception object dynamically using reflection depending on the exception key.

 public static void throwException(final String key) throws CheckedException, UncheckedException { ExceptionMapping exceptionMapping = exceptionMappings.getExceptionMappings().get(key); if (exceptionMapping != null) { try { Class exceptionClass = Class.forName(exceptionMapping.getClassName()); try { throw ()exceptionClass.newInstance(); // line X } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } } 

I want to know which class is for typecast on line X, so I don't need to use If / else. The reason I donโ€™t want to use, if there is still, itโ€™s possible that new classes may be added in the future, and I donโ€™t want to change this code every time a new exception is added.

My basic logic is my service level, which throws either CheckedException or UncheckedException. If a CheckedException is thrown, it will be handled by my web layer. Also, I cannot select Super parent class Exception or Throwable, since my web tier is catching a CheckedException. If a UncheckedException is thrown, an exception page will be displayed.

Please help me as I cannot continue any further.

EDIT: any other decision has also been made.

+8
java exception-handling factory-pattern
source share
6 answers

Well, in the name of science, here is how you can do it. Would I recommend doing this? In no case. Can I ever do something like this remotely? Probably not.

 public class ExceptionFactory { public static void throwException(String className) throws CheckedException, UncheckedException { Class<?> exceptionClass; try { exceptionClass = Class.forName(className); } catch (ClassNotFoundException e) { throw new IllegalArgumentException(e); } try { if (CheckedException.class.isAssignableFrom(exceptionClass)) { throw exceptionClass.asSubclass(CheckedException.class) .newInstance(); } else if (UncheckedException.class .isAssignableFrom(exceptionClass)) { throw exceptionClass.asSubclass(UncheckedException.class) .newInstance(); } else { throw new IllegalArgumentException( "Not a valid exception type: " + exceptionClass.getName()); } } catch (InstantiationException | IllegalAccessException e) { throw new IllegalStateException(e); } } public static void main(String... args) { try { throwException("CheckedException"); } catch (CheckedException e) { System.out.println(e); } catch (UncheckedException e) { System.out.println(e); } } } class CheckedException extends Exception { } class UncheckedException extends Exception { } 
+11
source share

I do not see the point in this factory. Even if you earn it (which you can, having all the exceptions thrown by subclasses of one class of ancestors), its use will be something like this:

 .... if (somethingInWrong) { ExceptionFactory.throwException("SomeKey"); } .... 

For each key, you still need to create an exception class to map to it. Let's say SomeKeyException is the exception that is displayed in "SomeKey".

In this case, itโ€™s much safer to just write:

 .... if (somethingInWrong) { throw new SomeKeyException(); } .... 

Thus, the compiler verifies that you are creating an exception class that it really knows. If you use Factory, you can use some string that is not a valid key, and the compiler cannot do anything about it. Only at runtime, your Factory will not be able to find an exception associated with an invalid key.

+2
source share

A few settings:

 public static void throwException(final String key) throws Throwable { ExceptionMapping exceptionMapping = exceptionMappings.getExceptionMappings().get(key); if (exceptionMapping != null) { try { Class<Throwable> exceptionClass = (Class<Throwable>)Class.forName(exceptionMapping.getClassName()); try { throw exceptionClass.cast( exceptionClass.newInstance() ); // line X } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } } 
+2
source share

There is no need to use reflection (as I said above, you should not use reflection unless you really need to ... ).

You can implement the exception class as something like this:

 class MyExceptions { static void myExceptionsThrower(String key) throws Exception { if("illegalstate".equals(key)) { throw new IllegalStateException("that my IllegalStateException bro!"); } else if("illegalaccess".equals(key)) { throw new IllegalAccessException("that my IllegalAccessException bro!"); } // etc... } } 

and use it with:

 MyExceptions.myExceptionsThrower(key); 
+1
source share

Here is my entry in this derby. :-)

Other answers commented on whether this is a reasonable design. I will throw these issues aside this answer.

A few of my pets are unnecessary warnings (even if they are suppressed), and exceptions that do not indicate what actually went wrong. In particular, simply listing the stack trace is usually not enough. Yes, this is just a test code, but when working with such code - even code designed to throw an exception - you really need to think about how to deal with errors. In this case, I decided to introduce such errors as instances of InternalError , as the configuration or something else may be wrong in different ways. In particular: if a class cannot be found, if it is found, but is not a subtype of CheckedException or UncheckedException (or even a regular class), or if it does not have a no-arg constructor, or if it is not available.

Another problem with some of the proposed solutions is that if the name of the exception class is "java.lang.InstantiationException" (or one of the other exceptions thrown from the outside), an instance of this type of exception can be thrown, thrown, and then caught inside. the result is a stack trace, but does not actually throw the requested exception. I avoided this by linearizing logic rather than nested try-catch blocks.

Finally, I pulled the code that generated the exception into a separate method so that it could be used for both verified and unverified cases. This can be greatly simplified if you change the hierarchy of exceptions to allow the exclusion of only one root (I recommend not marking) and have exception subtypes that are processed at the web level or sent to the caller.

 static void throwException(final String exClassName) throws CheckedException, UncheckedException { Class<?> clazz; try { clazz = Class.forName(exClassName); } catch (ClassNotFoundException cnfe) { throw new InternalError(exClassName, cnfe); } if (CheckedException.class.isAssignableFrom(clazz)) { throw newException(clazz.asSubclass(CheckedException.class)); } else if (UncheckedException.class.isAssignableFrom(clazz)) { throw newException(clazz.asSubclass(UncheckedException.class)); } else { throw new InternalError(exClassName + " is not a valid exception"); } } static <X extends Throwable> X newException(Class<X> clazz) { X x; try { x = clazz.newInstance(); } catch (InstantiationException|IllegalAccessException e) { throw new InternalError("creating instance of " + clazz, e); } return x; } 
+1
source share

This can be useful for creating a custom precondition exception to avoid multiple if conditions . Throws a precondition exception when checking for a null pointer.

 class Preconditions { /** * <p> * Checks the value to be null and if null throws a new Exception with the message given. * Used to reduce checking if conditions for complexity. * </p> * @param val - val to check null * @param exceptionClass - exception class to be thrown * @param args - message to be called for throwing exception * @throws Throwable - Common Throwable Exception. */ public static void checkNotNull(final Object val, final Class<?> exceptionClass, final Object ...args) throws Throwable { Class<?>[] argTypes = new Class<?>[args.length]; Arrays.stream(args).map(WithIndex.indexed()).forEach(arg ->argTypes[arg.index()] = arg.value().getClass()); if (null == val) throw (Throwable) exceptionClass.getConstructor(argTypes).newInstance(args); } } 

Then you can use it in code with:

  PreConditionUtil.checkNotNull(objectToCheck, CustomException.class, ErrorCode, "your error message", ...); 
0
source share

All Articles