Merge branch 'master' of https://github.com/SpringSource/spring-data-neo4j
Conflicts: spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/Neo4jTemplate.java spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/GraphRepositoryTest.java
@@ -6,9 +6,9 @@
|
||||
<exclude module="jmxtools"/>
|
||||
<exclude module="jmxri"/>
|
||||
</dependency>
|
||||
<dependency org="org.aspectj" name="aspectjrt" rev="1.6.11.RELEASE"/>
|
||||
<dependency org="org.aspectj" name="aspectjtools" rev="1.6.11.RELEASE"/>
|
||||
<dependency org="org.neo4j" name="neo4j-community" rev="1.5"/>
|
||||
<dependency org="org.aspectj" name="aspectjrt" rev="1.6.12"/>
|
||||
<dependency org="org.aspectj" name="aspectjtools" rev="1.6.12"/>
|
||||
<dependency org="org.neo4j" name="neo4j-community" rev="1.6.M02"/>
|
||||
<dependency org="junit" name="junit" rev="4.8.1"/>
|
||||
</dependencies>
|
||||
</ivy-module>
|
||||
|
||||
@@ -1,6 +1,18 @@
|
||||
Spring Data Graph Changelog
|
||||
===========================
|
||||
|
||||
Changes in version 2.0.0.RELEASE (2011-12-23)
|
||||
---------------------------------------------
|
||||
* Updated Neo4j, Cypher-DSL to 1.6.M02, SpringFramework to 3.0.7.RELEASE, Spring-Data-Commons to 1.2.0.RELEASE
|
||||
* updated documentation and examples, added chapter on how to deploy an SDN backed sample app to Heroku
|
||||
* allow customization for index names, e.g. for multi-tenancy
|
||||
* object typed fields are not converted if the actual instance can be stored by Neo4j
|
||||
* cleanup of maven dependencies on neo4j, logging frameworks,
|
||||
* allow injection of custom ConversionServices
|
||||
* template.fetch() reloads entities and collections
|
||||
* support for default field values on load via the @GraphProperty annotation
|
||||
|
||||
|
||||
Changes in version 2.0.0.RC1 (2011-11-11)
|
||||
-----------------------------------------
|
||||
* Updated Neo4j to 1.5 AspectJ to 1.6.12
|
||||
|
||||
7
pom.xml
@@ -7,7 +7,7 @@
|
||||
<name>Spring Data Neo4j Distribution</name>
|
||||
<description><![CDATA[Within the Spring Data project the Spring Data Neo4j library provides integration with the Neo4j graph database, offering object graph mapping, a Neo4jTemplate and Spring-Data-Commons Repository implementations.
|
||||
]]></description>
|
||||
<version>2.0.0.BUILD-SNAPSHOT</version>
|
||||
<version>2.1.0.BUILD-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<modules>
|
||||
<module>spring-data-neo4j-parent</module>
|
||||
@@ -161,6 +161,7 @@
|
||||
<module>spring-data-neo4j-examples/cineasts-aspects</module>
|
||||
<module>spring-data-neo4j-examples/cineasts-rest</module>
|
||||
<module>spring-data-neo4j-examples/myrestaurants-social</module>
|
||||
<module>spring-data-neo4j-examples/todos</module>
|
||||
</modules>
|
||||
</profile>
|
||||
<profile>
|
||||
@@ -243,7 +244,7 @@
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
<!--distributionManagement>
|
||||
<distributionManagement>
|
||||
<downloadUrl>http://www.springsource.com/spring-data</downloadUrl>
|
||||
<site>
|
||||
<id>static.springframework.org</id>
|
||||
@@ -259,7 +260,7 @@
|
||||
<name>Spring Snapshot Repository</name>
|
||||
<url>s3://maven.springframework.org/snapshot</url>
|
||||
</snapshotRepository>
|
||||
</distributionManagement-->
|
||||
</distributionManagement>
|
||||
<build>
|
||||
<extensions>
|
||||
<extension>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-neo4j-parent</artifactId>
|
||||
<version>2.0.0.BUILD-SNAPSHOT</version>
|
||||
<version>2.1.0.BUILD-SNAPSHOT</version>
|
||||
<relativePath>../spring-data-neo4j-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>spring-data-neo4j-aspects</artifactId>
|
||||
@@ -122,8 +122,8 @@
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.tinkerpop</groupId>
|
||||
<artifactId>gremlin</artifactId>
|
||||
<groupId>com.tinkerpop.gremlin</groupId>
|
||||
<artifactId>gremlin-groovy</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ public class IndexTest extends EntityTestBase {
|
||||
assertEquals(friendship, friendshipFinder.findByPropertyValue("Friendship.years", 1));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testGetRelationshipFromLookedUpNode() {
|
||||
|
||||
@@ -66,7 +66,7 @@ public class GremlinQueryEngineTest extends EntityTestBase {
|
||||
@Test
|
||||
@Transactional
|
||||
public void testQueryList() throws Exception {
|
||||
final String queryString = "t = new Table(); [g.v(michael),g.v(david)].each{ n -> n.as('person.name').as('person.age').table(t,['person.name','person.age']){ it.age }{ it.name } >> -1}; t;" ;
|
||||
final String queryString = "t = new Table(); [g.v(michael),g.v(david)].each{ n -> n.as('person.name').as('person.age').table(t,['person.name','person.age']){ it.age }{ it.name }.iterate()}; t;" ;
|
||||
final Collection<Object> result = IteratorUtil.asCollection(queryEngine.query(queryString, MapUtil.map("michael", getNodeId(michael), "david", getNodeId(testTeam.david))));
|
||||
|
||||
assertEquals(asList(testTeam.simpleRowFor(michael, "person"), testTeam.simpleRowFor(testTeam.david, "person")), result);
|
||||
|
||||
@@ -81,6 +81,8 @@ public class IndexingNodeTypeRepresentationStrategyTest extends EntityTestBase {
|
||||
assertEquals(node(subThing), subThingHits.getSingle());
|
||||
assertEquals(thing.getClass().getName(), node(thing).getProperty(IndexingNodeTypeRepresentationStrategy.TYPE_PROPERTY_NAME));
|
||||
assertEquals(subThing.getClass().getName(), node(subThing).getProperty(IndexingNodeTypeRepresentationStrategy.TYPE_PROPERTY_NAME));
|
||||
thingHits.close();
|
||||
subThingHits.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -83,6 +83,7 @@ public class IndexingRelationshipTypeRepresentationStrategyTest extends EntityTe
|
||||
Relationship rel = linkHits.getSingle();
|
||||
assertEquals(rel(link), rel);
|
||||
assertEquals(link.getClass().getName(), rel.getProperty("__type__"));
|
||||
linkHits.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -104,6 +105,7 @@ public class IndexingRelationshipTypeRepresentationStrategyTest extends EntityTe
|
||||
|
||||
IndexHits<Relationship> linkHits = typesIndex.get(IndexingNodeTypeRepresentationStrategy.INDEX_KEY, link.getClass().getName());
|
||||
assertNull(linkHits.getSingle());
|
||||
linkHits.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-neo4j-parent</artifactId>
|
||||
<version>2.0.0.BUILD-SNAPSHOT</version>
|
||||
<version>2.1.0.BUILD-SNAPSHOT</version>
|
||||
<relativePath>../spring-data-neo4j-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>spring-data-neo4j-cross-store</artifactId>
|
||||
@@ -125,8 +125,8 @@
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.tinkerpop</groupId>
|
||||
<artifactId>gremlin</artifactId>
|
||||
<groupId>com.tinkerpop.gremlin</groupId>
|
||||
<artifactId>gremlin-groovy</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@ public class CrossStoreNodeEntityState<ENTITY extends NodeBacked> extends Defaul
|
||||
final String foreignId = createForeignId(id);
|
||||
IndexHits<Node> indexHits = getForeignIdIndex().get(FOREIGN_ID, foreignId);
|
||||
Node node = indexHits.hasNext() ? indexHits.next() : null;
|
||||
indexHits.close();
|
||||
if (node == null) {
|
||||
node = template.createNode();
|
||||
persistForeignId(node, id);
|
||||
|
||||
@@ -52,7 +52,7 @@ public class DataGraphNamespaceHandlerCrossStoreTest {
|
||||
Neo4jTemplate template = config.template;
|
||||
Assert.assertNotNull("template", template);
|
||||
EmbeddedGraphDatabase graphDatabaseService = (EmbeddedGraphDatabase) template.getGraphDatabaseService();
|
||||
Assert.assertEquals("store-dir", "target/config-test", graphDatabaseService.getStoreDir());
|
||||
Assert.assertTrue("store-dir", graphDatabaseService.getStoreDir().endsWith("target/config-test"));
|
||||
Assert.assertNotNull("graphDatabaseService", config.graphDatabaseService);
|
||||
Assert.assertNotNull("transactionManager", config.transactionManager);
|
||||
config.graphDatabaseService.shutdown();
|
||||
|
||||
@@ -55,7 +55,6 @@
|
||||
|
||||
<bean id="graphDatabaseService" class="org.neo4j.test.ImpermanentGraphDatabase"
|
||||
destroy-method="shutdown" scope="singleton">
|
||||
<constructor-arg index="0" value="target/data/recommendation" />
|
||||
</bean>
|
||||
|
||||
<bean id="graphDatabase" class="org.springframework.data.neo4j.support.DelegatingGraphDatabase">
|
||||
|
||||
@@ -11,11 +11,11 @@
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<spring.version>3.0.6.RELEASE</spring.version>
|
||||
<spring.version>3.0.7.RELEASE</spring.version>
|
||||
<slf4j.version>1.6.1</slf4j.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<neo4j.version>1.5</neo4j.version>
|
||||
<spring-data-graph.version>2.0.0.BUILD-SNAPSHOT</spring-data-graph.version>
|
||||
<neo4j.version>1.6.M02</neo4j.version>
|
||||
<spring-data-graph.version>2.1.0.BUILD-SNAPSHOT</spring-data-graph.version>
|
||||
<aspectj.version>1.6.12</aspectj.version>
|
||||
<org.slf4j-version>1.6.1</org.slf4j-version>
|
||||
</properties>
|
||||
|
||||
@@ -11,11 +11,11 @@
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<spring.version>3.0.6.RELEASE</spring.version>
|
||||
<spring.version>3.0.7.RELEASE</spring.version>
|
||||
<slf4j.version>1.6.1</slf4j.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<neo4j.version>1.5</neo4j.version>
|
||||
<spring-data-graph.version>2.0.0.BUILD-SNAPSHOT</spring-data-graph.version>
|
||||
<neo4j.version>1.6.M02</neo4j.version>
|
||||
<spring-data-graph.version>2.1.0.BUILD-SNAPSHOT</spring-data-graph.version>
|
||||
<aspectj.version>1.6.12</aspectj.version>
|
||||
<org.slf4j-version>1.6.1</org.slf4j-version>
|
||||
</properties>
|
||||
@@ -85,7 +85,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-neo4j-rest</artifactId>
|
||||
<version>2.0.0.BUILD-SNAPSHOT</version>
|
||||
<version>2.1.0.BUILD-SNAPSHOT</version>
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -11,13 +11,13 @@
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<spring.version>3.0.6.RELEASE</spring.version>
|
||||
<spring.version>3.0.7.RELEASE</spring.version>
|
||||
<slf4j.version>1.6.1</slf4j.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<neo4j.version>1.5</neo4j.version>
|
||||
<spring-data-graph.version>2.0.0.BUILD-SNAPSHOT</spring-data-graph.version>
|
||||
<spring-data-graph.version>2.1.0.BUILD-SNAPSHOT</spring-data-graph.version>
|
||||
<org.slf4j-version>1.6.1</org.slf4j-version>
|
||||
<aspectj.version>1.6.12</aspectj.version>
|
||||
<neo4j.version>1.6.M02</neo4j.version>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
@@ -295,14 +295,11 @@
|
||||
<junitArtifactName>junit:junit</junitArtifactName>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- the eclipse plugin interacts with the aspectj-maven-plugin
|
||||
BUT ONLY if the ajdtVersion config value is set (remove it and it won't) -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-eclipse-plugin</artifactId>
|
||||
<version>2.8</version>
|
||||
<configuration>
|
||||
<!-- The ajdtVersion configuration parameter is optional. The valid values are none, 1.4, and 1.5. none indicates that AJDT should not be enabled even though Aspectj is enabled in maven. 1.4 generates the org.eclipse.ajdt.ui.prefs file in the .settings directory. 1.5 (or later) includes the configuration into the .classpath file and is the default value. -->
|
||||
<ajdtVersion>1.5</ajdtVersion>
|
||||
<additionalProjectnatures>
|
||||
<projectnature>org.eclipse.jdt.core.javanature</projectnature>
|
||||
@@ -310,47 +307,6 @@
|
||||
</additionalProjectnatures>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!--plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>aspectj-maven-plugin</artifactId>
|
||||
<version>1.2</version>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjrt</artifactId>
|
||||
<version>${aspectj.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjtools</artifactId>
|
||||
<version>${aspectj.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
<goal>test-compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<outxml>true</outxml>
|
||||
<aspectLibraries>
|
||||
<aspectLibrary>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aspects</artifactId>
|
||||
</aspectLibrary>
|
||||
<aspectLibrary>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-neo4j-aspects</artifactId>
|
||||
</aspectLibrary>
|
||||
</aspectLibraries>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin-->
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@ apply plugin: 'idea'
|
||||
apply plugin: 'eclipse'
|
||||
|
||||
|
||||
springVersion = "3.0.5.RELEASE"
|
||||
springDataNeo4jVersion = "1.1.0.RELEASE"
|
||||
aspectjVersion = "1.6.11.RELEASE"
|
||||
springVersion = "3.0.7.RELEASE"
|
||||
springDataNeo4jVersion = "2.0.0.RELEASE"
|
||||
aspectjVersion = "1.6.12"
|
||||
|
||||
apply from:'https://github.com/SpringSource/spring-data-neo4j/raw/master/build/gradle/springdataneo4j.gradle'
|
||||
|
||||
|
||||
@@ -11,11 +11,11 @@
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<spring.version>3.0.6.RELEASE</spring.version>
|
||||
<spring.version>3.0.7.RELEASE</spring.version>
|
||||
<aspectj.version>1.6.12</aspectj.version>
|
||||
<slf4j.version>1.6.1</slf4j.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<spring-data-neo4j.version>2.0.0.BUILD-SNAPSHOT</spring-data-neo4j.version>
|
||||
<spring-data-neo4j.version>2.1.0.BUILD-SNAPSHOT</spring-data-neo4j.version>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<ivy-module version="2.0" xmlns:m="http://ant.apache.org/ivy/maven">
|
||||
<info organisation="org.springframework.data.neo4j.examples" module="hello-worlds"/>
|
||||
<dependencies>
|
||||
<dependency org="org.springframework.data" name="spring-data-neo4j" rev="1.0.0.RELEASE">
|
||||
<dependency org="org.springframework.data" name="spring-data-neo4j" rev="2.0.0.RELEASE">
|
||||
<exclude module="jms"/>
|
||||
<exclude module="jmxtools"/>
|
||||
<exclude module="jmxri"/>
|
||||
</dependency>
|
||||
<dependency org="org.aspectj" name="aspectjrt" rev="1.6.11.RELEASE"/>
|
||||
<dependency org="org.aspectj" name="aspectjtools" rev="1.6.11.RELEASE"/>
|
||||
<dependency org="org.neo4j" name="neo4j-community" rev="1.3"/>
|
||||
<dependency org="org.aspectj" name="aspectjrt" rev="1.6.12"/>
|
||||
<dependency org="org.aspectj" name="aspectjtools" rev="1.6.12"/>
|
||||
<dependency org="org.neo4j" name="neo4j-community" rev="1.6.M02"/>
|
||||
<dependency org="junit" name="junit" rev="4.8.1"/>
|
||||
</dependencies>
|
||||
</ivy-module>
|
||||
|
||||
@@ -5,11 +5,8 @@ apply plugin: 'idea'
|
||||
apply plugin: 'eclipse'
|
||||
|
||||
|
||||
springVersion = "3.0.5.RELEASE"
|
||||
springDataNeo4jVersion = "1.1.0.RELEASE"
|
||||
aspectjVersion = "1.6.11.RELEASE"
|
||||
|
||||
apply from:'https://github.com/SpringSource/spring-data-neo4j/raw/master/build/gradle/springdataneo4j.gradle'
|
||||
springVersion = "3.0.7.RELEASE"
|
||||
springDataNeo4jVersion = "2.0.0.RELEASE"
|
||||
|
||||
configurations {
|
||||
runtime
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
<import file="${settings.dir}/install-ivy.xml" />
|
||||
<import file="${settings.dir}/path.xml" />
|
||||
|
||||
<taskdef resource="org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties" classpath="${lib.dir}/aspectjtools.jar"/>
|
||||
|
||||
<target name="lib.retrieve" depends="install-ivy">
|
||||
<mkdir dir="${lib.dir}" />
|
||||
<ivy:settings file="${settings.dir}/ivysettings.xml" />
|
||||
@@ -29,14 +27,8 @@
|
||||
<target name="compile" description="Compile production classes" depends="lib.retrieve">
|
||||
<mkdir dir="${main.target}" />
|
||||
|
||||
<iajc sourceroots="${main.src}" destDir="${main.target}" classpathref="path.libs" source="1.6">
|
||||
<aspectpath>
|
||||
<pathelement location="${lib.dir}/spring-aspects.jar"/>
|
||||
</aspectpath>
|
||||
<aspectpath>
|
||||
<pathelement location="${lib.dir}/spring-data-neo4j.jar"/>
|
||||
</aspectpath>
|
||||
</iajc>
|
||||
<javac sourcepath="${main.src}" destDir="${main.target}" classpathref="path.libs" source="1.6">
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<target name="compile-tests" description="Compile unit test classes" depends="compile">
|
||||
@@ -44,14 +36,8 @@
|
||||
<copy todir="${main.target}" failonerror="false">
|
||||
<fileset dir="${main.resources}"/>
|
||||
</copy>
|
||||
<iajc sourceroots="${test.src}" destDir="${test.target}" classpathref="path.testing" source="1.6">
|
||||
<aspectpath>
|
||||
<pathelement location="${lib.dir}/spring-aspects.jar"/>
|
||||
</aspectpath>
|
||||
<aspectpath>
|
||||
<pathelement location="${lib.dir}/spring-data-neo4j.jar"/>
|
||||
</aspectpath>
|
||||
</iajc>
|
||||
<javac sourcepath="${test.src}" destDir="${test.target}" classpathref="path.testing" source="1.6">
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<target name="test" depends="clean, compile, compile-tests">
|
||||
|
||||
@@ -11,11 +11,11 @@
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<spring.version>3.0.6.RELEASE</spring.version>
|
||||
<spring.version>3.0.7.RELEASE</spring.version>
|
||||
<aspectj.version>1.6.12</aspectj.version>
|
||||
<slf4j.version>1.6.1</slf4j.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<spring-data-neo4j.version>2.0.0.BUILD-SNAPSHOT</spring-data-neo4j.version>
|
||||
<spring-data-neo4j.version>2.1.0.BUILD-SNAPSHOT</spring-data-neo4j.version>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
<ivy-module version="2.0" xmlns:m="http://ant.apache.org/ivy/maven">
|
||||
<info organisation="org.springframework.data.neo4j.examples" module="hello-worlds"/>
|
||||
<dependencies>
|
||||
<dependency org="org.springframework.data" name="spring-data-neo4j" rev="1.0.0.RELEASE">
|
||||
<dependency org="org.springframework.data" name="spring-data-neo4j" rev="2.0.0.RELEASE">
|
||||
<exclude module="jms"/>
|
||||
<exclude module="jmxtools"/>
|
||||
<exclude module="jmxri"/>
|
||||
</dependency>
|
||||
<dependency org="org.aspectj" name="aspectjrt" rev="1.6.11.RELEASE"/>
|
||||
<dependency org="org.aspectj" name="aspectjtools" rev="1.6.11.RELEASE"/>
|
||||
<dependency org="org.neo4j" name="neo4j-community" rev="1.3"/>
|
||||
<dependency org="org.neo4j" name="neo4j-community" rev="1.6.M02"/>
|
||||
<dependency org="junit" name="junit" rev="4.8.1"/>
|
||||
</dependencies>
|
||||
</ivy-module>
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
<version>2.0.0-BUILD-SNAPSHOT</version>
|
||||
<name>imdb</name>
|
||||
<properties>
|
||||
<spring.version>3.0.6.RELEASE</spring.version>
|
||||
<spring.version>3.0.7.RELEASE</spring.version>
|
||||
<aspectj.version>1.6.12</aspectj.version>
|
||||
<slf4j.version>1.6.1</slf4j.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<data-graph.version>2.0.0.BUILD-SNAPSHOT</data-graph.version>
|
||||
<data-graph.version>2.1.0.BUILD-SNAPSHOT</data-graph.version>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
<groupId>com.springone.myrestaurants</groupId>
|
||||
<artifactId>myrestaurants-social</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<version>2.0.0.BUILD-SNAPSHOT</version>
|
||||
<version>2.1.0.BUILD-SNAPSHOT</version>
|
||||
<name>myrestaurants-social</name>
|
||||
<properties>
|
||||
<spring.version>3.0.6.RELEASE</spring.version>
|
||||
<spring-data-graph.version>2.0.0.BUILD-SNAPSHOT</spring-data-graph.version>
|
||||
<spring.version>3.0.7.RELEASE</spring.version>
|
||||
<spring-data-graph.version>2.1.0.BUILD-SNAPSHOT</spring-data-graph.version>
|
||||
<aspectj.version>1.6.12</aspectj.version>
|
||||
<slf4j.version>1.6.1</slf4j.version>
|
||||
<neo4j.version>1.5</neo4j.version>
|
||||
<neo4j.version>1.6.M02</neo4j.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<spring-security.version>3.0.6.RELEASE</spring-security.version>
|
||||
</properties>
|
||||
|
||||
9
spring-data-neo4j-examples/todos/.gitignore
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
target/
|
||||
.idea
|
||||
*.iml
|
||||
.project
|
||||
.classpath
|
||||
.settings/
|
||||
*.swp
|
||||
*~
|
||||
.DS_Store
|
||||
1
spring-data-neo4j-examples/todos/Procfile
Normal file
@@ -0,0 +1 @@
|
||||
web: sh target/bin/webapp
|
||||
60
spring-data-neo4j-examples/todos/bin/todo
Executable file
@@ -0,0 +1,60 @@
|
||||
#!/bin/sh
|
||||
|
||||
while getopts ":r" opt; do
|
||||
case $opt in
|
||||
r)
|
||||
export APP_URL=`heroku info --raw | sed -n 's/^web_url=\(.*\)$/\1/p'`
|
||||
;;
|
||||
\?)
|
||||
echo "Invalid option: -$OPTARG" >&2
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
APP_URL=${APP_URL:="http://localhost:8080/"}
|
||||
REST_ENDPOINT="${APP_URL}api/todos"
|
||||
CURL_OPTS="--verbose --fail -H Accept:application/json -H Content-Type:application/json"
|
||||
|
||||
list() {
|
||||
curl ${CURL_OPTS} ${REST_ENDPOINT}
|
||||
}
|
||||
|
||||
make() {
|
||||
TITLE=$1
|
||||
curl -d "{ \"title\" :\"${TITLE}\"}" ${CURL_OPTS} ${REST_ENDPOINT}
|
||||
}
|
||||
|
||||
remove() {
|
||||
ID=$1
|
||||
REST_ENDPOINT="${REST_ENDPOINT}/${ID}"
|
||||
curl -X DELETE ${CURL_OPTS} ${REST_ENDPOINT}
|
||||
}
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 { list | mk | rm }"
|
||||
}
|
||||
|
||||
if [ "$1" == "" ]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
case "$1" in
|
||||
list)
|
||||
list
|
||||
;;
|
||||
|
||||
mk)
|
||||
if [ "$2" == "" ]; then usage; echo " mk \"text\""; exit 1; fi
|
||||
make "$2"
|
||||
;;
|
||||
rm)
|
||||
if [ "$2" == "" ]; then usage; echo " rm {id}"; exit 1; fi
|
||||
remove "$2"
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
362
spring-data-neo4j-examples/todos/pom.xml
Normal file
@@ -0,0 +1,362 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.neo4j.app</groupId>
|
||||
<artifactId>sdn-todos</artifactId>
|
||||
<version>2.1.0.BUILD-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>sdn-todos</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<neo4j.version>1.5</neo4j.version>
|
||||
<spring.version>3.0.6.RELEASE</spring.version>
|
||||
<spring-data-neo4j.version>${project.version}</spring-data-neo4j.version>
|
||||
<aspectj.version>1.6.12</aspectj.version>
|
||||
<slf4j.version>1.6.1</slf4j.version>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-maven-release</id>
|
||||
<name>Spring Maven Release Repository</name>
|
||||
<url>http://maven.springframework.org/release</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>neo4j-public-repository</id>
|
||||
<url>http://m2.neo4j.org/</url>
|
||||
<name>Publicly available Maven 2 repository for Neo4j</name>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>spring-maven-milestone</id>
|
||||
<url>http://maven.springframework.org/milestone</url>
|
||||
<name>Spring Framework Maven MILESTONE Repository</name>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>spring-maven-snapshot</id>
|
||||
<url>http://maven.springframework.org/snapshot</url>
|
||||
<name>Springframework Maven SNAPSHOT Repository</name>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>spring-maven-release</id>
|
||||
<name>Spring Maven Release Repository</name>
|
||||
<url>http://maven.springframework.org/release</url>
|
||||
</pluginRepository>
|
||||
<pluginRepository>
|
||||
<id>spring-maven-milestone</id>
|
||||
<name>Spring Maven Milestone Repository</name>
|
||||
<url>http://maven.springframework.org/milestone</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
<dependencies>
|
||||
<!-- General dependencies for any application -->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.8.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
<version>1.2.16</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjrt</artifactId>
|
||||
<version>${aspectj.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjweaver</artifactId>
|
||||
<version>${aspectj.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<version>2.5</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.sf.flexjson</groupId>
|
||||
<artifactId>flexjson</artifactId>
|
||||
<version>2.1</version>
|
||||
</dependency>
|
||||
<!-- self-hosting servlet dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-webapp</artifactId>
|
||||
<version>7.4.4.v20110707</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mortbay.jetty</groupId>
|
||||
<artifactId>jsp-2.1-glassfish</artifactId>
|
||||
<version>2.1.v20100127</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aspects</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-neo4j-aspects</artifactId>
|
||||
<version>${spring-data-neo4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-neo4j-rest</artifactId>
|
||||
<version>${spring-data-neo4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
<version>1.0.0.GA</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j</artifactId>
|
||||
<version>${neo4j.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j-udc</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
<classifier />
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
<classifier />
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>appassembler-maven-plugin</artifactId>
|
||||
<version>1.1.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals><goal>assemble</goal></goals>
|
||||
<configuration>
|
||||
<assembleDirectory>target</assembleDirectory>
|
||||
<extraJvmArguments>-Xmx512m</extraJvmArguments>
|
||||
<programs>
|
||||
<program>
|
||||
<mainClass>Main</mainClass>
|
||||
<name>webapp</name>
|
||||
</program>
|
||||
</programs>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>2.3.2</version>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>aspectj-maven-plugin</artifactId>
|
||||
<version>1.2</version> <!-- NB: do use 1.3 or 1.3.x due to MASPECTJ-90 - wait for 1.4 -->
|
||||
<dependencies>
|
||||
<!-- NB: You must use Maven 2.0.9 or above or these are ignored (see
|
||||
MNG-2972) -->
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjrt</artifactId>
|
||||
<version>${aspectj.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjtools</artifactId>
|
||||
<version>${aspectj.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
<goal>test-compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<outxml>true</outxml>
|
||||
<aspectLibraries>
|
||||
<aspectLibrary>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aspects</artifactId>
|
||||
</aspectLibrary>
|
||||
<aspectLibrary>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-neo4j-aspects</artifactId>
|
||||
</aspectLibrary>
|
||||
</aspectLibraries>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>2.5</version>
|
||||
<configuration>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.8</version>
|
||||
<configuration>
|
||||
<printSummary>false</printSummary>
|
||||
<redirectTestOutputToFile>true</redirectTestOutputToFile>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- IDE -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-eclipse-plugin</artifactId>
|
||||
<version>2.7</version> <!-- Note 2.8 does not work with AspectJ aspect path -->
|
||||
<configuration>
|
||||
<downloadSources>true</downloadSources>
|
||||
<downloadJavadocs>false</downloadJavadocs>
|
||||
<wtpversion>2.0</wtpversion>
|
||||
<additionalBuildcommands>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.ajdt.core.ajbuilder</name>
|
||||
<arguments>
|
||||
<aspectPath>org.springframework.aspects</aspectPath>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.springframework.ide.eclipse.core.springbuilder</name>
|
||||
</buildCommand>
|
||||
</additionalBuildcommands>
|
||||
<additionalProjectnatures>
|
||||
<projectnature>org.eclipse.ajdt.ui.ajnature</projectnature>
|
||||
<projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
|
||||
</additionalProjectnatures>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-idea-plugin</artifactId>
|
||||
<version>2.2</version>
|
||||
<configuration>
|
||||
<downloadSources>true</downloadSources>
|
||||
<dependenciesAsLibraries>true</dependenciesAsLibraries>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>tomcat-maven-plugin</artifactId>
|
||||
<version>1.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.mortbay.jetty</groupId>
|
||||
<artifactId>jetty-maven-plugin</artifactId>
|
||||
<version>7.4.2.v20110526</version>
|
||||
<configuration>
|
||||
<webAppConfig>
|
||||
<contextPath>/${project.name}</contextPath>
|
||||
</webAppConfig>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
100
spring-data-neo4j-examples/todos/readme.md
Normal file
@@ -0,0 +1,100 @@
|
||||
Spring Data Neo4j Todos
|
||||
=======================
|
||||
|
||||
A simple todo list using Spring Data Neo4j, configured for easy deployment to Heroku.
|
||||
|
||||
Get Ready
|
||||
---------
|
||||
|
||||
To prepare for deploying to Heroku, you must first become a Hero:
|
||||
|
||||
* Create an account on [Heroku](http://heroku.com)
|
||||
* Install the `heroku` command-line client
|
||||
* See the [Heroku Quickstart](http://devcenter.heroku.com/articles/quickstart) for details
|
||||
|
||||
Feel ready? OK, then get a copy of this project and checkout the heroku-deploy branch:
|
||||
|
||||
```bash
|
||||
git clone git://github.com/SpringSource/spring-data-neo4j.git
|
||||
cp -r spring-data-neo4j/spring-data-neo4j-examples/todos .
|
||||
cd todos
|
||||
```
|
||||
|
||||
Local build and run
|
||||
-------------------
|
||||
|
||||
* Run a local Neo4j server (using default config)
|
||||
|
||||
```bash
|
||||
export NEO4J_REST_URL=http://localhost:7474/db/data
|
||||
export NEO4J_LOGIN=""
|
||||
export NEO4J_PASSWORD=""
|
||||
```
|
||||
* Build, then run locally
|
||||
|
||||
```bash
|
||||
mvn package
|
||||
sh target/bin/webapp
|
||||
```
|
||||
|
||||
* check that it is working (in another terminal, but same project directory)
|
||||
|
||||
```bash
|
||||
./bin/todo mk "tweet high praises to @neo4j"
|
||||
./bin/todo list
|
||||
```
|
||||
|
||||
Satisfied? Then `ctrl-c` to kill the application.
|
||||
|
||||
|
||||
Deploy on Heroku
|
||||
----------------
|
||||
|
||||
Initialize a local git repository:
|
||||
|
||||
```bash
|
||||
git init .
|
||||
git add .
|
||||
git commit -m "the start of my own todo application"
|
||||
```
|
||||
|
||||
Create a new provisioning stack on Heroku for the app. Heroku will notice that you've got
|
||||
a git repository, adding itself as a remote.
|
||||
|
||||
```bash
|
||||
heroku create --stack cedar`
|
||||
heroku addons:add neo4j
|
||||
git push heroku master
|
||||
```
|
||||
|
||||
Check to make sure it is running with `heroku ps`, which should show a `web.1` process with an "up" state.
|
||||
|
||||
Finally try it out using the `-r` flag to indicate remote access.
|
||||
|
||||
```bash
|
||||
./bin/todo -r mk "tweet thanks for the good work @mesirii @akollegger"
|
||||
./bin/todo -r list
|
||||
```
|
||||
|
||||
To see the Neo4j graph you just created through Heroku, use `heroku config` to reveal the NEO4J_URL
|
||||
which can take you to Neo4j's Webadmin. Have fun!
|
||||
|
||||
For details about preparing your own Spring Data Neo4j application for deployment to Heroku,
|
||||
see the Heroku chapter in "Good Relationships: The Spring Data Neo4j Guide Book".
|
||||
|
||||
Don't forget to decommission the Heroku application when you're done with it.
|
||||
Use `heroku destroy` to free up the instance.
|
||||
|
||||
CLI Tool
|
||||
--------
|
||||
|
||||
A simplistic `todo` script in the `bin` directory can directly create, delete and list todos.
|
||||
|
||||
Usage: todo [-r] [ list | mk | rm ]
|
||||
|
||||
todo -r - access the remote (Heroku) todo application
|
||||
todo list - list current todos
|
||||
todo mk "a new todo" - to create a todo
|
||||
todo rm 1 - to remove the todo with id 1
|
||||
|
||||
|
||||
23
spring-data-neo4j-examples/todos/src/main/java/Main.java
Normal file
@@ -0,0 +1,23 @@
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
public class Main
|
||||
{
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
String webappDirLocation = "src/main/webapp/";
|
||||
String webPort = System.getenv("PORT");
|
||||
if(webPort == null || webPort.isEmpty()) {
|
||||
webPort = "8080";
|
||||
}
|
||||
Server server = new Server(Integer.valueOf(webPort));
|
||||
WebAppContext root = new WebAppContext();
|
||||
root.setContextPath("/");
|
||||
root.setDescriptor(webappDirLocation+"/WEB-INF/web.xml");
|
||||
root.setResourceBase(webappDirLocation);
|
||||
root.setParentLoaderPriority(true);
|
||||
server.setHandler(root);
|
||||
server.start();
|
||||
server.join();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
package org.neo4j.app.todos;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.springframework.beans.factory.annotation.Configurable;
|
||||
import org.springframework.data.neo4j.annotation.GraphId;
|
||||
import org.springframework.data.neo4j.annotation.NodeEntity;
|
||||
|
||||
import flexjson.JSONDeserializer;
|
||||
import flexjson.JSONSerializer;
|
||||
|
||||
@NodeEntity
|
||||
@Configurable
|
||||
public class Todo {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@GraphId
|
||||
private Long id;
|
||||
|
||||
private String title;
|
||||
|
||||
private Boolean isDone = false;
|
||||
|
||||
public Todo() {;}
|
||||
|
||||
public Todo(Node n) {
|
||||
setPersistentState(n);
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return getNodeId();
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return this.title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public Boolean getIsDone() {
|
||||
return this.isDone;
|
||||
}
|
||||
|
||||
public void setIsDone(Boolean done) {
|
||||
this.isDone = done;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Done: ").append(getIsDone()).append(", ");
|
||||
sb.append("Title: ").append(getTitle());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String toJson() {
|
||||
return new JSONSerializer().exclude("*.class", "*.persistentState", "*.entityState").serialize(this);
|
||||
}
|
||||
|
||||
public static String toJsonArray(Iterable<Todo> collection) {
|
||||
return new JSONSerializer().exclude("*.class", "*.persistentState", "*.entityState").serialize(collection);
|
||||
}
|
||||
|
||||
public static Todo fromJsonToTodo(String json) {
|
||||
return new JSONDeserializer<Todo>().use(null, Todo.class).deserialize(json);
|
||||
}
|
||||
|
||||
public static Collection<Todo> fromJsonArrayToTodoes(String json) {
|
||||
return new JSONDeserializer<List<Todo>>().use(null, ArrayList.class).use("values", Todo.class).deserialize(json);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
package org.neo4j.app.todos;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.util.UriUtils;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
@RequestMapping("/todos")
|
||||
@Controller
|
||||
public class TodoController {
|
||||
|
||||
@Autowired TodoRepository todos;
|
||||
|
||||
/**
|
||||
* POST /todos { "title": "text of the todo" }
|
||||
*
|
||||
* Creates a new todo.
|
||||
*
|
||||
* @param json
|
||||
* @return json containing the id of the newly created todo
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.POST, headers = "Accept=application/json")
|
||||
public ResponseEntity<String> createFromJson(@RequestBody String json) {
|
||||
Todo createdTodo = todos.save(Todo.fromJsonToTodo(json));
|
||||
HttpHeaders headers= new HttpHeaders();
|
||||
headers.add("Content-Type", "application/text");
|
||||
return new ResponseEntity<String>("{\"id\":" + createdTodo.getId() + "}", headers, HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /todos/{id}
|
||||
*
|
||||
* Gets the full json for a todo.
|
||||
*
|
||||
* @param id
|
||||
* @return json representation of the requested todo, or HttpStatus.NOT_FOUND
|
||||
*/
|
||||
@RequestMapping(value = "/{id}", method = RequestMethod.GET, headers = "Accept=application/json")
|
||||
@ResponseBody
|
||||
public ResponseEntity<String> showJson(@PathVariable("id") Long id) {
|
||||
Todo todo = todos.findOne(id);
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add("Content-Type", "application/text; charset=utf-8");
|
||||
if (todo == null) {
|
||||
return new ResponseEntity<String>(headers, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
return new ResponseEntity<String>(todo.toJson(), headers, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get /todos/
|
||||
*
|
||||
* Gets a json array of all todos.
|
||||
*
|
||||
* @return json array representation of all todos
|
||||
*/
|
||||
@RequestMapping(headers = "Accept=application/json")
|
||||
@ResponseBody
|
||||
public ResponseEntity<String> listJson() {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add("Content-Type", "application/text; charset=utf-8");
|
||||
return new ResponseEntity<String>(Todo.toJsonArray(todos.findAll()), headers, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* PUT /todos/ { "id": id, "title": "text of todo", idDone: true|false }
|
||||
*
|
||||
* Updates an existing todo.
|
||||
*
|
||||
* @param json full json representation of the todo to update
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.PUT, headers = "Accept=application/json")
|
||||
public ResponseEntity<String> updateFromJson(@RequestBody String json) {
|
||||
HttpHeaders headers= new HttpHeaders();
|
||||
headers.add("Content-Type", "application/text");
|
||||
if (todos.save(Todo.fromJsonToTodo(json)) == null) {
|
||||
return new ResponseEntity<String>(headers, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
return new ResponseEntity<String>(headers, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* DELETE /todos/{id}
|
||||
*
|
||||
* Deletes an existing todo.
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/{id}", method = RequestMethod.DELETE, headers = "Accept=application/json")
|
||||
public ResponseEntity<String> deleteFromJson(@PathVariable("id") Long id) {
|
||||
Todo todo = todos.findOne(id);
|
||||
HttpHeaders headers= new HttpHeaders();
|
||||
headers.add("Content-Type", "application/text");
|
||||
if (todo == null) {
|
||||
return new ResponseEntity<String>(headers, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
todos.delete(todo);
|
||||
return new ResponseEntity<String>(headers, HttpStatus.OK);
|
||||
}
|
||||
|
||||
String encodeUrlPathSegment(String pathSegment, HttpServletRequest httpServletRequest) {
|
||||
String enc = httpServletRequest.getCharacterEncoding();
|
||||
if (enc == null) {
|
||||
enc = WebUtils.DEFAULT_CHARACTER_ENCODING;
|
||||
}
|
||||
try {
|
||||
pathSegment = UriUtils.encodePathSegment(pathSegment, enc);
|
||||
}
|
||||
catch (UnsupportedEncodingException uee) {}
|
||||
return pathSegment;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.neo4j.app.todos;
|
||||
|
||||
import org.springframework.data.neo4j.repository.GraphRepository;
|
||||
|
||||
public interface TodoRepository extends GraphRepository<Todo> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"
|
||||
xmlns:tx="http://www.springframework.org/schema/tx"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/data/neo4j
|
||||
http://www.springframework.org/schema/data/neo4j/spring-neo4j-2.0.xsd
|
||||
http://www.springframework.org/schema/tx
|
||||
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
|
||||
|
||||
<neo4j:repositories base-package="org.neo4j.app.todos"/>
|
||||
<tx:annotation-driven mode="aspectj"/>
|
||||
|
||||
<neo4j:config graphDatabaseService="graphDatabaseService"/>
|
||||
<bean id="graphDatabaseService"
|
||||
class="org.springframework.data.neo4j.rest.SpringRestGraphDatabase">
|
||||
<constructor-arg index="0" value="${NEO4J_REST_URL}" />
|
||||
<constructor-arg index="1" value="${NEO4J_LOGIN}" />
|
||||
<constructor-arg index="2" value="${NEO4J_PASSWORD}" />
|
||||
</bean>
|
||||
|
||||
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:jee="http://www.springframework.org/schema/jee"
|
||||
xmlns:tx="http://www.springframework.org/schema/tx"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
|
||||
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
|
||||
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
|
||||
|
||||
|
||||
<!--
|
||||
This will automatically locate any and all property files you have
|
||||
within your classpath, provided they fall under the META-INF/spring
|
||||
directory. The located property files are parsed and their values can
|
||||
then be used within application context files in the form of
|
||||
${propertyKey}.
|
||||
-->
|
||||
<context:property-placeholder location="classpath*:META-INF/spring/*.properties"/>
|
||||
|
||||
<!--
|
||||
Turn on AspectJ @Configurable support. As a result, any time you
|
||||
instantiate an object, Spring will attempt to perform dependency
|
||||
injection on that object. This occurs for instantiation via the "new"
|
||||
keyword, as well as via reflection. This is possible because AspectJ
|
||||
is used to "weave" Roo-based applications at compile time. In effect
|
||||
this feature allows dependency injection of any object at all in your
|
||||
system, which is a very useful feature (without @Configurable you'd
|
||||
only be able to dependency inject objects acquired from Spring or
|
||||
subsequently presented to a specific Spring dependency injection
|
||||
method). Roo applications use this useful feature in a number of
|
||||
areas, such as @PersistenceContext injection into entities.
|
||||
-->
|
||||
<context:spring-configured/>
|
||||
|
||||
<!--
|
||||
This declaration will cause Spring to locate every @Component,
|
||||
@Repository and @Service in your application. In practical terms this
|
||||
allows you to write a POJO and then simply annotate the new POJO as an
|
||||
@Service and Spring will automatically detect, instantiate and
|
||||
dependency inject your service at startup time. Importantly, you can
|
||||
then also have your new service injected into any other class that
|
||||
requires it simply by declaring a field for your service inside the
|
||||
relying class and Spring will inject it. Note that two exclude filters
|
||||
are declared. The first ensures that Spring doesn't spend time
|
||||
introspecting Roo-specific ITD aspects. The second ensures Roo doesn't
|
||||
instantiate your @Controller classes, as these should be instantiated
|
||||
by a web tier application context. Refer to web.xml for more details
|
||||
about the web tier application context setup services.
|
||||
|
||||
Furthermore, this turns on @Autowired, @PostConstruct etc support. These
|
||||
annotations allow you to use common Spring and Java Enterprise Edition
|
||||
annotations in your classes without needing to do any special configuration.
|
||||
The most commonly used annotation is @Autowired, which instructs Spring to
|
||||
dependency inject an object into your class.
|
||||
-->
|
||||
<context:component-scan base-package="org.neo4j.app.todos">
|
||||
<context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
|
||||
</context:component-scan>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,17 @@
|
||||
log4j.rootLogger=error, stdout
|
||||
|
||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
|
||||
# Print the date in ISO 8601 format
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
|
||||
|
||||
log4j.appender.R=org.apache.log4j.RollingFileAppender
|
||||
log4j.appender.R.File=application.log
|
||||
|
||||
log4j.appender.R.MaxFileSize=100KB
|
||||
# Keep one backup file
|
||||
log4j.appender.R.MaxBackupIndex=1
|
||||
|
||||
log4j.appender.R.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n
|
||||
47
spring-data-neo4j-examples/todos/src/main/webapp/404.html
Executable file
@@ -0,0 +1,47 @@
|
||||
<!DOCTYPE html>
|
||||
<!--[if lt IE 7 ]><html class="ie ie6" lang="en"> <![endif]-->
|
||||
<!--[if IE 7 ]><html class="ie ie7" lang="en"> <![endif]-->
|
||||
<!--[if IE 8 ]><html class="ie ie8" lang="en"> <![endif]-->
|
||||
<!--[if (gte IE 9)|!(IE)]><!--><html lang="en"> <!--<![endif]-->
|
||||
<head>
|
||||
|
||||
<!-- Basic Page Needs
|
||||
================================================== -->
|
||||
<meta charset="utf-8">
|
||||
<title>Your Page Title Here :)</title>
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
<!--[if lt IE 9]>
|
||||
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<!-- Mobile Specific Metas
|
||||
================================================== -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
|
||||
<!-- CSS
|
||||
================================================== -->
|
||||
<link rel="stylesheet" href="stylesheets/base.css">
|
||||
<link rel="stylesheet" href="stylesheets/skeleton.css">
|
||||
<link rel="stylesheet" href="stylesheets/layout.css">
|
||||
|
||||
<!-- Favicons
|
||||
================================================== -->
|
||||
<link rel="shortcut icon" href="images/favicon.ico">
|
||||
<link rel="apple-touch-icon" href="images/apple-touch-icon.png">
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="images/apple-touch-icon-72x72.png">
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="images/apple-touch-icon-114x114.png">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- Primary Page Layout
|
||||
================================================== -->
|
||||
<div class="container">
|
||||
<h1 style="margin-top: 100px; text-align:center">Sorry. Couldn't Find That Page!</h1>
|
||||
</div>
|
||||
|
||||
<!-- End Document
|
||||
================================================== -->
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
styleSheet=resources/styles/alt.css
|
||||
@@ -0,0 +1 @@
|
||||
styleSheet=resources/styles/standard.css
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
|
||||
|
||||
<!-- The controllers are autodetected POJOs labeled with the @Controller annotation. -->
|
||||
<context:component-scan base-package="org.neo4j.app.todos" use-default-filters="false">
|
||||
<context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
|
||||
</context:component-scan>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,88 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.4" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
|
||||
|
||||
|
||||
<display-name>sdn-todos</display-name>
|
||||
|
||||
<description>Neo4j SDN Todo Application</description>
|
||||
|
||||
|
||||
<!-- Enable escaping of form submission contents -->
|
||||
<context-param>
|
||||
<param-name>defaultHtmlEscape</param-name>
|
||||
<param-value>true</param-value>
|
||||
</context-param>
|
||||
|
||||
<context-param>
|
||||
<param-name>contextConfigLocation</param-name>
|
||||
<param-value>classpath*:META-INF/spring/applicationContext*.xml</param-value>
|
||||
</context-param>
|
||||
|
||||
<filter>
|
||||
<filter-name>CharacterEncodingFilter</filter-name>
|
||||
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
|
||||
<init-param>
|
||||
<param-name>encoding</param-name>
|
||||
<param-value>UTF-8</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<param-name>forceEncoding</param-name>
|
||||
<param-value>true</param-value>
|
||||
</init-param>
|
||||
</filter>
|
||||
|
||||
|
||||
|
||||
<filter>
|
||||
<filter-name>HttpMethodFilter</filter-name>
|
||||
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
|
||||
</filter>
|
||||
<filter-mapping>
|
||||
<filter-name>CharacterEncodingFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>HttpMethodFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<!-- Creates the Spring Container shared by all Servlets and Filters -->
|
||||
<listener>
|
||||
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
|
||||
</listener>
|
||||
|
||||
<!-- Handles Spring requests -->
|
||||
<servlet>
|
||||
<servlet-name>dispatcher</servlet-name>
|
||||
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
|
||||
<init-param>
|
||||
<param-name>contextConfigLocation</param-name>
|
||||
<param-value>/WEB-INF/spring/webmvc-config.xml</param-value>
|
||||
</init-param>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>dispatcher</servlet-name>
|
||||
<url-pattern>/api/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<session-config>
|
||||
<session-timeout>10</session-timeout>
|
||||
</session-config>
|
||||
|
||||
<welcome-file-list>
|
||||
<welcome-file>index.jsp</welcome-file>
|
||||
</welcome-file-list>
|
||||
|
||||
<error-page>
|
||||
<exception-type>java.lang.Exception</exception-type>
|
||||
<location>/uncaughtException</location>
|
||||
</error-page>
|
||||
|
||||
<error-page>
|
||||
<error-code>404</error-code>
|
||||
<location>/resourceNotFound</location>
|
||||
</error-page>
|
||||
</web-app>
|
||||
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
BIN
spring-data-neo4j-examples/todos/src/main/webapp/images/apple-touch-icon.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 7.9 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
107
spring-data-neo4j-examples/todos/src/main/webapp/index.jsp
Normal file
@@ -0,0 +1,107 @@
|
||||
<!DOCTYPE html>
|
||||
<!--[if lt IE 7 ]><html class="ie ie6" lang="en"> <![endif]-->
|
||||
<!--[if IE 7 ]><html class="ie ie7" lang="en"> <![endif]-->
|
||||
<!--[if IE 8 ]><html class="ie ie8" lang="en"> <![endif]-->
|
||||
<!--[if (gte IE 9)|!(IE)]><!--><html lang="en"> <!--<![endif]-->
|
||||
<head>
|
||||
|
||||
<!-- Basic Page Needs
|
||||
================================================== -->
|
||||
<meta charset="utf-8">
|
||||
<title>SDN Todos</title>
|
||||
<meta name="description" content="An SDN Demo Application">
|
||||
<meta name="author" content="Andreas Kollegger">
|
||||
<!--[if lt IE 9]>
|
||||
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<!-- Mobile Specific Metas
|
||||
================================================== -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
|
||||
<!-- CSS
|
||||
================================================== -->
|
||||
<link rel="stylesheet" href="stylesheets/base.css">
|
||||
<link rel="stylesheet" href="stylesheets/skeleton.css">
|
||||
<link rel="stylesheet" href="stylesheets/layout.css">
|
||||
|
||||
<!-- Favicons
|
||||
================================================== -->
|
||||
<link rel="shortcut icon" href="images/favicon.ico">
|
||||
<link rel="apple-touch-icon" href="images/apple-touch-icon.png">
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="images/apple-touch-icon-72x72.png">
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="images/apple-touch-icon-114x114.png">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
|
||||
<!-- Primary Page Layout
|
||||
================================================== -->
|
||||
|
||||
<!-- Delete everything in this .container and get started on your own site! -->
|
||||
|
||||
<div class="container">
|
||||
<div class="sixteen columns">
|
||||
<h1 class="remove-bottom" style="margin-top: 40px">Spring Data Neo4j: Todos</h1>
|
||||
<h5>heroku-deploy</h5>
|
||||
<hr />
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="one-third column">
|
||||
<h3>About SDN Todos</h3>
|
||||
<p>SDN Todos is a small demonstration application of Spring Data Neo4j. SDN is used to define a simple 'Todo' domain entity, exposed with a JSON endpoint.
|
||||
Inspired by the SproutCore (now <a href="http://www.emberjs.com/">ember.js</a>) demo application, this was originally intended as a server-side
|
||||
companion using Neo4j. Now, it is a headless baseline implementation with a simple CLI.
|
||||
</p>
|
||||
</div>
|
||||
<div class="one-third column">
|
||||
<h3>Highlights</h3>
|
||||
<p>SDN Todos is small, yet demonstrative:</p>
|
||||
<ul class="square">
|
||||
<li><strong>Spring Data Neo4j simplicity</strong>: annotated POJO, companion Repository and MVC controller</li>
|
||||
<li><strong>Heroku ready</strong>: run locally, or easily deploy into the cloud</li>
|
||||
<li><strong>CLI clarity</strong>: no distracting UI, just simple tooling</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="one-third column">
|
||||
<h3>Docs & Support</h3>
|
||||
<p>To learn more about developing with Spring Data Neo4j, visit <a href="https://spring.neo4j.org">spring.neo4j.org</a>.
|
||||
For questions or comments, join us on the <a href="http://groups.google.com/group/neo4j">Neo4j google group</a>.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- UI -->
|
||||
<div class="row">
|
||||
<h5>Todos (a simply jquery pull from the json endpoint):</h5>
|
||||
|
||||
<div id="todos">
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
</div>
|
||||
|
||||
<!-- footer -->
|
||||
<div class="row">
|
||||
<div class="eight columns">
|
||||
<a href="http://neo4j.org"><image src="images/icon_neo4j.png"/></a>
|
||||
</div>
|
||||
<div class="eight columns">
|
||||
<a href="http://spring.neo4j.org"><image style="float:right" src="images/icon_sdn.png"/></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div><!-- container -->
|
||||
|
||||
|
||||
|
||||
<!-- JS
|
||||
================================================== -->
|
||||
<script src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
|
||||
<script src="javascripts/sdn-todos.js"></script>
|
||||
|
||||
<!-- End Document
|
||||
================================================== -->
|
||||
</body>
|
||||
</html>
|
||||
25
spring-data-neo4j-examples/todos/src/main/webapp/javascripts/sdn-todos.js
Executable file
@@ -0,0 +1,25 @@
|
||||
$(document).ready(function() {
|
||||
|
||||
$.ajaxSetup ({
|
||||
cache: false
|
||||
});
|
||||
|
||||
var jsonUrl = "api/todos";
|
||||
|
||||
$.getJSON(
|
||||
jsonUrl,
|
||||
function(json) {
|
||||
var items = [];
|
||||
|
||||
$.each(json, function(i, todo) {
|
||||
items.push('<li>' + todo.title + '</li>');
|
||||
});
|
||||
|
||||
$('<ul/>', {
|
||||
'class': 'disc',
|
||||
html: items.join('')
|
||||
}).appendTo('div#todos');
|
||||
}
|
||||
);
|
||||
|
||||
});
|
||||
42
spring-data-neo4j-examples/todos/src/main/webapp/javascripts/tabs.js
Executable file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Skeleton V1.1
|
||||
* Copyright 2011, Dave Gamache
|
||||
* www.getskeleton.com
|
||||
* Free to use under the MIT license.
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
* 8/17/2011
|
||||
*/
|
||||
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
/* Tabs Activiation
|
||||
================================================== */
|
||||
|
||||
var tabs = $('ul.tabs');
|
||||
|
||||
tabs.each(function(i) {
|
||||
|
||||
//Get all tabs
|
||||
var tab = $(this).find('> li > a');
|
||||
tab.click(function(e) {
|
||||
|
||||
//Get Location of tab's content
|
||||
var contentLocation = $(this).attr('href');
|
||||
|
||||
//Let go if not a hashed one
|
||||
if(contentLocation.charAt(0)=="#") {
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
//Make Tab Active
|
||||
tab.removeClass('active');
|
||||
$(this).addClass('active');
|
||||
|
||||
//Show Tab Content & add active class
|
||||
$(contentLocation).show().addClass('active').siblings().hide().removeClass('active');
|
||||
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
log4j.rootLogger=error, stdout
|
||||
|
||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
|
||||
# Print the date in ISO 8601 format
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
|
||||
|
||||
log4j.appender.R=org.apache.log4j.RollingFileAppender
|
||||
log4j.appender.R.File=application.log
|
||||
|
||||
log4j.appender.R.MaxFileSize=100KB
|
||||
# Keep one backup file
|
||||
log4j.appender.R.MaxBackupIndex=1
|
||||
|
||||
log4j.appender.R.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n
|
||||
5
spring-data-neo4j-examples/todos/src/main/webapp/robots.txt
Executable file
@@ -0,0 +1,5 @@
|
||||
# www.robotstxt.org/
|
||||
# www.google.com/support/webmasters/bin/answer.py?hl=en&answer=156449
|
||||
|
||||
User-agent: *
|
||||
|
||||
338
spring-data-neo4j-examples/todos/src/main/webapp/stylesheets/base.css
Executable file
@@ -0,0 +1,338 @@
|
||||
/*
|
||||
* Skeleton V1.1
|
||||
* Copyright 2011, Dave Gamache
|
||||
* www.getskeleton.com
|
||||
* Free to use under the MIT license.
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
* 8/17/2011
|
||||
*/
|
||||
|
||||
|
||||
/* Table of Content
|
||||
==================================================
|
||||
#Reset & Basics
|
||||
#Basic Styles
|
||||
#Site Styles
|
||||
#Typography
|
||||
#Links
|
||||
#Lists
|
||||
#Images
|
||||
#Buttons
|
||||
#Tabs
|
||||
#Forms
|
||||
#Misc */
|
||||
|
||||
|
||||
/* #Reset & Basics (Inspired by E. Meyers)
|
||||
================================================== */
|
||||
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
font-size: 100%;
|
||||
font: inherit;
|
||||
vertical-align: baseline; }
|
||||
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {
|
||||
display: block; }
|
||||
body {
|
||||
line-height: 1; }
|
||||
ol, ul {
|
||||
list-style: none; }
|
||||
blockquote, q {
|
||||
quotes: none; }
|
||||
blockquote:before, blockquote:after,
|
||||
q:before, q:after {
|
||||
content: '';
|
||||
content: none; }
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0; }
|
||||
|
||||
|
||||
/* #Basic Styles
|
||||
================================================== */
|
||||
body {
|
||||
background: #fff;
|
||||
font: 14px/21px "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
color: #444;
|
||||
-webkit-font-smoothing: antialiased; /* Fix for webkit rendering */
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
|
||||
/* #Typography
|
||||
================================================== */
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
color: #181818;
|
||||
font-family: "Georgia", "Times New Roman", Helvetica, Arial, sans-serif;
|
||||
font-weight: normal; }
|
||||
h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { font-weight: inherit; }
|
||||
h1 { font-size: 46px; line-height: 50px; margin-bottom: 14px;}
|
||||
h2 { font-size: 35px; line-height: 40px; margin-bottom: 10px; }
|
||||
h3 { font-size: 28px; line-height: 34px; margin-bottom: 8px; }
|
||||
h4 { font-size: 21px; line-height: 30px; margin-bottom: 4px; }
|
||||
h5 { font-size: 17px; line-height: 24px; }
|
||||
h6 { font-size: 14px; line-height: 21px; }
|
||||
.subheader { color: #777; }
|
||||
|
||||
p { margin: 0 0 20px 0; }
|
||||
p img { margin: 0; }
|
||||
p.lead { font-size: 21px; line-height: 27px; color: #777; }
|
||||
|
||||
em { font-style: italic; }
|
||||
strong { font-weight: bold; color: #333; }
|
||||
small { font-size: 80%; }
|
||||
|
||||
/* Blockquotes */
|
||||
blockquote, blockquote p { font-size: 17px; line-height: 24px; color: #777; font-style: italic; }
|
||||
blockquote { margin: 0 0 20px; padding: 9px 20px 0 19px; border-left: 1px solid #ddd; }
|
||||
blockquote cite { display: block; font-size: 12px; color: #555; }
|
||||
blockquote cite:before { content: "\2014 \0020"; }
|
||||
blockquote cite a, blockquote cite a:visited, blockquote cite a:visited { color: #555; }
|
||||
|
||||
hr { border: solid #ddd; border-width: 1px 0 0; clear: both; margin: 10px 0 30px; height: 0; }
|
||||
|
||||
|
||||
/* #Links
|
||||
================================================== */
|
||||
a, a:visited { color: #333; text-decoration: underline; outline: 0; }
|
||||
a:hover, a:focus { color: #000; }
|
||||
p a, p a:visited { line-height: inherit; }
|
||||
|
||||
|
||||
/* #Lists
|
||||
================================================== */
|
||||
ul, ol { margin-bottom: 20px; }
|
||||
ul { list-style: none outside; }
|
||||
ol { list-style: decimal; }
|
||||
ol, ul.square, ul.circle, ul.disc { margin-left: 30px; }
|
||||
ul.square { list-style: square outside; }
|
||||
ul.circle { list-style: circle outside; }
|
||||
ul.disc { list-style: disc outside; }
|
||||
ul ul, ul ol,
|
||||
ol ol, ol ul { margin: 4px 0 5px 30px; font-size: 90%; }
|
||||
ul ul li, ul ol li,
|
||||
ol ol li, ol ul li { margin-bottom: 6px; }
|
||||
li { line-height: 18px; margin-bottom: 12px; }
|
||||
ul.large li { line-height: 21px; }
|
||||
li p { line-height: 21px; }
|
||||
|
||||
/* #Images
|
||||
================================================== */
|
||||
|
||||
img.scale-with-grid {
|
||||
max-width: 100%;
|
||||
height: auto; }
|
||||
|
||||
|
||||
/* #Buttons
|
||||
================================================== */
|
||||
|
||||
a.button,
|
||||
button,
|
||||
input[type="submit"],
|
||||
input[type="reset"],
|
||||
input[type="button"] {
|
||||
background: #eee; /* Old browsers */
|
||||
background: #eee -moz-linear-gradient(top, rgba(255,255,255,.2) 0%, rgba(0,0,0,.2) 100%); /* FF3.6+ */
|
||||
background: #eee -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,.2)), color-stop(100%,rgba(0,0,0,.2))); /* Chrome,Safari4+ */
|
||||
background: #eee -webkit-linear-gradient(top, rgba(255,255,255,.2) 0%,rgba(0,0,0,.2) 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: #eee -o-linear-gradient(top, rgba(255,255,255,.2) 0%,rgba(0,0,0,.2) 100%); /* Opera11.10+ */
|
||||
background: #eee -ms-linear-gradient(top, rgba(255,255,255,.2) 0%,rgba(0,0,0,.2) 100%); /* IE10+ */
|
||||
background: #eee linear-gradient(top, rgba(255,255,255,.2) 0%,rgba(0,0,0,.2) 100%); /* W3C */
|
||||
border: 1px solid #aaa;
|
||||
border-top: 1px solid #ccc;
|
||||
border-left: 1px solid #ccc;
|
||||
padding: 4px 12px;
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
color: #444;
|
||||
display: inline-block;
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
text-shadow: 0 1px rgba(255, 255, 255, .75);
|
||||
cursor: pointer;
|
||||
margin-bottom: 20px;
|
||||
line-height: 21px;
|
||||
font-family: "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; }
|
||||
|
||||
a.button:hover,
|
||||
button:hover,
|
||||
input[type="submit"]:hover,
|
||||
input[type="reset"]:hover,
|
||||
input[type="button"]:hover {
|
||||
color: #222;
|
||||
background: #ddd; /* Old browsers */
|
||||
background: #ddd -moz-linear-gradient(top, rgba(255,255,255,.3) 0%, rgba(0,0,0,.3) 100%); /* FF3.6+ */
|
||||
background: #ddd -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,.3)), color-stop(100%,rgba(0,0,0,.3))); /* Chrome,Safari4+ */
|
||||
background: #ddd -webkit-linear-gradient(top, rgba(255,255,255,.3) 0%,rgba(0,0,0,.3) 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: #ddd -o-linear-gradient(top, rgba(255,255,255,.3) 0%,rgba(0,0,0,.3) 100%); /* Opera11.10+ */
|
||||
background: #ddd -ms-linear-gradient(top, rgba(255,255,255,.3) 0%,rgba(0,0,0,.3) 100%); /* IE10+ */
|
||||
background: #ddd linear-gradient(top, rgba(255,255,255,.3) 0%,rgba(0,0,0,.3) 100%); /* W3C */
|
||||
border: 1px solid #888;
|
||||
border-top: 1px solid #aaa;
|
||||
border-left: 1px solid #aaa; }
|
||||
|
||||
a.button:active,
|
||||
button:active,
|
||||
input[type="submit"]:active,
|
||||
input[type="reset"]:active,
|
||||
input[type="button"]:active {
|
||||
border: 1px solid #666;
|
||||
background: #ccc; /* Old browsers */
|
||||
background: #ccc -moz-linear-gradient(top, rgba(255,255,255,.35) 0%, rgba(10,10,10,.4) 100%); /* FF3.6+ */
|
||||
background: #ccc -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,.35)), color-stop(100%,rgba(10,10,10,.4))); /* Chrome,Safari4+ */
|
||||
background: #ccc -webkit-linear-gradient(top, rgba(255,255,255,.35) 0%,rgba(10,10,10,.4) 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: #ccc -o-linear-gradient(top, rgba(255,255,255,.35) 0%,rgba(10,10,10,.4) 100%); /* Opera11.10+ */
|
||||
background: #ccc -ms-linear-gradient(top, rgba(255,255,255,.35) 0%,rgba(10,10,10,.4) 100%); /* IE10+ */
|
||||
background: #ccc linear-gradient(top, rgba(255,255,255,.35) 0%,rgba(10,10,10,.4) 100%); /* W3C */ }
|
||||
|
||||
.button.full-width,
|
||||
button.full-width,
|
||||
input[type="submit"].full-width,
|
||||
input[type="reset"].full-width,
|
||||
input[type="button"].full-width {
|
||||
width: 100%;
|
||||
padding-left: 0 !important;
|
||||
padding-right: 0 !important;
|
||||
text-align: center; }
|
||||
|
||||
|
||||
/* #Tabs (activate in tabs.js)
|
||||
================================================== */
|
||||
ul.tabs {
|
||||
display: block;
|
||||
margin: 0 0 20px 0;
|
||||
padding: 0;
|
||||
border-bottom: solid 1px #ddd; }
|
||||
ul.tabs li {
|
||||
display: block;
|
||||
width: auto;
|
||||
height: 30px;
|
||||
padding: 0;
|
||||
float: left;
|
||||
margin-bottom: 0; }
|
||||
ul.tabs li a {
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
width: auto;
|
||||
height: 29px;
|
||||
padding: 0px 20px;
|
||||
line-height: 30px;
|
||||
border: solid 1px #ddd;
|
||||
border-width: 1px 1px 0 0;
|
||||
margin: 0;
|
||||
background: #f5f5f5;
|
||||
font-size: 13px; }
|
||||
ul.tabs li a.active {
|
||||
background: #fff;
|
||||
height: 30px;
|
||||
position: relative;
|
||||
top: -4px;
|
||||
padding-top: 4px;
|
||||
border-left-width: 1px;
|
||||
margin: 0 0 0 -1px;
|
||||
color: #111;
|
||||
-moz-border-radius-topleft: 2px;
|
||||
-webkit-border-top-left-radius: 2px;
|
||||
border-top-left-radius: 2px;
|
||||
-moz-border-radius-topright: 2px;
|
||||
-webkit-border-top-right-radius: 2px;
|
||||
border-top-right-radius: 2px; }
|
||||
ul.tabs li:first-child a.active {
|
||||
margin-left: 0; }
|
||||
ul.tabs li:first-child a {
|
||||
border-width: 1px 1px 0 1px;
|
||||
-moz-border-radius-topleft: 2px;
|
||||
-webkit-border-top-left-radius: 2px;
|
||||
border-top-left-radius: 2px; }
|
||||
ul.tabs li:last-child a {
|
||||
-moz-border-radius-topright: 2px;
|
||||
-webkit-border-top-right-radius: 2px;
|
||||
border-top-right-radius: 2px; }
|
||||
|
||||
ul.tabs-content { margin: 0; display: block; }
|
||||
ul.tabs-content > li { display:none; }
|
||||
ul.tabs-content > li.active { display: block; }
|
||||
|
||||
/* Clearfixing tabs for beautiful stacking */
|
||||
ul.tabs:before,
|
||||
ul.tabs:after {
|
||||
content: '\0020';
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
width: 0;
|
||||
height: 0; }
|
||||
ul.tabs:after {
|
||||
clear: both; }
|
||||
ul.tabs {
|
||||
zoom: 1; }
|
||||
|
||||
|
||||
/* #Forms
|
||||
================================================== */
|
||||
|
||||
form {
|
||||
margin-bottom: 20px; }
|
||||
fieldset {
|
||||
margin-bottom: 20px; }
|
||||
input[type="text"],
|
||||
input[type="password"],
|
||||
input[type="email"],
|
||||
textarea,
|
||||
select {
|
||||
border: 1px solid #ccc;
|
||||
padding: 6px 4px;
|
||||
outline: none;
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
font: 13px "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
color: #777;
|
||||
margin: 0;
|
||||
width: 210px;
|
||||
max-width: 100%;
|
||||
display: block;
|
||||
margin-bottom: 20px;
|
||||
background: #fff; }
|
||||
select {
|
||||
padding: 0; }
|
||||
input[type="text"]:focus,
|
||||
input[type="password"]:focus,
|
||||
input[type="email"]:focus,
|
||||
textarea:focus {
|
||||
border: 1px solid #aaa;
|
||||
color: #444;
|
||||
-moz-box-shadow: 0 0 3px rgba(0,0,0,.2);
|
||||
-webkit-box-shadow: 0 0 3px rgba(0,0,0,.2);
|
||||
box-shadow: 0 0 3px rgba(0,0,0,.2); }
|
||||
textarea {
|
||||
min-height: 60px; }
|
||||
label,
|
||||
legend {
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
font-size: 13px; }
|
||||
select {
|
||||
width: 220px; }
|
||||
input[type="checkbox"] {
|
||||
display: inline; }
|
||||
label span,
|
||||
legend span {
|
||||
font-weight: normal;
|
||||
font-size: 13px;
|
||||
color: #444; }
|
||||
|
||||
/* #Misc
|
||||
================================================== */
|
||||
.remove-bottom { margin-bottom: 0 !important; }
|
||||
.half-bottom { margin-bottom: 10px !important; }
|
||||
.add-bottom { margin-bottom: 20px !important; }
|
||||
|
||||
|
||||
/* #SDN styling
|
||||
================================================== */
|
||||
#footer { background: #eee; }
|
||||
58
spring-data-neo4j-examples/todos/src/main/webapp/stylesheets/layout.css
Executable file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Skeleton V1.1
|
||||
* Copyright 2011, Dave Gamache
|
||||
* www.getskeleton.com
|
||||
* Free to use under the MIT license.
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
* 8/17/2011
|
||||
*/
|
||||
|
||||
/* Table of Content
|
||||
==================================================
|
||||
#Site Styles
|
||||
#Page Styles
|
||||
#Media Queries
|
||||
#Font-Face */
|
||||
|
||||
/* #Site Styles
|
||||
================================================== */
|
||||
|
||||
/* #Page Styles
|
||||
================================================== */
|
||||
|
||||
/* #Media Queries
|
||||
================================================== */
|
||||
|
||||
/* Smaller than standard 960 (devices and browsers) */
|
||||
@media only screen and (max-width: 959px) {}
|
||||
|
||||
/* Tablet Portrait size to standard 960 (devices and browsers) */
|
||||
@media only screen and (min-width: 768px) and (max-width: 959px) {}
|
||||
|
||||
/* All Mobile Sizes (devices and browser) */
|
||||
@media only screen and (max-width: 767px) {}
|
||||
|
||||
/* Mobile Landscape Size to Tablet Portrait (devices and browsers) */
|
||||
@media only screen and (min-width: 480px) and (max-width: 767px) {}
|
||||
|
||||
/* Mobile Portrait Size to Mobile Landscape Size (devices and browsers) */
|
||||
@media only screen and (max-width: 479px) {}
|
||||
|
||||
|
||||
/* #Font-Face
|
||||
================================================== */
|
||||
/* This is the proper syntax for an @font-face file
|
||||
Just create a "fonts" folder at the root,
|
||||
copy your FontName into code below and remove
|
||||
comment brackets */
|
||||
|
||||
/* @font-face {
|
||||
font-family: 'FontName';
|
||||
src: url('../fonts/FontName.eot');
|
||||
src: url('../fonts/FontName.eot?iefix') format('eot'),
|
||||
url('../fonts/FontName.woff') format('woff'),
|
||||
url('../fonts/FontName.ttf') format('truetype'),
|
||||
url('../fonts/FontName.svg#webfontZam02nTh') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal; }
|
||||
*/
|
||||
236
spring-data-neo4j-examples/todos/src/main/webapp/stylesheets/skeleton.css
vendored
Executable file
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* Skeleton V1.1
|
||||
* Copyright 2011, Dave Gamache
|
||||
* www.getskeleton.com
|
||||
* Free to use under the MIT license.
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
* 8/17/2011
|
||||
*/
|
||||
|
||||
|
||||
/* Table of Contents
|
||||
==================================================
|
||||
#Base 960 Grid
|
||||
#Tablet (Portrait)
|
||||
#Mobile (Portrait)
|
||||
#Mobile (Landscape)
|
||||
#Clearing */
|
||||
|
||||
|
||||
|
||||
/* #Base 960 Grid
|
||||
================================================== */
|
||||
|
||||
.container { position: relative; width: 960px; margin: 0 auto; padding: 0; }
|
||||
.column, .columns { float: left; display: inline; margin-left: 10px; margin-right: 10px; }
|
||||
.row { margin-bottom: 20px; }
|
||||
|
||||
/* Nested Column Classes */
|
||||
.column.alpha, .columns.alpha { margin-left: 0; }
|
||||
.column.omega, .columns.omega { margin-right: 0; }
|
||||
|
||||
/* Base Grid */
|
||||
.container .one.column { width: 40px; }
|
||||
.container .two.columns { width: 100px; }
|
||||
.container .three.columns { width: 160px; }
|
||||
.container .four.columns { width: 220px; }
|
||||
.container .five.columns { width: 280px; }
|
||||
.container .six.columns { width: 340px; }
|
||||
.container .seven.columns { width: 400px; }
|
||||
.container .eight.columns { width: 460px; }
|
||||
.container .nine.columns { width: 520px; }
|
||||
.container .ten.columns { width: 580px; }
|
||||
.container .eleven.columns { width: 640px; }
|
||||
.container .twelve.columns { width: 700px; }
|
||||
.container .thirteen.columns { width: 760px; }
|
||||
.container .fourteen.columns { width: 820px; }
|
||||
.container .fifteen.columns { width: 880px; }
|
||||
.container .sixteen.columns { width: 940px; }
|
||||
|
||||
.container .one-third.column { width: 300px; }
|
||||
.container .two-thirds.column { width: 620px; }
|
||||
|
||||
/* Offsets */
|
||||
.container .offset-by-one { padding-left: 60px; }
|
||||
.container .offset-by-two { padding-left: 120px; }
|
||||
.container .offset-by-three { padding-left: 180px; }
|
||||
.container .offset-by-four { padding-left: 240px; }
|
||||
.container .offset-by-five { padding-left: 300px; }
|
||||
.container .offset-by-six { padding-left: 360px; }
|
||||
.container .offset-by-seven { padding-left: 420px; }
|
||||
.container .offset-by-eight { padding-left: 480px; }
|
||||
.container .offset-by-nine { padding-left: 540px; }
|
||||
.container .offset-by-ten { padding-left: 600px; }
|
||||
.container .offset-by-eleven { padding-left: 660px; }
|
||||
.container .offset-by-twelve { padding-left: 720px; }
|
||||
.container .offset-by-thirteen { padding-left: 780px; }
|
||||
.container .offset-by-fourteen { padding-left: 840px; }
|
||||
.container .offset-by-fifteen { padding-left: 900px; }
|
||||
|
||||
|
||||
|
||||
/* #Tablet (Portrait)
|
||||
================================================== */
|
||||
|
||||
/* Note: Design for a width of 768px */
|
||||
|
||||
@media only screen and (min-width: 768px) and (max-width: 959px) {
|
||||
.container { width: 768px; }
|
||||
.container .column,
|
||||
.container .columns { margin-left: 10px; margin-right: 10px; }
|
||||
.column.alpha, .columns.alpha { margin-left: 0; margin-right: 10px; }
|
||||
.column.omega, .columns.omega { margin-right: 0; margin-left: 10px; }
|
||||
|
||||
.container .one.column { width: 28px; }
|
||||
.container .two.columns { width: 76px; }
|
||||
.container .three.columns { width: 124px; }
|
||||
.container .four.columns { width: 172px; }
|
||||
.container .five.columns { width: 220px; }
|
||||
.container .six.columns { width: 268px; }
|
||||
.container .seven.columns { width: 316px; }
|
||||
.container .eight.columns { width: 364px; }
|
||||
.container .nine.columns { width: 412px; }
|
||||
.container .ten.columns { width: 460px; }
|
||||
.container .eleven.columns { width: 508px; }
|
||||
.container .twelve.columns { width: 556px; }
|
||||
.container .thirteen.columns { width: 604px; }
|
||||
.container .fourteen.columns { width: 652px; }
|
||||
.container .fifteen.columns { width: 700px; }
|
||||
.container .sixteen.columns { width: 748px; }
|
||||
|
||||
.container .one-third.column { width: 236px; }
|
||||
.container .two-thirds.column { width: 492px; }
|
||||
|
||||
/* Offsets */
|
||||
.container .offset-by-one { padding-left: 48px; }
|
||||
.container .offset-by-two { padding-left: 96px; }
|
||||
.container .offset-by-three { padding-left: 144px; }
|
||||
.container .offset-by-four { padding-left: 192px; }
|
||||
.container .offset-by-five { padding-left: 240px; }
|
||||
.container .offset-by-six { padding-left: 288px; }
|
||||
.container .offset-by-seven { padding-left: 336px; }
|
||||
.container .offset-by-eight { padding-left: 348px; }
|
||||
.container .offset-by-nine { padding-left: 432px; }
|
||||
.container .offset-by-ten { padding-left: 480px; }
|
||||
.container .offset-by-eleven { padding-left: 528px; }
|
||||
.container .offset-by-twelve { padding-left: 576px; }
|
||||
.container .offset-by-thirteen { padding-left: 624px; }
|
||||
.container .offset-by-fourteen { padding-left: 672px; }
|
||||
.container .offset-by-fifteen { padding-left: 720px; }
|
||||
}
|
||||
|
||||
|
||||
/* #Mobile (Portrait)
|
||||
================================================== */
|
||||
|
||||
/* Note: Design for a width of 320px */
|
||||
|
||||
@media only screen and (max-width: 767px) {
|
||||
.container { width: 300px; }
|
||||
.columns, .column { margin: 0; }
|
||||
|
||||
.container .one.column,
|
||||
.container .two.columns,
|
||||
.container .three.columns,
|
||||
.container .four.columns,
|
||||
.container .five.columns,
|
||||
.container .six.columns,
|
||||
.container .seven.columns,
|
||||
.container .eight.columns,
|
||||
.container .nine.columns,
|
||||
.container .ten.columns,
|
||||
.container .eleven.columns,
|
||||
.container .twelve.columns,
|
||||
.container .thirteen.columns,
|
||||
.container .fourteen.columns,
|
||||
.container .fifteen.columns,
|
||||
.container .sixteen.columns,
|
||||
.container .one-third.column,
|
||||
.container .two-thirds.column { width: 300px; }
|
||||
|
||||
/* Offsets */
|
||||
.container .offset-by-one,
|
||||
.container .offset-by-two,
|
||||
.container .offset-by-three,
|
||||
.container .offset-by-four,
|
||||
.container .offset-by-five,
|
||||
.container .offset-by-six,
|
||||
.container .offset-by-seven,
|
||||
.container .offset-by-eight,
|
||||
.container .offset-by-nine,
|
||||
.container .offset-by-ten,
|
||||
.container .offset-by-eleven,
|
||||
.container .offset-by-twelve,
|
||||
.container .offset-by-thirteen,
|
||||
.container .offset-by-fourteen,
|
||||
.container .offset-by-fifteen { padding-left: 0; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* #Mobile (Landscape)
|
||||
================================================== */
|
||||
|
||||
/* Note: Design for a width of 480px */
|
||||
|
||||
@media only screen and (min-width: 480px) and (max-width: 767px) {
|
||||
.container { width: 420px; }
|
||||
.columns, .column { margin: 0; }
|
||||
|
||||
.container .one.column,
|
||||
.container .two.columns,
|
||||
.container .three.columns,
|
||||
.container .four.columns,
|
||||
.container .five.columns,
|
||||
.container .six.columns,
|
||||
.container .seven.columns,
|
||||
.container .eight.columns,
|
||||
.container .nine.columns,
|
||||
.container .ten.columns,
|
||||
.container .eleven.columns,
|
||||
.container .twelve.columns,
|
||||
.container .thirteen.columns,
|
||||
.container .fourteen.columns,
|
||||
.container .fifteen.columns,
|
||||
.container .sixteen.columns,
|
||||
.container .one-third.column,
|
||||
.container .two-thirds.column { width: 420px; }
|
||||
}
|
||||
|
||||
|
||||
/* #Clearing
|
||||
================================================== */
|
||||
|
||||
/* Self Clearing Goodness */
|
||||
.container:after { content: "\0020"; display: block; height: 0; clear: both; visibility: hidden; }
|
||||
|
||||
/* Use clearfix class on parent to clear nested columns,
|
||||
or wrap each row of columns in a <div class="row"> */
|
||||
.clearfix:before,
|
||||
.clearfix:after,
|
||||
.row:before,
|
||||
.row:after {
|
||||
content: '\0020';
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
width: 0;
|
||||
height: 0; }
|
||||
.row:after,
|
||||
.clearfix:after {
|
||||
clear: both; }
|
||||
.row,
|
||||
.clearfix {
|
||||
zoom: 1; }
|
||||
|
||||
/* You can also use a <br class="clear" /> to clear columns */
|
||||
.clear {
|
||||
clear: both;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-neo4j-parent</artifactId>
|
||||
<name>Spring Data Neo4j Parent</name>
|
||||
<version>2.0.0.BUILD-SNAPSHOT</version>
|
||||
<version>2.1.0.BUILD-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<description><![CDATA[Spring Data Neo4j parent project. Defines dependencies and common configuration for the build process.
|
||||
]]></description>
|
||||
@@ -124,12 +124,13 @@
|
||||
<org.mockito.version>1.8.4</org.mockito.version>
|
||||
<org.slf4j.version>1.6.1</org.slf4j.version>
|
||||
<org.springframework.version>3.0.6.RELEASE</org.springframework.version>
|
||||
<data.commons.version>1.2.0.M2</data.commons.version>
|
||||
<neo4j.version>1.5</neo4j.version>
|
||||
<data.commons.version>1.2.0.RC1</data.commons.version>
|
||||
<neo4j.version>1.6.M02</neo4j.version>
|
||||
<neo4j.spatial.version>0.7-SNAPSHOT</neo4j.spatial.version>
|
||||
<aspectj.version>1.6.12</aspectj.version>
|
||||
<blueprints.version>1.0</blueprints.version>
|
||||
<gremlin.version>1.3</gremlin.version>
|
||||
<blueprints.version>1.1</blueprints.version>
|
||||
<gremlin.version>1.4</gremlin.version>
|
||||
<pipes.version>1.4</pipes.version>
|
||||
</properties>
|
||||
<profiles>
|
||||
<profile>
|
||||
@@ -338,6 +339,61 @@
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.tinkerpop.gremlin</groupId>
|
||||
<artifactId>gremlin-groovy</artifactId>
|
||||
<version>${gremlin.version}</version>
|
||||
<type>jar</type>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j-ha</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j-management</artifactId>
|
||||
</exclusion>
|
||||
<!-- Sail support not needed -->
|
||||
<exclusion>
|
||||
<groupId>com.tinkerpop.blueprints</groupId>
|
||||
<artifactId>blueprints-sail-graph</artifactId>
|
||||
</exclusion>
|
||||
<!-- Maven support in groovy not needed -->
|
||||
<exclusion>
|
||||
<groupId>org.codehaus.groovy.maven</groupId>
|
||||
<artifactId>gmaven-plugin</artifactId>
|
||||
</exclusion>
|
||||
<!-- "readline" not needed - we only expose gremlin through webadmin -->
|
||||
<exclusion>
|
||||
<groupId>jline</groupId>
|
||||
<artifactId>jline</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.tinkerpop.blueprints</groupId>
|
||||
<artifactId>blueprints-neo4j-graph</artifactId>
|
||||
<version>${blueprints.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j-ha</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j-management</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.tinkerpop.blueprints</groupId>
|
||||
<artifactId>blueprints-core</artifactId>
|
||||
@@ -352,8 +408,8 @@
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.tinkerpop</groupId>
|
||||
<artifactId>gremlin</artifactId>
|
||||
<groupId>com.tinkerpop.gremlin</groupId>
|
||||
<artifactId>gremlin-groovy</artifactId>
|
||||
<version>${gremlin.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
@@ -414,7 +470,7 @@
|
||||
<dependency>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j-cypher-dsl</artifactId>
|
||||
<version>${neo4j.version}</version>
|
||||
<version>1.6.M02</version>
|
||||
<!--optional>true</optional-->
|
||||
</dependency>
|
||||
<!--dependency>
|
||||
@@ -439,6 +495,12 @@
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j-spatial</artifactId>
|
||||
<version>${neo4j.spatial.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-configuration</groupId>
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-neo4j-parent</artifactId>
|
||||
<version>2.0.0.BUILD-SNAPSHOT</version>
|
||||
<version>2.1.0.BUILD-SNAPSHOT</version>
|
||||
<relativePath>../spring-data-neo4j-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>spring-data-neo4j-rest</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>2.0.0.BUILD-SNAPSHOT</version>
|
||||
<version>2.1.0.BUILD-SNAPSHOT</version>
|
||||
<name>Spring Data Neo4j REST Wrapper</name>
|
||||
<description><![CDATA[Spring Data Neo4j Wrapper for the Neo4j REST API, provides a Graph Database proxy for the remote invocation.
|
||||
]]></description>
|
||||
@@ -48,7 +48,7 @@
|
||||
<dependency>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j-rest-graphdb</artifactId>
|
||||
<version>1.5</version>
|
||||
<version>1.6.M02</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.neo4j</groupId>
|
||||
@@ -150,8 +150,8 @@
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.tinkerpop</groupId>
|
||||
<artifactId>gremlin</artifactId>
|
||||
<groupId>com.tinkerpop.gremlin</groupId>
|
||||
<artifactId>gremlin-groovy</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ import org.mortbay.jetty.Server;
|
||||
import org.mortbay.jetty.handler.RequestLogHandler;
|
||||
import org.neo4j.graphdb.GraphDatabaseService;
|
||||
import org.neo4j.kernel.AbstractGraphDatabase;
|
||||
import org.neo4j.server.AddressResolver;
|
||||
import org.neo4j.server.Bootstrapper;
|
||||
import org.neo4j.server.NeoServerWithEmbeddedWebServer;
|
||||
import org.neo4j.server.configuration.PropertyFileConfigurator;
|
||||
@@ -38,7 +37,6 @@ import org.neo4j.server.web.Jetty6WebServer;
|
||||
import org.neo4j.test.ImpermanentGraphDatabase;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
@@ -78,11 +76,7 @@ public class LocalTestServer {
|
||||
return new GraphDatabaseFactory() {
|
||||
@Override
|
||||
public AbstractGraphDatabase createDatabase(String databaseStoreDirectory, Map<String, String> databaseProperties) {
|
||||
try {
|
||||
return new ImpermanentGraphDatabase();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return new ImpermanentGraphDatabase();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -97,12 +91,6 @@ public class LocalTestServer {
|
||||
return serverModules;
|
||||
}
|
||||
};
|
||||
final AddressResolver addressResolver = new AddressResolver() {
|
||||
@Override
|
||||
public String getHostname() {
|
||||
return hostname;
|
||||
}
|
||||
};
|
||||
final JettyStartupListener startupListener = new JettyStartupListener();
|
||||
final Jetty6WebServer jettyWebServer = new Jetty6WebServer() {
|
||||
@Override
|
||||
@@ -123,8 +111,7 @@ public class LocalTestServer {
|
||||
super.stop();
|
||||
}
|
||||
};
|
||||
neoServer = new NeoServerWithEmbeddedWebServer(bootstrapper
|
||||
, addressResolver, new StartupHealthCheck(), new PropertyFileConfigurator(new File(url.getPath())), jettyWebServer, serverModules) {
|
||||
neoServer = new NeoServerWithEmbeddedWebServer(bootstrapper, new StartupHealthCheck(), new PropertyFileConfigurator(new File(url.getPath())), jettyWebServer, serverModules) {
|
||||
@Override
|
||||
protected int getWebServerPort() {
|
||||
return port;
|
||||
|
||||
@@ -37,6 +37,7 @@ public class RestIndexTest extends RestTestBase {
|
||||
IndexHits<Node> hits = nodeIndex().get("name", "test");
|
||||
Assert.assertEquals("index results", true, hits.hasNext());
|
||||
Assert.assertEquals(node(), hits.next());
|
||||
hits.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -45,6 +46,7 @@ public class RestIndexTest extends RestTestBase {
|
||||
IndexHits<Node> hits = nodeIndex().query("name", "tes*");
|
||||
Assert.assertEquals("index results", true, hits.hasNext());
|
||||
Assert.assertEquals(node(), hits.next());
|
||||
hits.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -53,12 +55,14 @@ public class RestIndexTest extends RestTestBase {
|
||||
IndexHits<Node> hits = nodeIndex().query("age", "age:[30 TO 40]");
|
||||
Assert.assertEquals("index results", true, hits.hasNext());
|
||||
Assert.assertEquals(node(), hits.next());
|
||||
hits.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotFoundInNodeIndex() {
|
||||
IndexHits<Node> hits = nodeIndex().get("foo", "bar");
|
||||
Assert.assertEquals("no index results", false, hits.hasNext());
|
||||
hits.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -68,12 +72,14 @@ public class RestIndexTest extends RestTestBase {
|
||||
IndexHits<Relationship> hits = relationshipIndex().get("name", value);
|
||||
Assert.assertEquals("index results", true, hits.hasNext());
|
||||
Assert.assertEquals(relationship(), hits.next());
|
||||
hits.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotFoundInRelationshipIndex() {
|
||||
IndexHits<Relationship> hits = relationshipIndex().get("foo", "bar");
|
||||
Assert.assertEquals("no index results", false, hits.hasNext());
|
||||
hits.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -86,6 +92,8 @@ public class RestIndexTest extends RestTestBase {
|
||||
nodeIndex().remove(node(), "time", value);
|
||||
IndexHits<Node> hitsAfterRemove = nodeIndex().get("time", value);
|
||||
Assert.assertEquals("not found in index results", false, hitsAfterRemove.hasNext());
|
||||
hits.close();
|
||||
hitsAfterRemove.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -98,6 +106,8 @@ public class RestIndexTest extends RestTestBase {
|
||||
relationshipIndex().remove(relationship(), "time", value);
|
||||
IndexHits<Relationship> hitsAfterRemove = relationshipIndex().get("time", value);
|
||||
Assert.assertEquals("not found in index results", false, hitsAfterRemove.hasNext());
|
||||
hits.close();
|
||||
hitsAfterRemove.close();
|
||||
}
|
||||
|
||||
private Index<Node> nodeIndex() {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-neo4j-parent</artifactId>
|
||||
<version>2.0.0.BUILD-SNAPSHOT</version>
|
||||
<version>2.1.0.BUILD-SNAPSHOT</version>
|
||||
<relativePath>../spring-data-neo4j-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>spring-data-neo4j</artifactId>
|
||||
@@ -200,8 +200,8 @@
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.tinkerpop</groupId>
|
||||
<artifactId>gremlin</artifactId>
|
||||
<groupId>com.tinkerpop.gremlin</groupId>
|
||||
<artifactId>gremlin-groovy</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.data.neo4j.querydsl;
|
||||
import com.mysema.query.annotations.*;
|
||||
import com.mysema.query.apt.DefaultConfiguration;
|
||||
import com.mysema.query.apt.Processor;
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
import org.springframework.data.neo4j.annotation.NodeEntity;
|
||||
|
||||
import javax.annotation.processing.AbstractProcessor;
|
||||
|
||||
@@ -314,6 +314,11 @@ public abstract class AbstractGraphRepository<S extends PropertyContainer, T> im
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getStoredJavaType(Object entity) {
|
||||
return template.getStoredJavaType(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(T entity) {
|
||||
template.delete(entity);
|
||||
|
||||
@@ -123,4 +123,6 @@ public interface CRUDRepository<T> extends PagingAndSortingRepository<T, Long> {
|
||||
*/
|
||||
Page<T> findAll(Pageable pageable);
|
||||
|
||||
Class getStoredJavaType(Object entity);
|
||||
|
||||
}
|
||||
@@ -43,6 +43,11 @@ public class NodeGraphRepositoryImpl<T> extends AbstractGraphRepository<Node, T>
|
||||
return template.createRelationshipBetween(start,end,relationshipEntityClass,relationshipType,false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> R createDuplicateRelationshipBetween(T start, Object end, Class<R> relationshipEntityClass, String relationshipType) {
|
||||
return template.createRelationshipBetween(start,end,relationshipEntityClass,relationshipType,true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> R getRelationshipBetween(T start, Object end, Class<R> relationshipEntityClass, String relationshipType) {
|
||||
return template.getRelationshipBetween(start,end,relationshipEntityClass,relationshipType);
|
||||
|
||||
@@ -21,6 +21,7 @@ package org.springframework.data.neo4j.repository;
|
||||
*/
|
||||
public interface RelationshipOperationsRepository<T> {
|
||||
<R> R createRelationshipBetween(T start, Object end, Class<R> relationshipEntityClass, String relationshipType);
|
||||
<R> R createDuplicateRelationshipBetween(T start, Object end, Class<R> relationshipEntityClass, String relationshipType);
|
||||
<R> R getRelationshipBetween(T start, Object end, Class<R> relationshipEntityClass, String relationshipType);
|
||||
void deleteRelationshipBetween(T start, Object end, String type);
|
||||
}
|
||||
|
||||
@@ -23,8 +23,6 @@ import org.springframework.data.neo4j.support.query.QueryEngine;
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
import org.springframework.data.repository.query.Parameters;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author mh
|
||||
* @since 31.10.11
|
||||
@@ -66,6 +64,7 @@ class CypherGraphRepositoryQuery extends GraphRepositoryQuery {
|
||||
private String getSortOrder(Sort sort) {
|
||||
String result = "";
|
||||
for (Sort.Order order : sort) {
|
||||
if (!result.isEmpty()) result += ", ";
|
||||
result += order.getProperty() + " " + order.getDirection();
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -622,4 +622,11 @@ public class Neo4jTemplate implements Neo4jOperations, EntityPersister {
|
||||
ParameterCheck.notNull(entity,"entity");
|
||||
return getMappingPolicy(entity.getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getStoredJavaType(Object entity) {
|
||||
final PropertyContainer container = entity instanceof PropertyContainer ? (PropertyContainer)entity: getPersistentState(entity);
|
||||
if (container==null) return null;
|
||||
return getInfrastructure().getTypeRepresentationStrategies().getJavaType(container);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Collection;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -260,14 +261,15 @@ class Neo4jPersistentPropertyImpl extends AbstractPersistentProperty<Neo4jPersis
|
||||
}
|
||||
@Override
|
||||
public boolean isEntity() {
|
||||
return super.isEntity() && (hasRelationshipEntityType() || hasNodeEntityType());
|
||||
return super.isEntity() && (isRelationshipEntity(getType()) || isNodeEntity(getType()));
|
||||
}
|
||||
|
||||
private boolean hasRelationshipEntityType() {
|
||||
return getType().isAnnotationPresent(RelationshipEntity.class);
|
||||
private boolean isRelationshipEntity(final Class<?> type) {
|
||||
return type.isAnnotationPresent(RelationshipEntity.class);
|
||||
}
|
||||
private boolean hasNodeEntityType() {
|
||||
return getType().isAnnotationPresent(NodeEntity.class);
|
||||
|
||||
private boolean isNodeEntity(Class<?> type) {
|
||||
return type.isAnnotationPresent(NodeEntity.class);
|
||||
}
|
||||
|
||||
public String getIndexKey() {
|
||||
@@ -300,4 +302,17 @@ class Neo4jPersistentPropertyImpl extends AbstractPersistentProperty<Neo4jPersis
|
||||
public boolean isTransient() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<? extends TypeInformation<?>> getPersistentEntityType() {
|
||||
final Iterable<? extends TypeInformation<?>> result = super.getPersistentEntityType();
|
||||
for (Iterator<? extends TypeInformation<?>> it = result.iterator(); it.hasNext(); ) {
|
||||
final TypeInformation<?> typeInformation = it.next();
|
||||
final Class type = typeInformation.getType();
|
||||
if (isNodeEntity(type) || isRelationshipEntity(type)) continue;
|
||||
System.out.println("removing "+getName()+" "+type+" "+typeInformation.getActualType().getType());
|
||||
it.remove();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,12 @@ public class Neo4jPersistentEntityImpl<T> extends BasicPersistentEntity<T, Neo4j
|
||||
@Override
|
||||
public void verify() {
|
||||
super.verify();
|
||||
if (!isManaged() && getIdProperty()==null) throw new MappingException("No id property in "+this);
|
||||
if (isManaged()) {
|
||||
return;
|
||||
}
|
||||
final Neo4jPersistentProperty idProperty = getIdProperty();
|
||||
if (idProperty == null) throw new MappingException("No id property in " + this);
|
||||
if (idProperty.getType().isPrimitive()) throw new MappingException("The type of the id-property in " + idProperty+" must not be a primitive type but an object type like java.lang.Long");
|
||||
}
|
||||
|
||||
public boolean useShortNames() {
|
||||
|
||||
@@ -83,13 +83,7 @@ public class SourceStateTransmitter<S extends PropertyContainer> {
|
||||
}
|
||||
|
||||
private <T> T getProperty(BeanWrapper<Neo4jPersistentEntity<Object>, Object> wrapper, Neo4jPersistentProperty property, Class<T> type, boolean fieldAccessOnly) {
|
||||
try {
|
||||
return wrapper.getProperty(property, type, fieldAccessOnly);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new MappingException("Error retrieving property " + property.getName() + " from " + wrapper.getBean(), e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new MappingException("Error retrieving property " + property.getName() + " from " + wrapper.getBean(), e.getTargetException());
|
||||
}
|
||||
return wrapper.getProperty(property, type, fieldAccessOnly);
|
||||
}
|
||||
|
||||
private <R> Object getProperty(BeanWrapper<Neo4jPersistentEntity<R>, R> wrapper, Neo4jPersistentProperty property) {
|
||||
|
||||
@@ -38,7 +38,7 @@ public class GremlinExecutor {
|
||||
private volatile ScriptEngine engine;
|
||||
|
||||
private ScriptEngine createScriptEngine() {
|
||||
return new ScriptEngineManager().getEngineByName("gremlin");
|
||||
return new ScriptEngineManager().getEngineByName("gremlin-groovy");
|
||||
}
|
||||
|
||||
private static final AtomicInteger executionCount = new AtomicInteger();
|
||||
@@ -62,7 +62,7 @@ public class GremlinExecutor {
|
||||
|
||||
private Bindings createBindings(Map<String, Object> params) {
|
||||
final Bindings bindings = new SimpleBindings();
|
||||
bindings.put(GRAPH_VARIABLE, new Neo4jGraph(graphDatabaseService));
|
||||
bindings.put(GRAPH_VARIABLE, new Neo4jGraph(graphDatabaseService,false));
|
||||
if (params==null) return bindings;
|
||||
for (Map.Entry<String, Object> entry : params.entrySet()) {
|
||||
bindings.put(entry.getKey(),entry.getValue());
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.support.typerepresentation;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
import org.neo4j.graphdb.PropertyContainer;
|
||||
import org.neo4j.graphdb.index.Index;
|
||||
import org.neo4j.graphdb.index.IndexHits;
|
||||
import org.neo4j.helpers.collection.ClosableIterable;
|
||||
import org.springframework.data.neo4j.core.GraphDatabase;
|
||||
import org.springframework.data.neo4j.core.TypeRepresentationStrategy;
|
||||
import org.springframework.data.neo4j.support.index.ClosableIndexHits;
|
||||
import org.springframework.data.neo4j.support.index.IndexProvider;
|
||||
import org.springframework.data.neo4j.support.index.IndexType;
|
||||
|
||||
public abstract class AbstractIndexingTypeRepresentationStrategy<S extends PropertyContainer> implements
|
||||
TypeRepresentationStrategy<S> {
|
||||
|
||||
public static final String TYPE_PROPERTY_NAME = "__type__";
|
||||
public static final String INDEX_KEY = "className";
|
||||
protected String INDEX_NAME;
|
||||
protected final GraphDatabase graphDb;
|
||||
protected final EntityTypeCache typeCache;
|
||||
protected final IndexProvider indexProvider;
|
||||
private final Class<? extends PropertyContainer> clazz;
|
||||
private final Class<? extends Annotation> typeEntityClass;
|
||||
|
||||
public AbstractIndexingTypeRepresentationStrategy(GraphDatabase graphDb, IndexProvider indexProvider,
|
||||
final String indexName, final Class<? extends PropertyContainer> clazz,
|
||||
final Class<? extends Annotation> typeEntityClass) {
|
||||
this.graphDb = graphDb;
|
||||
this.indexProvider = indexProvider;
|
||||
typeCache = new EntityTypeCache();
|
||||
INDEX_NAME = indexName;
|
||||
this.clazz = clazz;
|
||||
this.typeEntityClass = typeEntityClass;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Index<S> getTypesIndex() {
|
||||
return (Index<S>) graphDb.createIndex(clazz, INDEX_NAME, IndexType.SIMPLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postEntityCreation(S state, Class<?> type) {
|
||||
addToTypesIndex(state, type);
|
||||
state.setProperty(TYPE_PROPERTY_NAME, type.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public long count(Class<?> entityClass) {
|
||||
long count = 0;
|
||||
final IndexHits<S> hits = getTypesIndex().get(INDEX_KEY, entityClass.getName());
|
||||
while (hits.hasNext()) {
|
||||
hits.next();
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preEntityRemoval(S state) {
|
||||
getTypesIndex().remove(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <U> ClosableIterable<S> findAll(Class<U> clazz) {
|
||||
return findAllRelBacked(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <U> Class<U> getJavaType(S propertyContainer) {
|
||||
if (propertyContainer == null)
|
||||
throw new IllegalArgumentException("Relationship or Node is null");
|
||||
String className = (String) propertyContainer.getProperty(TYPE_PROPERTY_NAME);
|
||||
return typeCache.getClassForName(className);
|
||||
}
|
||||
|
||||
protected void addToTypesIndex(S relationshipOrNode, Class<?> entityClass) {
|
||||
Class<?> type = entityClass;
|
||||
while (type.getAnnotation(typeEntityClass) != null) {
|
||||
String value = entityClass.getName();
|
||||
if (indexProvider != null)
|
||||
value = indexProvider.createIndexValueForType(entityClass);
|
||||
|
||||
getTypesIndex().add(relationshipOrNode, INDEX_KEY, value);
|
||||
type = type.getSuperclass();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("hiding")
|
||||
private <Object> ClosableIterable<S> findAllRelBacked(Class<Object> clazz) {
|
||||
String value = clazz.getName();
|
||||
if (indexProvider != null)
|
||||
value = indexProvider.createIndexValueForType(clazz);
|
||||
|
||||
final IndexHits<S> allEntitiesOfType = getTypesIndex().get(INDEX_KEY, value);
|
||||
return new ClosableIndexHits<S>(allEntitiesOfType);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,89 +17,31 @@
|
||||
package org.springframework.data.neo4j.support.typerepresentation;
|
||||
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.index.Index;
|
||||
import org.neo4j.graphdb.index.IndexHits;
|
||||
import org.neo4j.helpers.collection.ClosableIterable;
|
||||
import org.springframework.data.neo4j.annotation.NodeEntity;
|
||||
import org.springframework.data.neo4j.core.GraphDatabase;
|
||||
import org.springframework.data.neo4j.core.NodeTypeRepresentationStrategy;
|
||||
import org.springframework.data.neo4j.support.index.ClosableIndexHits;
|
||||
import org.springframework.data.neo4j.support.index.IndexProvider;
|
||||
import org.springframework.data.neo4j.support.index.IndexType;
|
||||
|
||||
public class IndexingNodeTypeRepresentationStrategy implements NodeTypeRepresentationStrategy {
|
||||
public class IndexingNodeTypeRepresentationStrategy extends AbstractIndexingTypeRepresentationStrategy<Node> implements
|
||||
NodeTypeRepresentationStrategy {
|
||||
|
||||
public static final String INDEX_NAME = "__types__";
|
||||
public static final String TYPE_PROPERTY_NAME = "__type__";
|
||||
public static final String INDEX_KEY = "className";
|
||||
private final GraphDatabase graphDb;
|
||||
private final EntityTypeCache typeCache;
|
||||
|
||||
private final IndexProvider indexProvider;
|
||||
|
||||
public IndexingNodeTypeRepresentationStrategy(GraphDatabase graphDb, IndexProvider indexProvider) {
|
||||
this.graphDb = graphDb;
|
||||
this.indexProvider = indexProvider;
|
||||
typeCache = new EntityTypeCache();
|
||||
}
|
||||
|
||||
private Index<Node> getNodeTypesIndex() {
|
||||
return graphDb.createIndex(Node.class, INDEX_NAME, IndexType.SIMPLE);
|
||||
super(graphDb, indexProvider, INDEX_NAME, Node.class, NodeEntity.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postEntityCreation(Node state, Class<?> type) {
|
||||
addToNodeTypesIndex(state, type);
|
||||
state.setProperty(TYPE_PROPERTY_NAME, type.getName());
|
||||
}
|
||||
|
||||
private void addToNodeTypesIndex(Node node, Class<?> entityClass) {
|
||||
protected void addToTypesIndex(Node node, Class<?> entityClass) {
|
||||
Class<?> klass = entityClass;
|
||||
|
||||
while (klass.getAnnotation(NodeEntity.class) != null) {
|
||||
String value = klass.getName();
|
||||
if (indexProvider != null)
|
||||
value = indexProvider.createIndexValueForType(klass);
|
||||
|
||||
getNodeTypesIndex().add(node, INDEX_KEY, value);
|
||||
getTypesIndex().add(node, INDEX_KEY, value);
|
||||
klass = klass.getSuperclass();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <U> ClosableIterable<Node> findAll(Class<U> clazz) {
|
||||
return findAllNodeBacked(clazz);
|
||||
}
|
||||
|
||||
private <Object> ClosableIterable<Node> findAllNodeBacked(Class<Object> clazz) {
|
||||
String value = clazz.getName();
|
||||
if (indexProvider != null)
|
||||
value = indexProvider.createIndexValueForType(clazz);
|
||||
|
||||
final IndexHits<Node> allEntitiesOfType = getNodeTypesIndex().get(INDEX_KEY, value);
|
||||
return new ClosableIndexHits<Node>(allEntitiesOfType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long count(Class<?> entityClass) {
|
||||
long count = 0;
|
||||
for (Object o : getNodeTypesIndex().get(INDEX_KEY, entityClass.getName())) {
|
||||
count += 1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Class<?> getJavaType(Node node) {
|
||||
if (node == null) throw new IllegalArgumentException("Node is null");
|
||||
String className = (String) node.getProperty(TYPE_PROPERTY_NAME);
|
||||
return typeCache.getClassForName(className);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preEntityRemoval(Node state) {
|
||||
getNodeTypesIndex().remove(state);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -17,92 +17,18 @@
|
||||
package org.springframework.data.neo4j.support.typerepresentation;
|
||||
|
||||
import org.neo4j.graphdb.Relationship;
|
||||
import org.neo4j.graphdb.index.Index;
|
||||
import org.neo4j.graphdb.index.IndexHits;
|
||||
import org.neo4j.helpers.collection.ClosableIterable;
|
||||
import org.springframework.data.neo4j.annotation.RelationshipEntity;
|
||||
import org.springframework.data.neo4j.core.GraphDatabase;
|
||||
import org.springframework.data.neo4j.core.RelationshipTypeRepresentationStrategy;
|
||||
import org.springframework.data.neo4j.support.index.ClosableIndexHits;
|
||||
import org.springframework.data.neo4j.support.index.IndexProvider;
|
||||
import org.springframework.data.neo4j.support.index.IndexType;
|
||||
|
||||
public class IndexingRelationshipTypeRepresentationStrategy implements RelationshipTypeRepresentationStrategy {
|
||||
public class IndexingRelationshipTypeRepresentationStrategy extends
|
||||
AbstractIndexingTypeRepresentationStrategy<Relationship> implements RelationshipTypeRepresentationStrategy {
|
||||
|
||||
public static final String INDEX_NAME = "__rel_types__";
|
||||
public static final String TYPE_PROPERTY_NAME = "__type__";
|
||||
public static final String INDEX_KEY = "className";
|
||||
private final GraphDatabase graphDb;
|
||||
private final EntityTypeCache typeCache;
|
||||
|
||||
private final IndexProvider indexProvider;
|
||||
|
||||
public IndexingRelationshipTypeRepresentationStrategy(GraphDatabase graphDb, IndexProvider indexProvider) {
|
||||
this.graphDb = graphDb;
|
||||
this.indexProvider = indexProvider;
|
||||
typeCache = new EntityTypeCache();
|
||||
}
|
||||
|
||||
private Index<Relationship> getRelTypesIndex() {
|
||||
return graphDb.createIndex(Relationship.class,INDEX_NAME, IndexType.SIMPLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postEntityCreation(Relationship state, Class<?> type) {
|
||||
addToTypesIndex(state, type);
|
||||
state.setProperty(TYPE_PROPERTY_NAME, type.getName());
|
||||
}
|
||||
|
||||
private void addToTypesIndex(Relationship node, Class<?> entityClass) {
|
||||
Class<?> type = entityClass;
|
||||
while (type.getAnnotation(RelationshipEntity.class) != null) {
|
||||
String value = entityClass.getName();
|
||||
if (indexProvider != null)
|
||||
value = indexProvider.createIndexValueForType(entityClass);
|
||||
|
||||
getRelTypesIndex().add(node, INDEX_KEY, value);
|
||||
type = type.getSuperclass();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <U> ClosableIterable<Relationship> findAll(Class<U> clazz) {
|
||||
return findAllRelBacked(clazz);
|
||||
}
|
||||
|
||||
private <Object> ClosableIterable<Relationship> findAllRelBacked(Class<Object> clazz) {
|
||||
String value = clazz.getName();
|
||||
if (indexProvider != null)
|
||||
value = indexProvider.createIndexValueForType(clazz);
|
||||
|
||||
final IndexHits<Relationship> allEntitiesOfType = getRelTypesIndex().get(INDEX_KEY, value);
|
||||
return new ClosableIndexHits<Relationship>(allEntitiesOfType);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long count(Class<?> entityClass) {
|
||||
long count = 0;
|
||||
final IndexHits<Relationship> hits = getRelTypesIndex().get(INDEX_KEY, entityClass.getName());
|
||||
while (hits.hasNext()) {
|
||||
hits.next();
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<?> getJavaType(Relationship relationship) {
|
||||
if (relationship == null) throw new IllegalArgumentException("Relationship is null");
|
||||
String className = (String) relationship.getProperty(TYPE_PROPERTY_NAME);
|
||||
return typeCache.getClassForName(className);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void preEntityRemoval(Relationship state) {
|
||||
getRelTypesIndex().remove(state);
|
||||
super(graphDb, indexProvider, INDEX_NAME, Relationship.class, RelationshipEntity.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -268,4 +268,6 @@ public interface Neo4jOperations {
|
||||
MappingPolicy getMappingPolicy(Class<?> targetType);
|
||||
|
||||
ResultConverter getDefaultConverter();
|
||||
|
||||
Class getStoredJavaType(Object entity);
|
||||
}
|
||||
|
||||
@@ -18,9 +18,11 @@ package org.springframework.data.neo4j.transaction;
|
||||
|
||||
import org.neo4j.helpers.Service;
|
||||
import org.neo4j.kernel.impl.core.KernelPanicEventGenerator;
|
||||
import org.neo4j.kernel.impl.nioneo.store.FileSystemAbstraction;
|
||||
import org.neo4j.kernel.impl.transaction.AbstractTransactionManager;
|
||||
import org.neo4j.kernel.impl.transaction.TransactionManagerProvider;
|
||||
import org.neo4j.kernel.impl.transaction.TxHook;
|
||||
import org.neo4j.kernel.impl.util.StringLogger;
|
||||
import org.springframework.beans.factory.annotation.Configurable;
|
||||
|
||||
@Configurable
|
||||
@@ -33,7 +35,7 @@ public class SpringProvider extends TransactionManagerProvider
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractTransactionManager loadTransactionManager(String s, KernelPanicEventGenerator kernelPanicEventGenerator, TxHook txHook) {
|
||||
protected AbstractTransactionManager loadTransactionManager(String s, KernelPanicEventGenerator kernelPanicEventGenerator, TxHook txHook, StringLogger stringLogger, FileSystemAbstraction fileSystemAbstraction) {
|
||||
return new SpringServiceImpl();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ public class DataGraphNamespaceHandlerTest {
|
||||
Neo4jTemplate template = config.neo4jTemplate;
|
||||
Assert.assertNotNull("template", template);
|
||||
AbstractGraphDatabase graphDatabaseService = (AbstractGraphDatabase) template.getGraphDatabaseService();
|
||||
Assert.assertEquals("store-dir", "target/config-test", graphDatabaseService.getStoreDir());
|
||||
Assert.assertTrue("store-dir", graphDatabaseService.getStoreDir().endsWith("target/config-test"));
|
||||
Assert.assertNotNull("graphDatabaseService",config.graphDatabaseService);
|
||||
Assert.assertNotNull("transactionManager",config.transactionManager);
|
||||
config.graphDatabaseService.shutdown();
|
||||
|
||||
@@ -17,7 +17,9 @@ package org.springframework.data.neo4j.mapping;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.neo4j.model.Person;
|
||||
import org.springframework.data.neo4j.model.PrimitiveIdEntity;
|
||||
import org.springframework.data.neo4j.support.index.IndexType;
|
||||
import org.springframework.data.neo4j.support.mapping.Neo4jMappingContext;
|
||||
import org.springframework.data.neo4j.support.mapping.Neo4jPersistentEntityImpl;
|
||||
@@ -54,4 +56,9 @@ public class Neo4jMappingContextTest {
|
||||
assertEquals(IndexType.SIMPLE,nameProperty.getIndexInfo().getIndexType());
|
||||
assertEquals(false,nameProperty.isRelationship());
|
||||
}
|
||||
|
||||
@Test(expected = MappingException.class)
|
||||
public void testPrimitiveGraphIdFails() {
|
||||
mappingContext.getPersistentEntity(PrimitiveIdEntity.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.springframework.data.neo4j.annotation.NodeEntity;
|
||||
@NodeEntity
|
||||
public abstract class Car {
|
||||
@GraphId
|
||||
long id;
|
||||
Long id;
|
||||
public Car() {
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@NodeEntity
|
||||
public class Group {
|
||||
public class Group implements IGroup {
|
||||
|
||||
public final static String OTHER_NAME_INDEX = "other_name";
|
||||
public static final String SEARCH_GROUPS_INDEX = "search_groups";
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.model;
|
||||
|
||||
/**
|
||||
* @author mh
|
||||
* @since 23.12.11
|
||||
*/
|
||||
public interface IGroup {
|
||||
}
|
||||
@@ -16,8 +16,7 @@
|
||||
|
||||
package org.springframework.data.neo4j.model;
|
||||
|
||||
import org.neo4j.graphdb.Direction;
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.*;
|
||||
import org.springframework.data.neo4j.annotation.*;
|
||||
import org.springframework.data.neo4j.fieldaccess.DynamicProperties;
|
||||
import org.springframework.data.neo4j.support.index.IndexType;
|
||||
@@ -27,12 +26,14 @@ import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
@NodeEntity
|
||||
public class Person {
|
||||
|
||||
public static final String NAME_INDEX = "name_index";
|
||||
public static final org.neo4j.graphdb.RelationshipType KNOWS = DynamicRelationshipType.withName("knows");
|
||||
@GraphId
|
||||
private Long graphId;
|
||||
|
||||
@@ -86,9 +87,26 @@ public class Person {
|
||||
@Query("start person=node({self}) match (person)<-[:persons]-(team)-[:persons]->(member) return member")
|
||||
private Iterable<Person> otherTeamMembers;
|
||||
|
||||
@Query("start person=node({self}) match (person)<-[:persons]-(team)-[:persons]->(member) return member.name, member.age")
|
||||
@Query("start person=node({self}) match (person)<-[:persons]-(team)-[:persons]->(member) return member.name?, member.age?")
|
||||
private Iterable<Map<String,Object>> otherTeamMemberData;
|
||||
|
||||
@RelatedTo(elementClass = Group.class, type = "interface_test", direction = Direction.OUTGOING)
|
||||
private Set<IGroup> groups;
|
||||
|
||||
RootEntity root;
|
||||
|
||||
public RootEntity getRoot() {
|
||||
return root;
|
||||
}
|
||||
|
||||
public void setRoot(RootEntity root) {
|
||||
this.root = root;
|
||||
}
|
||||
|
||||
public Set<IGroup> getGroups() {
|
||||
return groups;
|
||||
}
|
||||
|
||||
public Person(Node n) {
|
||||
this.graphId = n.getId();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.model;
|
||||
|
||||
import org.springframework.data.neo4j.annotation.GraphId;
|
||||
import org.springframework.data.neo4j.annotation.NodeEntity;
|
||||
|
||||
/**
|
||||
* @author mh
|
||||
* @since 14.12.11
|
||||
*/
|
||||
@NodeEntity
|
||||
public class PrimitiveIdEntity {
|
||||
@GraphId long id;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.model;
|
||||
|
||||
import org.springframework.data.neo4j.annotation.GraphId;
|
||||
import org.springframework.data.neo4j.annotation.NodeEntity;
|
||||
|
||||
/**
|
||||
* @author mh
|
||||
* @since 23.12.11
|
||||
*/
|
||||
@NodeEntity
|
||||
public class RootEntity {
|
||||
@GraphId Long id;
|
||||
|
||||
String rootName;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getRootName() {
|
||||
return rootName;
|
||||
}
|
||||
|
||||
public void setRootName(String rootName) {
|
||||
this.rootName = rootName;
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.helpers.collection.IteratorUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -30,6 +31,7 @@ import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.neo4j.model.Friendship;
|
||||
import org.springframework.data.neo4j.model.Group;
|
||||
import org.springframework.data.neo4j.model.Person;
|
||||
import org.springframework.data.neo4j.model.RootEntity;
|
||||
import org.springframework.data.neo4j.support.Neo4jTemplate;
|
||||
import org.springframework.data.neo4j.support.conversion.NoSuchColumnFoundException;
|
||||
import org.springframework.data.neo4j.support.node.Neo4jHelper;
|
||||
@@ -46,12 +48,14 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.internal.matchers.IsCollectionContaining.hasItem;
|
||||
import static org.junit.internal.matchers.IsCollectionContaining.hasItems;
|
||||
import static org.neo4j.helpers.collection.IteratorUtil.addToCollection;
|
||||
@@ -143,7 +147,7 @@ public class GraphRepositoryTest {
|
||||
assertThat( asCollection( teamMembers ), hasItems( testTeam.michael, testTeam.david, testTeam.emil ) );
|
||||
}
|
||||
|
||||
@Test @Transactional
|
||||
@Test @Transactional
|
||||
public void testFindIterableOfPersonWithQueryAnnotationSpatial() {
|
||||
Iterable<Person> teamMembers = personRepository.findWithinBoundingBox("personLayer", 55, 15, 57, 17);
|
||||
assertThat(asCollection(teamMembers), hasItems(testTeam.michael, testTeam.david));
|
||||
@@ -192,7 +196,7 @@ public class GraphRepositoryTest {
|
||||
|
||||
@Test @Transactional
|
||||
public void testFindPaged() {
|
||||
final PageRequest page = new PageRequest(0, 1, Sort.Direction.ASC, "member.name");
|
||||
final PageRequest page = new PageRequest(0, 1, Sort.Direction.ASC, "member.name","member.age");
|
||||
Page<Person> teamMemberPage1 = personRepository.findAllTeamMembersPaged(testTeam.sdg, page);
|
||||
assertThat(teamMemberPage1, hasItem(testTeam.david));
|
||||
}
|
||||
@@ -220,9 +224,27 @@ public class GraphRepositoryTest {
|
||||
assertEquals(asList(testTeam.michael, testTeam.emil, testTeam.david), asCollection(teamMembers));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testGetStoredJavaType() {
|
||||
Person p = personRepository.save(new Person());
|
||||
assertEquals(Person.class, personRepository.getStoredJavaType(p));
|
||||
assertEquals(Person.class, personRepository.getStoredJavaType(neo4jTemplate.getPersistentState(p)));
|
||||
assertEquals(null, personRepository.getStoredJavaType(new Person()));
|
||||
}
|
||||
@Test
|
||||
@Transactional
|
||||
public void testTemplateGetStoredJavaType() {
|
||||
Person p = neo4jTemplate.save(new Person());
|
||||
assertEquals(Person.class, neo4jTemplate.getStoredJavaType(p));
|
||||
assertEquals(Person.class, neo4jTemplate.getStoredJavaType(neo4jTemplate.getPersistentState(p)));
|
||||
assertEquals(null, neo4jTemplate.getStoredJavaType(new Person()));
|
||||
}
|
||||
|
||||
|
||||
@Test @Transactional
|
||||
public void testFindSortedNull() {
|
||||
Iterable<Person> teamMembers = personRepository.findAllTeamMembersSorted(testTeam.sdg, null);
|
||||
Collection<Person> teamMembers = IteratorUtil.asCollection(personRepository.findAllTeamMembersSorted(testTeam.sdg, null));
|
||||
assertThat(teamMembers, hasItems(testTeam.michael, testTeam.emil, testTeam.david));
|
||||
}
|
||||
|
||||
@@ -264,4 +286,38 @@ public class GraphRepositoryTest {
|
||||
assertEquals(2, IteratorUtil.count(loaded.getFriendships()));
|
||||
assertThat(loaded.getFriendships(),hasItem(friendship));
|
||||
}
|
||||
|
||||
@Test @Transactional
|
||||
public void testCreateDuplicateRelationship() {
|
||||
assertEquals(1, IteratorUtil.count(neo4jTemplate.<Node>getPersistentState(testTeam.michael).getRelationships(Person.KNOWS)));
|
||||
personRepository.createDuplicateRelationshipBetween(testTeam.michael, testTeam.david, Friendship.class, "knows");
|
||||
assertEquals(2, IteratorUtil.count(neo4jTemplate.<Node>getPersistentState(testTeam.michael).getRelationships(Person.KNOWS)));
|
||||
}
|
||||
|
||||
@Test @Transactional
|
||||
public void testUseInterfaceInRelationships() {
|
||||
final Person p = neo4jTemplate.save(new Person());
|
||||
final Group group = neo4jTemplate.save(new Group());
|
||||
neo4jTemplate.createRelationshipBetween(neo4jTemplate.<Node>getPersistentState(p),neo4jTemplate.<Node>getPersistentState(group),"interface_test",null);
|
||||
final Person p2 = neo4jTemplate.fetch(p);
|
||||
assertEquals(group,IteratorUtil.firstOrNull(p2.getGroups()));
|
||||
}
|
||||
|
||||
@Test @Transactional
|
||||
public void testConnectToRootEntity() {
|
||||
final Node referenceNode = neo4jTemplate.getReferenceNode();
|
||||
neo4jTemplate.postEntityCreation(referenceNode,RootEntity.class);
|
||||
final RootEntity root = neo4jTemplate.findOne(referenceNode.getId(), RootEntity.class);
|
||||
root.setRootName("RootName");
|
||||
neo4jTemplate.save(root);
|
||||
assertEquals(referenceNode.getId(), (long) root.getId());
|
||||
assertEquals("RootName", referenceNode.getProperty("rootName"));
|
||||
assertEquals("RootName", root.getRootName());
|
||||
|
||||
final Person person = new Person();
|
||||
person.setRoot(root);
|
||||
neo4jTemplate.save(person);
|
||||
final Person p2 = neo4jTemplate.findOne(person.getId(), Person.class);
|
||||
assertEquals(root.getId(),p2.getRoot().getId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ import java.util.Map;
|
||||
* @author Oliver Gierke
|
||||
* @since 29.03.11
|
||||
*/
|
||||
public interface PersonRepository extends GraphRepository<Person>, NamedIndexRepository<Person>, SpatialRepository<Person>, PersonRepositoryFriendship, CypherDslRepository<Person> {
|
||||
public interface PersonRepository extends GraphRepository<Person>, NamedIndexRepository<Person>, SpatialRepository<Person>, PersonRepositoryFriendship, CypherDslRepository<Person>, RelationshipOperationsRepository<Person> {
|
||||
|
||||
@Query("start team=node({p_team}) match (team)-[:persons]->(member) return member")
|
||||
Iterable<Person> findAllTeamMembers(@Param("p_team") Group team);
|
||||
|
||||
@@ -17,11 +17,13 @@ package org.springframework.data.neo4j.support;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.internal.matchers.IsCollectionContaining;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
import org.neo4j.graphdb.*;
|
||||
import org.neo4j.graphdb.index.Index;
|
||||
import org.neo4j.graphdb.traversal.TraversalDescription;
|
||||
import org.neo4j.helpers.collection.IteratorUtil;
|
||||
import org.neo4j.helpers.collection.MapUtil;
|
||||
import org.neo4j.kernel.Traversal;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -45,9 +47,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.neo4j.graphdb.Direction.OUTGOING;
|
||||
@@ -306,7 +306,11 @@ public class EntityNeo4jTemplateTest extends EntityTestBase {
|
||||
public void testCreateRelationshipBetweenNodes() throws Exception {
|
||||
final Friendship friendship = neo4jOperations.createRelationshipBetween(testTeam.david, testTeam.emil, Friendship.class, "knows", false);
|
||||
assertEquals(friendship.getId(),(Long)getNodeState(testTeam.david).getSingleRelationship(KNOWS, OUTGOING).getId());
|
||||
final List<Friendship> friendships = IteratorUtil.addToCollection(friendshipRepository.findAll(), new ArrayList<Friendship>());
|
||||
assertEquals(2,friendships.size());
|
||||
assertThat(friendships, IsCollectionContaining.hasItems(testTeam.friendShip, friendship));
|
||||
}
|
||||
|
||||
@Test @Transactional
|
||||
public void testCreateDuplicateRelationshipBetweenNodes() throws Exception {
|
||||
neo4jOperations.createRelationshipBetween(testTeam.michael, testTeam.david, Friendship.class, "knows", true);
|
||||
|
||||
@@ -29,10 +29,6 @@
|
||||
<firstname>Michael</firstname>
|
||||
<surname>Hunger</surname>
|
||||
</author>
|
||||
<author>
|
||||
<firstname>David</firstname>
|
||||
<surname>Montag</surname>
|
||||
</author>
|
||||
</authorgroup>
|
||||
|
||||
<legalnotice>
|
||||
@@ -134,6 +130,7 @@
|
||||
<xi:include href="reference/setup.xml"/>
|
||||
<xi:include href="reference/cross-store.xml"/>
|
||||
<xi:include href="reference/samples.xml"/>
|
||||
<xi:include href="reference/heroku.xml"/>
|
||||
<xi:include href="reference/performance.xml" />
|
||||
<xi:include href="reference/aspectj-details.xml" />
|
||||
<xi:include href="reference/neo4j-server.xml" />
|
||||
|
||||
@@ -59,6 +59,10 @@
|
||||
advanced AspectJ usage which caused some headaches. He always quickly solved our issues and gave us excellent
|
||||
answers.
|
||||
</para>
|
||||
<para>
|
||||
Many thanks to our colleagues David Montag, Andreas Kollegger and Rickard Öberg who not only contributed to
|
||||
Spring Data Neo4j but also provided content and feedback for this book.
|
||||
</para>
|
||||
<para>
|
||||
We also appreciate very much the foresight of Rod Johnson and Emil Eifrem to initiate the project, and now
|
||||
also providing great forewords. Their leadership inspired collaboration between the engineering teams at
|
||||
|
||||
BIN
src/docbkx/reference/attachdetach.key
Normal file
235
src/docbkx/reference/heroku.xml
Normal file
@@ -0,0 +1,235 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
|
||||
<chapter id="reference:heroku">
|
||||
<title>Heroku: Seeding the Cloud</title>
|
||||
<para>
|
||||
Deploying your application into the cloud is a great way to scale from from "wouldn't it be cool if.." to
|
||||
giving interviews to Forbes, Fast Company, and Jimmy Fallon. Heroku makes it super easy to provision everying
|
||||
you need, including a Neo4j Add-on. With a few simple adjustments, your Spring Data Neo4j application is
|
||||
ready to take that first step into the cloud.
|
||||
</para>
|
||||
<para>
|
||||
To deploy your Spring Data Neo4j web application to Heroku, you'll need:
|
||||
</para>
|
||||
<itemizedlist mark="circle">
|
||||
<listitem><para>account on <ulink url="http://heroku.com">Heroku</ulink></para></listitem>
|
||||
<listitem><para>git command line</para></listitem>
|
||||
<listitem><para>maven-based project</para></listitem>
|
||||
<listitem><para>standard Spring MV Servlet application</para></listitem>
|
||||
<listitem><para>well, and Spring Data Neo4j REST</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>
|
||||
For reference, the following sections detail the steps taken to make the Spring Data Neo4j Todos
|
||||
example ready for deployment to Heroku.
|
||||
</para>
|
||||
|
||||
<section>
|
||||
<title>Create a Self-Hosted Web Application</title>
|
||||
<para>
|
||||
Usually, a Spring MVC application is bundled into a war and deployed to an application server
|
||||
like Tomcat. But Heroku can host any kind of java application. It just needs to know what to
|
||||
launch. So, we'll transform the war into a self-hosted servlet using an embedded Jetty server,
|
||||
then add a startup script to launch it.
|
||||
</para>
|
||||
<para>
|
||||
First, we'll add the dependencies for Jetty to the <code>pom.xml</code>:
|
||||
</para>
|
||||
<example>
|
||||
<title>Jetty dependencies - pom.xml</title>
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-webapp</artifactId>
|
||||
<version>7.4.4.v20110707</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mortbay.jetty</groupId>
|
||||
<artifactId>jsp-2.1-glassfish</artifactId>
|
||||
<version>2.1.v20100127</version>
|
||||
</dependency>
|
||||
]]></programlisting>
|
||||
</example>
|
||||
<para>
|
||||
Then we'll change the scope of the servlet-api artifact from <code>provided</code> to <code>compile</code>.
|
||||
This library is normally provided at runtime by the application container. Since we're self-hosting,
|
||||
it needs to be included directly. Make sure the servlet-api dependency looks like this:
|
||||
</para>
|
||||
<example>
|
||||
<title>servlet-api dependencies - pom.xml</title>
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<version>2.5</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
]]></programlisting>
|
||||
</example>
|
||||
<para>
|
||||
We could provide a complicated command-line to Heroku to launch the app. Instead, we'll simplify
|
||||
the command-line by using the <code>appassembler-maven-plugin</code> to create a launch script. Add the plugin
|
||||
to your pom's <code>build/plugins</code> section:
|
||||
</para>
|
||||
<example>
|
||||
<title>appassembler-maven-plugin configuration pom.xml</title>
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>appassembler-maven-plugin</artifactId>
|
||||
<version>1.1.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals><goal>assemble</goal></goals>
|
||||
<configuration>
|
||||
<assembleDirectory>target</assembleDirectory>
|
||||
<extraJvmArguments>-Xmx512m</extraJvmArguments>
|
||||
<programs>
|
||||
<program>
|
||||
<mainClass>Main</mainClass>
|
||||
<name>webapp</name>
|
||||
</program>
|
||||
</programs>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
]]></programlisting>
|
||||
</example>
|
||||
<para>
|
||||
Finally, switch the packaging from <code>war</code> to <code>jar</code>. That's it for the pom.
|
||||
</para>
|
||||
<para>
|
||||
Now that the application is ready to be self-hosted, create a simple <code>Main</code> to
|
||||
bootstrap Jetty and host the servlet.
|
||||
</para>
|
||||
<example>
|
||||
<title>src/main/java/Main.java</title>
|
||||
<programlisting language="java"><![CDATA[
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
public class Main {
|
||||
public static void main(String[] args) throws Exception {
|
||||
String webappDirLocation = "src/main/webapp/";
|
||||
String webPort = System.getenv("PORT");
|
||||
if(webPort == null || webPort.isEmpty()) {
|
||||
webPort = "8080";
|
||||
}
|
||||
Server server = new Server(Integer.valueOf(webPort));
|
||||
WebAppContext root = new WebAppContext();
|
||||
root.setContextPath("/");
|
||||
root.setDescriptor(webappDirLocation+"/WEB-INF/web.xml");
|
||||
root.setResourceBase(webappDirLocation);
|
||||
root.setParentLoaderPriority(true);
|
||||
server.setHandler(root);
|
||||
server.start();
|
||||
server.join();
|
||||
}
|
||||
}
|
||||
]]></programlisting>
|
||||
</example>
|
||||
<para>
|
||||
Notice the use of environment variable "PORT" for discovering which port to use. Heroku and the
|
||||
Neo4j Add-on use a number of environment variable to configure the application. Next, we'll
|
||||
modify the Spring application context to use the Neo4j variables for specifying the connection
|
||||
to Neo4j itself.
|
||||
</para>
|
||||
<para>
|
||||
In the SDN Todos example, <code>src/main/resources/META-INF/spring/ applicationContext-graph.xml</code>
|
||||
was modified to look like this:
|
||||
</para>
|
||||
<example>
|
||||
<title>Spring Data Neo4j REST configuration - applicationContext-graph.xml</title>
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<neo4j:config graphDatabaseService="graphDatabaseService"/>
|
||||
<bean id="graphDatabaseService"
|
||||
class="org.springframework.data.neo4j.rest.SpringRestGraphDatabase">
|
||||
<constructor-arg index="0" value="${NEO4J_REST_URL}" />
|
||||
<constructor-arg index="1" value="${NEO4J_LOGIN}" />
|
||||
<constructor-arg index="2" value="${NEO4J_PASSWORD}" />
|
||||
</bean>
|
||||
]]></programlisting>
|
||||
</example>
|
||||
<para>
|
||||
Before provisioning at Heroku, test the application locally. First make sure you've got
|
||||
Neo4j server running locally, using default configuration. Then set the following
|
||||
environment variables:
|
||||
</para>
|
||||
<example>
|
||||
<title>environment variables</title>
|
||||
<programlisting><![CDATA[
|
||||
export NEO4J_REST_URL=http://localhost:7474/db/data
|
||||
export NEO4J_LOGIN=""
|
||||
export NEO4J_PASSWORD=""
|
||||
]]></programlisting>
|
||||
</example>
|
||||
<para>
|
||||
Now you can launch the app by running <code>sh target/bin/webapp</code>. If running the SDN Todos
|
||||
example, you can test it by running <code>./bin/todos list</code>. That should return an empty
|
||||
JSON array, since no todos have been created yet.
|
||||
</para>
|
||||
<para>
|
||||
For details about the <code>todos</code> script, see the <code>readme</code> included with the example.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Deploy to Heroku</title>
|
||||
<para>
|
||||
With a self-hosted application ready, deploying to Heroku needs a few more steps. First,
|
||||
create a <code>Procfile</code> at the top-level of the project, which will contain a single
|
||||
line identifying the command line which launches the application.
|
||||
</para>
|
||||
<para>
|
||||
The contents of the <code>Procfile</code> should contain:
|
||||
</para>
|
||||
<example>
|
||||
<title>Procfile</title>
|
||||
<programlisting><![CDATA[
|
||||
web: sh target/bin/webapp
|
||||
]]></programlisting>
|
||||
</example>
|
||||
<para>
|
||||
|
||||
<example>
|
||||
<title>deploy to heroku</title>
|
||||
<programlisting><![CDATA[
|
||||
# Initialize a local git repository, adding all the project files
|
||||
git init
|
||||
git add .
|
||||
git commit -m "initial commit"
|
||||
|
||||
# Provision a Heroku stack, add the Neo4j Add-on and deploy the appication
|
||||
|
||||
heroku create --stack cedar
|
||||
heroku addons:add neo4j
|
||||
git push heroku master
|
||||
|
||||
]]></programlisting>
|
||||
</example>
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
Note that the stack must be "cedar" to support running Java. Check that the process
|
||||
is running by using <code>heroku ps</code>, which should show a "web.1" process
|
||||
in the "up" state. Success!
|
||||
</para>
|
||||
</note>
|
||||
<para>
|
||||
For the SDN Todos application, you can try out the remote application using the <code>-r</code>
|
||||
switch with the <code>bin/todo</code> script like this:
|
||||
</para>
|
||||
<example>
|
||||
<title>Session with todo script</title>
|
||||
<programlisting><![CDATA[
|
||||
./bin/todo -r mk "tweet thanks for the good work @mesirii @akollegger"
|
||||
./bin/todo -r list
|
||||
]]></programlisting>
|
||||
</example>
|
||||
<para>
|
||||
To see the Neo4j graph you just created through Heroku, use <code>heroku config</code> to reveal
|
||||
the <code>NEO4J_URL</code> environment variable, which will take you to Neo4j's Webadmin.
|
||||
</para>
|
||||
</section>
|
||||
</chapter>
|
||||
@@ -66,7 +66,7 @@ public void foo( @Context WorldRepository repo ) {
|
||||
}
|
||||
]]></programlisting>
|
||||
</example>
|
||||
The <code>SpringPluginInitializer</code> merges the GraphDatabaseService with the Spring configuration
|
||||
The <code>SpringPluginInitializer</code> merges the server provided <code>GraphDatabaseService</code> with the Spring configuration
|
||||
and registers the named beans as Jersey <code>Injectables</code>. It is still necessary to list the
|
||||
initializer's fully qualified class name in a file named
|
||||
<code>META-INF/services/org.neo4j.server.plugins.PluginLifecycle</code>. The Neo4j Server can then pick
|
||||
@@ -76,21 +76,27 @@ public void foo( @Context WorldRepository repo ) {
|
||||
<section>
|
||||
<title>Using Spring Data Neo4j as a REST client</title>
|
||||
<para>
|
||||
Spring Data Neo4j can use a set of Java REST bindings which come as a drop in replacement for the
|
||||
GraphDatabaseService API. By simply configuring the <code>graphDatabaseService</code> to be a
|
||||
<code>RestGraphDatabase</code> pointing to a Neo4j Server instance.
|
||||
To use REST-API the Neo4j Server exposes, one would either go with REST libraries on the lower level or choose one of the Neo4j related
|
||||
rest drivers in various languages. For Java Neo4j provides the <ulink url="https://github.com/neo4j/java-rest-binding">Neo4j Java REST bindings</ulink>
|
||||
which come as a drop in replacement for the <code>GraphDatabaseService</code> API. Spring Data Neo4j REST uses those bindings to provide seamless
|
||||
access to a remote Neo4j Database.
|
||||
</para>
|
||||
<para>
|
||||
By simply configuring the <code>graphDatabaseService</code> to be a <code>SpringRestGraphDatabase</code> pointing to a Neo4j Server instance and
|
||||
referring to that from <code><neo4j:config></code> Spring Data Neo4j will use the server side database for both the simple mapping as
|
||||
well as the advanced mapping.
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
The Neo4j Server REST API does not allow for transactions to span across requests, which means
|
||||
that Spring Data Neo4j is not transactional when running with a <code>RestGraphDatabase</code>.
|
||||
that Spring Data Neo4j is not transactional across multiple operations when running with a <code>SpringRestGraphDatabase</code>.
|
||||
</para>
|
||||
</note>
|
||||
<para>
|
||||
Please also keep in mind that performing graph operations via the REST-API is about one order of
|
||||
magnitude slower than local operations. Try to use the Neo4j Cypher query language,
|
||||
server-side traversals (<code>RestTraversal</code>) or Gremlin expressions whenever possible for retrieving large sets of data.
|
||||
Future versions of Spring Data Neo4j will use the more performant batching as well as a binary protocol.
|
||||
Future versions of Spring Data Neo4j will use the more performant batch API as well as a binary protocol.
|
||||
</para>
|
||||
<para>
|
||||
To set up your project to use the REST bindings, add this dependency to your pom.xml:
|
||||
@@ -100,7 +106,7 @@ public void foo( @Context WorldRepository repo ) {
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-neo4j-rest</artifactId>
|
||||
<version>2.0.0.RC1</version>
|
||||
<version>2.0.0.RELEASE</version>
|
||||
</dependency>
|
||||
]]></programlisting>
|
||||
</example>
|
||||
@@ -111,18 +117,22 @@ public void foo( @Context WorldRepository repo ) {
|
||||
<programlisting language="xml"><![CDATA[<neo4j:config graphDatabaseService="graphDatabaseService"/>
|
||||
|
||||
<bean id="graphDatabaseService" class="org.springframework.data.neo4j.rest.SpringRestGraphDatabase">
|
||||
<constructor-arg value="http://localhost:7474/db/data/"/>
|
||||
<constructor-arg value="http://localhost:7474/db/data/" index="0"/>
|
||||
<!-- for running against a server requiring authentication
|
||||
<constructor-arg value="username" index="1"/>
|
||||
<constructor-arg value="password" index="2"/>
|
||||
-->
|
||||
</bean>
|
||||
]]></programlisting>
|
||||
</example>
|
||||
Your project is now set up to work against a remote Neo4j Server.
|
||||
</para>
|
||||
<para>
|
||||
The remote REST implementation works for both the Neo4jTemplate as well as the GraphEntities. For traversals
|
||||
and Cypher graph queries it is sensible to forward those to the remote endpoint and execute them there instead of
|
||||
walking the graph over the wire. RestGraphDatabase already supports that by providing methods that forward
|
||||
For traversals and Cypher and Gremlin graph queries it is sensible to forward those to the remote endpoint and execute them there
|
||||
instead of walking the graph over the wire. SpringRestGraphDatabase already supports that by providing methods that forward
|
||||
to the remote instance. (e.g. <code>queryEngineFor(), index() and createTraversalDescription()</code>).
|
||||
Please use those methods when interacting with a remote server for optimal performance.
|
||||
Please use those methods when interacting with a remote server for optimal performance. Those methods are also
|
||||
used by the Neo4jTemplate and the mapping infrastructure automatically.
|
||||
</para>
|
||||
<para>
|
||||
|
||||
|
||||
@@ -160,7 +160,8 @@ for (Node foundNode : nodeIndex.get("property","value")) {
|
||||
<ulink url="http://docs.neo4j.org/chunked/milestone/cypher-query-lang.html">"Cypher"</ulink> which draws from many
|
||||
sources. It resembles SQL but with an iconic representation of patterns in the graph (concepts drawn from SPARQL).
|
||||
The Cypher execution engine was written in Scala to leverage the high expressiveness for lazy sequence operations of the language and the
|
||||
parser combinator library.
|
||||
parser combinator library. A screencast explaining the possibilities in detail can be found on the
|
||||
<ulink url="http://video.neo4j.org/ybMbf/screencast-introduction-to-cypher/">Neo4j video site</ulink>.
|
||||
</para>
|
||||
<para>
|
||||
Cypher queries always begin with a <code>start</code> set of nodes. Those can be either expressed by their
|
||||
|
||||
|
Before Width: | Height: | Size: 121 KiB After Width: | Height: | Size: 121 KiB |
@@ -155,7 +155,7 @@
|
||||
</section>
|
||||
<section>
|
||||
<title>Cypher examples</title>
|
||||
<para>There is a <ulink url="http://neo4j.vidcaster.com/U2Y/introduction-to-cypher">screencast</ulink> available showing many features of the query language.
|
||||
<para>There is a <ulink url="http://video.neo4j.org/ybMbf/screencast-introduction-to-cypher">screencast</ulink> available showing many features of the query language.
|
||||
The following examples are taken from the cineasts dataset of the tutorial section.
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
@@ -190,7 +190,7 @@
|
||||
name can be split into its semantic parts and converted into a cypher query.
|
||||
<code>@Indexed</code> fields will be converted into index-lookups of the <code>start</code> clause,
|
||||
navigation along relationships will be reflected in the <code>match</code> clause properties with operators will end up as expressions in the
|
||||
<code>where</code> clause. Order and limiting of the query will by handled by provided <code>Pageable</code> or <Sort></Sort> parameters.
|
||||
<code>where</code> clause. Order and limiting of the query will by handled by provided <code>Pageable</code> or <code>Sort</code> parameters.
|
||||
The other parameters will be used in the order they appear in the method signature so that should align with the expressions stated in the method name.
|
||||
</para>
|
||||
<para>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<para>
|
||||
The <code>Neo4jTemplate</code> offers the convenient API of Spring templates for the Neo4j graph
|
||||
database. The Spring Data Neo4j Object Graph mapping builds upon the core functionality of the
|
||||
template to persist objects to the graph and load them in a variety of ways.
|
||||
template to persist objects to the graph and load them in a variety of ways.
|
||||
The template handles the active mapping mode (<xref linkend="reference:mapping"/>) transparently.
|
||||
</para>
|
||||
<para>
|
||||
@@ -17,6 +17,24 @@
|
||||
</para>
|
||||
|
||||
<xi:include href="../../snippets/SnippetNeo4jTemplateMethods.xml"/>
|
||||
<section>
|
||||
<title>Core-Operations</title>
|
||||
<para>
|
||||
<code>Neo4jTemplate</code> provides access to some of the methods of the Neo4j-Core-API directly. So accessing
|
||||
nodes and relationships (<code>getReferenceNode, getNode, getRelationship, getRelationshipBetween</code>),
|
||||
creating nodes and relationships (<code>createNode, createNodeAs, createRelationshipBetween</code>)
|
||||
and deleting them (<code>delete, deleteRelationshipBetween</code>) are supported. It also provides access to
|
||||
the underlying GraphDatabase via <code>getGraphDatabase</code>.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Entity-Persistence</title>
|
||||
<para>
|
||||
<code>Neo4jTemplate</code> allows to <code>save</code>,<code>find(One/All)</code>,<code>count</code><code>delete</code>
|
||||
and <code>projectTo</code> entities. It provides the stored type information via <code>getStoredJavaType</code>
|
||||
and can <code>fetch</code> lazy-loaded entities or <code>load</code> them alltogether.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Result</title>
|
||||
<para>
|
||||
@@ -26,7 +44,7 @@
|
||||
<code>ResultConverter<FROM,TO></code> which takes care of custom conversions. By default most
|
||||
query methods can already handle conversions from and to: Paths, Nodes, Relationship and GraphEntities
|
||||
as well as conversions backed by registered ConversionServices. A converted <code>Result<FROM></code> is an
|
||||
<code>Iterable<TO></code>. Results can be limited to a single value using the
|
||||
<code>Iterable<TO></code>. Results can be limited to a single value using the
|
||||
<code>result.single() or result.singleOrNull()</code>
|
||||
methods. It also offers support for a pure callback function using a <code>Handler<T></code>.
|
||||
</para>
|
||||
|
||||
@@ -21,11 +21,9 @@
|
||||
</para>
|
||||
<para>
|
||||
Stores entity types in the integrated index. Each entity node gets indexed with its type and
|
||||
any supertypes that are also<code>@NodeEntity</code>-annotated. The special index used for this
|
||||
is called<code>__types__</code>. Additionally, in order to get the type of an entity node, each
|
||||
node has a property
|
||||
<code>__type__</code>
|
||||
with the fully qualified type of that entity.
|
||||
all supertypes that are also <code>@NodeEntity</code>-annotated. The special index used for this
|
||||
is named <code>__types__</code>. Additionally, in order to retrieve the type of an entity node, each
|
||||
node has a property <code>__type__</code> with the fully qualified type of that entity.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
@@ -57,6 +55,12 @@
|
||||
<para>
|
||||
<code>IndexingRelationshipTypeRepresentationStrategy</code>
|
||||
</para>
|
||||
<para>
|
||||
Stores relationship entity types in the integrated index. Each entity relationship gets indexed with its type and
|
||||
all supertypes that are also <code>@RelationshipEntity</code>-annotated. The special index used for this
|
||||
is named <code>__rel_types__</code>. Additionally, in order to retrieve the type of an entity relationship, each
|
||||
relationship has a property <code>__type__</code> with the fully qualified type of that entity.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
|
||||
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
@@ -11,7 +11,7 @@
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<!--
|
||||
http://yuml.me/diagram/scruffy;dir:lr/class/%23%20Cineasts.net%20Domain,%20%5BActor%7Cname;%7CplayedIn()%5D*-ACTS_IN-%3E%5BRole%7Cname;%5D,%20%5BRole%5D-ACTS_IN-%3E*%5BMovie%7Ctitle;year%5D,%20%5BUser%7Clogin;name;password;%7Crate();befriend();%5D*-RATED-%3E%5BRating%7Cstars;comment;%5D,%20%5BRating%5D-RATED-%3E*%5BMovie%5D,%20%5BUser%5D*-FRIEND-%3E*%5BUser%5D.png
|
||||
http://yuml.me/diagram/scruffy;dir:lr/class/%23%20Cineasts.net%20Domain,%20%5BActor%7Cname;%7CplayedIn()%5D-ACTS_IN-%3E%5BRole%7Cname;%5D,%20%5BRole%5D-ACTS_IN-%3E%5BMovie%7Ctitle;year%5D,%20%5BUser%7Clogin;name;password;%7Crate();befriend();%5D-RATED-%3E%5BRating%7Cstars;comment;%5D,%20%5BRating%5D-RATED-%3E%5BMovie%5D,%20%5BUser%5D-FRIEND-%3E%5BUser%5D.png
|
||||
-->
|
||||
<imagedata fileref="domain.png"/>
|
||||
</imageobject>
|
||||
|
||||