de.hybris.platform.maintenance.CleanupCronJobIntegrationTest.java Source code

Java tutorial

Introduction

Here is the source code for de.hybris.platform.maintenance.CleanupCronJobIntegrationTest.java

Source

/*
 * [y] hybris Platform
 *
 * Copyright (c) 2000-2013 hybris AG
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of hybris
 * ("Confidential Information"). You shall not disclose such Confidential
 * Information and shall use it only in accordance with the terms of the
 * license agreement you entered into with hybris.
 * 
 *  
 */
package de.hybris.platform.maintenance;

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

import de.hybris.bootstrap.annotations.IntegrationTest;
import de.hybris.platform.core.Registry;
import de.hybris.platform.core.model.product.ProductModel;
import de.hybris.platform.core.model.test.TestItemModel;
import de.hybris.platform.cronjob.enums.CronJobResult;
import de.hybris.platform.cronjob.enums.CronJobStatus;
import de.hybris.platform.cronjob.model.CronJobModel;
import de.hybris.platform.impex.jalo.ImpExException;
import de.hybris.platform.impex.jalo.ImpExManager;
import de.hybris.platform.jalo.test.TestItem;
import de.hybris.platform.jobs.GenericMaintenanceJobPerformable;
import de.hybris.platform.jobs.maintenance.MaintenanceCleanupStrategy;
import de.hybris.platform.jobs.maintenance.impl.CleanupCronJobStrategy;
import de.hybris.platform.servicelayer.ServicelayerTransactionalTest;
import de.hybris.platform.servicelayer.cronjob.PerformResult;
import de.hybris.platform.servicelayer.internal.model.MaintenanceCleanupJobModel;
import de.hybris.platform.servicelayer.model.ModelService;
import de.hybris.platform.servicelayer.search.FlexibleSearchQuery;
import de.hybris.platform.servicelayer.search.FlexibleSearchService;
import de.hybris.platform.servicelayer.search.internal.resolver.ItemObjectResolver;
import de.hybris.platform.servicelayer.session.SessionService;
import de.hybris.platform.servicelayer.type.TypeService;
import de.hybris.platform.testframework.TestUtils;
import de.hybris.platform.util.CSVReader;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.commons.lang.CharUtils;
import org.joda.time.DateTime;
import org.junit.Before;
import org.junit.Test;

@IntegrationTest
public class CleanupCronJobIntegrationTest extends ServicelayerTransactionalTest {
    @Resource
    private ModelService modelService;

    @Resource
    private TypeService typeService;

    @Resource
    private FlexibleSearchService flexibleSearchService;

    @Resource
    private SessionService sessionService;

    private GenericMaintenanceJobPerformable gmjp;
    private CleanupCronJobStrategy cuCJmi;

    @Before
    public void setup() {
        final ItemObjectResolver modelResolver = Registry.getApplicationContext().getBean("modelResolver",
                ItemObjectResolver.class);

        //the performable with all the needed services
        gmjp = new GenericMaintenanceJobPerformable();
        gmjp.setModelService(modelService);
        gmjp.setFlexibleSearchService(flexibleSearchService);
        gmjp.setSessionService(sessionService);
        gmjp.setModelResolver(modelResolver);

        //the testsubject with the default values
        cuCJmi = new CleanupCronJobStrategy();
        cuCJmi.setModelService(modelService);
        cuCJmi.setTypeService(typeService);
        cuCJmi.setResult(Collections.singleton(CronJobResult.SUCCESS));
        cuCJmi.setStatus(Collections.singleton(CronJobStatus.FINISHED));
        cuCJmi.setExcludedCronJobCodes(Collections.EMPTY_SET);

        gmjp.setMaintenanceCleanupStrategy(cuCJmi);
        assertEquals("MaintenanceCleanupJob", gmjp.getType());

        final MaintenanceCleanupJobModel slayerJob = modelService.create(MaintenanceCleanupJobModel.class);
        slayerJob.setCode("cleanupCronJobsPerformable");
        slayerJob.setSpringId("cleanupCronJobsPerformable");

        modelService.save(slayerJob);
    }

