All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bonitasoft.engine.scheduler.impl.JobServiceImpl Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (C) 2019 Bonitasoft S.A.
 * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble
 * This library is free software; you can redistribute it and/or modify it under the terms
 * of the GNU Lesser General Public License as published by the Free Software Foundation
 * version 2.1 of the License.
 * This library 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 Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public License along with this
 * program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
 * Floor, Boston, MA 02110-1301, USA.
 **/
package org.bonitasoft.engine.scheduler.impl;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import lombok.extern.slf4j.Slf4j;
import org.bonitasoft.engine.commons.exceptions.SBonitaException;
import org.bonitasoft.engine.events.EventService;
import org.bonitasoft.engine.persistence.FilterOption;
import org.bonitasoft.engine.persistence.OrderByOption;
import org.bonitasoft.engine.persistence.OrderByType;
import org.bonitasoft.engine.persistence.PersistentObject;
import org.bonitasoft.engine.persistence.QueryOptions;
import org.bonitasoft.engine.persistence.ReadPersistenceService;
import org.bonitasoft.engine.persistence.SBonitaReadException;
import org.bonitasoft.engine.persistence.SelectListDescriptor;
import org.bonitasoft.engine.recorder.Recorder;
import org.bonitasoft.engine.recorder.SRecorderException;
import org.bonitasoft.engine.recorder.model.DeleteRecord;
import org.bonitasoft.engine.recorder.model.EntityUpdateDescriptor;
import org.bonitasoft.engine.recorder.model.InsertRecord;
import org.bonitasoft.engine.recorder.model.UpdateRecord;
import org.bonitasoft.engine.scheduler.JobService;
import org.bonitasoft.engine.scheduler.exception.failedJob.SFailedJobReadException;
import org.bonitasoft.engine.scheduler.exception.jobDescriptor.SJobDescriptorCreationException;
import org.bonitasoft.engine.scheduler.exception.jobDescriptor.SJobDescriptorDeletionException;
import org.bonitasoft.engine.scheduler.exception.jobDescriptor.SJobDescriptorReadException;
import org.bonitasoft.engine.scheduler.exception.jobLog.SJobLogCreationException;
import org.bonitasoft.engine.scheduler.exception.jobLog.SJobLogDeletionException;
import org.bonitasoft.engine.scheduler.exception.jobLog.SJobLogUpdatingException;
import org.bonitasoft.engine.scheduler.exception.jobParameter.SJobParameterCreationException;
import org.bonitasoft.engine.scheduler.exception.jobParameter.SJobParameterDeletionException;
import org.bonitasoft.engine.scheduler.exception.jobParameter.SJobParameterNotFoundException;
import org.bonitasoft.engine.scheduler.exception.jobParameter.SJobParameterReadException;
import org.bonitasoft.engine.scheduler.model.SFailedJob;
import org.bonitasoft.engine.scheduler.model.SJobDescriptor;
import org.bonitasoft.engine.scheduler.model.SJobLog;
import org.bonitasoft.engine.scheduler.model.SJobParameter;
import org.bonitasoft.engine.scheduler.recorder.SelectDescriptorBuilder;

/**
 * @author Celine Souchet
 * @author Matthieu Chaffotte
 */
@Slf4j
public class JobServiceImpl implements JobService {

    private final EventService eventService;

    private final Recorder recorder;

    private final ReadPersistenceService readPersistenceService;

    public JobServiceImpl(final EventService eventService, final Recorder recorder,
            final ReadPersistenceService readPersistenceService) {
        this.readPersistenceService = readPersistenceService;
        this.eventService = eventService;
        this.recorder = recorder;
    }

    @Override
    public SJobDescriptor createJobDescriptor(final SJobDescriptor sJobDescriptor, final long tenantId)
            throws SJobDescriptorCreationException {
        if (sJobDescriptor == null) {
            throw new IllegalArgumentException("The job descriptor is null");
        } else if (sJobDescriptor.getJobName() == null) {
            throw new IllegalArgumentException("The job name is null");
        }

        // Set the tenant manually on the object because it will be serialized
        final SJobDescriptor sJobDescriptorToRecord = new SJobDescriptor(sJobDescriptor.getJobClassName(),
                sJobDescriptor.getJobName(),
                sJobDescriptor.getDescription());
        sJobDescriptorToRecord.setTenantId(tenantId);

        try {
            create(sJobDescriptorToRecord, JOB_DESCRIPTOR);
        } catch (final SRecorderException sre) {
            throw new SJobDescriptorCreationException(sre);
        }
        return sJobDescriptorToRecord;
    }

