TSK-1991: rework of property names

This commit is contained in:
Mustapha Zorgati 2023-03-14 23:22:22 +01:00
parent 45df9e7500
commit d96b1c392a
78 changed files with 2597 additions and 2017 deletions

View File

@ -8,7 +8,6 @@ public final class CustomHoliday {
private final Integer month;
public CustomHoliday(Integer day, Integer month) {
// TODO: validate this is a valid date
this.day = day;
this.month = month;
}

View File

@ -1,39 +1,11 @@
package pro.taskana.common.api;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import pro.taskana.common.api.exceptions.SystemException;
/** The TaskanaRole enum contains all roles that are known to TASKANA. */
public enum TaskanaRole {
USER("taskana.roles.user"),
BUSINESS_ADMIN("taskana.roles.businessadmin"),
ADMIN("taskana.roles.admin"),
MONITOR("taskana.roles.monitor"),
TASK_ADMIN("taskana.roles.taskadmin"),
TASK_ROUTER("taskana.roles.taskrouter");
private final String propertyName;
TaskanaRole(String propertyName) {
this.propertyName = propertyName;
}
public static TaskanaRole fromPropertyName(String name) {
return Arrays.stream(TaskanaRole.values())
.filter(x -> x.propertyName.equalsIgnoreCase(name))
.findFirst()
.orElseThrow(
() ->
new SystemException("Internal System error when processing role property " + name));
}
public static List<String> getValidPropertyNames() {
return Arrays.stream(values()).map(TaskanaRole::getPropertyName).collect(Collectors.toList());
}
public String getPropertyName() {
return propertyName;
}
USER,
BUSINESS_ADMIN,
ADMIN,
MONITOR,
TASK_ADMIN,
TASK_ROUTER
}

View File

@ -20,6 +20,11 @@ public class TaskanaException extends Exception {
@Override
public String toString() {
return "TaskanaException [errorCode=" + errorCode + ", message=" + getMessage() + "]";
return getClass().getSimpleName()
+ " [errorCode="
+ errorCode
+ ", message="
+ getMessage()
+ "]";
}
}

View File

@ -20,6 +20,11 @@ public class TaskanaRuntimeException extends RuntimeException {
@Override
public String toString() {
return "TaskanaRuntimeException [errorCode=" + errorCode + ", message=" + getMessage() + "]";
return getClass().getSimpleName()
+ " [errorCode="
+ errorCode
+ ", message="
+ getMessage()
+ "]";
}
}

View File

@ -4,7 +4,7 @@ import pro.taskana.common.api.CustomHoliday;
import pro.taskana.common.internal.util.MapCreator;
/** This exception is thrown when an entry for the {@linkplain CustomHoliday} has a wrong format. */
public class WrongCustomHolidayFormatException extends TaskanaException {
public class WrongCustomHolidayFormatException extends TaskanaRuntimeException {
public static final String ERROR_KEY = "CUSTOM_HOLIDAY_WRONG_FORMAT";
private final String customHoliday;

View File

@ -1,482 +0,0 @@
package pro.taskana.common.internal.configuration;
import static java.util.function.Predicate.not;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.function.UnaryOperator;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pro.taskana.common.api.CustomHoliday;
import pro.taskana.common.api.LocalTimeInterval;
import pro.taskana.common.api.TaskanaRole;
import pro.taskana.common.api.exceptions.SystemException;
import pro.taskana.common.api.exceptions.WrongCustomHolidayFormatException;
import pro.taskana.common.internal.util.CheckedFunction;
import pro.taskana.common.internal.util.Pair;
import pro.taskana.common.internal.util.ReflectionUtil;
public class TaskanaConfigurationInitializer {
private static final Logger LOGGER =
LoggerFactory.getLogger(TaskanaConfigurationInitializer.class);
private static final String TASKANA_CUSTOM_HOLIDAY_DAY_MONTH_SEPARATOR = ".";
private static final String TASKANA_CLASSIFICATION_CATEGORIES_PROPERTY =
"taskana.classification.categories";
private static final Map<Class<?>, PropertyParser<?>> PROPERTY_INITIALIZER_BY_CLASS =
new HashMap<>();
static {
PROPERTY_INITIALIZER_BY_CLASS.put(Integer.class, new IntegerPropertyParser());
PROPERTY_INITIALIZER_BY_CLASS.put(Long.class, new LongPropertyParser());
PROPERTY_INITIALIZER_BY_CLASS.put(Boolean.class, new BooleanPropertyParser());
PROPERTY_INITIALIZER_BY_CLASS.put(String.class, new StringPropertyParser());
PROPERTY_INITIALIZER_BY_CLASS.put(Duration.class, new DurationPropertyParser());
PROPERTY_INITIALIZER_BY_CLASS.put(Instant.class, new InstantPropertyParser());
PROPERTY_INITIALIZER_BY_CLASS.put(List.class, new ListPropertyParser());
PROPERTY_INITIALIZER_BY_CLASS.put(Map.class, new MapPropertyParser());
PROPERTY_INITIALIZER_BY_CLASS.put(ZoneId.class, new ZoneIdPropertyParser());
PROPERTY_INITIALIZER_BY_CLASS.put(Enum.class, new EnumPropertyParser());
}
private TaskanaConfigurationInitializer() {
throw new IllegalStateException("utility class");
}
public static void configureAnnotatedFields(
Object instance, String separator, Map<String, String> props) {
final List<Field> fields = ReflectionUtil.retrieveAllFields(instance.getClass());
for (Field field : fields) {
Optional.ofNullable(field.getAnnotation(TaskanaProperty.class))
.ifPresent(
taskanaProperty -> {
Class<?> type = ReflectionUtil.wrap(field.getType());
PropertyParser<?> propertyParser;
if (type.isEnum()) {
propertyParser = PROPERTY_INITIALIZER_BY_CLASS.get(Enum.class);
} else {
propertyParser = PROPERTY_INITIALIZER_BY_CLASS.get(type);
}
if (propertyParser == null) {
throw new SystemException(String.format("Unknown configuration type '%s'", type));
}
propertyParser
.initialize(props, separator, field, taskanaProperty)
.ifPresent(value -> setFieldValue(instance, field, value));
});
}
}
public static Map<String, List<String>> configureClassificationCategoriesForType(
Map<String, String> props, List<String> classificationTypes) {
Function<String, List<String>> getClassificationCategoriesForType =
type ->
parseProperty(
props,
TASKANA_CLASSIFICATION_CATEGORIES_PROPERTY + "." + type.toLowerCase(),
p -> splitStringAndTrimElements(p, ",", String::toUpperCase))
.orElseGet(ArrayList::new);
return classificationTypes.stream()
.map(type -> Pair.of(type, getClassificationCategoriesForType.apply(type)))
.collect(Collectors.toMap(Pair::getLeft, Pair::getRight));
}
public static Map<TaskanaRole, Set<String>> configureRoles(
String separator, Map<String, String> props, boolean shouldUseLowerCaseForAccessIds) {
Function<TaskanaRole, Set<String>> getAccessIdsForRole =
role ->
new HashSet<>(
splitStringAndTrimElements(
props.getOrDefault(role.getPropertyName().toLowerCase(), ""),
separator,
shouldUseLowerCaseForAccessIds
? String::toLowerCase
: UnaryOperator.identity()));
return Arrays.stream(TaskanaRole.values())
.map(role -> Pair.of(role, getAccessIdsForRole.apply(role)))
.collect(Collectors.toMap(Pair::getLeft, Pair::getRight));
}
static List<String> splitStringAndTrimElements(String str, String separator) {
return splitStringAndTrimElements(str, separator, UnaryOperator.identity());
}
static List<String> splitStringAndTrimElements(
String str, String separator, UnaryOperator<String> modifier) {
return Arrays.stream(str.split(Pattern.quote(separator)))
.filter(not(String::isEmpty))
.map(String::trim)
.map(modifier)
.collect(Collectors.toList());
}
static CustomHoliday createCustomHolidayFromPropsEntry(String customHolidayEntry)
throws WrongCustomHolidayFormatException {
List<String> parts =
splitStringAndTrimElements(customHolidayEntry, TASKANA_CUSTOM_HOLIDAY_DAY_MONTH_SEPARATOR);
if (parts.size() == 2) {
return CustomHoliday.of(Integer.valueOf(parts.get(0)), Integer.valueOf(parts.get(1)));
}
throw new WrongCustomHolidayFormatException(customHolidayEntry);
}
private static void setFieldValue(Object instance, Field field, Object value) {
try {
field.setAccessible(true);
field.set(instance, value);
} catch (IllegalAccessException | IllegalArgumentException e) {
throw new SystemException(
"Property value " + value + " is invalid for field " + field.getName(), e);
}
}
private static <T> Optional<T> parseProperty(
Map<String, String> props, String key, CheckedFunction<String, T, Exception> function) {
String property = props.getOrDefault(key, "");
if (property.isEmpty()) {
return Optional.empty();
}
try {
return Optional.ofNullable(function.apply(property));
} catch (Exception t) {
throw new SystemException(
String.format("Could not parse property '%s' ('%s').", key, property), t);
}
}
interface PropertyParser<T> {
Optional<T> initialize(
Map<String, String> properties,
String separator,
Field field,
TaskanaProperty taskanaProperty);
}
static class MapPropertyParser implements PropertyParser<Map<?, ?>> {
@Override
public Optional<Map<?, ?>> initialize(
Map<String, String> properties,
String separator,
Field field,
TaskanaProperty taskanaProperty) {
if (!Map.class.isAssignableFrom(field.getType())) {
throw new SystemException(
String.format(
"Cannot initialize field '%s' because field type '%s' is not a Map",
field, field.getType()));
}
ParameterizedType genericType = (ParameterizedType) field.getGenericType();
Type[] actualTypeArguments = genericType.getActualTypeArguments();
Class<?> keyClass = (Class<?>) actualTypeArguments[0];
Type valueClass = actualTypeArguments[1];
// Parses property files into a Map using the following layout: <Property>.<Key> = <value>
String propertyKey = taskanaProperty.value();
Map<?, ?> mapFromProperties =
properties.keySet().stream()
.filter(it -> it.startsWith(propertyKey))
.map(
it -> {
// Keys of the map entry is everything after the propertyKey + "."
String keyAsString = it.substring(propertyKey.length() + 1);
Object key = getStringAsObject(keyAsString, keyClass);
// Value of the map entry is the value from the property
String propertyValue = properties.get(it);
Object value = getStringAsObject(propertyValue, separator, valueClass);
return Pair.of(key, value);
})
.collect(Collectors.toMap(Pair::getLeft, Pair::getRight));
if (mapFromProperties.isEmpty()) {
return Optional.empty();
} else {
return Optional.of(mapFromProperties);
}
}
private Object getStringAsObject(String string, String separator, Type type) {
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
Type rawType = parameterizedType.getRawType();
if (rawType.equals(Set.class)) {
return getStringAsSet(
string, separator, (Class<?>) parameterizedType.getActualTypeArguments()[0]);
}
} else if (type instanceof Class) {
return getStringAsObject(string, (Class<?>) type);
}
throw new SystemException(
String.format(
"Cannot parse property value '%s': It is not convertible to '%s'",
string, type.getTypeName()));
}
private Object getStringAsObject(String string, Class<?> targetClass) {
if (targetClass.isEnum()) {
Map<String, ?> enumConstantsByLowerCasedName =
Arrays.stream(targetClass.getEnumConstants())
.collect(Collectors.toMap(e -> e.toString().toLowerCase(), Function.identity()));
Object o = enumConstantsByLowerCasedName.get(string.toLowerCase());
if (o == null) {
throw new SystemException(
String.format(
"Invalid property value '%s': Valid values are '%s' or '%s",
string,
enumConstantsByLowerCasedName.keySet(),
Arrays.toString(targetClass.getEnumConstants())));
}
return o;
} else if (targetClass.equals(LocalTimeInterval.class)) {
List<String> startAndEnd = splitStringAndTrimElements(string, "-");
if (startAndEnd.size() != 2) {
throw new SystemException("Cannot convert " + string + " to " + LocalTimeInterval.class);
}
LocalTime start = LocalTime.parse(startAndEnd.get(0));
LocalTime end = LocalTime.parse(startAndEnd.get(1));
if (end.equals(LocalTime.MIN)) {
end = LocalTime.MAX;
}
return new LocalTimeInterval(start, end);
} else {
throw new SystemException(
String.format(
"Cannot parse property value '%s': It is not convertible to '%s'",
string, targetClass.getName()));
}
}
private Set<?> getStringAsSet(String string, String separator, Class<?> elementClass) {
return splitStringAndTrimElements(string, separator).stream()
.map(it -> getStringAsObject(it, elementClass))
.collect(Collectors.toSet());
}
}
static class ListPropertyParser implements PropertyParser<List<?>> {
@Override
public Optional<List<?>> initialize(
Map<String, String> properties,
String separator,
Field field,
TaskanaProperty taskanaProperty) {
if (!List.class.isAssignableFrom(ReflectionUtil.wrap(field.getType()))) {
throw new SystemException(
String.format(
"Cannot initialize field '%s' because field type '%s' is not a List",
field, field.getType()));
}
Class<?> genericClass =
(Class<?>) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0];
if (genericClass.isEnum()) {
Map<String, ?> enumConstants =
Arrays.stream(genericClass.getEnumConstants())
.collect(Collectors.toMap(e -> e.toString().toLowerCase(), Function.identity()));
CheckedFunction<String, List<?>, Exception> parseFunction =
s ->
splitStringAndTrimElements(s, separator).stream()
.map(String::toLowerCase)
.map(enumConstants::get)
.filter(Objects::nonNull)
.collect(Collectors.toList());
return parseProperty(properties, taskanaProperty.value(), parseFunction);
} else if (CustomHoliday.class.isAssignableFrom(genericClass)) {
CheckedFunction<String, List<?>, Exception> parseFunction =
s ->
splitStringAndTrimElements(s, separator).stream()
.map(
str -> {
try {
return createCustomHolidayFromPropsEntry(str);
} catch (WrongCustomHolidayFormatException e) {
LOGGER.warn(e.getMessage());
return null;
}
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
return parseProperty(properties, taskanaProperty.value(), parseFunction);
} else if (String.class.isAssignableFrom(genericClass)) {
CheckedFunction<String, List<?>, Exception> parseListFunction =
p -> splitStringAndTrimElements(p, ",", String::toUpperCase);
return parseProperty(properties, taskanaProperty.value(), parseListFunction);
} else {
throw new SystemException(
String.format(
"Cannot initialize field '%s' because field type '%s' is unknown",
field, genericClass));
}
}
}
static class InstantPropertyParser implements PropertyParser<Instant> {
@Override
public Optional<Instant> initialize(
Map<String, String> properties,
String separator,
Field field,
TaskanaProperty taskanaProperty) {
if (!Instant.class.isAssignableFrom(ReflectionUtil.wrap(field.getType()))) {
throw new SystemException(
String.format(
"Cannot initialize field '%s' because field type '%s' is not an Instant",
field, field.getType()));
}
return parseProperty(properties, taskanaProperty.value(), Instant::parse);
}
}
static class DurationPropertyParser implements PropertyParser<Duration> {
@Override
public Optional<Duration> initialize(
Map<String, String> properties,
String separator,
Field field,
TaskanaProperty taskanaProperty) {
if (!Duration.class.isAssignableFrom(ReflectionUtil.wrap(field.getType()))) {
throw new SystemException(
String.format(
"Cannot initialize field '%s' because field type '%s' is not a Duration",
field, field.getType()));
}
return parseProperty(properties, taskanaProperty.value(), Duration::parse);
}
}
static class StringPropertyParser implements PropertyParser<String> {
@Override
public Optional<String> initialize(
Map<String, String> properties,
String separator,
Field field,
TaskanaProperty taskanaProperty) {
if (!String.class.isAssignableFrom(ReflectionUtil.wrap(field.getType()))) {
throw new SystemException(
String.format(
"Cannot initialize field '%s' because field type '%s' is not a String",
field, field.getType()));
}
return parseProperty(properties, taskanaProperty.value(), String::new);
}
}
static class IntegerPropertyParser implements PropertyParser<Integer> {
@Override
public Optional<Integer> initialize(
Map<String, String> properties,
String separator,
Field field,
TaskanaProperty taskanaProperty) {
if (!Integer.class.isAssignableFrom(ReflectionUtil.wrap(field.getType()))) {
throw new SystemException(
String.format(
"Cannot initialize field '%s' because field type '%s' is not an Integer",
field, field.getType()));
}
return parseProperty(properties, taskanaProperty.value(), Integer::parseInt);
}
}
static class LongPropertyParser implements PropertyParser<Long> {
@Override
public Optional<Long> initialize(
Map<String, String> properties,
String separator,
Field field,
TaskanaProperty taskanaProperty) {
if (!Long.class.isAssignableFrom(ReflectionUtil.wrap(field.getType()))) {
throw new SystemException(
String.format(
"Cannot initialize field '%s' because field type '%s' is not a Long",
field, field.getType()));
}
return parseProperty(properties, taskanaProperty.value(), Long::parseLong);
}
}
static class BooleanPropertyParser implements PropertyParser<Boolean> {
@Override
public Optional<Boolean> initialize(
Map<String, String> properties,
String separator,
Field field,
TaskanaProperty taskanaProperty) {
if (!Boolean.class.isAssignableFrom(ReflectionUtil.wrap(field.getType()))) {
throw new SystemException(
String.format(
"Cannot initialize field '%s' because field type '%s' is not a Boolean",
field, field.getType()));
}
return parseProperty(properties, taskanaProperty.value(), Boolean::parseBoolean);
}
}
static class ZoneIdPropertyParser implements PropertyParser<ZoneId> {
@Override
public Optional<ZoneId> initialize(
Map<String, String> properties,
String separator,
Field field,
TaskanaProperty taskanaProperty) {
return parseProperty(properties, taskanaProperty.value(), ZoneId::of);
}
}
static class EnumPropertyParser implements PropertyParser<Enum<?>> {
@Override
public Optional<Enum<?>> initialize(
Map<String, String> properties,
String separator,
Field field,
TaskanaProperty taskanaProperty) {
if (!field.getType().isEnum()) {
throw new SystemException(
String.format(
"Cannot initialize field '%s' because field type '%s' is not an Enum",
field, field.getType()));
}
return parseProperty(
properties,
taskanaProperty.value(),
string -> {
Map<String, ?> enumConstantsByLowerCasedName =
Arrays.stream(field.getType().getEnumConstants())
.collect(
Collectors.toMap(e -> e.toString().toLowerCase(), Function.identity()));
Object o = enumConstantsByLowerCasedName.get(string.toLowerCase());
if (o == null) {
throw new SystemException(
String.format(
"Invalid property value '%s': Valid values are '%s' or '%s",
string,
enumConstantsByLowerCasedName.keySet(),
Arrays.toString(field.getType().getEnumConstants())));
}
return (Enum<?>) o;
});
}
}
}

View File

@ -0,0 +1,57 @@
package pro.taskana.common.internal.configuration.parser;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.regex.Pattern;
import pro.taskana.common.api.exceptions.SystemException;
import pro.taskana.common.internal.util.ReflectionUtil;
public class CollectionPropertyParser<T extends Collection<Object>> implements PropertyParser<T> {
private final Supplier<T> emptyCollection;
private final Class<T> targetClass;
public CollectionPropertyParser(Class<T> targetClass, Supplier<T> emptyCollection) {
this.emptyCollection = emptyCollection;
this.targetClass = targetClass;
}
@Override
public Class<?> getTargetClass() {
return targetClass;
}
@Override
public Optional<T> parse(String value, String separator, Type type) {
Class<?> rawClass = ReflectionUtil.wrap(ReflectionUtil.getRawClass(type));
if (!getTargetClass().isAssignableFrom(rawClass)) {
throw new SystemException(
String.format(
"Cannot initialize '%s' because target type '%s' is not a '%s'",
value, rawClass, getTargetClass()));
}
return Optional.ofNullable(value)
.flatMap(
string -> {
Class<?> elementClass =
ReflectionUtil.getRawClass(
((ParameterizedType) type).getActualTypeArguments()[0]);
PropertyParser<?> parser = PropertyParser.getPropertyParser(elementClass);
T collection = emptyCollection.get();
for (String it : value.split(Pattern.quote(separator))) {
it = it.trim();
if (!it.isEmpty()) {
parser.parse(it, separator, elementClass).ifPresent(collection::add);
}
}
if (collection.isEmpty()) {
return Optional.empty();
}
return Optional.of(collection);
});
}
}

View File

@ -0,0 +1,19 @@
package pro.taskana.common.internal.configuration.parser;
import java.util.List;
import pro.taskana.common.api.CustomHoliday;
import pro.taskana.common.api.exceptions.WrongCustomHolidayFormatException;
public class CustomHolidayParser extends SimpleParser<CustomHoliday> {
public CustomHolidayParser() {
super(CustomHoliday.class, CustomHolidayParser::parse);
}
private static CustomHoliday parse(String value) {
List<String> parts = splitStringAndTrimElements(value, ".");
if (parts.size() == 2) {
return CustomHoliday.of(Integer.valueOf(parts.get(0)), Integer.valueOf(parts.get(1)));
}
throw new WrongCustomHolidayFormatException(value);
}
}

View File

@ -0,0 +1,51 @@
package pro.taskana.common.internal.configuration.parser;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
import pro.taskana.common.api.exceptions.SystemException;
public class EnumPropertyParser implements PropertyParser<Enum<?>> {
@Override
public Class<?> getTargetClass() {
return Enum.class;
}
@Override
public boolean validateTargetField(Field field) {
return field.getType().isEnum();
}
@Override
public Optional<Enum<?>> parse(String value, String separator, Type type) {
Class<?> targetClass = (Class<?>) type;
if (!targetClass.isEnum()) {
throw new SystemException(
String.format(
"Cannot initialize '%s' because target type '%s' is not a '%s'",
value, targetClass, getTargetClass()));
}
return Optional.ofNullable(value)
.map(
v -> {
Map<String, ?> enumConstantsByLowerCaseName =
Arrays.stream(targetClass.getEnumConstants())
.collect(
Collectors.toMap(e -> e.toString().toLowerCase(), Function.identity()));
Enum<?> enumConstant = (Enum<?>) enumConstantsByLowerCaseName.get(v.toLowerCase());
if (enumConstant == null) {
throw new SystemException(
String.format(
"Invalid property value '%s': Valid values are '%s' or '%s",
v,
enumConstantsByLowerCaseName.keySet(),
Arrays.toString(targetClass.getEnumConstants())));
}
return enumConstant;
});
}
}

View File

@ -0,0 +1,26 @@
package pro.taskana.common.internal.configuration.parser;
import java.time.LocalTime;
import java.util.List;
import pro.taskana.common.api.LocalTimeInterval;
import pro.taskana.common.api.exceptions.SystemException;
public class LocalTimeIntervalParser extends SimpleParser<LocalTimeInterval> {
public LocalTimeIntervalParser() {
super(LocalTimeInterval.class, LocalTimeIntervalParser::parse);
}
private static LocalTimeInterval parse(String value) {
List<String> startAndEnd = splitStringAndTrimElements(value, "-");
if (startAndEnd.size() != 2) {
throw new SystemException(
String.format("Cannot convert '%s' to '%s'", value, LocalTimeInterval.class));
}
LocalTime start = LocalTime.parse(startAndEnd.get(0));
LocalTime end = LocalTime.parse(startAndEnd.get(1));
if (end.equals(LocalTime.MIN)) {
end = LocalTime.MAX;
}
return new LocalTimeInterval(start, end);
}
}

View File

@ -0,0 +1,83 @@
package pro.taskana.common.internal.configuration.parser;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import pro.taskana.common.api.exceptions.SystemException;
import pro.taskana.common.internal.configuration.TaskanaProperty;
import pro.taskana.common.internal.util.Pair;
import pro.taskana.common.internal.util.ReflectionUtil;
public class MapPropertyParser implements PropertyParser<Map<?, ?>> {
@Override
public Class<?> getTargetClass() {
return Map.class;
}
@Override
public Optional<Map<?, ?>> parse(
Map<String, String> properties,
String separator,
Field field,
TaskanaProperty taskanaProperty) {
if (!Map.class.isAssignableFrom(field.getType())) {
throw new SystemException(
String.format(
"Cannot initialize field '%s' because field type '%s' is not a Map",
field, field.getType()));
}
ParameterizedType genericType = (ParameterizedType) field.getGenericType();
Type[] actualTypeArguments = genericType.getActualTypeArguments();
Class<?> keyClass = ReflectionUtil.getRawClass(actualTypeArguments[0]);
Class<?> valueClass = ReflectionUtil.getRawClass(actualTypeArguments[1]);
// Parses property files into a Map using the following layout: <Property>.<Key> = <value>
String propertyKey = taskanaProperty.value();
Map<?, ?> mapFromProperties =
properties.keySet().stream()
.filter(it -> it.startsWith(propertyKey))
.map(
it -> {
// Keys of the map entry is everything after the propertyKey + "."
String rawKey = it.substring(propertyKey.length() + 1);
// key is always present. filter guarantees that.
@SuppressWarnings("OptionalGetWithoutIsPresent")
Object key =
PropertyParser.getPropertyParser(keyClass)
.parse(rawKey, separator, actualTypeArguments[0])
.get();
// Value of the map entry is the value from the property
String rawValue = properties.get(it);
Optional<?> value =
PropertyParser.getPropertyParser(valueClass)
.parse(rawValue, separator, actualTypeArguments[1]);
return value.map(o -> Pair.of(key, o)).orElse(null);
})
.filter(Objects::nonNull)
.collect(Collectors.toMap(Pair::getLeft, Pair::getRight));
if (mapFromProperties.isEmpty()) {
return Optional.empty();
} else {
return Optional.of(mapFromProperties);
}
}
@Override
public Optional<Map<?, ?>> parse(String value, String separator, Field field) {
throw new SystemException("Map type can't be nested!");
}
@Override
public Optional<Map<?, ?>> parse(String value, String separator, Type type) {
throw new SystemException("Map type can't be nested!");
}
}

View File

@ -0,0 +1,81 @@
package pro.taskana.common.internal.configuration.parser;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.time.Duration;
import java.time.Instant;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import pro.taskana.common.api.exceptions.SystemException;
import pro.taskana.common.internal.configuration.TaskanaProperty;
import pro.taskana.common.internal.util.ReflectionUtil;
public interface PropertyParser<T> {
Map<Class<?>, PropertyParser<?>> PROPERTY_INITIALIZER_BY_CLASS =
Stream.of(
new CollectionPropertyParser<>(List.class, ArrayList::new),
new CollectionPropertyParser<>(Set.class, HashSet::new),
new CustomHolidayParser(),
new LocalTimeIntervalParser(),
new MapPropertyParser(),
new EnumPropertyParser(),
new SimpleParser<>(Boolean.class, Boolean::parseBoolean),
new SimpleParser<>(Duration.class, Duration::parse),
new SimpleParser<>(Instant.class, Instant::parse),
new SimpleParser<>(Integer.class, Integer::parseInt),
new SimpleParser<>(Long.class, Long::parseLong),
new SimpleParser<>(String.class, Function.identity()),
new SimpleParser<>(ZoneId.class, ZoneId::of))
.collect(
Collectors.toUnmodifiableMap(PropertyParser::getTargetClass, Function.identity()));
static PropertyParser<?> getPropertyParser(Class<?> forClass) {
forClass = ReflectionUtil.wrap(forClass);
PropertyParser<?> propertyParser;
if (forClass.isEnum()) {
propertyParser = PROPERTY_INITIALIZER_BY_CLASS.get(Enum.class);
} else {
propertyParser = PROPERTY_INITIALIZER_BY_CLASS.get(forClass);
}
if (propertyParser == null) {
throw new SystemException(
String.format("No PropertyParser configured for class '%s'", forClass));
}
return propertyParser;
}
Class<?> getTargetClass();
Optional<T> parse(String value, String separator, Type type);
default Optional<T> parse(String value, String separator, Field field) {
if (!validateTargetField(field)) {
throw new SystemException(
String.format(
"Cannot initialize field '%s' because field type '%s' is not compatible to a '%s'",
field, field.getType(), getTargetClass()));
}
return parse(value, separator, field.getGenericType());
}
default Optional<T> parse(
Map<String, String> properties,
String separator,
Field field,
TaskanaProperty taskanaProperty) {
return parse(properties.get(taskanaProperty.value()), separator, field);
}
default boolean validateTargetField(Field field) {
return getTargetClass().isAssignableFrom(ReflectionUtil.wrap(field.getType()));
}
}

View File

@ -0,0 +1,48 @@
package pro.taskana.common.internal.configuration.parser;
import static java.util.function.Predicate.not;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import pro.taskana.common.api.exceptions.SystemException;
import pro.taskana.common.internal.util.ReflectionUtil;
public class SimpleParser<T> implements PropertyParser<T> {
private final Class<?> targetClass;
private final Function<String, T> parseFunction;
public SimpleParser(Class<?> targetClass, Function<String, T> parseFunction) {
this.targetClass = targetClass;
this.parseFunction = parseFunction;
}
@Override
public Optional<T> parse(String value, String separator, Type type) {
Class<?> rawClass = ReflectionUtil.getRawClass(type);
if (!getTargetClass().isAssignableFrom(ReflectionUtil.wrap(rawClass))) {
throw new SystemException(
String.format(
"Cannot initialize '%s' because target type '%s' is not a '%s'",
value, rawClass, getTargetClass()));
}
return Optional.ofNullable(value).map(it -> parseFunction.apply(value));
}
@Override
public Class<?> getTargetClass() {
return targetClass;
}
protected static List<String> splitStringAndTrimElements(String str, String separator) {
return Arrays.stream(str.split(Pattern.quote(separator)))
.filter(not(String::isEmpty))
.map(String::trim)
.collect(Collectors.toList());
}
}

View File

@ -3,6 +3,8 @@ package pro.taskana.common.internal.util;
import static java.util.function.Predicate.not;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@ -39,6 +41,13 @@ public class ReflectionUtil {
return fields.stream().filter(not(Field::isSynthetic)).collect(Collectors.toList());
}
public static Class<?> getRawClass(Type type) {
if (type instanceof ParameterizedType) {
return getRawClass(((ParameterizedType) type).getRawType());
}
return (Class<?>) type;
}
// safe because both Long.class and long.class are of type Class<Long>
@SuppressWarnings("unchecked")
public static <T> Class<T> wrap(Class<T> c) {

View File

@ -15,10 +15,7 @@ import pro.taskana.spi.history.api.events.workbasket.WorkbasketHistoryEvent;
public class LogfileHistoryServiceImpl implements TaskanaHistory {
public static final String TASKANA_HISTORY_LOGGER_NAME = "taskana.historylogger.name";
private static final Logger LOGGER = LoggerFactory.getLogger(LogfileHistoryServiceImpl.class);
private static final String JSON_EXCEPTION =
"Caught exception while serializing history event to JSON ";
private ObjectMapper objectMapper;
private Logger historyLogger;
@ -27,8 +24,7 @@ public class LogfileHistoryServiceImpl implements TaskanaHistory {
objectMapper = new ObjectMapper().registerModule(new JavaTimeModule());
String historyLoggerName =
taskanaEngine.getConfiguration().getProperties().get(TASKANA_HISTORY_LOGGER_NAME);
String historyLoggerName = taskanaEngine.getConfiguration().getLogHistoryLoggerName();
if (historyLoggerName != null) {
historyLogger = LoggerFactory.getLogger(historyLoggerName);
@ -50,7 +46,7 @@ public class LogfileHistoryServiceImpl implements TaskanaHistory {
historyLogger.info(objectMapper.writeValueAsString(event));
}
} catch (JsonProcessingException e) {
throw new SystemException(JSON_EXCEPTION, e);
throw new SystemException("Caught exception while serializing history event to JSON ", e);
}
}
@ -62,7 +58,7 @@ public class LogfileHistoryServiceImpl implements TaskanaHistory {
historyLogger.info(objectMapper.writeValueAsString(event));
}
} catch (JsonProcessingException e) {
throw new SystemException(JSON_EXCEPTION, e);
throw new SystemException("Caught exception while serializing history event to JSON ", e);
}
}
@ -74,7 +70,7 @@ public class LogfileHistoryServiceImpl implements TaskanaHistory {
historyLogger.info(objectMapper.writeValueAsString(event));
}
} catch (JsonProcessingException e) {
throw new SystemException(JSON_EXCEPTION, e);
throw new SystemException("Caught exception while serializing history event to JSON ", e);
}
}

View File

@ -5,8 +5,6 @@ import static org.assertj.core.api.Assertions.assertThat;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
@ -40,9 +38,7 @@ class LogfileHistoryServiceImplTest {
TaskanaConfiguration taskanaConfiguration = Mockito.mock(TaskanaConfiguration.class);
taskanaEngineMock = Mockito.mock(TaskanaEngine.class);
Mockito.when(taskanaEngineMock.getConfiguration()).thenReturn(taskanaConfiguration);
Map<String, String> mockProperties = new HashMap<>();
mockProperties.put(LogfileHistoryServiceImpl.TASKANA_HISTORY_LOGGER_NAME, "AUDIT");
Mockito.when(taskanaConfiguration.getProperties()).thenReturn(mockProperties);
Mockito.when(taskanaConfiguration.getLogHistoryLoggerName()).thenReturn("AUDIT");
}
@Test

View File

@ -106,12 +106,12 @@ public class TaskanaHistoryEngineImpl implements TaskanaHistoryEngine {
protected SqlSessionManager createSqlSessionManager() {
Environment environment =
new Environment(DEFAULT, this.transactionFactory, taskanaConfiguration.getDatasource());
new Environment(DEFAULT, this.transactionFactory, taskanaConfiguration.getDataSource());
Configuration configuration = new Configuration(environment);
// set databaseId
DB db;
try (Connection con = taskanaConfiguration.getDatasource().getConnection()) {
try (Connection con = taskanaConfiguration.getDataSource().getConnection()) {
db = DB.getDB(con);
configuration.setDatabaseId(db.dbProductId);
} catch (SQLException e) {

View File

@ -28,7 +28,7 @@ public enum ClassificationHistoryQueryColumnName implements QueryColumnName {
CUSTOM_7("custom_7"),
CUSTOM_8("custom_8");
private String name;
private final String name;
ClassificationHistoryQueryColumnName(String name) {
this.name = name;

View File

@ -32,36 +32,30 @@ public class HistoryCleanupJob extends AbstractTaskanaJob {
private static final Logger LOGGER = LoggerFactory.getLogger(HistoryCleanupJob.class);
private static final String TASKANA_JOB_HISTORY_BATCH_SIZE = "taskana.jobs.history.batchSize";
private static final String TASKANA_JOB_HISTORY_CLEANUP_MINIMUM_AGE =
"taskana.jobs.history.cleanup.minimumAge";
private final TaskanaHistoryEngineImpl taskanaHistoryEngine =
TaskanaHistoryEngineImpl.createTaskanaEngine(taskanaEngineImpl);
private final boolean allCompletedSameParentBusiness;
private final boolean allCompletedSameParentBusiness =
taskanaEngineImpl
.getConfiguration()
.isSimpleHistoryCleanupJobAllCompletedSameParentBusiness();
private Duration minimumAge = taskanaEngineImpl.getConfiguration().getCleanupJobMinimumAge();
private int batchSize = taskanaEngineImpl.getConfiguration().getJobBatchSize();
private final Duration minimumAge =
taskanaEngineImpl.getConfiguration().getSimpleHistoryCleanupJobMinimumAge();
private final int batchSize =
taskanaEngineImpl.getConfiguration().getSimpleHistoryCleanupJobBatchSize();
public HistoryCleanupJob(
TaskanaEngine taskanaEngine,
TaskanaTransactionProvider txProvider,
ScheduledJob scheduledJob) {
super(taskanaEngine, txProvider, scheduledJob, true);
allCompletedSameParentBusiness =
taskanaEngine.getConfiguration().isTaskCleanupJobAllCompletedSameParentBusiness();
initJobParameters(taskanaEngine.getConfiguration().getProperties());
}
@Override
public void execute() {
Instant createdBefore = Instant.now().minus(minimumAge);
LOGGER.info("Running job to delete all history events created before ({})", createdBefore);
try {
SimpleHistoryServiceImpl simpleHistoryService =
(SimpleHistoryServiceImpl) taskanaHistoryEngine.getTaskanaHistoryService();
@ -199,42 +193,4 @@ public class HistoryCleanupJob extends AbstractTaskanaJob {
return deletedTasksCount;
}
private void initJobParameters(Map<String, String> props) {
String jobBatchSizeProperty = props.get(TASKANA_JOB_HISTORY_BATCH_SIZE);
if (jobBatchSizeProperty != null && !jobBatchSizeProperty.isEmpty()) {
try {
batchSize = Integer.parseInt(jobBatchSizeProperty);
} catch (Exception e) {
LOGGER.warn(
"Could not parse jobBatchSizeProperty ({}). Using default. Exception: {} ",
jobBatchSizeProperty,
e.getMessage());
}
}
String historyEventCleanupJobMinimumAgeProperty =
props.get(TASKANA_JOB_HISTORY_CLEANUP_MINIMUM_AGE);
if (historyEventCleanupJobMinimumAgeProperty != null
&& !historyEventCleanupJobMinimumAgeProperty.isEmpty()) {
try {
minimumAge = Duration.parse(historyEventCleanupJobMinimumAgeProperty);
} catch (Exception e) {
LOGGER.warn(
"Could not parse historyEventCleanupJobMinimumAgeProperty ({}). Using default."
+ " Exception: {} ",
historyEventCleanupJobMinimumAgeProperty,
e.getMessage());
}
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Configured number of history events per transaction: {}", batchSize);
LOGGER.debug("HistoryCleanupJob configuration: runs every {}", runEvery);
LOGGER.debug(
"HistoryCleanupJob configuration: minimum age of history events to be cleanup up is {}",
minimumAge);
}
}
}

View File

@ -159,7 +159,7 @@ class DeleteHistoryEventsOnTaskDeletionAccTest extends AbstractAccTest {
throws SQLException {
TaskanaConfiguration configuration =
new TaskanaConfiguration.Builder(AbstractAccTest.taskanaConfiguration)
.deleteHistoryOnTaskDeletionEnabled(deleteHistoryOnTaskDeletionEnabled)
.deleteHistoryEventsOnTaskDeletionEnabled(deleteHistoryOnTaskDeletionEnabled)
.build();
initTaskanaEngine(configuration);
}

View File

@ -507,12 +507,12 @@ class HistoryCleanupJobAccTest extends AbstractAccTest {
}
private void createTaskanaEngineWithNewConfig(
boolean taskCleanupJobAllCompletedSameParentBusiness) throws SQLException {
boolean simpleHistoryCleanupJobAllCompletedSameParentBusiness) throws SQLException {
TaskanaConfiguration configuration =
new TaskanaConfiguration.Builder(AbstractAccTest.taskanaConfiguration)
.taskCleanupJobAllCompletedSameParentBusiness(
taskCleanupJobAllCompletedSameParentBusiness)
.simpleHistoryCleanupJobAllCompletedSameParentBusiness(
simpleHistoryCleanupJobAllCompletedSameParentBusiness)
.build();
initTaskanaEngine(configuration);
}

View File

@ -1,43 +1,43 @@
taskana.roles.user=cn=ksc-users,cn=groups,OU=Test,O=TASKANA | teamlead-1 | teamlead-2 | user-1-1 | user-1-2 | user-2-1 | user-2-2 | user-b-1 | user-b-2
taskana.roles.admin=name=konrad,Organisation=novatec|admin
taskana.roles.businessadmin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.business_admin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.monitor=monitor | cn=monitor-users,cn=groups,OU=Test,O=TASKANA
taskana.roles.taskadmin=taskadmin
taskana.domains=DOMAIN_A , DOMAIN_B
taskana.roles.task_admin=taskadmin
taskana.domains=DOMAIN_A | DOMAIN_B
taskana.user.minimalPermissionsToAssignDomains=READ | OPEN
taskana.classification.types=TASK , document
taskana.classification.categories.task=EXTERNAL, manual, autoMAtic, Process
taskana.classification.types=TASK | document
taskana.classification.categories.task=EXTERNAL| manual| autoMAtic| Process
taskana.classification.categories.document=EXTERNAL
taskana.jobs.maxRetries=3
taskana.jobs.batchSize=50
taskana.jobs.cleanup.runEvery=P1D
taskana.jobs.cleanup.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.minimumAge=P14D
taskana.jobs.history.batchSize=50
taskana.jobs.runEvery=P1D
taskana.jobs.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.task.minimumAge=P14D
taskana.jobs.cleanup.history.simple.batchSize=50
taskana.jobs.history.cleanup.runEvery=P1D
taskana.jobs.history.cleanup.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.history.cleanup.minimumAge=P15D
taskana.german.holidays.enabled=true
taskana.german.holidays.corpus-christi.enabled=false
taskana.history.deletion.on.task.deletion.enabled=true
taskana.workingtime.schedule.MONDAY=00:00-00:00
taskana.workingtime.schedule.TUESDAY=00:00-00:00
taskana.workingtime.schedule.WEDNESDAY=00:00-00:00
taskana.workingtime.schedule.THURSDAY=00:00-00:00
taskana.workingtime.schedule.FRIDAY=00:00-00:00
taskana.workingtime.timezone=UTC
taskana.jobs.cleanup.history.simple.minimumAge=P15D
taskana.workingTime.holidays.german.enabled=true
taskana.workingTime.holidays.german.corpus-christi.enabled=false
taskana.history.simple.deleteOnTaskDeletion.enabled=true
taskana.workingTime.schedule.MONDAY=00:00-00:00
taskana.workingTime.schedule.TUESDAY=00:00-00:00
taskana.workingTime.schedule.WEDNESDAY=00:00-00:00
taskana.workingTime.schedule.THURSDAY=00:00-00:00
taskana.workingTime.schedule.FRIDAY=00:00-00:00
taskana.workingTime.timezone=UTC
# enable or disable the jobscheduler at all
# set it to false and no jobs are running
taskana.jobscheduler.enabled=false
taskana.jobs.scheduler.enabled=false
# wait time before the first job run in millis
taskana.jobscheduler.initialstartdelay=100
taskana.jobs.scheduler.initialStartDelay=100
# sleeping time befor the next job runs
taskana.jobscheduler.period=12
taskana.jobs.scheduler.period=12
# timeunit for the sleeping period
# Possible values: MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS
taskana.jobscheduler.periodtimeunit=HOURS
taskana.jobscheduler.enableTaskCleanupJob=true
taskana.jobscheduler.enableTaskUpdatePriorityJob=true
taskana.jobscheduler.enableWorkbasketCleanupJob=true
taskana.jobscheduler.enableUserInfoRefreshJob=false
taskana.jobscheduler.enableHistorieCleanupJob=true
taskana.jobs.scheduler.periodTimeUnit=HOURS
taskana.jobs.cleanup.task.enable=true
taskana.jobs.priority.task.enable=true
taskana.jobs.cleanup.workbasket.enable=true
taskana.jobs.refresh.user.enable=false
taskana.jobs.cleanup.history.simple.enable=true

View File

@ -1,20 +1,20 @@
taskana.roles.user=cn=ksc-users,cn=groups,OU=Test,O=TASKANA | teamlead-1 | teamlead-2 | user-1-1 | user-1-2 | user-2-1 | user-2-2 | user-b-1 | user-b-2
taskana.roles.admin=admin | uid=admin,cn=users,OU=Test,O=TASKANA
taskana.roles.businessadmin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.business_admin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.monitor=monitor | cn=monitor-users,cn=groups,OU=Test,O=TASKANA
taskana.roles.taskadmin=taskadmin
taskana.domains=DOMAIN_A , DOMAIN_B
taskana.roles.task_admin=taskadmin
taskana.domains=DOMAIN_A | DOMAIN_B
taskana.user.minimalPermissionsToAssignDomains=READ | OPEN
taskana.classification.types=TASK , document
taskana.classification.categories.task=EXTERNAL, manual, autoMAtic, Process
taskana.classification.types=TASK | document
taskana.classification.categories.task=EXTERNAL| manual| autoMAtic| Process
taskana.classification.categories.document=EXTERNAL
taskana.jobs.maxRetries=3
taskana.jobs.batchSize=50
taskana.jobs.cleanup.runEvery=P1D
taskana.jobs.cleanup.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.minimumAge=P14D
taskana.german.holidays.enabled=true
taskana.german.holidays.corpus-christi.enabled=false
taskana.history.deletion.on.task.deletion.enabled=true
taskana.jobs.runEvery=P1D
taskana.jobs.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.task.minimumAge=P14D
taskana.workingTime.holidays.german.enabled=true
taskana.workingTime.holidays.german.corpus-christi.enabled=false
taskana.history.simple.deleteOnTaskDeletion.enabled=true

View File

@ -1,18 +1,19 @@
datasource.jndi=java:jboss/datasources/TestDS
taskana.domains=CDIDOMAIN
taskana.classification.types=T1
taskana.classification.categories.T1=DEFAULT
# enable or disable the jobscheduler at all
# set it to false and no jobs are running
taskana.jobscheduler.enabled=true
taskana.jobs.scheduler.enabled=true
# wait time before the first job run in millis
taskana.jobscheduler.initialstartdelay=100
taskana.jobs.scheduler.initialStartDelay=100
# sleeping time befor the next job runs
taskana.jobscheduler.period=1
taskana.jobs.scheduler.period=1
# timeunit for the sleeping period
# Possible values: MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS
taskana.jobscheduler.periodtimeunit=HOURS
taskana.jobscheduler.enableTaskCleanupJob=true
taskana.jobscheduler.enableTaskUpdatePriorityJob=true
taskana.jobscheduler.enableWorkbasketCleanupJob=true
taskana.jobscheduler.enableUserInfoRefreshJob=false
taskana.jobscheduler.enableHistorieCleanupJob=false
taskana.jobs.scheduler.periodTimeUnit=HOURS
taskana.jobs.cleanup.task.enable=true
taskana.jobs.priority.task.enable=true
taskana.jobs.cleanup.workbasket.enable=true
taskana.jobs.refresh.user.enable=false
taskana.jobs.cleanup.history.simple.enable=false

View File

@ -1,10 +1,13 @@
package acceptance;
import static java.util.function.Predicate.not;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.time.DayOfWeek;
import java.time.Duration;
import java.time.Instant;
@ -12,12 +15,16 @@ import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.sql.DataSource;
import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.Test;
@ -31,11 +38,28 @@ import pro.taskana.common.api.CustomHoliday;
import pro.taskana.common.api.LocalTimeInterval;
import pro.taskana.common.api.TaskanaRole;
import pro.taskana.common.api.exceptions.InvalidArgumentException;
import pro.taskana.common.internal.configuration.TaskanaProperty;
import pro.taskana.common.internal.util.CheckedConsumer;
import pro.taskana.common.internal.util.Pair;
import pro.taskana.common.internal.util.ReflectionUtil;
import pro.taskana.testapi.extensions.TestContainerExtension;
import pro.taskana.workbasket.api.WorkbasketPermission;
class TaskanaConfigurationTest {
public static final Map<String, String> TASKANA_PROPERTY_NAME_BY_FIELD_NAME =
ReflectionUtil.retrieveAllFields(Builder.class).stream()
.collect(
Collectors.toMap(
Field::getName,
f -> {
if (f.isAnnotationPresent(TaskanaProperty.class)) {
return f.getAnnotation(TaskanaProperty.class).value();
}
return "";
}));
// TODO: test for nested collections and validate they are immutable as well.
// Example: List<List<String>> or Map<String, List<String>>
@TestFactory
Stream<DynamicTest> should_SaveUnmodifiableCollections() {
@ -91,167 +115,547 @@ class TaskanaConfigurationTest {
return DynamicTest.stream(fields, Field::getName, testCase);
}
@TestFactory
Stream<DynamicTest> should_HaveBuilderMethod_For_EachOptionalConfiguration() {
Stream<Field> fields =
ReflectionUtil.retrieveAllFields(Builder.class).stream()
.filter(not(f -> Modifier.isStatic(f.getModifiers())))
.filter(not(f -> Modifier.isFinal(f.getModifiers())))
.filter(not(f -> "properties".equals(f.getName())));
ThrowingConsumer<Field> testCase =
field -> {
// throws Exception if anything is wrong with the builder method
Method method = Builder.class.getMethod(field.getName(), field.getType());
assertThat(method).isNotNull();
assertThat(method.getReturnType()).isEqualTo(Builder.class);
};
return DynamicTest.stream(fields, Field::getName, testCase);
}
@TestFactory
Stream<DynamicTest> should_HaveTaskanaPropertyAnnotation_For_EachOptionalConfiguration() {
Stream<Field> fields =
ReflectionUtil.retrieveAllFields(Builder.class).stream()
.filter(not(f -> Modifier.isStatic(f.getModifiers())))
.filter(not(f -> Modifier.isFinal(f.getModifiers())))
.filter(not(f -> "properties".equals(f.getName())));
ThrowingConsumer<Field> testCase =
field -> assertThat(field.isAnnotationPresent(TaskanaProperty.class)).isTrue();
return DynamicTest.stream(fields, Field::getName, testCase);
}
@Test
void should_ShareConfigurationNamesWithBuilder() {
Set<Pair<String, ? extends Class<?>>> configurationFields =
ReflectionUtil.retrieveAllFields(TaskanaConfiguration.class).stream()
.filter(not(f -> Modifier.isStatic(f.getModifiers())))
.map(field -> Pair.of(field.getName(), field.getType()))
.collect(Collectors.toSet());
Set<Pair<String, ? extends Class<?>>> builderFields =
ReflectionUtil.retrieveAllFields(TaskanaConfiguration.Builder.class).stream()
.filter(not(f -> Modifier.isStatic(f.getModifiers())))
.map(field -> Pair.of(field.getName(), field.getType()))
.collect(Collectors.toSet());
assertThat(configurationFields)
.as("TaskanaConfiguration and its builder should have the same configuration names")
.containsExactlyInAnyOrderElementsOf(builderFields);
}
@Test
void should_SetDefaultValues() {
Set<LocalTimeInterval> standardWorkingSlots =
Set.of(new LocalTimeInterval(LocalTime.MIN, LocalTime.MAX));
Map<DayOfWeek, Set<LocalTimeInterval>> defaultWorkingTimeSchedule =
Map.ofEntries(
Map.entry(DayOfWeek.MONDAY, standardWorkingSlots),
Map.entry(DayOfWeek.TUESDAY, standardWorkingSlots),
Map.entry(DayOfWeek.WEDNESDAY, standardWorkingSlots),
Map.entry(DayOfWeek.THURSDAY, standardWorkingSlots),
Map.entry(DayOfWeek.FRIDAY, standardWorkingSlots));
TaskanaConfiguration configuration =
new Builder(TestContainerExtension.createDataSourceForH2(), true, "schemaName").build();
// general configuration
assertThat(configuration.isSecurityEnabled()).isTrue();
assertThat(configuration.getDomains()).isEqualTo(Collections.emptySet());
assertThat(configuration.isEnforceServiceLevel()).isTrue();
// authentication configuration
assertThat(configuration.getRoleMap())
.isEqualTo(
Arrays.stream(TaskanaRole.values())
.collect(Collectors.toMap(Function.identity(), r -> Set.of())));
// classification configuration
assertThat(configuration.getClassificationTypes()).isEqualTo(Collections.emptySet());
assertThat(configuration.getClassificationCategoriesByType()).isEqualTo(Collections.emptyMap());
// working time configuration
assertThat(configuration.getWorkingTimeSchedule()).isEqualTo(defaultWorkingTimeSchedule);
assertThat(configuration.getWorkingTimeScheduleTimeZone())
.isEqualTo(ZoneId.of("Europe/Berlin"));
assertThat(configuration.getCustomHolidays()).isEqualTo(Collections.emptySet());
assertThat(configuration.isGermanPublicHolidaysEnabled()).isTrue();
assertThat(configuration.isGermanPublicHolidaysCorpusChristiEnabled()).isFalse();
// history configuration
assertThat(configuration.isDeleteHistoryEventsOnTaskDeletionEnabled()).isFalse();
assertThat(configuration.getLogHistoryLoggerName()).isNull();
// job configuration
assertThat(configuration.isJobSchedulerEnabled()).isTrue();
assertThat(configuration.getJobSchedulerInitialStartDelay()).isEqualTo(100);
assertThat(configuration.getJobSchedulerPeriod()).isEqualTo(5);
assertThat(configuration.getJobSchedulerPeriodTimeUnit()).isEqualTo(TimeUnit.MINUTES);
assertThat(configuration.getMaxNumberOfJobRetries()).isEqualTo(3);
assertThat(configuration.getJobBatchSize()).isEqualTo(100);
assertThat(configuration.getJobFirstRun()).isEqualTo(Instant.parse("2023-01-01T00:00:00Z"));
assertThat(configuration.getJobRunEvery()).isEqualTo(Duration.ofDays(1));
assertThat(configuration.isTaskCleanupJobEnabled()).isTrue();
assertThat(configuration.getTaskCleanupJobMinimumAge()).isEqualTo(Duration.ofDays(14));
assertThat(configuration.isTaskCleanupJobAllCompletedSameParentBusiness()).isTrue();
assertThat(configuration.isWorkbasketCleanupJobEnabled()).isTrue();
assertThat(configuration.isSimpleHistoryCleanupJobEnabled()).isFalse();
assertThat(configuration.getSimpleHistoryCleanupJobBatchSize()).isEqualTo(100);
assertThat(configuration.getSimpleHistoryCleanupJobMinimumAge()).isEqualTo(Duration.ofDays(14));
assertThat(configuration.isSimpleHistoryCleanupJobAllCompletedSameParentBusiness()).isTrue();
assertThat(configuration.isTaskUpdatePriorityJobEnabled()).isFalse();
assertThat(configuration.getTaskUpdatePriorityJobBatchSize()).isEqualTo(100);
assertThat(configuration.getTaskUpdatePriorityJobFirstRun())
.isEqualTo(Instant.parse("2023-01-01T00:00:00Z"));
assertThat(configuration.getTaskUpdatePriorityJobRunEvery()).isEqualTo(Duration.ofDays(1));
assertThat(configuration.isUserInfoRefreshJobEnabled()).isFalse();
assertThat(configuration.getUserRefreshJobFirstRun())
.isEqualTo(Instant.parse("2023-01-01T23:00:00Z"));
assertThat(configuration.getUserRefreshJobRunEvery()).isEqualTo(Duration.ofDays(1));
assertThat(configuration.getCustomJobs()).isEqualTo(Collections.emptySet());
// user configuration
assertThat(configuration.isAddAdditionalUserInfo()).isFalse();
assertThat(configuration.getMinimalPermissionsToAssignDomains())
.isEqualTo(Collections.emptySet());
}
@Test
void should_PopulateEveryTaskanaConfiguration_When_ImportingPropertiesFile() {
TaskanaConfiguration configuration =
new Builder(TestContainerExtension.createDataSourceForH2(), true, "TASKANA")
.initTaskanaProperties("/fullTaskana.properties")
.build();
verifyConfigurationValuesDifferFromDefaultConfiguration(configuration);
// general configuration
assertThat(configuration.getDomains()).isEqualTo(Set.of("DOMAIN_A", "DOMAIN_B"));
assertThat(configuration.isEnforceServiceLevel()).isFalse();
// authentication configuration
assertThat(configuration.getRoleMap())
.isEqualTo(
Map.ofEntries(
Map.entry(TaskanaRole.USER, Set.of("user-1", "user-2")),
Map.entry(TaskanaRole.ADMIN, Set.of("admin-1", "admin-2")),
Map.entry(TaskanaRole.BUSINESS_ADMIN, Set.of("businessadmin-1", "businessadmin-2")),
Map.entry(TaskanaRole.MONITOR, Set.of("monitor-1", "monitor-2")),
Map.entry(TaskanaRole.TASK_ADMIN, Set.of("taskadmin-1", "taskadmin-2")),
Map.entry(TaskanaRole.TASK_ROUTER, Set.of("taskrouter-1", "taskrouter-2"))));
// classification configuration
assertThat(configuration.getClassificationTypes()).isEqualTo(Set.of("TASK", "DOCUMENT"));
assertThat(configuration.getClassificationCategoriesByType())
.isEqualTo(
Map.ofEntries(
Map.entry("TASK", Set.of("EXTERNAL", "MANUAL", "AUTOMATIC", "PROCESS")),
Map.entry("DOCUMENT", Set.of("EXTERNAL"))));
// working time configuration
// assertThat(configuration.getWorkingTimeSchedule()).isEqualTo(defaultWorkingTimeSchedule);
assertThat(configuration.getWorkingTimeScheduleTimeZone()).isEqualTo(ZoneId.of("UTC"));
assertThat(configuration.getCustomHolidays())
.isEqualTo(Set.of(CustomHoliday.of(31, 7), CustomHoliday.of(16, 12)));
assertThat(configuration.isGermanPublicHolidaysEnabled()).isFalse();
assertThat(configuration.isGermanPublicHolidaysCorpusChristiEnabled()).isTrue();
// history configuration
assertThat(configuration.isDeleteHistoryEventsOnTaskDeletionEnabled()).isTrue();
assertThat(configuration.getLogHistoryLoggerName()).isEqualTo("AUDIT");
// job configuration
assertThat(configuration.isJobSchedulerEnabled()).isFalse();
assertThat(configuration.getJobSchedulerInitialStartDelay()).isEqualTo(30);
assertThat(configuration.getJobSchedulerPeriod()).isEqualTo(12);
assertThat(configuration.getJobSchedulerPeriodTimeUnit()).isEqualTo(TimeUnit.HOURS);
assertThat(configuration.getMaxNumberOfJobRetries()).isEqualTo(4);
assertThat(configuration.getJobBatchSize()).isEqualTo(50);
assertThat(configuration.getJobFirstRun()).isEqualTo(Instant.parse("2018-07-25T08:00:00Z"));
assertThat(configuration.getJobRunEvery()).isEqualTo(Duration.ofDays(2));
assertThat(configuration.isTaskCleanupJobEnabled()).isFalse();
assertThat(configuration.getTaskCleanupJobMinimumAge()).isEqualTo(Duration.ofDays(15));
assertThat(configuration.isTaskCleanupJobAllCompletedSameParentBusiness()).isFalse();
assertThat(configuration.isWorkbasketCleanupJobEnabled()).isFalse();
assertThat(configuration.isSimpleHistoryCleanupJobEnabled()).isTrue();
assertThat(configuration.getSimpleHistoryCleanupJobBatchSize()).isEqualTo(50);
assertThat(configuration.getSimpleHistoryCleanupJobMinimumAge()).isEqualTo(Duration.ofDays(17));
assertThat(configuration.isSimpleHistoryCleanupJobAllCompletedSameParentBusiness()).isFalse();
assertThat(configuration.isTaskUpdatePriorityJobEnabled()).isTrue();
assertThat(configuration.getTaskUpdatePriorityJobBatchSize()).isEqualTo(50);
assertThat(configuration.getTaskUpdatePriorityJobFirstRun())
.isEqualTo(Instant.parse("2018-07-25T08:00:00Z"));
assertThat(configuration.getTaskUpdatePriorityJobRunEvery()).isEqualTo(Duration.ofDays(3));
assertThat(configuration.isUserInfoRefreshJobEnabled()).isTrue();
assertThat(configuration.getUserRefreshJobFirstRun())
.isEqualTo(Instant.parse("2018-07-25T08:00:00Z"));
assertThat(configuration.getUserRefreshJobRunEvery()).isEqualTo(Duration.ofDays(4));
assertThat(configuration.getCustomJobs()).isEqualTo(Set.of("A", "B", "C"));
// user configuration
assertThat(configuration.isAddAdditionalUserInfo()).isTrue();
assertThat(configuration.getMinimalPermissionsToAssignDomains())
.isEqualTo(Set.of(WorkbasketPermission.READ, WorkbasketPermission.OPEN));
assertThat(configuration.getProperties())
.contains(
Map.entry("mycustomproperty1", "mycustomvalue1"),
Map.entry("mycustomproperty2", "mycustomvalue2"));
}
@Test
void should_PopulateEveryTaskanaConfiguration_When_EveryBuilderFunctionIsCalled() {
// given
List<String> expectedDomains = List.of("A", "B");
Map<TaskanaRole, Set<String>> expectedRoleMap = Map.of(TaskanaRole.ADMIN, Set.of("admin"));
List<String> expectedClassificationTypes = List.of("typeA", "typeB");
Map<String, List<String>> expectedClassificationCategories =
Map.of("typeA", List.of("categoryA"), "typeB", List.of("categoryB"));
List<CustomHoliday> expectedCustomHolidays = List.of(CustomHoliday.of(10, 10));
int expectedJobBatchSize = 50;
int expectedNumberOfJobRetries = 500;
Instant expectedCleanupJobFirstJun = Instant.MIN;
Duration expectedCleanupJobRunEvery = Duration.ofDays(2);
Duration expectedCleanupJobMinimumAge = Duration.ofDays(1);
int expectedPriorityJobBatchSize = 49;
Instant expectedPriorityJobFirstRun = Instant.MIN.plus(1, ChronoUnit.DAYS);
Instant expectedUserRefreshJobFirstRun = Instant.MIN.plus(2, ChronoUnit.DAYS);
Duration expectedUserRefreshJobRunEvery = Duration.ofDays(5);
List<WorkbasketPermission> expectedMinimalPermissionsToAssignDomains =
List.of(WorkbasketPermission.CUSTOM_2);
// general configuration
DataSource expectedDataSource = TestContainerExtension.createDataSourceForH2();
boolean expectedUseManagedTransactions = false;
String expectedSchemaName = "TASKANA";
boolean expectedSecurityEnabled = false;
Set<String> expectedDomains = Set.of("A", "B");
boolean expectedEnforceServiceLevel = false;
// authentication configuration
Map<TaskanaRole, Set<String>> expectedRoleMap =
Map.ofEntries(
Map.entry(TaskanaRole.USER, Set.of("user")),
Map.entry(TaskanaRole.BUSINESS_ADMIN, Set.of("business_admin")),
Map.entry(TaskanaRole.ADMIN, Set.of("admin")),
Map.entry(TaskanaRole.MONITOR, Set.of("monitor")),
Map.entry(TaskanaRole.TASK_ADMIN, Set.of("task_admin")),
Map.entry(TaskanaRole.TASK_ROUTER, Set.of("task_router")));
// classification configuration
Set<String> expectedClassificationTypes = Set.of("TYPEA", "TYPEB");
Map<String, Set<String>> expectedClassificationCategories =
Map.of("TYPEA", Set.of("CATEGORYA"), "TYPEB", Set.of("CATEGORYB"));
// working time configuration
Map<DayOfWeek, Set<LocalTimeInterval>> expectedWorkingTimeSchedule =
Map.of(DayOfWeek.MONDAY, Set.of(new LocalTimeInterval(LocalTime.MIN, LocalTime.NOON)));
ZoneId expectedWorkingTimeScheduleTimeZone = ZoneId.ofOffset("UTC", ZoneOffset.ofHours(4));
Set<CustomHoliday> expectedCustomHolidays = Set.of(CustomHoliday.of(10, 10));
boolean expectedGermanPublicHolidaysEnabled = false;
boolean expectedGermanPublicHolidaysCorpusChristiEnabled = true;
// history configuration
boolean expectedDeleteHistoryEventsOnTaskDeletionEnabled = true;
String expectedLogHistoryLoggerName = "LOGGER_NAME";
// job configuration
boolean expectedJobSchedulerEnabled = false;
long expectedJobSchedulerInitialStartDelay = 15;
long expectedJobSchedulerPeriod = 10;
TimeUnit expectedJobSchedulerPeriodTimeUnit = TimeUnit.DAYS;
List<String> expectedJobSchedulerCustomJobs = List.of("Job_A", "Job_B");
ZoneId expectedWorkingTimeScheduleTimeZone = ZoneId.ofOffset("UTC", ZoneOffset.ofHours(4));
int expectedNumberOfJobRetries = 500;
int expectedJobBatchSize = 50;
Instant expectedJobFirstJun = Instant.MIN;
Duration expectedJobRunEvery = Duration.ofDays(2);
boolean expectedTaskCleanupJobEnabled = false;
Duration expectedTaskCleanupJobMinimumAge = Duration.ofDays(1);
boolean expectedTaskCleanupJobAllCompletedSameParentBusiness = false;
boolean expectedWorkbasketCleanupJobEnabled = false;
boolean expectedSimpleHistoryCleanupJobEnabled = true;
int expectedSimpleHistoryCleanupJobBatchSize = 16;
Duration expectedSimpleHistoryCleanupJobMinimumAge = Duration.ofHours(3);
boolean expectedSimpleHistoryCleanupJobAllCompletedSameParentBusiness = false;
boolean expectedTaskUpdatePriorityJobEnabled = true;
int expectedPriorityJobBatchSize = 49;
Instant expectedPriorityJobFirstRun = Instant.MIN.plus(1, ChronoUnit.DAYS);
Duration expectedTaskUpdatePriorityJobRunEvery = Duration.ofMinutes(17);
boolean expectedUserInfoRefreshJobEnabled = true;
Instant expectedUserRefreshJobFirstRun = Instant.MIN.plus(2, ChronoUnit.DAYS);
Duration expectedUserRefreshJobRunEvery = Duration.ofDays(5);
Set<String> expectedJobSchedulerCustomJobs = Set.of("Job_A", "Job_B");
// user configuration
boolean expectedAddAdditionalUserInfo = true;
Set<WorkbasketPermission> expectedMinimalPermissionsToAssignDomains =
Set.of(WorkbasketPermission.CUSTOM_2);
// when
Map<DayOfWeek, Set<LocalTimeInterval>> expectedWorkingTimeSchedule =
Map.of(DayOfWeek.MONDAY, Set.of(new LocalTimeInterval(LocalTime.MIN, LocalTime.NOON)));
TaskanaConfiguration configuration =
new Builder(TestContainerExtension.createDataSourceForH2(), false, "TASKANA")
new Builder(
expectedDataSource,
expectedUseManagedTransactions,
expectedSchemaName,
expectedSecurityEnabled)
// general configuration
.domains(expectedDomains)
.enforceServiceLevel(expectedEnforceServiceLevel)
// authentication configuration
.roleMap(expectedRoleMap)
// classification configuration
.classificationTypes(expectedClassificationTypes)
.classificationCategoriesByTypeMap(expectedClassificationCategories)
.allowTimestampServiceLevelMismatch(true)
.classificationCategoriesByType(expectedClassificationCategories)
// working time configuration
.workingTimeSchedule(expectedWorkingTimeSchedule)
.workingTimeScheduleTimeZone(expectedWorkingTimeScheduleTimeZone)
.customHolidays(expectedCustomHolidays)
.germanPublicHolidaysEnabled(true)
.corpusChristiEnabled(true)
.deleteHistoryOnTaskDeletionEnabled(true)
.jobBatchSize(expectedJobBatchSize)
.maxNumberOfJobRetries(expectedNumberOfJobRetries)
.cleanupJobFirstRun(expectedCleanupJobFirstJun)
.cleanupJobRunEvery(expectedCleanupJobRunEvery)
.cleanupJobMinimumAge(expectedCleanupJobMinimumAge)
.taskCleanupJobAllCompletedSameParentBusiness(false)
.priorityJobBatchSize(expectedPriorityJobBatchSize)
.priorityJobFirstRun(expectedPriorityJobFirstRun)
.priorityJobActive(true)
.userRefreshJobFirstRun(expectedUserRefreshJobFirstRun)
.userRefreshJobRunEvery(expectedUserRefreshJobRunEvery)
.addAdditionalUserInfo(true)
.minimalPermissionsToAssignDomains(expectedMinimalPermissionsToAssignDomains)
.jobSchedulerEnabled(false)
.germanPublicHolidaysEnabled(expectedGermanPublicHolidaysEnabled)
.germanPublicHolidaysCorpusChristiEnabled(
expectedGermanPublicHolidaysCorpusChristiEnabled)
// history configuration
.deleteHistoryEventsOnTaskDeletionEnabled(
expectedDeleteHistoryEventsOnTaskDeletionEnabled)
.logHistoryLoggerName(expectedLogHistoryLoggerName)
// job configuration
.jobSchedulerEnabled(expectedJobSchedulerEnabled)
.jobSchedulerInitialStartDelay(expectedJobSchedulerInitialStartDelay)
.jobSchedulerPeriod(expectedJobSchedulerPeriod)
.jobSchedulerPeriodTimeUnit(expectedJobSchedulerPeriodTimeUnit)
.jobSchedulerEnableTaskCleanupJob(false)
.jobSchedulerEnableTaskUpdatePriorityJob(false)
.jobSchedulerEnableWorkbasketCleanupJob(false)
.jobSchedulerEnableUserInfoRefreshJob(false)
.jobSchedulerEnableHistorieCleanupJob(false)
.jobSchedulerCustomJobs(expectedJobSchedulerCustomJobs)
.workingTimeSchedule(expectedWorkingTimeSchedule)
.workingTimeScheduleTimeZone(expectedWorkingTimeScheduleTimeZone)
.maxNumberOfJobRetries(expectedNumberOfJobRetries)
.jobBatchSize(expectedJobBatchSize)
.jobFirstRun(expectedJobFirstJun)
.jobRunEvery(expectedJobRunEvery)
.taskCleanupJobEnabled(expectedTaskCleanupJobEnabled)
.taskCleanupJobMinimumAge(expectedTaskCleanupJobMinimumAge)
.taskCleanupJobAllCompletedSameParentBusiness(
expectedTaskCleanupJobAllCompletedSameParentBusiness)
.workbasketCleanupJobEnabled(expectedWorkbasketCleanupJobEnabled)
.simpleHistoryCleanupJobEnabled(expectedSimpleHistoryCleanupJobEnabled)
.simpleHistoryCleanupJobBatchSize(expectedSimpleHistoryCleanupJobBatchSize)
.simpleHistoryCleanupJobMinimumAge(expectedSimpleHistoryCleanupJobMinimumAge)
.simpleHistoryCleanupJobAllCompletedSameParentBusiness(
expectedSimpleHistoryCleanupJobAllCompletedSameParentBusiness)
.taskUpdatePriorityJobEnabled(expectedTaskUpdatePriorityJobEnabled)
.taskUpdatePriorityJobBatchSize(expectedPriorityJobBatchSize)
.taskUpdatePriorityJobFirstRun(expectedPriorityJobFirstRun)
.taskUpdatePriorityJobRunEvery(expectedTaskUpdatePriorityJobRunEvery)
.userInfoRefreshJobEnabled(expectedUserInfoRefreshJobEnabled)
.userRefreshJobFirstRun(expectedUserRefreshJobFirstRun)
.userRefreshJobRunEvery(expectedUserRefreshJobRunEvery)
.customJobs(expectedJobSchedulerCustomJobs)
// user configuration
.addAdditionalUserInfo(expectedAddAdditionalUserInfo)
.minimalPermissionsToAssignDomains(expectedMinimalPermissionsToAssignDomains)
.build();
// then
assertThat(configuration).hasNoNullFieldsOrProperties();
verifyConfigurationValuesDifferFromDefaultConfiguration(configuration);
// general configuration
assertThat(configuration.getDataSource()).isEqualTo(expectedDataSource);
assertThat(configuration.isUseManagedTransactions()).isEqualTo(expectedUseManagedTransactions);
assertThat(configuration.getSchemaName()).isEqualTo(expectedSchemaName);
assertThat(configuration.isSecurityEnabled()).isEqualTo(expectedSecurityEnabled);
assertThat(configuration.getDomains()).isEqualTo(expectedDomains);
assertThat(configuration.isEnforceServiceLevel()).isEqualTo(expectedEnforceServiceLevel);
// authentication configuration
assertThat(configuration.getRoleMap()).isEqualTo(expectedRoleMap);
// classification configuration
assertThat(configuration.getClassificationTypes()).isEqualTo(expectedClassificationTypes);
assertThat(configuration.getClassificationCategoriesByType())
.isEqualTo(expectedClassificationCategories);
assertThat(configuration.isAllowTimestampServiceLevelMismatch()).isTrue();
// working time configuration
assertThat(configuration.getWorkingTimeSchedule()).isEqualTo(expectedWorkingTimeSchedule);
assertThat(configuration.getWorkingTimeScheduleTimeZone())
.isEqualTo(expectedWorkingTimeScheduleTimeZone);
assertThat(configuration.getCustomHolidays()).isEqualTo(expectedCustomHolidays);
assertThat(configuration.isGermanPublicHolidaysEnabled()).isTrue();
assertThat(configuration.isCorpusChristiEnabled()).isTrue();
assertThat(configuration.isDeleteHistoryOnTaskDeletionEnabled()).isTrue();
assertThat(configuration.getJobBatchSize()).isEqualTo(expectedJobBatchSize);
assertThat(configuration.getMaxNumberOfJobRetries()).isEqualTo(expectedNumberOfJobRetries);
assertThat(configuration.getCleanupJobFirstRun()).isEqualTo(expectedCleanupJobFirstJun);
assertThat(configuration.getCleanupJobRunEvery()).isEqualTo(expectedCleanupJobRunEvery);
assertThat(configuration.getCleanupJobMinimumAge()).isEqualTo(expectedCleanupJobMinimumAge);
assertThat(configuration.isTaskCleanupJobAllCompletedSameParentBusiness()).isFalse();
assertThat(configuration.getPriorityJobBatchSize()).isEqualTo(expectedPriorityJobBatchSize);
assertThat(configuration.getPriorityJobFirstRun()).isEqualTo(expectedPriorityJobFirstRun);
assertThat(configuration.isPriorityJobActive()).isTrue();
assertThat(configuration.getUserRefreshJobFirstRun()).isEqualTo(expectedUserRefreshJobFirstRun);
assertThat(configuration.getUserRefreshJobRunEvery()).isEqualTo(expectedUserRefreshJobRunEvery);
assertThat(configuration.isAddAdditionalUserInfo()).isTrue();
assertThat(configuration.getMinimalPermissionsToAssignDomains())
.isEqualTo(expectedMinimalPermissionsToAssignDomains);
assertThat(configuration.isJobSchedulerEnabled()).isFalse();
assertThat(configuration.isGermanPublicHolidaysEnabled())
.isEqualTo(expectedGermanPublicHolidaysEnabled);
assertThat(configuration.isGermanPublicHolidaysCorpusChristiEnabled())
.isEqualTo(expectedGermanPublicHolidaysCorpusChristiEnabled);
// history configuration
assertThat(configuration.isDeleteHistoryEventsOnTaskDeletionEnabled())
.isEqualTo(expectedDeleteHistoryEventsOnTaskDeletionEnabled);
assertThat(configuration.getLogHistoryLoggerName()).isEqualTo(expectedLogHistoryLoggerName);
// job configuration
assertThat(configuration.isJobSchedulerEnabled()).isEqualTo(expectedJobSchedulerEnabled);
assertThat(configuration.getJobSchedulerInitialStartDelay())
.isEqualTo(expectedJobSchedulerInitialStartDelay);
assertThat(configuration.getJobSchedulerPeriod()).isEqualTo(expectedJobSchedulerPeriod);
assertThat(configuration.getJobSchedulerPeriodTimeUnit())
.isEqualTo(expectedJobSchedulerPeriodTimeUnit);
assertThat(configuration.isJobSchedulerEnableTaskCleanupJob()).isFalse();
assertThat(configuration.isJobSchedulerEnableTaskUpdatePriorityJob()).isFalse();
assertThat(configuration.isJobSchedulerEnableWorkbasketCleanupJob()).isFalse();
assertThat(configuration.isJobSchedulerEnableUserInfoRefreshJob()).isFalse();
assertThat(configuration.isJobSchedulerEnableHistorieCleanupJob()).isFalse();
assertThat(configuration.getJobSchedulerCustomJobs()).isEqualTo(expectedJobSchedulerCustomJobs);
assertThat(configuration.getWorkingTimeSchedule()).isEqualTo(expectedWorkingTimeSchedule);
assertThat(configuration.getWorkingTimeScheduleTimeZone())
.isEqualTo(expectedWorkingTimeScheduleTimeZone);
assertThat(configuration.getMaxNumberOfJobRetries()).isEqualTo(expectedNumberOfJobRetries);
assertThat(configuration.getJobBatchSize()).isEqualTo(expectedJobBatchSize);
assertThat(configuration.getJobFirstRun()).isEqualTo(expectedJobFirstJun);
assertThat(configuration.getJobRunEvery()).isEqualTo(expectedJobRunEvery);
assertThat(configuration.isTaskCleanupJobEnabled()).isEqualTo(expectedTaskCleanupJobEnabled);
assertThat(configuration.getTaskCleanupJobMinimumAge())
.isEqualTo(expectedTaskCleanupJobMinimumAge);
assertThat(configuration.isTaskCleanupJobAllCompletedSameParentBusiness())
.isEqualTo(expectedTaskCleanupJobAllCompletedSameParentBusiness);
assertThat(configuration.isWorkbasketCleanupJobEnabled())
.isEqualTo(expectedWorkbasketCleanupJobEnabled);
assertThat(configuration.isSimpleHistoryCleanupJobEnabled())
.isEqualTo(expectedSimpleHistoryCleanupJobEnabled);
assertThat(configuration.getSimpleHistoryCleanupJobBatchSize())
.isEqualTo(expectedSimpleHistoryCleanupJobBatchSize);
assertThat(configuration.getSimpleHistoryCleanupJobMinimumAge())
.isEqualTo(expectedSimpleHistoryCleanupJobMinimumAge);
assertThat(configuration.isSimpleHistoryCleanupJobAllCompletedSameParentBusiness())
.isEqualTo(expectedSimpleHistoryCleanupJobAllCompletedSameParentBusiness);
assertThat(configuration.isTaskUpdatePriorityJobEnabled())
.isEqualTo(expectedTaskUpdatePriorityJobEnabled);
assertThat(configuration.getTaskUpdatePriorityJobBatchSize())
.isEqualTo(expectedPriorityJobBatchSize);
assertThat(configuration.getTaskUpdatePriorityJobFirstRun())
.isEqualTo(expectedPriorityJobFirstRun);
assertThat(configuration.getTaskUpdatePriorityJobRunEvery())
.isEqualTo(expectedTaskUpdatePriorityJobRunEvery);
assertThat(configuration.isUserInfoRefreshJobEnabled())
.isEqualTo(expectedUserInfoRefreshJobEnabled);
assertThat(configuration.getUserRefreshJobFirstRun()).isEqualTo(expectedUserRefreshJobFirstRun);
assertThat(configuration.getUserRefreshJobRunEvery()).isEqualTo(expectedUserRefreshJobRunEvery);
assertThat(configuration.getCustomJobs()).isEqualTo(expectedJobSchedulerCustomJobs);
// user configuration
assertThat(configuration.isAddAdditionalUserInfo()).isEqualTo(expectedAddAdditionalUserInfo);
assertThat(configuration.getMinimalPermissionsToAssignDomains())
.isEqualTo(expectedMinimalPermissionsToAssignDomains);
}
@Test
void should_PopulateEveryConfigurationProperty_When_UsingCopyConstructor() {
// given
TaskanaConfiguration configuration =
new Builder(TestContainerExtension.createDataSourceForH2(), false, "TASKANA")
.domains(List.of("A", "B"))
new Builder(TestContainerExtension.createDataSourceForH2(), false, "TASKANA", false)
// general configuration
.domains(Set.of("A", "B"))
.enforceServiceLevel(false)
// authentication configuration
.roleMap(Map.of(TaskanaRole.ADMIN, Set.of("admin")))
.classificationTypes(List.of("typeA", "typeB"))
.classificationCategoriesByTypeMap(
Map.of("typeA", List.of("categoryA"), "typeB", List.of("categoryB")))
.allowTimestampServiceLevelMismatch(true)
.customHolidays(List.of(CustomHoliday.of(10, 10)))
.germanPublicHolidaysEnabled(true)
.corpusChristiEnabled(true)
.deleteHistoryOnTaskDeletionEnabled(true)
.jobBatchSize(50)
.maxNumberOfJobRetries(500)
.cleanupJobFirstRun(Instant.MIN)
.cleanupJobRunEvery(Duration.ofDays(2))
.cleanupJobMinimumAge(Duration.ofDays(1))
.taskCleanupJobAllCompletedSameParentBusiness(false)
.priorityJobBatchSize(49)
.priorityJobFirstRun(Instant.MIN.plus(1, ChronoUnit.DAYS))
.priorityJobActive(true)
.userRefreshJobFirstRun(Instant.MIN.plus(2, ChronoUnit.DAYS))
.userRefreshJobRunEvery(Duration.ofDays(5))
.addAdditionalUserInfo(true)
.minimalPermissionsToAssignDomains(List.of(WorkbasketPermission.CUSTOM_2))
.jobSchedulerEnabled(false)
.jobSchedulerInitialStartDelay(10)
.jobSchedulerPeriod(15)
.jobSchedulerPeriodTimeUnit(TimeUnit.DAYS)
.jobSchedulerEnableTaskCleanupJob(false)
.jobSchedulerEnableTaskUpdatePriorityJob(false)
.jobSchedulerEnableWorkbasketCleanupJob(false)
.jobSchedulerEnableUserInfoRefreshJob(false)
.jobSchedulerEnableHistorieCleanupJob(false)
.jobSchedulerCustomJobs(List.of("Job_A", "Job_B"))
// classification configuration
.classificationTypes(Set.of("typeA", "typeB"))
.classificationCategoriesByType(
Map.of("typeA", Set.of("categoryA"), "typeB", Set.of("categoryB")))
// working time configuration
.workingTimeSchedule(
Map.of(
DayOfWeek.MONDAY, Set.of(new LocalTimeInterval(LocalTime.MIN, LocalTime.NOON))))
.workingTimeScheduleTimeZone(ZoneId.ofOffset("UTC", ZoneOffset.ofHours(4)))
.customHolidays(Set.of(CustomHoliday.of(10, 10)))
.germanPublicHolidaysEnabled(false)
.germanPublicHolidaysCorpusChristiEnabled(true)
// history configuration
.deleteHistoryEventsOnTaskDeletionEnabled(true)
.logHistoryLoggerName("LOGGER_NAME")
// job configuration
.jobSchedulerEnabled(false)
.jobSchedulerInitialStartDelay(15)
.jobSchedulerPeriod(10)
.jobSchedulerPeriodTimeUnit(TimeUnit.DAYS)
.maxNumberOfJobRetries(500)
.jobBatchSize(50)
.jobFirstRun(Instant.MIN)
.jobRunEvery(Duration.ofDays(2))
.taskCleanupJobEnabled(false)
.taskCleanupJobMinimumAge(Duration.ofDays(1))
.taskCleanupJobAllCompletedSameParentBusiness(false)
.workbasketCleanupJobEnabled(false)
.simpleHistoryCleanupJobEnabled(true)
.simpleHistoryCleanupJobBatchSize(16)
.simpleHistoryCleanupJobMinimumAge(Duration.ofHours(3))
.simpleHistoryCleanupJobAllCompletedSameParentBusiness(false)
.taskUpdatePriorityJobEnabled(true)
.taskUpdatePriorityJobBatchSize(49)
.taskUpdatePriorityJobFirstRun(Instant.MIN.plus(1, ChronoUnit.DAYS))
.taskUpdatePriorityJobRunEvery(Duration.ofMinutes(17))
.userInfoRefreshJobEnabled(true)
.userRefreshJobFirstRun(Instant.MIN.plus(2, ChronoUnit.DAYS))
.userRefreshJobRunEvery(Duration.ofDays(5))
.customJobs(Set.of("Job_A", "Job_B"))
// user configuration
.addAdditionalUserInfo(true)
.minimalPermissionsToAssignDomains(Set.of(WorkbasketPermission.CUSTOM_2))
.build();
TaskanaConfiguration copyConfiguration = new Builder(configuration).build();
verifyConfigurationValuesDifferFromDefaultConfiguration(configuration);
verifyConfigurationValuesDifferFromDefaultConfiguration(copyConfiguration);
assertThat(copyConfiguration)
.hasNoNullFieldsOrProperties()
.usingRecursiveComparison()
.isNotSameAs(configuration)
.isEqualTo(configuration);
}
@Test
void should_MakeDomainUpperCase() {
TaskanaConfiguration configuration =
new Builder(TestContainerExtension.createDataSourceForH2(), false, "TASKANA")
.domains(Set.of("a", "b"))
.build();
assertThat(configuration.getDomains()).containsExactlyInAnyOrder("A", "B");
}
@Test
void should_MakeClassificationTypesUpperCase() {
TaskanaConfiguration configuration =
new Builder(TestContainerExtension.createDataSourceForH2(), false, "TASKANA")
.classificationTypes(Set.of("a", "b"))
.classificationCategoriesByType(
Map.ofEntries(Map.entry("a", Set.of()), Map.entry("b", Set.of())))
.build();
assertThat(configuration.getClassificationTypes()).containsExactlyInAnyOrder("A", "B");
}
@Test
void should_MakeClassificationCategoriesUpperCase() {
TaskanaConfiguration configuration =
new Builder(TestContainerExtension.createDataSourceForH2(), false, "TASKANA")
.classificationTypes(Set.of("typea", "typeb"))
.classificationCategoriesByType(
Map.ofEntries(
Map.entry("typea", Set.of("a", "b")), Map.entry("typeb", Set.of("c", "d"))))
.build();
assertThat(configuration.getClassificationCategoriesByType())
.containsExactlyInAnyOrderEntriesOf(
Map.ofEntries(
Map.entry("TYPEA", Set.of("A", "B")), Map.entry("TYPEB", Set.of("C", "D"))));
}
@Test
void should_FillAllTaskanaRoles_When_RoleMapIsIncomplete() {
TaskanaConfiguration configuration =
new Builder(TestContainerExtension.createDataSourceForH2(), false, "TASKANA")
.roleMap(Map.ofEntries(Map.entry(TaskanaRole.ADMIN, Set.of("a", "b"))))
.build();
assertThat(configuration.getRoleMap())
.containsExactlyInAnyOrderEntriesOf(
Map.ofEntries(
Map.entry(TaskanaRole.USER, Set.of()),
Map.entry(TaskanaRole.BUSINESS_ADMIN, Set.of()),
Map.entry(TaskanaRole.ADMIN, Set.of("a", "b")),
Map.entry(TaskanaRole.MONITOR, Set.of()),
Map.entry(TaskanaRole.TASK_ADMIN, Set.of()),
Map.entry(TaskanaRole.TASK_ROUTER, Set.of())));
}
@Test
void should_MakeAccessIdsLowerCase() {
TaskanaConfiguration configuration =
new Builder(TestContainerExtension.createDataSourceForH2(), false, "TASKANA")
.roleMap(
Map.ofEntries(
Map.entry(TaskanaRole.USER, Set.of("USER-1", "USER-2")),
Map.entry(
TaskanaRole.BUSINESS_ADMIN, Set.of("BUSINESS_ADMIN-1", "BUSINESS_ADMIN-2")),
Map.entry(TaskanaRole.ADMIN, Set.of("ADMIN-1", "ADMIN-2")),
Map.entry(TaskanaRole.MONITOR, Set.of("MONITOR-1", "MONITOR-2")),
Map.entry(TaskanaRole.TASK_ADMIN, Set.of("TASK_ADMIN-1", "TASK_ADMIN-2")),
Map.entry(TaskanaRole.TASK_ROUTER, Set.of("TASK_ROUTER-1", "TASK_ROUTER-2"))))
.build();
assertThat(configuration.getRoleMap())
.containsExactlyInAnyOrderEntriesOf(
Map.ofEntries(
Map.entry(TaskanaRole.USER, Set.of("user-1", "user-2")),
Map.entry(
TaskanaRole.BUSINESS_ADMIN, Set.of("business_admin-1", "business_admin-2")),
Map.entry(TaskanaRole.ADMIN, Set.of("admin-1", "admin-2")),
Map.entry(TaskanaRole.MONITOR, Set.of("monitor-1", "monitor-2")),
Map.entry(TaskanaRole.TASK_ADMIN, Set.of("task_admin-1", "task_admin-2")),
Map.entry(TaskanaRole.TASK_ROUTER, Set.of("task_router-1", "task_router-2"))));
}
@ParameterizedTest
@ValueSource(ints = {-1, 0})
void should_ThrowInvalidArgumentException_When_JobBatchSizeIsNotPositive(int jobBatchSize) {
@ -289,87 +693,88 @@ class TaskanaConfigurationTest {
@ParameterizedTest
@ValueSource(strings = {"P-1D", "P0D"})
void should_ThrowInvalidArgumentException_When_CleanupJobRunEveryIsNotPositive(
void should_ThrowInvalidArgumentException_When_JobRunEveryIsNotPositive(
String cleanupJobRunEvery) {
TaskanaConfiguration.Builder builder =
new TaskanaConfiguration.Builder(
TestContainerExtension.createDataSourceForH2(), false, "TASKANA")
.jobBatchSize(1)
.maxNumberOfJobRetries(1)
.cleanupJobRunEvery(Duration.parse(cleanupJobRunEvery));
.jobRunEvery(Duration.parse(cleanupJobRunEvery));
ThrowingCallable call = builder::build;
assertThatThrownBy(call)
.isInstanceOf(InvalidArgumentException.class)
.hasMessageContaining(
"Parameter cleanupJobRunEvery (taskana.jobs.cleanup.runEvery)"
+ " must be a positive integer");
"Parameter jobRunEvery (taskana.jobs.runEvery) must be a positive duration");
}
@Test
void should_ThrowInvalidArgumentException_When_CleanupJobMinimumAgeIsNegative() {
void should_ThrowInvalidArgumentException_When_SimpleHistoryCleanupJobMinimumAgeIsNegative() {
TaskanaConfiguration.Builder builder =
new TaskanaConfiguration.Builder(
TestContainerExtension.createDataSourceForH2(), false, "TASKANA")
.jobBatchSize(1)
.maxNumberOfJobRetries(1)
.cleanupJobRunEvery(Duration.ofDays(1))
.cleanupJobMinimumAge(Duration.ofDays(-1));
.simpleHistoryCleanupJobMinimumAge(Duration.ofDays(-1));
ThrowingCallable call = builder::build;
assertThatThrownBy(call)
.isInstanceOf(InvalidArgumentException.class)
.hasMessageContaining(
"Parameter cleanupJobMinimumAge (taskana.jobs.cleanup.minimumAge)"
+ " must be a positive integer");
"Parameter simpleHistoryCleanupJobMinimumAge "
+ "(taskana.jobs.cleanup.history.simple.minimumAge) must not be negative");
}
@Test
void should_ThrowInvalidArgumentException_When_TaskCleanupJobMinimumAgeIsNegative() {
TaskanaConfiguration.Builder builder =
new TaskanaConfiguration.Builder(
TestContainerExtension.createDataSourceForH2(), false, "TASKANA")
.taskCleanupJobMinimumAge(Duration.ofDays(-1));
ThrowingCallable call = builder::build;
assertThatThrownBy(call)
.isInstanceOf(InvalidArgumentException.class)
.hasMessageContaining(
"Parameter taskCleanupJobMinimumAge (taskana.jobs.cleanup.task.minimumAge) "
+ "must not be negative");
}
@ParameterizedTest
@ValueSource(ints = {-1, 0})
void should_ThrowInvalidArgumentException_When_PriorityJobBatchSizeIsNotPositive(
void should_ThrowInvalidArgumentException_When_TaskUpdatePriorityJobBatchSizeIsNotPositive(
int priorityJobBatchSize) {
TaskanaConfiguration.Builder builder =
new TaskanaConfiguration.Builder(
TestContainerExtension.createDataSourceForH2(), false, "TASKANA")
.jobBatchSize(1)
.maxNumberOfJobRetries(1)
.cleanupJobRunEvery(Duration.ofDays(1))
.cleanupJobMinimumAge(Duration.ofDays(1))
.priorityJobBatchSize(priorityJobBatchSize);
.taskUpdatePriorityJobBatchSize(priorityJobBatchSize);
ThrowingCallable call = builder::build;
assertThatThrownBy(call)
.isInstanceOf(InvalidArgumentException.class)
.hasMessageContaining(
"Parameter priorityJobBatchSize (taskana.jobs.priority.batchSize)"
"Parameter taskUpdatePriorityJobBatchSize (taskana.jobs.priority.task.batchSize)"
+ " must be a positive integer");
}
@ParameterizedTest
@ValueSource(strings = {"P-1D", "P0D"})
void should_ThrowInvalidArgumentException_When_PriorityJobRunEveryIsNotPositive(
void should_ThrowInvalidArgumentException_When_TaskPriorityUpdatePriorityJobRunEveryIsNotPositive(
String priorityJobRunEvery) {
TaskanaConfiguration.Builder builder =
new TaskanaConfiguration.Builder(
TestContainerExtension.createDataSourceForH2(), false, "TASKANA")
.jobBatchSize(1)
.maxNumberOfJobRetries(1)
.cleanupJobRunEvery(Duration.ofDays(1))
.cleanupJobMinimumAge(Duration.ofDays(1))
.priorityJobBatchSize(1)
.priorityJobRunEvery(Duration.parse(priorityJobRunEvery));
.taskUpdatePriorityJobRunEvery(Duration.parse(priorityJobRunEvery));
ThrowingCallable call = builder::build;
assertThatThrownBy(call)
.isInstanceOf(InvalidArgumentException.class)
.hasMessageContaining(
"Parameter priorityJobRunEvery (taskana.jobs.priority.runEvery)"
+ " must be a positive integer");
"Parameter taskUpdatePriorityJobRunEvery (taskana.jobs.priority.task.runEvery)"
+ " must be a positive duration");
}
@ParameterizedTest
@ -379,12 +784,6 @@ class TaskanaConfigurationTest {
TaskanaConfiguration.Builder builder =
new TaskanaConfiguration.Builder(
TestContainerExtension.createDataSourceForH2(), false, "TASKANA")
.jobBatchSize(1)
.maxNumberOfJobRetries(1)
.cleanupJobRunEvery(Duration.ofDays(1))
.cleanupJobMinimumAge(Duration.ofDays(1))
.priorityJobBatchSize(1)
.priorityJobRunEvery(Duration.ofDays(1))
.userRefreshJobRunEvery(Duration.parse(userRefreshJobRunEvery));
ThrowingCallable call = builder::build;
@ -393,21 +792,14 @@ class TaskanaConfigurationTest {
.isInstanceOf(InvalidArgumentException.class)
.hasMessageContaining(
"Parameter userRefreshJobRunEvery (taskana.jobs.user.refresh.runEvery)"
+ " must be a positive integer");
+ " must be a positive duration");
}
@Test
void should_ThrowInvalidArgumentException_When_JobSchededulerInitialStartDelayIsNotPositive() {
void should_ThrowInvalidArgumentException_When_JobSchedulerInitialStartDelayIsNegative() {
TaskanaConfiguration.Builder builder =
new TaskanaConfiguration.Builder(
TestContainerExtension.createDataSourceForH2(), false, "TASKANA")
.jobBatchSize(1)
.maxNumberOfJobRetries(1)
.cleanupJobRunEvery(Duration.ofDays(1))
.cleanupJobMinimumAge(Duration.ofDays(1))
.priorityJobBatchSize(1)
.priorityJobRunEvery(Duration.ofDays(1))
.userRefreshJobRunEvery(Duration.ofDays(1))
.jobSchedulerInitialStartDelay(-1);
ThrowingCallable call = builder::build;
@ -415,8 +807,44 @@ class TaskanaConfigurationTest {
assertThatThrownBy(call)
.isInstanceOf(InvalidArgumentException.class)
.hasMessageContaining(
"Parameter jobSchedulerInitialStartDelay (taskana.jobscheduler.initialstartdelay)"
+ " must be a positive integer");
"Parameter jobSchedulerInitialStartDelay (taskana.jobs.scheduler.initialStartDelay)"
+ " must be a natural integer");
}
@Test
void should_ThrowInvalidArgumentException_When_ClassificationTypesDoesNotExist() {
TaskanaConfiguration.Builder builder =
new TaskanaConfiguration.Builder(
TestContainerExtension.createDataSourceForH2(), false, "TASKANA")
.classificationTypes(Set.of("valid"))
.classificationCategoriesByType(Map.of("does_not_exist", Set.of("a", "b")));
ThrowingCallable call = builder::build;
assertThatThrownBy(call)
.isInstanceOf(InvalidArgumentException.class)
.hasMessageContaining(
"Parameter classificationCategoriesByType "
+ "(taskana.classification.categories.<KEY>) contains invalid Classification Types."
+ " configured: [VALID] detected: [DOES_NOT_EXIST]");
}
@Test
void should_ThrowInvalidArgumentException_When_ClassificationCategoryDoesNotExist() {
TaskanaConfiguration.Builder builder =
new TaskanaConfiguration.Builder(
TestContainerExtension.createDataSourceForH2(), false, "TASKANA")
.classificationTypes(Set.of("type1", "type2"))
.classificationCategoriesByType(Map.of("type1", Set.of("a", "b")));
ThrowingCallable call = builder::build;
assertThatThrownBy(call)
.isInstanceOf(InvalidArgumentException.class)
.hasMessageContaining(
"Some Classification Categories for parameter classificationTypes "
+ "(taskana.classification.types) are missing. "
+ "configured: [TYPE2, TYPE1] detected: [TYPE1]");
}
@ParameterizedTest
@ -426,14 +854,6 @@ class TaskanaConfigurationTest {
TaskanaConfiguration.Builder builder =
new TaskanaConfiguration.Builder(
TestContainerExtension.createDataSourceForH2(), false, "TASKANA")
.jobBatchSize(1)
.maxNumberOfJobRetries(1)
.cleanupJobRunEvery(Duration.ofDays(1))
.cleanupJobMinimumAge(Duration.ofDays(1))
.priorityJobBatchSize(1)
.priorityJobRunEvery(Duration.ofDays(1))
.userRefreshJobRunEvery(Duration.ofDays(1))
.jobSchedulerInitialStartDelay(1)
.jobSchedulerPeriod(jobSchedulerPeriod);
ThrowingCallable call = builder::build;
@ -441,7 +861,30 @@ class TaskanaConfigurationTest {
assertThatThrownBy(call)
.isInstanceOf(InvalidArgumentException.class)
.hasMessageContaining(
"Parameter jobSchedulerPeriod (taskana.jobscheduler.period)"
"Parameter jobSchedulerPeriod (taskana.jobs.scheduler.period)"
+ " must be a positive integer");
}
private static void verifyConfigurationValuesDifferFromDefaultConfiguration(
TaskanaConfiguration configuration) {
TaskanaConfiguration defaultConfiguration =
new Builder(TestContainerExtension.createDataSourceForH2(), true, "TASKANA").build();
Set<String> ignoredFields =
Set.of(
"dataSource", "useManagedTransactions", "securityEnabled", "schemaName", "properties");
ReflectionUtil.retrieveAllFields(TaskanaConfiguration.class).stream()
.filter(f -> !ignoredFields.contains(f.getName()))
.forEach(
CheckedConsumer.wrap(
field -> {
field.setAccessible(true);
Object value = field.get(configuration);
Object defaultValue = field.get(defaultConfiguration);
assertThat(value)
.as(
"Field '%s' (%s) should not be a default configuration value",
field.getName(), TASKANA_PROPERTY_NAME_BY_FIELD_NAME.get(field.getName()))
.isNotEqualTo(defaultValue);
}));
}
}

View File

@ -31,7 +31,7 @@ class TaskanaEngineExplicitTest {
DbSchemaCreator dsc =
new DbSchemaCreator(
taskanaConfiguration.getDatasource(), taskanaConfiguration.getSchemaName());
taskanaConfiguration.getDataSource(), taskanaConfiguration.getSchemaName());
assertThat(dsc.isValidSchemaVersion(TaskanaEngine.MINIMAL_TASKANA_SCHEMA_VERSION)).isTrue();
}
}

View File

@ -6,6 +6,7 @@ import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
@ -49,10 +50,10 @@ class JobSchedulerExecutionAccTest implements TaskanaConfigurationModifier {
@Override
public Builder modify(Builder builder) {
return builder
.jobSchedulerEnableTaskCleanupJob(true)
.cleanupJobFirstRun(Instant.now().minus(10, ChronoUnit.MILLIS))
.cleanupJobRunEvery(Duration.ofMillis(1))
.cleanupJobMinimumAge(Duration.ofMillis(10));
.taskCleanupJobEnabled(true)
.jobFirstRun(Instant.now().minus(10, ChronoUnit.MILLIS))
.jobRunEvery(Duration.ofMillis(1))
.taskCleanupJobMinimumAge(Duration.ofMillis(10));
}
@WithAccessId(user = "businessadmin")
@ -124,12 +125,11 @@ class JobSchedulerExecutionAccTest implements TaskanaConfigurationModifier {
@Override
public Builder modify(Builder builder) {
return builder
.jobSchedulerEnableTaskCleanupJob(false)
.cleanupJobFirstRun(Instant.now().minus(10, ChronoUnit.MILLIS))
.cleanupJobRunEvery(Duration.ofMillis(1))
.cleanupJobMinimumAge(Duration.ofMillis(10))
.jobSchedulerCustomJobs(
List.of(AlwaysFailJob.class.getName(), TaskCleanupJob.class.getName()));
.taskCleanupJobEnabled(false)
.jobFirstRun(Instant.now().minus(10, ChronoUnit.MILLIS))
.jobRunEvery(Duration.ofMillis(1))
.taskCleanupJobMinimumAge(Duration.ofMillis(10))
.customJobs(Set.of(AlwaysFailJob.class.getName(), TaskCleanupJob.class.getName()));
}
@WithAccessId(user = "businessadmin")

View File

@ -29,19 +29,18 @@ class JobSchedulerInitAccTest implements TaskanaConfigurationModifier {
@Override
public TaskanaConfiguration.Builder modify(TaskanaConfiguration.Builder builder) {
return builder
.cleanupJobRunEvery(runEvery)
.cleanupJobFirstRun(firstRun)
.jobRunEvery(runEvery)
.jobFirstRun(firstRun)
// config for TaskUpdatePriorityJob
.priorityJobActive(true)
.priorityJobRunEvery(runEvery)
.priorityJobFirstRun(firstRun)
.taskUpdatePriorityJobRunEvery(runEvery)
.taskUpdatePriorityJobFirstRun(firstRun)
.jobSchedulerEnabled(true)
.jobSchedulerInitialStartDelay(100)
.jobSchedulerPeriod(100)
.jobSchedulerPeriodTimeUnit(TimeUnit.SECONDS)
.jobSchedulerEnableTaskCleanupJob(true)
.jobSchedulerEnableTaskUpdatePriorityJob(true)
.jobSchedulerEnableWorkbasketCleanupJob(true);
.taskCleanupJobEnabled(true)
.taskUpdatePriorityJobEnabled(true)
.workbasketCleanupJobEnabled(true);
}
@Test

View File

@ -248,7 +248,7 @@ public class RequestChangesWithAfterSpiAccTest {
@BeforeAll
void setup(TaskanaConfiguration taskanaConfiguration) {
transactionProvider =
new PlainJavaTransactionProvider(taskanaEngine, taskanaConfiguration.getDatasource());
new PlainJavaTransactionProvider(taskanaEngine, taskanaConfiguration.getDataSource());
}
@WithAccessId(user = "user-1-1")

View File

@ -283,7 +283,7 @@ public class RequestChangesWithBeforeSpiAccTest {
@BeforeAll
void setup(TaskanaConfiguration taskanaConfiguration) {
transactionProvider =
new PlainJavaTransactionProvider(taskanaEngine, taskanaConfiguration.getDatasource());
new PlainJavaTransactionProvider(taskanaEngine, taskanaConfiguration.getDataSource());
}
@WithAccessId(user = "user-1-1")

View File

@ -249,7 +249,7 @@ public class RequestReviewWithAfterSpiAccTest {
@BeforeAll
void setup(TaskanaConfiguration taskanaConfiguration) {
transactionProvider =
new PlainJavaTransactionProvider(taskanaEngine, taskanaConfiguration.getDatasource());
new PlainJavaTransactionProvider(taskanaEngine, taskanaConfiguration.getDataSource());
}
@WithAccessId(user = "user-1-1")

View File

@ -284,7 +284,7 @@ public class RequestReviewWithBeforeSpiAccTest {
@BeforeAll
void setup(TaskanaConfiguration taskanaConfiguration) {
transactionProvider =
new PlainJavaTransactionProvider(taskanaEngine, taskanaConfiguration.getDatasource());
new PlainJavaTransactionProvider(taskanaEngine, taskanaConfiguration.getDataSource());
}
@WithAccessId(user = "user-1-1")

View File

@ -8,7 +8,6 @@ import static pro.taskana.testapi.DefaultTestEntities.defaultTestWorkbasket;
import static pro.taskana.testapi.DefaultTestEntities.randomTestUser;
import static pro.taskana.testapi.builder.UserBuilder.newUser;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@ -1017,7 +1016,7 @@ class UserServiceAccTest {
@Override
public TaskanaConfiguration.Builder modify(TaskanaConfiguration.Builder builder) {
return builder.minimalPermissionsToAssignDomains(List.of(WorkbasketPermission.APPEND));
return builder.minimalPermissionsToAssignDomains(Set.of(WorkbasketPermission.APPEND));
}
@WithAccessId(user = "user-1-1")
@ -1094,7 +1093,7 @@ class UserServiceAccTest {
@Override
public TaskanaConfiguration.Builder modify(TaskanaConfiguration.Builder builder) {
return builder.minimalPermissionsToAssignDomains(new ArrayList<>());
return builder.minimalPermissionsToAssignDomains(Set.of());
}
@WithAccessId(user = "user-1-1")

View File

@ -0,0 +1,58 @@
# general configuration
taskana.domains=DOMAIN_A | DOMAIN_B
taskana.servicelevel.validation.enforce=false
# authentication configuration
taskana.roles.user=user-1 | user-2
taskana.roles.admin=admin-1 | admin-2
taskana.roles.business_admin=businessadmin-1 | businessadmin-2
taskana.roles.monitor=monitor-1 | monitor-2
taskana.roles.task_admin=taskadmin-1 | taskadmin-2
taskana.roles.task_router=taskrouter-1 | taskrouter-2
# classification configuration
taskana.classification.types=TASK | document
taskana.classification.categories.task=EXTERNAL| manual| autoMAtic| Process
taskana.classification.categories.document=EXTERNAL
# working time configuration
taskana.workingTime.schedule.MONDAY=09:00-18:00
taskana.workingTime.schedule.TUESDAY=09:00-18:00
taskana.workingTime.schedule.WEDNESDAY=09:00-18:00
taskana.workingTime.schedule.THURSDAY=09:00-18:00
taskana.workingTime.schedule.FRIDAY=09:00-18:00
taskana.workingTime.timezone=UTC
taskana.workingTime.holidays.custom=31.07|16.12
taskana.workingTime.holidays.german.enabled=false
taskana.workingTime.holidays.german.corpus-christi.enabled=true
# history configuration
taskana.history.simple.deleteOnTaskDeletion.enabled=true
taskana.history.logger.name=AUDIT
# job configuration
taskana.jobs.scheduler.enabled=false
taskana.jobs.scheduler.initialStartDelay=30
taskana.jobs.scheduler.period=12
taskana.jobs.scheduler.periodTimeUnit=HOURS
taskana.jobs.maxRetries=4
taskana.jobs.batchSize=50
taskana.jobs.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.runEvery=P2D
taskana.jobs.cleanup.task.enable=false
taskana.jobs.cleanup.task.minimumAge=P15D
taskana.jobs.cleanup.task.allCompletedSameParentBusiness=false
taskana.jobs.cleanup.workbasket.enable=false
taskana.jobs.cleanup.history.simple.enable=true
taskana.jobs.cleanup.history.simple.batchSize=50
taskana.jobs.cleanup.history.simple.minimumAge=P17D
taskana.jobs.cleanup.history.simple.allCompletedSameParentBusiness=false
taskana.jobs.priority.task.enable=true
taskana.jobs.priority.task.batchSize=50
taskana.jobs.priority.task.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.priority.task.runEvery=P3D
taskana.jobs.refresh.user.enable=true
taskana.jobs.user.refresh.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.user.refresh.runEvery=P4D
taskana.jobs.customJobs=A | B | C
# user configuration
taskana.user.addAdditionalUserInfo=true
taskana.user.minimalPermissionsToAssignDomains=READ | OPEN
# custom configuration
mycustomproperty1=mycustomvalue1
mycustomproperty2=mycustomvalue2

View File

@ -1,35 +1,35 @@
taskana.roles.user=cn=ksc-users,cn=groups,OU=Test,O=TASKANA | teamlead-1 | teamlead-2 | user-1-1 | user-1-2 | user-2-1 | user-2-2 | user-b-1 | user-b-2
taskana.roles.admin=admin | uid=admin,cn=users,OU=Test,O=TASKANA
taskana.roles.businessadmin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.business_admin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.monitor=monitor | cn=monitor-users,cn=groups,OU=Test,O=TASKANA
taskana.roles.taskadmin=taskadmin
taskana.domains=DOMAIN_A , DOMAIN_B
taskana.roles.task_admin=taskadmin
taskana.domains=DOMAIN_A | DOMAIN_B
taskana.user.minimalPermissionsToAssignDomains=READ | OPEN
taskana.classification.types=TASK , document
taskana.classification.categories.task=EXTERNAL, manual, autoMAtic, Process
taskana.classification.types=TASK | document
taskana.classification.categories.task=EXTERNAL | manual | autoMAtic | Process
taskana.classification.categories.document=EXTERNAL
taskana.jobs.maxRetries=3
taskana.jobs.batchSize=50
taskana.jobs.cleanup.runEvery=P1D
taskana.jobs.cleanup.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.minimumAge=P14D
taskana.german.holidays.enabled=true
taskana.german.holidays.corpus-christi.enabled=false
taskana.history.deletion.on.task.deletion.enabled=true
taskana.validation.allowTimestampServiceLevelMismatch=false
taskana.jobs.runEvery=P1D
taskana.jobs.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.task.minimumAge=P14D
taskana.workingTime.holidays.german.enabled=true
taskana.workingTime.holidays.german.corpus-christi.enabled=false
taskana.history.simple.deleteOnTaskDeletion.enabled=true
taskana.servicelevel.validation.enforce=true
taskana.query.includeLongName=false
# enable or disable the jobscheduler at all
# set it to false and no jobs are running
taskana.jobscheduler.enabled=false
taskana.jobs.scheduler.enabled=true
# wait time before the first job run in millis
taskana.jobscheduler.initialstartdelay=100000
taskana.jobs.scheduler.initialStartDelay=100000
# sleeping time befor the next job runs
taskana.jobscheduler.period=12
taskana.jobs.scheduler.period=12
# timeunit for the sleeping period
# Possible values: MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS
taskana.jobscheduler.periodtimeunit=HOURS
taskana.jobscheduler.enableTaskCleanupJob=false
taskana.jobscheduler.enableTaskUpdatePriorityJob=false
taskana.jobscheduler.enableWorkbasketCleanupJob=false
taskana.jobscheduler.enableUserInfoRefreshJob=false
taskana.jobscheduler.enableHistorieCleanupJob=false
taskana.jobs.scheduler.periodTimeUnit=HOURS
taskana.jobs.cleanup.task.enable=false
taskana.jobs.priority.task.enable=false
taskana.jobs.cleanup.workbasket.enable=false
taskana.jobs.refresh.user.enable=false
taskana.jobs.cleanup.history.simple.enable=false

View File

@ -98,11 +98,10 @@ public class TaskanaEngineImpl implements TaskanaEngine {
private final BeforeRequestChangesManager beforeRequestChangesManager;
private final AfterRequestChangesManager afterRequestChangesManager;
private final InternalTaskanaEngineImpl internalTaskanaEngineImpl;
private final WorkingTimeCalculator workingTimeCalculator;
private final HistoryEventManager historyEventManager;
private final CurrentUserContext currentUserContext;
private final JobScheduler jobScheduler;
protected ConnectionManagementMode mode;
protected TransactionFactory transactionFactory;
protected SqlSessionManager sessionManager;
@ -127,7 +126,7 @@ public class TaskanaEngineImpl implements TaskanaEngine {
HolidaySchedule holidaySchedule =
new HolidaySchedule(
taskanaConfiguration.isGermanPublicHolidaysEnabled(),
taskanaConfiguration.isCorpusChristiEnabled(),
taskanaConfiguration.isGermanPublicHolidaysCorpusChristiEnabled(),
taskanaConfiguration.getCustomHolidays());
workingTimeCalculator =
new WorkingTimeCalculatorImpl(
@ -141,18 +140,6 @@ public class TaskanaEngineImpl implements TaskanaEngine {
initializeDbSchema(taskanaConfiguration);
// IMPORTANT: SPI has to be initialized last (and in this order) in order
// to provide a fully initialized TaskanaEngine instance during the SPI initialization!
priorityServiceManager = new PriorityServiceManager();
createTaskPreprocessorManager = new CreateTaskPreprocessorManager();
historyEventManager = new HistoryEventManager(this);
taskRoutingManager = new TaskRoutingManager(this);
reviewRequiredManager = new ReviewRequiredManager(this);
beforeRequestReviewManager = new BeforeRequestReviewManager(this);
afterRequestReviewManager = new AfterRequestReviewManager(this);
beforeRequestChangesManager = new BeforeRequestChangesManager(this);
afterRequestChangesManager = new AfterRequestChangesManager(this);
if (this.taskanaConfiguration.isJobSchedulerEnabled()) {
TaskanaConfiguration configuration =
new TaskanaConfiguration.Builder(this.taskanaConfiguration)
@ -164,10 +151,24 @@ public class TaskanaEngineImpl implements TaskanaEngine {
this.taskanaConfiguration.getJobSchedulerInitialStartDelay(),
this.taskanaConfiguration.getJobSchedulerPeriod(),
this.taskanaConfiguration.getJobSchedulerPeriodTimeUnit());
JobScheduler jobScheduler = new JobScheduler(taskanaEngine, clock);
jobScheduler = new JobScheduler(taskanaEngine, clock);
jobScheduler.start();
} else {
jobScheduler = null;
}
// IMPORTANT: SPI has to be initialized last (and in this order) in order
// to provide a fully initialized TaskanaEngine instance during the SPI initialization!
priorityServiceManager = new PriorityServiceManager();
createTaskPreprocessorManager = new CreateTaskPreprocessorManager();
historyEventManager = new HistoryEventManager(this);
taskRoutingManager = new TaskRoutingManager(this);
reviewRequiredManager = new ReviewRequiredManager(this);
beforeRequestReviewManager = new BeforeRequestReviewManager(this);
afterRequestReviewManager = new AfterRequestReviewManager(this);
beforeRequestChangesManager = new BeforeRequestChangesManager(this);
afterRequestChangesManager = new AfterRequestChangesManager(this);
// don't remove, to reset possible explicit mode
this.mode = connectionManagementMode;
}
@ -257,6 +258,10 @@ public class TaskanaEngineImpl implements TaskanaEngine {
internalTaskanaEngineImpl, sessionManager.getMapper(UserMapper.class));
}
public JobScheduler getJobScheduler() {
return jobScheduler;
}
@Override
public TaskanaConfiguration getConfiguration() {
return this.taskanaConfiguration;
@ -363,12 +368,12 @@ public class TaskanaEngineImpl implements TaskanaEngine {
*/
protected SqlSessionManager createSqlSessionManager() {
Environment environment =
new Environment("default", this.transactionFactory, taskanaConfiguration.getDatasource());
new Environment("default", this.transactionFactory, taskanaConfiguration.getDataSource());
Configuration configuration = new Configuration(environment);
// set databaseId
DB db;
try (Connection con = taskanaConfiguration.getDatasource().getConnection()) {
try (Connection con = taskanaConfiguration.getDataSource().getConnection()) {
db = DB.getDB(con);
configuration.setDatabaseId(db.dbProductId);
} catch (SQLException e) {
@ -426,7 +431,7 @@ public class TaskanaEngineImpl implements TaskanaEngine {
private void initializeDbSchema(TaskanaConfiguration taskanaConfiguration) throws SQLException {
DbSchemaCreator dbSchemaCreator =
new DbSchemaCreator(
taskanaConfiguration.getDatasource(), taskanaConfiguration.getSchemaName());
taskanaConfiguration.getDataSource(), taskanaConfiguration.getSchemaName());
boolean schemaCreated = dbSchemaCreator.run();
if (!schemaCreated && !dbSchemaCreator.isValidSchemaVersion(MINIMAL_TASKANA_SCHEMA_VERSION)) {

View File

@ -31,8 +31,8 @@ public abstract class AbstractTaskanaJob implements TaskanaJob {
this.txProvider = txProvider;
this.scheduledJob = job;
this.async = async;
firstRun = taskanaEngineImpl.getConfiguration().getCleanupJobFirstRun();
runEvery = taskanaEngineImpl.getConfiguration().getCleanupJobRunEvery();
firstRun = taskanaEngineImpl.getConfiguration().getJobFirstRun();
runEvery = taskanaEngineImpl.getConfiguration().getJobRunEvery();
}
public static TaskanaJob createFromScheduledJob(
@ -113,6 +113,18 @@ public abstract class AbstractTaskanaJob implements TaskanaJob {
job.scheduleNextJob();
}
public boolean isAsync() {
return async;
}
public Instant getFirstRun() {
return firstRun;
}
public Duration getRunEvery() {
return runEvery;
}
protected abstract String getType();
protected abstract void execute() throws TaskanaException;

View File

@ -28,31 +28,28 @@ public class JobScheduler {
this.clock = clock;
this.plainJavaTransactionProvider =
new PlainJavaTransactionProvider(
taskanaEngine, taskanaEngine.getConfiguration().getDatasource());
taskanaEngine, taskanaEngine.getConfiguration().getDataSource());
plainJavaTransactionProvider.executeInTransaction(
() -> {
if (taskanaEngine.getConfiguration().isJobSchedulerEnableTaskCleanupJob()) {
if (taskanaEngine.getConfiguration().isTaskCleanupJobEnabled()) {
AbstractTaskanaJob.initializeSchedule(taskanaEngine, TaskCleanupJob.class);
LOGGER.info("Job '{}' enabled", TaskCleanupJob.class.getName());
}
if (taskanaEngine.getConfiguration().isJobSchedulerEnableTaskUpdatePriorityJob()) {
if (taskanaEngine.getConfiguration().isTaskUpdatePriorityJobEnabled()) {
AbstractTaskanaJob.initializeSchedule(taskanaEngine, TaskUpdatePriorityJob.class);
LOGGER.info("Job '{}' enabled", TaskUpdatePriorityJob.class.getName());
}
if (taskanaEngine.getConfiguration().isJobSchedulerEnableWorkbasketCleanupJob()) {
if (taskanaEngine.getConfiguration().isWorkbasketCleanupJobEnabled()) {
AbstractTaskanaJob.initializeSchedule(taskanaEngine, WorkbasketCleanupJob.class);
LOGGER.info("Job '{}' enabled", WorkbasketCleanupJob.class.getName());
}
if (taskanaEngine.getConfiguration().isJobSchedulerEnableUserInfoRefreshJob()) {
if (taskanaEngine.getConfiguration().isUserInfoRefreshJobEnabled()) {
initJobByClassName("pro.taskana.user.jobs.UserInfoRefreshJob");
}
if (taskanaEngine.getConfiguration().isJobSchedulerEnableHistorieCleanupJob()) {
if (taskanaEngine.getConfiguration().isSimpleHistoryCleanupJobEnabled()) {
initJobByClassName("pro.taskana.simplehistory.impl.jobs.HistoryCleanupJob");
}
taskanaEngine
.getConfiguration()
.getJobSchedulerCustomJobs()
.forEach(this::initJobByClassName);
taskanaEngine.getConfiguration().getCustomJobs().forEach(this::initJobByClassName);
return "Initialized Jobs successfully";
});

View File

@ -252,7 +252,7 @@ class ServiceLevelHandler {
TaskImpl newTaskImpl, TaskImpl oldTaskImpl, Duration duration)
throws InvalidArgumentException {
// TODO pull this one out and in updatePlannedDueOnCreationOfNewTask, too.
if (taskanaEngine.getEngine().getConfiguration().isAllowTimestampServiceLevelMismatch()
if (!taskanaEngine.getEngine().getConfiguration().isEnforceServiceLevel()
&& newTaskImpl.getDue() != null
&& newTaskImpl.getPlanned() != null) {
@ -379,7 +379,7 @@ class ServiceLevelHandler {
private TaskImpl updatePlannedDueOnCreationOfNewTask(TaskImpl newTask, Duration duration)
throws InvalidArgumentException {
if (taskanaEngine.getEngine().getConfiguration().isAllowTimestampServiceLevelMismatch()
if (!taskanaEngine.getEngine().getConfiguration().isEnforceServiceLevel()
&& newTask.getDue() != null
&& newTask.getPlanned() != null) {
return newTask;

View File

@ -604,13 +604,13 @@ public class TaskQueryImpl implements TaskQuery {
}
@Override
public TaskQuery priorityWithin(IntInterval[] priorities) {
public TaskQuery priorityWithin(IntInterval... priorities) {
this.priorityWithin = priorities;
return this;
}
@Override
public TaskQuery priorityNotWithin(IntInterval[] priorities) {
public TaskQuery priorityNotWithin(IntInterval... priorities) {
this.priorityNotWithin = priorities;
return this;
}

View File

@ -663,7 +663,7 @@ public class TaskServiceImpl implements TaskService {
&& taskanaEngine
.getEngine()
.getConfiguration()
.isDeleteHistoryOnTaskDeletionEnabled()) {
.isDeleteHistoryEventsOnTaskDeletionEnabled()) {
historyEventManager.deleteEvents(taskIds);
}
}
@ -1596,7 +1596,10 @@ public class TaskServiceImpl implements TaskService {
taskMapper.delete(taskId);
if (taskanaEngine.getEngine().isHistoryEnabled()
&& taskanaEngine.getEngine().getConfiguration().isDeleteHistoryOnTaskDeletionEnabled()) {
&& taskanaEngine
.getEngine()
.getConfiguration()
.isDeleteHistoryEventsOnTaskDeletionEnabled()) {
historyEventManager.deleteEvents(Collections.singletonList(taskId));
}

View File

@ -40,7 +40,7 @@ public class TaskCleanupJob extends AbstractTaskanaJob {
TaskanaTransactionProvider txProvider,
ScheduledJob scheduledJob) {
super(taskanaEngine, txProvider, scheduledJob, true);
minimumAge = taskanaEngine.getConfiguration().getCleanupJobMinimumAge();
minimumAge = taskanaEngine.getConfiguration().getTaskCleanupJobMinimumAge();
batchSize = taskanaEngine.getConfiguration().getJobBatchSize();
allCompletedSameParentBusiness =
taskanaEngine.getConfiguration().isTaskCleanupJobAllCompletedSameParentBusiness();

View File

@ -17,7 +17,6 @@ public class TaskUpdatePriorityJob extends AbstractTaskanaJob {
private static final Logger LOGGER = LoggerFactory.getLogger(TaskUpdatePriorityJob.class);
private final int batchSize;
private final boolean isJobActive;
public TaskUpdatePriorityJob(TaskanaEngine taskanaEngine) {
this(taskanaEngine, null, null);
@ -28,18 +27,13 @@ public class TaskUpdatePriorityJob extends AbstractTaskanaJob {
TaskanaTransactionProvider txProvider,
ScheduledJob scheduledJob) {
super(taskanaEngine, txProvider, scheduledJob, true);
batchSize = taskanaEngine.getConfiguration().getPriorityJobBatchSize();
isJobActive = taskanaEngine.getConfiguration().isPriorityJobActive();
runEvery = taskanaEngine.getConfiguration().getPriorityJobRunEvery();
firstRun = taskanaEngine.getConfiguration().getPriorityJobFirstRun();
batchSize = taskanaEngine.getConfiguration().getTaskUpdatePriorityJobBatchSize();
runEvery = taskanaEngine.getConfiguration().getTaskUpdatePriorityJobRunEvery();
firstRun = taskanaEngine.getConfiguration().getTaskUpdatePriorityJobFirstRun();
}
@Override
public void execute() {
if (!isJobActive()) {
LOGGER.debug("Job to update task priority is not active.");
return;
}
TaskUpdatePriorityWorker worker = new TaskUpdatePriorityWorker(taskanaEngineImpl);
LOGGER.info("Running job to calculate all non finished task priorities");
try {
@ -51,10 +45,6 @@ public class TaskUpdatePriorityJob extends AbstractTaskanaJob {
}
}
public boolean isJobActive() {
return isJobActive;
}
public int getBatchSize() {
return batchSize;
}

View File

@ -33,6 +33,6 @@ public class SqlConnectionRunner {
}
public Connection getConnection() throws SQLException {
return taskanaEngine.getConfiguration().getDatasource().getConnection();
return taskanaEngine.getConfiguration().getDataSource().getConnection();
}
}

View File

@ -37,7 +37,11 @@ public class UserServiceImpl implements UserService {
this.userMapper = userMapper;
this.workbasketService = internalTaskanaEngine.getEngine().getWorkbasketService();
minimalWorkbasketPermissions =
internalTaskanaEngine.getEngine().getConfiguration().getMinimalPermissionsToAssignDomains();
List.copyOf(
internalTaskanaEngine
.getEngine()
.getConfiguration()
.getMinimalPermissionsToAssignDomains());
}
@Override

View File

@ -9,10 +9,12 @@ import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSessionManager;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import pro.taskana.TaskanaConfiguration;
import pro.taskana.common.api.TaskanaEngine;
@ -21,6 +23,7 @@ import pro.taskana.common.api.TimeInterval;
import pro.taskana.common.api.WorkingTimeCalculator;
import pro.taskana.common.internal.JobMapper;
import pro.taskana.common.internal.TaskanaEngineImpl;
import pro.taskana.common.internal.jobs.JobScheduler;
import pro.taskana.common.test.config.DataSourceGenerator;
import pro.taskana.sampledata.SampleDataGenerator;
import pro.taskana.task.api.models.Attachment;
@ -47,6 +50,12 @@ public abstract class AbstractAccTest {
resetDb(false);
}
@AfterAll
protected static void destroyClass() {
Optional.ofNullable(((TaskanaEngineImpl) taskanaEngine).getJobScheduler())
.ifPresent(JobScheduler::stop);
}
protected static void resetDb(boolean dropTables) throws Exception {
DataSource dataSource = DataSourceGenerator.getDataSource();

View File

@ -5,9 +5,9 @@ import static org.assertj.core.api.Assertions.assertThat;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.junit.jupiter.api.BeforeEach;
@ -40,7 +40,7 @@ class TaskanaConfigAccTest {
@Test
void should_ConfigureMinimalPermissionsToAssignDomains_For_DefaultPropertiesFile() {
assertThat(taskanaConfiguration.getMinimalPermissionsToAssignDomains())
.containsExactly(WorkbasketPermission.READ, WorkbasketPermission.OPEN);
.containsExactlyInAnyOrder(WorkbasketPermission.READ, WorkbasketPermission.OPEN);
}
@Test
@ -55,43 +55,11 @@ class TaskanaConfigAccTest {
.containsExactlyInAnyOrder("EXTERNAL", "MANUAL", "AUTOMATIC", "PROCESS");
}
@Test
void should_NotConfigureClassificationTypes_When_PropertiesAreNotDefined() throws Exception {
String propertiesFileName = createNewConfigFile("dummyTestConfig1.properties", false, true);
String delimiter = ";";
taskanaConfiguration =
new TaskanaConfiguration.Builder(
DataSourceGenerator.getDataSource(),
true,
DataSourceGenerator.getSchemaName(),
true)
.initTaskanaProperties(propertiesFileName, delimiter)
.build();
assertThat(taskanaConfiguration.getClassificationTypes()).isEmpty();
}
@Test
void should_NotConfigureClassificationCategories_When_PropertiesAreNotDefined() throws Exception {
String propertiesFileName = createNewConfigFile("dummyTestConfig2.properties", true, false);
String delimiter = ";";
taskanaConfiguration =
new TaskanaConfiguration.Builder(
DataSourceGenerator.getDataSource(),
true,
DataSourceGenerator.getSchemaName(),
true)
.initTaskanaProperties(propertiesFileName, delimiter)
.build();
assertThat(taskanaConfiguration.getClassificationCategoriesByType())
.containsExactly(
Map.entry("TASK", Collections.emptyList()),
Map.entry("DOCUMENT", Collections.emptyList()));
}
@Test
void should_ApplyClassificationProperties_When_PropertiesAreDefined() throws Exception {
String propertiesFileName = createNewConfigFile("dummyTestConfig3.properties", true, true);
String delimiter = ";";
String propertiesFileName =
createNewConfigFile("dummyTestConfig3.properties", delimiter, true, true);
taskanaConfiguration =
new TaskanaConfiguration.Builder(
DataSourceGenerator.getDataSource(),
@ -101,25 +69,30 @@ class TaskanaConfigAccTest {
.initTaskanaProperties(propertiesFileName, delimiter)
.build();
assertThat(taskanaConfiguration.getClassificationCategoriesByType())
.containsExactly(
Map.entry("TASK", List.of("EXTERNAL", "MANUAL", "AUTOMATIC", "PROCESS")),
Map.entry("DOCUMENT", List.of("EXTERNAL")));
.containsExactlyInAnyOrderEntriesOf(
Map.ofEntries(
Map.entry("TASK", Set.of("EXTERNAL", "MANUAL", "AUTOMATIC", "PROCESS")),
Map.entry("DOCUMENT", Set.of("EXTERNAL"))));
}
private String createNewConfigFile(
String filename, boolean addingTypes, boolean addingClassification) throws Exception {
String filename, String delimiter, boolean addingTypes, boolean addingClassification)
throws Exception {
Path file = Files.createFile(tempDir.resolve(filename));
List<String> lines =
Stream.of(
"taskana.roles.admin =Holger|Stefan",
"taskana.roles.businessadmin = ebe | konstantin ",
"taskana.roles.business_admin = ebe | konstantin ",
"taskana.roles.user = nobody")
.collect(Collectors.toList());
if (addingTypes) {
lines.add("taskana.classification.types= TASK , document");
lines.add(String.format("taskana.classification.types= TASK %s document", delimiter));
}
if (addingClassification) {
lines.add("taskana.classification.categories.task= EXTERNAL, manual, autoMAtic, Process");
lines.add(
String.format(
"taskana.classification.categories.task= EXTERNAL%s manual%s autoMAtic%s Process",
delimiter, delimiter, delimiter));
lines.add("taskana.classification.categories.document= EXTERNAL");
}

View File

@ -1,12 +1,15 @@
package acceptance.config;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import javax.sql.DataSource;
import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
import org.junit.jupiter.api.Test;
import pro.taskana.TaskanaConfiguration;
import pro.taskana.common.api.CustomHoliday;
import pro.taskana.common.api.TaskanaEngine;
import pro.taskana.common.api.exceptions.WrongCustomHolidayFormatException;
import pro.taskana.common.test.config.DataSourceGenerator;
class TaskanaConfigurationTest {
@ -32,7 +35,7 @@ class TaskanaConfigurationTest {
.initTaskanaProperties("/corpusChristiEnabled.properties", "|")
.build();
assertThat(configuration.isCorpusChristiEnabled()).isTrue();
assertThat(configuration.isGermanPublicHolidaysCorpusChristiEnabled()).isTrue();
}
@Test
@ -47,12 +50,20 @@ class TaskanaConfigurationTest {
}
@Test
void should_ReturnEmptyList_When_AllCustomHolidaysAreInWrongFormatInPropertiesFile() {
void should_ThrowError_When_AnyCustomHolidayIsInWrongFormatInPropertiesFile() {
DataSource ds = DataSourceGenerator.getDataSource();
TaskanaConfiguration configuration =
new TaskanaConfiguration.Builder(ds, false, DataSourceGenerator.getSchemaName(), true)
.initTaskanaProperties("/custom_holiday_with_wrong_format_taskana.properties", "|")
.build();
assertThat(configuration.getCustomHolidays()).isEmpty();
TaskanaConfiguration.Builder builder =
new TaskanaConfiguration.Builder(ds, false, DataSourceGenerator.getSchemaName(), true);
ThrowingCallable call =
() ->
builder.initTaskanaProperties(
"/custom_holiday_with_wrong_format_taskana.properties", "|");
assertThatThrownBy(call)
.isInstanceOf(WrongCustomHolidayFormatException.class)
.extracting(WrongCustomHolidayFormatException.class::cast)
.extracting(WrongCustomHolidayFormatException::getCustomHoliday)
.isEqualTo("31,07");
}
}

View File

@ -133,9 +133,9 @@ class TaskanaRoleConfigAccTest {
List<String> lines =
List.of(
"taskana.roles.admin =uSeR " + delimiter + "name=Username,Organisation=novatec",
" taskana.roles.businessadmin = name=user2, ou = bpm " + delimiter + " user3 ",
" taskana.roles.business_admin = name=user2, ou = bpm " + delimiter + " user3 ",
" taskana.roles.user = ",
"taskana.roles.taskadmin= taskadmin");
"taskana.roles.task_admin= taskadmin");
Files.write(file, lines, StandardCharsets.UTF_8);
@ -147,9 +147,9 @@ class TaskanaRoleConfigAccTest {
List<String> lines =
List.of(
"taskana.roles.admin =uSeR|Username",
" taskana.roles.businessadmin = user2 | user3 ",
" taskana.roles.business_admin = user2 | user3 ",
" taskana.roles.user = nobody",
"taskana.roles.taskadmin= taskadmin");
"taskana.roles.task_admin= taskadmin");
Files.write(file, lines, StandardCharsets.UTF_8);

View File

@ -160,7 +160,7 @@ class TaskCleanupJobAccTest extends AbstractAccTest {
TaskanaConfiguration taskanaConfiguration =
new TaskanaConfiguration.Builder(AbstractAccTest.taskanaEngine.getConfiguration())
.taskCleanupJobAllCompletedSameParentBusiness(true)
.cleanupJobMinimumAge(Duration.ofMillis(1))
.taskCleanupJobMinimumAge(Duration.ofMillis(1))
.build();
TaskanaEngine taskanaEngine =
TaskanaEngine.buildTaskanaEngine(taskanaConfiguration, ConnectionManagementMode.AUTOCOMMIT);
@ -206,7 +206,7 @@ class TaskCleanupJobAccTest extends AbstractAccTest {
JobRunner runner = new JobRunner(taskanaEngine);
runner.runJobs();
Duration runEvery = taskanaConfiguration.getCleanupJobRunEvery();
Duration runEvery = taskanaConfiguration.getJobRunEvery();
jobsToRun = jobMapper.findJobsToRun(Instant.now().plus(runEvery));
assertThat(jobsToRun).extracting(ScheduledJob::getDue).containsExactly(firstDue.plus(runEvery));
@ -219,13 +219,13 @@ class TaskCleanupJobAccTest extends AbstractAccTest {
Duration runEvery = Duration.ofMinutes(5);
TaskanaConfiguration taskanaConfiguration =
new TaskanaConfiguration.Builder(AbstractAccTest.taskanaConfiguration)
.cleanupJobRunEvery(runEvery)
.cleanupJobFirstRun(firstRun)
.jobRunEvery(runEvery)
.jobFirstRun(firstRun)
.jobSchedulerEnabled(true)
.jobSchedulerInitialStartDelay(1)
.jobSchedulerPeriod(1)
.jobSchedulerPeriodTimeUnit(TimeUnit.SECONDS)
.jobSchedulerEnableTaskCleanupJob(true)
.taskCleanupJobEnabled(true)
.build();
TaskanaEngine taskanaEngine =
@ -242,8 +242,8 @@ class TaskCleanupJobAccTest extends AbstractAccTest {
throws Exception {
TaskanaConfiguration taskanaConfiguration =
new TaskanaConfiguration.Builder(AbstractAccTest.taskanaEngine.getConfiguration())
.cleanupJobRunEvery(Duration.ofMillis(1))
.cleanupJobFirstRun(Instant.now().plus(5, ChronoUnit.MINUTES))
.jobRunEvery(Duration.ofMillis(1))
.jobFirstRun(Instant.now().plus(5, ChronoUnit.MINUTES))
.build();
TaskanaEngine taskanaEngine = TaskanaEngine.buildTaskanaEngine(taskanaConfiguration);

View File

@ -7,19 +7,16 @@ import acceptance.AbstractAccTest;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import pro.taskana.TaskanaConfiguration;
import pro.taskana.common.api.BaseQuery.SortDirection;
import pro.taskana.common.api.ScheduledJob;
import pro.taskana.common.api.TaskanaEngine;
import pro.taskana.common.api.TaskanaEngine.ConnectionManagementMode;
import pro.taskana.common.internal.jobs.AbstractTaskanaJob;
import pro.taskana.common.test.security.JaasExtension;
import pro.taskana.common.test.security.WithAccessId;
import pro.taskana.task.api.TaskQueryColumnName;
import pro.taskana.task.internal.jobs.TaskUpdatePriorityJob;
/** Acceptance test for all "jobs tasks runner" scenarios. */
@ -34,10 +31,9 @@ class TaskUpdatePriorityJobAccTest extends AbstractAccTest {
taskanaConfiguration =
new TaskanaConfiguration.Builder(AbstractAccTest.taskanaConfiguration)
.priorityJobActive(true)
.priorityJobBatchSize(20)
.priorityJobRunEvery(Duration.ofMinutes(30))
.priorityJobFirstRun(Instant.parse("2007-12-03T10:15:30.00Z"))
.taskUpdatePriorityJobBatchSize(20)
.taskUpdatePriorityJobRunEvery(Duration.ofMinutes(30))
.taskUpdatePriorityJobFirstRun(Instant.parse("2007-12-03T10:15:30.00Z"))
.build();
taskanaEngine = TaskanaEngine.buildTaskanaEngine(taskanaConfiguration);
}
@ -52,35 +48,6 @@ class TaskUpdatePriorityJobAccTest extends AbstractAccTest {
assertThatCode(job::execute).doesNotThrowAnyException();
}
@Test
@WithAccessId(user = "admin")
void should_doNothing_When_NotActive() throws Exception {
// given
TaskanaConfiguration taskanaConfiguration =
new TaskanaConfiguration.Builder(AbstractAccTest.taskanaConfiguration)
.priorityJobActive(false)
.build();
TaskanaEngine taskanaEngine = TaskanaEngine.buildTaskanaEngine(taskanaConfiguration);
TaskUpdatePriorityJob job = new TaskUpdatePriorityJob(taskanaEngine);
List<String> priorities =
taskanaEngine
.getTaskService()
.createTaskQuery()
.listValues(TaskQueryColumnName.PRIORITY, SortDirection.ASCENDING);
// when
job.execute();
// then
List<String> prioritiesUnchanged =
taskanaEngine
.getTaskService()
.createTaskQuery()
.listValues(TaskQueryColumnName.PRIORITY, SortDirection.ASCENDING);
assertThat(priorities).isEqualTo(prioritiesUnchanged);
}
@Test
@WithAccessId(user = "admin")
void should_ScheduleNextJob() throws Exception {
@ -106,7 +73,7 @@ class TaskUpdatePriorityJobAccTest extends AbstractAccTest {
// given
TaskanaConfiguration taskanaConfiguration =
new TaskanaConfiguration.Builder(AbstractAccTest.taskanaConfiguration)
.priorityJobBatchSize(20)
.taskUpdatePriorityJobBatchSize(20)
.build();
// when
@ -117,30 +84,17 @@ class TaskUpdatePriorityJobAccTest extends AbstractAccTest {
assertThat(job.getBatchSize()).isEqualTo(20);
}
@Test
@WithAccessId(user = "admin")
void should_readConfigurationForIsActive() throws Exception {
// given
TaskanaConfiguration taskanaConfiguration =
new TaskanaConfiguration.Builder(AbstractAccTest.taskanaConfiguration)
.priorityJobActive(false)
.build();
// when
final TaskUpdatePriorityJob job =
new TaskUpdatePriorityJob(TaskanaEngine.buildTaskanaEngine(taskanaConfiguration));
// then
assertThat(job.isJobActive()).isFalse();
}
@Test
void should_containInformation_When_convertedToString() throws Exception {
// given
Instant expectedFirstRun = Instant.now();
int expectedBatchSize = 543;
Duration expectedRunEvery = Duration.ofMinutes(30);
TaskanaConfiguration taskanaConfiguration =
new TaskanaConfiguration.Builder(AbstractAccTest.taskanaConfiguration)
.priorityJobBatchSize(543)
.priorityJobRunEvery(Duration.ofMinutes(30))
.taskUpdatePriorityJobFirstRun(expectedFirstRun)
.taskUpdatePriorityJobBatchSize(expectedBatchSize)
.taskUpdatePriorityJobRunEvery(expectedRunEvery)
.build();
// when
@ -148,6 +102,8 @@ class TaskUpdatePriorityJobAccTest extends AbstractAccTest {
new TaskUpdatePriorityJob(TaskanaEngine.buildTaskanaEngine(taskanaConfiguration));
// then
assertThat(job).asString().contains("543").contains(Duration.ofMinutes(30).toString());
assertThat(job.getFirstRun()).isEqualTo(expectedFirstRun);
assertThat(job.getBatchSize()).isEqualTo(expectedBatchSize);
assertThat(job.getRunEvery()).isEqualTo(expectedRunEvery);
}
}

View File

@ -197,7 +197,7 @@ class CreateTaskAccTest extends AbstractAccTest {
// Given
TaskanaConfiguration taskanaConfiguration =
new TaskanaConfiguration.Builder(AbstractAccTest.taskanaConfiguration)
.allowTimestampServiceLevelMismatch(true)
.enforceServiceLevel(false)
.build();
TaskanaEngine taskanaEngine = TaskanaEngine.buildTaskanaEngine(taskanaConfiguration);
Task newTask = taskanaEngine.getTaskService().newTask("USER-1-1", "DOMAIN_A");

View File

@ -73,7 +73,7 @@ class UpdateTaskAccTest extends AbstractAccTest {
// Given
TaskanaConfiguration taskanaConfiguration =
new TaskanaConfiguration.Builder(AbstractAccTest.taskanaConfiguration)
.allowTimestampServiceLevelMismatch(false)
.enforceServiceLevel(true)
.build();
TaskanaEngine taskanaEngine = TaskanaEngine.buildTaskanaEngine(taskanaConfiguration);
Task task = taskanaEngine.getTaskService().getTask("TKI:000000000000000000000000000000000000");
@ -95,7 +95,7 @@ class UpdateTaskAccTest extends AbstractAccTest {
// Given
TaskanaConfiguration taskanaConfiguration =
new TaskanaConfiguration.Builder(AbstractAccTest.taskanaConfiguration)
.allowTimestampServiceLevelMismatch(true)
.enforceServiceLevel(false)
.build();
TaskanaEngine taskanaEngine = TaskanaEngine.buildTaskanaEngine(taskanaConfiguration);
Task task = taskanaEngine.getTaskService().getTask("TKI:000000000000000000000000000000000000");

View File

@ -1 +1 @@
taskana.german.holidays.corpus-christi.enabled=true
taskana.workingTime.holidays.german.corpus-christi.enabled=true

View File

@ -1 +1 @@
taskana.custom.holidays=31.07|16.12
taskana.workingTime.holidays.custom=31.07|16.12

View File

@ -1 +1 @@
taskana.custom.holidays=31,07|1612
taskana.workingTime.holidays.custom=31,07|1612

View File

@ -1,42 +1,42 @@
taskana.roles.user=cn=ksc-users,cn=groups,OU=Test,O=TASKANA | teamlead-1 | teamlead-2 | user-1-1 | user-1-2 | user-2-1 | user-2-2 | user-b-1 | user-b-2
taskana.roles.admin=admin | uid=admin,cn=users,OU=Test,O=TASKANA
taskana.roles.businessadmin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.business_admin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.monitor=monitor | cn=monitor-users,cn=groups,OU=Test,O=TASKANA
taskana.roles.taskadmin=taskadmin
taskana.roles.taskrouter=cn=routers,cn=groups,OU=Test,O=TASKANA | user-taskrouter
taskana.domains=DOMAIN_A , DOMAIN_B
taskana.roles.task_admin=taskadmin
taskana.roles.task_router=cn=routers,cn=groups,OU=Test,O=TASKANA | user-taskrouter
taskana.domains=DOMAIN_A | DOMAIN_B
taskana.user.minimalPermissionsToAssignDomains=READ | OPEN
taskana.classification.types=TASK , document
taskana.classification.categories.task=EXTERNAL, manual, autoMAtic, Process
taskana.classification.types=TASK | document
taskana.classification.categories.task=EXTERNAL| manual| autoMAtic| Process
taskana.classification.categories.document=EXTERNAL
taskana.jobs.maxRetries=3
taskana.jobs.batchSize=50
taskana.jobs.cleanup.runEvery=P1D
taskana.jobs.cleanup.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.minimumAge=P14D
taskana.german.holidays.enabled=true
taskana.german.holidays.corpus-christi.enabled=false
taskana.history.deletion.on.task.deletion.enabled=true
taskana.validation.allowTimestampServiceLevelMismatch=false
taskana.jobs.runEvery=P1D
taskana.jobs.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.task.minimumAge=P14D
taskana.workingTime.holidays.german.enabled=true
taskana.workingTime.holidays.german.corpus-christi.enabled=false
taskana.history.simple.deleteOnTaskDeletion.enabled=true
taskana.servicelevel.validation.enforce=true
taskana.query.includeLongName=false
taskana.workingtime.schedule.MONDAY=00:00-00:00
taskana.workingtime.schedule.TUESDAY=00:00-00:00
taskana.workingtime.schedule.WEDNESDAY=00:00-00:00
taskana.workingtime.schedule.THURSDAY=00:00-00:00
taskana.workingtime.schedule.FRIDAY=00:00-00:00
taskana.workingtime.timezone=UTC
taskana.workingTime.schedule.MONDAY=00:00-00:00
taskana.workingTime.schedule.TUESDAY=00:00-00:00
taskana.workingTime.schedule.WEDNESDAY=00:00-00:00
taskana.workingTime.schedule.THURSDAY=00:00-00:00
taskana.workingTime.schedule.FRIDAY=00:00-00:00
taskana.workingTime.timezone=UTC
# enable or disable the jobscheduler at all
# set it to false and no jobs are running
taskana.jobscheduler.enabled=false
taskana.jobs.scheduler.enabled=true
# wait time before the first job run in millis
taskana.jobscheduler.initialstartdelay=100000
taskana.jobs.scheduler.initialStartDelay=100000
# sleeping time befor the next job runs
taskana.jobscheduler.period=12
taskana.jobs.scheduler.period=12
# timeunit for the sleeping period
# Possible values: MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS
taskana.jobscheduler.periodtimeunit=HOURS
taskana.jobscheduler.enableTaskCleanupJob=false
taskana.jobscheduler.enableTaskUpdatePriorityJob=false
taskana.jobscheduler.enableWorkbasketCleanupJob=false
taskana.jobscheduler.enableUserInfoRefreshJob=false
taskana.jobscheduler.enableHistorieCleanupJob=false
taskana.jobs.scheduler.periodTimeUnit=HOURS
taskana.jobs.cleanup.task.enable=false
taskana.jobs.priority.task.enable=false
taskana.jobs.cleanup.workbasket.enable=false
taskana.jobs.refresh.user.enable=false
taskana.jobs.cleanup.history.simple.enable=false

View File

@ -1,33 +1,33 @@
taskana.roles.user=cn=ksc-users,cn=groups,OU=Test,O=TASKANA | teamlead-1 | teamlead-2 | user-1-1 | user-1-2 | user-2-1 | user-2-2 | user-b-1 | user-b-2
taskana.roles.admin=admin | uid=admin,cn=users,OU=Test,O=TASKANA
taskana.roles.businessadmin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.taskadmin=taskadmin
taskana.domains=DOMAIN_A , DOMAIN_B
taskana.roles.business_admin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.task_admin=taskadmin
taskana.domains=DOMAIN_A | DOMAIN_B
taskana.user.minimalPermissionsToAssignDomains=READ | OPEN
taskana.classification.types=TASK , document
taskana.classification.categories.task=EXTERNAL, manual, autoMAtic, Process
taskana.classification.types=TASK | document
taskana.classification.categories.task=EXTERNAL| manual| autoMAtic| Process
taskana.classification.categories.document=EXTERNAL
taskana.jobs.cleanup.schedule=0 0 3 * * *
taskana.jobs.cleanup.runEvery=P1D
taskana.jobs.cleanup.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.minimumAge=PT0S
taskana.jobs.runEvery=P1D
taskana.jobs.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.task.minimumAge=PT0S
taskana.jobs.cleanup.allCompletedSameParentBusiness=false
taskana.jobs.history.batchSize=50
taskana.jobs.cleanup.history.simple.batchSize=50
taskana.jobs.history.cleanup.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.history.cleanup.minimumAge=P14D
taskana.jobs.cleanup.history.simple.minimumAge=P14D
taskana.jobs.history.cleanup.runEvery=P1D
# enable or disable the jobscheduler at all
# set it to false and no jobs are running
taskana.jobscheduler.enabled=false
taskana.jobs.scheduler.enabled=false
# wait time before the first job run in millis
taskana.jobscheduler.initialstartdelay=100000
taskana.jobs.scheduler.initialStartDelay=100000
# sleeping time befor the next job runs
taskana.jobscheduler.period=12
taskana.jobs.scheduler.period=12
# timeunit for the sleeping period
# Possible values: MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS
taskana.jobscheduler.periodtimeunit=HOURS
taskana.jobscheduler.enableTaskCleanupJob=false
taskana.jobscheduler.enableTaskUpdatePriorityJob=false
taskana.jobscheduler.enableWorkbasketCleanupJob=false
taskana.jobscheduler.enableUserInfoRefreshJob=false
taskana.jobscheduler.enableHistorieCleanupJob=false
taskana.jobs.scheduler.periodTimeUnit=HOURS
taskana.jobs.cleanup.task.enable=false
taskana.jobs.priority.task.enable=false
taskana.jobs.cleanup.workbasket.enable=false
taskana.jobs.refresh.user.enable=false
taskana.jobs.cleanup.history.simple.enable=false

View File

@ -1,6 +1,7 @@
package pro.taskana.example;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import java.sql.Connection;
@ -21,7 +22,6 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
import pro.taskana.classification.api.ClassificationService;
import pro.taskana.common.api.KeyDomain;
import pro.taskana.common.api.TaskanaEngine;
import pro.taskana.common.api.exceptions.TaskanaException;
import pro.taskana.common.internal.TaskanaEngineImpl;
import pro.taskana.common.internal.transaction.TaskanaTransactionProvider;
import pro.taskana.common.internal.util.IdGenerator;
@ -35,6 +35,7 @@ import pro.taskana.task.internal.models.TaskImpl;
import pro.taskana.workbasket.api.WorkbasketService;
import pro.taskana.workbasket.api.WorkbasketType;
import pro.taskana.workbasket.api.exceptions.WorkbasketInUseException;
import pro.taskana.workbasket.api.exceptions.WorkbasketNotFoundException;
import pro.taskana.workbasket.api.models.Workbasket;
import pro.taskana.workbasket.internal.jobs.WorkbasketCleanupJob;
import pro.taskana.workbasket.internal.models.WorkbasketImpl;
@ -167,66 +168,61 @@ class TaskanaTransactionIntTest {
}
@Test
void testWorkbasketCleanupJobTransaction() {
try {
void testWorkbasketCleanupJobTransaction() throws Exception {
WorkbasketService workbasketService = taskanaEngine.getWorkbasketService();
workbasketService.createWorkbasket(createWorkBasket("key1", "wb1"));
workbasketService.createWorkbasket(createWorkBasket("key2", "wb2"));
workbasketService.createWorkbasket(createWorkBasket("key3", "wb3"));
TaskService taskService = taskanaEngine.getTaskService();
ClassificationService classificationService = taskanaEngine.getClassificationService();
classificationService.newClassification("TEST", "DOMAIN_A", "TASK");
taskService.createTask(createTask("key1", "TEST"));
taskService.createTask(createTask("key2", "TEST"));
taskService.createTask(createTask("key3", "TEST"));
WorkbasketService workbasketService = taskanaEngine.getWorkbasketService();
workbasketService.createWorkbasket(createWorkBasket("key1", "wb1"));
workbasketService.createWorkbasket(createWorkBasket("key2", "wb2"));
workbasketService.createWorkbasket(createWorkBasket("key3", "wb3"));
TaskService taskService = taskanaEngine.getTaskService();
ClassificationService classificationService = taskanaEngine.getClassificationService();
classificationService.newClassification("TEST", "DOMAIN_A", "TASK");
taskService.createTask(createTask("key1", "TEST"));
taskService.createTask(createTask("key2", "TEST"));
taskService.createTask(createTask("key3", "TEST"));
assertThat(workbasketService.createWorkbasketQuery().count()).isEqualTo(3);
assertThat(taskService.createTaskQuery().count()).isEqualTo(3);
assertThat(workbasketService.createWorkbasketQuery().count()).isEqualTo(3);
assertThat(taskService.createTaskQuery().count()).isEqualTo(3);
List<TaskSummary> tasks =
taskService
.createTaskQuery()
.workbasketKeyDomainIn(new KeyDomain("key1", "DOMAIN_A"))
.list();
taskService.claim(tasks.get(0).getId());
taskService.completeTask(tasks.get(0).getId());
tasks =
taskService
.createTaskQuery()
.workbasketKeyDomainIn(new KeyDomain("key2", "DOMAIN_A"))
.list();
taskService.claim(tasks.get(0).getId());
taskService.completeTask(tasks.get(0).getId());
workbasketService.deleteWorkbasket(workbasketService.getWorkbasket("key1", "DOMAIN_A").getId());
workbasketService.deleteWorkbasket(workbasketService.getWorkbasket("key2", "DOMAIN_A").getId());
List<TaskSummary> tasks =
taskService
.createTaskQuery()
.workbasketKeyDomainIn(new KeyDomain("key1", "DOMAIN_A"))
.list();
taskService.claim(tasks.get(0).getId());
taskService.completeTask(tasks.get(0).getId());
tasks =
taskService
.createTaskQuery()
.workbasketKeyDomainIn(new KeyDomain("key2", "DOMAIN_A"))
.list();
taskService.claim(tasks.get(0).getId());
taskService.completeTask(tasks.get(0).getId());
workbasketService.deleteWorkbasket(
workbasketService.getWorkbasket("key1", "DOMAIN_A").getId());
workbasketService.deleteWorkbasket(
workbasketService.getWorkbasket("key2", "DOMAIN_A").getId());
// Clean two tasks, key1 and key2.
TaskCleanupJob taskCleanupJob =
new TaskCleanupJob(taskanaEngine, springTransactionProvider, null);
taskCleanupJob.run();
// Clean two tasks, key1 and key2.
TaskCleanupJob taskCleanupJob =
new TaskCleanupJob(taskanaEngine, springTransactionProvider, null);
taskCleanupJob.run();
ThrowingCallable httpCall =
() ->
workbasketService.deleteWorkbasket(
workbasketService.getWorkbasket("key3", "DOMAIN_A").getId());
assertThatThrownBy(httpCall)
.isInstanceOf(WorkbasketInUseException.class)
.hasMessageContaining("contains non-completed Tasks");
ThrowingCallable httpCall =
() ->
workbasketService.deleteWorkbasket(
workbasketService.getWorkbasket("key3", "DOMAIN_A").getId());
assertThatThrownBy(httpCall)
.isInstanceOf(WorkbasketInUseException.class)
.hasMessageContaining("contains non-completed Tasks");
WorkbasketCleanupJob job =
new WorkbasketCleanupJob(taskanaEngine, springTransactionProvider, null);
job.run();
WorkbasketCleanupJob job =
new WorkbasketCleanupJob(taskanaEngine, springTransactionProvider, null);
job.run();
assertThat(workbasketService.getWorkbasket("key1", "DOMAIN_A")).isNull();
assertThat(workbasketService.getWorkbasket("key2", "DOMAIN_A")).isNull();
assertThat(workbasketService.getWorkbasket("key3", "DOMAIN_A")).isNotNull();
} catch (TaskanaException e) {
e.printStackTrace();
}
assertThatThrownBy(() -> workbasketService.getWorkbasket("key1", "DOMAIN_A"))
.isInstanceOf(WorkbasketNotFoundException.class);
assertThatThrownBy(() -> workbasketService.getWorkbasket("key2", "DOMAIN_A"))
.isInstanceOf(WorkbasketNotFoundException.class);
assertThatCode(() -> workbasketService.getWorkbasket("key3", "DOMAIN_A"))
.doesNotThrowAnyException();
}
private static ObjectReference createDefaultObjRef() {

View File

@ -1,35 +1,35 @@
taskana.roles.user=cn=ksc-users,cn=groups,OU=Test,O=TASKANA | teamlead-1 | teamlead-2 | user-1-1 | user-1-2 | user-2-1 | user-2-2 | user-b-1 | user-b-2
taskana.roles.admin=admin | uid=admin,cn=users,OU=Test,O=TASKANA
taskana.roles.businessadmin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.business_admin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.monitor=monitor | cn=monitor-users,cn=groups,OU=Test,O=TASKANA
taskana.roles.taskadmin=taskadmin
taskana.domains=DOMAIN_A , DOMAIN_B
taskana.roles.task_admin=taskadmin
taskana.domains=DOMAIN_A | DOMAIN_B
taskana.user.minimalPermissionsToAssignDomains=READ | OPEN
taskana.classification.types=TASK , document
taskana.classification.categories.task=EXTERNAL, manual, autoMAtic, Process
taskana.classification.types=TASK | document
taskana.classification.categories.task=EXTERNAL| manual| autoMAtic| Process
taskana.classification.categories.document=EXTERNAL
taskana.jobs.maxRetries=3
taskana.jobs.batchSize=50
taskana.jobs.cleanup.runEvery=P1D
taskana.jobs.cleanup.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.minimumAge=P0D
taskana.german.holidays.enabled=true
taskana.german.holidays.corpus-christi.enabled=false
taskana.history.deletion.on.task.deletion.enabled=true
taskana.validation.allowTimestampServiceLevelMismatch=false
taskana.jobs.runEvery=P1D
taskana.jobs.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.task.minimumAge=P0D
taskana.workingTime.holidays.german.enabled=true
taskana.workingTime.holidays.german.corpus-christi.enabled=false
taskana.history.simple.deleteOnTaskDeletion.enabled=true
taskana.servicelevel.validation.enforce=true
taskana.query.includeLongName=false
# enable or disable the jobscheduler at all
# set it to false and no jobs are running
taskana.jobscheduler.enabled=false
taskana.jobs.scheduler.enabled=false
# wait time before the first job run in millis
taskana.jobscheduler.initialstartdelay=100000
taskana.jobs.scheduler.initialStartDelay=100000
# sleeping time befor the next job runs
taskana.jobscheduler.period=12
taskana.jobs.scheduler.period=12
# timeunit for the sleeping period
# Possible values: MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS
taskana.jobscheduler.periodtimeunit=HOURS
taskana.jobscheduler.enableTaskCleanupJob=false
taskana.jobscheduler.enableTaskUpdatePriorityJob=false
taskana.jobscheduler.enableWorkbasketCleanupJob=false
taskana.jobscheduler.enableUserInfoRefreshJob=false
taskana.jobscheduler.enableHistorieCleanupJob=false
taskana.jobs.scheduler.periodTimeUnit=HOURS
taskana.jobs.cleanup.task.enable=false
taskana.jobs.priority.task.enable=false
taskana.jobs.cleanup.workbasket.enable=false
taskana.jobs.refresh.user.enable=false
taskana.jobs.cleanup.history.simple.enable=false

View File

@ -7,12 +7,14 @@ import static pro.taskana.testapi.util.ExtensionCommunicator.isTopLevelClass;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionManager;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ExtensionContext.Store;
import org.junit.jupiter.api.extension.TestInstancePostProcessor;
import org.junit.jupiter.api.extension.TestInstancePreDestroyCallback;
import org.junit.platform.commons.JUnitException;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
@ -31,6 +33,7 @@ import pro.taskana.common.internal.InternalTaskanaEngine;
import pro.taskana.common.internal.JobMapper;
import pro.taskana.common.internal.JobServiceImpl;
import pro.taskana.common.internal.TaskanaEngineImpl;
import pro.taskana.common.internal.jobs.JobScheduler;
import pro.taskana.common.internal.security.CurrentUserContextImpl;
import pro.taskana.common.internal.util.ReflectionUtil;
import pro.taskana.common.internal.util.SpiLoader;
@ -50,7 +53,8 @@ import pro.taskana.user.internal.UserServiceImpl;
import pro.taskana.workbasket.api.WorkbasketService;
import pro.taskana.workbasket.internal.WorkbasketServiceImpl;
public class TaskanaInitializationExtension implements TestInstancePostProcessor {
public class TaskanaInitializationExtension
implements TestInstancePostProcessor, TestInstancePreDestroyCallback {
public static final String STORE_TASKANA_ENTITY_MAP = "taskanaEntityMap";
@ -88,6 +92,18 @@ public class TaskanaInitializationExtension implements TestInstancePostProcessor
}
}
@SuppressWarnings("unchecked")
@Override
public void preDestroyTestInstance(ExtensionContext context) {
if (isTopLevelClass(context.getRequiredTestClass())) {
Map<Class<?>, Object> entityMap =
(Map<Class<?>, Object>) getClassLevelStore(context).get(STORE_TASKANA_ENTITY_MAP);
TaskanaEngineImpl taskanaEngineImpl =
(TaskanaEngineImpl) entityMap.get(TaskanaEngineImpl.class);
Optional.ofNullable(taskanaEngineImpl.getJobScheduler()).ifPresent(JobScheduler::stop);
}
}
private static Map<Class<?>, Object> extractEnclosingTestInstances(Object instance) {
HashMap<Class<?>, Object> instanceByClass = new HashMap<>();
while (instance != null) {

View File

@ -2,8 +2,8 @@ package pro.taskana.testapi;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.List;
import java.util.OptionalInt;
import java.util.Set;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
@ -46,7 +46,7 @@ class TaskanaInitializationExtensionTest {
@Override
public TaskanaConfiguration.Builder modify(TaskanaConfiguration.Builder builder) {
return builder.domains(List.of("A", "B"));
return builder.domains(Set.of("A", "B"));
}
@Test

View File

@ -20,7 +20,7 @@ class TestContainerExtensionTest {
@Test
void should_CreateDataSource_For_TopLevelTestClass() {
DataSource datasource = taskanaConfiguration.getDatasource();
DataSource datasource = taskanaConfiguration.getDataSource();
assertThat(datasource).isNotNull();
}
@ -40,9 +40,9 @@ class TestContainerExtensionTest {
@Test
void should_ReuseDataSource_For_NestedTestClass() {
DataSource nestedDataSource = taskanaConfiguration.getDatasource();
DataSource nestedDataSource = taskanaConfiguration.getDataSource();
DataSource topLevelDataSource =
TestContainerExtensionTest.this.taskanaConfiguration.getDatasource();
TestContainerExtensionTest.this.taskanaConfiguration.getDataSource();
assertThat(nestedDataSource).isSameAs(topLevelDataSource).isNotNull();
}
@ -70,9 +70,9 @@ class TestContainerExtensionTest {
@Test
void should_ReuseDataSource_For_NestedTestClassWhichImplementsConfigurationModifier() {
DataSource nestedDataSource = taskanaConfiguration.getDatasource();
DataSource nestedDataSource = taskanaConfiguration.getDataSource();
DataSource topLevelDataSource =
TestContainerExtensionTest.this.taskanaConfiguration.getDatasource();
TestContainerExtensionTest.this.taskanaConfiguration.getDataSource();
assertThat(nestedDataSource).isSameAs(topLevelDataSource).isNotNull();
}
@ -96,9 +96,9 @@ class TestContainerExtensionTest {
@Test
void should_ReuseDataSource_For_NestedTestAnnotatedWithCleanTaskanaContext() {
DataSource nestedDataSource = taskanaConfiguration.getDatasource();
DataSource nestedDataSource = taskanaConfiguration.getDataSource();
DataSource topLevelDataSource =
TestContainerExtensionTest.this.taskanaConfiguration.getDatasource();
TestContainerExtensionTest.this.taskanaConfiguration.getDataSource();
assertThat(nestedDataSource).isNotNull().isSameAs(topLevelDataSource);
}
@ -121,12 +121,12 @@ class TestContainerExtensionTest {
@Test
void should_ReuseDataSource_For_NestedTestAnnotatedWithCleanTaskanaContext() {
DataSource nestedNestedDataSource = taskanaConfiguration.getDatasource();
DataSource nestedNestedDataSource = taskanaConfiguration.getDataSource();
DataSource nestedDataSource =
NestedNestedTestClassAnnotatedWithCleanTaskanaContext.this.taskanaConfiguration
.getDatasource();
.getDataSource();
DataSource topLevelDataSource =
TestContainerExtensionTest.this.taskanaConfiguration.getDatasource();
TestContainerExtensionTest.this.taskanaConfiguration.getDataSource();
assertThat(nestedNestedDataSource)
.isNotNull()
@ -168,9 +168,9 @@ class TestContainerExtensionTest {
@Test
void should_ReuseNewDataSource_For_NestedTestAnnotatedWithCleanTaskanaContext() {
DataSource nestedDataSource = taskanaConfiguration.getDatasource();
DataSource nestedDataSource = taskanaConfiguration.getDataSource();
DataSource topLevelDataSource =
TestContainerExtensionTest.this.taskanaConfiguration.getDatasource();
TestContainerExtensionTest.this.taskanaConfiguration.getDataSource();
assertThat(nestedDataSource).isNotNull().isSameAs(topLevelDataSource);
}
@ -196,9 +196,9 @@ class TestContainerExtensionTest {
@Test
void should_ReuseDataSource_For_NestedTestClassWithServiceProvider() {
DataSource nestedDataSource = taskanaConfiguration.getDatasource();
DataSource nestedDataSource = taskanaConfiguration.getDataSource();
DataSource topLevelDataSource =
TestContainerExtensionTest.this.taskanaConfiguration.getDatasource();
TestContainerExtensionTest.this.taskanaConfiguration.getDataSource();
assertThat(nestedDataSource).isSameAs(topLevelDataSource).isNotNull();
}

View File

@ -1,35 +1,35 @@
taskana.roles.user=cn=ksc-users,cn=groups,OU=Test,O=TASKANA | teamlead-1 | teamlead-2 | user-1-1 | user-1-2 | user-2-1 | user-2-2 | user-b-1 | user-b-2
taskana.roles.admin=admin | uid=admin,cn=users,OU=Test,O=TASKANA
taskana.roles.businessadmin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.business_admin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.monitor=monitor | cn=monitor-users,cn=groups,OU=Test,O=TASKANA
taskana.roles.taskadmin=taskadmin
taskana.domains=DOMAIN_A , DOMAIN_B
taskana.roles.task_admin=taskadmin
taskana.domains=DOMAIN_A | DOMAIN_B
taskana.user.minimalPermissionsToAssignDomains=READ | OPEN
taskana.classification.types=TASK , document
taskana.classification.categories.task=EXTERNAL, manual, autoMAtic, Process
taskana.classification.types=TASK | document
taskana.classification.categories.task=EXTERNAL| manual| autoMAtic| Process
taskana.classification.categories.document=EXTERNAL
taskana.jobs.maxRetries=3
taskana.jobs.batchSize=50
taskana.jobs.cleanup.runEvery=P1D
taskana.jobs.cleanup.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.minimumAge=P14D
taskana.german.holidays.enabled=true
taskana.german.holidays.corpus-christi.enabled=false
taskana.history.deletion.on.task.deletion.enabled=true
taskana.validation.allowTimestampServiceLevelMismatch=false
taskana.jobs.runEvery=P1D
taskana.jobs.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.task.minimumAge=P14D
taskana.workingTime.holidays.german.enabled=true
taskana.workingTime.holidays.german.corpus-christi.enabled=false
taskana.history.simple.deleteOnTaskDeletion.enabled=true
taskana.servicelevel.validation.enforce=true
taskana.query.includeLongName=false
# enable or disable the jobscheduler at all
# set it to false and no jobs are running
taskana.jobscheduler.enabled=false
taskana.jobs.scheduler.enabled=false
# wait time before the first job run in millis
taskana.jobscheduler.initialstartdelay=100000
taskana.jobs.scheduler.initialStartDelay=100000
# sleeping time befor the next job runs
taskana.jobscheduler.period=12
taskana.jobs.scheduler.period=12
# timeunit for the sleeping period
# Possible values: MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS
taskana.jobscheduler.periodtimeunit=HOURS
taskana.jobscheduler.enableTaskCleanupJob=false
taskana.jobscheduler.enableTaskUpdatePriorityJob=false
taskana.jobscheduler.enableWorkbasketCleanupJob=false
taskana.jobscheduler.enableUserInfoRefreshJob=false
taskana.jobscheduler.enableHistorieCleanupJob=false
taskana.jobs.scheduler.periodTimeUnit=HOURS
taskana.jobs.cleanup.task.enable=false
taskana.jobs.priority.task.enable=false
taskana.jobs.cleanup.workbasket.enable=false
taskana.jobs.refresh.user.enable=false
taskana.jobs.cleanup.history.simple.enable=false

View File

@ -1,40 +1,40 @@
taskana.roles.user=cn=ksc-users,cn=groups,OU=Test,O=TASKANA | teamlead-1 | teamlead-2 | user-1-1 | user-1-2 | user-2-1 | user-2-2 | user-b-1 | user-b-2
taskana.roles.admin=admin | uid=admin,cn=users,OU=Test,O=TASKANA
taskana.roles.businessadmin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.business_admin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.monitor=monitor | cn=monitor-users,cn=groups,OU=Test,O=TASKANA
taskana.roles.taskadmin=taskadmin
taskana.domains=DOMAIN_A,DOMAIN_B,DOMAIN_C,DOMAIN_TEST
taskana.roles.task_admin=taskadmin
taskana.domains=DOMAIN_A|DOMAIN_B|DOMAIN_C|DOMAIN_TEST
taskana.user.minimalPermissionsToAssignDomains=READ | OPEN
taskana.classification.types=TASK,DOCUMENT
taskana.classification.categories.task=EXTERNAL, manual, autoMAtic, Process
taskana.classification.types=TASK|DOCUMENT
taskana.classification.categories.task=EXTERNAL| manual| autoMAtic| Process
taskana.classification.categories.document=EXTERNAL
taskana.jobs.maxRetries=3
taskana.jobs.batchSize=50
taskana.jobs.cleanup.runEvery=P1D
taskana.jobs.cleanup.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.minimumAge=P14D
taskana.jobs.history.batchSize=50
taskana.jobs.runEvery=P1D
taskana.jobs.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.task.minimumAge=P14D
taskana.jobs.cleanup.history.simple.batchSize=50
taskana.jobs.history.cleanup.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.history.cleanup.minimumAge=P14D
taskana.jobs.cleanup.history.simple.minimumAge=P14D
taskana.jobs.history.cleanup.runEvery=P1D
taskana.jobs.user.refresh.runEvery=P1D
taskana.jobs.user.refresh.firstRunAt=2018-07-25T23:00:00Z
taskana.german.holidays.enabled=true
taskana.german.holidays.corpus-christi.enabled=true
taskana.historylogger.name=AUDIT
taskana.workingTime.holidays.german.enabled=true
taskana.workingTime.holidays.german.corpus-christi.enabled=true
taskana.history.logger.name=AUDIT
taskana.routing.dmn=/dmn-table.dmn
# enable or disable the jobscheduler at all
# set it to false and no jobs are running
taskana.jobscheduler.enabled=false
taskana.jobs.scheduler.enabled=false
# wait time before the first job run in millis
taskana.jobscheduler.initialstartdelay=100
taskana.jobs.scheduler.initialStartDelay=100
# sleeping time befor the next job runs
taskana.jobscheduler.period=12
taskana.jobs.scheduler.period=12
# timeunit for the sleeping period
# Possible values: MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS
taskana.jobscheduler.periodtimeunit=HOURS
taskana.jobscheduler.enableTaskCleanupJob=true
taskana.jobscheduler.enableTaskUpdatePriorityJob=true
taskana.jobscheduler.enableWorkbasketCleanupJob=true
taskana.jobscheduler.enableUserInfoRefreshJob=true
taskana.jobscheduler.enableHistorieCleanupJob=false
taskana.jobs.scheduler.periodTimeUnit=HOURS
taskana.jobs.cleanup.task.enable=true
taskana.jobs.priority.task.enable=true
taskana.jobs.cleanup.workbasket.enable=true
taskana.jobs.refresh.user.enable=true
taskana.jobs.cleanup.history.simple.enable=false

View File

@ -1,31 +1,31 @@
taskana.roles.user=cn=ksc-users,cn=groups,OU=Test,O=TASKANA | teamlead-1 | teamlead-2 | user-1-1 | user-1-2 | user-2-1 | user-2-2 | user-b-1 | user-b-2
taskana.roles.admin=admin | uid=admin,cn=users,OU=Test,O=TASKANA
taskana.roles.businessadmin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.business_admin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.monitor=monitor | cn=monitor-users,cn=groups,OU=Test,O=TASKANA
taskana.roles.taskadmin=taskadmin
taskana.domains=DOMAIN_A,DOMAIN_B,DOMAIN_C,DOMAIN_TEST
taskana.roles.task_admin=taskadmin
taskana.domains=DOMAIN_A|DOMAIN_B|DOMAIN_C|DOMAIN_TEST
taskana.user.minimalPermissionsToAssignDomains=READ | OPEN
taskana.classification.types=TASK,DOCUMENT
taskana.classification.categories.task=EXTERNAL, manual, autoMAtic, Process
taskana.classification.types=TASK|DOCUMENT
taskana.classification.categories.task=EXTERNAL| manual| autoMAtic| Process
taskana.classification.categories.document=EXTERNAL
taskana.jobs.maxRetries=3
taskana.jobs.batchSize=50
taskana.jobs.cleanup.runEvery=P1D
taskana.jobs.cleanup.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.minimumAge=P14D
taskana.german.holidays.enabled=true
taskana.jobs.runEvery=P1D
taskana.jobs.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.task.minimumAge=P14D
taskana.workingTime.holidays.german.enabled=true
# enable or disable the jobscheduler at all
# set it to false and no jobs are running
taskana.jobscheduler.enabled=false
taskana.jobs.scheduler.enabled=false
# wait time before the first job run in millis
taskana.jobscheduler.initialstartdelay=100
taskana.jobs.scheduler.initialStartDelay=100
# sleeping time befor the next job runs
taskana.jobscheduler.period=12
taskana.jobs.scheduler.period=12
# timeunit for the sleeping period
# Possible values: MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS
taskana.jobscheduler.periodtimeunit=HOURS
taskana.jobscheduler.enableTaskCleanupJob=true
taskana.jobscheduler.enableTaskUpdatePriorityJob=true
taskana.jobscheduler.enableWorkbasketCleanupJob=true
taskana.jobscheduler.enableUserInfoRefreshJob=true
taskana.jobscheduler.enableHistorieCleanupJob=false
taskana.jobs.scheduler.periodTimeUnit=HOURS
taskana.jobs.cleanup.task.enable=true
taskana.jobs.priority.task.enable=true
taskana.jobs.cleanup.workbasket.enable=true
taskana.jobs.refresh.user.enable=true
taskana.jobs.cleanup.history.simple.enable=false

View File

@ -1,20 +1,20 @@
taskana.roles.user=cn=ksc-users,cn=groups,OU=Test,O=TASKANA | teamlead-1 | teamlead-2 | user-1-1 | user-1-2 | user-2-1 | user-2-2 | user-b-1 | user-b-2
taskana.roles.admin=admin | uid=admin,cn=users,OU=Test,O=TASKANA
taskana.roles.businessadmin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.business_admin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.monitor=monitor | cn=monitor-users,cn=groups,OU=Test,O=TASKANA
taskana.roles.taskadmin=taskadmin
taskana.domains=DOMAIN_A,DOMAIN_B,DOMAIN_C,DEFAULT_DOMAIN,DOMAIN_TEST
taskana.roles.task_admin=taskadmin
taskana.domains=DOMAIN_A|DOMAIN_B|DOMAIN_C|DEFAULT_DOMAIN|DOMAIN_TEST
taskana.user.minimalPermissionsToAssignDomains=READ | OPEN
taskana.classification.types=TASK,DOCUMENT
taskana.classification.categories.task=EXTERNAL, manual, autoMAtic, Process
taskana.classification.types=TASK|DOCUMENT
taskana.classification.categories.task=EXTERNAL| manual| autoMAtic| Process
taskana.classification.categories.document=EXTERNAL
taskana.jobs.maxRetries=3
taskana.jobs.batchSize=50
taskana.jobs.cleanup.runEvery=P1D
taskana.jobs.cleanup.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.minimumAge=P14D
taskana.jobs.history.batchSize=50
taskana.jobs.runEvery=P1D
taskana.jobs.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.task.minimumAge=P14D
taskana.jobs.cleanup.history.simple.batchSize=50
taskana.jobs.history.cleanup.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.history.cleanup.minimumAge=P14D
taskana.jobs.cleanup.history.simple.minimumAge=P14D
taskana.jobs.history.cleanup.runEvery=P1D
taskana.german.holidays.enabled=true
taskana.workingTime.holidays.german.enabled=true

View File

@ -1,36 +1,36 @@
taskana.roles.user=cn=ksc-users,cn=groups,OU=Test,O=TASKANA | teamlead-1 | teamlead-2 | user-1-1 | user-1-2 | user-2-1 | user-2-2 | user-b-1 | user-b-2
taskana.roles.admin=admin | uid=admin,cn=users,OU=Test,O=TASKANA
taskana.roles.businessadmin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.business_admin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.monitor=monitor | cn=monitor-users,cn=groups,OU=Test,O=TASKANA
taskana.roles.taskadmin=taskadmin
taskana.domains=DOMAIN_A,DOMAIN_B,DOMAIN_C,DOMAIN_TEST
taskana.roles.task_admin=taskadmin
taskana.domains=DOMAIN_A|DOMAIN_B|DOMAIN_C|DOMAIN_TEST
taskana.user.minimalPermissionsToAssignDomains=READ | OPEN
taskana.classification.types=TASK,DOCUMENT
taskana.classification.categories.task=EXTERNAL, manual, autoMAtic, Process
taskana.classification.types=TASK|DOCUMENT
taskana.classification.categories.task=EXTERNAL| manual| autoMAtic| Process
taskana.classification.categories.document=EXTERNAL
taskana.jobs.maxRetries=3
taskana.jobs.batchSize=50
taskana.jobs.cleanup.runEvery=P1D
taskana.jobs.cleanup.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.minimumAge=P14D
taskana.jobs.history.batchSize=50
taskana.jobs.runEvery=P1D
taskana.jobs.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.task.minimumAge=P14D
taskana.jobs.cleanup.history.simple.batchSize=50
taskana.jobs.history.cleanup.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.history.cleanup.minimumAge=P14D
taskana.jobs.cleanup.history.simple.minimumAge=P14D
taskana.jobs.history.cleanup.runEvery=P1D
taskana.german.holidays.enabled=true
taskana.historylogger.name=AUDIT
taskana.workingTime.holidays.german.enabled=true
taskana.history.logger.name=AUDIT
# enable or disable the jobscheduler at all
# set it to false and no jobs are running
taskana.jobscheduler.enabled=true
taskana.jobs.scheduler.enabled=true
# wait time before the first job run in millis
taskana.jobscheduler.initialstartdelay=100
taskana.jobs.scheduler.initialStartDelay=100
# sleeping time befor the next job runs
taskana.jobscheduler.period=12
taskana.jobs.scheduler.period=12
# timeunit for the sleeping period
# Possible values: MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS
taskana.jobscheduler.periodtimeunit=HOURS
taskana.jobscheduler.enableTaskCleanupJob=true
taskana.jobscheduler.enableTaskUpdatePriorityJob=true
taskana.jobscheduler.enableWorkbasketCleanupJob=true
taskana.jobscheduler.enableUserInfoRefreshJob=true
taskana.jobscheduler.enableHistorieCleanupJob=true
taskana.jobs.scheduler.periodTimeUnit=HOURS
taskana.jobs.cleanup.task.enable=true
taskana.jobs.priority.task.enable=true
taskana.jobs.cleanup.workbasket.enable=true
taskana.jobs.refresh.user.enable=true
taskana.jobs.cleanup.history.simple.enable=true

View File

@ -1,7 +1,7 @@
package pro.taskana.common.rest;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.config.EnableHypermediaSupport;
import org.springframework.http.ResponseEntity;
@ -48,7 +48,7 @@ public class TaskanaEngineController {
*/
@GetMapping(path = RestEndpoints.URL_DOMAIN)
@Transactional(readOnly = true, rollbackFor = Exception.class)
public ResponseEntity<List<String>> getDomains() {
public ResponseEntity<Set<String>> getDomains() {
return ResponseEntity.ok(taskanaConfiguration.getDomains());
}
@ -62,7 +62,7 @@ public class TaskanaEngineController {
*/
@GetMapping(path = RestEndpoints.URL_CLASSIFICATION_CATEGORIES)
@Transactional(readOnly = true, rollbackFor = Exception.class)
public ResponseEntity<List<String>> getClassificationCategories(
public ResponseEntity<Set<String>> getClassificationCategories(
@RequestParam(required = false) String type) {
if (type != null) {
return ResponseEntity.ok(taskanaConfiguration.getClassificationCategoriesByType(type));
@ -77,7 +77,7 @@ public class TaskanaEngineController {
*/
@GetMapping(path = RestEndpoints.URL_CLASSIFICATION_TYPES)
@Transactional(readOnly = true, rollbackFor = Exception.class)
public ResponseEntity<List<String>> getClassificationTypes() {
public ResponseEntity<Set<String>> getClassificationTypes() {
return ResponseEntity.ok(taskanaConfiguration.getClassificationTypes());
}
@ -89,7 +89,7 @@ public class TaskanaEngineController {
*/
@GetMapping(path = RestEndpoints.URL_CLASSIFICATION_CATEGORIES_BY_TYPES)
@Transactional(readOnly = true, rollbackFor = Exception.class)
public ResponseEntity<Map<String, List<String>>> getClassificationCategoriesByTypeMap() {
public ResponseEntity<Map<String, Set<String>>> getClassificationCategoriesByTypeMap() {
return ResponseEntity.ok(taskanaConfiguration.getClassificationCategoriesByType());
}

View File

@ -46,7 +46,6 @@ import pro.taskana.common.api.exceptions.TaskanaRuntimeException;
import pro.taskana.common.api.exceptions.UnsupportedDatabaseException;
import pro.taskana.common.api.exceptions.WrongCustomHolidayFormatException;
import pro.taskana.common.internal.util.MapCreator;
import pro.taskana.common.internal.util.Pair;
import pro.taskana.common.rest.models.ExceptionRepresentationModel;
import pro.taskana.spi.history.api.exceptions.TaskanaHistoryEventNotFoundException;
import pro.taskana.task.api.exceptions.AttachmentPersistenceException;
@ -74,58 +73,56 @@ public class TaskanaRestExceptionHandler extends ResponseEntityExceptionHandler
public static final String ERROR_KEY_QUERY_MALFORMED = "QUERY_PARAMETER_MALFORMED";
public static final String ERROR_KEY_PAYLOAD = "PAYLOAD_TOO_LARGE";
public static final String ERROR_KEY_UNKNOWN_ERROR = "UNKNOWN_ERROR";
private static final Map<String, HttpStatus> HTTP_STATUS_BY_ERRORCODE_KEY =
Stream.of(
Pair.of(MalformedServiceLevelException.ERROR_KEY, HttpStatus.BAD_REQUEST),
Pair.of(WrongCustomHolidayFormatException.ERROR_KEY, HttpStatus.BAD_REQUEST),
Pair.of(DomainNotFoundException.ERROR_KEY, HttpStatus.BAD_REQUEST),
Pair.of(InvalidArgumentException.ERROR_KEY, HttpStatus.BAD_REQUEST),
Pair.of(ERROR_KEY_QUERY_MALFORMED, HttpStatus.BAD_REQUEST),
Pair.of(InvalidCallbackStateException.ERROR_KEY, HttpStatus.BAD_REQUEST),
Pair.of(InvalidOwnerException.ERROR_KEY, HttpStatus.BAD_REQUEST),
Pair.of(InvalidTaskStateException.ERROR_KEY, HttpStatus.BAD_REQUEST),
//
Pair.of(NotAuthorizedException.ERROR_KEY, HttpStatus.FORBIDDEN),
Pair.of(NotAuthorizedOnTaskCommentException.ERROR_KEY, HttpStatus.FORBIDDEN),
Pair.of(NotAuthorizedOnWorkbasketException.ERROR_KEY_ID, HttpStatus.FORBIDDEN),
Pair.of(
NotAuthorizedOnWorkbasketException.ERROR_KEY_KEY_DOMAIN, HttpStatus.FORBIDDEN),
//
Pair.of(ClassificationNotFoundException.ERROR_KEY_ID, HttpStatus.NOT_FOUND),
Pair.of(ClassificationNotFoundException.ERROR_KEY_KEY_DOMAIN, HttpStatus.NOT_FOUND),
Pair.of(TaskCommentNotFoundException.ERROR_KEY, HttpStatus.NOT_FOUND),
Pair.of(TaskNotFoundException.ERROR_KEY, HttpStatus.NOT_FOUND),
Pair.of(UserNotFoundException.ERROR_KEY, HttpStatus.NOT_FOUND),
Pair.of(WorkbasketNotFoundException.ERROR_KEY_ID, HttpStatus.NOT_FOUND),
Pair.of(WorkbasketNotFoundException.ERROR_KEY_KEY_DOMAIN, HttpStatus.NOT_FOUND),
Pair.of(TaskanaHistoryEventNotFoundException.ERROR_KEY, HttpStatus.NOT_FOUND),
//
Pair.of(AttachmentPersistenceException.ERROR_KEY, HttpStatus.CONFLICT),
Pair.of(ClassificationAlreadyExistException.ERROR_KEY, HttpStatus.CONFLICT),
Pair.of(ConcurrencyException.ERROR_KEY, HttpStatus.CONFLICT),
Pair.of(TaskAlreadyExistException.ERROR_KEY, HttpStatus.CONFLICT),
Pair.of(UserAlreadyExistException.ERROR_KEY, HttpStatus.CONFLICT),
Pair.of(WorkbasketAccessItemAlreadyExistException.ERROR_KEY, HttpStatus.CONFLICT),
Pair.of(WorkbasketAlreadyExistException.ERROR_KEY, HttpStatus.CONFLICT),
Pair.of(WorkbasketMarkedForDeletionException.ERROR_KEY, HttpStatus.CONFLICT),
//
Pair.of(ERROR_KEY_PAYLOAD, HttpStatus.PAYLOAD_TOO_LARGE),
//
Pair.of(ClassificationInUseException.ERROR_KEY, HttpStatus.LOCKED),
Pair.of(WorkbasketInUseException.ERROR_KEY, HttpStatus.LOCKED),
//
Pair.of(AutocommitFailedException.ERROR_KEY, HttpStatus.INTERNAL_SERVER_ERROR),
Pair.of(ConnectionNotSetException.ERROR_KEY, HttpStatus.INTERNAL_SERVER_ERROR),
Pair.of(SystemException.ERROR_KEY, HttpStatus.INTERNAL_SERVER_ERROR),
Pair.of(UnsupportedDatabaseException.ERROR_KEY, HttpStatus.INTERNAL_SERVER_ERROR),
Pair.of(ERROR_KEY_UNKNOWN_ERROR, HttpStatus.INTERNAL_SERVER_ERROR))
.collect(Collectors.toMap(Pair::getLeft, Pair::getRight));
private static final Map<String, HttpStatus> HTTP_STATUS_BY_ERROR_CODE_KEY =
Map.ofEntries(
Map.entry(MalformedServiceLevelException.ERROR_KEY, HttpStatus.BAD_REQUEST),
Map.entry(WrongCustomHolidayFormatException.ERROR_KEY, HttpStatus.BAD_REQUEST),
Map.entry(DomainNotFoundException.ERROR_KEY, HttpStatus.BAD_REQUEST),
Map.entry(InvalidArgumentException.ERROR_KEY, HttpStatus.BAD_REQUEST),
Map.entry(ERROR_KEY_QUERY_MALFORMED, HttpStatus.BAD_REQUEST),
Map.entry(InvalidCallbackStateException.ERROR_KEY, HttpStatus.BAD_REQUEST),
Map.entry(InvalidOwnerException.ERROR_KEY, HttpStatus.BAD_REQUEST),
Map.entry(InvalidTaskStateException.ERROR_KEY, HttpStatus.BAD_REQUEST),
//
Map.entry(NotAuthorizedException.ERROR_KEY, HttpStatus.FORBIDDEN),
Map.entry(NotAuthorizedOnTaskCommentException.ERROR_KEY, HttpStatus.FORBIDDEN),
Map.entry(NotAuthorizedOnWorkbasketException.ERROR_KEY_ID, HttpStatus.FORBIDDEN),
Map.entry(NotAuthorizedOnWorkbasketException.ERROR_KEY_KEY_DOMAIN, HttpStatus.FORBIDDEN),
//
Map.entry(ClassificationNotFoundException.ERROR_KEY_ID, HttpStatus.NOT_FOUND),
Map.entry(ClassificationNotFoundException.ERROR_KEY_KEY_DOMAIN, HttpStatus.NOT_FOUND),
Map.entry(TaskCommentNotFoundException.ERROR_KEY, HttpStatus.NOT_FOUND),
Map.entry(TaskNotFoundException.ERROR_KEY, HttpStatus.NOT_FOUND),
Map.entry(UserNotFoundException.ERROR_KEY, HttpStatus.NOT_FOUND),
Map.entry(WorkbasketNotFoundException.ERROR_KEY_ID, HttpStatus.NOT_FOUND),
Map.entry(WorkbasketNotFoundException.ERROR_KEY_KEY_DOMAIN, HttpStatus.NOT_FOUND),
Map.entry(TaskanaHistoryEventNotFoundException.ERROR_KEY, HttpStatus.NOT_FOUND),
//
Map.entry(AttachmentPersistenceException.ERROR_KEY, HttpStatus.CONFLICT),
Map.entry(ClassificationAlreadyExistException.ERROR_KEY, HttpStatus.CONFLICT),
Map.entry(ConcurrencyException.ERROR_KEY, HttpStatus.CONFLICT),
Map.entry(TaskAlreadyExistException.ERROR_KEY, HttpStatus.CONFLICT),
Map.entry(UserAlreadyExistException.ERROR_KEY, HttpStatus.CONFLICT),
Map.entry(WorkbasketAccessItemAlreadyExistException.ERROR_KEY, HttpStatus.CONFLICT),
Map.entry(WorkbasketAlreadyExistException.ERROR_KEY, HttpStatus.CONFLICT),
Map.entry(WorkbasketMarkedForDeletionException.ERROR_KEY, HttpStatus.CONFLICT),
//
Map.entry(ERROR_KEY_PAYLOAD, HttpStatus.PAYLOAD_TOO_LARGE),
//
Map.entry(ClassificationInUseException.ERROR_KEY, HttpStatus.LOCKED),
Map.entry(WorkbasketInUseException.ERROR_KEY, HttpStatus.LOCKED),
//
Map.entry(AutocommitFailedException.ERROR_KEY, HttpStatus.INTERNAL_SERVER_ERROR),
Map.entry(ConnectionNotSetException.ERROR_KEY, HttpStatus.INTERNAL_SERVER_ERROR),
Map.entry(SystemException.ERROR_KEY, HttpStatus.INTERNAL_SERVER_ERROR),
Map.entry(UnsupportedDatabaseException.ERROR_KEY, HttpStatus.INTERNAL_SERVER_ERROR),
Map.entry(ERROR_KEY_UNKNOWN_ERROR, HttpStatus.INTERNAL_SERVER_ERROR));
@ExceptionHandler(MaxUploadSizeExceededException.class)
protected ResponseEntity<Object> handleMaxUploadSizeExceededException(
MaxUploadSizeExceededException ex, WebRequest req) {
HttpStatus status =
HTTP_STATUS_BY_ERRORCODE_KEY.getOrDefault(
HTTP_STATUS_BY_ERROR_CODE_KEY.getOrDefault(
ERROR_KEY_PAYLOAD, HttpStatus.INTERNAL_SERVER_ERROR);
return buildResponse(ErrorCode.of(ERROR_KEY_PAYLOAD), ex, req, status);
}
@ -146,7 +143,7 @@ public class TaskanaRestExceptionHandler extends ResponseEntityExceptionHandler
protected ResponseEntity<Object> handleIllegalArgumentException(
IllegalArgumentException ex, WebRequest req) {
HttpStatus status =
HTTP_STATUS_BY_ERRORCODE_KEY.getOrDefault(
HTTP_STATUS_BY_ERROR_CODE_KEY.getOrDefault(
InvalidArgumentException.ERROR_KEY, HttpStatus.INTERNAL_SERVER_ERROR);
return buildResponse(ErrorCode.of(InvalidArgumentException.ERROR_KEY), ex, req, status);
}
@ -155,7 +152,7 @@ public class TaskanaRestExceptionHandler extends ResponseEntityExceptionHandler
protected ResponseEntity<Object> handleTaskanaRuntimeException(
TaskanaRuntimeException ex, WebRequest req) {
HttpStatus status =
HTTP_STATUS_BY_ERRORCODE_KEY.getOrDefault(
HTTP_STATUS_BY_ERROR_CODE_KEY.getOrDefault(
ex.getErrorCode().getKey(), HttpStatus.INTERNAL_SERVER_ERROR);
return buildResponse(ex.getErrorCode(), ex, req, status);
}
@ -163,7 +160,7 @@ public class TaskanaRestExceptionHandler extends ResponseEntityExceptionHandler
@ExceptionHandler(TaskanaException.class)
protected ResponseEntity<Object> handleTaskanaException(TaskanaException ex, WebRequest req) {
HttpStatus status =
HTTP_STATUS_BY_ERRORCODE_KEY.getOrDefault(
HTTP_STATUS_BY_ERROR_CODE_KEY.getOrDefault(
ex.getErrorCode().getKey(), HttpStatus.INTERNAL_SERVER_ERROR);
return buildResponse(ex.getErrorCode(), ex, req, status);
}

View File

@ -60,7 +60,7 @@ class TaskanaEngineControllerIntTest {
TEMPLATE.exchange(
url, HttpMethod.GET, auth, ParameterizedTypeReference.forType(List.class));
assertThat(response.getBody())
.containsExactlyInAnyOrder("MANUAL", "EXTERNAL", "AUTOMATIC", "PROCESS", "EXTERNAL");
.containsExactlyInAnyOrder("MANUAL", "EXTERNAL", "AUTOMATIC", "PROCESS");
}
@Test
@ -78,8 +78,9 @@ class TaskanaEngineControllerIntTest {
assertThat(response.getBody().getUserId()).isEqualTo("teamlead-1");
assertThat(response.getBody().getGroupIds())
.contains("cn=business-admins,cn=groups,ou=test,o=taskana");
assertThat(response.getBody().getRoles()).contains(TaskanaRole.BUSINESS_ADMIN);
assertThat(response.getBody().getRoles()).doesNotContain(TaskanaRole.ADMIN);
assertThat(response.getBody().getRoles())
.contains(TaskanaRole.BUSINESS_ADMIN)
.doesNotContain(TaskanaRole.ADMIN);
}
@Test

View File

@ -19,7 +19,6 @@ class MyTaskanaConfigurationIntTest {
@Test
void should_loadApplicationContextWithMyTaskanaProperties_When_ApplicationStarts() {
assertThat(appContext.getBean("taskanaPropertiesFileName", String.class))
.isEqualTo("/mytaskana.properties");
assertThat(appContext.getBean("taskanaPropertiesDelimiter", String.class)).isEqualTo(";");

View File

@ -48,7 +48,7 @@ class UserInfoRefreshJobIntTest {
@Order(1)
void should_RefreshUserInfo_When_UserInfoRefreshJobIsExecuted() throws Exception {
try (Connection connection = taskanaEngine.getConfiguration().getDatasource().getConnection()) {
try (Connection connection = taskanaEngine.getConfiguration().getDataSource().getConnection()) {
List<User> users = getUsers(connection);
assertThat(users).hasSize(14);
@ -99,7 +99,7 @@ class UserInfoRefreshJobIntTest {
@Order(2)
void should_PostprocessUser_When_RefreshUserPostprocessorIsActive() throws Exception {
try (Connection connection = taskanaEngine.getConfiguration().getDatasource().getConnection()) {
try (Connection connection = taskanaEngine.getConfiguration().getDataSource().getConnection()) {
UserInfoRefreshJob userInfoRefreshJob = new UserInfoRefreshJob(taskanaEngine);
userInfoRefreshJob.execute();

View File

@ -1,33 +1,33 @@
## Used to test and demonstrate special configuration file
taskana.roles.user=cn=ksc-users,cn=groups,OU=Test,O=TASKANA ; teamlead-1 ; teamlead-2 ; user-1-1
taskana.roles.admin=admin ; uid=admin,cn=users,OU=Test,O=TASKANA
taskana.roles.businessadmin=businessadmin ; cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.business_admin=businessadmin ; cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.monitor=monitor ; cn=monitor-users,cn=groups,OU=Test,O=TASKANA
taskana.roles.taskadmin=taskadmin
taskana.domains=DOMAIN_A,DOMAIN_B,DOMAIN_C,DOMAIN_TEST
taskana.roles.task_admin=taskadmin
taskana.domains=DOMAIN_A;DOMAIN_B;DOMAIN_C;DOMAIN_TEST
taskana.user.minimalPermissionsToAssignDomains=READ ; OPEN
taskana.classification.types=TASK,DOCUMENT
taskana.classification.categories.task=EXTERNAL, manual, autoMAtic, Process
taskana.classification.types=TASK;DOCUMENT
taskana.classification.categories.task=EXTERNAL; manual; autoMAtic; Process
taskana.classification.categories.document=EXTERNAL
taskana.jobs.maxRetries=3
taskana.jobs.batchSize=50
taskana.jobs.cleanup.runEvery=P1D
taskana.jobs.cleanup.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.minimumAge=P14D
taskana.german.holidays.enabled=true
taskana.history.deletion.on.task.deletion.enabled=true
taskana.jobs.runEvery=P1D
taskana.jobs.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.task.minimumAge=P14D
taskana.workingTime.holidays.german.enabled=true
taskana.history.simple.deleteOnTaskDeletion.enabled=true
# enable or disable the jobscheduler at all
# set it to false and no jobs are running
taskana.jobscheduler.enabled=false
taskana.jobs.scheduler.enabled=false
# wait time before the first job run in millis
taskana.jobscheduler.initialstartdelay=100
taskana.jobs.scheduler.initialStartDelay=100
# sleeping time befor the next job runs
taskana.jobscheduler.period=12
taskana.jobs.scheduler.period=12
# timeunit for the sleeping period
# Possible values: MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS
taskana.jobscheduler.periodtimeunit=HOURS
taskana.jobscheduler.enableTaskCleanupJob=true
taskana.jobscheduler.enableTaskUpdatePriorityJob=true
taskana.jobscheduler.enableWorkbasketCleanupJob=true
taskana.jobscheduler.enableUserInfoRefreshJob=true
taskana.jobscheduler.enableHistorieCleanupJob=false
taskana.jobs.scheduler.periodTimeUnit=HOURS
taskana.jobs.cleanup.task.enable=true
taskana.jobs.priority.task.enable=true
taskana.jobs.cleanup.workbasket.enable=true
taskana.jobs.refresh.user.enable=true
taskana.jobs.cleanup.history.simple.enable=false

View File

@ -1,33 +1,33 @@
taskana.roles.user=cn=ksc-users,cn=groups,OU=Test,O=TASKANA | teamlead-1 | teamlead-2 | user-1-1
taskana.roles.admin=admin | uid=admin,cn=users,OU=Test,O=TASKANA
taskana.roles.businessadmin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.business_admin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.monitor=monitor | cn=monitor-users,cn=groups,OU=Test,O=TASKANA
taskana.roles.taskadmin=taskadmin
taskana.domains=DOMAIN_A,DOMAIN_B,DOMAIN_C,DOMAIN_TEST
taskana.roles.task_admin=taskadmin
taskana.domains=DOMAIN_A|DOMAIN_B|DOMAIN_C|DOMAIN_TEST
taskana.user.minimalPermissionsToAssignDomains=READ | OPEN
taskana.classification.types=TASK,DOCUMENT
taskana.classification.categories.task=EXTERNAL, manual, autoMAtic, Process
taskana.classification.types=TASK|DOCUMENT
taskana.classification.categories.task=EXTERNAL| manual| autoMAtic| Process
taskana.classification.categories.document=EXTERNAL
taskana.jobs.maxRetries=3
taskana.jobs.batchSize=50
taskana.jobs.cleanup.runEvery=P1D
taskana.jobs.cleanup.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.minimumAge=P14D
taskana.german.holidays.enabled=true
taskana.history.deletion.on.task.deletion.enabled=true
taskana.jobs.runEvery=P1D
taskana.jobs.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.task.minimumAge=P14D
taskana.workingTime.holidays.german.enabled=true
taskana.history.simple.deleteOnTaskDeletion.enabled=true
# enable or disable the jobscheduler at all
# set it to false and no jobs are running
taskana.jobscheduler.enabled=false
taskana.jobs.scheduler.enabled=false
# wait time before the first job run in millis
taskana.jobscheduler.initialstartdelay=100
taskana.jobs.scheduler.initialStartDelay=100
# sleeping time befor the next job runs
taskana.jobscheduler.period=12
taskana.jobs.scheduler.period=12
# timeunit for the sleeping period
# Possible values: MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS
taskana.jobscheduler.periodtimeunit=HOURS
taskana.jobscheduler.enableTaskCleanupJob=true
taskana.jobscheduler.enableTaskUpdatePriorityJob=true
taskana.jobscheduler.enableWorkbasketCleanupJob=true
taskana.jobscheduler.enableUserInfoRefreshJob=true
taskana.jobscheduler.enableHistorieCleanupJob=false
taskana.jobs.scheduler.periodTimeUnit=HOURS
taskana.jobs.cleanup.task.enable=true
taskana.jobs.priority.task.enable=true
taskana.jobs.cleanup.workbasket.enable=true
taskana.jobs.refresh.user.enable=true
taskana.jobs.cleanup.history.simple.enable=false

View File

@ -1,32 +1,32 @@
taskana.roles.user=cn=ksc-users,cn=groups,OU=Test,O=TASKANA | teamlead-1 | teamlead-2 | user-1-1 | user-1-2 | user-2-1 | user-2-2 | user-b-1 | user-b-2
taskana.roles.admin=admin | uid=admin,cn=users,OU=Test,O=TASKANA
taskana.roles.businessadmin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.business_admin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.monitor=monitor | cn=monitor-users,cn=groups,OU=Test,O=TASKANA
taskana.roles.taskadmin=taskadmin
taskana.domains=DOMAIN_A,DOMAIN_B,DOMAIN_C,DOMAIN_TEST
taskana.roles.task_admin=taskadmin
taskana.domains=DOMAIN_A|DOMAIN_B|DOMAIN_C|DOMAIN_TEST
taskana.user.minimalPermissionsToAssignDomains=READ | OPEN
taskana.classification.types=TASK,DOCUMENT
taskana.classification.categories.task=EXTERNAL, manual, autoMAtic, Process
taskana.classification.types=TASK|DOCUMENT
taskana.classification.categories.task=EXTERNAL| manual| autoMAtic| Process
taskana.classification.categories.document=EXTERNAL
taskana.jobs.maxRetries=3
taskana.jobs.batchSize=50
taskana.jobs.cleanup.runEvery=P1D
taskana.jobs.cleanup.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.minimumAge=P14D
taskana.german.holidays.enabled=true
taskana.history.deletion.on.task.deletion.enabled=true
taskana.jobs.runEvery=P1D
taskana.jobs.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.task.minimumAge=P14D
taskana.workingTime.holidays.german.enabled=true
taskana.history.simple.deleteOnTaskDeletion.enabled=true
# enable or disable the jobscheduler at all
# set it to false and no jobs are running
taskana.jobscheduler.enabled=false
taskana.jobs.scheduler.enabled=false
# wait time before the first job run in millis
taskana.jobscheduler.initialstartdelay=100
taskana.jobs.scheduler.initialStartDelay=100
# sleeping time befor the next job runs
taskana.jobscheduler.period=12
taskana.jobs.scheduler.period=12
# timeunit for the sleeping period
# Possible values: MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS
taskana.jobscheduler.periodtimeunit=HOURS
taskana.jobscheduler.enableTaskCleanupJob=true
taskana.jobscheduler.enableTaskUpdatePriorityJob=true
taskana.jobscheduler.enableWorkbasketCleanupJob=true
taskana.jobscheduler.enableUserInfoRefreshJob=false
taskana.jobscheduler.enableHistorieCleanupJob=false
taskana.jobs.scheduler.periodTimeUnit=HOURS
taskana.jobs.cleanup.task.enable=true
taskana.jobs.priority.task.enable=true
taskana.jobs.cleanup.workbasket.enable=true
taskana.jobs.refresh.user.enable=false
taskana.jobs.cleanup.history.simple.enable=false

View File

@ -1,38 +1,38 @@
taskana.roles.user=cn=ksc-users,cn=groups,OU=Test,O=TASKANA | teamlead-1 | teamlead-2 | user-1-1 | user-1-2 | user-2-1 | user-2-2 | user-b-1 | user-b-2
taskana.roles.admin=admin | uid=admin,cn=users,OU=Test,O=TASKANA
taskana.roles.businessadmin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.business_admin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA
taskana.roles.monitor=monitor | cn=monitor-users,cn=groups,OU=Test,O=TASKANA
taskana.roles.taskadmin=taskadmin
taskana.domains=DOMAIN_A,DOMAIN_B,DOMAIN_C
taskana.roles.task_admin=taskadmin
taskana.domains=DOMAIN_A|DOMAIN_B|DOMAIN_C
taskana.user.minimalPermissionsToAssignDomains=READ | OPEN
taskana.classification.types=TASK,DOCUMENT
taskana.classification.categories.task=EXTERNAL, manual, autoMAtic, Process
taskana.classification.types=TASK|DOCUMENT
taskana.classification.categories.task=EXTERNAL| manual| autoMAtic| Process
taskana.classification.categories.document=EXTERNAL
taskana.jobs.maxRetries=3
taskana.jobs.batchSize=50
taskana.jobs.cleanup.runEvery=P1D
taskana.jobs.cleanup.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.minimumAge=P14D
taskana.jobs.history.batchSize=50
taskana.jobs.runEvery=P1D
taskana.jobs.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.cleanup.task.minimumAge=P14D
taskana.jobs.cleanup.history.simple.batchSize=50
taskana.jobs.history.cleanup.firstRunAt=2018-07-25T08:00:00Z
taskana.jobs.history.cleanup.minimumAge=P14D
taskana.jobs.cleanup.history.simple.minimumAge=P14D
taskana.jobs.history.cleanup.runEvery=P1D
taskana.german.holidays.enabled=true
taskana.german.holidays.corpus-christi.enabled=true
taskana.historylogger.name=AUDIT
taskana.workingTime.holidays.german.enabled=true
taskana.workingTime.holidays.german.corpus-christi.enabled=true
taskana.history.logger.name=AUDIT
taskana.routing.dmn=/dmn-table.dmn
# enable or disable the jobscheduler at all
# set it to false and no jobs are running
taskana.jobscheduler.enabled=false
taskana.jobs.scheduler.enabled=false
# wait time before the first job run in millis
taskana.jobscheduler.initialstartdelay=100
taskana.jobs.scheduler.initialStartDelay=100
# sleeping time befor the next job runs
taskana.jobscheduler.period=12
taskana.jobs.scheduler.period=12
# timeunit for the sleeping period
# Possible values: MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS
taskana.jobscheduler.periodtimeunit=HOURS
taskana.jobscheduler.enableTaskCleanupJob=true
taskana.jobscheduler.enableTaskUpdatePriorityJob=true
taskana.jobscheduler.enableWorkbasketCleanupJob=true
taskana.jobscheduler.enableUserInfoRefreshJob=false
taskana.jobscheduler.enableHistorieCleanupJob=false
taskana.jobs.scheduler.periodTimeUnit=HOURS
taskana.jobs.cleanup.task.enable=true
taskana.jobs.priority.task.enable=true
taskana.jobs.cleanup.workbasket.enable=true
taskana.jobs.refresh.user.enable=false
taskana.jobs.cleanup.history.simple.enable=false