Skip to content

Commit

Permalink
Fix class loading issue in async environments.
Browse files Browse the repository at this point in the history
  • Loading branch information
meistermeier committed Jan 11, 2024
1 parent 256c1f2 commit be4f22e
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 2 deletions.
32 changes: 30 additions & 2 deletions api/src/main/java/org/neo4j/ogm/config/Configuration.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import java.util.Objects;
import java.util.Optional;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Stream;

import org.neo4j.ogm.support.ClassUtils;
Expand Down Expand Up @@ -65,8 +66,35 @@ public enum ClassLoaderPrecedence {
OGM_CLASS_LOADER
}

public static final ThreadLocal<ClassLoaderPrecedence> CLASS_LOADER_PRECEDENCE = ThreadLocal
.withInitial(() -> ClassLoaderPrecedence.CONTEXT_CLASS_LOADER);
/**
* Set the class loader precedence for interacting with classes during the mapping process.
* This is necessary when running Neo4j-OGM in async environments (like {@code CompletableFuture} usage, Spring Boot's @Async , etc.).
* In those cases, please use {@link Configuration#setClassLoaderPrecedence(ClassLoaderPrecedence)} with {@link ClassLoaderPrecedence#OGM_CLASS_LOADER}.
*
* @deprecated The direct access to this static field has been deprecated.
* Please use the {@link Configuration#setClassLoaderPrecedence(ClassLoaderPrecedence)} method.
*/
@Deprecated
public static final AtomicReference<ClassLoaderPrecedence> CLASS_LOADER_PRECEDENCE = new AtomicReference(ClassLoaderPrecedence.CONTEXT_CLASS_LOADER);

/**
* Set the class loader precedence for interacting with classes during the mapping process.
* This is necessary when running Neo4j-OGM in async environments (like {@code CompletableFuture} usage, Spring Boot's @Async , etc.).
* In those cases, please use {@link Configuration#setClassLoaderPrecedence(ClassLoaderPrecedence)} with {@link ClassLoaderPrecedence#OGM_CLASS_LOADER}.
*
*/
public static void setClassLoaderPrecedence(ClassLoaderPrecedence classLoaderPrecedence) {
CLASS_LOADER_PRECEDENCE.set(classLoaderPrecedence);
}

/**
* Retrieve the current set class loader precedence that is used for working with classes during the mapping process.
*
* @return current configured {@link ClassLoaderPrecedence}
*/
public static ClassLoaderPrecedence getClassLoaderPrecedence() {
return CLASS_LOADER_PRECEDENCE.get();
}

/**
* @return The classloader to be used by OGM.
Expand Down
13 changes: 13 additions & 0 deletions neo4j-ogm-docs/modules/ROOT/partials/reference/configuration.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -402,3 +402,16 @@ Neo4j-OGM uses SLF4J to log statements.
In production, you can set the log level in a file called *logback.xml* to be found at the root of the classpath.
Please see the link:http://logback.qos.ch/manual/[Logback manual] for further details.


[[reference:configuration:class-loading]]
== Class loading precedence

In some scenarios and environments (Spring Boot's `@Async` annotated classes/methods, `CompletableFuture` usage, etc.) , it is necessary to declare the used class loading precedence for Neo4j-OGM to use.
As default, it uses the current thread's context class loader.
To change this behaviour, the `OGM_CLASS_LOADER` has to be set only once for the `Configuration` class.
This can be done during configuration of your application or similar.

[source, java, indent=0]
----
Configuration.setClassLoaderPrecedence(Configuration.ClassLoaderPrecedence.OGM_CLASS_LOADER);
----

0 comments on commit be4f22e

Please sign in to comment.