Java error Concurrent modification Exception - java

I need help for this case below :
I have 2 method :
private void calculateTime(Map.Entry<List<String>, List<LogRecord>> entry, List<LogProcess> processList) {
List<List<LogRecord>> processSpentTime = new ArrayList<List<LogRecord>>();
processSpentTime = subListProcess(entry, processSpentTime);
for (List<LogRecord> item : processSpentTime) {
processList = parse(item, DEFAULT_START_LEVEL);
}
}
and the second method
private List<LogProcess> parse(List<LogRecord> recordList, int level) {
List<LogProcess> processList = new ArrayList<LogProcess>();
if(!recordList.isEmpty()) {
LogProcess process = findProcess(recordList, level);
if(!(process instanceof NullLogProcess)) {
if(!(process instanceof IncompleteLogProcess)) {
processList.add(process);
}
int fromIndex = recordList.indexOf(process.returnStartIndexOfNextProcess()) + 1;
processList.addAll(parse(recordList.subList(fromIndex, recordList.size()), level));
}
}
return processList;
}
public LogProcess findProcess(List<LogRecord> recordList, int level) {
LogRecord endRecord = null;
LogRecord startRecord = findStartRecord(recordList);
if(startRecord instanceof NullLogRecord) {
return new NullLogProcess();
}
List<LogRecord> startEndRecord = findStartEndRecord(startRecord, recordList);
startRecord = startEndRecord.get(0);
endRecord = startEndRecord.get(1);
LogProcess process = returnLogProcess(startRecord, endRecord);
process.setLevel(level);
process.setChildren(findChildProcess(recordList, startRecord, endRecord, level + 1));
return process;
}
private List<LogProcess> findChildProcess(List<LogRecord> recordList, LogRecord startRecord, LogRecord endRecord, int level) {
int fromIndex = recordList.indexOf(startRecord) + 1;
int toIndex = recordList.indexOf(endRecord);
if(toIndex > fromIndex) {
List<LogRecord> recordSubList = recordList.subList(fromIndex, toIndex);
return parse(recordSubList, level);
} else {
return new ArrayList<LogProcess>();
}
}
private List<LogRecord> findStartEndRecord(LogRecord startRecord, List<LogRecord> recordList) {
List<LogRecord> startEndRecord = new ArrayList<LogRecord>();
if (!recordList.isEmpty()) {
startEndRecord.add(startRecord);
for (LogRecord record : recordList) {
boolean isStartRecord = record.isStartPoint() && record.hasSameActionName(startRecord);
if(isStartRecord){
startEndRecord = new ArrayList<LogRecord>();;
startEndRecord.add(record);
continue;
}
boolean isEndRecord = record.isEndPoint() && record.hasSameActionName(startRecord);
if (isEndRecord) {
startEndRecord.add(record);
return startEndRecord;
}
}
return startEndRecord;
}
return startEndRecord;
}
private LogRecord findStartRecord(List<LogRecord> recordList) {
for (LogRecord record : recordList) {
if (record.isStartPoint()){
recordList.remove(record);
return record;
}
}
return new NullLogRecord();
}
at the method calculatime in the for loop I just get the result for the first item, and after that I got error the same the title . please help me and explain me more for this case .

The name of this exception is a bit confusing, because it isn't related to multi threading.
What happens is that you are iterating over a collection which is being modified while you are iterating over it.
If performance is not your highest concern, a simple way out would be to copy the list and iterate over that copy and add items to the original list.

My guess is it's related to recordList.subList():
Returns a view of the portion of this list. [..] The returned list is backed by this list. [..] The semantics of the list returned by this method become undefined if the backing list (i.e., this list) is structurally modified in any way other than via the returned list. [..] All methods first check to see if the actual modCount of the backing list is equal to its expected value, and throw a ConcurrentModificationException if it is not.
I don't see any modification, so it probably happens in findProcess(). Consider creating a copy of that list:
new ArrayList(recordList.subList())

