In some languages it is possible to get the column number of a line in a stacktrace, however in Java we only have line numbers.
To give you an example, in another language we can have:
Error
at <anonymous>:2:2
at Object.InjectedScript._evaluateOn (<anonymous>:641:39)
at Object.InjectedScript._evaluateAndWrap (<anonymous>:580:52)
at Object.InjectedScript.evaluate (<anonymous>:495:21)"
Although this might be a bad example as I'm causing the error from the browser console, you can see the column numbers which is really helpful in solving errors.
To give you the example in Java ( Yes, names were changed ) :
Caused by: java.lang.IllegalArgumentException: path was null
at org.jboss.resteasy.specimpl.ResteasyUriBuilder.path(ResteasyUriBuilder.java:362)
at enterprise.money.service(AbstractSomething.java:88)
This leads to line 88
which contains
URI uri = uriInfo.getBaseUriBuilder().path(objectA).path(objectB).build();
With the stacktrace I have I can't check which .path
call caused the exception. So my question is, are there any solutions that allow me to get the reference of the column?
( To guard from some possible alternative answers, we need a solution to get the column numbers, other answers like how to step through the debugger or refactoring every builder pattern, etc., will not answer the question )
This is not possible.
You can bypass it, by formatting your code in that way:
URI uri = uriInfo
.getBaseUriBuilder()
.path(objectA)
.path(objectB)
.build();
In Oracle Java 8 you can write
public static void main(String... ignored) {
List<String> s = new ArrayList<>();
s.add("hello");
Predicate<? super String> predicate1 = (t) -> t.length() > 0;
Predicate<? super String> predicate2 = (t) -> t.length() < 8;
Predicate<? super String> predicate3 = null;
List<String> collect = s.stream()
.filter(predicate1) // 16
.filter(predicate2) // 17
.filter(predicate3) // 18
.collect(Collectors.toList());
}
and you get
Exception in thread "main" java.lang.NullPointerException
at java.util.Objects.requireNonNull(Objects.java:203)
at java.util.stream.ReferencePipeline.filter(ReferencePipeline.java:161)
at Example.main(Example.java:18)
For the Oracle JDK, this appears to be only in Java 8, not Java 7.
Reverse engineering this for Java would be pretty painful. In theory you could analyse the original source and work out which expression(s) could throw such an exception.
If you have this as an issue, it is highly likely your lines are too complicated/dense. Most IDEs make it really easy to refactor expressions to extract portions of code. This will give you more resolution of where an exception was thrown.
Another solution to this specific problem is to have methods with @NotNull and the IDE can detect which arguments could be null, but should never be.
URI uri = uriInfo.getBaseUriBuilder().path(objectA)
.path(/*highlighted*/objectB).build();
The IDE can warn you that you are passing a variable to a method which can't take a null
If you do this, you will pick up these bugs much earlier and it make it easier to fix. (The IDE comes with some quick fixes)
Note: generally speaking a incorrectly passed null
argument the API should throw a NullPointerException IMHO, however often an IllegalArgumentException is thrown somewhat inconsistently.
As I see it, an argument for IllegalArgumentException is that;
null
is expected to be the same as other incorrect arguments such as a length of -1IMHO passing null
to a method which doesn't accept a null
is a programming bug, not a matter of happening to provide an incorrect input.
You can't get the columns from the stack trace.
What you can do is using intermediate variables, so that you have each method call on a different line:
UriBuilder builder = uriInfo.getBaseUriBuilder();
builder = builder.path(objectA);
builder = builder.path(objectB);
URI uri = builder.build();
This is painful, but it can temporarily help finding the problem, then you can put it back as it was.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With