ObservableList throwing NullPointerException - java

I am adding some elements to an ObservableList in JavaFX and after adding some items I start getting NullPointerException for all the items I add. According to the JavaDoc the add() method throws NullPointerException when:
NullPointerException - if the specified element is null and this list
does not permit null elements
But as you can see while I'm debugging my element is NOT null:
So why I am getting this NullPointerException?
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at javafx.scene.chart.XYChart$Series$1.onChanged(XYChart.java:1525)
at com.sun.javafx.collections.ListListenerHelper$SingleChange.fireValueChangedEvent(ListListenerHelper.java:158)
at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:72)
at javafx.collections.ObservableListBase.fireChange(ObservableListBase.java:233)
at javafx.collections.ListChangeBuilder.commit(ListChangeBuilder.java:482)
at javafx.collections.ListChangeBuilder.endChange(ListChangeBuilder.java:541)
at javafx.collections.ObservableListBase.endChange(ObservableListBase.java:205)
at javafx.collections.ModifiableObservableListBase.add(ModifiableObservableListBase.java:155)
at java.util.AbstractList.add(AbstractList.java:108)
at sample.Main$1.handle(Main.java:115)
at javafx.animation.AnimationTimer$AnimationTimerReceiver$1.run(AnimationTimer.java:58)
at javafx.animation.AnimationTimer$AnimationTimerReceiver$1.run(AnimationTimer.java:56)
at java.security.AccessController.doPrivileged(Native Method)
at javafx.animation.AnimationTimer$AnimationTimerReceiver.handle(AnimationTimer.java:56)
at com.sun.scenario.animation.AbstractMasterTimer.timePulseImpl(AbstractMasterTimer.java:359)
at com.sun.scenario.animation.AbstractMasterTimer$MainLoop.run(AbstractMasterTimer.java:269)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:475)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:460)
at com.sun.javafx.tk.quantum.QuantumToolkit$13.run(QuantumToolkit.java:327)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.access$300(WinApplication.java:39)
at com.sun.glass.ui.win.WinApplication$4$1.run(WinApplication.java:112)
at java.lang.Thread.run(Thread.java:745)
Where sample.Main$1.handle(Main.java:115) is where I use the add() method.
EDIT:
It seems it only happens when I add the items inside things like TimerTask() or AnimationTimer():
new AnimationTimer(){
#Override
public void handle(long now) {
for (XYChart.Data<Double, Double> data : fullDataQueue){
chartData.add(data);
}
}
}.start();
Otherwise I'm not getting this expection!
EDIT 2:
Ok I think I know what the problem is, here is the test code:
#Test
public void testSeriesAddInAnimator(){
// Data
XYChart.Series<Double, Double> series = new XYChart.Series<>();
ConcurrentLinkedQueue<XYChart.Data<Double, Double>> fullDataQueue = new ConcurrentLinkedQueue<>();
ObservableList<XYChart.Data<Double, Double>> chartData = FXCollections.observableArrayList();
series.setData(chartData);
// Start adding data
final Random random = new Random();
for(int n = 0; n < 10000; ++n){
fullDataQueue.add(new XYChart.Data<>((double)n, random.nextDouble()));
}
new AnimationTimer(){
#Override
public void handle(long now) {
for (XYChart.Data<Double, Double> data : fullDataQueue){
chartData.add(data);
}
System.out.println("Stop!");
//stop(); -> Uncomment this and we get no exception!
}
}.start();
System.out.println("Done testSeriesAddInAnimator()!");
}
This seems to happens if I re-add existing data in the Series. It's not RT-37798 bug, but I think it's a bug too. If we comment stop() method inside AnimationTimer the same data will be re-added and we start getting all this NullPointerException.
The exception is in XYChart.java line 1525:
for(int i=c.getFrom(); i<c.getTo(); i++) {
getData().get(i).setSeries(Series.this);
// update linkedList Pointers for data in this series
if (begin == null) {
begin = getData().get(i);
begin.next = null;
} else {
if (i == 0) {
getData().get(0).next = begin;
begin = getData().get(0);
} else {
Data<X,Y> ptr = begin;
for (int j = 0; j < i -1 ; j++) {
ptr = ptr.next; // NPE HERE!!!!!
}
getData().get(i).next = ptr.next;
ptr.next = getData().get(i);
}
}
}
But if I try to remove all items in the ObservableList and then add the ones I want I get the NullPointerException related to the bug you mentioned (RT-37798). So it seems I'm doomed, nothing I can do until they fix the bug.

