Added external Transaction Manager Integration (via Spring configured JtaTransactionManager)

moved TransactionManagers to transaction package
provided JotmFactory Bean for Test
removed Bundlor
This commit is contained in:
Michael Hunger
2011-02-22 15:16:15 +01:00
parent aa9c09b6b4
commit cd4a51c60f
20 changed files with 558 additions and 141 deletions

View File

@@ -85,12 +85,4 @@
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.springsource.bundlor</groupId>
<artifactId>com.springsource.bundlor.maven</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -1,19 +0,0 @@
Bundle-SymbolicName: org.springframework.data.graph
Bundle-Name: Spring Data Graph
Bundle-Vendor: SpringSource
Bundle-ManifestVersion: 2
Import-Package:
sun.reflect;version="0";resolution:=optional
Import-Template:
org.springframework.beans.*;version="[3.0.0, 4.0.0)",
org.springframework.core.*;version="[3.0.0, 4.0.0)",
org.springframework.dao.*;version="[3.0.0, 4.0.0)",
org.springframework.util.*;version="[3.0.0, 4.0.0)",
org.springframework.data.core.*;version="[1.0.0, 2.0.0)",
org.springframework.data.core.*;version="[1.0.0, 2.0.0)",
org.springframework.data.persistence.*;version="[1.0.0, 2.0.0)",
org.aopalliance.*;version="[1.0.0, 2.0.0)";resolution:=optional,
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
org.w3c.dom.*;version="0"

View File

@@ -10,14 +10,14 @@
<packaging>pom</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- versions for commonly-used dependencies -->
<junit.version>4.8.1</junit.version>
<log4j.version>1.2.15</log4j.version>
<org.mockito.version>1.8.4</org.mockito.version>
<org.slf4j.version>1.5.10</org.slf4j.version>
<org.springframework.version>3.0.5.RELEASE</org.springframework.version>
<data.commons.version>1.0.0.BUILD-SNAPSHOT</data.commons.version>
<neo4j.version>1.3.M02</neo4j.version>
<neo4j.version>1.3.M02</neo4j.version>
<aspectj.version>1.6.11.BUILD-SNAPSHOT</aspectj.version>
</properties>
<profiles>
<profile>
@@ -113,6 +113,11 @@
<artifactId>spring-tx</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
@@ -220,6 +225,17 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ow2.jotm</groupId>
<artifactId>jotm-core</artifactId>
<version>2.1.9</version>
</dependency>
<dependency>
<groupId>org.ow2.spec.ee</groupId>
<artifactId>ow2-connector-1.5-spec</artifactId>
<version>1.0-M1</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
@@ -292,6 +308,7 @@
<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>
@@ -303,6 +320,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.6</version>
<configuration>
<useFile>true</useFile>
<includes>
@@ -317,7 +335,9 @@
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.0.4</version>
<executions>
<execution>
<id>attach-sources</id>
@@ -328,43 +348,10 @@
</executions>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<!--
configures the springsource bundlor plugin, which generates
OSGI-compatible MANIFEST.MF files during the 'compile' phase of
the maven build. this plugin is declared within the
pluginManagement section because not every module that inherits
from this pom needs bundlor's services, e.g.:
spring-integration-samples and all its children. for this reason,
all modules that wish to use bundlor must declare it explicitly.
it is not necessary to specify the <version> or <configuration>
sections, but groupId and artifactId are required. see
http://static.springsource.org/s2-bundlor/1.0.x/user-guide/html/ch04s03.html
for more info
-->
<groupId>com.springsource.bundlor</groupId>
<artifactId>com.springsource.bundlor.maven</artifactId>
<version>1.0.0.RELEASE</version>
<configuration>
<failOnWarnings>true</failOnWarnings>
</configuration>
<executions>
<execution>
<id>bundlor</id>
<goals>
<goal>bundlor</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
<pluginRepositories>
<pluginRepository>
<!-- necessary for bundlor and utils -->
<!-- necessary for utils -->
<id>repository.plugin.springsource.release</id>
<name>SpringSource Maven Repository</name>
<url>http://repository.springsource.com/maven/bundles/release</url>

View File

