INTSAMPLES-91 Transaction Synchronization Sample

INTSAMPLES-91 Initial Commit

INTSAMPLES-91 Polishing

INTSAMPLES-91 Add JDBC Activity
This commit is contained in:
Gary Russell
2012-09-25 15:30:53 +01:00
parent 542f3569e4
commit 80986a0080
8 changed files with 380 additions and 0 deletions

View File

@@ -62,6 +62,7 @@ This category targets developers who are already more familiar with the Spring I
* **stored-procedures-oracle** Provides an example of the stored procedure Outbound Gateway using *ORACLE XE*
* **monitoring** The project used in the *[Spring Integration Management and Monitoring Webinar](http://www.springsource.org/node/3598)* Also available on the *[SpringSourceDev YouTube Channel](http://www.youtube.com/SpringSourceDev)*
* **retry-and-more** Provides samples showing the application of MessageHandler Advice Chains to endpoints - retry, circuit breaker, expression evaluating
* **tx-synch** Provides a sample demonstrating the use of transaction syncrhonization, renaming an input file to a different filename, depending on whether the transaction commits, or rolls back.
## Advanced

48
intermediate/tx-synch/README.md Executable file
View File

@@ -0,0 +1,48 @@
Transaction Synchronization Sample "tx-synch"
=============================================
This sample shows how to use the 2.2.0 Transaction Synchronization feature.
Run the class `TransactionSynchronizationDemo` as a java application (main).
The Spring Integration application consists of a simple flow that reads a file, and stores its contents in a database table.
If the contents of the file starts with "fail", after writing to the database, the 'ConditionalService' throws an exception and rolls back the database update.
There are two synchronization actions
- rename the file, adding '.SUCCEEDED' to the filename when the transaction commits
- rename the file, adding '.FAILED' to the filename when the transaction rolls back
These actions are logged.
The file inbound adapter looks for files in ${java.io.tmpdir}/txSynchDemo
The java.io.tmpdir for your machine is displayed in the console…
````
This is the Transaction Synchronization Sample -
Press 'Enter' to terminate.
Place a file in /var/folders/k0/gch26h6d2ms9t0g7pyhtzfkc0000gn/T/txSynchDemo ending
with .txt
If the first line begins with 'fail' the transaction
transaction will be rolled back.The result of the
expression evaluation is logged.
=========================================================
/var/folders/k0/gch26h6d2ms9t0g7pyhtzfkc0000gn/T/txSynchDir
````
To send a good file, put a file in that directory; for example:
echo good > /var/folders/k0/gch26h6d2ms9t0g7pyhtzfkc0000gn/T/txSynchDemo/xx.txt
echo failing > /var/folders/k0/gch26h6d2ms9t0g7pyhtzfkc0000gn/T/txSynchDemo/x.txt
The inbound adapter uses the default filters so each filename may only be used once for each run of the program.
In addition, there is a JDBC inbound adapter that polls the database every 5 seconds, and logs its contents - this can be used to see commit Vs. rollback in the database.

102
intermediate/tx-synch/pom.xml Executable file
View File

@@ -0,0 +1,102 @@
<?xml version="1.0" encoding="UTF-8"?>
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.integration.samples</groupId>
<artifactId>tx-synch</artifactId>
<version>2.1.0.BUILD-SNAPSHOT</version>
<name>Samples (Intermediate) - Transaction Synchronization</name>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.framework.version>3.1.2.RELEASE</spring.framework.version>
<spring.integration.version>2.2.0.RC1</spring.integration.version>
<log4j.version>1.2.16</log4j.version>
<junit.version>4.10</junit.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-stream</artifactId>
<version>${spring.integration.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-jdbc</artifactId>
<version>${spring.integration.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-file</artifactId>
<version>${spring.integration.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-ftp</artifactId>
<version>${spring.integration.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.framework.version}</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.3.166</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.8.5</version>
</dependency>
<!-- test-scoped dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.framework.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
<compilerArgument>-Xlint:all</compilerArgument>
<showWarnings>true</showWarnings>
<showDeprecation>false</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2</version>
<configuration>
<mainClass>${java.main.class}</mainClass>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>repo.springsource.org.milestone</id>
<name>Spring Framework Maven Milestone Repository</name>
<url>https://repo.springsource.org/libs-snapshot</url>
</repository>
</repositories>
</project>

View File

@@ -0,0 +1,48 @@
/*
* Copyright 2002-2012 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.integration.samples.advice;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
/**
* @author Gary Russell
* @since 2.2
*
*/
public class ConditionalService {
@Autowired
private JdbcTemplate jdbcTemplate;
private final Log logger = LogFactory.getLog(this.getClass());
/**
* If this service receives a payload 'fail.*' it throws an Exception.
* @param payload
*/
public void failIfTextIsFail(String payload) {
this.jdbcTemplate.update("insert into FOO values(?)", payload);
if (payload.startsWith("fail")) {
logger.info("Service failure for " + payload);
throw new RuntimeException("Forced Exception");
}
logger.info("Service success for " + payload);
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright 2002-2012 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.integration.samples.advice;
import org.apache.log4j.Logger;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author Gary Russell
* @since 2.2
*
*/
public class TransactionSynchronizationDemo {
private static final Logger LOGGER = Logger.getLogger(TransactionSynchronizationDemo.class);
public static void main(String[] args) throws Exception {
LOGGER.info("\n========================================================="
+ "\n "
+ "\n Welcome to Spring Integration! "
+ "\n "
+ "\n For more information please visit: "
+ "\n http://www.springsource.org/spring-integration "
+ "\n "
+ "\n=========================================================" );
final AbstractApplicationContext context =
new ClassPathXmlApplicationContext("classpath:META-INF/spring/integration/transaction-synch-context.xml");
context.registerShutdownHook();
LOGGER.info("\n========================================================="
+ "\n "
+ "\n This is the Transaction Synchronization Sample - "
+ "\n "
+ "\n Press 'Enter' to terminate. "
+ "\n "
+ "\n Place a file in " + System.getProperty("java.io.tmpdir") + "/txSynchDemo ending "
+ "\n with .txt "
+ "\n If the first line begins with 'fail' the transaction "
+ "\n transaction will be rolled back.The result of the "
+ "\n expression evaluation is logged. "
+ "\n "
+ "\n=========================================================" );
System.out.println(System.getProperty("java.io.tmpdir") + "/txSynchDir");
System.in.read();
System.exit(0);
}
}

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-stream="http://www.springframework.org/schema/integration/stream"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:int-file="http://www.springframework.org/schema/integration/file"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:int-jdbc="http://www.springframework.org/schema/integration/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/file http://www.springframework.org/schema/integration/file/spring-integration-file.xsd
http://www.springframework.org/schema/integration/jdbc http://www.springframework.org/schema/integration/jdbc/spring-integration-jdbc-2.2.xsd
http://www.springframework.org/schema/integration/stream http://www.springframework.org/schema/integration/stream/spring-integration-stream.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config />
<context:property-placeholder />
<int-file:inbound-channel-adapter
channel="inputChannel"
auto-create-directory="true"
filename-pattern="*.txt"
directory="${java.io.tmpdir}/txSynchDemo/">
<int:poller fixed-delay="500">
<int:transactional transaction-manager="txManager" synchronization-factory="syncFactory" />
</int:poller>
</int-file:inbound-channel-adapter>
<int:transaction-synchronization-factory id="syncFactory">
<int:after-commit expression="payload.renameTo(payload.absolutePath + '.SUCCEEDED') ? payload + ' renamed after success' : payload + 'failed to rename after success'"
channel="infoLogger" />
<int:after-rollback expression="payload.renameTo(payload.absolutePath + '.FAILED') ? payload + ' renamed after faiure' : payload + 'failed to rename after failure'"
channel="errorLogger" />
</int:transaction-synchronization-factory>
<int:channel id="inputChannel"/>
<int-file:file-to-string-transformer input-channel="inputChannel" output-channel="toServiceChannel" />
<int:service-activator input-channel="toServiceChannel"
ref="conditionalService"
method="failIfTextIsFail" />
<int:logging-channel-adapter id="infoLogger" level="INFO" />
<int:logging-channel-adapter id="errorLogger" level="ERROR" />
<bean id="conditionalService" class="org.springframework.integration.samples.advice.ConditionalService" />
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<jdbc:embedded-database id="dataSource" type="H2">
<jdbc:script location="classpath:table.sql" />
</jdbc:embedded-database>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- Poll the database for rows -->
<int-jdbc:inbound-channel-adapter channel="infoLogger"
query="select BAR from FOO" data-source="dataSource">
<int:poller fixed-delay="5000" />
</int-jdbc:inbound-channel-adapter>
</beans>

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<!-- Appenders -->
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{HH:mm:ss.SSS} %-5p [%t][%c] %m%n" />
</layout>
</appender>
<!-- Loggers -->
<logger name="org.springframework">
<level value="warn" />
</logger>
<logger name="org.springframework.integration.endpoint.SourcePollingChannelAdapter">
<level value="warn" />
</logger>
<logger name="org.springframework.integration">
<level value="warn" />
</logger>
<logger name="org.springframework.integration.handler.LoggingHandler">
<level value="info" />
</logger>
<logger name="org.springframework.integration.samples">
<level value="info" />
</logger>
<logger name="org.springframework.retry">
<level value="warn" />
</logger>
<!-- Root Logger -->
<root>
<priority value="warn" />
<appender-ref ref="console" />
</root>
</log4j:configuration>

View File

@@ -0,0 +1,4 @@
CREATE TABLE IF NOT EXISTS FOO (
BAR VARCHAR(256)
);