    @Test
    public void testCleanupCronjob_Timeframe() throws ImpExException {
        final int currentExistingCJs = countExistingCronJobs(CronJobResult.SUCCESS, CronJobStatus.FINISHED);

        createCronJobs("too_young", CronJobResult.SUCCESS, CronJobStatus.FINISHED, 1, 1);
        createCronJobs("young", CronJobResult.SUCCESS, CronJobStatus.FINISHED, 7, 13);
        createCronJobs("very_old", CronJobResult.SUCCESS, CronJobStatus.FINISHED, 113, 100);
        assertEquals(currentExistingCJs + 121,
                countExistingCronJobs(CronJobResult.SUCCESS, CronJobStatus.FINISHED));

        final MaintenanceCleanupJobModel job = new MaintenanceCleanupJobModel();

        final CronJobModel cjm = new CronJobModel();
        cjm.setJob(job);

        PerformResult result = gmjp.perform(cjm);
        assertEquals(CronJobResult.SUCCESS, result.getResult());
        assertEquals(CronJobStatus.FINISHED, result.getStatus());

        assertEquals(currentExistingCJs + 8, countExistingCronJobs(CronJobResult.SUCCESS, CronJobStatus.FINISHED));

        job.setThreshold(Integer.valueOf(3));

        result = gmjp.perform(cjm);
        assertEquals(CronJobResult.SUCCESS, result.getResult());
        assertEquals(CronJobStatus.FINISHED, result.getStatus());

        assertEquals(currentExistingCJs + 1, countExistingCronJobs(CronJobResult.SUCCESS, CronJobStatus.FINISHED));
    }

    @Test
    public void testCleanupCronjob_StatusAndResult() throws ImpExException {
        final int currentExistingCJs = countExistingCronJobs(null, null);

        gmjp.setPageSize(2); //just using a smaller page size for fun

        createCronJobs("success_finished", CronJobResult.SUCCESS, CronJobStatus.FINISHED, 1, 50);
        createCronJobs("success_aborted", CronJobResult.SUCCESS, CronJobStatus.ABORTED, 2, 50);
        createCronJobs("error_finished", CronJobResult.ERROR, CronJobStatus.FINISHED, 4, 50);
        createCronJobs("failure_aborted", CronJobResult.FAILURE, CronJobStatus.ABORTED, 8, 50);
        createCronJobs("failure_unknow", CronJobResult.FAILURE, CronJobStatus.UNKNOWN, 16, 50);

        assertEquals(currentExistingCJs + 31, countExistingCronJobs(null, null));
        assertEquals(currentExistingCJs + 3, countExistingCronJobs(CronJobResult.SUCCESS, null));
        assertEquals(currentExistingCJs + 10, countExistingCronJobs(null, CronJobStatus.ABORTED));
        assertEquals(currentExistingCJs + 16, countExistingCronJobs(CronJobResult.FAILURE, CronJobStatus.UNKNOWN));

        final Set<CronJobResult> results = new HashSet<CronJobResult>();
        results.add(CronJobResult.FAILURE);
        results.add(CronJobResult.ERROR);
        cuCJmi.setResult(results);

        final Set<CronJobStatus> statuses = new HashSet<CronJobStatus>();
        statuses.add(CronJobStatus.FINISHED);
        statuses.add(CronJobStatus.ABORTED);
        statuses.add(CronJobStatus.UNKNOWN);
        cuCJmi.setStatus(statuses);

        final PerformResult result = gmjp.perform(new CronJobModel());
        assertEquals(CronJobResult.SUCCESS, result.getResult());
        assertEquals(CronJobStatus.FINISHED, result.getStatus());

        assertEquals(currentExistingCJs + 3, countExistingCronJobs(null, null));
    }

