Announcement Announcement Module
Collapse
No announcement yet.
Transcational filesystem access Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Transcational filesystem access

    Hi,

    Is there any way to put filesystem operations (creating and writing to file) under spring transaction scope?
    I thought that spring-integration-file will solve my problems, but unfortunately it didn't.
    It seems that file:outbound-channel-adapter is not under transaction scope, so even if transaction is rolled back, the file is still on disk.

    applicationContext.xml:
    Code:
    <bean id="test" class="file.spring.FileBeanSpring">
    	<property name="factory" ref="filesOut" />
    </bean>
    <bean id="periodicTrigger" class="org.springframework.scheduling.support.PeriodicTrigger">
    	<constructor-arg value="0" />
    </bean>
    <file:outbound-channel-adapter id="filesOut" directory="target\fileStorage" />
    <integration:poller default="true" trigger="periodicTrigger">
    	<integration:transactional transaction-manager="txManager" />
    </integration:poller>
    FileBeanSpring.java:
    Code:
    public class FileBeanSpring {
    	private DirectChannel factory;
    	
    	@Transactional(propagation=Propagation.REQUIRED)
    	public void storeFile(File fileToStore) throws Exception {
    		Message<File> message = new GenericMessage<File>(fileToStore);
    		factory.send(message);
    	}
    
    	public void setFactory(DirectChannel factory) {
    		this.factory = factory;
    	}
    }
    FileBeanTest.java:
    Code:
    @ContextConfiguration( { "file:src/main/resources/applicationContext.xml"})
    @TransactionConfiguration(defaultRollback = true, transactionManager = "txManager")
    public class FileBeanTest extends AbstractTransactionalJUnit4SpringContextTests {
    
    	@Autowired
    	private FileBeanSpring bean;
    	
    	@Before
    	public void clearStorageDirectory() {
    		for(File f : new File("target\\fileStorage").listFiles()) {
    			f.delete();
    		}
    	}
    	
    	@Test
    	public void testFileStore() throws Exception {
    		File f = new File("src/test/resources/test.txt"); 
    		bean.storeFile(f);
    		File destinationFile = new File("target/fileStorage/test.txt");
    		assertFalse(destinationFile.exists());	
    	}
    }
    Whole application is available at: http://svn.oledzki.info/svn/Java/Pub...g-integration/

    What should I do, to made file:outbound-channel-adapter transactional?

  • #2
    First of all, you need a transactional file system with an XA enabled Transaction Manager. Check out http://www.jboss.org/jbosstm/fileio , the page say that have one (I'm not tested it in any way).

    Few Years ago, I solved the same problem using a TransactionSynchronization that hold a stack with file system operations. It's not really transactional, but work well unless the application hangs or unplug the machine .

    Code:
     **
     * A TransacionSynchronization to add filesystem operations to DataSourceTransactionManager.
     * 
     * Filesystem is not transactional but we use the Synchronization to be 
     * notified by DataSourceTransactionManager when they commit or rollback database operations
     * and get a chance to sychronize filesystem and database.
     * 
     * filesystem failures will not be transactional.
     * 
     * @author Jose Luis Martin
     */
    
    public class FSTransactionSynchronization extends TransactionSynchronizationAdapter {
    	
    	/** log */
    	private static final Log log = LogFactory.getLog(FSTransactionSynchronization.class);
    	/** Stack for filesystem commands */
    	private CommandStack stack;
    
    	/**
    	 * Ctor 
    	 * @param stack the command stack to use in this sychronization
    	 */
    	public FSTransactionSynchronization(CommandStack stack) {
    		this.stack = stack;
    	}
    	
    	/**
    	 * callback for after transaction completion.
    	 * Undo filesystem commands on database rollbacks.
    	 * @param status the transaction status
    	 */
    	public void afterCompletion(int status) {
    		// Undo operations on rollbacks
    		if (TransactionSynchronization.STATUS_ROLLED_BACK == status) {
    			stack.rollback();
    		}
    		else if (TransactionSynchronization.STATUS_COMMITTED == status) {
    			// Database transaction was commited ensure that command stack its commited too.
    			try {
    				stack.commit();
    			} catch (Exception e) {
    				log.error("Command stack fail to commit!. Database and Filesystem are out of sync.");
    			}
    		}
    		stack.clear();
    	}
    }

    Comment


    • #3
      Can XADisk help?

      Hi,

      XADisk supports local and XA transactions over file-systems to allows applications to do file/directory operations inside transactions (local or XA transactions). It works over *all* Java5/above JVMs independent of the environment (web severs, j2ee server, standalone applications. I also know of some projects which integrated XADisk with Spring).

      Hope that helps.

      Thanks,
      Nitin
      Last edited by nitin_verma; Feb 12th, 2012, 04:17 AM.

      Comment


      • #4
        Originally posted by chelu View Post
        First of all, you need a transactional file system with an XA enabled Transaction Manager. Check out http://www.jboss.org/jbosstm/fileio , the page say that have one (I'm not tested it in any way).
        Thanks for information about fileio. Although I was looking for library which support declarative transaction I will try to use fileio because it look quite interesting.
        Originally posted by chelu View Post
        Few Years ago, I solved the same problem using a TransactionSynchronization that hold a stack with file system operations. It's not really transactional, but work well unless the application hangs or unplug the machine .
        Thanks, I will also try to use this.

        Comment


        • #5
          Originally posted by nitin_verma View Post
          XADisk supports local and XA transactions over file-systems to allows applications to do file/directory operations inside transactions (local or XA transactions).
          It looks interesting, but I'm still trying to successfully integrate it with spring.

          Comment


          • #6
            In versions of Windows earlier than Vista, the filesystem is not transactional, so you need a separate tool to do transactions on your files.

            You could use Component Services (COM+) to implement a Compensating Resource Manager (CRM). The CRM will provide the transaction log and will roll back changes during a system restart if it crashed during the update of your files, but you will have to provide the code (in your own DLL) to commit and rollback the transation, typically by means of moving files in and out of a temp folder. It can all be done in .Net by means of the System.EnterpriseServices namespace. If I recall correctly, Microsoft Official Course 2557 contains a chapter that teaches how to create a CRM, and the example that they use is built precisely on changes to the filesystem.

            Comment


            • #7
              Originally posted by LDevil View Post
              It looks interesting, but I'm still trying to successfully integrate it with spring.
              Hello,

              You may want to look at my post in this thread for basic integration with XADisk:

              http://groups.google.com/group/xadis...38ebd7f043ce47

              Thanks,
              Nitin
              Last edited by nitin_verma; Aug 8th, 2011, 03:29 PM.

              Comment


              • #8
                Thanks for helping me. In the meantime I was able to create a little more advanced integration of XADisk with spring. Unfortunately I have to use Jencks, which is no active anymore, but it seems that everything works. I can use booth XADisk and EntityManager in the same transaction.
                I'm still trying to achieve similar result without Jenkcs library, but unfortunately without luck. If someone has idea how to achieve this please let me know.
                Sample project which demonstrate how to use XADisk in Spring is available at my svn repository: http://svn.oledzki.info/svn/Java/Public/xadisk-jencks/

                Comment


                • #9
                  Originally posted by LDevil View Post
                  I'm still trying to achieve similar result without Jenkcs library, but unfortunately without luck. If someone has idea how to achieve this please let me know.
                  We can give it a try and probably help you out; can you please detail the problem at the xadisk google-group so that apart from me, others can also provide inputs.

                  Thanks,
                  Nitin

                  Comment

                  Working...
                  X