    @Override
    public void deleteJobDescriptor(final long id) throws SJobDescriptorReadException, SJobDescriptorDeletionException {
        final SJobDescriptor sJobDescriptor = getJobDescriptor(id);
        if (sJobDescriptor == null) {
            if (log.isTraceEnabled()) {
                final StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.append("jobDescriptor with id");
                stringBuilder.append(id);
                stringBuilder.append(" already deleted, ignore it");
                log.trace(stringBuilder.toString());
            }
        } else {
            deleteJobDescriptor(sJobDescriptor);
        }
    }

    @Override
    public void deleteJobDescriptor(final SJobDescriptor sJobDescriptor) throws SJobDescriptorDeletionException {
        if (sJobDescriptor == null) {
            throw new IllegalArgumentException("The job descriptor is null");
        }
        try {
            delete(sJobDescriptor, JOB_DESCRIPTOR);
        } catch (final SBonitaException e) {
            throw new SJobDescriptorDeletionException(e);
        }
    }

    @Override
    public SJobDescriptor getJobDescriptor(final long id) throws SJobDescriptorReadException {
        try {
            final SJobDescriptor sJobDescriptor = readPersistenceService
                    .selectById(SelectDescriptorBuilder.getElementById(SJobDescriptor.class,
                            "SJobDescriptor", id));
            return sJobDescriptor;
        } catch (final SBonitaReadException sbre) {
            throw new SJobDescriptorReadException(sbre);
        }
    }

    @Override
    public long getNumberOfJobDescriptors(final QueryOptions queryOptions) throws SBonitaReadException {
        return readPersistenceService.getNumberOfEntities(SJobDescriptor.class, queryOptions, null);
    }

    @Override
    public List searchJobDescriptors(final QueryOptions queryOptions) throws SBonitaReadException {
        return readPersistenceService.searchEntity(SJobDescriptor.class, queryOptions, null);
    }

    @Override
    public List createJobParameters(final List sJobParameters, final long tenantId,
            final long jobDescriptorId)
            throws SJobParameterCreationException {
        final List createdSJobParameters = new ArrayList();
        if (sJobParameters != null) {
            for (final SJobParameter sJobParameter : sJobParameters) {
                createdSJobParameters.add(createJobParameter(sJobParameter, tenantId, jobDescriptorId));
            }
        }
        return createdSJobParameters;
    }

    @Override
    public List setJobParameters(final long tenantId, final long jobDescriptorId,
            final List parameters)
            throws SJobParameterCreationException {
        deleteAllJobParameters(jobDescriptorId);
        return createJobParameters(parameters, tenantId, jobDescriptorId);
    }

    protected void deleteAllJobParameters(final long jobDescriptorId) throws SJobParameterCreationException {
        try {
            for (SJobParameter jobParameter : getJobParameters(jobDescriptorId)) {
                deleteJobParameter(jobParameter);
            }
        } catch (final SBonitaException sbe) {
            throw new SJobParameterCreationException(sbe);
        }
    }

    @Override
    public SJobParameter createJobParameter(final SJobParameter sJobParameter, final long tenantId,
            final long jobDescriptorId)
            throws SJobParameterCreationException {
        if (sJobParameter == null) {
            throw new IllegalArgumentException("The job descriptor is null");
        }

        // Set the tenant manually on the object because it will be serialized
        final SJobParameter sJobParameterToRecord = SJobParameter.builder()
                .key(sJobParameter.getKey())
                .value(sJobParameter.getValue()).jobDescriptorId(jobDescriptorId).build();
        sJobParameterToRecord.setTenantId(tenantId);

        try {
            create(sJobParameterToRecord, JOB_PARAMETER);
        } catch (final SRecorderException sre) {
            throw new SJobParameterCreationException(sre);
        }
        return sJobParameter;
    }

