Skip to content
Open
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
20 changes: 20 additions & 0 deletions distro/src/readme.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,26 @@ <h3>Release Notes - Flowable - 8.0.0</h3>
Date properties e.g., Process Instance start time will be returned as an ISO 8601 in the UTC timezone.
E.g., if the start time was returned as <code>2025-09-24T09:58:12.609+02:00</code> now it is returned as <code>2025-09-24T07:58:12.609Z</code>.
</li>
<li>
Remove Joda Time support.
If Joda Time variables were being used, then the Joda LocalDate variable is now an instance of java.time.LocalDate
and the Joda DateTime variable is now an instance of java.time.Instant.
If variables should keep being read as Joda Time (e.g., for custom scripts etc.), then with Spring Boot the property <code>flowable.joda-time-variable-support</code>
can be set to <code>WRITE</code>.
The available values for <code>flowable.joda-time-variable-support</code> are:
<ul>
<li><code>DISABLE</code> - Completely disables Joda Time. If you have Joda Time variables in the database then reading those variables will fail.
</li>
<li><code>READ_AS_JAVA_TIME</code> - Reads Joda Time variables from the database as Java LocalDate and DateTime. This is the default configuration.
</li>
<li><code>WRITE</code> - Reads and Writes Joda Time variables. This is the same as prior to Flowable 8. The joda-time dependency has to be available
on the classpath.
</li>
</ul>
Keep in mind that this only works for variables, Flowable itself no longer supports Joda Time, i.e., due dates, timers, etc. no longer support Joda Time
values.
</li>

</ul>
<h3>Release Notes - Flowable - 7.2.0</h3>

Expand Down
2 changes: 1 addition & 1 deletion docs/docusaurus/docs/cmmn/ch06-cmmn.md
Original file line number Diff line number Diff line change
Expand Up @@ -929,7 +929,7 @@ Properties:

- **Timer expression**: an expression that defines when the timer should occur. The following options are possible:

- An expression resolving to a java.util.Date or org.joda.time.DateTime instance (for example, \_${someBean.calculateNextDate(someCaseInstanceVariable)})
- An expression resolving to a java.util.Date, java.time.Instant, java.time.LocalDate or java.time.LocalDateTime instance (for example, \_${someBean.calculateNextDate(someCaseInstanceVariable)})

- An ISO8601 date

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,20 @@
package org.flowable.app.rest.service;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.TimeZone;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
Expand All @@ -50,8 +49,6 @@
import org.flowable.common.engine.impl.test.EnsureCleanDb;
import org.flowable.common.engine.impl.test.LoggingExtension;
import org.flowable.common.rest.util.RestUrlBuilder;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.ExtendWith;
Expand Down Expand Up @@ -271,19 +268,11 @@ protected void assertErrorResult(String url, ObjectNode body, int statusCode) th
* Extract a date from the given string. Assertion fails when invalid date has been provided.
*/
protected Date getDateFromISOString(String isoString) {
DateTimeFormatter dateFormat = ISODateTimeFormat.dateTime();
try {
return dateFormat.parseDateTime(isoString).toDate();
} catch (IllegalArgumentException iae) {
fail("Illegal date provided: " + isoString);
return null;
}
return Date.from(Instant.parse(isoString));
}

protected String getISODateString(Date time) {
TimeZone tz = TimeZone.getTimeZone("UTC");
longDateFormat.setTimeZone(tz);
return longDateFormat.format(time);
return time.toInstant().toString();
}