@@ -200,10 +200,6 @@
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>com.springsource.bundlor</groupId>
<artifactId>com.springsource.bundlor.maven</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -1,26 +0,0 @@
Bundle-SymbolicName: org.springframework.data.neo4j.roo
Bundle-Name: Spring Data Neo4J Roo Support
Bundle-Vendor: SpringSource
Bundle-ManifestVersion: 2
Import-Package:
sun.reflect;version="0";resolution:=optional
Import-Template:
org.springframework.beans.*;version="[3.0.0, 4.0.0)",
org.springframework.core.*;version="[3.0.0, 4.0.0)",
org.springframework.dao.*;version="[3.0.0, 4.0.0)",
org.springframework.jdbc.*;version="[3.0.0, 4.0.0)",
org.springframework.orm.*;version="[3.0.0, 4.0.0)",
org.springframework.transaction.*;version="[3.0.0, 4.0.0)",
org.springframework.util.*;version="[3.0.0, 4.0.0)",
org.springframework.data.core.*;version="[1.0.0, 2.0.0)",
org.springframework.data.core.*;version="[1.0.0, 2.0.0)",
org.springframework.data.annotation.*;version="[1.0.0, 2.0.0)",
org.springframework.data.graph.*;version="[1.0.0, 2.0.0)",
org.springframework.persistence.*;version="[1.0.0, 2.0.0)",
org.neo4j.*;version="0",
org.aspectj.*;version="[1.6.5, 2.0.0)",
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
javax.annotation.*;version="0";resolution:=optional,
javax.persistence.*;version="[1.0.0, 3.0.0)";resolution:=optional,
javax.persistence.spi.*;version="[1.0.0, 3.0.0)";resolution:=optional,
javax.transaction.*;version="[1.0.1, 2.0.0)";resolution:=optional

View File

@@ -10,9 +10,6 @@
<artifactId>spring-data-neo4j</artifactId>
<packaging>jar</packaging>
<name>Spring Data Neo4J Support</name>
<properties>
<aspectj.version>1.6.11.BUILD-SNAPSHOT</aspectj.version>
</properties>
<dependencies>
<!-- Spring -->
@@ -27,7 +24,6 @@
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!-- Spring Data -->
@@ -44,6 +40,18 @@
<artifactId>spring-data-graph-core</artifactId>
</dependency>
<dependency>
<groupId>org.ow2.jotm</groupId>
<artifactId>jotm-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.ow2.spec.ee</groupId>
<artifactId>ow2-connector-1.5-spec</artifactId>
<scope>provided</scope>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
@@ -216,10 +224,6 @@
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>com.springsource.bundlor</groupId>
<artifactId>com.springsource.bundlor.maven</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -1,4 +1,4 @@
package org.springframework.data.graph.neo4j.support;
package org.springframework.data.graph.neo4j.transaction;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

View File

@@ -1,4 +1,4 @@
package org.springframework.data.graph.neo4j.support;
package org.springframework.data.graph.neo4j.transaction;
import org.springframework.transaction.support.TransactionSynchronizationManager;

View File

