+ Start a Discussion
JSpenceJSpence 

Apex Bug?

Hi there,

 

I'm trying to compare a field in an object which relates to another object which has the same API name.

This results in a FATAL_ERROR System.NullPointerException: Attempt to de-reference a null object.

 

I can print the information successfully, the probelm arrises when I do string1.equals(string2); (where String 2 is the field name in an object AND an object API name.) For some reason Apex decides I want the object name instead of the field name, which is weird since I'm defining "object.field" in my .equals()

 

Is there a way to select by alias in SOQL or set up a new instance of String (String myString = new String();) ?

Best Answer chosen by Admin (Salesforce Developers) 
David81David81

I'd do it like this

 

public List<Rate_Card_Items__c> fetchRateCards() {
     return [
          SELECT id, Rate_Card__c, Work_Order__c
          FROM Rate_Card_Items__c
          WHERE
               isdeleted = false
               AND Work_Order__c != null
          ORDER BY
               Rate_Card__c, Work_Order__c
     ];
}



All Answers

kiranmutturukiranmutturu

i think the second value is coming as null... but before checking that you are trying to compare the original string with the secong string like string.equals(string2).....like this... thats the prob

JSpenceJSpence

The second string is not null. I can print them both and they both have values.

 

It seems the .equals() is assuming I want the OBJECT which has the same name as a field within a different object.

goabhigogoabhigo

Can post the part of the code? Are you sure the error is for that statement, if yes, are you sure string1 has value (System.debug(string1);) ???

kiranmutturukiranmutturu

give me the syntax how you are using in in the code...

JSpenceJSpence

I can assure you these have values.

 

public List<Rate_Card_Items__c> fetchRateCards() {
     return [
          SELECT id, Rate_Card__c, Work_Order__c
          FROM Rate_Card_Items__c
          WHERE
               isdeleted = false
          ORDER BY
               Rate_Card__c, Work_Order__c
     ];
}

 

 

Work_Order__c is a Custom Object AND is a field in the Rate_Card_Items__c object. The field called Work_Order__c in Rate_Card_Items__c relates to a field in the object mentioned.

 

The comparason I'm trying:

 

Rate_Card_Items__c current = oldRateCards.get(0);
     for (Integer i = 1; i < oldRateCards.size(); i++) {
          Rate_Card_Items__c item = oldRateCards.get(i);
          String workOrder = item.Work_Order__c;
          if (workOrder.equals(current.Work_Order__c)) { //error here
               ...
          }
     }

 

 

These are both strings, so dont worry about the types.

Shashikant SharmaShashikant Sharma

Things that I notices in your code 

 

You showed 

public List<Rate_Card_Items__c> fetchRateCards() 

 

but you are using

 

oldRateCards in comparision code. Please check you are using correct list. If you are just for one verification do this

 

Added three null checks 

workOrder != null  && current != null && current.Work_Order__c != null 

 

Rate_Card_Items__c current = oldRateCards.get(0);
     for (Integer i = 1; i < oldRateCards.size(); i++) {
          Rate_Card_Items__c item = oldRateCards.get(i);
          String workOrder = item.Work_Order__c;
          if (workOrder != null  && current != null && current.Work_Order__c != null && workOrder.equals(current.Work_Order__c)) { //error here
               ...
          }
     }

 Please verify above and share the outcome.

JSpenceJSpence

I forgot to include this in my previous code: 

 

List<Rate_Card_Items__c> oldRateCards = fetchRateCards();

 

I am using the correst list.

 

Those extra conditions wont make any difference because it still wants to use the Work_Order__c object over the current.Work_Order__c field.

 

I make other comparisons with 'current' and 'item' which work. Comparing a field which shares its api name with an entire custom object seems not to work.

Shashikant SharmaShashikant Sharma

Please add this system.debug in your code and let me know the results

I am pretty sure one of them is null , my guess is workOrder  should be null

 

system.debug('******  workOrder  : ' + workOrder );          

system.debug('******  current : ' + current);

 