protected String buildUrl(String[] fragments, Object... arguments) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
import org.flowable.common.engine.impl.el.ExpressionManager;
import org.flowable.common.engine.impl.interceptor.CommandInterceptor;
import org.flowable.common.engine.impl.interceptor.EngineConfigurationConstants;
import org.flowable.common.engine.impl.joda.JodaDeprecationLogger;
import org.flowable.common.engine.impl.persistence.deploy.DefaultDeploymentCache;
import org.flowable.common.engine.impl.persistence.deploy.DeploymentCache;
import org.flowable.common.engine.impl.persistence.entity.TableDataManager;
Expand All @@ -80,6 +81,7 @@
import org.flowable.variable.api.types.VariableType;
import org.flowable.variable.api.types.VariableTypes;
import org.flowable.variable.service.VariableServiceConfiguration;
import org.flowable.variable.service.impl.JodaTimeVariableSupport;
import org.flowable.variable.service.impl.db.IbatisVariableTypeHandler;
import org.flowable.variable.service.impl.types.BigDecimalType;
import org.flowable.variable.service.impl.types.BigIntegerType;
Expand All @@ -91,8 +93,6 @@
import org.flowable.variable.service.impl.types.EmptyCollectionType;
import org.flowable.variable.service.impl.types.InstantType;
import org.flowable.variable.service.impl.types.IntegerType;
import org.flowable.variable.service.impl.types.JodaDateTimeType;
import org.flowable.variable.service.impl.types.JodaDateType;
import org.flowable.variable.service.impl.types.JsonType;
import org.flowable.variable.service.impl.types.LocalDateTimeType;
import org.flowable.variable.service.impl.types.LocalDateType;
Expand Down Expand Up @@ -156,6 +156,8 @@ public class AppEngineConfiguration extends AbstractBuildableEngineConfiguration
*/
protected boolean jsonVariableTypeTrackObjects = true;

protected JodaTimeVariableSupport jodaTimeVariableSupport = JodaTimeVariableSupport.READ_AS_JAVA_TIME;


protected BusinessCalendarManager businessCalendarManager;