@@ -0,0 +1,171 @@
/*
* Copyright 2010 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.graph.neo4j.transaction;
import org.objectweb.jotm.Current;
import org.objectweb.jotm.Jotm;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import javax.naming.NamingException;
import javax.transaction.SystemException;
/**
* FactoryBean that retrieves the JTA UserTransaction/TransactionManager for
* ObjectWeb's <a HREF="http://jotm.objectweb.org">JOTM</a>. Will retrieve
* an already active JOTM instance if found (e.g. if running in JOnAS),
* else create a new local JOTM instance.
* <p/>
* <p>With JOTM, the same object implements both the
* {@link javax.transaction.UserTransaction} and the
* {@link javax.transaction.TransactionManager} interface,
* as returned by this FactoryBean.
* <p/>
* <p>A local JOTM instance is well-suited for working in conjunction with
* ObjectWeb's <a HREF="http://xapool.experlog.com">XAPool</a>, e.g. with bean
* definitions like the following:
* <p/>
* <pre class="code">
* &lt;bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean"/&gt;
* <p/>
* &lt;bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"&gt;
* &lt;property name="userTransaction" ref="jotm"/&gt;
* &lt;/bean&gt;
* <p/>
* &lt;bean id="innerDataSource" class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown"&gt;
* &lt;property name="transactionManager" ref="jotm"/&gt;
* &lt;property name="driverName" value="..."/&gt;
* &lt;property name="url" value="..."/&gt;
* &lt;property name="user" value="..."/&gt;
* &lt;property name="password" value="..."/&gt;
* &lt;/bean&gt;
* <p/>
* &lt;bean id="dataSource" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown"&gt;
* &lt;property name="dataSource" ref="innerDataSource"/&gt;
* &lt;property name="user" value="..."/&gt;
* &lt;property name="password" value="..."/&gt;
* &lt;property name="maxSize" value="..."/&gt;
* &lt;/bean&gt;</pre>
* <p/>
* Note that Spring's {@link org.springframework.transaction.jta.JtaTransactionManager} will automatically detect
* that the passed-in UserTransaction reference also implements the
* TransactionManager interface. Hence, it is not necessary to specify a
* separate reference for JtaTransactionManager's "transactionManager" property.
* <p/>
* <p>Implementation note: This FactoryBean uses JOTM's static access method
* to obtain the JOTM {@link org.objectweb.jotm.Current} object, which
* implements both the UserTransaction and the TransactionManager interface,
* as mentioned above.
*
* @author Juergen Hoeller
* @see org.springframework.transaction.jta.JtaTransactionManager#setUserTransaction
* @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
* @see org.objectweb.jotm.Current
* @since 21.01.2004
*/
public class JotmFactoryBean implements FactoryBean, DisposableBean, InitializingBean {
private Current jotmCurrent;
private Jotm jotm;
private String jotmHome;
private Integer defaultTimeout;
private Boolean transactionRecovery;
/**
* Set the default transaction timeout for the JOTM instance.
* <p>Should only be called for a local JOTM instance,
* not when accessing an existing (shared) JOTM instance.
*/
public void setDefaultTimeout(int defaultTimeout) {
this.defaultTimeout = defaultTimeout;
}
public void setTransactionRecovery(boolean transactionRecovery) throws SystemException {
this.transactionRecovery = transactionRecovery;
}
/**
* @param jotmHome the directory that contains conf/jotm.properties
*/
public void setJotmHome(String jotmHome) {
this.jotmHome = jotmHome;
}
@Override
public void afterPropertiesSet() throws Exception {
createJotm();
}
private void createJotm() throws NamingException, SystemException {
if (jotmHome!=null) {
System.setProperty("jotm.home",jotmHome);
}
// Check for already active JOTM instance.
this.jotmCurrent = Current.getCurrent();
// If none found, create new local JOTM instance.
if (this.jotmCurrent == null) {
// Only for use within the current Spring context:
// local, not bound to registry.
this.jotm = new Jotm(true, false);
this.jotmCurrent = Current.getCurrent();
}
if (defaultTimeout!=null) {
this.jotmCurrent.setDefaultTimeout(defaultTimeout);
}
if (transactionRecovery!=null) {
this.jotmCurrent.setTransactionRecovery(transactionRecovery);
}
}
/**
* Return the JOTM instance created by this factory bean, if any.
* Will be <code>null</code> if an already active JOTM instance is used.
* <p>Application code should never need to access this.
*/
public Jotm getJotm() {
return this.jotm;
}
public Object getObject() {
return this.jotmCurrent;
}
public Class getObjectType() {
return this.jotmCurrent.getClass();
}
public boolean isSingleton() {
return true;
}
/**
* Stop the local JOTM instance, if created by this FactoryBean.
*/
public void destroy() {
if (this.jotm != null) {
this.jotm.stop();
}
}
}

View File

