Skip to content

Conversation

@ThuF
Copy link
Contributor

@ThuF ThuF commented Dec 23, 2025

TODO:

  • Remove all // TODO comments

Fixes: #5574

let projectFile = {
"guid": parameters.projectName,
"actions": []
}

Check notice

Code scanning / CodeQL

Semicolon insertion Note

Avoid automated semicolon insertion (92% of all statements in
the enclosing function
have an explicit semicolon).

Copilot Autofix

AI 14 days ago

In general, to fix this kind of issue, you add an explicit semicolon at the end of statements that currently depend on JavaScript’s automatic semicolon insertion. This makes the statement boundaries explicit and avoids subtle parsing differences if the code is refactored or minified.

For this specific case, the let projectFile = { ... } declaration in components/template/template-application-dao-v2/src/main/resources/META-INF/dirigible/template-application-dao-v2/project.json.mjs should be terminated with a semicolon immediately after the closing } of the object literal. Concretely, change line 9 from } to };. No other logic, imports, or definitions are needed, and this will not alter runtime behavior.

Suggested changeset 1
components/template/template-application-dao-v2/src/main/resources/META-INF/dirigible/template-application-dao-v2/project.json.mjs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/components/template/template-application-dao-v2/src/main/resources/META-INF/dirigible/template-application-dao-v2/project.json.mjs b/components/template/template-application-dao-v2/src/main/resources/META-INF/dirigible/template-application-dao-v2/project.json.mjs
--- a/components/template/template-application-dao-v2/src/main/resources/META-INF/dirigible/template-application-dao-v2/project.json.mjs
+++ b/components/template/template-application-dao-v2/src/main/resources/META-INF/dirigible/template-application-dao-v2/project.json.mjs
@@ -6,7 +6,7 @@
 	let projectFile = {
 		"guid": parameters.projectName,
 		"actions": []
-	}
+	};
 	const newProjectFile = JSON.stringify(projectFile);
 
 	let currenctWorkspace = workspace.getWorkspace(parameters.workspaceName);
EOF
@@ -6,7 +6,7 @@
let projectFile = {
"guid": parameters.projectName,
"actions": []
}
};
const newProjectFile = JSON.stringify(projectFile);

