1
votes

I have a weird problem with the node auto fetching in Spring Data Neo4j 4.0.0. I have a class like below :

@NodeEntity
public class FilterVersionChange extends UnitVersion {
    @GraphId
    private Long id;

    public FilterVersionChange() {
        super();
    }

    public FilterVersionChange(String description, Long creationDate)
    {
        super(description, creationDate);
    }

    @Relationship(type="CONTAINS", direction = Relationship.OUTGOING)
    private Set<FilterState> filterStates;

    @Relationship(type="REFERENCES", direction = Relationship.OUTGOING)
    private FilterVersionChange referencedFilterVersionChange;

    @Relationship(type="ADDED", direction = Relationship.OUTGOING)
    private Set<FilterState> newFilterStates;

    @Relationship(type="DELETED", direction = Relationship.OUTGOING)
    private Set<FilterState> deletedFilterStates;

    @Relationship(type="MODIFIED", direction = Relationship.OUTGOING)
    private Set<ModifiedUnitState> modifiedFilterStates;

    @Relationship(type="TRACKS", direction = Relationship.INCOMING)
    private FilterVersion filterVersion;

    @Relationship(type = "CREATED_ON", direction = Relationship.OUTGOING)
    private TimeTreeSecond timeTreeSecond;

    public void createdOn(TimeTreeSecond timeTreeSecond) {
        this.timeTreeSecond = timeTreeSecond;
    }

    public void contains(Set<FilterState> filterStates) {
        this.filterStates = filterStates;
    }

    public void references(FilterVersionChange referencedFilterVersionChange) {
        this.referencedFilterVersionChange = referencedFilterVersionChange;
    }

    public void added(Set<FilterState> newFilterStates) {
        this.newFilterStates = newFilterStates;
    }

    public void deleted(Set<FilterState> deletedFilterStates) {
        this.deletedFilterStates = deletedFilterStates;
    }

    public void modified(Set<ModifiedUnitState> modifiedFilterStates) {
        this.modifiedFilterStates = modifiedFilterStates;
    }

    public void trackedIn(FilterVersion filterVersion) {
        this.filterVersion = filterVersion;
    }

    public FilterVersion getFilterVersion() {
        return filterVersion;
    }

    public Set<FilterState> getFilterStates() {
        return filterStates;
    }
}

In the database, I have one FilterVersionChange node with several FilterStates nodes attached to it via 'CONTAINS' and 'ADDED' relationships. Assume that I have the id of that FilterVersionChange node and I want to get the node by calling findOne(id). But, what I get from it is null value for the filterStates variable.

As I understand from the documentation, findOne should retrieve the depth of 1 by default. But I really have no idea why I get the value of null with the filterStates variable.

Thank you in advance and your suggestion would be really appreciated!

EDIT

This is the function where the insertion code is.

public FilterVersionChange createNewFilterVersionChange(String projectName,
                                                        String filterVersionName,
                                                        String filterVersionChangeDescription,
                                                        Set<FilterState> filterStates)
{
    Long filterVersionNodeId = filterVersionRepository.findFilterVersionByName(projectName, filterVersionName);
    if(filterVersionNodeId != null)
    {
        FilterVersion newFilterVersion = filterVersionRepository.findOne(filterVersionNodeId, 2);
        HashMap<String, Filter> filterHashMap = new HashMap<String, Filter>();
        Iterable<Filter> filters = filterRepository.findAll();
        if(filters.iterator().hasNext())
        {
            for(Filter filter : filters)
            {
                filterHashMap.put(filter.getMatchingString(), filter);
            }
        }

        for(FilterState filterState : filterStates)
        {
            Filter filter;
            if(filterHashMap.isEmpty() == false)
            {
                 filter = filterHashMap.get(filterState.getMatchingString());
            }
            else
            {
                filter = new Filter(filterState.getMatchingString(), filterState.getMatchingType());
                filter.belongsTo(newFilterVersion.getProject());
            }
            filterState.stateOf(filter);
        }

        Date now = new Date();
        FilterVersionChange filterVersionChange = new FilterVersionChange();
        filterVersionChange.setDescription(filterVersionChangeDescription);
        filterVersionChange.setCreationDate(now.getTime());
        filterVersionChange.contains(filterStates);
        filterVersionChange.added(filterStates);
        filterVersionChange.trackedIn(newFilterVersion);
        TimeTreeSecond timeInstantNode = timeTreeService.getFilterTimeInstantNode(projectName, now.getTime());
        filterVersionChange.createdOn(timeInstantNode);
        FilterVersionChange addedFilterVersionChange = filterVersionChangeRepository.save(filterVersionChange);

        return addedFilterVersionChange;
    }
    else
    {
        return null;
    }
}

