Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent race condition in entity filtering #4204

Merged
merged 1 commit into from
Aug 12, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2019 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
Expand Down Expand Up @@ -82,4 +82,10 @@ public ObjectGraph createObjectGraph(final Class<?> entityClass, final Set<Strin
? new EmptyObjectGraph(entityClass)
: new ObjectGraphImpl(classToGraph, entityGraph, filteringScopes);
}

@Override
public EntityGraph putIfAbsent(Class<?> entityClass, EntityGraph entityGraph, boolean forWriter) {
final ConcurrentMap<Class<?>, EntityGraph> classToGraph = forWriter ? writerClassToGraph : readerClassToGraph;
return classToGraph.putIfAbsent(entityClass, entityGraph);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2019 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
Expand Down Expand Up @@ -50,7 +50,6 @@
*/
@Singleton
final class EntityInspectorImpl implements EntityInspector {

private final List<EntityProcessor> entityProcessors;

@Inject
Expand All @@ -71,21 +70,26 @@ public EntityInspectorImpl(final InjectionManager injectionManager) {
@Override
public void inspect(final Class<?> entityClass, final boolean forWriter) {
if (!graphProvider.containsEntityGraph(entityClass, forWriter)) {
final EntityGraph graph = graphProvider.getOrCreateEntityGraph(entityClass, forWriter);
final EntityGraph graph = new EntityGraphImpl(entityClass);
final Set<Class<?>> inspect = new HashSet<>();

// Class.
if (!inspectEntityClass(entityClass, graph, forWriter)) {
// Properties.
final Map<String, Method> unmatchedAccessors = inspectEntityProperties(entityClass, graph, inspect, forWriter);
final Map<String, Method> unmatchedAccessors =
inspectEntityProperties(entityClass, graph, inspect, forWriter);

// Setters/Getters without fields.
inspectStandaloneAccessors(unmatchedAccessors, graph, forWriter);

graphProvider.putIfAbsent(entityClass, graph, forWriter);

// Inspect new classes.
for (final Class<?> clazz : inspect) {
inspect(clazz, forWriter);
}
} else {
graphProvider.putIfAbsent(entityClass, graph, forWriter);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2019 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
Expand Down Expand Up @@ -66,4 +66,15 @@ public interface EntityGraphProvider {
* @return an entity-filtering object graph instance.
*/
public ObjectGraph createObjectGraph(final Class<?> entityClass, final Set<String> filteringScopes, final boolean forWriter);

/**
* Store an {@code EntityGraph} for a given entity if not already stored
* @param entityClass entity class which the object graph should be created for.
* @param entityGraph an entity graph to be stored
* @param forWriter flag determining whether the graph should be created for writer/reader.
* @return the previous value associated with the {@code entityClass, forWriter} key,
* or {@code null} if there was no previous mapping for the key. This behavior is inherited from
* {@link java.util.Map#putIfAbsent(Object, Object)}.
*/
public EntityGraph putIfAbsent(final Class<?> entityClass, EntityGraph entityGraph, final boolean forWriter);
}