@@ -1,4 +1,4 @@
package org.springframework.data.graph.neo4j.support;
package org.springframework.data.graph.neo4j.transaction;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2010 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.graph.neo4j.transaction;
import org.neo4j.helpers.Service;
import org.neo4j.kernel.impl.core.KernelPanicEventGenerator;
import org.neo4j.kernel.impl.transaction.AbstractTransactionManager;
import org.neo4j.kernel.impl.transaction.TransactionManagerProvider;
import org.neo4j.kernel.impl.transaction.TxFinishHook;
import org.springframework.beans.factory.annotation.Configurable;
@Configurable
@Service.Implementation( TransactionManagerProvider.class )
public class SpringProvider extends TransactionManagerProvider
{
public SpringProvider()
{
super( "spring-jta" );
}
@Override
protected AbstractTransactionManager loadTransactionManager( String txLogDir,
KernelPanicEventGenerator kpe, TxFinishHook rollbackHook )
{
return new SpringServiceImpl();
}
}

View File

@@ -0,0 +1,102 @@
/*
* Copyright 2010 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.graph.neo4j.transaction;
import org.neo4j.kernel.impl.transaction.AbstractTransactionManager;
import org.neo4j.kernel.impl.transaction.XaDataSourceManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.transaction.jta.JtaTransactionManager;
import javax.transaction.*;
/**
* @author Chris Gioran
*/
@Configurable
class SpringServiceImpl extends AbstractTransactionManager
{
@Autowired
private JtaTransactionManager jtaTransactionManager;
private TransactionManager delegate;
SpringServiceImpl()
{
}
@Override
public void init( XaDataSourceManager xaDsManager )
{
delegate = jtaTransactionManager.getTransactionManager();
}
public void begin() throws NotSupportedException, SystemException
{
delegate.begin();
}
public void commit() throws RollbackException, HeuristicMixedException,
HeuristicRollbackException, SecurityException,
IllegalStateException, SystemException
{
delegate.commit();
}
public int getStatus() throws SystemException
{
return delegate.getStatus();
}
public Transaction getTransaction() throws SystemException
{
return delegate.getTransaction();
}
public void resume( Transaction tobj ) throws InvalidTransactionException,
IllegalStateException, SystemException
{
delegate.resume( tobj );
}
public void rollback() throws IllegalStateException, SecurityException,
SystemException
{
delegate.rollback();
}
public void setRollbackOnly() throws IllegalStateException, SystemException
{
delegate.setRollbackOnly();
}
public void setTransactionTimeout( int seconds ) throws SystemException
{
delegate.setTransactionTimeout( seconds );
}
public Transaction suspend() throws SystemException
{
return delegate.suspend();
}
@Override
public void stop()
{
// Currently a no-op
}
}

View File

