1

I'm trying to utilize the timetree library in my spring data neo4j 4.0.0 project.

As elaborated in this page, https://github.com/graphaware/neo4j-timetree, I've edited my neo4j.properties file to enable the auto event attaching, add timetree dependency to my gradle, and set a property 'creationDate' in the event node with Long data type. Albeit everything looks as it should be, it still doesn't create any timetree.

Hereby is my neo4j.property file:

# Runtime must be enabled like this
com.graphaware.runtime.enabled=true

# A Runtime module that takes care of attaching the events like this (TT is the ID of the module)
com.graphaware.module.TT.1=com.graphaware.module.timetree.module.TimeTreeModuleBootstrapper

# Nodes which represent events and should be attached automatically have to be defined
com.graphaware.module.TT.event=hasLabel('StructureVersionChange'),hasLabel('RuleVersionChange'),hasLabel('FilterVersionChange')

# Optionally, a property on the event nodes that represents the the time (long) at which the event took place must be specified (defaults to "timestamp")
com.graphaware.module.TT.timestamp=creationDate

# Optionally, a resolution can be specified (defaults to DAY)
com.graphaware.module.TT.resolution=SECOND

# Optionally, a time zone can be specified (defaults to UTC)
com.graphaware.module.TT.timezone=CEST

# Optionally, a relationship type with which the events will be attached to the tree can be specified (defaults to AT_TIME)
com.graphaware.module.TT.relationship=CREATED_ON

# autoAttach must be set to true
com.graphaware.module.TT.autoAttach=true

Actually, before this I tried to use JAVA API version of Timetree for my project, but then I was really confused by the parameter type of the timetree constructor, which is Node. Whereas, in spring my Nodes have types of their classes.

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

EDIT:

neo4j.properties

# Runtime must be enabled like this
com.graphaware.runtime.enabled=true

# A Runtime module that takes care of attaching the events like this (TT is the ID of the module)
com.graphaware.module.TT.1=com.graphaware.module.timetree.module.TimeTreeModuleBootstrapper

# Nodes which represent events and should be attached automatically have to be defined
com.graphaware.module.TT.event=hasLabel('FilterVersionChange') || hasLabel('StructureVersionChange') || hasLabel('CodeUnitVersionChange') || hasLabel('RuleVersionChange') || hasLabel('EpisodeVersion')

# Optionally, a property on the event nodes that represents the the time (long) at which the event took place must be specified (defaults to "timestamp")
com.graphaware.module.TT.timestamp=creationDate

# Optionally, a resolution can be specified (defaults to DAY)
com.graphaware.module.TT.resolution=SECOND

# Optionally, a time zone can be specified (defaults to UTC)
com.graphaware.module.TT.timezone=CEST

# Optionally, a relationship type with which the events will be attached to the tree can be specified (defaults to AT_TIME)
com.graphaware.module.TT.relationship=CREATED_ON

# autoAttach must be set to true
com.graphaware.module.TT.autoAttach=true

data/log/neo4j.0.0

May 17, 2015 4:07:42 PM com.sun.jersey.server.impl.application.WebApplicationImpl _initiate
INFO: Initiating Jersey application, version 'Jersey: 1.18.1 02/19/2014 03:28 AM'
May 17, 2015 4:07:42 PM com.sun.jersey.server.impl.application.WebApplicationImpl _initiate
INFO: Initiating Jersey application, version 'Jersey: 1.18.1 02/19/2014 03:28 AM'
May 17, 2015 4:07:43 PM com.sun.jersey.server.impl.application.WebApplicationImpl _initiate
INFO: Initiating Jersey application, version 'Jersey: 1.18.1 02/19/2014 03:28 AM'
May 17, 2015 4:11:39 PM com.sun.jersey.server.impl.application.WebApplicationImpl _initiate
INFO: Initiating Jersey application, version 'Jersey: 1.18.1 02/19/2014 03:28 AM'
May 17, 2015 4:11:39 PM com.sun.jersey.server.impl.application.WebApplicationImpl _initiate
INFO: Initiating Jersey application, version 'Jersey: 1.18.1 02/19/2014 03:28 AM'
May 17, 2015 4:11:39 PM com.sun.jersey.server.impl.application.WebApplicationImpl _initiate
INFO: Initiating Jersey application, version 'Jersey: 1.18.1 02/19/2014 03:28 AM'
May 17, 2015 4:28:49 PM com.sun.jersey.server.impl.application.WebApplicationImpl _initiate
INFO: Initiating Jersey application, version 'Jersey: 1.18.1 02/19/2014 03:28 AM'
May 17, 2015 4:28:49 PM com.sun.jersey.server.impl.application.WebApplicationImpl _initiate
INFO: Initiating Jersey application, version 'Jersey: 1.18.1 02/19/2014 03:28 AM'
May 17, 2015 4:28:49 PM com.sun.jersey.server.impl.application.WebApplicationImpl _initiate
INFO: Initiating Jersey application, version 'Jersey: 1.18.1 02/19/2014 03:28 AM'