    @Override
    public void deleteJobParameter(final long id)
            throws SJobParameterNotFoundException, SJobParameterReadException, SJobParameterDeletionException {
        final SJobParameter sJobParameter = getJobParameter(id);
        deleteJobParameter(sJobParameter);
    }

    @Override
    public void deleteJobParameter(final SJobParameter sJobParameter) throws SJobParameterDeletionException {
        try {
            delete(sJobParameter, JOB_PARAMETER);
        } catch (final SBonitaException e) {
            throw new SJobParameterDeletionException(e);
        }
    }

    @Override
    public SJobParameter getJobParameter(final long id)
            throws SJobParameterNotFoundException, SJobParameterReadException {
        try {
            final SJobParameter sJobParameter = readPersistenceService
                    .selectById(SelectDescriptorBuilder.getElementById(SJobParameter.class, "SJobParameter",
                            id));
            if (sJobParameter == null) {
                throw new SJobParameterNotFoundException(id);
            }
            return sJobParameter;
        } catch (final SBonitaReadException sbre) {
            throw new SJobParameterReadException(sbre);
        }
    }

    @Override
    public List getJobParameters(Long jobDescriptorId) throws SBonitaReadException {
        Map parameters = Collections. singletonMap("jobDescriptorId", jobDescriptorId);
        return readPersistenceService.selectList(new SelectListDescriptor("getJobParameters", parameters,
                SJobParameter.class, QueryOptions.countQueryOptions()));
    }

    @Override
    public SJobLog createJobLog(final SJobLog sJobLog) throws SJobLogCreationException {
        try {
            create(sJobLog, JOB_LOG);
        } catch (final SRecorderException sre) {
            throw new SJobLogCreationException(sre);
        }
        return sJobLog;
    }

    @Override
    public void deleteJobLog(final long id) throws SJobLogDeletionException, SBonitaReadException {
        final SJobLog sJobLog = getJobLog(id);
        if (sJobLog != null) {
            deleteJobLog(sJobLog);
        }
    }

    @Override
    public void deleteJobLog(final SJobLog sJobLog) throws SJobLogDeletionException {
        try {
            delete(sJobLog, JOB_LOG);
        } catch (final SBonitaException e) {
            throw new SJobLogDeletionException(e);
        }
    }

    @Override
    public void deleteJobLogs(final long jobDescriptorId) throws SJobLogDeletionException, SBonitaReadException {
        List jobLogs = getJobLogs(jobDescriptorId, 0, 100);
        while (!jobLogs.isEmpty()) {
            deleteJobLogs(jobLogs);
            jobLogs = getJobLogs(jobDescriptorId, 0, 100);
        }
    }

    private void deleteJobLogs(final List jobLogs) throws SJobLogDeletionException {
        for (final SJobLog sJobLog : jobLogs) {
            deleteJobLog(sJobLog);
        }
    }

    @Override
    public List getJobLogs(final long jobDescriptorId, final int fromIndex, final int maxResults)
            throws SBonitaReadException {
        final FilterOption filter = new FilterOption(SJobLog.class, "jobDescriptorId", jobDescriptorId);
        final OrderByOption orderByOption = new OrderByOption(SJobLog.class, "jobDescriptorId", OrderByType.ASC);
        final QueryOptions options = new QueryOptions(fromIndex, maxResults, Arrays.asList(orderByOption),
                Arrays.asList(filter), null);
        return searchJobLogs(options);
    }

    @Override
    public SJobLog getJobLog(final long id) throws SBonitaReadException {
        return readPersistenceService.selectById(SelectDescriptorBuilder.getElementById(SJobLog.class, "SJobLog", id));
    }

    @Override
    public long getNumberOfJobLogs(final QueryOptions queryOptions) throws SBonitaReadException {
        return readPersistenceService.getNumberOfEntities(SJobLog.class, queryOptions, null);
    }

    @Override
    public List searchJobLogs(final QueryOptions queryOptions) throws SBonitaReadException {
        return readPersistenceService.searchEntity(SJobLog.class, queryOptions, null);
    }

    private void delete(final PersistentObject persistentObject, final String eventType) throws SRecorderException {
        recorder.recordDelete(new DeleteRecord(persistentObject), eventType);
    }