let currenctWorkspace = workspace.getWorkspace(parameters.workspaceName);
Copilot is powered by AI and may make mistakes. Always verify output.
try (Session session = getSessionFactory().openSession()) {
Transaction transaction = session.beginTransaction();
Object id = session.save(type, object);
Object id = session.save(type, data);

Check notice

Code scanning / CodeQL

Deprecated method or constructor invocation

Invoking [Session.save](1) should be avoided because it has been deprecated.

Copilot Autofix

AI 8 days ago

In general, the fix is to stop using the deprecated Session.save(String entityName, Object object) overload and instead use a non-deprecated persistence method such as persist(Object entity) combined with retrieval of the identifier via session.getIdentifier(entity). This aligns with modern Hibernate/JPA semantics and avoids the string-based overload that has been deprecated.

In this specific method, we have type (the Hibernate entity name) and data (a Map<String, Object> normalized for that entity). The call currently is:

Object id = session.save(type, data);

To avoid the deprecated overload while preserving functionality (returning the generated identifier), we can:

  1. Replace session.save(type, data) with session.persist(data);.
  2. After persisting, obtain the identifier with session.getIdentifier(data) and assign it to id.

This keeps the transaction semantics identical (same session and transaction handling) and still returns the identifier to the caller. For dynamic-map entities, Hibernate supports using a Map instance directly as the entity, provided it’s associated with a dynamic-map entity name in the mapping. Using persist in this way is the recommended pattern, and getIdentifier is non-deprecated and works for persistent instances. No new imports are required because Session already provides persist and getIdentifier, and we are not changing any types or introducing any new classes.

Concretely, in components/data/data-store/src/main/java/org/eclipse/dirigible/components/data/store/DataStore.java, in the save(String type, Map<String, Object> object) method, change the line with session.save(type, data) to the two-step sequence of session.persist(data); followed by Object id = session.getIdentifier(data);. The rest of the method remains the same.

Suggested changeset 1
components/data/data-store/src/main/java/org/eclipse/dirigible/components/data/store/DataStore.java

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/components/data/data-store/src/main/java/org/eclipse/dirigible/components/data/store/DataStore.java b/components/data/data-store/src/main/java/org/eclipse/dirigible/components/data/store/DataStore.java
--- a/components/data/data-store/src/main/java/org/eclipse/dirigible/components/data/store/DataStore.java
+++ b/components/data/data-store/src/main/java/org/eclipse/dirigible/components/data/store/DataStore.java
@@ -152,7 +152,8 @@
         Map<String, Object> data = JsonTypeConverter.normalizeForEntity(object, type);
         try (Session session = getSessionFactory().openSession()) {
             Transaction transaction = session.beginTransaction();
-            Object id = session.save(type, data);
+            session.persist(data);
+            Object id = session.getIdentifier(data);
             transaction.commit();
             return id;
         }
EOF
@@ -152,7 +152,8 @@
Map<String, Object> data = JsonTypeConverter.normalizeForEntity(object, type);
try (Session session = getSessionFactory().openSession()) {
Transaction transaction = session.beginTransaction();
Object id = session.save(type, data);
session.persist(data);
Object id = session.getIdentifier(data);
transaction.commit();
return id;
}
Copilot is powered by AI and may make mistakes. Always verify output.
try (Session session = getSessionFactory().openSession()) {
Transaction transaction = session.beginTransaction();
session.saveOrUpdate(type, object);
session.saveOrUpdate(type, data);

Check notice

Code scanning / CodeQL

Deprecated method or constructor invocation

Invoking [Session.saveOrUpdate](1) should be avoided because it has been deprecated.

Copilot Autofix

AI 8 days ago

Generally, the fix is to stop using the deprecated Session.saveOrUpdate(String entityName, Object object) and replace it with a non-deprecated persistence operation that preserves the existing behavior. For transient entities use persist/save, for detached ones use merge or update; for dynamic entity-name use, the closest non-deprecated alternative is session.merge(String entityName, Object object) or session.persist(String entityName, Object object) depending on semantics.

In this specific method:

public void upsert(String type, Map object) {
    Map<String, Object> data = JsonTypeConverter.normalizeForEntity(object, type);

    try (Session session = getSessionFactory().openSession()) {
        Transaction transaction = session.beginTransaction();
        session.saveOrUpdate(type, data);
        transaction.commit();
    }
}

the intention is clearly “upsert” (insert if new, update if existing). The best non-deprecated Hibernate operation that implements this semantic in one call is Session.merge(String entityName, Object object), which will insert if there is no row and update otherwise, and is not deprecated. So we should replace session.saveOrUpdate(type, data); with session.merge(type, data); while leaving the rest of the logic intact. No new imports are required because merge is a method on org.hibernate.Session, which is already imported; only the line with the deprecated call needs to change in components/data/data-store/src/main/java/org/eclipse/dirigible/components/data/store/DataStore.java.

Suggested changeset 1
components/data/data-store/src/main/java/org/eclipse/dirigible/components/data/store/DataStore.java

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/components/data/data-store/src/main/java/org/eclipse/dirigible/components/data/store/DataStore.java b/components/data/data-store/src/main/java/org/eclipse/dirigible/components/data/store/DataStore.java
--- a/components/data/data-store/src/main/java/org/eclipse/dirigible/components/data/store/DataStore.java
+++ b/components/data/data-store/src/main/java/org/eclipse/dirigible/components/data/store/DataStore.java
@@ -291,7 +291,7 @@
 
         try (Session session = getSessionFactory().openSession()) {
             Transaction transaction = session.beginTransaction();
-            session.saveOrUpdate(type, data);
+            session.merge(type, data);
             transaction.commit();
         }
     }
EOF
@@ -291,7 +291,7 @@

try (Session session = getSessionFactory().openSession()) {
Transaction transaction = session.beginTransaction();
session.saveOrUpdate(type, data);
session.merge(type, data);
transaction.commit();
}
}
Copilot is powered by AI and may make mistakes. Always verify output.
try (Session session = getSessionFactory().openSession()) {
Transaction transaction = session.beginTransaction();
session.update(type, object);
session.update(type, data);

Check notice

Code scanning / CodeQL

Deprecated method or constructor invocation

Invoking [Session.update](1) should be avoided because it has been deprecated.

Copilot Autofix

AI 8 days ago

In general, the fix is to stop using the deprecated Session.update(String entityName, Object object) overload and switch to a non‑deprecated API that has equivalent behavior. For plain Hibernate code, the most direct replacement is session.bySimpleNaturalId(entityClass).load(id) for natural IDs or session.update(Object) for entities already associated with a proper type; however, in this code the entity is represented as a Map<String, Object> and the entity name is passed explicitly as type. To maintain that behavior, the best like‑for‑like replacement is to obtain an EntityPersister for the given entity name from the SessionFactory and use its non‑deprecated update style operations. But that is more invasive and relies on internal APIs. A simpler and still valid approach in recent Hibernate is to use Session.merge(String entityName, Object object), which is not deprecated and supports passing an entity name as a string while handling both transient and detached instances. Since this update method is used within an explicit transaction and the object is detached (built as a Map via JsonTypeConverter.normalizeForEntity), merge is an appropriate replacement that preserves functionality while avoiding the deprecated update overload.

Concretely, in DataStore.java, in the update(String type, Map object) method, replace session.update(type, data); with session.merge(type, data);. This uses the non‑deprecated Session.merge(String entityName, Object object) method, which is available on the same Session type already imported, so no additional imports are needed and no other code paths need to change. The upsert and delete methods also use string‑entity overloads (saveOrUpdate(type, data) and delete(type, object)), but the CodeQL issue you asked about is specifically for update, so we will only change that line.


Suggested changeset 1
components/data/data-store/src/main/java/org/eclipse/dirigible/components/data/store/DataStore.java

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/components/data/data-store/src/main/java/org/eclipse/dirigible/components/data/store/DataStore.java b/components/data/data-store/src/main/java/org/eclipse/dirigible/components/data/store/DataStore.java
--- a/components/data/data-store/src/main/java/org/eclipse/dirigible/components/data/store/DataStore.java
+++ b/components/data/data-store/src/main/java/org/eclipse/dirigible/components/data/store/DataStore.java
@@ -318,7 +318,7 @@
 
         try (Session session = getSessionFactory().openSession()) {
             Transaction transaction = session.beginTransaction();
-            session.update(type, data);
+            session.merge(type, data);
             transaction.commit();
         }
     }