data/graph.db/messages

2015-05-17 14:28:46.537+0000 INFO  [o.n.k.i.DiagnosticsManager]: --- INITIALIZED diagnostics START ---
2015-05-17 14:28:46.538+0000 INFO  [o.n.k.i.DiagnosticsManager]: Neo4j Kernel properties:
2015-05-17 14:28:46.541+0000 INFO  [o.n.k.i.DiagnosticsManager]: com.graphaware.module.TT.resolution=DAY
2015-05-17 14:28:46.541+0000 INFO  [o.n.k.i.DiagnosticsManager]: com.graphaware.module.TT.timestamp=creationDate
2015-05-17 14:28:46.541+0000 INFO  [o.n.k.i.DiagnosticsManager]: com.graphaware.module.TT.relationship=CREATED_ON
2015-05-17 14:28:46.541+0000 INFO  [o.n.k.i.DiagnosticsManager]: com.graphaware.module.TT.event=hasLabel('FilterVersionChange') || hasLabel('ArchitectureUnitVersionChange') || hasLabel('CodeUnitVersionChange') || hasLabel('RuleVersionChange') || hasLabel('EpisodeVersion')
2015-05-17 14:28:46.541+0000 INFO  [o.n.k.i.DiagnosticsManager]: store_dir=C:\NEO4J-~1.1\data\graph.db
2015-05-17 14:28:46.541+0000 INFO  [o.n.k.i.DiagnosticsManager]: com.graphaware.runtime.enabled=true
2015-05-17 14:28:46.541+0000 INFO  [o.n.k.i.DiagnosticsManager]: com.graphaware.module.TT.autoAttach=true
2015-05-17 14:28:46.541+0000 INFO  [o.n.k.i.DiagnosticsManager]: remote_shell_enabled=true
2015-05-17 14:28:46.541+0000 INFO  [o.n.k.i.DiagnosticsManager]: com.graphaware.module.TT.timezone=CEST
2015-05-17 14:28:46.541+0000 INFO  [o.n.k.i.DiagnosticsManager]: com.graphaware.module.TT.1=com.graphaware.module.timetree.module.TimeTreeModuleBootstrapper
2015-05-17 14:28:46.544+0000 INFO  [o.n.k.i.DiagnosticsManager]: Diagnostics providers:
2015-05-17 14:28:46.544+0000 INFO  [o.n.k.i.DiagnosticsManager]: org.neo4j.kernel.configuration.Config
...
...
2015-05-17 14:28:48.656+0000 INFO  [o.n.k.i.DiagnosticsManager]: --- STARTED diagnostics for KernelDiagnostics:StoreFiles END ---
2015-05-17 14:28:48.696+0000 INFO  [o.n.k.EmbeddedGraphDatabase]: Database is now ready
2015-05-17 14:28:48.696+0000 INFO  [o.n.s.d.LifecycleManagingDatabase]: Successfully started database
2015-05-17 14:28:48.699+0000 INFO  [o.n.k.i.DiagnosticsManager]: --- SERVER STARTED START ---
2015-05-17 14:28:48.736+0000 INFO  [o.n.s.CommunityNeoServer]: Starting HTTP on port :7474 with 8 threads available
2015-05-17 14:28:48.872+0000 INFO  [o.n.s.CommunityNeoServer]: Enabling HTTPS on port :7473
2015-05-17 14:28:48.989+0000 INFO  [o.n.s.w.Jetty9WebServer]: Mounting static content at [/webadmin] from [webadmin-html]
2015-05-17 14:28:49.023+0000 INFO  [o.n.s.w.Jetty9WebServer]: Mounting static content at [/browser] from [browser]
2015-05-17 14:28:49.956+0000 INFO  [o.n.s.CommunityNeoServer]: Server started on: http://localhost:7474/
2015-05-17 14:28:49.956+0000 INFO  [o.n.s.CommunityNeoServer]: Remote interface ready and available at [http://localhost:7474/]
2015-05-17 14:28:49.956+0000 INFO  [o.n.k.i.DiagnosticsManager]: --- SERVER STARTED END ---

Class Entity

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

    public FilterVersionChange() {
        super();
    }

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

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

    @Relationship(type="PREVIOUS", direction = Relationship.OUTGOING)
    private FilterVersionChange previousFilterVersionChange;

    @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;

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

    public void previous(FilterVersionChange previousFilterVersionChange) {
        this.previousFilterVersionChange = previousFilterVersionChange;
    }

    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;
    }
}

