Findbugs-NP - NP_NULL_ON_SOME_PATH - java

Findbugs is showing NP_NULL_ON_SOME_PATH for a line.
It says that there is a branch of statement that, if executed, guarantees that a null value will be dereferenced, which would generate a NullPointerException when the code is executed.
Of course, the problem might be that the branch or statement is infeasible and that the null pointer exception can't ever be executed; deciding that is beyond the ability of FindBugs.
Here is the code:
public int compare(Object o1, Object o2)
{
....
String sTypeName1 = row1.getFieldValue(OBJECT_TYPE_FIELD_NAME);
String sTypeName2 = row2.getFieldValue(OBJECT_TYPE_FIELD_NAME);
if (sTypeName1!= null && sTypeName1.indexOf("~") != -1)
{
sTypeName1 = m_oc.getString(sTypeName1);
}
if (sTypeName2!= null && sTypeName2.indexOf("~") != -1)
{
sTypeName2 = m_oc.getString(sTypeName2);
}
int cf = sTypeName1.compareTo(sTypeName2);
if (cf == 0)
{
cf = o1.toString().compareTo(o2.toString());
}
return cf;
}
It is showing 2 errors of same kind for the code:
int cf = sTypeName1.compareTo(sTypeName2);
Here it says that there is a possible null pointer dereference from the value loaded from sTypeName1.
So I had to put a null check before this code like:
if(sTypeName1 != null && sTypeName2 != null)
{
int cf = sTypeName1.compareTo(sTypeName2);
}
but the issue is not resolved. :(
Could anyone suggest a solution and also what is wrong with my approach?
Thanks a lot for going through my question :)

For me the issue is resolved. This code does not produce a bug report:
String sTypeName1 = row1.getFieldValue("qqq");
String sTypeName2 = row2.getFieldValue("www");
if (sTypeName1 != null && sTypeName1.indexOf("~") != -1) {
sTypeName1 = m_oc.getString(sTypeName1);
}
if (sTypeName2 != null && sTypeName2.indexOf("~") != -1) {
sTypeName2 = m_oc.getString(sTypeName2);
}
int cf = 0;
if (sTypeName1 != null && sTypeName2 != null) {
cf = sTypeName1.compareTo(sTypeName2);
}
if (cf == 0) {
cf = o1.toString().compareTo(o2.toString());
}
return cf;
Probably you did not recompile your code or did not perform the FindBugs analysis again.

From my experience this can be caused by situations like this:
Situation 1 - Findbugs will complain if you only set b under some conditions, such as if a is not null, then later reference b. If a could really be null, you need to handle what to do if b is null too as a result. If a is never null, remove the null check. Also, for me it identified the line where b was defined as the first problematic line, rather than when b.doSomething() is called.
if (a != null) {
b = a.getB();
}
b.doSomething();
Situation 2 - You nullcheck in one place, but not another. Nullcheck everywhere, or nowhere
if (x != null) {
x.doSomething1();
}
x.doSomething2();

Related

How to prevent the error: null > 0 java