You are getting the exception because of this :
for (LogRecord record : recordList) {
if (record.isStartPoint()){
recordList.remove(record); <--- This is the cause
return record;
}
}
Use an Iterator Instead
Iterator<LogRecord> iterator = recordList.iterator();
while(iterator.hasNext()){
LogRecord logRecord = iterator.next();
if(record.isStartPoint()){
iterator.remove();
return logRecord;
}
Check if this works

Related

Strange behaviour with ArrayList

I'm in the process of building a basic database using csv files, and i'm currently testing the select function out when i ran into something strange.
private ArrayList<Record> selectField(String selectTerm)
{
Log.log("Selection " + selectTerm,2,"DB_io");
ArrayList<Record> ret = new ArrayList<Record>();
if (titleRow.values.contains(selectTerm))
{
Log.log("Adding values to " + selectTerm);
int ordinal = titleRow.values.indexOf(selectTerm);
Log.log("Ordinal " + ordinal);
List<String> tempList = new ArrayList<String>();
for (Record r : data)
{
List<String> tempList = new ArrayList<String>();
tempList.add(r.values.get(ordinal));
Record s = new Record(tempList);
ret.add(s);
tempList.clear();
}
Log.log("Number of records in ret " + ret.size());
for (Record t : ret)
{
Log.log(t.toString());
}
}
else
{
Log.log("keyField does not contain that field");
return null;
}
Log.log("Values " + ret.toString());
return ret;
}
When i do this, the part where it logs t.ToString() shows the record to be empty, whereas if i log it before tempList.clear(), it shows the record to be containing data like it should.
If i move the tempList declaration into the Record r : data loop, then it works fine and the Record t : ret loop works outputs the contents of the record like it should
Why is this?
Edit : Record class
public class Record
{
List<String> values = new ArrayList<String>();
public Record(List<String> terms)
{
this.values = terms;
}
public Record(String[] s)
{
this.values = Arrays.asList(s);
}
public String toString()
{
return values.toString();
}
}
Your Record instance holds a reference to the ArrayList instance you passed to its constructor. Therefore, when you call tempList.clear(), you clear the same List that your Record instance is holding a reference to.
You shouldn't call tempList.clear(), since you are creating a new ArrayList in each iteration of your loop anyway.
you are referencing object from more than one place and clear method is cleaning object by setting its reference to null:
instead of ret.add(s); you can use ret.add(s.clone());

Integrating Kafka with Apache Calcite

I'm trying to integrate calcite with Kafka, I refrenced CsvStreamableTable.
Each ConsumerRecord is convert to Object[] using the fowlloing code:
static class ArrayRowConverter extends RowConverter<Object[]> {
private List<Schema.Field> fields;
public ArrayRowConverter(List<Schema.Field> fields) {
this.fields = fields;
}
#Override
Object[] convertRow(ConsumerRecord<String, GenericRecord> consumerRecord) {
Object[] objects = new Object[fields.size()+1];
int i = 0 ;
objects[i++] = consumerRecord.timestamp();
for(Schema.Field field : this.fields) {
Object obj = consumerRecord.value().get(field.name());
if( obj instanceof Utf8 ){
objects[i ++] = obj.toString();
}else {
objects[i ++] = obj;
}
}
return objects;
}
}
Enumerator is implemented as following,one thread is constantly polling records from kafka and put them into a queue, getRecord() method poll from that queue:
public E current() {
return current;
}
public boolean moveNext() {
for(;;) {
if(cancelFlag.get()) {
return false;
}
ConsumerRecord<String, GenericRecord> record = getRecord();
if(record == null) {
try {
Thread.sleep(200L);
} catch (InterruptedException e) {
e.printStackTrace();
}
continue;
}
current = rowConvert.convertRow(record);
return true;
}
}
I tested SELECT STREAM * FROM Kafka.clicks, it works fine.
rowtime is the first column explicitly added,and the value is record Timestamp of Kafka.
But when I tried
SELECT STREAM FLOOR(rowtime TO HOUR)
AS rowtime,ip,COUNT(*) AS c FROM KAFKA.clicks GROUP BY FLOOR(rowtime TO HOUR), ip
It threw exception
java.sql.SQLException: Error while executing SQL "SELECT STREAM FLOOR(rowtime TO HOUR) AS rowtime,ip,COUNT(*) AS c FROM KAFKA.clicks GROUP BY FLOOR(rowtime TO HOUR), ip": From line 1, column 85 to line 1, column 119: Streaming aggregation requires at least one monotonic expression in GROUP BY clause
at org.apache.calcite.avatica.Helper.createException(Helper.java:56)
at org.apache.calcite.avatica.Helper.createException(Helper.java:41)
You need to declare that the "ROWTIME" column is monotonic. In MockCatalogReader, note how "ROWTIME" is declared monotonic in the "ORDERS" and "SHIPMENTS" streams. That’s why some queries in SqlValidatorTest.testStreamGroupBy() are valid and others are not. The key method relied up by the validator is SqlValidatorTable.getMonotonicity(String columnName).

How to Iterate over too big ArrayList<String>?

I have two ArrayList sourceMessageList and TargetMessageList. I need to compare both the message list data.
Now lets say List1 - 100 Records. List2 - 1000 records
From List1- 1st record is compared with each record in list2 and then List1- 2nd record is compared with each record in list2.
But list2 is getting the value hasNext() to true for 1st source data in list1.
private void compareMessageList(ArrayList<String> source_messageList, ArrayList<String> target_messageList)
throws Exception {
// TODO Auto-generated method stub
Iterator<String> sourceMessageIterator = source_messageList.iterator();
Iterator<String> targetMessageIterator = null;
while (sourceMessageIterator.hasNext()) {
String sourceMessage = (String) sourceMessageIterator.next();
targetMessageIterator = target_messageList.iterator();
while (targetMessageIterator.hasNext()) {
String targetMessage = (String) targetMessageIterator.next();
if (getCorpValue(sourceMessage).equalsIgnoreCase(getCorpValue(targetMessage))) {
assertXMLEquals(convertSwiftMessageToXML(sourceMessage), convertSwiftMessageToXML(targetMessage));
}
}
}
if (buffer.toString().length() > 0) {
writeDifferenceTofile(buffer.toString());
buffer.delete(0, buffer.length());
throw new CatsException("There are some differences in the files.");
}
System.out.println("Exiting now ...");
}
The above code is taking too much time to execute.
To speed things up:
HashMap<String, String> lowers = new HashMap<String, String>();
for (String source : source_messageList) {
lowers.put(getCorpValue(source).toLowerCase(), source);
}
for (String target : target_messageList) {
final String corpTarget = getCorpValue(target).toLowerCase();
if(lowers.containsKey(corpTarget)) {
assertXMLEquals(
convertSwiftMessageToXML(lowers.get(corpTarget)),
convertSwiftMessageToXML(target)
);
}
}

limit to display 50 from all the data

hello there i'm a little bit confuse with this code....sorry for my bad grammar..still new in this java.
private void loadSessionEvents() {
ArgumentBuilder arg = new ArgumentBuilder();
arg.addArg(getSessionLogId());
DBResult result = DBOperator.getInstance().doOperation(
FileOperation.class, "loadSessionLogEvents", arg.getTypeInfo());
// ArrayList<MsmLogIveScreenshots> logEvent =
// (ArrayList<MsmLogIveScreenshots>) result
// .getValue("RETURN");
// setSessionLogEvents(logEvent);
ArrayList<Object> logList = (ArrayList<Object>) result
.getValue("RETURN");
ArrayList<SessionLogEventModel> windowLogs = null;
if (ValidationUtils.nonNullAndNotEmpty(logList)) {
windowLogs = new ArrayList<SessionLogEventModel>();
for (int i = 0; i < logList.size(); i++) {
Object obj = logList.get(i);
if (obj instanceof MsmLogIveScreenshots) {
SessionLogEventModel log = convertSessionLogToModel((MsmLogIveScreenshots) obj);
windowLogs.add(log);
} else if (obj instanceof MsmDbAuditOracle) {
SessionLogEventModel log = convertOracleLogToModel((MsmDbAuditOracle) obj);
windowLogs.add(log);
}
}
setSessionLogEventModel(windowLogs);
}
i understand that for loop will eventually load all the data..but what i want is it will still load all the data but only choose 50 list of data to show in jsp..sorry again for my grammar..
The most common practise here is to take the 50 most recent values. So what I would do is check the length, and use subList.
Example
if(logList.size() > 50)
{
// you've got more than 50 objects here.
logList = logList.subList(logList.size() - 50, logList.size());
}
If you have less than or equal to 50 elements in your List, then there's no need to cut it.

Illegal state exception :Field added to a manager while it is already parented

I'm getting exception IllegalStateException :
Field added to a manager while it is already parented
When i call below function second time,when i am changing the value of spinner and this function is called second time, i am getting illegal state exception.
Here is my code :
void showSpinnerDialog(int type) {
if (_customSpinnerPopup == null) {
_customSpinnerPopup = new CustomSpinnerPopup();
}
UiApplication.getUiApplication().pushModalScreen(_customSpinnerPopup);
if (_customSpinnerPopup.isSet()) {
String choice = _customSpinnerPopup.getChoice();
_editFieldSpinbox.setText(choice);
getAlbumsForLanguage(choice);
}
}
private void getAlbumsForLanguage(String choice) {
language = choice;
fieldManager.deleteAll();
final RichList list = new RichList(fieldManager, true, 2, 1);
songItemsList = new Vector();
songItemsList = ServerAPI.getNewSongsForLanguage(language, null);
for (int i = 0; i < songItemsList.size(); i++) {
SongItem songItem = (SongItem) songItemsList.elementAt(i);
list.add(new Object[] { bitmap1, songItem.getName(),
"Artist:" + songItem.getArtist(),
"Movie: " + songItem.getMovie() });
}
add(fieldManager);// **here i am getting exception**
list.setFocusPolicy(TableController.ROW_FOCUS);
list.setCommand(new Command(new CommandHandler() {
public void execute(ReadOnlyCommandMetadata metadata, Object object) {
SongItem song = (SongItem) songItemsList.elementAt(list.getFocusRow());
Dialog.alert("exe !" + song.getName());
As the exception message suggests, you cannot add a Field or a Manager (which is a Field) to another container, more than once, unless you remove it first. When you call getAlbumsForLanguage() the second time, you will call this:
add(fieldManager);// **here i am getting exception**
a second time, which is illegal. To solve this, just surround that line with:
if (fieldManager.getManager() == null) {
add(fieldManager);
}

Categories

Resources