Repository

@Repository
public interface FilterVersionRepository extends GraphRepository<FilterVersion> {
    @Query("MATCH (project:Project {name:{0}})-[:HAS_FILTER_VERSION]->(filterVersion:FilterVersion {name:{1}}) RETURN filterVersion")
    FilterVersion findFilterVersionByName(String projectName, String filterVersionName);

}

Caller function

public FilterVersionChange createNewFilterVersionChange(String projectName,
                                                            String filterVersionName,
                                                            String filterVersionChangeDescription,
                                                            Set<FilterState> filterStates)
    {
        FilterVersion filterVersion = filterVersionRepository.findFilterVersionByName(projectName, filterVersionName);
        if(filterVersion != null)
        {
            for(FilterState filterState : filterStates)
            {
                Filter filter = new Filter(filterState.getMatchingString(), filterState.getMatchingType());
                filterState.stateOf(filter);
            }
            Set<FilterVersionChange> filterVersionChanges = new HashSet<FilterVersionChange>();
            FilterVersionChange filterVersionChange = new FilterVersionChange(filterVersionChangeDescription, new Date());
            filterVersionChange.contains(filterStates);
            filterVersionChange.added(filterStates);
            filterVersionChanges.add(filterVersionChange);
            filterVersion.tracks(filterVersionChanges);
            filterVersionRepository.save(filterVersion);
            return filterVersionChange;
        }
        else
        {
            return null;
        }
    }

FilterVersion.class

@NodeEntity
public class FilterVersion {
    @GraphId
    private Long id;

    private String name;
    private String description;
    private Date creationDate;

    public FilterVersion() {

    }

    public FilterVersion(String name, String description, Date creationDate) {
        this.name = name;
        this.description = description;
        this.creationDate = creationDate;
    }

    @Relationship(type = "TRACKS", direction = Relationship.OUTGOING)
    private Set<FilterVersionChange> filterVersionChanges;

    @Relationship(type = "HAS_FILTER_VERSION", direction = Relationship.INCOMING)
    private Project project;

    public void setName(String name) {
        this.name = name;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public void setCreationDate(Date creationDate) {
        this.creationDate = creationDate;
    }

    public void tracks(Set<FilterVersionChange> filterVersionChanges) {
        this.filterVersionChanges = filterVersionChanges;
    }

    public void belongsTo(Project project) {
        this.project = project;
    }

    public Project getProject() {
        return project;
    }
}

UnitVersion.class

@NodeEntity
public class UnitVersion {
    @GraphId
    protected Long id;

    private String description;
    private Long creationDate;

    public UnitVersion() {

    }

    public UnitVersion(String description, Date creationDate) {
        this.description = description;
        this.creationDate = creationDate.getTime();
    }

    @Relationship(type = "MAPPED_ON", direction = Relationship.OUTGOING)
    private UnitVersion unitVersion;

    public void setDescription(String description) {
        this.description = description;
    }

    public void setCreationDate(Date creationDate) {
        this.creationDate = creationDate.getTime();
    }

