Hi,
I'm working on a Java SE app which uses EclipseLink (2.5.1) and Spring (3.2.5). I've got a code which retrieves from the DB 100 entities then processes them in 10 separate threads (threaded executor).
Data is retrieved using a single thread by the following method:
@Transactional(readOnly = true)
public List<? extends FeedLocation> getWithNoFeedDownloadProcessed(int limit) {
TypedQuery<FeedLocation> query = em.createQuery("SELECT f FROM FeedLocation f WHERE f.feedDownloadProcessed IS NULL",
FeedLocation.class);
query.setMaxResults(limit);
return query.getResultList();
}
In FeedLocation class there is defined a lazy association:
@OneToMany(mappedBy="feedLocation", fetch = FetchType.LAZY, cascade= CascadeType.ALL)
@OrderColumn(name="position")
private List<FeedUrl> feedUrls;
public List<FeedUrl> getFeedUrls() {
return feedUrls;
}
Then when fetched FeedLocations are processed in separate threads there is a code which iterates through feedUrls. This code throws ConcurrencyException:
for (FeedUrl feedUrl : feedLocation.getFeedUrls()) { // this line throws the exception
// code ommited
}
Exception message:
A signal was attempted before wait() on ConcurrencyManager. This normally means that an attempt was made to commit or rollback a transaction before it was started, or to rollback a transaction twice
However, when I use JOIN FETCH in getWithNoFeedDownloadProcessed then no exception is raised and everything works as expected:
@Transactional(readOnly = true)
public List<? extends FeedLocation> getWithNotFeedDownloadProcessed(int limit) {
TypedQuery<FeedLocation> query = em.createQuery("SELECT DISTINCT f FROM FeedLocation f LEFT JOIN FETCH f.feedUrls WHERE f.feedDownloadProcessed IS NULL",
FeedLocation.class);
query.setMaxResults(limit);
return query.getResultList();
}
My question is wether it is a normal and expected behavior, and I should be careful when working with threads and entities which use lazy loading, or maybe there is some config option which should be set to make it working correctly, or maybe it is some bug?
Additional info: c3p0 is used for connection pooling (version: 0.9.1.2) and org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver is used for weaving (with spring-instrument-.jar javaagent).
Thank you,
Michal