Skip to content

Commit

Permalink
InstanceLoader: ConcurrentModificationException if find() is called a…
Browse files Browse the repository at this point in the history
…synchronously
  • Loading branch information
wglanzer committed Apr 21, 2017
1 parent 6b5667f commit d9568bf
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 3 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>de.adito.picoservice</groupId>
<artifactId>picoservice</artifactId>
<version>1.1.0</version>
<version>1.1.1</version>

<name>${project.groupId}:${project.artifactId}</name>
<description>A minimalist registry for java services using serviceloader</description>
Expand Down
25 changes: 23 additions & 2 deletions src/main/java/de/adito/picoservice/InstanceLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,15 @@ IPicoRegistry load()
return new IPicoRegistry()
{
private final ServiceLoader<IPicoRegistration> serviceLoader = ServiceLoader.load(IPicoRegistration.class);
private final Collection<IPicoRegistration> loadedServices = _loadServices();

@Nonnull
@Override
public <C, A extends Annotation> Map<Class<? extends C>, A> find(@Nonnull Class<C> pSearchedType,
@Nonnull Class<A> pAnnotationClass)
{
Map<Class<? extends C>, A> map = new HashMap<>();
for (IPicoRegistration registration : serviceLoader)
for (IPicoRegistration registration : loadedServices)
{
Class<?> annotatedClass = registration.getAnnotatedClass();
if (pSearchedType.isAssignableFrom(annotatedClass))
Expand All @@ -55,7 +56,7 @@ public <T, C> Stream<T> find(@Nonnull Class<C> pSearchedType,
@Nonnull Function<Class<? extends C>, T> pResolverFunction)
{
Stream.Builder<T> streamBuilder = Stream.builder();
for (IPicoRegistration registration : serviceLoader)
for (IPicoRegistration registration : loadedServices)
{
Class<?> annotatedClass = registration.getAnnotatedClass();
if (pSearchedType.isAssignableFrom(annotatedClass))
Expand All @@ -69,6 +70,26 @@ public <T, C> Stream<T> find(@Nonnull Class<C> 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 <a href="https://anydoby.com/jblog/en/java/2128">https://anydoby.com/jblog/en/java/2128</a>
* @see <a href="https://issues.apache.org/jira/browse/SIS-193">https://issues.apache.org/jira/browse/SIS-193</a>
*/
@Nonnull
private Collection<IPicoRegistration> _loadServices()
{
synchronized (serviceLoader)
{
HashSet<IPicoRegistration> foundServices = new HashSet<>();
for (IPicoRegistration registration : serviceLoader)
foundServices.add(registration);
return Collections.unmodifiableSet(foundServices);
}
}
};
}
}

0 comments on commit d9568bf

Please sign in to comment.