neo4j / neo4j-ogm

Java Object-Graph Mapping Library for Neo4j
https://neo4j.com/docs/ogm-manual/
Apache License 2.0
337 stars 165 forks source link

MappingException when querying object with List<Enum> using Embedded #359

Closed jaredhancock31 closed 7 years ago

jaredhancock31 commented 7 years ago

Expected Behavior

Using the EmbeddedDriver, I should be able to query for an Entity with a Collection of Enums without issue. These Enums should be able to have instance fields.

Current Behavior

public class Person extends Entity {
    List<RoleType> roleTypes;
    // getters and setters
}

public enum RoleType {
    DEVELOPER("dev"),
    ARCHITECT("arch"),
    MANAGER("mgr");

    private String value;

    public String getValue() {
        return value;
    }

    RoleType(String value) {
        this.value = value;
    }
}

Now, consider the following two session query methods:

// call this "method1"
<T> Iterable<T> query(Class<T> objectType, String cypher, Map<String, ?> parameters);

// call this "method2"
Result query(String cypher, Map<String, ?> parameters);

When using method1, there are no issues. However, method2 breaks when trying to map the roleTypes field to the Person entity (Caused by: java.lang.ClassCastException: [Ljava.lang.String; cannot be cast to java.util.Collection).

Note that I've only seen this on Embedded (so far). This also happens if a List<Long> field is persisted as an empty ArrayList.

Steps to Reproduce (for bugs)

Link to repo demonstrating problem (please PM me for access): https://github.com/jaredhancock31/cisco-sdn4/tree/listEnums

  1. save entity with collection of enums with instance strings.
  2. using the query api that does not require expected return type, send a query that will return the object in question.

Stacktrace:

Caused by: org.neo4j.ogm.exception.MappingException: Error mapping GraphModel to instance of com.cisco.example.domain.Person at org.neo4j.ogm.context.GraphEntityMapper.mapEntities(GraphEntityMapper.java:138) ~[neo4j-ogm-core-2.1.2.jar:na] at org.neo4j.ogm.context.GraphEntityMapper.map(GraphEntityMapper.java:110) ~[neo4j-ogm-core-2.1.2.jar:na] at org.neo4j.ogm.context.GraphEntityMapper.map(GraphEntityMapper.java:105) ~[neo4j-ogm-core-2.1.2.jar:na] at org.neo4j.ogm.context.RestModelMapper.mapEntity(RestModelMapper.java:157) ~[neo4j-ogm-core-2.1.2.jar:na] at org.neo4j.ogm.context.RestModelMapper.map(RestModelMapper.java:76) ~[neo4j-ogm-core-2.1.2.jar:na] at org.neo4j.ogm.session.delegates.ExecuteQueriesDelegate.query(ExecuteQueriesDelegate.java:102) ~[neo4j-ogm-core-2.1.2.jar:na] at org.neo4j.ogm.session.delegates.ExecuteQueriesDelegate.query(ExecuteQueriesDelegate.java:81) ~[neo4j-ogm-core-2.1.2.jar:na] at org.neo4j.ogm.session.Neo4jSession.query(Neo4jSession.java:392) ~[neo4j-ogm-core-2.1.2.jar:na] at com.cisco.example.Application.lambda$demo$0(Application.java:86) [main/:na] at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:776) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE] ... 11 common frames omitted Caused by: java.lang.ClassCastException: [Ljava.lang.String; cannot be cast to java.util.Collection at org.neo4j.ogm.entity.io.EntityAccess.merge(EntityAccess.java:73) ~[neo4j-ogm-core-2.1.2.jar:na] at org.neo4j.ogm.entity.io.EntityAccess.merge(EntityAccess.java:39) ~[neo4j-ogm-core-2.1.2.jar:na] at org.neo4j.ogm.context.GraphEntityMapper.writeProperty(GraphEntityMapper.java:226) ~[neo4j-ogm-core-2.1.2.jar:na] at org.neo4j.ogm.context.GraphEntityMapper.setProperties(GraphEntityMapper.java:184) ~[neo4j-ogm-core-2.1.2.jar:na] at org.neo4j.ogm.context.GraphEntityMapper.mapNodes(GraphEntityMapper.java:151) ~[neo4j-ogm-core-2.1.2.jar:na] at org.neo4j.ogm.context.GraphEntityMapper.mapEntities(GraphEntityMapper.java:135) ~[neo4j-ogm-core-2.1.2.jar:na] ... 20 common frames omitted

Context

We use a few queries that don't want to pass in an expected return type, as the data being returned may not be uniform in type.

Your Environment

nmervaillie commented 7 years ago

Thanks for reporting. Making a test case is also very much appreciated ! The fix is under review and should be available soon

fairy3 commented 7 years ago

Hi Does the fix available already? Thanks

frant-hartm commented 7 years ago

It is available in 2.1.3-SNAPSHOT. We will be releasing 2.1.3 tomorrow.

fairy3 commented 7 years ago

Thanks Please, tell me should I open a new issue for these one or it's fixed already (it happens when I try to set Enum value) java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Enum at org.neo4j.ogm.typeconversion.EnumStringConverter.toGraphProperty(EnumStringConverter.java:28) at org.neo4j.ogm.cypher.Filter.getTransformedPropertyValue(Filter.java:295) at org.neo4j.ogm.cypher.function.PropertyComparison.parameters(PropertyComparison.java:83) at org.neo4j.ogm.cypher.Filter.parameters(Filter.java:335) at org.neo4j.ogm.session.request.NodeQueryBuilder.build(NodeQueryBuilder.java:60) at org.neo4j.ogm.session.request.FilteredQueryBuilder.buildNodeQuery(FilteredQueryBuilder.java:40) at org.neo4j.ogm.session.request.strategy.impl.NodeQueryStatements$DepthZeroReadStrategy.findByProperties(NodeQueryStatements.java:162) at org.neo4j.ogm.session.request.strategy.impl.NodeQueryStatements.findByType(NodeQueryStatements.java:127) at org.neo4j.ogm.session.delegates.LoadByTypeDelegate.loadAll(LoadByTypeDelegate.java:83) at org.neo4j.ogm.session.delegates.LoadByTypeDelegate.loadAll(LoadByTypeDelegate.java:157) at org.neo4j.ogm.session.Neo4jSession.loadAll(Neo4jSession.java:250)

frant-hartm commented 7 years ago

@fairy3 This is different. Could you open a new issue with more info?

fairy3 commented 7 years ago

Sure