This is an automated email from the ASF dual-hosted git repository.
ilgrosso pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/syncope.git
The following commit(s) were added to refs/heads/master by this push:
new 86b41829e4 [SYNCOPE-1840] Reworking MacroTask's form properties storage
86b41829e4 is described below
commit 86b41829e4a33f0068138014fa6f44394c06a396
Author: Francesco Chicchiriccò <[email protected]>
AuthorDate: Thu Nov 7 16:12:22 2024 +0100
[SYNCOPE-1840] Reworking MacroTask's form properties storage
---
.../console/panels/SchemaTypeWizardBuilder.java | 3 +-
.../client/console/rest/TaskRestClient.java | 4 +-
.../console/tasks/FormPropertyDefsPanel.java | 14 ++---
.../console/tasks/FormPropertyDefsPanel.html | 6 +--
.../console/tasks/FormPropertyDefsPanel.properties | 1 +
.../tasks/FormPropertyDefsPanel_fr_CA.properties | 1 +
.../tasks/FormPropertyDefsPanel_it.properties | 1 +
.../tasks/FormPropertyDefsPanel_ja.properties | 1 +
.../tasks/FormPropertyDefsPanel_pt_BR.properties | 1 +
.../tasks/FormPropertyDefsPanel_ru.properties | 1 +
.../syncope/common/lib/to/FormPropertyDefTO.java | 16 ++++++
.../common/rest/api/service/TaskService.java | 3 +-
.../org/apache/syncope/core/logic/TaskLogic.java | 5 +-
.../core/rest/cxf/service/TaskServiceImpl.java | 19 ++++++-
.../api/entity/task/FormPropertyDef.java | 10 +++-
.../core/persistence/jpa/dao/JPATaskDAO.java | 6 ++-
.../jpa/entity/task/JPAFormPropertyDef.java | 63 ++++++++++++++++++++--
.../core/persistence/jpa/inner/TaskTest.java | 6 ++-
.../neo4j/entity/task/Neo4jFormPropertyDef.java | 54 +++++++++++++++++--
.../core/persistence/neo4j/inner/TaskTest.java | 6 ++-
.../core/provisioning/api/data/TaskDataBinder.java | 3 +-
.../provisioning/java/data/TaskDataBinderImpl.java | 19 +++----
.../provisioning/java/job/MacroJobDelegate.java | 34 ++++++------
.../apache/syncope/fit/core/MacroTaskITCase.java | 11 ++--
pom.xml | 2 +-
25 files changed, 224 insertions(+), 66 deletions(-)
diff --git
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypeWizardBuilder.java
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypeWizardBuilder.java
index ab6e018b0f..9570a917d6 100644
---
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypeWizardBuilder.java
+++
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypeWizardBuilder.java
@@ -179,8 +179,7 @@ public class SchemaTypeWizardBuilder extends
BaseAjaxWizardBuilder<SchemaTO> {
LOG.error("Invalid Locale: {}",
validatable.getValue(), e);
validatable.error(new ValidationError("Invalid
Locale: " + validatable.getValue()));
- RequestCycle.get().find(AjaxRequestTarget.class).
- ifPresent(target ->
target.add(Labels.this));
+
RequestCycle.get().find(AjaxRequestTarget.class).ifPresent(t ->
t.add(Labels.this));
}
});
item.add(locale);
diff --git
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java
index f7c5713445..8da0fda7a4 100644
---
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java
+++
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java
@@ -25,6 +25,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
import org.apache.syncope.client.lib.batch.BatchRequest;
import org.apache.syncope.client.ui.commons.DateOps;
import org.apache.syncope.common.lib.form.SyncopeForm;
@@ -194,7 +195,8 @@ public class TaskRestClient extends BaseRestClient
implements ExecutionRestClien
}
public SyncopeForm getMacroTaskForm(final String taskKey) {
- return getService(TaskService.class).getMacroTaskForm(taskKey);
+ return getService(TaskService.class).
+ getMacroTaskForm(taskKey,
SyncopeConsoleSession.get().getLocale().toLanguageTag());
}
public void delete(final TaskType type, final String taskKey) {
diff --git
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel.java
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel.java
index 8b59be9fb3..3529397e63 100644
---
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel.java
+++
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel.java
@@ -21,6 +21,7 @@ package org.apache.syncope.client.console.tasks;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
+import java.util.Locale;
import java.util.Optional;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
@@ -89,13 +90,6 @@ public class FormPropertyDefsPanel extends
AbstractModalPanel<MacroTaskTO> {
protected void populateItem(final ListItem<FormPropertyDefTO>
item) {
FormPropertyDefTO fpd = item.getModelObject();
- AjaxTextFieldPanel key = new AjaxTextFieldPanel(
- "key",
- "key",
- new PropertyModel<>(fpd, "key"),
- true);
- item.add(key.setRequired(true).hideLabel());
-
AjaxTextFieldPanel name = new AjaxTextFieldPanel(
"name",
"name",
@@ -103,6 +97,12 @@ public class FormPropertyDefsPanel extends
AbstractModalPanel<MacroTaskTO> {
true);
item.add(name.setRequired(true).hideLabel());
+ AjaxGridFieldPanel<Locale, String> labels = new
AjaxGridFieldPanel<>(
+ "labels",
+ "labels",
+ new PropertyModel<>(fpd, "labels"));
+ item.add(labels.hideLabel());
+
AjaxCheckBoxPanel readable = new AjaxCheckBoxPanel(
"readable",
"readable",
diff --git
a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel.html
b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel.html
index 933b16e786..7ab57b2801 100644
---
a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel.html
+++
b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel.html
@@ -25,8 +25,8 @@ under the License.
wicket:id="propertyDefContainer">
<tbody>
<tr>
- <th><wicket:message key="key"/></th>
<th><wicket:message key="name"/></th>
+ <th><wicket:message key="labels"/></th>
<th><wicket:message key="readable"/></th>
<th><wicket:message key="writable"/></th>
<th><wicket:message key="required"/></th>
@@ -37,10 +37,10 @@ under the License.
<tr wicket:id="propertyDefs">
<td>
- <span wicket:id="key"/>
+ <span wicket:id="name"/>
</td>
<td>
- <span wicket:id="name"/>
+ <span wicket:id="labels"/>
</td>
<td>
<span wicket:id="readable"/>
diff --git
a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel.properties
b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel.properties
index 5831fc80ca..c61b80b25d 100644
---
a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel.properties
+++
b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel.properties
@@ -24,3 +24,4 @@ enumValues=Values
datePattern=Pattern
dropdownSingleSelection=Single Selection
dropdownFreeForm=Free Form
+labels=Labels
diff --git
a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel_fr_CA.properties
b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel_fr_CA.properties
index 5831fc80ca..c61b80b25d 100644
---
a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel_fr_CA.properties
+++
b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel_fr_CA.properties
@@ -24,3 +24,4 @@ enumValues=Values
datePattern=Pattern
dropdownSingleSelection=Single Selection
dropdownFreeForm=Free Form
+labels=Labels
diff --git
a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel_it.properties
b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel_it.properties
index 5cd41d2b8b..aa7ba2735a 100644
---
a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel_it.properties
+++
b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel_it.properties
@@ -24,3 +24,4 @@ enumValues=Valori
datePattern=Modello
dropdownSingleSelection=Selezione Singola
dropdownFreeForm=Modalit\u00e0 libera
+labels=Etichette
diff --git
a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel_ja.properties
b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel_ja.properties
index 5831fc80ca..c61b80b25d 100644
---
a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel_ja.properties
+++
b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel_ja.properties
@@ -24,3 +24,4 @@ enumValues=Values
datePattern=Pattern
dropdownSingleSelection=Single Selection
dropdownFreeForm=Free Form
+labels=Labels
diff --git
a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel_pt_BR.properties
b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel_pt_BR.properties
index 5831fc80ca..c61b80b25d 100644
---
a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel_pt_BR.properties
+++
b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel_pt_BR.properties
@@ -24,3 +24,4 @@ enumValues=Values
datePattern=Pattern
dropdownSingleSelection=Single Selection
dropdownFreeForm=Free Form
+labels=Labels
diff --git
a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel_ru.properties
b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel_ru.properties
index 5831fc80ca..c61b80b25d 100644
---
a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel_ru.properties
+++
b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/tasks/FormPropertyDefsPanel_ru.properties
@@ -24,3 +24,4 @@ enumValues=Values
datePattern=Pattern
dropdownSingleSelection=Single Selection
dropdownFreeForm=Free Form
+labels=Labels
diff --git
a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/FormPropertyDefTO.java
b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/FormPropertyDefTO.java
index 4f1d24aba5..a7c5df45aa 100644
---
a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/FormPropertyDefTO.java
+++
b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/FormPropertyDefTO.java
@@ -18,7 +18,10 @@
*/
package org.apache.syncope.common.lib.to;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import java.util.HashMap;
import java.util.LinkedHashMap;
+import java.util.Locale;
import java.util.Map;
import java.util.regex.Pattern;
import org.apache.commons.lang3.builder.EqualsBuilder;
@@ -33,6 +36,8 @@ public class FormPropertyDefTO implements NamedEntityTO {
private String name;
+ private final Map<Locale, String> labels = new HashMap<>();
+
private FormPropertyType type;
private boolean readable = true;
@@ -71,6 +76,15 @@ public class FormPropertyDefTO implements NamedEntityTO {
this.name = name;
}
+ @JsonIgnore
+ public String getLabel(final Locale locale) {
+ return labels.getOrDefault(locale, key);
+ }
+
+ public Map<Locale, String> getLabels() {
+ return labels;
+ }
+
public FormPropertyType getType() {
return type;
}
@@ -144,6 +158,7 @@ public class FormPropertyDefTO implements NamedEntityTO {
return new HashCodeBuilder().
append(key).
append(name).
+ append(labels).
append(type).
append(readable).
append(writable).
@@ -171,6 +186,7 @@ public class FormPropertyDefTO implements NamedEntityTO {
return new EqualsBuilder().
append(key, other.key).
append(name, other.name).
+ append(labels, other.labels).
append(type, other.type).
append(readable, other.readable).
append(writable, other.writable).
diff --git
a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/TaskService.java
b/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/TaskService.java
index 8b2ceb8561..5edca62132 100644
---
a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/TaskService.java
+++
b/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/TaskService.java
@@ -169,12 +169,13 @@ public interface TaskService extends ExecutableService {
* Fetches the form to fill and submit for execution, for the given macro
task (if defined).
*
* @param key macro task key
+ * @param locale form locale
* @return the form to fill and submit for execution, for the given macro
task (if defined)
*/
@GET
@Path("MACRO/{key}/form")
@Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML,
MediaType.APPLICATION_XML })
- SyncopeForm getMacroTaskForm(@NotNull @PathParam("key") String key);
+ SyncopeForm getMacroTaskForm(@NotNull @PathParam("key") String key,
@NotNull @QueryParam("locale") String locale);
/**
* Executes the macro task matching the given specs, with the provided
form as input.
diff --git
a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/TaskLogic.java
b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/TaskLogic.java
index 99c57b1a19..ac427805a9 100644
---
a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/TaskLogic.java
+++
b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/TaskLogic.java
@@ -23,6 +23,7 @@ import java.lang.reflect.Method;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
@@ -277,14 +278,14 @@ public class TaskLogic extends
AbstractExecutableLogic<TaskTO> {
@PreAuthorize("hasRole('" + IdRepoEntitlement.TASK_READ + "')")
@Transactional(readOnly = true)
- public SyncopeForm getMacroTaskForm(final String key) {
+ public SyncopeForm getMacroTaskForm(final String key, final Locale locale)
{
MacroTask task = taskDAO.findById(TaskType.MACRO, key).
filter(MacroTask.class::isInstance).map(MacroTask.class::cast).
orElseThrow(() -> new NotFoundException("MacroTask " + key));
securityChecks(IdRepoEntitlement.TASK_READ,
task.getRealm().getFullPath());
- return binder.getMacroTaskForm(task);
+ return binder.getMacroTaskForm(task, locale);
}
protected ExecTO doExecute(
diff --git
a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/TaskServiceImpl.java
b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/TaskServiceImpl.java
index f116eb2bda..374fbfb576 100644
---
a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/TaskServiceImpl.java
+++
b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/TaskServiceImpl.java
@@ -23,11 +23,15 @@ import jakarta.ws.rs.core.Response;
import java.net.URI;
import java.time.OffsetDateTime;
import java.util.List;
+import java.util.Locale;
+import org.apache.commons.lang3.LocaleUtils;
+import org.apache.syncope.common.lib.SyncopeClientException;
import org.apache.syncope.common.lib.form.SyncopeForm;
import org.apache.syncope.common.lib.to.ExecTO;
import org.apache.syncope.common.lib.to.PagedResult;
import org.apache.syncope.common.lib.to.SchedTaskTO;
import org.apache.syncope.common.lib.to.TaskTO;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
import org.apache.syncope.common.lib.types.ExecStatus;
import org.apache.syncope.common.lib.types.TaskType;
import org.apache.syncope.common.rest.api.RESTHeaders;
@@ -112,8 +116,19 @@ public class TaskServiceImpl extends
AbstractExecutableService implements TaskSe
}
@Override
- public SyncopeForm getMacroTaskForm(final String key) {
- return logic.getMacroTaskForm(key);
+ public SyncopeForm getMacroTaskForm(final String key, final String locale)
{
+ Locale localeObj = null;
+ try {
+ localeObj = LocaleUtils.toLocale(locale);
+ } catch (Exception e) {
+ LOG.error("While attempting to convert {} to Locale", locale, e);
+
+ SyncopeClientException sce =
SyncopeClientException.build(ClientExceptionType.InvalidEntity);
+ sce.getElements().add("Invalid locale '" + locale + "'");
+ throw sce;
+ }
+
+ return logic.getMacroTaskForm(key, localeObj);
}
@Override
diff --git
a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/FormPropertyDef.java
b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/FormPropertyDef.java
index 518ab750d7..551990a886 100644
---
a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/FormPropertyDef.java
+++
b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/FormPropertyDef.java
@@ -18,12 +18,14 @@
*/
package org.apache.syncope.core.persistence.api.entity.task;
+import java.util.Locale;
import java.util.Map;
+import java.util.Optional;
import java.util.regex.Pattern;
import org.apache.syncope.common.lib.form.FormPropertyType;
-import org.apache.syncope.core.persistence.api.entity.ProvidedKeyEntity;
+import org.apache.syncope.core.persistence.api.entity.Entity;
-public interface FormPropertyDef extends ProvidedKeyEntity {
+public interface FormPropertyDef extends Entity {
MacroTask getMacroTask();
@@ -33,6 +35,10 @@ public interface FormPropertyDef extends ProvidedKeyEntity {
void setName(String name);
+ Optional<String> getLabel(Locale locale);
+
+ Map<Locale, String> getLabels();
+
FormPropertyType getType();
void setType(FormPropertyType type);
diff --git
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java
index bae01701bf..19372eaafb 100644
---
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java
+++
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java
@@ -54,6 +54,7 @@ import
org.apache.syncope.core.persistence.api.entity.task.Task;
import org.apache.syncope.core.persistence.api.entity.task.TaskUtils;
import org.apache.syncope.core.persistence.api.entity.task.TaskUtilsFactory;
import org.apache.syncope.core.persistence.jpa.entity.task.JPAMacroTask;
+import org.apache.syncope.core.persistence.jpa.entity.task.JPAMacroTaskCommand;
import org.apache.syncope.core.persistence.jpa.entity.task.JPANotificationTask;
import org.apache.syncope.core.persistence.jpa.entity.task.JPAPropagationTask;
import
org.apache.syncope.core.persistence.jpa.entity.task.JPAPropagationTaskExec;
@@ -202,8 +203,9 @@ public class JPATaskDAO implements TaskDAO {
@Override
public List<MacroTask> findByCommand(final Implementation command) {
- TypedQuery<MacroTask> query = entityManager.createQuery("SELECT e FROM
" + JPAMacroTask.class.getSimpleName()
- + " e WHERE :command MEMBER OF e.commands", MacroTask.class);
+ TypedQuery<MacroTask> query = entityManager.createQuery(
+ "SELECT e.macroTask FROM " +
JPAMacroTaskCommand.class.getSimpleName() + " e "
+ + "WHERE e.command=:command", MacroTask.class);
query.setParameter("command", command);
return query.getResultList();
diff --git
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAFormPropertyDef.java
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAFormPropertyDef.java
index f877ddacee..dd1309bc9c 100644
---
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAFormPropertyDef.java
+++
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAFormPropertyDef.java
@@ -24,8 +24,16 @@ import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.Lob;
import jakarta.persistence.ManyToOne;
+import jakarta.persistence.PostLoad;
+import jakarta.persistence.PostPersist;
+import jakarta.persistence.PostUpdate;
+import jakarta.persistence.PrePersist;
+import jakarta.persistence.PreUpdate;
import jakarta.persistence.Table;
+import jakarta.persistence.Transient;
import jakarta.validation.constraints.NotNull;
+import java.util.HashMap;
+import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Pattern;
@@ -33,19 +41,24 @@ import org.apache.syncope.common.lib.form.FormPropertyType;
import org.apache.syncope.core.persistence.api.entity.task.FormPropertyDef;
import org.apache.syncope.core.persistence.api.entity.task.MacroTask;
import
org.apache.syncope.core.persistence.common.validation.FormPropertyDefCheck;
-import
org.apache.syncope.core.persistence.jpa.entity.AbstractProvidedKeyEntity;
+import
org.apache.syncope.core.persistence.jpa.entity.AbstractGeneratedKeyEntity;
import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
@Entity
@Table(name = JPAFormPropertyDef.TABLE)
@FormPropertyDefCheck
-public class JPAFormPropertyDef extends AbstractProvidedKeyEntity implements
FormPropertyDef {
+public class JPAFormPropertyDef extends AbstractGeneratedKeyEntity implements
FormPropertyDef {
private static final long serialVersionUID = -5839990371546587373L;
public static final String TABLE = "FormPropertyDef";
- protected static final TypeReference<Map<String, String>> TYPEREF = new
TypeReference<Map<String, String>>() {
+ protected static final TypeReference<Map<String, String>>
ENUMVALUES_TYPEREF =
+ new TypeReference<Map<String, String>>() {
+ };
+
+ protected static final TypeReference<HashMap<Locale, String>>
LABEL_TYPEREF =
+ new TypeReference<HashMap<Locale, String>>() {
};
private int idx;
@@ -56,6 +69,12 @@ public class JPAFormPropertyDef extends
AbstractProvidedKeyEntity implements For
@NotNull
private String name;
+ @Lob
+ private String labels;
+
+ @Transient
+ private Map<Locale, String> labelMap = new HashMap<>();
+
@NotNull
@Enumerated(EnumType.STRING)
private FormPropertyType type;
@@ -107,6 +126,16 @@ public class JPAFormPropertyDef extends
AbstractProvidedKeyEntity implements For
this.name = name;
}
+ @Override
+ public Optional<String> getLabel(final Locale locale) {
+ return Optional.ofNullable(labelMap.get(locale));
+ }
+
+ @Override
+ public Map<Locale, String> getLabels() {
+ return labelMap;
+ }
+
@Override
public FormPropertyType getType() {
return type;
@@ -169,7 +198,7 @@ public class JPAFormPropertyDef extends
AbstractProvidedKeyEntity implements For
@Override
public Map<String, String> getEnumValues() {
- return Optional.ofNullable(enumValues).map(v ->
POJOHelper.deserialize(v, TYPEREF)).orElse(Map.of());
+ return Optional.ofNullable(enumValues).map(v ->
POJOHelper.deserialize(v, ENUMVALUES_TYPEREF)).orElse(Map.of());
}
@Override
@@ -196,4 +225,30 @@ public class JPAFormPropertyDef extends
AbstractProvidedKeyEntity implements For
public void setDropdownFreeForm(final boolean dropdownFreeForm) {
this.dropdownFreeForm = dropdownFreeForm;
}
+
+ protected void json2map(final boolean clearFirst) {
+ if (clearFirst) {
+ getLabels().clear();
+ }
+ if (labels != null) {
+ getLabels().putAll(POJOHelper.deserialize(labels, LABEL_TYPEREF));
+ }
+ }
+
+ @PostLoad
+ public void postLoad() {
+ json2map(false);
+ }
+
+ @PostPersist
+ @PostUpdate
+ public void postSave() {
+ json2map(true);
+ }
+
+ @PrePersist
+ @PreUpdate
+ public void map2json() {
+ labels = POJOHelper.serialize(getLabels());
+ }
}
diff --git
a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/TaskTest.java
b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/TaskTest.java
index ab6717e2c0..b2379b8158 100644
---
a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/TaskTest.java
+++
b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/TaskTest.java
@@ -26,6 +26,7 @@ import static org.junit.jupiter.api.Assertions.fail;
import java.util.HashSet;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
@@ -188,8 +189,8 @@ public class TaskTest extends AbstractTest {
task.add(macroTaskCommand);
FormPropertyDef formPropertyDef =
entityFactory.newEntity(FormPropertyDef.class);
- formPropertyDef.setKey("one");
- formPropertyDef.setName("One");
+ formPropertyDef.setName("one");
+ formPropertyDef.getLabels().put(Locale.ENGLISH, "One");
formPropertyDef.setType(FormPropertyType.Enum);
formPropertyDef.setMacroTask(task);
task.add(formPropertyDef);
@@ -216,6 +217,7 @@ public class TaskTest extends AbstractTest {
assertEquals(1, task.getCommands().size());
assertEquals(command, task.getCommands().get(0).getCommand());
assertEquals(1, task.getFormPropertyDefs().size());
+ assertNotNull(task.getFormPropertyDefs().get(0).getKey());
assertEquals(formPropertyDef, task.getFormPropertyDefs().get(0));
MacroTask actual = (MacroTask) taskDAO.findById(TaskType.MACRO,
task.getKey()).orElseThrow();
diff --git
a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jFormPropertyDef.java
b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jFormPropertyDef.java
index ab6f9c9caa..9bac96cf61 100644
---
a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jFormPropertyDef.java
+++
b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jFormPropertyDef.java
@@ -20,6 +20,8 @@ package org.apache.syncope.core.persistence.neo4j.entity.task;
import com.fasterxml.jackson.core.type.TypeReference;
import jakarta.validation.constraints.NotNull;
+import java.util.HashMap;
+import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Pattern;
@@ -27,20 +29,27 @@ import org.apache.syncope.common.lib.form.FormPropertyType;
import org.apache.syncope.core.persistence.api.entity.task.FormPropertyDef;
import org.apache.syncope.core.persistence.api.entity.task.MacroTask;
import
org.apache.syncope.core.persistence.common.validation.FormPropertyDefCheck;
-import
org.apache.syncope.core.persistence.neo4j.entity.AbstractProvidedKeyNode;
+import
org.apache.syncope.core.persistence.neo4j.entity.AbstractGeneratedKeyNode;
import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
+import org.springframework.data.annotation.Transient;
import org.springframework.data.neo4j.core.schema.Node;
+import org.springframework.data.neo4j.core.schema.PostLoad;
import org.springframework.data.neo4j.core.schema.Relationship;
@Node(Neo4jFormPropertyDef.NODE)
@FormPropertyDefCheck
-public class Neo4jFormPropertyDef extends AbstractProvidedKeyNode implements
FormPropertyDef {
+public class Neo4jFormPropertyDef extends AbstractGeneratedKeyNode implements
FormPropertyDef {
private static final long serialVersionUID = -5839990371546587373L;
public static final String NODE = "FormPropertyDef";
- protected static final TypeReference<Map<String, String>> TYPEREF = new
TypeReference<Map<String, String>>() {
+ protected static final TypeReference<Map<String, String>>
ENUMVALUES_TYPEREF =
+ new TypeReference<Map<String, String>>() {
+ };
+
+ protected static final TypeReference<HashMap<Locale, String>>
LABEL_TYPEREF =
+ new TypeReference<HashMap<Locale, String>>() {
};
@NotNull
@@ -50,6 +59,11 @@ public class Neo4jFormPropertyDef extends
AbstractProvidedKeyNode implements For
@NotNull
private String name;
+ private String labels;
+
+ @Transient
+ private Map<Locale, String> labelMap = new HashMap<>();
+
@NotNull
private FormPropertyType type;
@@ -95,6 +109,16 @@ public class Neo4jFormPropertyDef extends
AbstractProvidedKeyNode implements For
this.name = name;
}
+ @Override
+ public Optional<String> getLabel(final Locale locale) {
+ return Optional.ofNullable(labelMap.get(locale));
+ }
+
+ @Override
+ public Map<Locale, String> getLabels() {
+ return labelMap;
+ }
+
@Override
public FormPropertyType getType() {
return type;
@@ -157,7 +181,7 @@ public class Neo4jFormPropertyDef extends
AbstractProvidedKeyNode implements For
@Override
public Map<String, String> getEnumValues() {
- return Optional.ofNullable(enumValues).map(v ->
POJOHelper.deserialize(v, TYPEREF)).orElse(Map.of());
+ return Optional.ofNullable(enumValues).map(v ->
POJOHelper.deserialize(v, ENUMVALUES_TYPEREF)).orElse(Map.of());
}
@Override
@@ -184,4 +208,26 @@ public class Neo4jFormPropertyDef extends
AbstractProvidedKeyNode implements For
public void setDropdownFreeForm(final boolean dropdownFreeForm) {
this.dropdownFreeForm = dropdownFreeForm;
}
+
+ protected void json2map(final boolean clearFirst) {
+ if (clearFirst) {
+ getLabels().clear();
+ }
+ if (labels != null) {
+ getLabels().putAll(POJOHelper.deserialize(labels, LABEL_TYPEREF));
+ }
+ }
+
+ @PostLoad
+ public void postLoad() {
+ json2map(false);
+ }
+
+ public void postSave() {
+ json2map(true);
+ }
+
+ public void map2json() {
+ labels = POJOHelper.serialize(getLabels());
+ }
}
diff --git
a/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/TaskTest.java
b/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/TaskTest.java
index a8f721e395..67aac5eef7 100644
---
a/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/TaskTest.java
+++
b/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/TaskTest.java
@@ -26,6 +26,7 @@ import static org.junit.jupiter.api.Assertions.fail;
import java.util.HashSet;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
@@ -188,8 +189,8 @@ public class TaskTest extends AbstractTest {
task.add(macroTaskCommand);
FormPropertyDef formPropertyDef =
entityFactory.newEntity(FormPropertyDef.class);
- formPropertyDef.setKey("one");
- formPropertyDef.setName("One");
+ formPropertyDef.setName("one");
+ formPropertyDef.getLabels().put(Locale.ENGLISH, "One");
formPropertyDef.setType(FormPropertyType.Enum);
formPropertyDef.setMacroTask(task);
task.add(formPropertyDef);
@@ -216,6 +217,7 @@ public class TaskTest extends AbstractTest {
assertEquals(1, task.getCommands().size());
assertEquals(command, task.getCommands().get(0).getCommand());
assertEquals(1, task.getFormPropertyDefs().size());
+ assertNotNull(task.getFormPropertyDefs().get(0).getKey());
assertEquals(formPropertyDef, task.getFormPropertyDefs().get(0));
MacroTask actual = (MacroTask) taskDAO.findById(TaskType.MACRO,
task.getKey()).orElseThrow();
diff --git
a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/TaskDataBinder.java
b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/TaskDataBinder.java
index a8a1dc56af..464437ac1a 100644
---
a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/TaskDataBinder.java
+++
b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/TaskDataBinder.java
@@ -18,6 +18,7 @@
*/
package org.apache.syncope.core.provisioning.api.data;
+import java.util.Locale;
import org.apache.syncope.common.lib.form.SyncopeForm;
import org.apache.syncope.common.lib.to.ExecTO;
import org.apache.syncope.common.lib.to.SchedTaskTO;
@@ -40,5 +41,5 @@ public interface TaskDataBinder {
<T extends TaskTO> T getTaskTO(Task<?> task, TaskUtils taskUtil, boolean
details);
- SyncopeForm getMacroTaskForm(MacroTask task);
+ SyncopeForm getMacroTaskForm(MacroTask task, Locale locale);
}
diff --git
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java
index 2c19d573aa..2edcae08bb 100644
---
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java
+++
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java
@@ -19,6 +19,7 @@
package org.apache.syncope.core.provisioning.java.data;
import java.util.Comparator;
+import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
@@ -270,8 +271,8 @@ public class TaskDataBinderImpl extends
AbstractExecutableDatabinder implements
macroTask.getFormPropertyDefs().clear();
macroTaskTO.getFormPropertyDefs().forEach(fpdTO -> {
FormPropertyDef fpd =
entityFactory.newEntity(FormPropertyDef.class);
- fpd.setKey(fpdTO.getKey());
fpd.setName(fpdTO.getName());
+ fpd.getLabels().putAll(fpdTO.getLabels());
fpd.setType(fpdTO.getType());
fpd.setReadable(fpdTO.isReadable());
fpd.setWritable(fpdTO.isWritable());
@@ -499,6 +500,7 @@ public class TaskDataBinderImpl extends
AbstractExecutableDatabinder implements
FormPropertyDefTO fpdTO = new FormPropertyDefTO();
fpdTO.setKey(fpd.getKey());
fpdTO.setName(fpd.getName());
+ fpdTO.getLabels().putAll(fpd.getLabels());
fpdTO.setType(fpd.getType());
fpdTO.setReadable(fpd.isReadable());
fpdTO.setWritable(fpd.isWritable());
@@ -581,7 +583,7 @@ public class TaskDataBinderImpl extends
AbstractExecutableDatabinder implements
}
@Override
- public SyncopeForm getMacroTaskForm(final MacroTask task) {
+ public SyncopeForm getMacroTaskForm(final MacroTask task, final Locale
locale) {
if (task.getFormPropertyDefs().isEmpty()) {
throw new NotFoundException("No form properties defined for
MacroTask " + task.getKey());
}
@@ -608,13 +610,13 @@ public class TaskDataBinderImpl extends
AbstractExecutableDatabinder implements
form.getProperties().addAll(task.getFormPropertyDefs().stream().map(fpd -> {
FormProperty prop = new FormProperty();
- prop.setId(fpd.getKey());
- prop.setName(fpd.getName());
+ prop.setId(fpd.getName());
+ prop.setName(fpd.getLabels().getOrDefault(locale, fpd.getName()));
prop.setReadable(fpd.isReadable());
prop.setRequired(fpd.isRequired());
prop.setWritable(fpd.isWritable());
prop.setType(fpd.getType());
- actions.flatMap(a -> a.getDefaultValue(fpd.getKey())).ifPresent(v
-> prop.setValue(v));
+ actions.flatMap(a -> a.getDefaultValue(fpd.getName())).ifPresent(v
-> prop.setValue(v));
switch (prop.getType()) {
case String ->
prop.setStringRegEx(fpd.getStringRegEx());
@@ -623,12 +625,11 @@ public class TaskDataBinderImpl extends
AbstractExecutableDatabinder implements
prop.setDatePattern(fpd.getDatePattern());
case Enum ->
- fpd.getEnumValues().
- forEach((key, value) ->
prop.getEnumValues().add(new FormPropertyValue(key, value)));
+ fpd.getEnumValues().forEach((k, v) ->
prop.getEnumValues().add(new FormPropertyValue(k, v)));
case Dropdown -> {
- actions.ifPresent(a -> a.getDropdownValues(fpd.getKey()).
- forEach((key, value) ->
prop.getDropdownValues().add(new FormPropertyValue(key, value))));
+ actions.ifPresent(a -> a.getDropdownValues(fpd.getName()).
+ forEach((k, v) -> prop.getDropdownValues().add(new
FormPropertyValue(k, v))));
prop.setDropdownSingleSelection(fpd.isDropdownSingleSelection());
prop.setDropdownFreeForm(fpd.isDropdownFreeForm());
}
diff --git
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/MacroJobDelegate.java
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/MacroJobDelegate.java
index 69e1a26856..c013ce1205 100644
---
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/MacroJobDelegate.java
+++
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/MacroJobDelegate.java
@@ -92,8 +92,8 @@ public class MacroJobDelegate extends
AbstractSchedTaskJobDelegate<MacroTask> {
Set<String> missingFormProperties =
task.getFormPropertyDefs().stream().
filter(FormPropertyDef::isRequired).
map(fpd -> Pair.of(
- fpd.getKey(),
- macroTaskForm.getProperty(fpd.getKey()).map(p -> p.getValue()
!= null))).
+ fpd.getName(),
+ macroTaskForm.getProperty(fpd.getName()).map(p -> p.getValue()
!= null))).
filter(pair -> pair.getRight().isEmpty()).
map(Pair::getLeft).
collect(Collectors.toSet());
@@ -104,7 +104,7 @@ public class MacroJobDelegate extends
AbstractSchedTaskJobDelegate<MacroTask> {
// build the JEXL context where variables are mapped to property
values, built according to the defined type
Map<String, Object> vars = new HashMap<>();
for (FormPropertyDef fpd : task.getFormPropertyDefs()) {
- String value =
macroTaskForm.getProperty(fpd.getKey()).map(FormProperty::getValue).orElse(null);
+ String value =
macroTaskForm.getProperty(fpd.getName()).map(FormProperty::getValue).orElse(null);
if (value == null) {
continue;
}
@@ -115,37 +115,37 @@ public class MacroJobDelegate extends
AbstractSchedTaskJobDelegate<MacroTask> {
map(pattern -> !pattern.matcher(value).matches()).
orElse(false)) {
- throw new JobExecutionException("RegEx not matching
for " + fpd.getKey() + ": " + value);
+ throw new JobExecutionException("RegEx not matching
for " + fpd.getName() + ": " + value);
}
- vars.put(fpd.getKey(), value);
+ vars.put(fpd.getName(), value);
}
case Password ->
- vars.put(fpd.getKey(), value);
+ vars.put(fpd.getName(), value);
case Boolean ->
- vars.put(fpd.getKey(), BooleanUtils.toBoolean(value));
+ vars.put(fpd.getName(), BooleanUtils.toBoolean(value));
case Date -> {
try {
- vars.put(fpd.getKey(),
StringUtils.isBlank(fpd.getDatePattern())
+ vars.put(fpd.getName(),
StringUtils.isBlank(fpd.getDatePattern())
? FormatUtils.parseDate(value)
: FormatUtils.parseDate(value,
fpd.getDatePattern()));
} catch (DateTimeParseException e) {
- throw new JobExecutionException("Unparseable date " +
fpd.getKey() + ": " + value, e);
+ throw new JobExecutionException("Unparseable date " +
fpd.getName() + ": " + value, e);
}
}
case Long ->
- vars.put(fpd.getKey(), NumberUtils.toLong(value));
+ vars.put(fpd.getName(), NumberUtils.toLong(value));
case Enum -> {
if (!fpd.getEnumValues().containsKey(value)) {
- throw new JobExecutionException("Not allowed for " +
fpd.getKey() + ": " + value);
+ throw new JobExecutionException("Not allowed for " +
fpd.getName() + ": " + value);
}
- vars.put(fpd.getKey(), value);
+ vars.put(fpd.getName(), value);
}
case Dropdown -> {
@@ -154,14 +154,14 @@ public class MacroJobDelegate extends
AbstractSchedTaskJobDelegate<MacroTask> {
? List.of(value)
: List.of(value.split(";"));
- if (!actions.map(a ->
a.getDropdownValues(fpd.getKey()).keySet()).
+ if (!actions.map(a ->
a.getDropdownValues(fpd.getName()).keySet()).
orElse(Set.of()).containsAll(values)) {
- throw new JobExecutionException("Not allowed for "
+ fpd.getKey() + ": " + values);
+ throw new JobExecutionException("Not allowed for "
+ fpd.getName() + ": " + values);
}
}
- vars.put(fpd.getKey(), value);
+ vars.put(fpd.getName(), value);
}
default -> {
@@ -309,7 +309,9 @@ public class MacroJobDelegate extends
AbstractSchedTaskJobDelegate<MacroTask> {
throw new JobExecutionException(
"While running " + command.getKey(),
- new
IllegalArgumentException(args.getClass().getName()));
+ new IllegalArgumentException(violations.stream().
+ map(v -> v.getPropertyPath() + ": " +
v.getMessage()).
+ collect(Collectors.joining(","))));
}
}
diff --git
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MacroTaskITCase.java
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MacroTaskITCase.java
index ef830174dd..f98c7277bc 100644
---
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MacroTaskITCase.java
+++
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MacroTaskITCase.java
@@ -27,6 +27,7 @@ import static org.junit.jupiter.api.Assertions.fail;
import jakarta.ws.rs.core.Response;
import java.nio.charset.StandardCharsets;
+import java.util.Locale;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.IOUtils;
import org.apache.syncope.common.lib.SyncopeClientException;
@@ -130,16 +131,16 @@ public class MacroTaskITCase extends AbstractITCase {
new
CommandTO.Builder(TestCommand.class.getSimpleName()).args(TCA).build());
FormPropertyDefTO realm = new FormPropertyDefTO();
- realm.setKey("realm");
- realm.setName("Realm");
+ realm.setName("realm");
+ realm.getLabels().put(Locale.ENGLISH, "Realm");
realm.setWritable(true);
realm.setRequired(true);
realm.setType(FormPropertyType.String);
task.getFormPropertyDefs().add(realm);
FormPropertyDefTO parent = new FormPropertyDefTO();
- parent.setKey("parent");
- parent.setName("Parent Realm");
+ parent.setName("parent");
+ parent.getLabels().put(Locale.ENGLISH, "Parent Realm");
parent.setWritable(true);
parent.setRequired(true);
parent.setType(FormPropertyType.Dropdown);
@@ -166,7 +167,7 @@ public class MacroTaskITCase extends AbstractITCase {
@Test
public void execute() {
- SyncopeForm form = TASK_SERVICE.getMacroTaskForm(MACRO_TASK_KEY);
+ SyncopeForm form = TASK_SERVICE.getMacroTaskForm(MACRO_TASK_KEY,
Locale.ENGLISH.toLanguageTag());
form.getProperty("realm").orElseThrow().setValue("macro");
FormProperty parent = form.getProperty("parent").orElseThrow();
assertTrue(parent.getDropdownValues().stream().anyMatch(v ->
"/odd".equals(v.getKey())));
diff --git a/pom.xml b/pom.xml
index 7bd73d0d69..5bdbe3c86f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -503,7 +503,7 @@ under the License.
<docker.mysql.version>9.0</docker.mysql.version>
<docker.mariadb.version>11</docker.mariadb.version>
<docker.oracle.version>23-slim-faststart</docker.oracle.version>
- <docker.neo4j.version>5.24.2</docker.neo4j.version>
+ <docker.neo4j.version>5.25.1</docker.neo4j.version>
<jdbc.postgresql.version>42.7.4</jdbc.postgresql.version>
<jdbc.mysql.version>9.1.0</jdbc.mysql.version>