diff --git a/pom.xml b/pom.xml index 1e91efe..cd3ed8a 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ de.adito.picoservice picoservice - 1.1.0 + 1.1.1 ${project.groupId}:${project.artifactId} A minimalist registry for java services using serviceloader diff --git a/src/main/java/de/adito/picoservice/InstanceLoader.java b/src/main/java/de/adito/picoservice/InstanceLoader.java index 22feb34..bd19d8a 100644 --- a/src/main/java/de/adito/picoservice/InstanceLoader.java +++ b/src/main/java/de/adito/picoservice/InstanceLoader.java @@ -28,6 +28,7 @@ IPicoRegistry load() return new IPicoRegistry() { private final ServiceLoader serviceLoader = ServiceLoader.load(IPicoRegistration.class); + private final Collection loadedServices = _loadServices(); @Nonnull @Override @@ -35,7 +36,7 @@ public Map, A> find(@Nonnull Class< @Nonnull Class pAnnotationClass) { Map, A> map = new HashMap<>(); - for (IPicoRegistration registration : serviceLoader) + for (IPicoRegistration registration : loadedServices) { Class annotatedClass = registration.getAnnotatedClass(); if (pSearchedType.isAssignableFrom(annotatedClass)) @@ -55,7 +56,7 @@ public Stream find(@Nonnull Class pSearchedType, @Nonnull Function, T> pResolverFunction) { Stream.Builder streamBuilder = Stream.builder(); - for (IPicoRegistration registration : serviceLoader) + for (IPicoRegistration registration : loadedServices) { Class annotatedClass = registration.getAnnotatedClass(); if (pSearchedType.isAssignableFrom(annotatedClass)) @@ -69,6 +70,26 @@ public Stream find(@Nonnull Class pSearchedType, return streamBuilder.build(); } + /** + * We have to load all of our PicoServices into a separate collection, because + * the Java-ServiceLoader throws a ConcurrentModificationException if >1 iterators + * are iterated at the same time. + * Reloading of cached Registrations is currently not supported yet. + * + * @see https://anydoby.com/jblog/en/java/2128 + * @see https://issues.apache.org/jira/browse/SIS-193 + */ + @Nonnull + private Collection _loadServices() + { + synchronized (serviceLoader) + { + HashSet foundServices = new HashSet<>(); + for (IPicoRegistration registration : serviceLoader) + foundServices.add(registration); + return Collections.unmodifiableSet(foundServices); + } + } }; } }