EOF
@@ -318,7 +318,7 @@

try (Session session = getSessionFactory().openSession()) {
Transaction transaction = session.beginTransaction();
session.update(type, data);
session.merge(type, data);
transaction.commit();
}
}
Copilot is powered by AI and may make mistakes. Always verify output.

String precisionValue = extractValue.apply(argText, "precision");
if (precisionValue != null)
columnDetails.setPrecision(Integer.valueOf(precisionValue));

Check notice

Code scanning / CodeQL

Missing catch of NumberFormatException

Potential uncaught 'java.lang.NumberFormatException'.

Copilot Autofix

AI 14 days ago

In general, to fix this kind of problem, any conversion from a string to an integer (such as Integer.parseInt or Integer.valueOf) that operates on data derived from external or free-form input should be surrounded by a try/catch (NumberFormatException e) block, or otherwise validated before parsing. This allows the code to handle malformed values gracefully instead of throwing an uncaught runtime exception.

For this specific case in EntityParser.java, the best fix without changing existing functionality is to mirror the existing handling used for length. That is:

  • Wrap columnDetails.setPrecision(Integer.valueOf(precisionValue)); in a try/catch (NumberFormatException e) block.
  • On failure, log or print a warning (consistent with the length handling), and skip setting the precision.
  • Do the same for scaleValue and columnDetails.setScale(Integer.valueOf(scaleValue));, since it has the same risk and comes from the same source.