    private void create(final PersistentObject persistentObject, final String eventType) throws SRecorderException {
        recorder.recordInsert(new InsertRecord(persistentObject), eventType);
    }

    @Override
    public List getFailedJobs(final int startIndex, final int maxResults) throws SFailedJobReadException {
        final QueryOptions queryOptions = new QueryOptions(startIndex, maxResults);
        try {
            return readPersistenceService.selectList(SelectDescriptorBuilder.getFailedJobs(queryOptions));
        } catch (final SBonitaReadException sbre) {
            throw new SFailedJobReadException(sbre);
        }
    }

    @Override
    public void deleteJobDescriptorByJobName(final String jobName) throws SJobDescriptorDeletionException {
        final List filters = new ArrayList();
        filters.add(new FilterOption(SJobDescriptor.class, "jobName", jobName));
        final List orders = Arrays
                .asList(new OrderByOption(SJobDescriptor.class, "id", OrderByType.ASC));
        final QueryOptions queryOptions = new QueryOptions(0, 1, orders, filters, null);
        try {
            final List jobDescriptors = searchJobDescriptors(queryOptions);
            if (!jobDescriptors.isEmpty()) {
                deleteJobDescriptor(jobDescriptors.get(0));
            }
        } catch (final SBonitaReadException e) {
            throw new SJobDescriptorDeletionException(
                    "Job " + jobName + " not found, can't delete corresponding job descriptor");
        }
    }

    @Override
    public void deleteAllJobDescriptors() throws SJobDescriptorDeletionException {
        final List filters = new ArrayList();
        final QueryOptions queryOptions = new QueryOptions(0, 100, null, filters, null);
        try {
            final List jobDescriptors = searchJobDescriptors(queryOptions);
            for (final SJobDescriptor sJobDescriptor : jobDescriptors) {
                deleteJobDescriptor(sJobDescriptor);
            }
        } catch (final SBonitaReadException e) {
            throw new SJobDescriptorDeletionException(e);
        }
    }

    @Override
    public void updateJobLog(final SJobLog jobLog, final EntityUpdateDescriptor descriptor)
            throws SJobLogUpdatingException {
        try {
            recorder.recordUpdate(UpdateRecord.buildSetFields(jobLog, descriptor), JOB_LOG);
        } catch (final SRecorderException e) {
            throw new SJobLogUpdatingException(e);
        }
    }

    @Override
    public void logJobError(final Throwable jobException, final Long jobDescriptorId)
            throws SBonitaReadException, SJobLogUpdatingException,
            SJobLogCreationException, SJobDescriptorReadException {
        final List jobLogs = getJobLogs(jobDescriptorId, 0, 1);
        if (!jobLogs.isEmpty()) {
            final SJobLog jobLog = jobLogs.get(0);
            final EntityUpdateDescriptor descriptor = new EntityUpdateDescriptor();
            final StringWriter exceptionWriter = new StringWriter();
            jobException.printStackTrace(new PrintWriter(exceptionWriter));
            descriptor.addField("lastMessage", exceptionWriter.toString());
            descriptor.addField("lastUpdateDate", System.currentTimeMillis());
            descriptor.addField("retryNumber", jobLog.getRetryNumber() + 1);
            updateJobLog(jobLog, descriptor);
        } else {
            createJobLog(jobException, jobDescriptorId);
        }
    }

    public void createJobLog(final Throwable jobException, final Long jobDescriptorId)
            throws SJobLogCreationException, SJobDescriptorReadException {
        SJobDescriptor jobDescriptor = getJobDescriptor(jobDescriptorId);
        if (jobDescriptor != null) {
            final SJobLog jobLog = new SJobLog(jobDescriptorId);
            jobLog.setLastMessage(getStackTrace(jobException));
            jobLog.setRetryNumber(0L);
            jobLog.setLastUpdateDate(System.currentTimeMillis());
            createJobLog(jobLog);
        } else {
            log.warn("Impossible to mark the job with id '"
                    + jobDescriptorId
                    + "' as failed because no job was found for this identifier. It was probably removed just after its failure and before this action.");
        }
    }

    private String getStackTrace(final Throwable jobException) {
        final StringWriter exceptionWriter = new StringWriter();
        jobException.printStackTrace(new PrintWriter(exceptionWriter));
        return exceptionWriter.toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy