org.structr.common.TransactionTest.java Source code

Java tutorial

Introduction

Here is the source code for org.structr.common.TransactionTest.java

Source

/**
 * Copyright (C) 2010-2016 Structr GmbH
 *
 * This file is part of Structr <http://structr.org>.
 *
 * Structr is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * Structr is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Structr.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.structr.common;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.fail;
import org.apache.commons.lang3.StringUtils;
import org.structr.common.error.FrameworkException;
import org.structr.core.app.StructrApp;
import org.structr.core.entity.AbstractNode;
import org.structr.core.entity.SchemaNode;
import org.structr.core.entity.SchemaProperty;
import org.structr.core.entity.TestOne;
import org.structr.core.graph.NodeAttribute;
import org.structr.core.graph.NodeInterface;
import org.structr.core.graph.Tx;
import org.structr.core.script.Scripting;
import org.structr.schema.action.ActionContext;

/**
 *
 */
public class TransactionTest extends StructrTest {

    private static final Logger logger = Logger.getLogger(TransactionTest.class.getName());

    public void testRollbackOnError() {

        final ActionContext ctx = new ActionContext(securityContext, null);

        /**
         * first the old scripting style
         */
        TestOne testNode = null;

        try (final Tx tx = app.tx()) {

            testNode = createTestNode(TestOne.class);
            testNode.setProperty(TestOne.aString, "InitialString");
            testNode.setProperty(TestOne.anInt, 42);

            tx.success();

        } catch (FrameworkException ex) {

            logger.log(Level.WARNING, "", ex);
            fail("Unexpected exception");

        }

        try (final Tx tx = app.tx()) {

            Scripting.replaceVariables(ctx, testNode,
                    "${ ( set(this, 'aString', 'NewString'), set(this, 'anInt', 'NOT_AN_INTEGER') ) }");
            fail("StructrScript: setting anInt to 'NOT_AN_INTEGER' should cause an Exception");

            tx.success();

        } catch (FrameworkException expected) {
        }

        try {

            try (final Tx tx = app.tx()) {

                assertEquals("Property value should still have initial value!", "InitialString",
                        testNode.getProperty(TestOne.aString));

                tx.success();
            }

        } catch (FrameworkException ex) {

            logger.log(Level.WARNING, "", ex);
            fail("Unexpected exception");

        }
    }

    public void testConstraintsConcurrently() {

            /**
             * This test concurrently creates 1000 nodes in
             * batches of 10, with 10 threads simultaneously.
             */

            try (final Tx tx = app.tx()) {

            app.create(SchemaNode.class, new NodeAttribute(SchemaNode.name, "Item"), new NodeAttribute(
                    SchemaNode.schemaProperties,
                    Arrays.asList(app.create(SchemaProperty.class, new NodeAttribute(SchemaProperty.name, "name"),
                            new NodeAttribute(SchemaProperty.propertyType, "String"),
                            new NodeAttribute(SchemaProperty.unique, true),
                            new NodeAttribute(SchemaProperty.indexed, true)))));

            tx.success();

        } catch (FrameworkException ex) {
            fail("Error creating schema node");
        }

        final Class itemType = StructrApp.getConfiguration().getNodeEntityClass("Item");

        assertNotNull("Error creating schema node", itemType);

        final Runnable worker = new Runnable() {

            @Override
            public void run() {

                int i = 0;

                while (i < 1000) {

                    try (final Tx tx = app.tx()) {

                        for (int j = 0; j < 10 && i < 1000; j++) {

                            app.create(itemType, "Item" + StringUtils.leftPad(Integer.toString(i++), 5, "0"));
                        }

                        tx.success();

                    } catch (FrameworkException expected) {
                    }
                }
            }
        };

        final ExecutorService service = Executors.newFixedThreadPool(10);
        final List<Future> futures = new LinkedList<>();

        for (int i = 0; i < 10; i++) {

            futures.add(service.submit(worker));
        }

        // wait for result of async. operations
        for (final Future future : futures) {

            try {
                future.get();

            } catch (Throwable t) {

                logger.log(Level.WARNING, "", t);
                fail("Unexpected exception");
            }
        }

        try (final Tx tx = app.tx()) {

            final List<NodeInterface> items = app.nodeQuery(itemType).sort(AbstractNode.name).getAsList();
            int i = 0;

            assertEquals("Invalid concurrent constraint test result", 1000, items.size());

            for (final NodeInterface item : items) {

                assertEquals("Invalid name detected", "Item" + StringUtils.leftPad(Integer.toString(i++), 5, "0"),
                        item.getName());
            }

            tx.success();

        } catch (FrameworkException ex) {
            fail("Unexpected exception");
        }

    }
}