How to manage the transaction(which includes File IO) when an IOException is thrown from the close file method

假装没事ソ 提交于 2021-02-18 22:07:07

问题


I've recently begun using Spring's Data Source Transaction Manager. I have a problem now. My transaction includes updates to a DB table and a write operation to a file.

It works fine but I have some doubts about file I/O. As you see below, I have configured openFile and closeFile methods of my bean as the init-method and the destroy-method respectively, which in turn provides those methods to be called just like a constuructor and a destructor. If the file is not closed properly, some of the records may not have successfully been written to the output.txt file which means that I have not been able to handle transaction management properly as well.

However, I'd like to rollback those DB updates which have not been appended to the flat file. With my solution, it looks impossible to add the fileClose method to the transaction. Does anyone know how to implement this desired action properly?

Any suggestions would be greatly appreciated

<!--XML CONFIGURATION -->
<bean id="myFileWriter" class="com.job.step.ItemFileWriter"  init-method="openFile" destroy-method="closeFile">
    <property name="jdbcTemplate" ref="jdbcTemplateProduct"/>   
</bean> 

public class ItemFileWriter implements ItemWriter<Item> {
private static final Logger log = Logger.getLogger(ItemFileWriter.class);   
private BufferedWriter bw = null;
public void openFile() throws IOException {
    try {
        bw = new BufferedWriter(new FileWriter("C:\\output.txt"));
    } catch (IOException e) {           
        //log.error(e);
        throw e;
    }       
}
public void closeFile() throws IOException {
    if (bw != null) {
        try {
            bw.close();
        } catch (IOException e) {
            log.error(e);
            throw e;
        }
    }
}

@Transactional(rollbackFor = IOException.class)
public void write(List<? extends Item> itemList) throws IOException 
{               
    for (Iterator<? extends Item> iterator = itemList.iterator(); iterator.hasNext();) {
        Item item = (Item) iterator.next();

        String updateRtlnOutbound = "UPDATE SAMPLESCHEMA.SAMPLETABLE SET STATUS='TRANSFERRED' WHERE ID = ?";
        jdbcTemplate.update(updateRtlnOutbound, new Object[]{item.getID()});

        String item = String.format("%09d\n", item.customerNumber);
        bw.write(item);
    }                           
}
}   

回答1:


Generally speaking, file IO is not transactional (except for some OS-specific features).

So, the best you can do is to move open and close operation to write() method, in order to execute them inside a transaction and rollback the transaction if closing fails.

Note, however, that you can't rollback the file IO in the case of transaction rollback, so that under some circumstances you can get the correct file with items, whereas in the database these items are not marked as TRANSFERRED.

To sove this problem you can try to use low-level transaction management support and try to delete the file in the case of rollback, but I think it still can't provide strong guarantees of consistency:

@Transactional(rollbackFor = IOException.class)
public void write(List<? extends Item> itemList) throws IOException 
{                
    openFile();
    TransactionSynchronizationManager().registerSynchronization(new TransactionSynchronizationAdapter() {
        public void afterCompletion(int status) {
            if (status = STATUS_ROLLED_BACK) {
                // try to delete the file
            }
        }
    });

    try {
        ...
    } finally {
        closeFile();                        
    }
}



回答2:


You are doing operations over two different systems: file-system and database. Typically, XA transactions make it easy for us to combine different transactional systems into a single transaction.

Most databases can be made to participate in XA transactions. For file-system you can use XADisk to enable XA. Once you enable XA on both database (through right configuration of data-source) and file-system (through xadisk), you can be sure that both the file and database operations commit or both of them rollback.



来源:https://stackoverflow.com/questions/5245682/how-to-manage-the-transactionwhich-includes-file-io-when-an-ioexception-is-thr

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!