Expand Down Expand Up @@ -402,8 +404,7 @@ public void initVariableTypes() {
variableTypes.addType(new InstantType());
variableTypes.addType(new LocalDateType());
variableTypes.addType(new LocalDateTimeType());
variableTypes.addType(new JodaDateType());
variableTypes.addType(new JodaDateTimeType());
jodaTimeVariableSupport.registerJodaTypes(variableTypes);
variableTypes.addType(new DoubleType());
variableTypes.addType(new BigDecimalType());
variableTypes.addType(new BigIntegerType());
Expand Down Expand Up @@ -740,6 +741,19 @@ public AppEngineConfiguration setJsonVariableTypeTrackObjects(boolean jsonVariab
return this;
}

public JodaTimeVariableSupport getJodaTimeVariableSupport() {
return jodaTimeVariableSupport;
}

public AppEngineConfiguration setJodaTimeVariableSupport(JodaTimeVariableSupport jodaTimeVariableSupport) {
//noinspection deprecation
if (JodaTimeVariableSupport.WRITE == jodaTimeVariableSupport) {
JodaDeprecationLogger.LOGGER.warn("Using deprecated joda time write support for the app engine configuration");
}
this.jodaTimeVariableSupport = jodaTimeVariableSupport;
return this;
}

public boolean isDisableIdmEngine() {
return disableIdmEngine;
}
Expand Down
4 changes: 0 additions & 4 deletions modules/flowable-batch-service/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,6 @@
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
Expand Down
4 changes: 0 additions & 4 deletions modules/flowable-bpmn-converter/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,6 @@
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-reload4j</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@
import org.flowable.common.engine.impl.interceptor.CommandInterceptor;
import org.flowable.common.engine.impl.interceptor.EngineConfigurationConstants;
import org.flowable.common.engine.impl.javax.el.ELResolver;
import org.flowable.common.engine.impl.joda.JodaDeprecationLogger;
import org.flowable.common.engine.impl.persistence.deploy.DefaultDeploymentCache;
import org.flowable.common.engine.impl.persistence.deploy.DeploymentCache;
import org.flowable.common.engine.impl.persistence.entity.TableDataManager;
Expand Down Expand Up @@ -304,6 +305,7 @@
import org.flowable.variable.api.types.VariableTypes;
import org.flowable.variable.service.VariableServiceConfiguration;
import org.flowable.variable.service.history.InternalHistoryVariableManager;
import org.flowable.variable.service.impl.JodaTimeVariableSupport;
import org.flowable.variable.service.impl.db.IbatisVariableTypeHandler;
import org.flowable.variable.service.impl.types.BigDecimalType;
import org.flowable.variable.service.impl.types.BigIntegerType;
Expand All @@ -315,8 +317,6 @@
import org.flowable.variable.service.impl.types.EmptyCollectionType;
import org.flowable.variable.service.impl.types.InstantType;
import org.flowable.variable.service.impl.types.IntegerType;
import org.flowable.variable.service.impl.types.JodaDateTimeType;
import org.flowable.variable.service.impl.types.JodaDateType;
import org.flowable.variable.service.impl.types.JsonType;
import org.flowable.variable.service.impl.types.LocalDateTimeType;
import org.flowable.variable.service.impl.types.LocalDateType;
Expand Down Expand Up @@ -514,6 +514,8 @@ public class CmmnEngineConfiguration extends AbstractBuildableEngineConfiguratio
*/
protected boolean jsonVariableTypeTrackObjects = true;

protected JodaTimeVariableSupport jodaTimeVariableSupport = JodaTimeVariableSupport.READ_AS_JAVA_TIME;

protected List<CaseInstanceMigrationCallback> caseInstanceMigrationCallbacks;

// Set Http Client config defaults
Expand Down Expand Up @@ -1408,8 +1410,7 @@ public void initVariableTypes() {
variableTypes.addType(new InstantType());
variableTypes.addType(new LocalDateType());
variableTypes.addType(new LocalDateTimeType());
variableTypes.addType(new JodaDateType());
variableTypes.addType(new JodaDateTimeType());
jodaTimeVariableSupport.registerJodaTypes(variableTypes);
variableTypes.addType(new DoubleType());
variableTypes.addType(new BigDecimalType());
variableTypes.addType(new BigIntegerType());
Expand Down Expand Up @@ -2967,6 +2968,19 @@ public CmmnEngineConfiguration setJsonVariableTypeTrackObjects(boolean jsonVaria
return this;
}

public JodaTimeVariableSupport getJodaTimeVariableSupport() {
return jodaTimeVariableSupport;
}

public CmmnEngineConfiguration setJodaTimeVariableSupport(JodaTimeVariableSupport jodaTimeVariableSupport) {
//noinspection deprecation
if (JodaTimeVariableSupport.WRITE == jodaTimeVariableSupport) {
JodaDeprecationLogger.LOGGER.warn("Using deprecated joda time write support for the CMMN engine configuration");
}
this.jodaTimeVariableSupport = jodaTimeVariableSupport;
return this;
}

public CaseDiagramGenerator getCaseDiagramGenerator() {
return caseDiagramGenerator;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,12 @@
import org.flowable.common.engine.impl.calendar.DueDateBusinessCalendar;
import org.flowable.common.engine.impl.el.ExpressionManager;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.common.engine.impl.joda.JodaDeprecationLogger;
import org.flowable.common.engine.impl.runtime.Clock;
import org.flowable.common.engine.impl.util.DateUtil;
import org.flowable.job.service.JobServiceConfiguration;
import org.flowable.job.service.impl.persistence.entity.JobEntity;
import org.flowable.job.service.impl.persistence.entity.TimerJobEntity;
import org.flowable.job.service.impl.persistence.entity.TimerJobEntityManager;
import org.joda.time.DateTime;

/**
* {@link CmmnActivityBehavior} implementation for the CMMN Timer Event Listener.
Expand Down Expand Up @@ -101,12 +99,6 @@ protected void handleCreateTransition(CommandContext commandContext, PlanItemIns
if (timerValue instanceof Date) {
timerDueDate = (Date) timerValue;

} else if (timerValue instanceof DateTime timerDateTime) {
JodaDeprecationLogger.LOGGER.warn(
"Using Joda-Time DateTime has been deprecated and will be removed in a future version. Timer event listener expression {} in {} resolved to a Joda-Time DateTime. ",
timerEventListener.getTimerExpression(), planItemInstance);
timerDueDate = timerDateTime.toDate();

} else if (timerValue instanceof String timerString) {

BusinessCalendarManager businessCalendarManager = CommandContextUtil.getCmmnEngineConfiguration(commandContext).getBusinessCalendarManager();
Expand Down Expand Up @@ -146,7 +138,7 @@ protected void handleCreateTransition(CommandContext commandContext, PlanItemIns
}

if (timerDueDate == null) {
throw new FlowableException("Timer expression '" + timerEventListener.getTimerExpression() + "' did not resolve to java.util.Date, org.joda.time.DateTime, "
throw new FlowableException("Timer expression '" + timerEventListener.getTimerExpression() + "' did not resolve to java.util.Date, "
+ "java.time.Instant, java.time.LocalDate, java.time.LocalDateTime or "
+ "an ISO8601 date/duration/repetition string or a cron expression for " + planItemInstance);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@
import org.flowable.variable.service.impl.types.DoubleType;
import org.flowable.variable.service.impl.types.InstantType;
import org.flowable.variable.service.impl.types.IntegerType;
import org.flowable.variable.service.impl.types.JodaDateTimeType;
import org.flowable.variable.service.impl.types.JodaDateType;
import org.flowable.variable.service.impl.types.JodaDateTimeFallbackType;
import org.flowable.variable.service.impl.types.JodaDateFallbackType;
import org.flowable.variable.service.impl.types.JsonType;
import org.flowable.variable.service.impl.types.LocalDateTimeType;
import org.flowable.variable.service.impl.types.LocalDateType;
Expand Down Expand Up @@ -140,8 +140,8 @@ public Object aggregateSingleVariable(DelegatePlanItemInstance planItemInstance,
case InstantType.TYPE_NAME:
case LocalDateType.TYPE_NAME:
case LocalDateTimeType.TYPE_NAME:
case JodaDateType.TYPE_NAME:
case JodaDateTimeType.TYPE_NAME:
case JodaDateFallbackType.TYPE_NAME:
case JodaDateTimeFallbackType.TYPE_NAME:
case UUIDType.TYPE_NAME:
// For all these types it is OK to use toString as their string representation is what we want to have
objectNode.put(targetVarName, varInstance.getValue().toString());
Expand Down
6 changes: 0 additions & 6 deletions modules/flowable-common-rest/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,6 @@
<artifactId>slf4j-api</artifactId>
</dependency>

<!-- Joda time -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>

<!--- Commons -->
<dependency>
<groupId>org.apache.commons</groupId>
Expand Down
4 changes: 0 additions & 4 deletions modules/flowable-content-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@
<groupId>org.flowable</groupId>
<artifactId>flowable-engine-common-api</artifactId>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
</dependencies>

</project>
4 changes: 0 additions & 4 deletions modules/flowable-dmn-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@
<groupId>org.flowable</groupId>
<artifactId>flowable-engine-common-api</artifactId>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
package org.flowable.dmn.api;

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
Expand All @@ -22,8 +23,6 @@

import org.flowable.dmn.model.DecisionRule;
import org.flowable.dmn.model.HitPolicy;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
Expand Down Expand Up @@ -258,8 +257,7 @@ protected static boolean isBoolean(Object obj) {
}

protected static boolean isDate(Object obj) {
return (obj instanceof Date || obj instanceof DateTime || obj instanceof LocalDate || obj instanceof java.time.LocalDate || obj instanceof LocalDateTime
|| obj instanceof Instant);
return (obj instanceof Date || obj instanceof LocalDate || obj instanceof LocalDateTime || obj instanceof Instant);
}

protected static boolean isNumber(Object obj) {
Expand Down
4 changes: 0 additions & 4 deletions modules/flowable-dmn-engine/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,6 @@
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.uuid</groupId>
<artifactId>java-uuid-generator</artifactId>
Expand Down
Loading
Loading