org.springframework.batch.item.xml.TransactionalStaxEventItemWriterTests.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.batch.item.xml.TransactionalStaxEventItemWriterTests.java

Source

/*
 * Copyright 2008-2014 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.batch.item.xml;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.List;

import javax.xml.stream.XMLEventFactory;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLStreamException;
import javax.xml.transform.Result;

import org.apache.commons.io.FileUtils;
import org.junit.Before;
import org.junit.Test;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.XmlMappingException;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;

/**
 * Tests for {@link StaxEventItemWriter}.
 */
public class TransactionalStaxEventItemWriterTests {

    // object under test
    private StaxEventItemWriter<Object> writer;

    private PlatformTransactionManager transactionManager = new ResourcelessTransactionManager();

    // output file
    private Resource resource;

    private ExecutionContext executionContext;

    // test item for writing to output
    private Object item = new Object() {
        @Override
        public String toString() {
            return ClassUtils.getShortName(StaxEventItemWriter.class) + "-testString";
        }
    };

    private List<? extends Object> items = Collections.singletonList(item);

    private static final String TEST_STRING = "<!--" + ClassUtils.getShortName(StaxEventItemWriter.class)
            + "-testString-->";

    @Before
    public void setUp() throws Exception {
        resource = new FileSystemResource(File.createTempFile("StaxEventWriterOutputSourceTests", ".xml"));
        writer = createItemWriter();
        executionContext = new ExecutionContext();
    }

    /**
     * Item is written to the output file only after flush.
     */
    @Test
    public void testWriteAndFlush() throws Exception {
        writer.open(executionContext);
        new TransactionTemplate(transactionManager).execute(new TransactionCallback<Void>() {
            @Override
            public Void doInTransaction(TransactionStatus status) {
                try {
                    writer.write(items);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
                return null;
            }
        });
        writer.close();
        String content = outputFileContent();
        assertTrue("Wrong content: " + content, content.contains(TEST_STRING));
    }

    /**
     * Item is written to the output file only after flush.
     */
    @Test
    public void testWriteWithHeaderAfterRollback() throws Exception {
        writer.setHeaderCallback(new StaxWriterCallback() {

            @Override
            public void write(XMLEventWriter writer) throws IOException {
                XMLEventFactory factory = XMLEventFactory.newInstance();
                try {
                    writer.add(factory.createStartElement("", "", "header"));
                    writer.add(factory.createEndElement("", "", "header"));
                } catch (XMLStreamException e) {
                    throw new RuntimeException(e);
                }

            }

        });
        writer.open(executionContext);
        try {
            new TransactionTemplate(transactionManager).execute(new TransactionCallback<Void>() {
                @Override
                public Void doInTransaction(TransactionStatus status) {
                    try {
                        writer.write(items);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                    throw new RuntimeException("Planned");
                }
            });
            fail("Expected RuntimeException");
        } catch (RuntimeException e) {
            // expected
        }
        writer.close();
        writer.open(executionContext);
        new TransactionTemplate(transactionManager).execute(new TransactionCallback<Void>() {
            @Override
            public Void doInTransaction(TransactionStatus status) {
                try {
                    writer.write(items);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
                return null;
            }
        });
        writer.close();
        String content = outputFileContent();
        assertEquals("Wrong content: " + content, 1, StringUtils.countOccurrencesOf(content, ("<header/>")));
        assertEquals("Wrong content: " + content, 1, StringUtils.countOccurrencesOf(content, TEST_STRING));
    }

    /**
     * Item is written to the output file only after flush.
     */
    @Test
    public void testWriteWithHeaderAfterFlushAndRollback() throws Exception {
        writer.setHeaderCallback(new StaxWriterCallback() {

            @Override
            public void write(XMLEventWriter writer) throws IOException {
                XMLEventFactory factory = XMLEventFactory.newInstance();
                try {
                    writer.add(factory.createStartElement("", "", "header"));
                    writer.add(factory.createEndElement("", "", "header"));
                } catch (XMLStreamException e) {
                    throw new RuntimeException(e);
                }

            }

        });
        writer.open(executionContext);
        new TransactionTemplate(transactionManager).execute(new TransactionCallback<Void>() {
            @Override
            public Void doInTransaction(TransactionStatus status) {
                try {
                    writer.write(items);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
                return null;
            }
        });
        writer.update(executionContext);
        writer.close();
        writer.open(executionContext);
        try {
            new TransactionTemplate(transactionManager).execute(new TransactionCallback<Void>() {
                @Override
                public Void doInTransaction(TransactionStatus status) {
                    try {
                        writer.write(items);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                    throw new RuntimeException("Planned");
                }
            });
            fail("Expected RuntimeException");
        } catch (RuntimeException e) {
            // expected
        }
        writer.close();
        String content = outputFileContent();
        assertEquals("Wrong content: " + content, 1, StringUtils.countOccurrencesOf(content, ("<header/>")));
        assertEquals("Wrong content: " + content, 1, StringUtils.countOccurrencesOf(content, TEST_STRING));
    }

    /**
     * @return output file content as String
     */
    private String outputFileContent() throws IOException {
        return FileUtils.readFileToString(resource.getFile(), (String) null);
    }

    /**
     * Writes object's toString representation as XML comment.
     */
    private static class SimpleMarshaller implements Marshaller {
        @Override
        public void marshal(Object graph, Result result) throws XmlMappingException, IOException {
            try {
                StaxUtils.getXmlEventWriter(result)
                        .add(XMLEventFactory.newInstance().createComment(graph.toString()));
            } catch (Exception e) {
                throw new RuntimeException("Exception while writing to output file", e);
            }
        }

        @Override
        public boolean supports(Class<?> clazz) {
            return true;
        }
    }

    /**
     * @return new instance of fully configured writer
     */
    private StaxEventItemWriter<Object> createItemWriter() throws Exception {
        StaxEventItemWriter<Object> source = new StaxEventItemWriter<Object>();
        source.setResource(resource);

        Marshaller marshaller = new SimpleMarshaller();
        source.setMarshaller(marshaller);

        source.setEncoding("UTF-8");
        source.setRootTagName("root");
        source.setVersion("1.0");
        source.setOverwriteOutput(true);
        source.setSaveState(true);

        source.afterPropertiesSet();

        return source;
    }
}