From 807ded24c4c03ea2a7418ff974b95773c6677c56 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Fri, 22 May 2020 16:12:49 +0200 Subject: [PATCH 1/5] Avoid ClassCastException on IllegalArgumentException from sync invocation Closes gh-25110 --- .../cache/interceptor/CacheAspectSupport.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/spring-context/src/main/java/org/springframework/cache/interceptor/CacheAspectSupport.java b/spring-context/src/main/java/org/springframework/cache/interceptor/CacheAspectSupport.java index bbb6b1b983..23f132824d 100644 --- a/spring-context/src/main/java/org/springframework/cache/interceptor/CacheAspectSupport.java +++ b/spring-context/src/main/java/org/springframework/cache/interceptor/CacheAspectSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -52,6 +52,7 @@ import org.springframework.util.CollectionUtils; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.util.ObjectUtils; +import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; import org.springframework.util.function.SingletonSupplier; import org.springframework.util.function.SupplierUtils; @@ -381,9 +382,9 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker return wrapCacheValue(method, cache.get(key, () -> unwrapReturnValue(invokeOperation(invoker)))); } catch (Cache.ValueRetrievalException ex) { - // The invoker wraps any Throwable in a ThrowableWrapper instance so we - // can just make sure that one bubbles up the stack. - throw (CacheOperationInvoker.ThrowableWrapper) ex.getCause(); + // Directly propagate ThrowableWrapper from the invoker, + // or potentially also an IllegalArgumentException etc. + ReflectionUtils.rethrowRuntimeException(ex.getCause()); } } else { From e5c079edfc07bdb6e818f7d3c973f110cd50895c Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Fri, 22 May 2020 16:22:59 +0200 Subject: [PATCH 2/5] Introduce serializeToByteArray/deserializeFromByteArray on (De)Serializer Closes gh-25117 --- .../cache/concurrent/ConcurrentMapCache.java | 20 +++---------------- .../core/serializer/Deserializer.java | 16 ++++++++++++++- .../core/serializer/Serializer.java | 18 ++++++++++++++++- .../support/SerializingConverter.java | 8 ++------ 4 files changed, 37 insertions(+), 25 deletions(-) diff --git a/spring-context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCache.java b/spring-context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCache.java index 8a64912219..1a17605578 100644 --- a/spring-context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCache.java +++ b/spring-context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCache.java @@ -16,9 +16,6 @@ package org.springframework.cache.concurrent; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -45,6 +42,7 @@ import org.springframework.util.Assert; * @author Juergen Hoeller * @author Stephane Nicoll * @since 3.1 + * @see ConcurrentMapCacheManager */ public class ConcurrentMapCache extends AbstractValueAdaptingCache { @@ -190,7 +188,7 @@ public class ConcurrentMapCache extends AbstractValueAdaptingCache { Object storeValue = super.toStoreValue(userValue); if (this.serialization != null) { try { - return serializeValue(this.serialization, storeValue); + return this.serialization.serializeToByteArray(storeValue); } catch (Throwable ex) { throw new IllegalArgumentException("Failed to serialize cache value '" + userValue + @@ -202,17 +200,11 @@ public class ConcurrentMapCache extends AbstractValueAdaptingCache { } } - private static Object serializeValue(SerializationDelegate serialization, Object storeValue) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - serialization.serialize(storeValue, out); - return out.toByteArray(); - } - @Override protected Object fromStoreValue(@Nullable Object storeValue) { if (storeValue != null && this.serialization != null) { try { - return super.fromStoreValue(deserializeValue(this.serialization, storeValue)); + return super.fromStoreValue(this.serialization.deserializeFromByteArray((byte[]) storeValue)); } catch (Throwable ex) { throw new IllegalArgumentException("Failed to deserialize cache value '" + storeValue + "'", ex); @@ -221,12 +213,6 @@ public class ConcurrentMapCache extends AbstractValueAdaptingCache { else { return super.fromStoreValue(storeValue); } - - } - - private static Object deserializeValue(SerializationDelegate serialization, Object storeValue) throws IOException { - ByteArrayInputStream in = new ByteArrayInputStream((byte[]) storeValue); - return serialization.deserialize(in); } } diff --git a/spring-core/src/main/java/org/springframework/core/serializer/Deserializer.java b/spring-core/src/main/java/org/springframework/core/serializer/Deserializer.java index 25d3324a67..afa173ab38 100644 --- a/spring-core/src/main/java/org/springframework/core/serializer/Deserializer.java +++ b/spring-core/src/main/java/org/springframework/core/serializer/Deserializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package org.springframework.core.serializer; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; @@ -24,8 +25,10 @@ import java.io.InputStream; * * @author Gary Russell * @author Mark Fisher + * @author Juergen Hoeller * @since 3.0.5 * @param the object type + * @see Serializer */ @FunctionalInterface public interface Deserializer { @@ -41,4 +44,15 @@ public interface Deserializer { */ T deserialize(InputStream inputStream) throws IOException; + /** + * Read (assemble) an object of type T from the given byte array. + * @param serialized the byte array + * @return the deserialized object + * @throws IOException in case of deserialization failure + * @since 5.2.7 + */ + default T deserializeFromByteArray(byte[] serialized) throws IOException { + return deserialize(new ByteArrayInputStream(serialized)); + } + } diff --git a/spring-core/src/main/java/org/springframework/core/serializer/Serializer.java b/spring-core/src/main/java/org/springframework/core/serializer/Serializer.java index ab88650bfc..1436f99bc2 100644 --- a/spring-core/src/main/java/org/springframework/core/serializer/Serializer.java +++ b/spring-core/src/main/java/org/springframework/core/serializer/Serializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package org.springframework.core.serializer; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -24,8 +25,10 @@ import java.io.OutputStream; * * @author Gary Russell * @author Mark Fisher + * @author Juergen Hoeller * @since 3.0.5 * @param the object type + * @see Deserializer */ @FunctionalInterface public interface Serializer { @@ -41,4 +44,17 @@ public interface Serializer { */ void serialize(T object, OutputStream outputStream) throws IOException; + /** + * Turn an object of type T into a serialized byte array. + * @param object the object to serialize + * @return the resulting byte array + * @throws IOException in case of serialization failure + * @since 5.2.7 + */ + default byte[] serializeToByteArray(T object) throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(1024); + serialize(object, out); + return out.toByteArray(); + } + } diff --git a/spring-core/src/main/java/org/springframework/core/serializer/support/SerializingConverter.java b/spring-core/src/main/java/org/springframework/core/serializer/support/SerializingConverter.java index a49637ce76..1f0fa8f17a 100644 --- a/spring-core/src/main/java/org/springframework/core/serializer/support/SerializingConverter.java +++ b/spring-core/src/main/java/org/springframework/core/serializer/support/SerializingConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,8 +16,6 @@ package org.springframework.core.serializer.support; -import java.io.ByteArrayOutputStream; - import org.springframework.core.convert.converter.Converter; import org.springframework.core.serializer.DefaultSerializer; import org.springframework.core.serializer.Serializer; @@ -58,10 +56,8 @@ public class SerializingConverter implements Converter { */ @Override public byte[] convert(Object source) { - ByteArrayOutputStream byteStream = new ByteArrayOutputStream(1024); try { - this.serializer.serialize(source, byteStream); - return byteStream.toByteArray(); + return this.serializer.serializeToByteArray(source); } catch (Throwable ex) { throw new SerializationFailedException("Failed to serialize object using " + From d7161f5e5ebc6e41adbc94e3a164c910846010c9 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Fri, 22 May 2020 16:23:46 +0200 Subject: [PATCH 3/5] Polishing --- .../cache/caffeine/CaffeineCache.java | 3 +- .../cache/ehcache/EhCacheCache.java | 3 +- .../cache/ehcache/EhCacheCacheManager.java | 3 +- .../cache/jcache/JCacheCache.java | 3 +- .../cache/jcache/JCacheCacheManager.java | 3 +- .../concurrent/ConcurrentMapCacheManager.java | 6 ++-- .../cache/support/NoOpCache.java | 3 +- .../cache/support/NoOpCacheManager.java | 4 +-- .../cache/CacheReproTests.java | 3 +- .../ConcurrentMapCacheManagerTests.java | 31 +++++++------------ .../concurrent/ConcurrentMapCacheTests.java | 11 +++---- .../core/ReactiveTypeDescriptor.java | 4 +-- 12 files changed, 35 insertions(+), 42 deletions(-) diff --git a/spring-context-support/src/main/java/org/springframework/cache/caffeine/CaffeineCache.java b/spring-context-support/src/main/java/org/springframework/cache/caffeine/CaffeineCache.java index 34dc622f8b..a19884b19c 100644 --- a/spring-context-support/src/main/java/org/springframework/cache/caffeine/CaffeineCache.java +++ b/spring-context-support/src/main/java/org/springframework/cache/caffeine/CaffeineCache.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,6 +35,7 @@ import org.springframework.util.Assert; * @author Juergen Hoeller * @author Stephane Nicoll * @since 4.3 + * @see CaffeineCacheManager */ public class CaffeineCache extends AbstractValueAdaptingCache { diff --git a/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheCache.java b/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheCache.java index 26ea8929d3..4309fa73a2 100644 --- a/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheCache.java +++ b/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheCache.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,6 +34,7 @@ import org.springframework.util.Assert; * @author Juergen Hoeller * @author Stephane Nicoll * @since 3.1 + * @see EhCacheCacheManager */ public class EhCacheCache implements Cache { diff --git a/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheCacheManager.java b/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheCacheManager.java index 709404e6f2..f3e58a55b2 100644 --- a/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheCacheManager.java +++ b/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheCacheManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,6 +34,7 @@ import org.springframework.util.Assert; * @author Juergen Hoeller * @author Stephane Nicoll * @since 3.1 + * @see EhCacheCache */ public class EhCacheCacheManager extends AbstractTransactionSupportingCacheManager { diff --git a/spring-context-support/src/main/java/org/springframework/cache/jcache/JCacheCache.java b/spring-context-support/src/main/java/org/springframework/cache/jcache/JCacheCache.java index 73c6176a5e..84d2e3f9bc 100644 --- a/spring-context-support/src/main/java/org/springframework/cache/jcache/JCacheCache.java +++ b/spring-context-support/src/main/java/org/springframework/cache/jcache/JCacheCache.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,6 +36,7 @@ import org.springframework.util.Assert; * @author Juergen Hoeller * @author Stephane Nicoll * @since 3.2 + * @see JCacheCacheManager */ public class JCacheCache extends AbstractValueAdaptingCache { diff --git a/spring-context-support/src/main/java/org/springframework/cache/jcache/JCacheCacheManager.java b/spring-context-support/src/main/java/org/springframework/cache/jcache/JCacheCacheManager.java index 08c2b0ec27..e4feb09554 100644 --- a/spring-context-support/src/main/java/org/springframework/cache/jcache/JCacheCacheManager.java +++ b/spring-context-support/src/main/java/org/springframework/cache/jcache/JCacheCacheManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,6 +36,7 @@ import org.springframework.util.Assert; * @author Juergen Hoeller * @author Stephane Nicoll * @since 3.2 + * @see JCacheCache */ public class JCacheCacheManager extends AbstractTransactionSupportingCacheManager { diff --git a/spring-context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCacheManager.java b/spring-context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCacheManager.java index 817ebf3871..aea913288d 100644 --- a/spring-context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCacheManager.java +++ b/spring-context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCacheManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -190,9 +190,7 @@ public class ConcurrentMapCacheManager implements CacheManager, BeanClassLoaderA */ protected Cache createConcurrentMapCache(String name) { SerializationDelegate actualSerialization = (isStoreByValue() ? this.serialization : null); - return new ConcurrentMapCache(name, new ConcurrentHashMap<>(256), - isAllowNullValues(), actualSerialization); - + return new ConcurrentMapCache(name, new ConcurrentHashMap<>(256), isAllowNullValues(), actualSerialization); } } diff --git a/spring-context/src/main/java/org/springframework/cache/support/NoOpCache.java b/spring-context/src/main/java/org/springframework/cache/support/NoOpCache.java index e3e54862a8..6c814ff18e 100644 --- a/spring-context/src/main/java/org/springframework/cache/support/NoOpCache.java +++ b/spring-context/src/main/java/org/springframework/cache/support/NoOpCache.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,6 +30,7 @@ import org.springframework.util.Assert; * @author Costin Leau * @author Stephane Nicoll * @since 4.3.4 + * @see NoOpCacheManager */ public class NoOpCache implements Cache { diff --git a/spring-context/src/main/java/org/springframework/cache/support/NoOpCacheManager.java b/spring-context/src/main/java/org/springframework/cache/support/NoOpCacheManager.java index 1fe5d9a055..0b3137b885 100644 --- a/spring-context/src/main/java/org/springframework/cache/support/NoOpCacheManager.java +++ b/spring-context/src/main/java/org/springframework/cache/support/NoOpCacheManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,7 +37,7 @@ import org.springframework.lang.Nullable; * @author Costin Leau * @author Stephane Nicoll * @since 3.1 - * @see CompositeCacheManager + * @see NoOpCache */ public class NoOpCacheManager implements CacheManager { diff --git a/spring-context/src/test/java/org/springframework/cache/CacheReproTests.java b/spring-context/src/test/java/org/springframework/cache/CacheReproTests.java index 05e8215114..4c81623f50 100644 --- a/spring-context/src/test/java/org/springframework/cache/CacheReproTests.java +++ b/spring-context/src/test/java/org/springframework/cache/CacheReproTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -393,7 +393,6 @@ public class CacheReproTests { public TestBean insertItem(TestBean item) { return item; } - } diff --git a/spring-context/src/test/java/org/springframework/cache/concurrent/ConcurrentMapCacheManagerTests.java b/spring-context/src/test/java/org/springframework/cache/concurrent/ConcurrentMapCacheManagerTests.java index 6c82b1b988..811b55bb8f 100644 --- a/spring-context/src/test/java/org/springframework/cache/concurrent/ConcurrentMapCacheManagerTests.java +++ b/spring-context/src/test/java/org/springframework/cache/concurrent/ConcurrentMapCacheManagerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,18 +33,15 @@ public class ConcurrentMapCacheManagerTests { public void testDynamicMode() { CacheManager cm = new ConcurrentMapCacheManager(); Cache cache1 = cm.getCache("c1"); - boolean condition2 = cache1 instanceof ConcurrentMapCache; - assertThat(condition2).isTrue(); + assertThat(cache1 instanceof ConcurrentMapCache).isTrue(); Cache cache1again = cm.getCache("c1"); assertThat(cache1).isSameAs(cache1again); Cache cache2 = cm.getCache("c2"); - boolean condition1 = cache2 instanceof ConcurrentMapCache; - assertThat(condition1).isTrue(); + assertThat(cache2 instanceof ConcurrentMapCache).isTrue(); Cache cache2again = cm.getCache("c2"); assertThat(cache2).isSameAs(cache2again); Cache cache3 = cm.getCache("c3"); - boolean condition = cache3 instanceof ConcurrentMapCache; - assertThat(condition).isTrue(); + assertThat(cache3 instanceof ConcurrentMapCache).isTrue(); Cache cache3again = cm.getCache("c3"); assertThat(cache3).isSameAs(cache3again); @@ -74,13 +71,11 @@ public class ConcurrentMapCacheManagerTests { public void testStaticMode() { ConcurrentMapCacheManager cm = new ConcurrentMapCacheManager("c1", "c2"); Cache cache1 = cm.getCache("c1"); - boolean condition3 = cache1 instanceof ConcurrentMapCache; - assertThat(condition3).isTrue(); + assertThat(cache1 instanceof ConcurrentMapCache).isTrue(); Cache cache1again = cm.getCache("c1"); assertThat(cache1).isSameAs(cache1again); Cache cache2 = cm.getCache("c2"); - boolean condition2 = cache2 instanceof ConcurrentMapCache; - assertThat(condition2).isTrue(); + assertThat(cache2 instanceof ConcurrentMapCache).isTrue(); Cache cache2again = cm.getCache("c2"); assertThat(cache2).isSameAs(cache2again); Cache cache3 = cm.getCache("c3"); @@ -97,12 +92,10 @@ public class ConcurrentMapCacheManagerTests { cm.setAllowNullValues(false); Cache cache1x = cm.getCache("c1"); - boolean condition1 = cache1x instanceof ConcurrentMapCache; - assertThat(condition1).isTrue(); + assertThat(cache1x instanceof ConcurrentMapCache).isTrue(); assertThat(cache1x != cache1).isTrue(); Cache cache2x = cm.getCache("c2"); - boolean condition = cache2x instanceof ConcurrentMapCache; - assertThat(condition).isTrue(); + assertThat(cache2x instanceof ConcurrentMapCache).isTrue(); assertThat(cache2x != cache2).isTrue(); Cache cache3x = cm.getCache("c3"); assertThat(cache3x).isNull(); @@ -126,16 +119,14 @@ public class ConcurrentMapCacheManagerTests { ConcurrentMapCacheManager cm = new ConcurrentMapCacheManager("c1", "c2"); assertThat(cm.isStoreByValue()).isFalse(); Cache cache1 = cm.getCache("c1"); - boolean condition1 = cache1 instanceof ConcurrentMapCache; - assertThat(condition1).isTrue(); - assertThat(((ConcurrentMapCache)cache1).isStoreByValue()).isFalse(); + assertThat(cache1 instanceof ConcurrentMapCache).isTrue(); + assertThat(((ConcurrentMapCache) cache1).isStoreByValue()).isFalse(); cache1.put("key", "value"); cm.setStoreByValue(true); assertThat(cm.isStoreByValue()).isTrue(); Cache cache1x = cm.getCache("c1"); - boolean condition = cache1x instanceof ConcurrentMapCache; - assertThat(condition).isTrue(); + assertThat(cache1x instanceof ConcurrentMapCache).isTrue(); assertThat(cache1x != cache1).isTrue(); assertThat(cache1x.get("key")).isNull(); } diff --git a/spring-context/src/test/java/org/springframework/cache/concurrent/ConcurrentMapCacheTests.java b/spring-context/src/test/java/org/springframework/cache/concurrent/ConcurrentMapCacheTests.java index 96715e5e3c..4e8a9d3fbc 100644 --- a/spring-context/src/test/java/org/springframework/cache/concurrent/ConcurrentMapCacheTests.java +++ b/spring-context/src/test/java/org/springframework/cache/concurrent/ConcurrentMapCacheTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,8 +36,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException * @author Juergen Hoeller * @author Stephane Nicoll */ -public class ConcurrentMapCacheTests - extends AbstractValueAdaptingCacheTests { +public class ConcurrentMapCacheTests extends AbstractValueAdaptingCacheTests { protected ConcurrentMap nativeCache; @@ -49,12 +48,11 @@ public class ConcurrentMapCacheTests @BeforeEach - public void setUp() throws Exception { + public void setup() { this.nativeCache = new ConcurrentHashMap<>(); this.cache = new ConcurrentMapCache(CACHE_NAME, this.nativeCache, true); this.nativeCacheNoNull = new ConcurrentHashMap<>(); - this.cacheNoNull = new ConcurrentMapCache(CACHE_NAME_NO_NULL, - this.nativeCacheNoNull, false); + this.cacheNoNull = new ConcurrentMapCache(CACHE_NAME_NO_NULL, this.nativeCacheNoNull, false); this.cache.clear(); } @@ -73,6 +71,7 @@ public class ConcurrentMapCacheTests return this.nativeCache; } + @Test public void testIsStoreByReferenceByDefault() { assertThat(this.cache.isStoreByValue()).isFalse(); diff --git a/spring-core/src/main/java/org/springframework/core/ReactiveTypeDescriptor.java b/spring-core/src/main/java/org/springframework/core/ReactiveTypeDescriptor.java index ad6e99fcf0..035ac1b56a 100644 --- a/spring-core/src/main/java/org/springframework/core/ReactiveTypeDescriptor.java +++ b/spring-core/src/main/java/org/springframework/core/ReactiveTypeDescriptor.java @@ -105,7 +105,7 @@ public final class ReactiveTypeDescriptor { * Whether the underlying operation is deferred and needs to be started * explicitly, e.g. via subscribing (or similar), or whether it is triggered * without the consumer having any control. - * @since 5.1.16 + * @since 5.2.7 */ public boolean isDeferred() { return this.deferred; @@ -169,7 +169,7 @@ public final class ReactiveTypeDescriptor { * non-deferred, async type such as {@link java.util.concurrent.CompletableFuture}. * @param type the reactive type * @param emptySupplier a supplier of an empty-value instance of the reactive type - * @since 5.1.16 + * @since 5.2.7 */ public static ReactiveTypeDescriptor nonDeferredAsyncValue(Class type, Supplier emptySupplier) { return new ReactiveTypeDescriptor(type, false, false, emptySupplier, false); From 4018b462f1e0573a321551eda1a12f1fe70e7611 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Fri, 22 May 2020 16:35:34 +0200 Subject: [PATCH 4/5] JdbcOperations polishing (backported from master) --- .../jdbc/core/JdbcOperations.java | 27 ++++++---- .../NamedParameterJdbcOperations.java | 50 ++++++++++--------- .../jdbc/core/JdbcTemplateQueryTests.java | 34 +++++-------- .../NamedParameterJdbcTemplateTests.java | 13 ++++- 4 files changed, 67 insertions(+), 57 deletions(-) diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcOperations.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcOperations.java index de6df06fc3..67ff03c8d7 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcOperations.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcOperations.java @@ -100,7 +100,7 @@ public interface JdbcOperations { * @param rse a callback that will extract all rows of results * @return an arbitrary result object, as returned by the ResultSetExtractor * @throws DataAccessException if there is any problem executing the query - * @see #query(String, Object[], ResultSetExtractor) + * @see #query(String, ResultSetExtractor, Object...) */ @Nullable T query(String sql, ResultSetExtractor rse) throws DataAccessException; @@ -114,7 +114,7 @@ public interface JdbcOperations { * @param sql the SQL query to execute * @param rch a callback that will extract results, one row at a time * @throws DataAccessException if there is any problem executing the query - * @see #query(String, Object[], RowCallbackHandler) + * @see #query(String, RowCallbackHandler, Object...) */ void query(String sql, RowCallbackHandler rch) throws DataAccessException; @@ -128,7 +128,7 @@ public interface JdbcOperations { * @param rowMapper a callback that will map one object per row * @return the result List, containing mapped objects * @throws DataAccessException if there is any problem executing the query - * @see #query(String, Object[], RowMapper) + * @see #query(String, RowMapper, Object...) */ List query(String sql, RowMapper rowMapper) throws DataAccessException; @@ -146,7 +146,7 @@ public interface JdbcOperations { * @throws IncorrectResultSizeDataAccessException if the query does not * return exactly one row * @throws DataAccessException if there is any problem executing the query - * @see #queryForObject(String, Object[], RowMapper) + * @see #queryForObject(String, RowMapper, Object...) */ @Nullable T queryForObject(String sql, RowMapper rowMapper) throws DataAccessException; @@ -166,7 +166,7 @@ public interface JdbcOperations { * @throws IncorrectResultSizeDataAccessException if the query does not return * exactly one row, or does not return exactly one column in that row * @throws DataAccessException if there is any problem executing the query - * @see #queryForObject(String, Object[], Class) + * @see #queryForObject(String, Class, Object...) */ @Nullable T queryForObject(String sql, Class requiredType) throws DataAccessException; @@ -184,7 +184,7 @@ public interface JdbcOperations { * @throws IncorrectResultSizeDataAccessException if the query does not * return exactly one row * @throws DataAccessException if there is any problem executing the query - * @see #queryForMap(String, Object[]) + * @see #queryForMap(String, Object...) * @see ColumnMapRowMapper */ Map queryForMap(String sql) throws DataAccessException; @@ -201,7 +201,7 @@ public interface JdbcOperations { * (for example, {@code Integer.class}) * @return a List of objects that match the specified element type * @throws DataAccessException if there is any problem executing the query - * @see #queryForList(String, Object[], Class) + * @see #queryForList(String, Class, Object...) * @see SingleColumnRowMapper */ List queryForList(String sql, Class elementType) throws DataAccessException; @@ -218,7 +218,7 @@ public interface JdbcOperations { * @param sql the SQL query to execute * @return an List that contains a Map per row * @throws DataAccessException if there is any problem executing the query - * @see #queryForList(String, Object[]) + * @see #queryForList(String, Object...) */ List> queryForList(String sql) throws DataAccessException; @@ -237,7 +237,7 @@ public interface JdbcOperations { * @return an SqlRowSet representation (possibly a wrapper around a * {@code javax.sql.rowset.CachedRowSet}) * @throws DataAccessException if there is any problem executing the query - * @see #queryForRowSet(String, Object[]) + * @see #queryForRowSet(String, Object...) * @see SqlRowSetResultSetExtractor * @see javax.sql.rowset.CachedRowSet */ @@ -323,7 +323,8 @@ public interface JdbcOperations { * @throws DataAccessException if there is any problem */ @Nullable - T query(String sql, @Nullable PreparedStatementSetter pss, ResultSetExtractor rse) throws DataAccessException; + T query(String sql, @Nullable PreparedStatementSetter pss, ResultSetExtractor rse) + throws DataAccessException; /** * Query given SQL to create a prepared statement from SQL and a list of arguments @@ -466,7 +467,8 @@ public interface JdbcOperations { * @return the result List, containing mapped objects * @throws DataAccessException if the query fails */ - List query(String sql, @Nullable PreparedStatementSetter pss, RowMapper rowMapper) throws DataAccessException; + List query(String sql, @Nullable PreparedStatementSetter pss, RowMapper rowMapper) + throws DataAccessException; /** * Query given SQL to create a prepared statement from SQL and a list of @@ -903,6 +905,7 @@ public interface JdbcOperations { * @param sql the SQL statement to execute * @param batchArgs the List of Object arrays containing the batch of arguments for the query * @return an array containing the numbers of rows affected by each update in the batch + * @throws DataAccessException if there is any problem issuing the update */ int[] batchUpdate(String sql, List batchArgs) throws DataAccessException; @@ -913,6 +916,7 @@ public interface JdbcOperations { * @param argTypes the SQL types of the arguments * (constants from {@code java.sql.Types}) * @return an array containing the numbers of rows affected by each update in the batch + * @throws DataAccessException if there is any problem issuing the update */ int[] batchUpdate(String sql, List batchArgs, int[] argTypes) throws DataAccessException; @@ -926,6 +930,7 @@ public interface JdbcOperations { * @param pss the ParameterizedPreparedStatementSetter to use * @return an array containing for each batch another array containing the numbers of rows affected * by each update in the batch + * @throws DataAccessException if there is any problem issuing the update * @since 3.1 */ int[][] batchUpdate(String sql, Collection batchArgs, int batchSize, diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcOperations.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcOperations.java index eaf221a294..ad5c627eeb 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcOperations.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -130,7 +130,7 @@ public interface NamedParameterJdbcOperations { * (leaving it to the PreparedStatement to guess the corresponding SQL type) * @param rse object that will extract results * @return an arbitrary result object, as returned by the ResultSetExtractor - * @throws org.springframework.dao.DataAccessException if the query fails + * @throws DataAccessException if the query fails */ @Nullable T query(String sql, Map paramMap, ResultSetExtractor rse) @@ -145,7 +145,7 @@ public interface NamedParameterJdbcOperations { * @param sql the SQL query to execute * @param rse object that will extract results * @return an arbitrary result object, as returned by the ResultSetExtractor - * @throws org.springframework.dao.DataAccessException if the query fails + * @throws DataAccessException if the query fails */ @Nullable T query(String sql, ResultSetExtractor rse) throws DataAccessException; @@ -170,7 +170,7 @@ public interface NamedParameterJdbcOperations { * @param paramMap map of parameters to bind to the query * (leaving it to the PreparedStatement to guess the corresponding SQL type) * @param rch object that will extract results, one row at a time - * @throws org.springframework.dao.DataAccessException if the query fails + * @throws DataAccessException if the query fails */ void query(String sql, Map paramMap, RowCallbackHandler rch) throws DataAccessException; @@ -182,7 +182,7 @@ public interface NamedParameterJdbcOperations { * equivalent to a query call with an empty parameter Map. * @param sql the SQL query to execute * @param rch object that will extract results, one row at a time - * @throws org.springframework.dao.DataAccessException if the query fails + * @throws DataAccessException if the query fails */ void query(String sql, RowCallbackHandler rch) throws DataAccessException; @@ -194,7 +194,7 @@ public interface NamedParameterJdbcOperations { * @param paramSource container of arguments to bind to the query * @param rowMapper object that will map one object per row * @return the result List, containing mapped objects - * @throws org.springframework.dao.DataAccessException if the query fails + * @throws DataAccessException if the query fails */ List query(String sql, SqlParameterSource paramSource, RowMapper rowMapper) throws DataAccessException; @@ -208,7 +208,7 @@ public interface NamedParameterJdbcOperations { * (leaving it to the PreparedStatement to guess the corresponding SQL type) * @param rowMapper object that will map one object per row * @return the result List, containing mapped objects - * @throws org.springframework.dao.DataAccessException if the query fails + * @throws DataAccessException if the query fails */ List query(String sql, Map paramMap, RowMapper rowMapper) throws DataAccessException; @@ -222,7 +222,7 @@ public interface NamedParameterJdbcOperations { * @param sql the SQL query to execute * @param rowMapper object that will map one object per row * @return the result List, containing mapped objects - * @throws org.springframework.dao.DataAccessException if the query fails + * @throws DataAccessException if the query fails */ List query(String sql, RowMapper rowMapper) throws DataAccessException; @@ -238,7 +238,7 @@ public interface NamedParameterJdbcOperations { * @throws org.springframework.dao.IncorrectResultSizeDataAccessException * if the query does not return exactly one row, or does not return exactly * one column in that row - * @throws org.springframework.dao.DataAccessException if the query fails + * @throws DataAccessException if the query fails */ @Nullable T queryForObject(String sql, SqlParameterSource paramSource, RowMapper rowMapper) @@ -257,7 +257,7 @@ public interface NamedParameterJdbcOperations { * @throws org.springframework.dao.IncorrectResultSizeDataAccessException * if the query does not return exactly one row, or does not return exactly * one column in that row - * @throws org.springframework.dao.DataAccessException if the query fails + * @throws DataAccessException if the query fails */ @Nullable T queryForObject(String sql, Map paramMap, RowMapper rowMapper) @@ -275,7 +275,7 @@ public interface NamedParameterJdbcOperations { * @throws org.springframework.dao.IncorrectResultSizeDataAccessException * if the query does not return exactly one row, or does not return exactly * one column in that row - * @throws org.springframework.dao.DataAccessException if the query fails + * @throws DataAccessException if the query fails * @see org.springframework.jdbc.core.JdbcTemplate#queryForObject(String, Class) */ @Nullable @@ -295,7 +295,7 @@ public interface NamedParameterJdbcOperations { * @throws org.springframework.dao.IncorrectResultSizeDataAccessException * if the query does not return exactly one row, or does not return exactly * one column in that row - * @throws org.springframework.dao.DataAccessException if the query fails + * @throws DataAccessException if the query fails * @see org.springframework.jdbc.core.JdbcTemplate#queryForObject(String, Class) */ @Nullable @@ -312,7 +312,7 @@ public interface NamedParameterJdbcOperations { * @return the result Map (one entry for each column, using the column name as the key) * @throws org.springframework.dao.IncorrectResultSizeDataAccessException * if the query does not return exactly one row - * @throws org.springframework.dao.DataAccessException if the query fails + * @throws DataAccessException if the query fails * @see org.springframework.jdbc.core.JdbcTemplate#queryForMap(String) * @see org.springframework.jdbc.core.ColumnMapRowMapper */ @@ -332,7 +332,7 @@ public interface NamedParameterJdbcOperations { * @return the result Map (one entry for each column, using the column name as the key) * @throws org.springframework.dao.IncorrectResultSizeDataAccessException * if the query does not return exactly one row - * @throws org.springframework.dao.DataAccessException if the query fails + * @throws DataAccessException if the query fails * @see org.springframework.jdbc.core.JdbcTemplate#queryForMap(String) * @see org.springframework.jdbc.core.ColumnMapRowMapper */ @@ -348,7 +348,7 @@ public interface NamedParameterJdbcOperations { * @param elementType the required type of element in the result list * (for example, {@code Integer.class}) * @return a List of objects that match the specified element type - * @throws org.springframework.dao.DataAccessException if the query fails + * @throws DataAccessException if the query fails * @see org.springframework.jdbc.core.JdbcTemplate#queryForList(String, Class) * @see org.springframework.jdbc.core.SingleColumnRowMapper */ @@ -366,7 +366,7 @@ public interface NamedParameterJdbcOperations { * @param elementType the required type of element in the result list * (for example, {@code Integer.class}) * @return a List of objects that match the specified element type - * @throws org.springframework.dao.DataAccessException if the query fails + * @throws DataAccessException if the query fails * @see org.springframework.jdbc.core.JdbcTemplate#queryForList(String, Class) * @see org.springframework.jdbc.core.SingleColumnRowMapper */ @@ -383,7 +383,7 @@ public interface NamedParameterJdbcOperations { * @param sql the SQL query to execute * @param paramSource container of arguments to bind to the query * @return a List that contains a Map per row - * @throws org.springframework.dao.DataAccessException if the query fails + * @throws DataAccessException if the query fails * @see org.springframework.jdbc.core.JdbcTemplate#queryForList(String) */ List> queryForList(String sql, SqlParameterSource paramSource) throws DataAccessException; @@ -399,7 +399,7 @@ public interface NamedParameterJdbcOperations { * @param paramMap map of parameters to bind to the query * (leaving it to the PreparedStatement to guess the corresponding SQL type) * @return a List that contains a Map per row - * @throws org.springframework.dao.DataAccessException if the query fails + * @throws DataAccessException if the query fails * @see org.springframework.jdbc.core.JdbcTemplate#queryForList(String) */ List> queryForList(String sql, Map paramMap) throws DataAccessException; @@ -417,7 +417,7 @@ public interface NamedParameterJdbcOperations { * @param paramSource container of arguments to bind to the query * @return an SqlRowSet representation (possibly a wrapper around a * {@code javax.sql.rowset.CachedRowSet}) - * @throws org.springframework.dao.DataAccessException if there is any problem executing the query + * @throws DataAccessException if there is any problem executing the query * @see org.springframework.jdbc.core.JdbcTemplate#queryForRowSet(String) * @see org.springframework.jdbc.core.SqlRowSetResultSetExtractor * @see javax.sql.rowset.CachedRowSet @@ -438,7 +438,7 @@ public interface NamedParameterJdbcOperations { * (leaving it to the PreparedStatement to guess the corresponding SQL type) * @return an SqlRowSet representation (possibly a wrapper around a * {@code javax.sql.rowset.CachedRowSet}) - * @throws org.springframework.dao.DataAccessException if there is any problem executing the query + * @throws DataAccessException if there is any problem executing the query * @see org.springframework.jdbc.core.JdbcTemplate#queryForRowSet(String) * @see org.springframework.jdbc.core.SqlRowSetResultSetExtractor * @see javax.sql.rowset.CachedRowSet @@ -450,7 +450,7 @@ public interface NamedParameterJdbcOperations { * @param sql the SQL containing named parameters * @param paramSource container of arguments and SQL types to bind to the query * @return the number of rows affected - * @throws org.springframework.dao.DataAccessException if there is any problem issuing the update + * @throws DataAccessException if there is any problem issuing the update */ int update(String sql, SqlParameterSource paramSource) throws DataAccessException; @@ -460,7 +460,7 @@ public interface NamedParameterJdbcOperations { * @param paramMap map of parameters to bind to the query * (leaving it to the PreparedStatement to guess the corresponding SQL type) * @return the number of rows affected - * @throws org.springframework.dao.DataAccessException if there is any problem issuing the update + * @throws DataAccessException if there is any problem issuing the update */ int update(String sql, Map paramMap) throws DataAccessException; @@ -471,7 +471,7 @@ public interface NamedParameterJdbcOperations { * @param paramSource container of arguments and SQL types to bind to the query * @param generatedKeyHolder a {@link KeyHolder} that will hold the generated keys * @return the number of rows affected - * @throws org.springframework.dao.DataAccessException if there is any problem issuing the update + * @throws DataAccessException if there is any problem issuing the update * @see MapSqlParameterSource * @see org.springframework.jdbc.support.GeneratedKeyHolder */ @@ -486,7 +486,7 @@ public interface NamedParameterJdbcOperations { * @param generatedKeyHolder a {@link KeyHolder} that will hold the generated keys * @param keyColumnNames names of the columns that will have keys generated for them * @return the number of rows affected - * @throws org.springframework.dao.DataAccessException if there is any problem issuing the update + * @throws DataAccessException if there is any problem issuing the update * @see MapSqlParameterSource * @see org.springframework.jdbc.support.GeneratedKeyHolder */ @@ -498,6 +498,7 @@ public interface NamedParameterJdbcOperations { * @param sql the SQL statement to execute * @param batchValues the array of Maps containing the batch of arguments for the query * @return an array containing the numbers of rows affected by each update in the batch + * @throws DataAccessException if there is any problem issuing the update */ int[] batchUpdate(String sql, Map[] batchValues); @@ -506,6 +507,7 @@ public interface NamedParameterJdbcOperations { * @param sql the SQL statement to execute * @param batchArgs the array of {@link SqlParameterSource} containing the batch of arguments for the query * @return an array containing the numbers of rows affected by each update in the batch + * @throws DataAccessException if there is any problem issuing the update */ int[] batchUpdate(String sql, SqlParameterSource[] batchArgs); diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/core/JdbcTemplateQueryTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/core/JdbcTemplateQueryTests.java index 76f54dca8f..a1c719b879 100644 --- a/spring-jdbc/src/test/java/org/springframework/jdbc/core/JdbcTemplateQueryTests.java +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/core/JdbcTemplateQueryTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -164,8 +164,7 @@ public class JdbcTemplateQueryTests { return rs.getInt(1); } }); - boolean condition = o instanceof Integer; - assertThat(condition).as("Correct result type").isTrue(); + assertThat(o instanceof Integer).as("Correct result type").isTrue(); verify(this.resultSet).close(); verify(this.statement).close(); } @@ -278,7 +277,7 @@ public class JdbcTemplateQueryTests { private void doTestQueryForListWithArgs(String sql) throws Exception { given(this.resultSet.next()).willReturn(true, true, false); given(this.resultSet.getObject(1)).willReturn(11, 12); - List> li = this.template.queryForList(sql, new Object[] {3}); + List> li = this.template.queryForList(sql, 3); assertThat(li.size()).as("All rows returned").isEqualTo(2); assertThat(((Integer) li.get(0).get("age")).intValue()).as("First row is Integer").isEqualTo(11); assertThat(((Integer) li.get(1).get("age")).intValue()).as("Second row is Integer").isEqualTo(12); @@ -291,7 +290,7 @@ public class JdbcTemplateQueryTests { public void testQueryForListWithArgsAndEmptyResult() throws Exception { String sql = "SELECT AGE FROM CUSTMR WHERE ID < ?"; given(this.resultSet.next()).willReturn(false); - List> li = this.template.queryForList(sql, new Object[] {3}); + List> li = this.template.queryForList(sql, 3); assertThat(li.size()).as("All rows returned").isEqualTo(0); verify(this.preparedStatement).setObject(1, 3); verify(this.resultSet).close(); @@ -303,7 +302,7 @@ public class JdbcTemplateQueryTests { String sql = "SELECT AGE FROM CUSTMR WHERE ID < ?"; given(this.resultSet.next()).willReturn(true, false); given(this.resultSet.getObject(1)).willReturn(11); - List> li = this.template.queryForList(sql, new Object[] {3}); + List> li = this.template.queryForList(sql, 3); assertThat(li.size()).as("All rows returned").isEqualTo(1); assertThat(((Integer) li.get(0).get("age")).intValue()).as("First row is Integer").isEqualTo(11); verify(this.preparedStatement).setObject(1, 3); @@ -316,7 +315,7 @@ public class JdbcTemplateQueryTests { String sql = "SELECT AGE FROM CUSTMR WHERE ID < ?"; given(this.resultSet.next()).willReturn(true, false); given(this.resultSet.getInt(1)).willReturn(11); - List li = this.template.queryForList(sql, new Object[] {3}, Integer.class); + List li = this.template.queryForList(sql, Integer.class, 3); assertThat(li.size()).as("All rows returned").isEqualTo(1); assertThat(li.get(0).intValue()).as("First row is Integer").isEqualTo(11); verify(this.preparedStatement).setObject(1, 3); @@ -329,7 +328,7 @@ public class JdbcTemplateQueryTests { String sql = "SELECT AGE FROM CUSTMR WHERE ID < ?"; given(this.resultSet.next()).willReturn(true, false); given(this.resultSet.getObject(1)).willReturn(11); - Map map = this.template.queryForMap(sql, new Object[] {3}); + Map map = this.template.queryForMap(sql, 3); assertThat(((Integer) map.get("age")).intValue()).as("Row is Integer").isEqualTo(11); verify(this.preparedStatement).setObject(1, 3); verify(this.resultSet).close(); @@ -341,14 +340,8 @@ public class JdbcTemplateQueryTests { String sql = "SELECT AGE FROM CUSTMR WHERE ID = ?"; given(this.resultSet.next()).willReturn(true, false); given(this.resultSet.getInt(1)).willReturn(22); - Object o = this.template.queryForObject(sql, new Object[] {3}, new RowMapper() { - @Override - public Integer mapRow(ResultSet rs, int rowNum) throws SQLException { - return rs.getInt(1); - } - }); - boolean condition = o instanceof Integer; - assertThat(condition).as("Correct result type").isTrue(); + Object o = this.template.queryForObject(sql, (rs, rowNum) -> rs.getInt(1), 3); + assertThat(o instanceof Integer).as("Correct result type").isTrue(); verify(this.preparedStatement).setObject(1, 3); verify(this.resultSet).close(); verify(this.preparedStatement).close(); @@ -359,9 +352,8 @@ public class JdbcTemplateQueryTests { String sql = "SELECT AGE FROM CUSTMR WHERE ID = ?"; given(this.resultSet.next()).willReturn(true, false); given(this.resultSet.getInt(1)).willReturn(22); - Object o = this.template.queryForObject(sql, new Object[] {3}, Integer.class); - boolean condition = o instanceof Integer; - assertThat(condition).as("Correct result type").isTrue(); + Object o = this.template.queryForObject(sql, Integer.class, 3); + assertThat(o instanceof Integer).as("Correct result type").isTrue(); verify(this.preparedStatement).setObject(1, 3); verify(this.resultSet).close(); verify(this.preparedStatement).close(); @@ -372,7 +364,7 @@ public class JdbcTemplateQueryTests { String sql = "SELECT AGE FROM CUSTMR WHERE ID = ?"; given(this.resultSet.next()).willReturn(true, false); given(this.resultSet.getInt(1)).willReturn(22); - int i = this.template.queryForObject(sql, new Object[] {3}, Integer.class).intValue(); + int i = this.template.queryForObject(sql, Integer.class, 3).intValue(); assertThat(i).as("Return of an int").isEqualTo(22); verify(this.preparedStatement).setObject(1, 3); verify(this.resultSet).close(); @@ -384,7 +376,7 @@ public class JdbcTemplateQueryTests { String sql = "SELECT AGE FROM CUSTMR WHERE ID = ?"; given(this.resultSet.next()).willReturn(true, false); given(this.resultSet.getLong(1)).willReturn(87L); - long l = this.template.queryForObject(sql, new Object[] {3}, Long.class).longValue(); + long l = this.template.queryForObject(sql, Long.class, 3).longValue(); assertThat(l).as("Return of a long").isEqualTo(87); verify(this.preparedStatement).setObject(1, 3); verify(this.resultSet).close(); diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplateTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplateTests.java index 119c6865e3..48a0e52a89 100644 --- a/spring-jdbc/src/test/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplateTests.java +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplateTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -237,6 +237,7 @@ public class NamedParameterJdbcTemplateTests { verify(connection).prepareStatement(SELECT_NAMED_PARAMETERS_PARSED); verify(preparedStatement).setObject(1, 1, Types.DECIMAL); verify(preparedStatement).setString(2, "UK"); + verify(resultSet).close(); verify(preparedStatement).close(); verify(connection).close(); } @@ -259,6 +260,7 @@ public class NamedParameterJdbcTemplateTests { assertThat(cust.getId() == 1).as("Customer id was assigned correctly").isTrue(); assertThat(cust.getForename().equals("rod")).as("Customer forename was assigned correctly").isTrue(); verify(connection).prepareStatement(SELECT_NO_PARAMETERS); + verify(resultSet).close(); verify(preparedStatement).close(); verify(connection).close(); } @@ -285,6 +287,7 @@ public class NamedParameterJdbcTemplateTests { verify(connection).prepareStatement(SELECT_NAMED_PARAMETERS_PARSED); verify(preparedStatement).setObject(1, 1, Types.DECIMAL); verify(preparedStatement).setString(2, "UK"); + verify(resultSet).close(); verify(preparedStatement).close(); verify(connection).close(); } @@ -307,6 +310,7 @@ public class NamedParameterJdbcTemplateTests { assertThat(customers.get(0).getId() == 1).as("Customer id was assigned correctly").isTrue(); assertThat(customers.get(0).getForename().equals("rod")).as("Customer forename was assigned correctly").isTrue(); verify(connection).prepareStatement(SELECT_NO_PARAMETERS); + verify(resultSet).close(); verify(preparedStatement).close(); verify(connection).close(); } @@ -326,12 +330,14 @@ public class NamedParameterJdbcTemplateTests { cust.setForename(rs.getString(COLUMN_NAMES[1])); return cust; }); + assertThat(customers.size()).isEqualTo(1); assertThat(customers.get(0).getId() == 1).as("Customer id was assigned correctly").isTrue(); assertThat(customers.get(0).getForename().equals("rod")).as("Customer forename was assigned correctly").isTrue(); verify(connection).prepareStatement(SELECT_NAMED_PARAMETERS_PARSED); verify(preparedStatement).setObject(1, 1, Types.DECIMAL); verify(preparedStatement).setString(2, "UK"); + verify(resultSet).close(); verify(preparedStatement).close(); verify(connection).close(); } @@ -349,10 +355,12 @@ public class NamedParameterJdbcTemplateTests { cust.setForename(rs.getString(COLUMN_NAMES[1])); return cust; }); + assertThat(customers.size()).isEqualTo(1); assertThat(customers.get(0).getId() == 1).as("Customer id was assigned correctly").isTrue(); assertThat(customers.get(0).getForename().equals("rod")).as("Customer forename was assigned correctly").isTrue(); verify(connection).prepareStatement(SELECT_NO_PARAMETERS); + verify(resultSet).close(); verify(preparedStatement).close(); verify(connection).close(); } @@ -365,6 +373,7 @@ public class NamedParameterJdbcTemplateTests { params.put("id", new SqlParameterValue(Types.DECIMAL, 1)); params.put("country", "UK"); + Customer cust = namedParameterTemplate.queryForObject(SELECT_NAMED_PARAMETERS, params, (rs, rownum) -> { Customer cust1 = new Customer(); @@ -372,11 +381,13 @@ public class NamedParameterJdbcTemplateTests { cust1.setForename(rs.getString(COLUMN_NAMES[1])); return cust1; }); + assertThat(cust.getId() == 1).as("Customer id was assigned correctly").isTrue(); assertThat(cust.getForename().equals("rod")).as("Customer forename was assigned correctly").isTrue(); verify(connection).prepareStatement(SELECT_NAMED_PARAMETERS_PARSED); verify(preparedStatement).setObject(1, 1, Types.DECIMAL); verify(preparedStatement).setString(2, "UK"); + verify(resultSet).close(); verify(preparedStatement).close(); verify(connection).close(); } From cd9ee98ff88052706e722a45d72cce901aecd580 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Fri, 22 May 2020 17:08:02 +0200 Subject: [PATCH 5/5] Upgrade to Jetty 9.4.29, Hibernate ORM 5.4.16, WebJars Locator 0.45 --- build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 70fe708e79..b684c0e8dd 100644 --- a/build.gradle +++ b/build.gradle @@ -30,7 +30,7 @@ configure(allprojects) { project -> mavenBom "io.netty:netty-bom:4.1.50.Final" mavenBom "io.projectreactor:reactor-bom:Dysprosium-SR7" mavenBom "io.rsocket:rsocket-bom:1.0.0" - mavenBom "org.eclipse.jetty:jetty-bom:9.4.28.v20200408" + mavenBom "org.eclipse.jetty:jetty-bom:9.4.29.v20200521" mavenBom "org.jetbrains.kotlin:kotlin-bom:1.3.72" mavenBom "org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.3.5" mavenBom "org.junit:junit-bom:5.6.2" @@ -115,9 +115,9 @@ configure(allprojects) { project -> dependency "net.sf.ehcache:ehcache:2.10.6" dependency "org.ehcache:jcache:1.0.1" dependency "org.ehcache:ehcache:3.4.0" - dependency "org.hibernate:hibernate-core:5.4.15.Final" + dependency "org.hibernate:hibernate-core:5.4.16.Final" dependency "org.hibernate:hibernate-validator:6.1.5.Final" - dependency "org.webjars:webjars-locator-core:0.44" + dependency "org.webjars:webjars-locator-core:0.45" dependency "org.webjars:underscorejs:1.8.3" dependencySet(group: 'org.apache.tomcat', version: '9.0.35') {