diff --git a/ebean-api/src/main/java/io/ebean/config/BackgroundExecutorWrapper.java b/ebean-api/src/main/java/io/ebean/config/BackgroundExecutorWrapper.java index b290e5863..28081c30f 100644 --- a/ebean-api/src/main/java/io/ebean/config/BackgroundExecutorWrapper.java +++ b/ebean-api/src/main/java/io/ebean/config/BackgroundExecutorWrapper.java @@ -6,6 +6,10 @@ import java.util.concurrent.Callable; * BackgroundExecutorWrapper that can be used to wrap tasks that are sent to background (i.e. another thread). * It should copy all necessary thread-local variables. See {@link MdcBackgroundExecutorWrapper} for implementation details. * + * Note: only tasks that are executed immediately (submit, execute) are wrapped. Periodic or scheduled tasks are not wrapped, + * as these may keep copied variables in memory either forever or until the scheduled task is finished. + * The caller is responsible to handle these cases. + * * @author Roland Praml, FOCONIS AG */ public interface BackgroundExecutorWrapper { diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/core/SpiOrmQueryRequest.java b/ebean-core/src/main/java/io/ebeaninternal/server/core/SpiOrmQueryRequest.java index 039158200..174392918 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/core/SpiOrmQueryRequest.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/core/SpiOrmQueryRequest.java @@ -121,7 +121,7 @@ public interface SpiOrmQueryRequest extends BeanQueryRequest, DocQueryRequ Map findMap(); /** - * Execute the findSingleAttributeList query. + * Execute the findSingleAttributeCollection query. */ > A findSingleAttributeCollection(A collection); diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/executor/DefaultBackgroundExecutor.java b/ebean-core/src/main/java/io/ebeaninternal/server/executor/DefaultBackgroundExecutor.java index d7975e04b..47271bc38 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/executor/DefaultBackgroundExecutor.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/executor/DefaultBackgroundExecutor.java @@ -106,23 +106,23 @@ public final class DefaultBackgroundExecutor implements SpiBackgroundExecutor { @Override public ScheduledFuture scheduleWithFixedDelay(Runnable task, long initialDelay, long delay, TimeUnit unit) { - return schedulePool.scheduleWithFixedDelay(wrap(logExceptions(task)), initialDelay, delay, unit); + return schedulePool.scheduleWithFixedDelay(logExceptions(task), initialDelay, delay, unit); } @Override public ScheduledFuture scheduleAtFixedRate(Runnable task, long initialDelay, long delay, TimeUnit unit) { - return schedulePool.scheduleAtFixedRate(wrap(logExceptions(task)), initialDelay, delay, unit); + return schedulePool.scheduleAtFixedRate(logExceptions(task), initialDelay, delay, unit); } @Override public ScheduledFuture schedule(Runnable task, long delay, TimeUnit unit) { - return schedulePool.schedule(wrap(logExceptions(task)), delay, unit); + return schedulePool.schedule(logExceptions(task), delay, unit); } @Override public ScheduledFuture schedule(Callable task, long delay, TimeUnit unit) { // Note: No "logExceptions" as we expect Future.get() by the invoker - return schedulePool.schedule(wrap(task), delay, unit); + return schedulePool.schedule(task, delay, unit); } @Override diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/idgen/UuidV1RndIdGenerator.java b/ebean-core/src/main/java/io/ebeaninternal/server/idgen/UuidV1RndIdGenerator.java index 21e34a8b3..adbf5e082 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/idgen/UuidV1RndIdGenerator.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/idgen/UuidV1RndIdGenerator.java @@ -106,7 +106,7 @@ public class UuidV1RndIdGenerator implements PlatformIdGenerator { delta = current - last; if (delta < -10000 * 20000) { - log.log(INFO, "Clock skew of {} ms detected", delta / -10000); + log.log(INFO, "Clock skew of {0} ms detected", delta / -10000); // The clock was adjusted back about 2 seconds, or we were generating a lot of ids too fast // if so, we try to set the current as last and also increment the clockSeq. lock.lock(); diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/transaction/JdbcTransaction.java b/ebean-core/src/main/java/io/ebeaninternal/server/transaction/JdbcTransaction.java index 9fae2e21c..4b8408c27 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/transaction/JdbcTransaction.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/transaction/JdbcTransaction.java @@ -885,6 +885,9 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes { public final void preCommit() { internalBatchFlush(); firePreCommit(); + // we must flush the batch queue again, because the callback can + // modify current transaction + internalBatchFlush(); } /** diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeCalendar.java b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeCalendar.java index 8ac56e517..0331296cb 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeCalendar.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeCalendar.java @@ -61,7 +61,7 @@ final class ScalarTypeCalendar extends ScalarTypeBaseDateTime { @Override protected String toJsonNanos(Calendar value) { - return String.valueOf(value.getTime()); + return String.valueOf(value.getTime().getTime()); } @Override diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeLocalDateTime.java b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeLocalDateTime.java index 3de0184e1..eb84613ea 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeLocalDateTime.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeLocalDateTime.java @@ -11,6 +11,7 @@ import java.sql.Timestamp; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; +import java.time.format.DateTimeParseException; /** * ScalarType for java.sql.Timestamp. @@ -48,7 +49,7 @@ final class ScalarTypeLocalDateTime extends ScalarTypeBaseDateTime list3 = DB.find(Customer.class).setUseQueryCache(true).setReadOnly(false).where() - .ilike("name", "Rob").findList(); + .ilike("name", "Rob").findList(); assertNotSame(list, list3); BeanCollection bc3 = (BeanCollection) list3; @@ -349,10 +349,10 @@ public class TestQueryCache extends BaseTestCase { // and now, ensure that we hit the database LoggedSql.start(); colA_second = DB.find(EColAB.class) - .setUseQueryCache(CacheMode.PUT) - .where() - .eq("columnB", "someId") - .findIds(); + .setUseQueryCache(CacheMode.PUT) + .where() + .eq("columnB", "someId") + .findIds(); sql = LoggedSql.stop(); assertThat(sql).hasSize(1); @@ -361,15 +361,15 @@ public class TestQueryCache extends BaseTestCase { @Test public void findCountDifferentQueriesBit() { DB.getDefault().pluginApi().cacheManager().clearAll(); - differentFindCount(q->q.bitwiseAny("id",1), q->q.bitwiseAny("id",0)); - differentFindCount(q->q.bitwiseAll("id",1), q->q.bitwiseAll("id",0)); + differentFindCount(q -> q.bitwiseAny("id", 1), q -> q.bitwiseAny("id", 0)); + differentFindCount(q -> q.bitwiseAll("id", 1), q -> q.bitwiseAll("id", 0)); // differentFindCount(q->q.bitwiseNot("id",1), q->q.bitwiseNot("id",0)); NOT 1 == AND 1 = 0 - differentFindCount(q->q.bitwiseAnd("id",1, 0), q->q.bitwiseAnd("id",1, 1)); + differentFindCount(q -> q.bitwiseAnd("id", 1, 0), q -> q.bitwiseAnd("id", 1, 1)); - differentFindCount(q->q.bitwiseAnd("id",2, 0), q->q.bitwiseAnd("id",4, 0)); - differentFindCount(q->q.bitwiseAnd("id",2, 1), q->q.bitwiseAnd("id",4, 1)); + differentFindCount(q -> q.bitwiseAnd("id", 2, 0), q -> q.bitwiseAnd("id", 4, 0)); + differentFindCount(q -> q.bitwiseAnd("id", 2, 1), q -> q.bitwiseAnd("id", 4, 1)); // Will produce hash collision - differentFindCount(q->q.bitwiseAnd("id",10, 0), q->q.bitwiseAnd("id",0, 928210)); + differentFindCount(q -> q.bitwiseAnd("id", 10, 0), q -> q.bitwiseAnd("id", 0, 928210)); }