Rate_Card_Items__c current = oldRateCards.get(0);
     for (Integer i = 1; i < oldRateCards.size(); i++) {
          Rate_Card_Items__c item = oldRateCards.get(i);
          String workOrder = item.Work_Order__c;
          system.debug('******  workOrder  : ' + workOrder );
          system.debug('******  current : ' + current);
          if (workOrder.equals(current.Work_Order__c)) { //error here
               ...
          }
     }

 

JSpenceJSpence

Both print with data. I highlighted this in an earlier post.

 

(I'm using your code)

David81David81

Maybe I'm confused here, but why are you converting an Id to a String? Why not just compare the two Ids with "=="?

JSpenceJSpence

That works(I think?). I was questioning this because normally in Java == compares the object refrences rather than the characters inside the String like .equals() does.

 

For example:

 

String s1 = "Hi!"; 
String s2 = new String(s1); 
System.out.println(s1 + " equals " + s2 + " : " + 
s1.equals(s2)); 
System.out.println(s1 + " == " + s2 + " : " + (s1 == s2));

 with output:

Hi! == Hi! : false

Hi! equals Hi! : true 

 

 

Does nobody think the origional problem is strange? Comparing String representations of IDs in the past has worked for me but not in this case where a field relates to an object field where both api names are the same.

David81David81

Out of curiosity, I'd be interested to know what happens if you convert both values to strings prior to the comparison, rather than just the one.

JSpenceJSpence

I have tried loads of things and I always end up with the same error:

 

FATAL_ERROR System.NullPointerException: Attempt to de-reference a null object.

 

 

From what I gather String myString = object.fieldName in apex is a string pointer, not a new string.

 

I also tried creating a myString class:

 

 

public class myString {

String newString;

myString(String newString) {
this.newString = newString;
}

public String getString() {
return newString;
}
}

myString abc = new myString(object.field);

 (Rough writeup from memory but you get the idea..) I have also tried String.valueOf.

 

They all come out with the same error!

David81David81

Must be something odd going on here. I just did a quick test in my dev org.

 

  1. Created two custom objects - testParent and testChild.
  2. Created a lookup field on testChild that links to testParent and called it testParent.
  3. Inserted a testParent record.
  4. Inserted 2 testChild records that both link to the single testParent.
  5. Ran the following code in the System Log
List<testChild__c> tests = [SELECT Id,testParent__c FROM testChild__c];
testChild__c current = tests.get(0);

for (Integer i = 1; i < tests.size(); i++) {
         testChild__c item = tests.get(i);
          String parent = item.testParent__c;
          if (parent.equals(current.testParent__c)) {
              system.debug('MATCHES');
          }
     }

 

No errors and the expected debug statement shows in the logs.

JSpenceJSpence

Thanks for testing that David. There's something strange going on as none of my colleagues can understand this either.

David81David81

Just for kicks, can you add another filter to your query that pulls the list such as

Work_Order__c != null



JSpenceJSpence
public List<Rate_Card_Items__c> fetchRateCards() {
     return [
          SELECT id, Rate_Card__c, Work_Order__c
          FROM Rate_Card_Items__c
          WHERE
               isdeleted = false
               AND Work_Order__c <> ''
          ORDER BY
               Rate_Card__c, Work_Order__c
     ];
}

 Like that?

David81David81

I'd do it like this

 

public List<Rate_Card_Items__c> fetchRateCards() {
     return [
          SELECT id, Rate_Card__c, Work_Order__c
          FROM Rate_Card_Items__c
          WHERE
               isdeleted = false
               AND Work_Order__c != null
          ORDER BY
               Rate_Card__c, Work_Order__c
     ];
}



This was selected as the best answer
JSpenceJSpence

Well done sir. That also works.

 

I'm not sure there are supposed to be null references in there since its a foreign key/lookup but thanks for that, I can't believe I never checked that.

David81David81

Some values must be null. If it's just a "Lookup" type field, then it isn't required. You can put validation in to ensure it is filled in, or change it to a "Master-Detail" relationship which will force that field to be required. Take a look at the docs to see if "Master-Detail" is right for this one, since there are a couple other bits that come along with it.