Jonas
Jonas

Reputation: 128807

How can I print the argument value that caused Exception in Java?

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

Upvotes: 4

Views: 2377

Answers (3)

Liggy
Liggy

Reputation: 1201

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!

Upvotes: 1

Martin Wickman
Martin Wickman

Reputation: 19905

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.

Upvotes: 3

Joachim Sauer
Joachim Sauer

Reputation: 308001

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.

Upvotes: 9

Related Questions