    public void mappedOn(UnitVersion unitVersion) {
        this.unitVersion = unitVersion;
    }
}
Luanne
  • 19,145
  • 1
  • 39
  • 51
Peter Sie
  • 175
  • 11
  • 1
    How have you installed Neo4j? It is an unfortunate fact that the GraphAware Framework only works when you install Neo4j from the .zip download, not the .exe installer. (https://github.com/graphaware/neo4j-framework#getting-graphaware-framework) – Michal Bachman May 17 '15 at 12:52
  • I set up my Neo4j using the .exe installer. But I reinstalled it with the .zip installer just now after reading your comment, set up the neo4j.properties file, and it still doesn't work. :( – Peter Sie May 17 '15 at 14:19
  • Could you also post code for the UnitVersion class? – Luanne May 18 '15 at 04:31
  • And the FilterVersion class too please – Luanne May 18 '15 at 04:44
  • How are you running this? By running your application against a running Neo4j server configured with GraphAware plugins or via a test? – Luanne May 18 '15 at 07:34
  • @Luanne Not via a test. I just run this application against a running Neo4j server. But, I am not sure about the GraphAware plugin you're talking about. Do I need to configure something in my Neo4j server? – Peter Sie May 18 '15 at 08:40
  • Yeah, putting it into an answer :) – Luanne May 18 '15 at 08:42

2 Answers2

4

The dependency is only useful if you're using the timetree programatically. If your application is running against a Neo4j server, then you need to download and save to your Neo4j server plugins directory:

a) The GraphAware framework (choose either Community or Enterprise)

b) The TimeTree module

Both can be downloaded from http://graphaware.com/products/

Without this, even with a configuration in neo4j.properties, the GraphAware Runtime isn't started and the timetree will not work.

If you want to run your code via a test, then you need to include the dependencies for the TimeTree and GraphAware Runtime and start the GraphAware Runtime yourself, with code such as:

 GraphAwareRuntime runtime = GraphAwareRuntimeFactory.createRuntime(getDatabase());
        runtime.registerModule(new TimeTreeModule("timetree",
                TimeTreeConfiguration
                        .defaultConfiguration()
                        .with(new NodeInclusionPolicy() {
                            @Override
                            public boolean include(Node node) {
                                return node.hasLabel(DynamicLabel.label("User"));
                            }
                        })

                        })
                        .withRelationshipType(DynamicRelationshipType.withName("CREATED_ON"))
                        .withTimeZone(DateTimeZone.forTimeZone(TimeZone.getTimeZone("GMT+1")))
                        .withTimestampProperty("createdOn")
                        .withResolution(Resolution.DAY)
                ,
                getDatabase()));
        runtime.start();

Then you can write tests such as

 @Test
    public void shouldSaveUser()
    {
        User user = new User( "Michal" );
        user.setCreatedOn(1431937636995l);
        userRepository.save( user );

        assertSameGraph( getDatabase(), "CREATE (u:User:Person {name:'Michal', createdOn:1431937636995})," +
                "(root:TimeTreeRoot)," +
                        "(root)-[:FIRST]->(year:Year {value:2015})," +
                        "(root)-[:CHILD]->(year)," +
                        "(root)-[:LAST]->(year)," +
                        "(year)-[:FIRST]->(month:Month {value:5})," +
                        "(year)-[:CHILD]->(month)," +
                        "(year)-[:LAST]->(month)," +
                        "(month)-[:FIRST]->(day:Day {value:18})," +
                        "(month)-[:CHILD]->(day)," +
                        "(month)-[:LAST]->(day)," +
                        "(day)<-[:CREATED_ON]-(u)"
        );

    }