    @Test
    public void testCleanupCronjob_ExclusionList() throws ImpExException {
        final int currentExistingCJs = countExistingCronJobs(null, null);

        createCronJobs("do_not_delete", CronJobResult.SUCCESS, CronJobStatus.FINISHED, 3, 50);
        createCronJobs("to_delete", CronJobResult.SUCCESS, CronJobStatus.FINISHED, 8, 50);

        assertEquals(currentExistingCJs + 11, countExistingCronJobs(CronJobResult.SUCCESS, CronJobStatus.FINISHED));

        final Set<String> excluded = new HashSet<String>();
        excluded.add("do_not_delete_0");
        excluded.add("do_not_delete_2");
        cuCJmi.setExcludedCronJobCodes(excluded);

        final PerformResult result = gmjp.perform(new CronJobModel());
        assertEquals(CronJobResult.SUCCESS, result.getResult());
        assertEquals(CronJobStatus.FINISHED, result.getStatus());

        assertEquals(currentExistingCJs + 2, countExistingCronJobs(null, null));

    }

    @Test
    public void testAbortOnErrorWithDummyList() {
        assertEquals("expect NO testItems in the db!", Integer.valueOf(0), countTestItems());
        assertFalse(checkForTestItemWithField("dummyitem_1"));
        for (int i = 0; i < 8; i++) {
            final TestItemModel testitem = modelService.create(TestItemModel.class);
            testitem.setTestDumpProperty("dummyitem_" + i);
        }
        modelService.saveAll();
        assertTrue(checkForTestItemWithField("dummyitem_1"));
        assertEquals(Integer.valueOf(8), countTestItems());

        final RemoveFirstSevenTestItemStrategy throwStrategy = new RemoveFirstSevenTestItemStrategy();
        gmjp.setMaintenanceCleanupStrategy(throwStrategy);
        gmjp.setAbortOnError(true);
        gmjp.setPageSize(3);

        try {
            TestUtils.disableFileAnalyzer("Expecting the DummyException here", 100);

            final PerformResult result = gmjp.perform(new CronJobModel());
            assertEquals(CronJobResult.ERROR, result.getResult());
            assertEquals(CronJobStatus.ABORTED, result.getStatus());

            assertEquals(Integer.valueOf(7), countTestItems());

            assertFalse(checkForTestItemWithField("dummyitem_0"));
            assertTrue(checkForTestItemWithField("dummyitem_1"));
        } finally {
            TestUtils.enableFileAnalyzer();
        }
    }

    @Test
    public void testNotAbortOnErrorWithDummyList() {
        assertEquals("expect NO testItems in the db!", Integer.valueOf(0), countTestItems());
        assertFalse(checkForTestItemWithField("dummyitem_1"));
        for (int i = 0; i < 8; i++) {
            final TestItemModel testitem = modelService.create(TestItemModel.class);
            testitem.setTestDumpProperty("dummyitem_" + i);
        }
        modelService.saveAll();
        assertTrue(checkForTestItemWithField("dummyitem_1"));
        assertEquals(Integer.valueOf(8), countTestItems());

        final RemoveFirstSevenTestItemStrategy throwStrategy = new RemoveFirstSevenTestItemStrategy();
        gmjp.setMaintenanceCleanupStrategy(throwStrategy);
        gmjp.setAbortOnError(false);
        gmjp.setPageSize(3);

        try {
            TestUtils.disableFileAnalyzer("Expecting the DummyException here", 100);
            final PerformResult result = gmjp.perform(new CronJobModel());
            assertEquals(CronJobResult.FAILURE, result.getResult());
            assertEquals(CronJobStatus.FINISHED, result.getStatus());

            assertEquals(Integer.valueOf(5), countTestItems());

            assertFalse(checkForTestItemWithField("dummyitem_0"));
            assertTrue(checkForTestItemWithField("dummyitem_1"));
            assertFalse(checkForTestItemWithField("dummyitem_3"));
            assertTrue(checkForTestItemWithField("dummyitem_4"));
            assertFalse(checkForTestItemWithField("dummyitem_6"));
            assertTrue(checkForTestItemWithField("dummyitem_7"));
        } finally {
            TestUtils.enableFileAnalyzer();
        }
    }

