1

I am not sure if my problem is a non-existent feature or I am using the neo4j-ogm framework incorrectly. Since you are only supposed to post bugs or feature requests in the projects GitHub repository, I would like to place my question here first.

Please be aware, that I shortened my real code to just give you an idea what I try to achieve.

My example application consists of two modules: Module a contains a class to create neo4j-ogm sessions. There I read the configuration from a property file and create the session factory, passing the packages to scan as parameters:

public Neo4jController(final String ... packagesWithNodes) {
    ConfigurationSource props = new ClasspathConfigurationSource("neo4jogm.properties");
    Configuration configuration = new Configuration.Builder(props).build();

    SessionFactory sessionFactory = new SessionFactory(configuration, packagesWithNodes);
    ...
}

Module b includes module a as a Maven dependency and then tries to persist a NodeEntity via the Session object. The Session is created correctly, but the NodeEntity in the passed package is not recognized.

public MyObject create(final MyObject newObject) {
  Neo4jController neo4jController = new Neo4jController("my.example.package");
  neo4jController.getNeo4jSession().save(newObject);

  ...
}

This always results in an IllegalArgumentException:

Class class my.example.package.MyObject is not a valid entity class. Please check the entity mapping.

This is what my NodeEntity in module b looks like

package my.example.package;

import de.bitandgo.workflow.common.model.Neo4jNode;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Property;

@NodeEntity(label = "MyObject")
public class MyObject extends Neo4jNode {

  @Property
  public String name;
}

The base class contains among others

public abstract class Neo4jNode {

    @Id
    @GeneratedValue
    private Long id;
}

I know that neo4j-ogm uses glassgraph internally for scanning the classpath. The corresponding call in the framework with prepended configuration looks like this:

private static List<String> useClassgraph(String[] packagesOrClasses) {

    // .enableExternalClasses() is not needed, as the super classes are loaded anywhere when the class is loaded.
    try (ScanResult scanResult = new ClassGraph()
        .ignoreClassVisibility()
        .acceptPackages(packagesOrClasses)
        .acceptClasses(packagesOrClasses)
        .scan()) {
        return scanResult.getAllClasses().getNames();
    }
}

Via debugging I verified that the desired package my.example.package was passed as an argument to the GlassGraph object.

Also the Neo4jController in module a is able to load the class. I have tested this with the following code

try {
  Class<?> aClass = Class.forName("my.example.package.MyObject");
  System.out.println(aClass);  // prints "class my.example.package.MyObject"
} catch (ClassNotFoundException e) {}

My question is whether neo4j-ogm/classgraph may not be able to find the class at all due to the way neo4j-ogm uses classgraph, or if I am doing something wrong in the usage.

Update 1: The problem seems to be related to my application running inside an application server (TomEE). When I deploy my application ClassGraph is not able to find the configured package. But executing the exact same scan via a classical main method finds me the expected class.

public static void main(String[] args) {
        try (ScanResult scanResult = new ClassGraph()
                .ignoreClassVisibility()
                .acceptPackages("my.example.package")
                .acceptClasses()
                .scan()) {
            System.out.println(scanResult.getAllClasses().getNames());
        }
    }

So I assume the problem is related to the compiled classes not being visible in the "normal" classpath when deploying the application into an application server?

I appreciate any input.

Thanks a lot

Richard
  • 582
  • 5
  • 19

1 Answers1

0

The problem was indeed related to the glassgraph library, which is used by neo4j-ogm for scanning the class path for model files.

glassgraph supports a wide variety of classloaders, but the one of TomEE wasn't included yet. This problem has been fixed since version 4.8.107, so if you run into a similar problem check whether glassgraph supports the classloader of the application server used by you.

You can easily overwrite neo4j-ogm's classgraph dependency by specifying the version you need in your pom.xml.

<dependency>
  <groupId>org.neo4j</groupId>
  <artifactId>neo4j-ogm-core</artifactId>
  <version>${neo4j-version}</version>
  <scope>compile</scope>
</dependency>
<dependency>
  <groupId>org.neo4j</groupId>
  <artifactId>neo4j-ogm-bolt-driver</artifactId>
  <version>${neo4j-version}</version>
  <scope>runtime</scope>
</dependency>

<!-- overwriting the internal classloader of neo4j-ogm because it's used version does not support ApacheTomEE -->
<dependency>
  <groupId>io.github.classgraph</groupId>
  <artifactId>classgraph</artifactId>
  <version>4.8.107</version>
</dependency>

The problem was not related to my multi module Maven structure.

Richard
  • 582
  • 5
  • 19