This can be implemented entirely within the shown method body; no new imports are strictly necessary if we keep using System.err.println as with the existing length parsing. Concretely, within components/data/data-store/src/main/java/org/eclipse/dirigible/components/data/store/parser/EntityParser.java, around lines 453–459, replace the direct calls to Integer.valueOf(...) with try/catch blocks that log a warning and avoid throwing.

Suggested changeset 1
components/data/data-store/src/main/java/org/eclipse/dirigible/components/data/store/parser/EntityParser.java

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/components/data/data-store/src/main/java/org/eclipse/dirigible/components/data/store/parser/EntityParser.java b/components/data/data-store/src/main/java/org/eclipse/dirigible/components/data/store/parser/EntityParser.java
--- a/components/data/data-store/src/main/java/org/eclipse/dirigible/components/data/store/parser/EntityParser.java
+++ b/components/data/data-store/src/main/java/org/eclipse/dirigible/components/data/store/parser/EntityParser.java
@@ -451,12 +451,22 @@
                         columnDetails.setDefaultValue(defaultValue);
 
                     String precisionValue = extractValue.apply(argText, "precision");
-                    if (precisionValue != null)
-                        columnDetails.setPrecision(Integer.valueOf(precisionValue));
+                    if (precisionValue != null) {
+                        try {
+                            columnDetails.setPrecision(Integer.valueOf(precisionValue));
+                        } catch (NumberFormatException e) {
+                            System.err.println("Warning: Could not parse precision value: " + precisionValue);
+                        }
+                    }
 
                     String scaleValue = extractValue.apply(argText, "scale");