    @Test
    public void testSetIllegalValues() {
        try {
            cuCJmi.setResult(null);
            fail("should fail with IllegalArgumentException");
        } catch (final IllegalArgumentException e) {
            assertEquals("The CronJob result set must contains at least one value!", e.getMessage());
        }

        try {
            cuCJmi.setResult(new HashSet<CronJobResult>());
            fail("should fail with IllegalArgumentException");
        } catch (final IllegalArgumentException e) {
            assertEquals("The CronJob result set must contains at least one value!", e.getMessage());
        }

        try {
            cuCJmi.setStatus(null);
            fail("should fail with IllegalArgumentException");
        } catch (final IllegalArgumentException e) {
            assertEquals("The CronJob status set must contains at least one value!", e.getMessage());
        }

        try {
            cuCJmi.setStatus(new HashSet<CronJobStatus>());
            fail("should fail with IllegalArgumentException");
        } catch (final IllegalArgumentException e) {
            assertEquals("The CronJob status set must contains at least one value!", e.getMessage());
        }

        try {
            gmjp.setPageSize(-10);
            fail("should fail with IllegalArgumentException");
        } catch (final IllegalArgumentException e) {
            assertEquals("pagesize cannot be negative", e.getMessage());
        }

    }

    @Test
    public void testOverrideBeanValuesByJobThreeshold() throws ImpExException {
        final int currentExistingCJs = countExistingCronJobs(CronJobResult.SUCCESS, CronJobStatus.FINISHED);

        createCronJobs("too_young", CronJobResult.SUCCESS, CronJobStatus.FINISHED, 1, 1);
        createCronJobs("old", CronJobResult.SUCCESS, CronJobStatus.FINISHED, 7, 13);
        createCronJobs("very_old", CronJobResult.SUCCESS, CronJobStatus.FINISHED, 113, 100);
        assertEquals(currentExistingCJs + 121,
                countExistingCronJobs(CronJobResult.SUCCESS, CronJobStatus.FINISHED));

        final CronJobModel cjm = new CronJobModel();
        final MaintenanceCleanupJobModel the_job = new MaintenanceCleanupJobModel();

        the_job.setThreshold(Integer.valueOf(4));
        cjm.setJob(the_job);

        final PerformResult result = gmjp.perform(cjm);
        assertEquals(CronJobResult.SUCCESS, result.getResult());
        assertEquals(CronJobStatus.FINISHED, result.getStatus());

        assertEquals(currentExistingCJs + 1, countExistingCronJobs(CronJobResult.SUCCESS, CronJobStatus.FINISHED));
    }

    @Test
    public void testOverrideBeanValuesByJobThreesholdWithNullValue() throws ImpExException {
        final int currentExistingCJs = countExistingCronJobs(CronJobResult.SUCCESS, CronJobStatus.FINISHED);

        createCronJobs("young", CronJobResult.SUCCESS, CronJobStatus.FINISHED, 5, 13);
        createCronJobs("old", CronJobResult.SUCCESS, CronJobStatus.FINISHED, 5, 15);
        assertEquals(currentExistingCJs + 10, countExistingCronJobs(CronJobResult.SUCCESS, CronJobStatus.FINISHED));

        final CronJobModel cjm = new CronJobModel();
        final MaintenanceCleanupJobModel the_job = new MaintenanceCleanupJobModel();

        the_job.setThreshold(null); //bean has value set to 14, see setup() method
        cjm.setJob(the_job);

        final PerformResult result = gmjp.perform(cjm);
        assertEquals(CronJobResult.SUCCESS, result.getResult());
        assertEquals(CronJobStatus.FINISHED, result.getStatus());

        assertEquals(currentExistingCJs + 5, countExistingCronJobs(CronJobResult.SUCCESS, CronJobStatus.FINISHED));
    }

