Important Notice - Forums is archived
To simplify things and help our users to be more productive, we have archived the current forum and focus our efforts on helping developers on Stack Overflow. You can post new questions on Stack Overflow or join our Discord channel.

Vaadin lets you build secure, UX-first PWAs entirely in Java.
Free ebook & tutorial.
ConcurrentModificationException on Thread
Hi guys, Please HELP!
Been trying to solve this issue since last night and still cant find any solution. some of you might have encountered and could share ideas on how to solve this.
PayrollDataGridProperties payroll = new PayrollDataGridProperties(); //GRID
generateBtn.addClickListener((Button.ClickEvent event) -> {
payroll.getContainerDataSource().removeAllItems();
getUI().getSession().getLockInstance();
try {
MyRunnable run = new MyRunnable();
Thread t = new Thread(run);
t.start();
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(PayrollByGroupUI.class.getName()).log(Level.SEVERE, null, ex);
}
UI.getCurrent().setPollInterval(500);
});
void processPayroll(int employeeId){
Employee e = es.findEmployeeById(employeeId);
double basicSalary = cps.findMonthlySalary(cps.findSalaryGrade(
pcps.findPCP(
e.getPositionClassificationPlanId()).getCompensationPlanID()).getSalaryGrade(),
e.getCompensationPlanStep(),
CommonUtil.convertStringToInteger(sslComboBox.getValue().toString()));
double taxableSalary = atacs.taxableSalary(basicSalary, e.getDependent())/12;
double grossAmount = basicSalary + PayrollConstants.PERA;
double withholding = atacs.monthlyTaxDue(taxableSalary, e.getDependent());
double rlip = atacs.monthlyGsis(basicSalary);
double phic = atacs.monthlyPhic(basicSalary);
double hdmf = atacs.monthlyHdmf(basicSalary);
double totalDeduction = els.findTotalLoanByEmployee(employeeId) + withholding + rlip + phic + hdmf;
double netAmountPay = grossAmount - totalDeduction;
payroll.addRow(basicSalary,
0.0,
basicSalary,
PayrollConstants.PERA,
grossAmount,
withholding,
rlip,
phic,
hdmf,
totalDeduction,
netAmountPay,
netAmountPay/2,
netAmountPay/2);
}
class MyRunnable implements Runnable {
@Override
public void run() {
List<Employee> eList = es.findAllByPap(getDataId());
synchronized(eList){
for(Employee e : eList){
processPayroll(e.getEmployeeId());
if(current < dataSize){
status.setValue(""+(CommonUtil.roundOffToTwoDecimalPlaces((current/dataSize)*100))+"%");
current += 1;
progress.setValue(new Float(current/dataSize));
} else {
status.setValue("Finished... 100%");
}
}
}
}
}
First attempt to execute the code will cause an error:
java.util.ConcurrentModificationException
at java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1216)
at java.util.ArrayList$SubList.size(ArrayList.java:1025)
at java.util.Collections$UnmodifiableCollection.size(Collections.java:1090)...
second attempt will cause an error:
Exception in thread "Thread-37" java.lang.IllegalStateException: A connector should not be marked as dirty while a response is being written.
at com.vaadin.ui.ConnectorTracker.markDirty(ConnectorTracker.java:505)
at com.vaadin.server.AbstractClientConnector.markAsDirty(AbstractClientConnector.java:141)
at com.vaadin.server.communication.data.RpcDataProviderExtension.insertRowData(RpcDataProviderExtension.java:450)
after I try again to execute the code It will run without a problem. I already have a previous project using the same execution but I dont know what causes the error on this one. It will only load about 400+ data to the Grid.
Agata Vackova: Use ui.access(runnable), when updating UI form another thread: Server Push.
I've tried your suggestion but all the data was loaded in a Grid at the same time. I want to see the grid updated row by row to verify that all data are being loaded inside the Grid when clicking the button with Threading.
I tried this approach:
generateBtn.addClickListener((Button.ClickEvent event) -> {
getUI().getSession().getLockInstance();
try {
MyRunnable run = new MyRunnable();
Thread.sleep(1000);
UI.getCurrent().access(run);
} catch (InterruptedException ex) {
Notification.show("Error on Group Payroll Thread!", Notification.Type.ERROR_MESSAGE);
Logger.getLogger(PayrollByGroupUI.class.getName()).log(Level.SEVERE, null, ex);
}
UI.getCurrent().setPollInterval(500);
});
and this one:
generateBtn.addClickListener((Button.ClickEvent event) -> {
getUI().getSession().getLockInstance();
new ProcessGroupPayroll().start();
UI.getCurrent().setPollInterval(500);
});
class ProcessGroupPayroll extends Thread {
@Override
public void run(){
try {
Thread.sleep(1000);
UI.getCurrent().access(new Runnable() {
@Override
public void run() {
List<Employee> eList = es.findAllByPap(getDataId());
synchronized(eList){
for(Employee e : eList){
processPayroll(e.getEmployeeId());
if(current < dataSize){
status.setValue(""+(CommonUtil.roundOffToTwoDecimalPlaces((current/dataSize)*100))+"%");
current += 1;
progress.setValue(new Float(current/dataSize));
} else {
status.setValue("Finished... 100%");
}
}
}
}
});
UI.getCurrent().access(new Runnable() {
@Override
public void run() {
savePayroll.setEnabled(true);
}
});
} catch (InterruptedException ex) {
Logger.getLogger(PayrollByGroupUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Both solution as provided me the same output...
Try to lock session during adding the row only:
UI.getCurrent().access(() -> {
payroll.addRow(basicSalary,
0.0,
basicSalary,
PayrollConstants.PERA,
grossAmount,
withholding,
rlip,
phic,
hdmf,
totalDeduction,
netAmountPay,
netAmountPay/2,
netAmountPay/2)
});[/code]
What do you mean by locking the session during adding the row?
PayrollDataGridProperties payroll = new PayrollDataGridProperties(); //GRID
generateBtn.addClickListener((Button.ClickEvent event) -> {
payroll.getContainerDataSource().removeAllItems();
try {
MyRunnable run = new MyRunnable();
Thread t = new Thread(run);
t.start();
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(PayrollByGroupUI.class.getName()).log(Level.SEVERE, null, ex);
}
UI.getCurrent().setPollInterval(500);
});
void processPayroll(int employeeId){
Employee e = es.findEmployeeById(employeeId);
double basicSalary = cps.findMonthlySalary(cps.findSalaryGrade(
pcps.findPCP(
e.getPositionClassificationPlanId()).getCompensationPlanID()).getSalaryGrade(),
e.getCompensationPlanStep(),
CommonUtil.convertStringToInteger(sslComboBox.getValue().toString()));
double taxableSalary = atacs.taxableSalary(basicSalary, e.getDependent())/12;
double grossAmount = basicSalary + PayrollConstants.PERA;
double withholding = atacs.monthlyTaxDue(taxableSalary, e.getDependent());
double rlip = atacs.monthlyGsis(basicSalary);
double phic = atacs.monthlyPhic(basicSalary);
double hdmf = atacs.monthlyHdmf(basicSalary);
double totalDeduction = els.findTotalLoanByEmployee(employeeId) + withholding + rlip + phic + hdmf;
double netAmountPay = grossAmount - totalDeduction;
UI.getCurrent().access(() -> {
payroll.addRow(basicSalary,
0.0,
basicSalary,
PayrollConstants.PERA,
grossAmount,
withholding,
rlip,
phic,
hdmf,
totalDeduction,
netAmountPay,
netAmountPay/2,
netAmountPay/2);
});
}
class MyRunnable implements Runnable {
@Override
public void run() {
List<Employee> eList = es.findAllByPap(getDataId());
synchronized(eList){
for(Employee e : eList){
processPayroll(e.getEmployeeId());
UI.getCurrent().access(() -> {
if(current < dataSize){
status.setValue(""+(CommonUtil.roundOffToTwoDecimalPlaces((current/dataSize)*100))+"%");
current += 1;
progress.setValue(new Float(current/dataSize));
} else {
status.setValue("Finished... 100%");
}
});
}
}
}
};