Here is the FilterState class

@NodeEntity
public class FilterState {

    @GraphId
    private Long id;

    private String matchingString;
    private String matchingType;

    public FilterState() {

    }

    public FilterState(String matchingString, String matchingType) {
        this.matchingString = matchingString;
        setMatchingType(matchingType);
    }

    @Relationship(type="STATE_OF", direction = Relationship.OUTGOING)
    private Filter filter;

    @Relationship(type="PART_OF", direction = Relationship.OUTGOING)
    private CodeUnit codeUnit;

    @Relationship(type="CONTAINS", direction = Relationship.INCOMING)
    private FilterVersionChange containedInFilterVersionChange;

    @Relationship(type="ADDED", direction = Relationship.INCOMING)
    private FilterVersionChange addedInFilterVersionChange;

    public void setMatchingString(String matchingString) {
        this.matchingString = matchingString;
    }

    public void setMatchingType(String matchingType) {
        String type = null;
        if(matchingType.equalsIgnoreCase("RegexFilter"))
        {
            type = "RegexFilter";
        }
        else if(matchingType.equalsIgnoreCase("ClassFilter"))
        {
            type = "ClassFilter";
        }
        this.matchingType = type;
    }

    public void stateOf(Filter filter) {
        this.filter = filter;
    }

    public void partOf(CodeUnit codeUnit) {
        this.codeUnit = codeUnit;
    }

    public String getMatchingString() {
        return matchingString;
    }

    public String getMatchingType() {
        return matchingType;
    }

    public Filter getFilter() {
        return filter;
    }

    public Long getId() {
        return id;
    }

    public void addedIn(FilterVersionChange addedInFilterVersionChange) {
        this.addedInFilterVersionChange = addedInFilterVersionChange;
    }

    public FilterVersionChange getContainedInFilterVersionChange() {
        return containedInFilterVersionChange;
    }
}

and here is the gradle file

def RMQVersion = "3.3.4"
def GSONVersion = "2.3.1"

def Neo4jVersion = "2.2.1"
def Neo4jTimeTreeVersion = "2.2.1.30.21"

def SpringVersion = "4.1.6.RELEASE"
def SDNVersion = "4.0.0.BUILD-SNAPSHOT"

def JunitVersion = "4.12"

apply plugin: 'java'
apply plugin: 'maven'

sourceCompatibility = 1.5
version = '1.0'

repositories {
    mavenCentral()
    maven {
        url("http://maven.springframework.org/milestone")
    }
    maven {
        url("http://repo.spring.io/libs-snapshot")
    }
}

dependencies {
    compile "org.springframework.data:spring-data-neo4j:${SDNVersion}"

    compile "org.neo4j:neo4j:${Neo4jVersion}"
    compile "com.graphaware.neo4j:timetree:${Neo4jTimeTreeVersion}"

    compile "com.rabbitmq:amqp-client:${RMQVersion}"
    compile "com.google.code.gson:gson:${GSONVersion}"

    testCompile group: 'org.springframework.data', name: 'spring-data-neo4j', version: SDNVersion, classifier: 'tests'
    testCompile group: 'org.springframework', name: 'spring-test', version: SpringVersion
    testCompile group: 'junit', name: 'junit', version: JunitVersion
}
1
Is it just missing the Contains and Added? Or is it not loading any relationships at all? Are you using the snapshot built or 4.0.0.M1? Can you turn on the debug log by including <logger name="org.springframework.data.neo4j" level="debug" /> in logback.xml and see if there's anything of importance?Luanne
It's just missing the contains and added and the other Set relationships. The other non Set relationships are loaded. I use 4.0.0.BUILD-SNAPSHOT. I don't have a file named logback.xml here. I use .zip neo4j installation package.Peter Sie
And because it doesn't load those related nodes, it's always gets deleted in database when I save it. it's pretty frustrating..Peter Sie
Is the data created correctly in the graph with the right labels etc.? You can just add a logback.xml as a resource in your project, which should be picked up. Mine looks like <?xml version="1.0" encoding="UTF-8"?> <configuration> <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d %5p %40.40c:%4L - %m%n</pattern> </encoder> </appender> <logger name="org.springframework.data.neo4j" level="debug" /> <root level="info"> <appender-ref ref="console" /> </root> </configuration>Luanne
please see the updated discussion, a fix is available now.Luanne

1 Answers

3
votes

This issue has been fixed post 4.0.0M1, please use the latest build snapshot, thanks.