The structure that I have is:
Map<String, ArrayList<Bean>>
This Arraylist is modified (added/removed) from different locations within different threads.
At times, some bean inside the ArrayList is becoming null. How can I track when it becomes null? I want to track what makes the bean null, to fix the bug.
This happens when the scenario is tested with a huge data set.
Here's the exact code that's failing:
for (int i = 0; i < eventlogs.size(); i++) {
MessageEventLogBean msgEventLogBean = (MessageEventLogBean) eventlogs.get(i);
eventlogs.remove(i);
try {
logWriter.write(msgEventLogBean, context);
} catch (FusionException e) {
logger.error("Error While writing the event log bean ", e);
}
}
Instead of a standard list implementation, use an anonymous class that overrides the add method and adds special code to check if the added object is null, like this:
List<T> list = new ArrayList<T>() {
public boolean add(T e) {
if (e == null) {
throw new NullPointerException("Attempt to add null to list");
}
return super.add(e);
}
};
You should similarly override all "add" methods to be sure. When code adds a null, it will explode and you will see the exception in the log and be able to see who did it be examining the stacktrace.
EDITED
To be clear, it is impossible for an object in a List to "become null". You can add a null, or you can remove an object from the List, but an object already in the List will stay there until removed.
To be clear, the only way for a null to get in the list is by putting it there - ie adding it via one of the add() methods or the addAll() method. Concurrent modification issues can not cause this issue (you may get a ConcurrentModificationException, but that still won't put a null in there).
Code such as
Object o = list.get(1);
o = null;
has no effect because you're just nulling a copy of the reference to the object - list still a reference to the object.
However, depending on the design of the Bean objects, they might be mutable. While the reference to the Bean object would remain intact, it might be possible for some of the fields within the Bean to become null. To catch this, you would need to code the setters to explode when given a null argument, either by re-writing the class, or by overloading the setters via an anonymous class (similar to my initial suggestion above).
It's a bit of work, but you can create your own List interface implementation that delegates all methods to the ArrayList. In the accessor method where you would normally return the ArrayList, instead return your debug implementation with the ArrayList wrapped inside of it. Then just set a breakpoint on your set method, and you'll know exactly what code is calling set on the ArrayList.
Perhaps this is what you intended
private final Queue<MessageEventLogBean> eventlogs = new ConcurrentLinkedQueue<>();
// this loop stops when it runs out of objects.
MessageEventLogBean msgEventLogBean;
while ((msgEventLogBean = eventlogs.poll()) != null) {
try {
logWriter.write(msgEventLogBean, context);
} catch (FusionException e) {
logger.error("Error While writing the event log bean ", e);
}
}
or
// this loops until the thread is interrupted
private final BlockingQueue<MessageEventLogBean> eventlogs = new LinkedBlockingQueue<>();
while (true) {
MessageEventLogBean msgEventLogBean = eventlogs.take();
try {
logWriter.write(msgEventLogBean, context);
} catch (FusionException e) {
logger.error("Error While writing the event log bean ", e);
}
}
Both options are thread safe.
You can override the add() and set() methods for the list so that null is invalid and throws an exception.
List<MyType> list = new ArrayList<MyType>() {
public boolean add(MyType mt) {
if(mt == null) throw new IllegalArgumentException();
super.add(mt);
}
};
Consider the following code
String a = "hi"; // a => "hi"
String b = a; // a => "hi" and b => "hi"
a = null; // a => null and b => "hi"
String a is a reference to a String and when you assign null to it you change just the value of a and other references to the same object are unaffected.
A way to process every second entry, or why using remove(i) is unlikely to be what you want.
List<Integer> list = new ArrayList<>();
for(int i=0;i<10;i++) list.add(i);
for(int i=0;i<list.size();i++) {
System.out.println(list.get(i));
list.remove(i);
}
prints
0
2
4
6
8
Related
I have this situation many times in my code,
I have a method for example such as:
private Object doSomething(){
//Do something
doSomething ? return Object : return null;
}
This is just an example, then in the main body of my code I need to check that this doesn't return null before I do something else. For example:
if(doSomething() != null){
Object object = doSomething();
From a performance perspective this method is being asked to run twice, once to check it doesn't return null and next to assign the new variable as long as it returns a valid object.
Is there a way to develop this code where this double running doesn't have to take place. Bearing in mind that the check to make sure the object is valid is important in the code.
Just reverse the process. First assign the result of that call to a variable, then check if the variable is null.
Object object = doSomething();
if (object != null) {
// do whatever with object
} else {
// do something else
}
It is worth noting that the problem with multiple calls to doSomething may not only be a performance penalty. It could also be a problem if:
doSomething has side effects, for example if it inserts a row in a database, in which case calling it twice will insert two rows.
doSomething depends on some external state which may change between invocations.
Consider using Optional rather than returning null (introduced with Java 8).
public Optional<Object> doSomething() {
return Optional.ofNullable(someData);
}
When invoked, you have an Optional reference that may (or may not) have contents.
Optional<Object> maybeSomething = doSomething();
if (maybeSomething.isPresent()) {
Object someData = maybeSomething.get();
System.out.println("SomeData = "+someData);
}
Optional blends well with lambda so you could rewrite that as..
Optional<Object> maybeSomething = doSomething();
maybeSomething.ifPresent(someData -> System.out.println("SomeData = " + someData);
or, if you don't need to do more work with someData you could even do
doSomething().ifPresent(someData -> System.out.println("SomeData = " + someData);
I need specific data for a report, then I gettin all information from a parent object
Object1
It has many attributes, object attributes
Object11, Object12, Object13, attr1, attr2...
The attributes has many attributes too
Object111, Object131, Object132,..
by now I got 5 level data attributes.
When I send information to my report it says, Error: cause:null
object1.getIdObject11().getIdObject111().getDescription;
It trows error because Object111 is null
I tried using
object1.getIdObject11().getIdObject111().getDescription==null?'':object1.getIdObject11().getIdObject111().getDescription;
but it only verify if description is null, and throws the same error
Then I tried to verify Object
if(object1.getIdObject11().getIdObject111() == null) {
var = object1.getIdObject11().getIdObject111().getDescription;
} else {
var = "";
}
But when Object11 is null, it throws same error.
I don't think its a good way doing this for each attribute (have to get like 30 attributes)
if(object1.getIdObject11()!=null) {
if(object1.getIdObject11().getIdObject111()!=null) {
if(object1.getIdObject11().getIdObject111().getIdObject1111()!=null) {
//...
}
}
}
I want to verify if is there a null object and set '' (blank) if it is, with no such a large code(because the gotten params are set inside a report, mixed with letter).
reportline1 = "Area: "+object1.getIdObject11().getIdObject111().getName;
You code breaks Demeter's law. That's why it's better to refactor the design itself.
As a workaround, you can use Optional
var = Optional.ofNullable(object1)
.map(o -> o.getIdObject11())
.map(o -> o.getIdObject111())
.map(o -> o.getDescription())
.orElse("")
The way I would probably do this to extend the functionality of the code easily in the future might take a bit of writing in the beginning but will be easily usable forever.
I would create a new method in your parent class called hasNull that returns a boolean like so:
public boolean hasNull()
{
boolean hasANull = false;
//Call another hasNull() inside of object11 which in turns calls hasNull() in object111 etc.
//If any of the calls return with a true/null value set hasANull to true
return hasANull;
}
This in turn checks to see if the current objects it contains are null. If one of the class variables is another custom class you created you can then add another hasNull into that one and keep going until you get to the lowest level where you can do a specific operation when the value is null such as set it to "".
After implementing this you will be able to just be able to use it like this any time you need it:
if (!object1.hasNull())
{
//Do whatever you want if there are no null values
}
else
{
//Do whatever you want if there is a null value
}
You can also make this a void method if you only want it to toggle the values on the lowest level, and do not need to do anything in either case.
I prefer the solution that gave dehasi.
But you can also do something like that:
getOrElse(() -> object1.getIdObject11().getIdObject111().getDescription(), "")
Where getOrElse is:
public static <T> T getOrElse(Supplier<T> getter, T elseValue) {
try {
return getter.get();
} catch (Exception e) {
// log or do something with it
}
return elseValue;
}
It may be controversial becaouse you use Exception to do this.
You can use this code to check if your object has a null attribute, the object is myclass;
for (Field f : myclass.getClass().getDeclaredFields()) {
f.setAccessible(true);
try {
if (Objects.isNull(f.get(myclass))) {
isLineContainsNull = true;
}
} catch (Exception e) {
log.error(e.getMessage());
}
}
I try to add some items to a JComboBox and I receive a NullPointerException error.
This is a sample of my code :
public adminPanel() {
fillComboTeacher();
initComponents();
}
public void fillComboTeacher(){
HashSet<Person> set = cont1.returnTeachers();
Iterator it = set.iterator();
try {
while (it.hasNext()) {
Person p = (Person) it.next();
String name = p.getName();
comboTeacher.addItem(name);
}
} catch (Exception e) {
System.out.println(e);
}
}
Person class - name, state (with getters and setters)
returnTeachers() - returns a HashSet containing Persons with state = "Teacher"
I don't understand why I'm receiving this error and why I can't fill the ComboBox, I followed a tutorial step-by-step and something is still not well.
Thanks!
You are calling fillComboTeacher before calling initComponents.
Looking at the method's name, I assumed that you initialized comboTeacher in the latter.
So at that point (comboTeacher.addItem(name);), comboTeacher is not yet initialized and hence the NullPointerException.
To fix this, just swap the two method calls in the constructor to initialize your components before trying to use them.
Few notes:
A NullPointerException is often easy to fix. Just look at the stacktrace (it indicates the line where the NPE occurs) and see what can be null and why at this line.
Don't use a raw iterator, but a generic one (Iterator<Person> it = set.iterator();), that will avoid you to cast the object returned by a next() call.
Since you are only reading the elements in the set, you can simply use a for-each loop for(Person p : cont1.returnTeachers()) comboTeacher.addItem(p.getName());
In code we have got a lot of chain methods, for example obj.getA().getB().getC().getD(). I want to create helper class which will check if method getD() isn't null, but before that I need to check all previous getters. I can do it in this way:
try {
obj.getA().getB().getC().getD();
}
catch (NullPointerException e) {
// some getter is null
}
or (which is "silly")
if (obj!null && obj.getA()!=null && obj.getA().getB()!=null && ...) {
obj.getA().getB().getC().getD();
}
else {
// some getter is null
}
I don't want to check it every time using try{} catch() in my code. What is the best solution for this purpose?
I think that the best will be:
obj.getA().getB().getC().getD().isNull() - for this purpose I will need to change all of my getters, for example implement some interface which contains isNull() method.
NullObjectHelper.isNull(obj.getA().getB().getC().getD()); - this will be the best (I think so) but how to implement this?
As of Java 8 you can use methods like Optional.isPresent and Optional.orElse to handle null in getter chains:
boolean dNotNull = Optional.ofNullable(obj)
.map(Obj::getA)
.map(A::getB)
.map(B::getC)
.map(C::getD)
.isPresent();
While this is preferable to catching NullPointerException the downside of this approach is the object allocations for Optional instances.
It is possible to write your own static methods that perform similar operations without this overhead:
boolean dNotNull = Nulls.isNotNull(obj, Obj::getA, A::getB, B::getC, C::getD);
For a sample implementation, see the Nullifier type here.
No approach is likely to have greater runtime efficiency than nested if-not-null checks.
You can achieve the desired result with Option pattern. This enforces you to change a method signature, but basically if your method returns some type T, it guarantees it has some non-null value, and if it returnsOption<T> it means it either has value T, or null.
Java 7 had some feature called null safety, but it was removed from the final release. You could do:
obj?.getA()?.getB()?.getC()?.getD()
Moreover, Java 8 will add a feature called Optional so you would do it safely.
In fact, if you really want to use that now, try Null Object pattern. It means that instead of returning plain null you can return some sort of default value, which won't trigger NullPointerException. Though, you need add some changes to your getters
class Object {
A getA() {
// ...
return a == null ? A.NULL : a;
}
}
class A {
static A NULL = new A(); // some default behaviour
B getB() {
if (this == NULL) return B.NULL;
// ...
return b == null ? B.NULL : b;
}
}
EDIT: If you want utility to do it you can wrap it in some functional interface and then call it.
static boolean isNullResult(Callable call) throws Exception {
try {
return call.call() == null;
} catch (NullPointerException npe) {
return true;
}
}
Usage will be the following:
isNullResult(new Callable<Integer>() {
#Override
public Integer call() throws Exception {
return new A().getB().getC().getInt();
}
});
It won't require you to change existing functionality
As already stated, the true solution is refactoring.
In the meantime, you could just wrap your first workaround in a function:
static D getD(MyClass obj) {
try {
return obj.getA().getB().getC().getD();
}
catch (NullPointerException e) {
return null; // Or even better, some default D
}
}
At the caller site:
D d = getD(obj);
At least you don't have to trash the caller with try-catch blocks. You still need to handle the errors somehow, when some of the intermediate getX() call returns a null and so d becomes null. The best would be to return some default D in the wrapper function.
I don't see how the two options you list at the end of your question would help if any of the intermediate getX() returns a null; you will get a NullPointerException.
I'm looking for a Google Collections method that returns the first result of a sequence of Suppliers that doesn't return null.
I was looking at using Iterables.find() but in my Predicate I would have to call my supplier to compare the result against null, and then have to call it again once the find method returned the supplier.
Given your comment to Calm Storm's answer (the desire not to call Supplier.get() twice), then what about:
private static final Function<Supplier<X>, X> SUPPLY = new Function<....>() {
public X apply(Supplier<X> in) {
// If you will never have a null Supplier, you can skip the test;
// otherwise, null Supplier will be treated same as one that returns null
// from get(), i.e. skipped
return (in == null) ? null : in.get();
}
}
then
Iterable<Supplier<X>> suppliers = ... wherever this comes from ...
Iterable<X> supplied = Iterables.transform(suppliers, SUPPLY);
X first = Iterables.find(supplied, Predicates.notNull());
note that the Iterable that comes out of Iterables.transform() is lazily-evaluated, therefore as Iterables.find() loops over it, you only evaluate as far as the first non-null-returning one, and that only once.
You asked for how to do this using Google Collections, but here's how you would do it without using Google Collections. Compare it to Cowan's answer (which is a good answer) -- which is easier to understand?
private static Thing findThing(List<Supplier<Thing>> thingSuppliers) {
for (Supplier<Thing> supplier : thingSuppliers) {
Thing thing = supplier.get();
if (thing != null) {
return thing;
}
}
// throw exception or return null
}
In place of the comment -- if this was the fault of the caller of your class, throw IllegalArgumentException or IllegalStateException as appropriate; if this shouldn't have ever happened, use AssertionError; if it's a normal occurrence your code that invokes this expects to have to check for, you might return null.
What is wrong with this?
List<Supplier> supplierList = //somehow get the list
Supplier s = Iterables.find(supplierList, new Predicate<Supplier>(){
boolean apply(Supplier supplier) {
return supplier.isSomeMethodCall() == null;
}
boolean equals(Object o) {
return false;
}
});
Are you trying to save some lines? The only optimisation I can think is to static import the find so you can get rid of "Iterables". Also the predicate is an anonymous inner class, if you need it in more than one place you can create a class and it would look as,
List<Supplier> supplierList = //somehow get the list
Supplier s = find(supplierList, new SupplierPredicateFinder());
Where SupplierPredicateFinder is another class.
UPDATE : In that case find is the wrong method. You actually need a custom function like this which can return two values. If you are using commons-collections then you can use a DefaultMapEntry or you can simply return an Object[2] or a Map.Entry.
public static DefaultMapEntry getSupplier(List<Supplier> list) {
for(Supplier s : list) {
Object heavyObject = s.invokeCostlyMethod();
if(heavyObject != null) {
return new DefaultMapEntry(s, heavyObject);
}
}
}
Replace the DefaultMapEntry with a List of size 2 or a hashmap of size 1 or an array of length 2 :)