-                    if (scaleValue != null)
-                        columnDetails.setScale(Integer.valueOf(scaleValue));
+                    if (scaleValue != null) {
+                        try {
+                            columnDetails.setScale(Integer.valueOf(scaleValue));
+                        } catch (NumberFormatException e) {
+                            System.err.println("Warning: Could not parse scale value: " + scaleValue);
+                        }
+                    }
                 }
             } else if ("OneToMany".equals(decoratorName)) {
                 // Expects @OneToMany(() => OrderItem, { table: '...', joinColumn: '...', ... })
EOF
@@ -451,12 +451,22 @@
columnDetails.setDefaultValue(defaultValue);

String precisionValue = extractValue.apply(argText, "precision");
if (precisionValue != null)
columnDetails.setPrecision(Integer.valueOf(precisionValue));
if (precisionValue != null) {
try {
columnDetails.setPrecision(Integer.valueOf(precisionValue));
} catch (NumberFormatException e) {
System.err.println("Warning: Could not parse precision value: " + precisionValue);
}
}

String scaleValue = extractValue.apply(argText, "scale");
if (scaleValue != null)
columnDetails.setScale(Integer.valueOf(scaleValue));
if (scaleValue != null) {
try {
columnDetails.setScale(Integer.valueOf(scaleValue));
} catch (NumberFormatException e) {
System.err.println("Warning: Could not parse scale value: " + scaleValue);
}
}
}
} else if ("OneToMany".equals(decoratorName)) {
// Expects @OneToMany(() => OrderItem, { table: '...', joinColumn: '...', ... })
Copilot is powered by AI and may make mistakes. Always verify output.

String scaleValue = extractValue.apply(argText, "scale");
if (scaleValue != null)
columnDetails.setScale(Integer.valueOf(scaleValue));

Check notice

Code scanning / CodeQL

Missing catch of NumberFormatException

Potential uncaught 'java.lang.NumberFormatException'.

Copilot Autofix

AI 14 days ago

To fix the problem, the calls that convert precisionValue and scaleValue from String to Integer should handle potential NumberFormatException in the same manner as the existing length conversion: wrap the conversion in a try/catch and handle invalid values gracefully (for example by logging a warning and skipping the assignment). This preserves current functionality for valid input while safely ignoring malformed numeric metadata instead of failing the entire parse.

Concretely, in EntityParser.java around lines 453–459, modify the blocks:

  • For precisionValue, change:

    if (precisionValue != null)
        columnDetails.setPrecision(Integer.valueOf(precisionValue));

    to:

    if (precisionValue != null && !precisionValue.isEmpty()) {
        try {
            columnDetails.setPrecision(Integer.parseInt(precisionValue));
        } catch (NumberFormatException e) {
            System.err.println("Warning: Could not parse precision value: " + precisionValue);
        }
    }
  • For scaleValue, change:

    if (scaleValue != null)
        columnDetails.setScale(Integer.valueOf(scaleValue));

    to:

    if (scaleValue != null && !scaleValue.isEmpty()) {
        try {
            columnDetails.setScale(Integer.parseInt(scaleValue));
        } catch (NumberFormatException e) {
            System.err.println("Warning: Could not parse scale value: " + scaleValue);
        }
    }

This mirrors the existing pattern used for length, introduces no new dependencies, and keeps behavior for valid numbers unchanged. No additional imports or methods are required.

Suggested changeset 1
components/data/data-store/src/main/java/org/eclipse/dirigible/components/data/store/parser/EntityParser.java

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/components/data/data-store/src/main/java/org/eclipse/dirigible/components/data/store/parser/EntityParser.java b/components/data/data-store/src/main/java/org/eclipse/dirigible/components/data/store/parser/EntityParser.java
--- a/components/data/data-store/src/main/java/org/eclipse/dirigible/components/data/store/parser/EntityParser.java
+++ b/components/data/data-store/src/main/java/org/eclipse/dirigible/components/data/store/parser/EntityParser.java
@@ -451,12 +451,22 @@
                         columnDetails.setDefaultValue(defaultValue);
 
                     String precisionValue = extractValue.apply(argText, "precision");
-                    if (precisionValue != null)
-                        columnDetails.setPrecision(Integer.valueOf(precisionValue));
+                    if (precisionValue != null && !precisionValue.isEmpty()) {
+                        try {
+                            columnDetails.setPrecision(Integer.parseInt(precisionValue));
+                        } catch (NumberFormatException e) {
+                            System.err.println("Warning: Could not parse precision value: " + precisionValue);
+                        }
+                    }
 
                     String scaleValue = extractValue.apply(argText, "scale");
-                    if (scaleValue != null)
-                        columnDetails.setScale(Integer.valueOf(scaleValue));
+                    if (scaleValue != null && !scaleValue.isEmpty()) {
+                        try {
+                            columnDetails.setScale(Integer.parseInt(scaleValue));
+                        } catch (NumberFormatException e) {
+                            System.err.println("Warning: Could not parse scale value: " + scaleValue);
+                        }
+                    }
                 }
             } else if ("OneToMany".equals(decoratorName)) {
                 // Expects @OneToMany(() => OrderItem, { table: '...', joinColumn: '...', ... })
EOF
@@ -451,12 +451,22 @@
columnDetails.setDefaultValue(defaultValue);

String precisionValue = extractValue.apply(argText, "precision");
if (precisionValue != null)
columnDetails.setPrecision(Integer.valueOf(precisionValue));
if (precisionValue != null && !precisionValue.isEmpty()) {
try {
columnDetails.setPrecision(Integer.parseInt(precisionValue));
} catch (NumberFormatException e) {
System.err.println("Warning: Could not parse precision value: " + precisionValue);
}
}

String scaleValue = extractValue.apply(argText, "scale");
if (scaleValue != null)
columnDetails.setScale(Integer.valueOf(scaleValue));
if (scaleValue != null && !scaleValue.isEmpty()) {
try {
columnDetails.setScale(Integer.parseInt(scaleValue));
} catch (NumberFormatException e) {
System.err.println("Warning: Could not parse scale value: " + scaleValue);
}
}
}
} else if ("OneToMany".equals(decoratorName)) {
// Expects @OneToMany(() => OrderItem, { table: '...', joinColumn: '...', ... })
Copilot is powered by AI and may make mistakes. Always verify output.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[EDM] Add New Templates with Decorators

2 participants