@@ -1,4 +1,4 @@
package org.springframework.data.graph.neo4j.support;
package org.springframework.data.graph.neo4j.transaction;
/**
* @author mh

View File

@@ -0,0 +1 @@
org.springframework.data.graph.neo4j.transaction.SpringProvider

View File

@@ -1,4 +1,4 @@
package org.springframework.data.graph.neo4j.support;
package org.springframework.data.graph.neo4j.transaction;
import org.hamcrest.Description;
import org.hamcrest.Factory;
@@ -9,10 +9,10 @@ import org.springframework.transaction.support.DefaultTransactionDefinition;
import static junit.framework.Assert.*;
import static org.junit.Assert.assertThat;
import static org.springframework.data.graph.neo4j.support.ChainedTransactionManagerTest.TestPlatformTransactionManager.createFailingTransactionManager;
import static org.springframework.data.graph.neo4j.support.ChainedTransactionManagerTest.TestPlatformTransactionManager.createNonFailingTransactionManager;
import static org.springframework.data.graph.neo4j.support.ChainedTransactionManagerTest.TransactionManagerMatcher.isCommitted;
import static org.springframework.data.graph.neo4j.support.ChainedTransactionManagerTest.TransactionManagerMatcher.wasRolledback;
import static org.springframework.data.graph.neo4j.transaction.ChainedTransactionManagerTest.TestPlatformTransactionManager.createFailingTransactionManager;
import static org.springframework.data.graph.neo4j.transaction.ChainedTransactionManagerTest.TestPlatformTransactionManager.createNonFailingTransactionManager;
import static org.springframework.data.graph.neo4j.transaction.ChainedTransactionManagerTest.TransactionManagerMatcher.isCommitted;
import static org.springframework.data.graph.neo4j.transaction.ChainedTransactionManagerTest.TransactionManagerMatcher.wasRolledback;
import static org.springframework.transaction.HeuristicCompletionException.getStateString;
/**

View File

@@ -0,0 +1,109 @@
package org.springframework.data.graph.neo4j.transaction;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.NotFoundException;
import org.neo4j.graphdb.index.IndexHits;
import org.neo4j.kernel.Config;
import org.neo4j.kernel.EmbeddedGraphDatabase;
import org.objectweb.jotm.Current;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.transaction.jta.JtaTransactionManager;
import org.springframework.transaction.jta.ManagedTransactionAdapter;
import javax.transaction.NotSupportedException;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
/**
* @author mh
* @since 21.02.11
*/
public class JOTMIntegrationTest {
private ClassPathXmlApplicationContext ctx;
private GraphDatabaseService gds;
@Before
public void setUp() throws Exception {
ctx = new ClassPathXmlApplicationContext("classpath:spring-tx-text-context.xml");
gds = ctx.getBean(GraphDatabaseService.class);
}
@After
public void tearDown() throws Exception {
if (ctx != null) ctx.close();
}
@Test
public void createdNodeShouldBeFoundAfterCommit() throws Exception {
org.neo4j.graphdb.Transaction transaction = gds.beginTx();
Node node = null;
try {
node = gds.createNode();
assertNotNull(node);
transaction.success();
} finally {
transaction.finish();
}
Node readBackOutsideOfTx = gds.getNodeById(node.getId());
assertEquals(node, readBackOutsideOfTx);
try {
transaction = gds.beginTx();
Node readBackInsideOfTx = gds.getNodeById(node.getId());
assertEquals(node, readBackInsideOfTx);
transaction.success();
} finally {
transaction.finish();
}
}
@Test
public void indexedNodeShouldBeFound() throws Exception {
org.neo4j.graphdb.Transaction transaction = gds.beginTx();
Node node = null;
try {
node = gds.createNode();
gds.index().forNodes("node").add(node, "name", "value");
transaction.success();
} finally {
transaction.finish();
}
Node retrievedNode = gds.index().forNodes("node").get("name", "value").getSingle();
assertEquals(node,retrievedNode);
}
@Test(expected = NotFoundException.class)
public void createdNodeShouldBeNotAvailableAfterRollback() throws Exception {
org.neo4j.graphdb.Transaction tx = gds.beginTx();
long nodeId=0;
try {
Node node = gds.createNode();
nodeId = node.getId();
tx.failure();
} finally {
tx.finish();
}
gds.getNodeById(nodeId);
}
@Test
public void databaseConfiguredWithSpringJtaShouldUseJtaTransactionManager() throws SystemException, NotSupportedException {
Map<Object, Object> config = ((EmbeddedGraphDatabase) gds).getConfig().getParams();
assertEquals("spring-jta", config.get(Config.TXMANAGER_IMPLEMENTATION));
JtaTransactionManager tm = ctx.getBean("transactionManager", JtaTransactionManager.class);
Transaction transaction = tm.createTransaction("jotm", 1000);
assertEquals(ManagedTransactionAdapter.class, transaction.getClass());
assertEquals(Current.class, ((ManagedTransactionAdapter) transaction).getTransactionManager().getClass());
}
}

View File

@@ -137,7 +137,7 @@
<bean id="transactionManager" class="org.springframework.data.graph.neo4j.support.ChainedTransactionManager" >
<bean id="transactionManager" class="org.springframework.data.graph.neo4j.transaction.ChainedTransactionManager" >
<constructor-arg>
<list>
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="jpaTransactionManager">

View File

@@ -0,0 +1,37 @@
<?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"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-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/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config />
<context:spring-configured/>
<bean id="jotm" class="org.springframework.data.graph.neo4j.transaction.JotmFactoryBean">
<!--property name="jotmHome" value="target/classes/jotm"/-->
</bean>
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager" ref="jotm"/>
</bean>
<bean class="org.neo4j.kernel.EmbeddedGraphDatabase" destroy-method="shutdown">
<constructor-arg value="target/test-db"/>
<constructor-arg>
<map>
<entry key="tx_manager_impl" value="spring-jta"/>
</map>
</constructor-arg>
</bean>
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
</beans>

View File

