I am writing a parser for csv-files, and sometimes I get NumberFormatException. Is there an easy way to print the argument value that caused the exception?
For the moment do I have many try-catch blocks that look like this:
String ean;
String price;
try {
builder.ean(Long.parseLong(ean));
} catch (NumberFormatException e) {
System.out.println("EAN: " + ean);
e.printStackTrace();
}
try {
builder.price(new BigDecimal(price));
} catch (NumberFormatException e) {
System.out.println("Price: " + price);
e.printStackTrace();
}
I would like to be able to write something like:
try {
builder.ean(Long.parseLong(ean));
} catch (NumberFormatException e) {
e.printMethod(); // Long.parseLong()
e.printArgument(); // should print the string ean "99013241.23"
e.printStackTrace();
}
Is there any way that I at least can improve my code? And do this kind of printing/logging more programmatically?
UPDATE: I tried to implement what Joachim Sauer answered, but I don't know if I got everything right or if I could improve it. Please give me some feedback. Here is my code:
public class TrackException extends NumberFormatException {
private final String arg;
private final String method;
public TrackException (String arg, String method) {
this.arg = arg;
this.method = method;
}
public void printArg() {
System.err.println("Argument: " + arg);
}
public void printMethod() {
System.err.println("Method: " + method);
}
}
The Wrapper class:
import java.math.BigDecimal;
public class TrackEx {
public static Long parseLong(String arg) throws TrackException {
try {
return Long.parseLong(arg);
} catch (NumberFormatException e) {
throw new TrackException(arg, "Long.parseLong");
}
}
public static BigDecimal createBigDecimal(String arg) throws TrackException {
try {
return new BigDecimal(arg);
} catch (NumberFormatException e) {
throw new TrackException(arg, "BigDecimal.<init>");
}
}
}
Example of use:
try {
builder.ean(TrackEx.createBigDecimal(ean));
builder.price(TrackEx.createBigDecimal(price));
} catch (TrackException e) {
e.printArg();
e.printMethod();
}
EDIT: Same question but for .NET: In a .net Exception how to get a stacktrace with argument values
You can easily implement such detailed information on custom-written exceptions, but most existing exceptions don't provide much more than a detail message and a causing exception.
For example you could wrap all your number parsing needs into a utility class that catches the NumberFormatException and throws a custom exception instead (possibly extending NumberFormatException).
An example where the some additional information is carried via the exception is SQLException which has
a getErrorCode() and a getSQLState() method.
Create a method such as private parse (String value, int type) which does the actual parsing work including exception handling and logging.
parse(ean, TYPE_LONG);
parse(price, TYPE_BIG_DECIMAL);
Where TYPE_ is just something to tell the method how it should parse the value.
Similar to another suggestion, you could extract Long.parseLong(ean) into it's own method (either privately within the class or public on another utility sort of class).
This new method would handle any custom logic AND you could test it in isolation. Yay!
Related
I have a Spring Boot application that has the following approximate structure:
project
Api
ApiImpl
Application
Api is an interface that looks like this:
public interface Api {
public String methodOne(...) throws ExceptionOne, ExceptionTwo, ExceptionThree;
...
public int methodN(...) throws ExceptionOne, ExceptionThree, ExceptionFour;
}
ApiImpls is the request controller (in reality there is a second layer, but this should suffice for this example). There, I do something like the following right now:
#Controller
public class ApiImpl {
public String methodOne(...) {
try {
// do stuff that can yield an exception
}
catch(ExceptionOne e) {
// set proper response code and return values
}
catch(ExceptionTwo e) {
// set proper response code and return values
}
catch(ExceptionThree e) {
// set proper response code and return values
}
}
}
Basically, this behaviour yields a lot of repetition (might as well name my exceptions D, R, and Y...), but is otherwise very suited to handling the internal application logic.
My question is: How can I implement a custom Exception Dispatcher that would handle this in Java? Ideally, I would want something like this answer here, but unfortunately simply throwing the current exception like in that C++ code is not possible in Java, as far as I know. For brevity, what I would like to accomplish is something like the following:
#Controller
public class ApiImpl {
public String methodOne(...) {
try {
// do stuff that can yield an exception
}
catch(ExceptionOne e) {
handle()
}
}
private void handle() { // maybe Throwable or Exception subclass as parameter
// handle the correct exception type, set correct response code, etc.
}
}
Are there any good approaches to doing this so as to minimize code repetition?
Here is a preliminary attempt I tried to get this working:
public class Thrower {
public Thrower(int e) throws ExceptionOne, ExceptionTwo, ExceptionThree {
if(e == 0) {
throw new ExceptionOne();
}
if(e == 1) {
throw new ExceptionTwo();
}
if(e == 2) {
throw new ExceptionThree();
}
}
}
class ExceptionOne extends Exception {}
class ExceptionTwo extends Exception {}
class ExceptionThree extends Exception {}
public class ExceptionHandler {
private void handle(Exception ex) throws Exception {
try {
throw ex;
}
catch(ExceptionOne e) {
e.printStackTrace();
System.out.println("Exception one");
}
catch(ExceptionTwo e) {
e.printStackTrace();
System.out.println("Exception two");
}
catch(ExceptionThree e) {
e.printStackTrace();
System.out.println("Exception three");
}
}
public void causesException(int which) throws Throwable {
try {
Thrower t = new Thrower(which);
}
catch(Exception e) {
handle(e);
}
}
public static void main(String[] args) throws Throwable {
ExceptionHandler eh = new ExceptionHandler();
eh.causesException(0);
eh.causesException(1);
eh.causesException(2);
}
}
This works as expected, and I can handle the different exception types as needed (shown here using a constructor, but the principle would be the same). However, this feels extremely clunky.
If you are looking for globally handling all Controller Layer exceptions (in Spring MVC architecture), you can do that at one place for all controllers (option1 below) by using #ExceptionHandler methods which is a ControllerAdvice from Spring.
Option(1): Configure Exceptions in Separate Class
#ControllerAdvice
class MyProjectExceptionHandler {
#ExceptionHandler(value = ExceptionOne.class)
public R exceptionOne(ExceptionOne exe) {
//set proper response code and return values
}
#ExceptionHandler(value = ExceptionTwo.class)
public R exceptionTwo(ExceptionTwo exe) {
//set proper response code and return values
}
}
Option(2): Configure Exceptions in Controller Class itself
If you are looking for handling the exceptions within the Controller class itself, then you can do that as below:
#Controller
public class ApiImpl {
public String methodOne(...) {
}
#ExceptionHandler(ExceptionOne.class)
public R exceptionTwo(ExceptionOne exe) {
//set proper response code and return values
}
//other exceptions
}
You can look more on this at here
I would like to annotate some of my test cases with KnownFault - which would do pretty much what expectedException does plus some magic using YouTrack's REST API. I would also like to have an IntermittentFailure attribute which would mean that I'm aware that the test might occasionally fail with [exception] [message] but I wouldn't want this to block the rest of my build chain.
After some research I found that my test class should implement IHookable, then I could have something like this:
#Override
public void run(IHookCallBack callBack, ITestResult result) {
callBack.runTestMethod(result);
if (result.getThrowable().getCause() instanceof IllegalArgumentException){
System.out.println("This is expected.");
result.setThrowable(null);
}
else{
System.out.println("Unexpected exception");
}
}
The problem with this is the actual implementation of invokeHookable:
final Throwable[] error = new Throwable[1];
IHookCallBack callback = new IHookCallBack() {
#Override
public void runTestMethod(ITestResult tr) {
try {
invokeMethod(thisMethod, testInstance, parameters);
} catch (Throwable t) {
error[0] = t;
tr.setThrowable(t); // make Throwable available to IHookable
}
}
#Override
public Object[] getParameters() {
return parameters;
}
};
hookable.run(callback, testResult);
if (error[0] != null) {
throw error[0];
}
Unfortunately that last line means that my test case is going to throw an exception no matter what as the error array is completely out of my hands in the run method.
So, what would be the proper way of intercepting an exception and handling it the way I want to?
What you are trying to do is really interesting. You should try to propose changes on https://github.com/cbeust/testng/pull/
But maybe IHookable is not the best listener you can use. Did you try IInvokedMethodListener?
void afterInvocation(IInvokedMethod method, ITestResult result) {
if (result.getThrowable().getCause() instanceof IllegalArgumentException) {
System.out.println("This is expected.");
result.setThrowable(null);
result.setStatus(SUCCESS); // If you want to change the status
} else {
System.out.println("Unexpected exception");
}
}
I'm having a small issue with my java code.
public class test {
static char[] pass = getMac(); // getting error on this line
public static char[] getMac() throws UnknownHostException
{
...code...
return x;
}
}
I am already throwing the exception in the method but i'm getting the error on this line too :
static char[] pass = getMac(); // getting error on this line
unhandled Exception Type : unknownHostException
is there any way to fix this ?
Thanks
I have tried :
try
{
static char[] pass = getMac();
}
catch (UnknownHostException e)
{
.....
}
but it doesn't work in the main class .
I am already throwing the exception in the method...
Right. That's the problem. By saying that the method throws that exception, you're forcing the calling code to handle it. Java's class initialization code isn't going to handle it for you, so you're getting an unhandled exception error.
Either handle it in the method, or defer initializing that static field until a time when you can handle it*. Note that static initializer blocks are allowed to include flow logic, so that's also an option.
Handling it in the method:
public static char[] getMac()
{
try {
// ...
return x;
}
catch (UnknownHostException e) {
// Appropriate handling
return null; // Or whatever's appropriate
}
}
Using a static initializer block:
public class test {
static char[] pass;
static {
try {
// ...
pass = x;
}
catch (UnknownHostException e) {
// Appropriate handling
pass = null; // Or whatever's appropriate
}
}
}
When I received an exception such as IOException or RunTimeException, I can only know the line number in the class.
First of my question. Is it possible to retrieve the method name through exception?
Second, is it possible to retrieve the method and the parameter of this method by line number?
p.s. I need to know the exact method name and its parameters, because I want to distinguish the overloading methods. To distinguish overloading methods, all that I know is to determine its parameters.
try{
//your code here}
catch(Exception e){
for (StackTraceElement st : e.getStackTrace())
{
System.out.println("Class: " + st.getClassName() + " Method : "
+ st.getMethodName() + " line : " + st.getLineNumber());
}
}
as you can see in the code above, you can get the stackTrace and loop over it to get all the method names and line numbers, refer to this for more info http://download.oracle.com/javase/1.4.2/docs/api/java/lang/StackTraceElement.html
If you look at the stacktrace you can know in which line the error occurred.
When using an overriden method you get the exact class name, source file and line number, you just have to know how to read it.
From that page:
java.lang.NullPointerException
at MyClass.mash(MyClass.java:9) //<--- HERE!!!!
at MyClass.crunch(MyClass.java:6)
at MyClass.main(MyClass.java:3)
This says, the problem occurred in line 9 of file MyClass.java in the method mash, which was in turn invoked by the method crunch at line 6 of the same file which was invoked by main in line 3 of the same file.
Heres the source code:
class MyClass {
public static void main(String[] args) {
crunch(null); // line 3
}
static void crunch(int[] a) {
mash(a); // line 6
}
static void mash(int[] b) {
System.out.println(b[0]);//line 9, method mash.
}
}
Basically you just have to ... well read it!
Stacktraces are a bit hard to grasp the first time, but later they become a very powerful tool.
I hope this helps.
pass it the exception and it will print the parameter types of the methods along with the exception
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
public class Main
{
public static void main(String[] args)
{
new Main().run();
}
public void run(){
try
{
new Car().run(60, "Casino");
}
catch (Exception e)
{
detailedException(e);
}
try
{
new Engine().run(10);
}
catch (Exception e)
{
detailedException(e);
}
}
public void detailedException(Exception e)
{
try
{
StringBuilder buffer = new StringBuilder(e.getClass().getName()).append(" \"").append(e.getMessage()).append("\"\n");
for (var trace: e.getStackTrace())
{
buffer.append("\tat ").append(trace.getClassName()).append(".").append(trace.getMethodName()).append("(").append(trace.getFileName()).append(":").append(trace.getLineNumber()).append(")[");
Class<?> clazz = Class.forName(trace.getClassName());
ArrayList<Method> methods = new ArrayList<>(Arrays.asList(clazz.getMethods()));
methods.removeIf(m -> !m.getName().equals(trace.getMethodName()));
Method method = methods.get(0);
for (var param: method.getParameters())
{
buffer.append(param.getName()).append(":").append(param.getParameterizedType().getTypeName()).append(", ");
}
buffer.append("]->").append(method.getGenericReturnType().getTypeName()).append("\n");
}
System.err.println(buffer);
}
catch (Exception parseFailed){
e.printStackTrace();
}
}
}
class Car extends Engine
{
public void run(int when, String where) throws Exception
{
super.run(25);
}
}
class Engine
{
public String run(int For) throws Exception
{
throw new Exception("need more fuel");
}
}
There are some task that should't be done in parallel, (for example opening a file, reading, writing, and closing, there is an order on that...)
But... Some task are more like a shoping list, I mean they could have a desirable order but it's not a must..example in communication or loading independient drivers etc..
For that kind of tasks,
I would like to know a java best practice or pattern for manage exceptions..
The java simple way is:
getUFO {
try {
loadSoundDriver();
loadUsbDriver();
loadAlienDetectorDriver();
loadKeyboardDriver();
} catch (loadSoundDriverFailed) {
doSomethingA;
} catch (loadUsbDriverFailed) {
doSomethingB;
} catch (loadAlienDetectorDriverFailed) {
doSomethingC;
} catch (loadKeyboardDriverFailed) {
doSomethingD;
}
}
But what about having an exception in one of the actions but wanting to
try with the next ones??
I've thought this approach, but don't seem to be a good use for exceptions
I don't know if it works, doesn't matter, it's really awful!!
getUFO {
Exception ex=null;
try {
try{ loadSoundDriver();
}catch (Exception e) { ex=e; }
try{ loadUsbDriver();
}catch (Exception e) { ex=e; }
try{ loadAlienDetectorDriver();
}catch (Exception e) { ex=e; }
try{ loadKeyboardDriver()
}catch (Exception e) { ex=e; }
if(ex!=null)
{ throw ex;
}
} catch (loadSoundDriverFailed) {
doSomethingA;
} catch (loadUsbDriverFailed) {
doSomethingB;
} catch (loadAlienDetectorDriverFailed) {
doSomethingC;
} catch (loadKeyboardDriverFailed) {
doSomethingD;
}
}
seems not complicated to find a better practice for doing that.. I still didn't
thanks for any advice
Consider the execute around idiom.
Another option (which isn't really all that different, it just decouples them more) is to do each task in a separate thread.
Edit:
Here is the kind of thing I have in mind:
public interface LoadableDriver {
public String getName();
public void loadDriver() throws DriverException;
public void onError(Throwable e);
}
public class DriverLoader {
private Map<String, Exception> errors = new HashMap<String, Exception>();
public void load(LoadableDriver driver) {
try {
driver.loadDriver();
} catch (DriverException e) {
errors.put(driver.getName(), e);
driver.onError(e);
}
}
public Map<String, Exception> getErrors() { return errors; }
}
public class Main {
public void loadDrivers() {
DriverLoader loader = new DriverLoader();
loader.loadDriver(new LoadableDriver(){
public String getName() { return "SoundDriver"; }
public void loadDriver() { loadSoundDriver(); }
public void onError(Throwable e) { doSomethingA(); }
});
//etc. Or in the alternative make a real class that implements the interface for each driver.
Map<String, Exception> errors = loader.getErrors();
//react to any specific drivers that were not loaded and try again.
}
}
Edit: This is what a clean Java version would ultimately look like if you implemented the drivers as classes (which is what the Java OO paradigm would expect here IMHO). The Main.loadDrivers() method would change like this:
public void loadDrivers(LoadableDriver... drivers) {
DriverLoader loader = ...
for(LoadableDriver driver : drivers) {
loader.load(driver);
}
//retry code if you want.
Set<LoadableDriver> failures = loader.getErrors();
if(failures.size() > 0 && tries++ > MAX_TRIES) {
//log retrying and then:
loadDrivers(drivers.toArray(new LoadableDriver[0]));
}
}
Of course I no longer use a map because the objects would be self-sufficient (you could get rid of the getName() method as well, but probably should override toString()), so the errors are just returned in a set to retry. You could make the retry code even simpler if each driver was responsible for knowing how often it should it retry.
Java won't look as nice as a well done C++ template, but that is the Java language design choice - prefer simplicity over complex language features that can make code hard to maintain over time if not done properly.
Try this:
protected void loadDrivers() {
loadSoundDriver();
loadUsbDriver();
loadAlienDetectorDriver();
loadKeyboardDriver();
}
Then:
protected void loadSoundDriver() {
try {
// original code ...
}
catch( Exception e ) {
soundDriverFailed( e );
}
}
protected void soundDriverFailed( Exception e ) {
log( e );
}
This gives subclasses a chance to change the behaviour. For example, a subclass could implement loading each driver in a separate thread. The main class need not care about how the drivers are loaded, nor should any users of the main class.
IMO, for your case, if the exception is "ignorable" it's best if the "loadSoundDriver" method catches the exception and simply returns an error.
Then in the function that loads stuff, you can record all the errors and at the end of the sequence, decide what to do with them.
[edit]
Something like this:
// init
MyError soundErr = loadSoundDriver();
MyError otherErr = loadOtherDriver();
if(soundErr!=null || otherErr !=null){
// handle the error(s)
}
Just surround every single load operation with its own try / catch block.
try {
loadSoundDriver();
} catch (loadSoundDriverFailed) {
doSomethingA;
}
try {
loadUsbDriver();
} catch (loadUsbDriverFailed) {
doSomethingB;
}
// ...
So you can handle every exception by itself and continue processing the oder operations.