views:

128

answers:

3

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

+8  A: 

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.

Joachim Sauer
I don't know If I fully understood you, but I added my implementation in the question. Please give me a comment If I got it wrong. Anyway, it works fine.
Jonas
+3  A: 

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.

Martin Wickman
+1  A: 

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!

Liggy