It looks like it isn't data, but one of datas components that is null.
I couldn't find matching source code, but if you look at
javafx.scene.chart.XYChart$Series$1.onChanged(XYChart.java:1525)
Im confident that you find a dereferencing of a component of data.

Ok it seems that RT-37798 bug is solved in JDK 8u20 Build 21. Will submit the bug I am having to see If I can get some response (https://javafx-jira.kenai.com/browse/RT-37824).
Thank you for your help!

Related

Compose variable number of ListenableFuture

I'm quite new to Futures and am stuck on chaining calls and create a list of objects. I'm using Android, API min is 19.
I want to code the method getAllFoo() below:
ListenableFuture<List<Foo>> getAllFoo() {
// ...
}
I have these 2 methods available:
ListenableFuture<Foo> getFoo(int index) {
// gets a Foo by its index
}
ListenableFuture<Integer> getNbFoo() {
// gets the total number of Foo objects
}
Method Futures.allAsList() would work nicely here, but my main constraint is that each call to getFoo(int index) cannot occur until the previous one is completed.
As far as I understand it (and tested it), Futures.allAsList() "fans-out" the calls (all the calls start at the same time), so I can't use something like that:
ListenableFuture<List<Foo>> getAllFoo() {
// ...
List<ListenableFuture<Foo>> allFutureFoos = new ArrayList<>();
for (int i = 0; i < size; i++) {
allFutureFoos.add(getFoo(i));
}
ListenableFuture<List<Foo>> allFoos = Futures.allAsList(allFutureFoos);
return allFoos;
}
I have this kind of (ugly) solution (that works):
// ...
final SettableFuture<List<Foo>> future = SettableFuture.create();
List<Foo> listFoos = new ArrayList<>();
addApToList(future, 0, nbFoo, listFoos);
// ...
private ListenableFuture<List<Foo>> addFooToList(SettableFuture future, int idx, int size, List<Foo> allFoos) {
Futures.addCallback(getFoo(idx), new FutureCallback<Foo>() {
#Override
public void onSuccess(Foo foo) {
allFoos.add(foo);
if ((idx + 1) < size) {
addFooToList(future, idx + 1, size, allFoos);
} else {
future.set(allFoos);
}
}
#Override
public void onFailure(Throwable throwable) {
future.setException(throwable);
}
});
return future;
}
How can I implement that elegantly using ListenableFuture ?
I found multiple related topics (like this or that), but these are using "coded" transform, and are not based on a variable number of transformations.
How can I compose ListenableFutures and get the same return value as Futures.allAsList(), but by chaining calls (fan-in)?
Thanks !
As a general rule, it's better to chain derived futures together with transform/catching/whennAllSucceed/whenAllComplete than with manual addListener/addCallback calls. The transformation methods can do some more for you:
present fewer opportunities to forget to set an output, thus hanging the program
propagate cancellation
avoid retaining memory longer than needed
do tricks to reduce the chance of stack overflows
Anyway, I'm not sure there's a particularly elegant way to do this, but I suggest something along these lines (untested!):
ListenableFuture<Integer> countFuture = getNbFoo();
return countFuture.transformAsync(
count -> {
List<ListenableFuture<Foo>> results = new ArrayList<>();
ListenableFuture<?> previous = countFuture;
for (int i = 0; i < count; i++) {
final int index = i;
ListenableFuture<Foo> current = previous.transformAsync(
unused -> getFoo(index),
directExecutor());
results.add(current);
previous = current;
}
return allAsList(results);
},
directExecutor());

java.util.ConcurrentModificationException in Android Game Loop

I am using a canvas, moving objects on the screen, when an object hit the left side of the canvas (x=0), another object of the same type gets instantiated, and start moving on the screen.
Everything works fine, a few objects gets created and start moving around the screen.
At a certain point, I receive a concurrent modification exception in my run method where the game loop is, where gameObjs is an ArrayList:
#Override
public void run() {
while(isRunning){
if(!myHolder.getSurface().isValid())
continue;
Canvas canvas = myHolder.lockCanvas();
canvas.drawRect(0,0,canvas.getWidth(), canvas.getHeight(), pWhite);
for(MyGameObject gameObj : gameObjs){
gameObj.move(canvas);
}
myHolder.unlockCanvasAndPost(canvas);
}
}
I've tried to use an Iterator, but still getting the same error.
I really appreciate your help. Thank you in advance!
Collections.synchronizedList(...) won't work if something like this is happening... (throws a ConcurrentModificationException...)
public class ConcurrentTest {
public static void main(String[] args) {
List<String> things = new ArrayList<>();
Runnable modifyThread = () -> {
while(true) {
for(int k = 0; k < 1000; k++) {
things.add(String.valueOf(k));
}
while(!things.isEmpty()) {
things.remove(0);
}
}
};
Runnable readThread = () -> {
while(true) {
for(String thing : Collections.synchronizedList(things)) {
System.out.println(thing);
}
}
};
new Thread(modifyThread).start();
new Thread(readThread).start();
}
}
Try and find other places in your code where this list is being modified. There must be another thread manipulating the collection while you are iterating through it.
You could take a copy of the list before iterating over it.
For example, in the code above, try...
for(String thing : new ArrayList<>(things)) {
...instead of...
for(String thing : Collections.synchronizedList(things)) {
...and you will no longer get an exception (but this still won't be "correct", if you run it, you will see loads of nulls being printed out...)
Even better, keep the read loop as...
for(String thing : things) {
...but change the type of list...
List<String> things = new CopyOnWriteArrayList<>();

ArrayList in Session object seems to lose contents

I'm having a problem with retrieving and casting ArrayList from session. I get the following error:
javax.servlet.ServletException: java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
I stored the arrayList in the session:
List<UserApplication> userList = uaDAO.searchUser(eds);
if (!userList.isEmpty()) {
request.getSession().setAttribute("userList", userList);
action_forward = EDITSUCCESS;
and for casting the session object to ArrayList, did the following:
EditStudentForm edt = (EditStudentForm)form;
if ((session.getAttribute("userList")) instanceof List){
List <UserApplication> studtList = (ArrayList<UserApplication>)session.getAttribute("userList");
}
try {
uaDAO.editUser(edt,studtList);
action_forward = EDITSUCCESS;
}
I'm getting the error over here in the DAO class:
public void editUser(EditStudentForm edt,List studtList) throws Exception {
PreparedStatement pst = null;
StringBuilder sb = new StringBuilder();
int stCode =Integer.parseInt(studtList.get(1).toString()); GETTING ERROR HERE
if (edt.getTitle() != null && !edt.getTitle().equals(studtList.get(2).toString())) {
sb.append("title = '").append(edt.getTitle()).append("'");
}
.
.
You are explicitly asking for 2nd (studtList.get(1)) and 3rd (studtList.get(2)) item in the list but never really make sure this list is big enough. Moreover your code apparently doesn't even compile:
if ((session.getAttribute("userList")) instanceof List){
List <UserApplication> studtList = ///...
}
try {
uaDAO.editUser(edt,studtList);
studtList is unaccessible in try block, also parenthesis in if statement are unmatched.
Check your studtList value.
From the error it seems your studtList only contain one item and you're try to get the second item with this code :
int stCode =Integer.parseInt(studtList.get(1).toString());
Change your code like this :
public void editUser(EditStudentForm edt,List studtList) throws Exception {
PreparedStatement pst = null;
StringBuilder sb = new StringBuilder();
if(studtList.size() > 1)
int stCode =Integer.parseInt(studtList.get(1).toString()); GETTING ERROR HERE
if (studtList.size() > 2 && edt.getTitle() != null && !edt.getTitle().equals(studtList.get(2).toString())) {
sb.append("title = '").append(edt.getTitle()).append("'");
}
}
In studtList there are no two elements and size of list maybe 1 or 0 elements, you should check it before try to call studtList.get(1). In ArrayList indexing start from 0 and if you want get first element you should call studtList.get(0).
In this code:
EditStudentForm edt = (EditStudentForm)form;
if ((session.getAttribute("userList")) instanceof List){
List <UserApplication> studtList = (ArrayList<UserApplication>)session.getAttribute("userList");
}
try {
uaDAO.editUser(edt,studtList);
action_forward = EDITSUCCESS;
}
You create a new variable 'studtList' that is never used. It's scope is only the { } pair around that one line.
There has to be another variable by that same name, studtList, in the outer scope so the 'editUser()' call can work.
Additional Note
As the other folks have answered, it looks like you may be doing a .get(1) and expecting the first element of the array list. Maybe. Maybe not.

ConcurrentModificationException for Java LinkedList

I have LinkedList of objects and an iterator. I know that this ConcurrentModificationException is thrown when you try to modify the list while running the iterator. But in my case, I don't understand where this modification is being done.
The iterator looks like this :
private static void insertTasks(Task t) {
if(eventQueue.size() == 0) {
eventQueue.addFirst(tsk);
return;
}
int pos = 0;
while (itr.hasNext()){
//The line below throws the exception
if (t.getArrivalTime() <= itr.next().getArrivalTime() )
{
break;
}
pos++;
}
}
I am calling this insertTasks method from another method as shown below :
tsk = null;
tsk = new Task(1,"P1",1,4.0f,1.5f,0.0f,8.0f);
insertTasks(tsk);
tsk = null;
tsk = new Task(0,"P0",2,5.0f,2.5f,1.0f,10.0f);
insertTasks(tsk);
The getArrivalTime in the Task objects looks like :
public float getArrivalTime() { return arrivalTime; }
My question is, where am I doing this modification ? The while loop where I run this iterator is not doing any modification. Does it ?
Am I missing something ?
I reckon the problem is that itr is a static field in your class and that's creating the issue, as you're adding an element to eventQueue in your second call to insertTasks().
Avoid static fields... program yourself to fear them and avoid them as much as you can :). They evil, and OO unfriendly.

concurrentexception i don't understand where it's the error

I receive this exception
Exception in thread "Thread-3" java.util.ConcurrentModificationException
at java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:761)
at java.util.LinkedList$ListItr.next(LinkedList.java:696)
at ServerMultiThread.run(ServerMultiThread.java:89)
at java.lang.Thread.run(Thread.java:680)
from this code:
synchronized(itemsList)
{
if(itemsList.isEmpty())
{
item.initCounter();
itemsList.add(item);
pw.println("It's the first time you connect to server!");
}
else
{
for(ItemClient itm : itemsList)
{
if(itm.equals(item))
{
int value = itm.getCounter();
value++;
itm.setCounter(value);
pw.println(itm.getCounter());
}
else
{
item.initCounter();
itemsList.add(item);
pw.println("It's the first time you connect to server!");
}
}
}
}
the row 89 corresponds to this for(ItemClient itm : itemsList). Why I receive this error?
You are changing the LinkedList content inside the for-each loop. The implementation of the LinkedList iterator checks on the next call to next() if the list has changed and throws the exception (sad I know ...).
The enhanced for loop is used to iterate over the given set of values, but during iteration you are modifying the contents of the same, that's why you getting that error, instead use a normal for loop to do your stuff for this thing.
Regards
Sadly, there is no easy way around it. As the others have said, you cannot modify a collection inside this kind of loop. Your other option is to use a normal for loop. However, accessing a LinkedList by index like:
for(int i = 0; i < list.size(); i++) {
list.get(i);
}
takes O(N) time for each item, because the linked list needs to be traversed from the beginning each time.
If the linked list is not essential to your algorithm, I suggest you to use an ArrayList instead and change your code as follows:
for(int i = 0; i < itemsList.size(); i++) {
itm = itemsList.get(i);
if(itm.equals(item)) {
int value = itm.getCounter();
value++;
itm.setCounter(value);
pw.println(itm.getCounter());
} else {
item.initCounter();
itemsList.add(item);
pw.println("It's the first time you connect to server!");
}
}
This will not throw the exception, but it's still not a nice piece of code because you are adding to the list while iterating and that is never a good idea.
I hope you had patience to read so far!
My final suggestion for you is to hold a temporary list of elements that you need to add and append them to the initial list at the end of the loop. This way you can keep all your original code and the LinkedList:
LinkedList<ItemClient> tempList = new LinkedList<ItemClient>();
for(ItemClient itm: itemsList) {
itm = itemsList.get(i);
if(itm.equals(item)) {
int value = itm.getCounter();
value++;
itm.setCounter(value);
pw.println(itm.getCounter());
} else {
item.initCounter();
tempList.add(item);
pw.println("It's the first time you connect to server!");
}
}
itemsList.addAll(tempList);

Categories

Resources