I currently have an enumlist. The enumlist gets filled at random, so there is a possibility that one has the value null. That is logical because it doesn't get filled.
The problem is further in my code I have:
if (player.Enumlist().get(CART_BLACK) > 0) {
}
Java throws a NullPointerException. Is there something I could add to the if-statement to prevent this error?
If get(CART_BLACK) may return null:
Get the value before the condition and replace it with a negative value if it's null:
Integer cartBlack = player.Enumlist().get(CART_BLACK);
if (cartBlack == null) cartBlack = -1;
if (cartBlack > 0) {
If player.Enumlist() may return null
Similar, but not quite identical:
final Enumlist list = player.Enumlist();
final int cartBlack = list == null ? -1 : list.get(CART_BLACK);
if (cartBlack > 0) {
You'll need to guard against nullity:
if(player.Enumlist().get(CART_BLACK) != null &&
player.Enumlist().get(CART_BLACK) > 0) {...}
or a more efficient version:
Integer temp = player.Enumlist().get(CART_BLACK);
if (temp != null && temp > 0){...}
if( player.Enumlist().get(CART_BLACK) != null && player.Enumlist().get(CART_BLACK) > 0) {
}
This will work because ifs are checked from left to right, and if one condition fails the rest won't be evaluated and you won't get the NPE.
Correcting the issue at the end makes the trick but it is not fine because it means that it may occur in other invocations. Besides, as a consequence, you may finish by overusing not null guards as you will never know if the null is a normal case.
So you should favor the use of Optional (Java 8 or Guava) as return rather than null to make your API clearer (it may return an empty thing so convey that) and more robust (the contained object has to be specifically unwrapped).
For example :
Optional<Integer> optValue = player.Enumlist().get(CART_BLACK);
optValue.filter(v -> v > 0)
.ifPresent( v -> ...);
You need to do Null Checking:
if (player == null || player.Enumlist () == null) {
throw new Exception("Player or Enumlist cannot be null");
}
You should also check that the Integer value is not null, but I guess that would be pretty weird if you wrote the code.
You are using get which could give you an IndexOutOfBoundsException eventually. You could check that using the size method or using streams.
If (player.Enumlist().size() > CART_BLACK && player.Enumlist().get(CART_BLACK) != null && player.Enumlist().get(CART_BLACK) > 0) {
//...
}
You may check for Null also handle the exception using try..catch block
try
{
if( player.Enumlist().get(CART_BLACK)!=null && player.Enumlist().get(CART_BLACK) > 0)
{
}
}
catch(NullPointerException)
{
//handle exception here
}

Introduce a new variable instead of reusing the parameter "entity"

I am solving SonarQube issues , in that issues I face an below warning any one please tell me how can i fix it,
Here is my class
public static Agency updateEntity(AgencyModel model, Agency entity) {
if (model == null || entity == null) {
return null;
}
if (entity.getAgencyId() != model.getAgencyId()) {
entity = new Agency()
// for the above variable 'entity' i get the warning, "Introduce a new
variable instead of reusing the parameter "entity".
}
entity.setAgencyId(model.getAgencyId());
if (entity.getAgencyLogoLarge() == null) {
entity.setAgencyLogoLarge(new File());
}
entity.setAgencyLogoLarge(FileModel.updateEntity(model.getAgencyLogoLarge(), entity.getAgencyLogoLarge()));
if (entity.getAgencyLogoSmall() == null) {
entity.setAgencyLogoSmall(new File());
}
entity.setAgencyLogoSmall(FileModel.updateEntity(model.getAgencyLogoSmall(), entity.getAgencyLogoSmall()));
entity.setAgencyName(model.getAgencyName());
entity.setContactPersons(
AgencyContactPersonModel.updateEntities(model.getContactPersons(), entity.getContactPersons()));
entity.setOtherDetails(model.getOtherDetails());
entity.setClassification(ClassificationModel.updateEntity(model.getClassification(), entity.getClassification()));
entity.setStatus(entity.getStatus());
entity.setCreatedBy((model.getCreatedBy() != null && model.getCreatedBy() != 0) ? model.getCreatedBy()
: entity.getCreatedBy());
entity.setUpdatedBy((model.getUpdatedBy() != null && model.getUpdatedBy() != 0) ? model.getUpdatedBy()
: entity.getUpdatedBy());
entity.setUpdatedDate(new Date());
entity.setStatus(Constant.ACTIVE);
return entity;
}
In above method i get that warning , will any one please tell me that what is the best approach to solve the above problem.
Assigning a value to a method argument often indicates a bug (even though this is not the case in your example), which is probably why SonarQube gives that warning.
Assuming you have no way of disabling that warning (or you don't want to), you can eliminate it by introducing a new local variable:
public static Agency updateEntity(AgencyModel model, Agency entity) {
Entity result;
if (model == null || entity == null) {
return null;
}
if (entity.getAgencyId() != model.getAgencyId()) {
result = new Agency();
} else {
result = entity;
}
... use result variable instead of entity variable ...
return result;
}

Expressions should not be too complex for conditional operators

I am using Sonar and its giving me the suggestion "Expressions should not be too complex"
How can I make a better representation of below code?
Code
if (eDelivery != null && Boolean.parseBoolean(eDelivery.getReceiveConfirmationElectronically()) &&
!Boolean.parseBoolean(eDelivery.getInvalidEmailAddress()) && !Boolean.parseBoolean(eDelivery.getEmailUndeliverable()) &&
eDelivery.getUserEmailAddress() != null && !eDelivery.getUserEmailAddress().isEmpty()) {
// Implementation code
}
These conditions all relate to the eDelivery object, so deal with this there.
First, there's the question of why you're doing all these parseBoolean calls for properties that look like they should be boolean to start with. But okay, let's assume that you can't change that. Fine, so add 2ndary methods:
public class EDelivery {
public boolean isReceiveConfirmationElectronically() {
return Boolean.parseBoolean(getReceiveConfirmationElectronically())
}
// &etc...
Already that cleans it up considerably:
if (eDelivery != null && eDelivery.isReceiveConfirmationElectronically() &&
!eDelivery.isInvalidEmailAddress() && !eDelivery.isEmailUndeliverable() &&
eDelivery.getUserEmailAddress() != null && !eDelivery.getUserEmailAddress().isEmpty()) {
// Implementation code
But that doesn't address the number of conditions. So now:
// in EDelivery class
public boolean isEmailGood() {
return !isInvalidEmailAddress() && !isEmailUndeliverable() &&
getUserEmailAddress() != null && !getUserEmailAddress().isEmpty())
}
So now we're at:
if (eDelivery != null && eDelivery.isReceiveConfirmationElectronically() &&
eDelivery.isEmailGood()) {
// Implementation code
At this point you've met the requirement, but if you wanted to take it a little further:
// in EDelivery class
public boolean canSendElectronicConfirmation(){
return isEmailGood() && isReceiveConfirmationElectronically();
}
Which reduces your original if statement to
if (eDelivery != null && eDelivery.canSendElectronicConfirmation()) {
// Implementation code

Java Multiple comparision in java

Pardon me if this is a stupid question.. I was wondering if there is any support for following comparison in Java:
(a, b, c .... != null) in place for :
(a != null && b != null && c != null && d ! null and so on ..)
I was trying to make code more readable as my code which is almost unreadable due to multiple condition in single statement.
code :
variable = (rest.host != null && rest.payload != null
&& rest.lockQueue != null && rest.endpoint != null ) || rest.default.setState
|| rest.scheduler.locked && rest.scheduler.queue.isFull()
&& lastPayload.getActivity.status.executing ? onExecute(rest.payload) : wait(TIME);
If your elements are in a collection, use collection.stream().allMatch(x -> x != null). Actually, there's even a predicate for that: collection.stream().allMatch(Objects::nonNull).
If your elements aren't in a collection, you can still use Arrays.asList() to create an ad-hoc list from them. So, in your case:
Arrays.asList(rest.host, rest.payload, rest.lockQueue, rest.endpoint).stream().allMatch(Objects::nonNull)
EDIT: actually, as someone mentioned in another answer, there is a method that creates a stream directly, namely Stream.of(...). So:
Stream.of(rest.host, rest.payload, rest.lockQueue, rest.endpoint).allMatch(Objects::nonNull)
You could do something like this to make sure everything is not null, if using a Java version lower than 8. Otherwise I would go with the other people's answers using streams.
private boolean checkIfNotNull( Object ... objects ) {
for(int i = 0; i < objects.length; i++) {
if(objects[i] == null)
return false;
}
return true;
}
and you could pass in all the objects that you want to check if they are null.
then you can call this in the if statement such as
if( checkIfNotNull( a, b, c, d, e, f, g ) ) {
//do stuff
}
In java 8, it could be done as next Stream.of(a, b, c, d).allMatch(Objects::nonNull), it will return true if they are all non null.
I think if you want your code more readable, you should replace your comparisons with method calls that "says" what each comparison is.
Example:
if (isAllRight(a, b, c)) {
...
}
In other cases you can break them into single comparisons and check one by one:
if (a == NUL) {
return false;
}
if (b == NULL) {
return false;
}
return true;

handling Null for bigdecimal

My code looks like below,
caseX caseXObj = caseXBo.getCaseXDao().findCaseXBySID(selectedID);
if(caseXObj != null && caseXObj.getCaseInGrossAmt() != null){
} else {
caseXObj.setCaseAmt(BigDecimal.ZERO);
}
I have handled NUll pointer for the caseX and also for getter and when null set the bigdeciaml to a default ZERO value. Still I get Null pointer exception in the setter line.Any suggestions?
It's quite possible that caseXObj is null, so it'll cause the NullPointerException. You should test the three cases like this:
caseX caseXObj = caseXBo.getCaseXDao().findCaseXBySID(selectedID);
if (caseXObj != null && caseXObj.getCaseInGrossAmt() != null) {
// do something with caseXObj
} else if (caseXObj == null) {
// initialize caseXObj, you were misssing this case!
} else {
caseXObj.setCaseAmt(BigDecimal.ZERO);
}
In essence, the error was that you were testing for only two cases - and there are three of them.
Assuming it is OK for getCaseXDao() to return null, you need to assign to caseXObj rather than use it as a pointer in the else clause.
That because you don't check for null in your else part.
It should be:
caseX caseXObj = caseXBo.getCaseXDao().findCaseXBySID(selectedID);
if(caseXObj != null && caseXObj.getCaseInGrossAmt() != null)
{
//...
}
else
{
if (caseXObj != null)
{
caseXObj.setCaseAmt(BigDecimal.ZERO);
}
}

Categories

Resources