I have following piece of code in Java:
String func() {
Object data = otherFunc();
return data.toString();
}
The otherFunc() is #Nullable function and it can return null. So the IDE highlights toString() method as dangerous, because it can cause NullPointerException.
But in my case, I'm 100% confident about not-null result of otherFunc(). So I added an assert condition there:
String func() {
Object data = otherFunc();
MyAssert.notNull(data, some_debug_info);
return data.toString();
}
There is a null-check verification inside the MyAssert.notNull() call and throwing an exception (with some additional debug info) if it's null.
Android Studio highlights toString() anyway...
Question:
How can I indicate that "data" object can't be null after the MyAssert.notNull() call? Maybe with some #annotations?
There are many similar places in the code, so the solution should modify the assert function only!
IntelliJ's Contract annotations might be what you're looking for.
Annotating your method with #Contract("null, _ -> fail") should tell intelliJ that entering null as the first parameter would cause an exception, meaning any code after the call will assume it is non-null.
Related
I'd like to ask something confuses me a lot. Here is the scenario, lets say I have a method preparePayload that takes some argument like messageType, destAddr etc. The duty of method is construct a fully payload (with headers, prefixes etc). Here is the problem, I want to return statusCode (which is enum, like STATUS_OK,STATUS_INVALID_DEST, STATUS_INVALID_MSG_TYPE etc.), and than respect to return status I'd like to implement my logic. But if there is no error (STATUS_OK), I need the prepared payload to move on. So my method should return eighter payload or status code.
In C language, simply sending payload buffer address as an argument to preparePayload method solves the problem perfectly. When the method returns, simply reading payload from the buffer address and moving on the application works. How can I implement this kind of logic in Java?
In addition, preparePayload method is just an example I gave, so the methods I implemented may return String, int[], some class object that I wrote etc. I mean, the type of object that method should return in success case may vary.
Any suggestion will very welcome.
Besides changing to exceptions, there is one more hackish way to allow for "input/output" parameters, like:
public ResultEnum preparePayLoad(List<PayLoad> toPrepare, ... other args) {
...
PayLoad newThing = ...
...
toPrepare.add(newThing);
return someEnum;
}
So, you could use such an approach to "emulate" the "C style"; but the more Java/OO would be
public PayLoad preparePayLoad(args) {
...
PayLoad newThing = ...
...
return newThing;
}
and to throw (checked or unchecked) exceptions for error situations.
The correct idiom in Java is to throw a checked exception (some will say unchecked is better, there is a slight controversy here).
The three important mechanisms you get is:
automatic propagation of error codes up the stack. If you do not handle some type of error in your code (don't check for it), it will get propagated up as an exception - you don't need layered checks (and avoid an error of returning an invalid result, quite common in C),
exceptions work as an "alternate return type", ensuring type safety for both correct results and the error messages (which are full objects - and can contain any number of useful information besides the code)
checked exceptions allow the compiler to check if all the important error statuses are handled in some way.
You can create a class, a wrapper, for example:
public class Result {
public enum Status {
STATUS_OK, STATUS_INVALID_DEST, STATUS_INVALID_MSG_TYPE
}
Status status;
String payload;
}
that will be returned by your method preparePayload. Then, when you call your method, you can do it like this:
Result result = preparePayload(args);
//better will be a switch with case for each possible status
if (result.state == Result.State.STATUS_OK)
//do what you want with payload
System.out.println(result.payload);
else
return;
I am using Findbugs integerated with eclipse.
When I run findbugs on my project the below code is not captured for possible null pointer exception.
In the below snippet the object test is prone to null pointer exception which is not identified by findbugs.
#Override
public boolean saveIrr(TestObject test) throws DuplicateRecordException {
boolean status = false
try {
test.getAddDate();
status = adhocMaintPopupMapper.saveIrr(IRRPopupMaint);
} catch (DataIntegrityViolationException e) {
logger.error("Error in Saving!", e);
throw new TransactionDataException("Error in Saving!", e);
}
return status;
}
Is there any configuration change required to make findbugs to identify this?
If you add #Nonnull to the parameter declaration, FindBugs will highlight anywhere you're passing a value that isn't checked for null. If you mark it #CheckForNull, FindBugs will highlight anywhere in the method that you access it without checking for null.
Which you do depends on the method's contract: does it tolerate null or not? Looking at its implementation it does not allow for null without throwing an unexpected exception. Therefore, test should be marked #Nonnull so you can spot incorrect calls.
Update
FindBugs will only check fields, parameters, method return values that are annotated with either #Nonnull or #CheckForNull. Anything without an annotation is assumed #Nullable which tells FindBugs to ignore it.
public boolean saveIrr(#Nonnull TestObject test) { ... }
public void dontCareAboutNull(TestObject value) {
saveIrr(value); // no bug
}
public void mightBeNull(#CheckForNull TestObject value) {
saveIrr(value); // bug
}
For this reason, we apply #Nonnull to all three types of values at the package level. Any value that needs to allow null must be annotated with #CheckForNull. We do not allow the use of #Nullable except in very few corner cases (e.g. #Autowired fields which Spring enforces).
I noticed that you're missing a ; in your code after "boolean status = false", this could be the reason why findbug has problems to parse your code.
OK from what I understood : you want to identify that test has not beeing tested for null. As far as I know there is no way to configure findbugs for doing this. Findbugs can warn you in 2 other cases :
- NP_ARGUMENT_MIGHT_BE_NULL : if you call your method saveIrr with a and argument that has not been tested for null before.
- NP_NULL_INSTANCEOF : if findbug identified that your value is guaranteed to be null at a point.
You can check all the Null Pointer warnings here they are identified with NP: http://findbugs.sourceforge.net/bugDescriptions.html
I think that such a warning would result in a too huge amount of bugs detected : all methods with arguments would give warnings for arguments that would be used before beeing tested.
What you can do is use the annotions of findbugs/jsr305. So if you add #Nullable to the getDate() method in TestObject it may trigger a NP warning. If you want to use those annotions be sure that the jsr305.jar is in your classpath...
I am using PMD Plug-in 3.2.6.v2009033006 . But the default rulesets in pmd is not captured possible null pointer exception .
Java Code
public class SignUp extends HttpServlet{
public void doGet(HttpServletRequest req , HttpServletResponse res){
String user = req.getParameter("user");
user.trim();
}
}
user.trim(); if the user variable is null it will be prone to null pointer exception . I checked my code with pmd but it will not indicate this ?
How can i capture this ? . Is there any custom pmd ruleset is available?
Is there any custom rulesets available for capturing this ?
PMD isn't the right tool for this. You should use FindBugs to catch such problems.
But even with FindBugs, you won't catch anything because the above code is perfectly reasonable, and doesn't have any bug, unless you know that getParameter("user") can return null, and that there is something better to do than throwing a NullPointerException in this case.
If such code triggered an error, basically every line of code which calls a method on an object returned by another method would trigger an error. FindBugs supports annotations that allows declaring that the caller of a method should always check for null on the result returned by this method. See http://findbugs.sourceforge.net/manual/annotations.html. But of course, for third-party code, you can't do anything (other than writing your own rules).
I'm wanting to use two custom matchers for a single method. Basically, if I pass the method VALUE_A, I want it to return RESULT_A, and if I pass it VALUE_B, I want it to return RESULT_B. So here's a code excerpt :
class IsNonEmpty extends ArgumentMatcher<Get> {
public boolean matches(Object get) {
//For some reason, this method is called when I assign the IsEmpty matcher to MockHtable.get()
//When this happens, the value of the get argument is null, so this method throws an NPE
return Arrays.equals(((Get) get).getRow(), SERIALIZATION_HELPER.getValidBytes(key));
}
}
class IsEmpty extends ArgumentMatcher<Get> {
public boolean matches(Object get) {
return !(Arrays.equals(((Get) get).getRow(), SERIALIZATION_HELPER.getValidBytes(key)));
}
}
[...]
//This line executes just fine
Mockito.when(mockHTable.get(Mockito.argThat(new IsNonEmpty()))).thenReturn(dbResult);
[...]
//This line calls IsNonEmpty.matches() for some reason. IsNonEmpty.matches() throws an NPE
Mockito.when(mockHTable.get(Mockito.argThat(new IsEmpty()))).thenReturn(emptyResult);
When I assign the IsEmpty custom matcher to mockHTable.get() method, it calls the IsNonEmpty.matches() function. No idea why it's doing this. So I change the IsNonEmpty class to this :
class IsNonEmpty extends ArgumentMatcher<Get> {
public boolean matches(Object get) {
//For some reason, this method is called when I assign the IsEmpty matcher. Weird, no?
if(get == null) {
return false;
}
return Arrays.equals(((Get) get).getRow(), SERIALIZATION_HELPER.getValidBytes(key));
}
}
and then everything works just fine! IsNonEmpty.matches() is still called when I assign the IsEmpty matcher to the mockHTable.get() function, but my matchers work exactly how they should.
So what's the deal? Why does this happen? Is my work-around an adequate way to compensate for this quirky behavior, or am I Doing It Wrong?
The reason why IsNonEmpty.matches() gets called on the second line of stubbing is that the Mockito.argThat(new IsEmpty()) returns null, which is then passed to mockHTable.get(). This call has to be checked against the earlier stubbing, to see whether it's a match; and that means calling IsNonEmpty.matches().
I'm not sure why this makes your test fail - it's hard to tell without seeing all of the code.
But, I would seriously recommend using doReturn...when instead of when...thenReturn whenever you have to stub the same mock more than once. You won't encounter issues like this if you do. In fact, I prefer to use doReturn...when in preference to when...thenReturn always (and similarly doThrow and doAnswer), although most people prefer when...thenReturn.
Re-writing one of your stubbing lines with the doReturn...when syntax looks like the following. The other is similar.
Mockito.doReturn(dbResult).when(mockHTable).get(Mockito.argThat(new IsNonEmpty()));
Lastly, a plea, on behalf of the Mockito development team (of which I am a member). If you think there is a bug in Mockito here - and from your description, I think there may well be - please EITHER
send a message to the Mockito mailing group (mockito#googlegroups.com) OR
raise an issue on the Mockito issues list (http://code.google.com/p/mockito/issues/list).
It's useful to the Mockito team if you can actually post a complete example, rather than just what you think the key lines are - sometimes the cause of a Mockito problem is in quite an unexpected place.
I just want to create an object of class, but got this error when debugging. Can anybody tell me what the problem is? The location of this code is in some Spring(2.5) Service class.
There is a similar problem: OJB Reference Descriptor 1:0 relationship? Should I set auto-retrieve to false?
Thanks a lot~
The root cause is that when debugging the java debug interface will call the toString() of your class to show the class information in the pop up box, so if the toString method is not defined correctly, this may happen.
I also had a similar exception when debugging in Eclipse. When I moused-over an object, the pop up box displayed an com.sun.jdi.InvocationException message. The root cause for me was not the toString() method of my class, but rather the hashCode() method. It was causing a NullPointerException, which caused the com.sun.jdi.InvocationException to appear during debugging. Once I took care of the null pointer, everything worked as expected.
Well, it might be because of several things as mentioned by others before and after. In my case the problem was same but reason was something else.
In a class (A), I had several objects and one of object was another class (B) with some other objects. During the process, one of the object (String) from class B was null, and then I tried to access that object via parent class (A).
Thus, console will throw null point exception but eclipse debugger will show above mentioned error.
I hope you can do the remaining.
For me the same exception was thrown when the toString was defined as such:
#Override
public String toString() {
return "ListElem [next=" + next + ", data=" + data + "]";
}
Where ListElem is a linked list element and I created a ListElem as such:
private ListElem<Integer> cyclicLinkedList = new ListElem<>(3);
ListElem<Integer> cyclicObj = new ListElem<>(4);
...
cyclicLinkedList.setNext(new ListElem<Integer>(2)).setNext(cyclicObj)
.setNext(new ListElem<Integer>(6)).setNext(new ListElem<Integer>(2)).setNext(cyclicObj);
This effectively caused a cyclic linked list that cannot be printed. Thanks for the pointer.
I was facing the same issue because I was using Lombok #Data annotation that was creating toString and hashcode methods in class files, so I removed #Data annotation and used specific #Gettter #Setter annotation that fixed my issue.
we should use #Data only when we need all #ToString, #EqualsAndHashCode, #Getter on all fields, and #Setter on all non-final fields, and #RequiredArgsConstructor.
I had the same issue once. In my case toString() method was badly created. TO be precise a static final variable was included in the toString method when a developer form my team was assigned code cleaning task and to add toString(), hashCode() code and equals() methods to domain objects where ever possible. but in of the classes because of over looking at it, he included final static variable that caused the "com.sun.jdi.InvocationException" this exception was visible on debugging only when I hovered over the object which has the exception.
I got similar exception in Eclipse. This was due to java.lang.StackOverflowError error. I had overriden toString() method in child class, having JoinColumn, which was returning string using object of parentclass, resulting in circular dependency. Try to remove that object from toString(), and it will work.
Disabling 'Show Logical Structure' button/icon of the upper right corner of the variables window in the eclipse debugger resolved it, in my case.
so I had same problem here. Found out that my domain instance was getting detached from the hibernate session. I used isAttached() to check and attached the domain using d.attach()
This was my case
I had a entity Student which was having many-to-one relation with another entity Classes (the classes which he studied).
I wanted to save the data into another table, which was having foreign keys of both Student and Classes. At some instance of execution, I was bringing a List of Students under some conditions, and each Student will have a reference of Classes class.
Sample code :-
Iterator<Student> itr = studentId.iterator();
while (itr.hasNext())
{
Student student = (Student) itr.next();
MarksCardSiNoGen bo = new MarksCardSiNoGen();
bo.setStudentId(student);
Classes classBo = student.getClasses();
bo.setClassId(classBo);
}
Here you can see that, I'm setting both Student and Classes reference to the BO I want to save. But while debugging when I inspected student.getClasses() it was showing this exception(com.sun.jdi.InvocationException).
The problem I found was that, after fetching the Student list using HQL query, I was flushing and closing the session. When I removed that session.close(); statement the problem was solved.
The session was closed when I finally saved all the data into table(MarksCardSiNoGen).
Hope this helps.
I have received com.sun.jdi.InvocationException occurred invoking method when I lazy loaded entity field which used secondary database config (Spring Boot with 2 database configs - lazy loading with second config does not work). Temporary solution was to add FetchType.EAGER.
There could be two reasons an element doesn't exist:
Bad xpath (//*[#id'forgotQuote])
Correct xpath but no element (//*[contains(text(),'This text is not in the page')])
Would you get com.sun.jdi.InvocationException in either case when you are running Debug and you hover your mouse over a reference to the WeBElement (this with Selenium and Java)???
We use the following, but can't distinguish if it returns false due to bad xpath or non-existent element (valid xpath syntax):
public static boolean isElementDisplayed(WebElement element) {
boolean isDisplayed = false;
try {
isDisplayed = element.isDisplayed();
} catch (NoSuchElementException e) {
;// No Worries
}
return isDisplayed;
}
Removing hashCode() and equals() solved my issue. In my case, I used Apache's commons-lang hash code and equals builders for creating non-static classes manually, so the compiler didn't throw any exception. But at runtime it caused the invocation exception.
In my case it was due to the object reference getting stale.
I was automating my application using selenium webdriver, so i type something into a text box and then it navigates to another page, so while i come back on the previous page , that object gets stale.
So this was causing the exception, I handled it by again initialising the elements -
PageFactory.initElements(driver, Test.class;
I also faced the same problem. In my case I was hitting a java.util.UnknownFormatConversionException. I figured this out only after putting a printStackTrace call. I resolved it by changing my code as shown below.
from:
StringBuilder sb = new StringBuilder();
sb.append("***** Test Details *****\n");
String.format("[Test: %1]", sb.toString());
to:
String.format("[Test: %s]", sb.toString());
I faced the same problem once. In my case it was because of overridden equals method. One values was coming null.