From 71b306517294287f8599bd2b9d5c8e34322e984b Mon Sep 17 00:00:00 2001 From: Alex Osborne Date: Tue, 11 May 2021 21:55:03 +0900 Subject: [PATCH] Handle empty Optionals when browsing beans addPresentableNestedNames() recursively walks the properties of beans calling getters. Likely unintentionally this includes calling getClass() and recursing into the reflection API. When running on JDK 11 the reflection API has some methods (e.g. in java.lang.module) that return instances of Optional. With the newer version of Spring's BeanWrapperImpl encounters an Optional it attempts to unwrap it and throws IllegalArgumentException if it is empty. Let's fix this in two ways. Firstly let's avoid walking the reflection API entirely as its irrelevant for the purposes of bean browsing by not inspecting the properties of instances of java.lang.Class. Secondly in case any Heritrix beans start using Optional in future lets also handle the empty case by also not inspecting, the same as we do for null. Fixes #376 Reported-By: Lauren Ko --- .../org/archive/crawler/restlet/JobRelatedResource.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/engine/src/main/java/org/archive/crawler/restlet/JobRelatedResource.java b/engine/src/main/java/org/archive/crawler/restlet/JobRelatedResource.java index 4dfe548c..25c6289a 100644 --- a/engine/src/main/java/org/archive/crawler/restlet/JobRelatedResource.java +++ b/engine/src/main/java/org/archive/crawler/restlet/JobRelatedResource.java @@ -31,6 +31,7 @@ import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.logging.Logger; @@ -91,7 +92,10 @@ public abstract class JobRelatedResource extends BaseResource { */ protected void addPresentableNestedNames(Collection namedBeans, Object obj, Set alreadyWritten) { - if (obj == null || alreadyWritten.contains(obj) + if (obj == null + || (obj instanceof Optional && !((Optional) obj).isPresent()) + || obj instanceof Class + || alreadyWritten.contains(obj) || obj.getClass().getName().startsWith("org.springframework.")) { return; }