    @Test
    public void testOverrideBeanValuesByJobThreesholdWithNegativeValue() throws ImpExException {
        final CronJobModel cjm = new CronJobModel();
        final MaintenanceCleanupJobModel the_job = new MaintenanceCleanupJobModel();

        the_job.setThreshold(Integer.valueOf(-10)); //the performable will complain
        //the beanvalue is correct, but after platform is started up the job can overwrite it
        //TODO: set constraints for the job?!?

        cjm.setJob(the_job);
        gmjp.setAbortOnError(true);

        try {
            gmjp.perform(cjm);
            fail("should fail with IllegalArgumentException");
        } catch (final IllegalArgumentException e) {
            assertEquals("Cannot set negative value for daysold", e.getMessage());
        }
    }

    @Test
    public void testOverrideBeanValuesByJobCronjobType() throws ImpExException {
        final int currentExistingCJs = countExistingCronJobs(CronJobResult.SUCCESS, CronJobStatus.FINISHED);

        createCronJobs("cleanupcronjobs", CronJobResult.SUCCESS, CronJobStatus.FINISHED, 5, 15, "CleanupCronJob");
        createCronJobs("normaljobs", CronJobResult.SUCCESS, CronJobStatus.FINISHED, 5, 15);
        assertEquals(currentExistingCJs + 10, countExistingCronJobs(CronJobResult.SUCCESS, CronJobStatus.FINISHED));

        //10 jobs older than 14 days, now removing only CleanupCronJob

        final CronJobModel cjm = new CronJobModel();
        final MaintenanceCleanupJobModel the_job = new MaintenanceCleanupJobModel();

        the_job.setSearchType(typeService.getComposedTypeForCode("CleanupCronJob"));
        cjm.setJob(the_job);

        final PerformResult result = gmjp.perform(cjm);
        assertEquals(CronJobResult.SUCCESS, result.getResult());
        assertEquals(CronJobStatus.FINISHED, result.getStatus());

        assertEquals(currentExistingCJs + 5, countExistingCronJobs(CronJobResult.SUCCESS, CronJobStatus.FINISHED));

    }

    @Test
    public void testOverrideBeanValuesByJobCronjobTypeNullValue() throws ImpExException {
        final int currentExistingCJs = countExistingCronJobs(CronJobResult.SUCCESS, CronJobStatus.FINISHED);

        createCronJobs("cleanupcronjobs", CronJobResult.SUCCESS, CronJobStatus.FINISHED, 5, 15, "CleanupCronJob");
        createCronJobs("normaljobs", CronJobResult.SUCCESS, CronJobStatus.FINISHED, 5, 15);
        assertEquals(currentExistingCJs + 10, countExistingCronJobs(CronJobResult.SUCCESS, CronJobStatus.FINISHED));

        //10 jobs older than 14 days, now removing only CleanupCronJob

        final CronJobModel cjm = new CronJobModel();
        final MaintenanceCleanupJobModel the_job = new MaintenanceCleanupJobModel();

        the_job.setSearchType(null); //the default value which is the normal CronJobModel will kick in
        cjm.setJob(the_job);

        final PerformResult result = gmjp.perform(cjm);
        assertEquals(CronJobResult.SUCCESS, result.getResult());
        assertEquals(CronJobStatus.FINISHED, result.getStatus());

        assertEquals(currentExistingCJs, countExistingCronJobs(CronJobResult.SUCCESS, CronJobStatus.FINISHED));
    }

    @Test
    public void testOverrideBeanValuesByJobCronjobTypeWithNotAssignableComposedType() throws ImpExException {
        final CronJobModel cjm = new CronJobModel();
        final MaintenanceCleanupJobModel the_job = new MaintenanceCleanupJobModel();

        the_job.setSearchType(typeService.getComposedTypeForCode(ProductModel._TYPECODE));
        cjm.setJob(the_job);

        try {
            gmjp.perform(cjm);
            fail("should fail with IllegalArgumentException");
        } catch (final IllegalArgumentException e) {
            assertEquals(ProductModel._TYPECODE + " must be a subtype of " + CronJobModel._TYPECODE,
                    e.getMessage());
        }
    }