Luanne
  • 19,145
  • 1
  • 39
  • 51
  • Does this auto attaching mechanism support multiple timetree graphs in one database? In my case I need more than one timetree. – Peter Sie May 18 '15 at 10:16
  • 1
    I'm having the same problem, I can't seem to get the TimeTree plugin to do anything. Similarly I'm - Using Windows 8.1 - Using Neo4J Community 2.2.2 - I put the graphaware-server-community-all-2.2.2.31.jar and graphaware-timetree-2.2.2.31.22.jar files in the plugins folder - I setup my neo4j.property file similar to OP's, trying to use the autoAttach feature, matching on a particular label (the nodes I want to match have 2 labels, but I'm only using one in the TimeTree config) - I'm using a .net application to send queries to Neo4J. I have no root node or any time nodes. Any suggestions? – Joe Jun 04 '15 at 05:57
  • Does the node you're creating have the right timestamp property (long)? Please consider opening another question with your configuration etc. – Luanne Jun 04 '15 at 06:09
  • Thanks for the reply, the datatype of my timestamp property was wrong, it was a string instead of a long. Once corrected the TimeTree plugin started creating nodes. – Joe Jun 06 '15 at 23:07
1

Defining the possible labels for the TimeTree has a little different syntax as explained in the InclusionPolicy documentation https://github.com/graphaware/neo4j-framework/tree/master/common#inclusion-policies

The syntax is the following :

com.graphaware.module.TT.event=hasLabel('StructureVersionChange')||hasLabel('RuleVersionChange')||hasLabel('FilterVersionChange')

For debugging purposes you may want to add these lines to your conf/custom-logback.xml file :

<appender name="EXTENSIONLOG"  class="ch.qos.logback.core.FileAppender">
  <file>data/log/extensions.log</file>
  <encoder>
      <pattern>%date{yyyy-MM-dd HH:mm:ss.SSSZ} %-5level [%logger{15}]: %message%n</pattern>
  </encoder>
</appender>

<logger name="com.graphaware" level="debug">
  <appender-ref ref="EXTENSIONLOG"/>
</logger>

and look at the extensions.log file

Christophe Willemsen
  • 19,399
  • 2
  • 29
  • 36
  • Thank you for pointing that out! But, I don't know why it still doesn't work. Still there is no time tree nodes created here. Is there anything that I've missed other than: adding timetree dependency, setting this properties file, and providing time property on the event node with Long type? – Peter Sie May 17 '15 at 11:07
  • do you have any output in data/log/console.log and data/graph.db/messages.log file ? – Christophe Willemsen May 17 '15 at 11:11
  • also can you paste the code you use that should trigger the timetree. – Christophe Willemsen May 17 '15 at 11:17
  • I have edited my post. I can't seem to find the console.log file. There's only message file under my db directory. I create my event nodes just as usual. I expect that this auto attaching system doesn't take any extra code on the programming side. – Peter Sie May 17 '15 at 11:44
  • the console.log is under data/log – Christophe Willemsen May 17 '15 at 11:50
  • Sorry but there are only 3 directories right under my db directory: dbms, index, and schema. There is no data nor log directory here.. – Peter Sie May 17 '15 at 11:55
  • are you running on windows ? – Christophe Willemsen May 17 '15 at 12:28
  • I gues @MichalBachman comment on your question is making things clear – Christophe Willemsen May 17 '15 at 14:22
  • Ya, I have reinstalled my Neo4j with the .zip installer just now and unfortunately it still doesn't work. I use Neo4j 2.2.1 – Peter Sie May 17 '15 at 14:24
  • Ok then maybe we'll need your full code, meaning your entities, the repository, please add the logging configuration and a full output of your logs now that neo4j is installed in the other way you should have the log directories present – Christophe Willemsen May 17 '15 at 14:27
  • I have edited my post. The messages file is too big I just include the beginning of the initialization and some last records. – Peter Sie May 17 '15 at 14:45
  • yeah it can be too big, however the console.log file is missing, you should have a console.log with lines like "15:31:22.447 [main] INFO c.g.s.GraphAwareEnterpriseNeoServer - Server started on: http://localhost:7474/ 15:31:22.447 [main] INFO c.g.s.GraphAwareEnterpriseNeoServer - Remote interface ready and available at [http://localhost:7474/] when the db has finished to start – Christophe Willemsen May 17 '15 at 14:51
  • There is no console.log file under my data/log. There are only : extensions, neo4j.0.0, neo4j.0.0.log.lck, and README. – Peter Sie May 17 '15 at 15:03
  • do you have something in %APPDATA%\Neo4j Community\logs ? – Christophe Willemsen May 17 '15 at 15:04
  • Nope, there is no Neo4j folder under my AppData folder – Peter Sie May 17 '15 at 15:08
  • Is the data in Neo4j well persisted, I mean they all have the correct labels and creationDate property as specified in the config? – Christophe Willemsen May 17 '15 at 15:11
  • Yes, the event node has 2 labels (1 of them is FilterVersionChange) and it has the creationDate property with Long type value. Label: FilterVersionChange UnitVersion; creationDate:1431874594403; description:Some Filter Change Description – Peter Sie May 17 '15 at 15:13