@@ -1,30 +0,0 @@
Bundle-SymbolicName: org.springframework.data.neo4j
Bundle-Name: Spring Data Neo4J
Bundle-Vendor: SpringSource
Bundle-ManifestVersion: 2
Import-Package:
sun.reflect;version="0";resolution:=optional
Import-Template:
org.springframework.beans.*;version="[3.0.0, 4.0.0)",
org.springframework.context.*;version="[3.0.0, 4.0.0)",
org.springframework.core.*;version="[3.0.0, 4.0.0)",
org.springframework.dao.*;version="[3.0.0, 4.0.0)",
org.springframework.jdbc.*;version="[3.0.0, 4.0.0)",
org.springframework.orm.*;version="[3.0.0, 4.0.0)",
org.springframework.transaction.*;version="[3.0.0, 4.0.0)",
org.springframework.util.*;version="[3.0.0, 4.0.0)",
org.springframework.data.core.*;version="[1.0.0, 2.0.0)",
org.springframework.data.core.*;version="[1.0.0, 2.0.0)",
org.springframework.data.annotation.*;version="[1.0.0, 2.0.0)",
org.springframework.persistence.*;version="[1.0.0, 2.0.0)",
org.springframework.data.graph.*;version="0",
org.neo4j.*;version="0",
org.w3c.dom.*;version="0",
org.aspectj.*;version="[1.6.5, 2.0.0)",
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
org.apache.lucene.*;version="0",
javax.validation.*;version="0";resolution:=optional,
javax.annotation.*;version="0";resolution:=optional,
javax.persistence.*;version="[1.0.0, 3.0.0)";resolution:=optional,
javax.persistence.spi.*;version="[1.0.0, 3.0.0)";resolution:=optional,
javax.transaction.*;version="[1.0.1, 2.0.0)";resolution:=optional

View File

@@ -324,6 +324,58 @@ for (Person person : finder.findAllByProperyValue("occupation","developer")) {
trainInSpringData(developer.projectTo(Trainee.class));
}
}
]]></programlisting>
<section>
<title>Dynamic Typing - Projection to unrelated, fitting types</title>
<para>
As the underlying data model of a graph database doesn't imply and enforce strict type constraints like a relational
model does, it offers much more flexibility on how to model your domain classes and which of those to use in different
contexts.
</para>
<para>
For instance an order can be used in these contexts: customer, procurement, logistics, billing, fulfillment and many more.
Each of those contexts requires its distinct set of attributes and operations. As Java doesn't support mixins one would put
the sum of all of those into the entity class and thereby making it very big, brittle and hard to understand.
Being able to take a basic order and project it to a different (not related in the inheritance hierarchy or even an interface)
order type that is valid in the current context and only offers the attributes and methods needed here would be very benefitial.
</para>
<para>DATAGRAPH offers initial support for projecting node and relationship entities to different target types.
All instances of this projected entity share the same backing node or relationship, so data changes are reflected
immediately.
</para>
<para>
This could for instance also be used to handle nodes of a traversal with a unified (simpler) type (e.g. for
reporting or auditing) and only project them to a concrete, more functional target type when the business
logic requires it.
</para>
<programlisting lang="JAVA" ><![CDATA[
// not related to Person at all
@NodeEntity
class Trainee {
String name;
@RelatedTo(elementClass=Training.class);
Set<Training> trainings;
}
for (Person person : finder.findAllByProperyValue("occupation","developer")) {
Developer developer=person.projectTo(Developer.class)
if (developer.isJavaDeveloper()) {
trainInSpringData(developer.projectTo(Trainee.class));
}
}
]]></programlisting>
</section>
<section>
<title>Neo4jTemplate</title>
<para></para>
<programlisting lang="JAVA" ><![CDATA[
Neo4jOperations neo = new Neo4jTemplate(grapDatabase);
Node mark = neo.createNode(_("name","Mark"));
Node thomas = neo.createNode(_("name","Thomas"));
neo.createRelationship(mark,thomas, WORKS_WITH);
neo.index("devs","name","Mark",mark);
assert "Mark".equals(neo.query("devs","name","Mark",new NodeNamePathMapper()));
]]></programlisting>
</section>