    private void createCronJobs(final String codeprefix, final CronJobResult cjr, final CronJobStatus cjs,
            final int count, final int daysold) throws ImpExException {
        createCronJobs(codeprefix, cjr, cjs, count, daysold, "CronJob");
    }

    private void createCronJobs(final String codeprefix, final CronJobResult cjr, final CronJobStatus cjs,
            final int count, final int daysold, final String cronjobtype) throws ImpExException {
        final StringBuffer cronjobbuffer = new StringBuffer(1000);
        cronjobbuffer.append(
                "insert_update " + cronjobtype + ";code[unique=true];job(code);status(code)[forceWrite=true];");
        cronjobbuffer.append("result(code)[forceWrite=true];startTime[forceWrite=true,dateformat=dd-MM-yyyy];");
        cronjobbuffer.append("endTime[forceWrite=true,dateformat=dd-MM-yyyy] ").append(CharUtils.LF);

        for (int index = 0; index < count; index++) {
            final DateTime start = new DateTime().minusDays(daysold).minusHours(1);
            final DateTime end = new DateTime().minusDays(daysold);
            cronjobbuffer
                    .append(";" + codeprefix + "_" + index + ";cleanupCronJobsPerformable;" + cjs.getCode() + ";");
            cronjobbuffer.append(cjr.getCode() + ";" + start.getDayOfMonth() + "-" + start.getMonthOfYear() + "-"
                    + start.getYear());
            cronjobbuffer.append(";" + end.getDayOfMonth() + "-" + end.getMonthOfYear() + "-" + end.getYear())
                    .append(CharUtils.LF);
        }
        ImpExManager.getInstance().importDataLight(new CSVReader(cronjobbuffer.toString()), true);
    }

    private int countExistingCronJobs(final CronJobResult cjr, final CronJobStatus cjs) {
        final Map<String, Object> params = new HashMap<String, Object>();
        params.put("result", cjr);
        params.put("status", cjs);
        final StringBuffer query = new StringBuffer("select {pk} from {cronjob} ");
        query.append(cjr != null || cjs != null ? "where " : "");
        query.append(cjs == null ? " " : "{status}=?status ");
        query.append(cjr != null && cjs != null ? "and " : "");
        query.append(cjr == null ? " " : "{result}=?result ");

        final FlexibleSearchQuery fsq = new FlexibleSearchQuery(query.toString(), params);
        return flexibleSearchService.search(fsq).getTotalCount();
    }

    private Integer countTestItems() {
        final FlexibleSearchQuery fsq = new FlexibleSearchQuery("select count({pk}) from {testitem}");
        fsq.setResultClassList(Arrays.asList(Integer.class));
        return (Integer) flexibleSearchService.search(fsq).getResult().get(0);
    }

    private boolean checkForTestItemWithField(final String value) {
        final FlexibleSearchQuery fsq = new FlexibleSearchQuery(
                "select {pk} from {testitem} where {testDumpProperty} = ?value",
                Collections.singletonMap("value", value));
        fsq.setResultClassList(Arrays.asList(TestItem.class));
        return flexibleSearchService.search(fsq).getTotalCount() > 0;
    }

    private class RemoveFirstSevenTestItemStrategy
            implements MaintenanceCleanupStrategy<TestItemModel, CronJobModel> {

        @Override
        public FlexibleSearchQuery createFetchQuery(final CronJobModel cjm) {
            return new FlexibleSearchQuery("select {pk} from {testitem} order by {testDumpProperty} asc");
        }

        @Override
        public void process(final List<TestItemModel> elements) {
            for (int i = 0; i < elements.size(); i++) {
                if (i < 1) {
                    modelService.remove(elements.get(i));
                } else {
                    throw new DummyException("got " + elements.get(i).getTestDumpProperty()
                            + " - throwing now the expected DummyException");
                }
            }
        }

    }

    private class DummyException extends RuntimeException {
        public DummyException(final String reason) {
            super(reason);
        }
    }
}