Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

business-calendar #3686

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.jbpm.process.core.timer;
package org.kie.kogito.calendar;

import java.util.Date;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import org.kie.kogito.KogitoConfig;
import org.kie.kogito.auth.IdentityProvider;
import org.kie.kogito.calendar.BusinessCalendar;
import org.kie.kogito.jobs.JobsService;
import org.kie.kogito.signal.SignalManagerHub;
import org.kie.kogito.uow.UnitOfWorkManager;
Expand All @@ -38,4 +39,6 @@ public interface ProcessConfig extends KogitoConfig {
ProcessVersionResolver versionResolver();

IdentityProvider identityProvider();

BusinessCalendar getBusinessCalendar();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.jbpm.process.core.constants;
Abhitocode marked this conversation as resolved.
Show resolved Hide resolved

public class CalendarConstants {
public static final String BUSINESS_CALENDAR_PATH = "calendar.properties";
gitgabrio marked this conversation as resolved.
Show resolved Hide resolved
public static final String BUSINESS_CALENDAR_ENVIRONMENT_KEY = "jbpm.business.calendar";
Abhitocode marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
*/
package org.jbpm.process.core.timer;

import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.time.Duration;
Expand All @@ -35,10 +34,13 @@
import java.util.regex.Matcher;

import org.jbpm.util.PatternConstants;
import org.kie.kogito.calendar.BusinessCalendar;
Abhitocode marked this conversation as resolved.
Show resolved Hide resolved
import org.kie.kogito.timer.SessionClock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.jbpm.process.core.constants.CalendarConstants.BUSINESS_CALENDAR_PATH;

/**
* Default implementation of BusinessCalendar interface that is configured with properties.
* Following are supported properties:
Expand Down Expand Up @@ -103,38 +105,26 @@ public class BusinessCalendarImpl implements BusinessCalendar {
public static final String WEEKEND_DAYS = "business.weekend.days";
public static final String TIMEZONE = "business.cal.timezone";

private static final String DEFAULT_PROPERTIES_NAME = "/jbpm.business.calendar.properties";

public BusinessCalendarImpl() {
Abhitocode marked this conversation as resolved.
Show resolved Hide resolved
String propertiesLocation = System.getProperty("jbpm.business.calendar.properties");

if (propertiesLocation == null) {
propertiesLocation = DEFAULT_PROPERTIES_NAME;
}
businessCalendarConfiguration = new Properties();

InputStream in = this.getClass().getResourceAsStream(propertiesLocation);
if (in != null) {

try {
businessCalendarConfiguration.load(in);
} catch (IOException e) {
logger.error("Error while loading properties for business calendar", e);

}
}
init();

this(null);
}

public BusinessCalendarImpl(Properties configuration) {
this.businessCalendarConfiguration = configuration;
init();
this(configuration, null);
}

public BusinessCalendarImpl(Properties configuration, SessionClock clock) {
this.businessCalendarConfiguration = configuration;
this.clock = clock;
if (configuration == null) {
try (InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(BUSINESS_CALENDAR_PATH)) {
businessCalendarConfiguration = new Properties();
businessCalendarConfiguration.load(is);
} catch (Exception e) {
logger.error("Error while loading properties for business calendar", e);
Copy link
Contributor

@gitgabrio gitgabrio Oct 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi
if the IOException is thrown here, the businessCalendarConfiguration is basically empty - i.e. calendar properties are not loaded... and this should not be hided, because the application will misbehave.
At line 133, businessCalendarConfiguration is != null, so the code will go to

getPropertyAsInt(DAYS_PER_WEEK, "5"); ->

String value = businessCalendarConfiguration.getProperty(propertyName, defaultValue); return Integer.parseInt(value);

I may be wrong, but I've the impression it is going to fail miserably.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated I/O Exception

Copy link
Contributor

@gitgabrio gitgabrio Oct 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Abhitocode . Now there is a domain issue to solve:
is the calendar.properties file absolutely required or not ?
IF it is needed/required, then the application should throw an exception back when it fails to load
If, on the other side, is optional, then the code should first check if it is present and then, eventually, try to load it.
The goal is that our code should reflect "exactly" the logic that is meant to implement: am I clear ? Does this make sense ? <- @martinweiler

}
} else {
this.businessCalendarConfiguration = configuration;
}
init();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;

import org.drools.core.common.EndOperationListener;
import org.drools.core.common.InternalAgenda;
Expand Down Expand Up @@ -53,11 +54,15 @@
import org.kie.api.runtime.rule.ViewChangedEventListener;
import org.kie.api.time.SessionClock;
import org.kie.kogito.Application;
import org.kie.kogito.calendar.BusinessCalendar;
import org.kie.kogito.internal.process.event.KogitoProcessEventSupport;
import org.kie.kogito.internal.process.runtime.KogitoProcessInstance;
import org.kie.kogito.internal.process.runtime.KogitoProcessRuntime;
import org.kie.kogito.internal.process.workitem.KogitoWorkItemManager;
import org.kie.kogito.jobs.JobsService;
import org.kie.kogito.process.ProcessConfig;

import static org.jbpm.process.core.constants.CalendarConstants.BUSINESS_CALENDAR_ENVIRONMENT_KEY;

/**
* A severely limited implementation of the WorkingMemory interface.
Expand All @@ -72,6 +77,10 @@ class DummyKnowledgeRuntime implements InternalKnowledgeRuntime, KogitoProcessRu
this.processRuntime = processRuntime;
this.environment = new EnvironmentImpl();
// register codegen-based node instances factories
BusinessCalendar calendar = processRuntime.getApplication().config().get(ProcessConfig.class).getBusinessCalendar();
Abhitocode marked this conversation as resolved.
Show resolved Hide resolved
if (Objects.nonNull(calendar)) {
environment.set(BUSINESS_CALENDAR_ENVIRONMENT_KEY, calendar);
}
environment.set("NodeInstanceFactoryRegistry", new CodegenNodeInstanceFactoryRegistry());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
import org.drools.core.phreak.PropagationEntry;
import org.jbpm.process.core.event.EventFilter;
import org.jbpm.process.core.event.EventTypeFilter;
import org.jbpm.process.core.timer.BusinessCalendar;
import org.jbpm.process.core.timer.DateTimeUtils;
import org.jbpm.process.core.timer.Timer;
import org.jbpm.ruleflow.core.RuleFlowProcess;
Expand All @@ -52,6 +51,7 @@
import org.kie.internal.process.CorrelationKey;
import org.kie.internal.runtime.StatefulKnowledgeSession;
import org.kie.kogito.Application;
import org.kie.kogito.calendar.BusinessCalendar;
import org.kie.kogito.internal.process.runtime.KogitoProcessInstance;
import org.kie.kogito.internal.process.workitem.KogitoWorkItemManager;
import org.kie.kogito.jobs.DurationExpirationTime;
Expand All @@ -64,6 +64,7 @@
import org.kie.kogito.signal.SignalManager;
import org.kie.kogito.uow.UnitOfWorkManager;

import static org.jbpm.process.core.constants.CalendarConstants.BUSINESS_CALENDAR_ENVIRONMENT_KEY;
import static org.jbpm.ruleflow.core.Metadata.TRIGGER_MAPPING_INPUT;

public class LightProcessRuntime extends AbstractProcessRuntime {
Expand Down Expand Up @@ -426,8 +427,8 @@ public boolean isActive() {

protected ExpirationTime createTimerInstance(Timer timer, InternalKnowledgeRuntime kruntime) {

if (kruntime != null && kruntime.getEnvironment().get("jbpm.business.calendar") != null) {
BusinessCalendar businessCalendar = (BusinessCalendar) kruntime.getEnvironment().get("jbpm.business.calendar");
if (kruntime != null && kruntime.getEnvironment().get(BUSINESS_CALENDAR_ENVIRONMENT_KEY) != null) {
BusinessCalendar businessCalendar = (BusinessCalendar) kruntime.getEnvironment().get(BUSINESS_CALENDAR_ENVIRONMENT_KEY);

long delay = businessCalendar.calculateBusinessTimeAsDuration(timer.getDelay());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
import org.drools.core.time.impl.ThreadSafeTrackableTimeJobFactoryManager;
import org.jbpm.process.core.event.EventFilter;
import org.jbpm.process.core.event.EventTypeFilter;
import org.jbpm.process.core.timer.BusinessCalendar;
import org.jbpm.process.core.timer.DateTimeUtils;
import org.jbpm.process.core.timer.Timer;
import org.jbpm.process.instance.event.DefaultSignalManagerFactory;
Expand Down Expand Up @@ -64,6 +63,7 @@
import org.kie.internal.process.CorrelationKey;
import org.kie.internal.runtime.StatefulKnowledgeSession;
import org.kie.kogito.Application;
import org.kie.kogito.calendar.BusinessCalendar;
import org.kie.kogito.internal.process.runtime.KogitoProcessInstance;
import org.kie.kogito.internal.process.runtime.KogitoProcessRuntime;
import org.kie.kogito.jobs.DurationExpirationTime;
Expand All @@ -78,6 +78,7 @@
import org.kie.kogito.signal.SignalManager;
import org.kie.kogito.uow.UnitOfWorkManager;

import static org.jbpm.process.core.constants.CalendarConstants.BUSINESS_CALENDAR_ENVIRONMENT_KEY;
import static org.jbpm.ruleflow.core.Metadata.TRIGGER_MAPPING_INPUT;

public class ProcessRuntimeImpl extends AbstractProcessRuntime {
Expand Down Expand Up @@ -409,8 +410,8 @@ public boolean isActive() {
}

protected ExpirationTime createTimerInstance(Timer timer, InternalKnowledgeRuntime kruntime) {
if (kruntime != null && kruntime.getEnvironment().get("jbpm.business.calendar") != null) {
BusinessCalendar businessCalendar = (BusinessCalendar) kruntime.getEnvironment().get("jbpm.business.calendar");
if (kruntime != null && kruntime.getEnvironment().get(BUSINESS_CALENDAR_ENVIRONMENT_KEY) != null) {
BusinessCalendar businessCalendar = (BusinessCalendar) kruntime.getEnvironment().get(BUSINESS_CALENDAR_ENVIRONMENT_KEY);

long delay = businessCalendar.calculateBusinessTimeAsDuration(timer.getDelay());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
import org.jbpm.process.core.ContextResolver;
import org.jbpm.process.core.context.variable.Variable;
import org.jbpm.process.core.context.variable.VariableScope;
import org.jbpm.process.core.timer.BusinessCalendar;
import org.jbpm.process.core.timer.DateTimeUtils;
import org.jbpm.process.core.timer.Timer;
import org.jbpm.process.instance.ContextInstance;
Expand Down Expand Up @@ -81,6 +80,7 @@
import org.kie.api.definition.process.WorkflowElementIdentifier;
import org.kie.api.runtime.rule.AgendaFilter;
import org.kie.internal.process.CorrelationKey;
import org.kie.kogito.calendar.BusinessCalendar;
import org.kie.kogito.internal.process.event.KogitoEventListener;
import org.kie.kogito.internal.process.runtime.KogitoNodeInstance;
import org.kie.kogito.internal.process.runtime.KogitoNodeInstanceContainer;
Expand All @@ -102,6 +102,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.jbpm.process.core.constants.CalendarConstants.BUSINESS_CALENDAR_ENVIRONMENT_KEY;
import static org.jbpm.ruleflow.core.Metadata.COMPENSATION;
import static org.jbpm.ruleflow.core.Metadata.CONDITION;
import static org.jbpm.ruleflow.core.Metadata.CORRELATION_KEY;
Expand Down Expand Up @@ -565,8 +566,8 @@ public TimerInstance configureSLATimer(String slaDueDateExpression) {
logger.debug("SLA due date is set to {}", slaDueDateExpression);
InternalKnowledgeRuntime kruntime = getKnowledgeRuntime();
long duration;
if (kruntime.getEnvironment().get("jbpm.business.calendar") != null) {
BusinessCalendar businessCalendar = (BusinessCalendar) kruntime.getEnvironment().get("jbpm.business.calendar");
if (kruntime.getEnvironment().get(BUSINESS_CALENDAR_ENVIRONMENT_KEY) != null) {
BusinessCalendar businessCalendar = (BusinessCalendar) kruntime.getEnvironment().get(BUSINESS_CALENDAR_ENVIRONMENT_KEY);
duration = businessCalendar.calculateBusinessTimeAsDuration(slaDueDateExpression);
} else {
duration = DateTimeUtils.parseDuration(slaDueDateExpression);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import org.drools.core.common.InternalAgenda;
import org.drools.core.common.ReteEvaluator;
import org.drools.core.rule.consequence.InternalMatch;
import org.jbpm.process.core.timer.BusinessCalendar;
import org.jbpm.process.core.timer.DateTimeUtils;
import org.jbpm.process.core.timer.Timer;
import org.jbpm.process.instance.InternalProcessRuntime;
Expand All @@ -44,6 +43,7 @@
import org.jbpm.workflow.instance.impl.WorkflowProcessInstanceImpl;
import org.kie.api.event.rule.MatchCreatedEvent;
import org.kie.api.runtime.KieRuntime;
import org.kie.kogito.calendar.BusinessCalendar;
import org.kie.kogito.internal.process.event.KogitoEventListener;
import org.kie.kogito.internal.process.runtime.KogitoNodeInstance;
import org.kie.kogito.internal.process.runtime.KogitoProcessContext;
Expand All @@ -60,6 +60,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.jbpm.process.core.constants.CalendarConstants.BUSINESS_CALENDAR_ENVIRONMENT_KEY;
import static org.jbpm.workflow.core.Node.CONNECTION_DEFAULT_TYPE;
import static org.jbpm.workflow.instance.node.TimerNodeInstance.TIMER_TRIGGERED_EVENT;

Expand Down Expand Up @@ -145,8 +146,8 @@ protected void configureSla() {
protected ExpirationTime createTimerInstance(Timer timer) {

KieRuntime kruntime = getProcessInstance().getKnowledgeRuntime();
if (kruntime != null && kruntime.getEnvironment().get("jbpm.business.calendar") != null) {
BusinessCalendar businessCalendar = (BusinessCalendar) kruntime.getEnvironment().get("jbpm.business.calendar");
if (kruntime != null && kruntime.getEnvironment().get(BUSINESS_CALENDAR_ENVIRONMENT_KEY) != null) {
BusinessCalendar businessCalendar = (BusinessCalendar) kruntime.getEnvironment().get(BUSINESS_CALENDAR_ENVIRONMENT_KEY);
String delay = null;
switch (timer.getTimeType()) {
case Timer.TIME_CYCLE:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.kie.api.event.process.ProcessEventListener;
import org.kie.kogito.Addons;
import org.kie.kogito.auth.IdentityProvider;
import org.kie.kogito.calendar.BusinessCalendar;
import org.kie.kogito.event.EventPublisher;
import org.kie.kogito.jobs.JobsService;
import org.kie.kogito.process.ProcessConfig;
Expand All @@ -51,6 +52,7 @@ public abstract class AbstractProcessConfig implements ProcessConfig {
private final JobsService jobsService;
private final ProcessVersionResolver versionResolver;
private final IdentityProvider identityProvider;
private final BusinessCalendar businessCalendar;

protected AbstractProcessConfig(
Iterable<WorkItemHandlerConfig> workItemHandlerConfig,
Abhitocode marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -62,7 +64,8 @@ protected AbstractProcessConfig(
String kogitoService,
Iterable<UnitOfWorkEventListener> unitOfWorkListeners,
Iterable<ProcessVersionResolver> versionResolver,
Iterable<IdentityProvider> identityProvider) {
Iterable<IdentityProvider> identityProvider,
Abhitocode marked this conversation as resolved.
Show resolved Hide resolved
Iterable<BusinessCalendar> businessCalendar) {

this.workItemHandlerConfig = mergeWorkItemHandler(workItemHandlerConfig, DefaultWorkItemHandlerConfig::new);
this.processEventListenerConfig = merge(processEventListenerConfigs, processEventListeners);
Expand All @@ -72,6 +75,7 @@ protected AbstractProcessConfig(
this.jobsService = orDefault(jobsService, () -> null);
this.versionResolver = orDefault(versionResolver, () -> null);
this.identityProvider = orDefault(identityProvider, NoOpIdentityProvider::new);
this.businessCalendar = orDefault(businessCalendar, () -> null);

eventPublishers.forEach(publisher -> unitOfWorkManager().eventManager().addPublisher(publisher));
unitOfWorkListeners.forEach(listener -> unitOfWorkManager().register(listener));
Expand Down Expand Up @@ -124,6 +128,11 @@ public IdentityProvider identityProvider() {
return identityProvider;
}

@Override
public BusinessCalendar getBusinessCalendar() {
return this.businessCalendar;
}

public org.kie.kogito.Addons addons() {
return Addons.EMTPY;
}
Expand Down
Loading
Loading