This is an automated email from the ASF dual-hosted git repository.

yasith pushed a commit to branch service-layer-improvements
in repository https://gitbox.apache.org/repos/asf/airavata.git

commit 80485503025d8d46a39b710997e276723b58c713
Author: yasithdev <[email protected]>
AuthorDate: Sun Dec 14 02:14:14 2025 -0600

    migrations -  dbcp2 to hikari, guice to spring, quartz to spring quartz, 
shiro to spring security, setup mapstruct to migrate dozer
---
 .../plans/spring_migration_plan_c41f8113.plan.md   | 215 +++++++++++++++++++++
 airavata-api/pom.xml                               |  52 +++--
 .../org/apache/airavata/common/utils/DBUtil.java   |  24 ++-
 .../org/apache/airavata/common/utils/JPAUtils.java |   2 +-
 .../org/apache/airavata/common/utils/JSONUtil.java | 143 ++++++++------
 .../java/org/apache/airavata/config/JpaConfig.java |  23 ++-
 .../task/parsing/models/ParsingTaskInputs.java     |  18 +-
 .../task/parsing/models/ParsingTaskOutputs.java    |  18 +-
 .../metadata/analyzer/DataInterpreterService.java  |   8 +-
 .../rescheduler/ProcessReschedulingService.java    |   8 +-
 .../cluster/ClusterStatusMonitorJobScheduler.java  |  10 +-
 .../ComputationalResourceMonitoringService.java    |   8 +-
 .../realtime/parser/RealtimeJobStatusParser.java   |  10 +-
 .../utils/migration/MappingToolRunner.java         |   2 +-
 .../security/interceptor/SecurityCheck.java        |   3 +-
 .../security/interceptor/SecurityModule.java       |  84 ++++++--
 .../airavata/security/userstore/JDBCUserStore.java | 144 ++++++++++----
 .../airavata/security/userstore/LDAPUserStore.java | 117 ++++++++---
 pom.xml                                            |  11 ++
 19 files changed, 688 insertions(+), 212 deletions(-)

diff --git a/.cursor/plans/spring_migration_plan_c41f8113.plan.md 
b/.cursor/plans/spring_migration_plan_c41f8113.plan.md
new file mode 100644
index 0000000000..9aa6f6d679
--- /dev/null
+++ b/.cursor/plans/spring_migration_plan_c41f8113.plan.md
@@ -0,0 +1,215 @@
+---
+name: Spring Migration Plan
+overview: "Migrate non-Spring dependencies to Spring equivalents: Guice → 
Spring DI, Dozer → MapStruct, Commons DBCP2 → HikariCP, Quartz → Spring 
Scheduling, Apache Shiro → Spring Security, and Gson → Jackson."
+todos: []
+---
+
+# Spring Dependency Migration Plan
+
+## Overview
+
+Migrate dependencies in `airavata-api` to Spring equivalents to align with 
Spring Boot architecture and reduce external dependencies.
+
+## Dependencies to Migrate
+
+### 1. Google Guice → Spring Dependency Injection
+
+**Current Usage:**
+
+- `SecurityModule.java` - Uses Guice `AbstractModule` for AOP interceptor 
binding
+- `@SecurityCheck` annotation - Uses Guice `@BindingAnnotation`
+- Security interceptor registration via Guice
+
+**Migration Strategy:**
+
+- Replace `SecurityModule` with Spring `@Configuration` class
+- Convert `@SecurityCheck` to Spring AOP annotation (e.g., custom 
`@SecurityCheck` with Spring AOP)
+- Use Spring AOP `@Aspect` and `@Around` instead of Guice interceptors
+- Update `SecurityInterceptor` to use Spring `MethodInterceptor` (already uses 
it, but needs Spring AOP setup)
+
+**Files to Modify:**
+
+- 
`airavata-api/src/main/java/org/apache/airavata/security/interceptor/SecurityModule.java`
 - Replace with Spring config
+- 
`airavata-api/src/main/java/org/apache/airavata/security/interceptor/SecurityCheck.java`
 - Update annotation
+- 
`airavata-api/src/main/java/org/apache/airavata/security/interceptor/SecurityInterceptor.java`
 - Already Spring-compatible
+- Remove Guice dependency from `pom.xml`
+
+---
+
+### 2. Dozer → MapStruct (Recommended) or ModelMapper
+
+**Current Usage:**
+
+- 69+ service classes use `com.github.dozermapper.core.Mapper`
+- `DozerMapperConfig.java` - Spring bean configuration
+- `dozer_mapping.xml` - XML mapping configuration
+- Custom converters: `StorageDateConverter`, `CsvStringConverter`
+- Custom bean factory: `CustomBeanFactory`
+
+**Migration Strategy:**
+
+- **Option A (Recommended): MapStruct** - Compile-time mapping, type-safe, 
better performance
+- Add `mapstruct` and `mapstruct-processor` dependencies
+- Create mapper interfaces with `@Mapper` annotation
+- MapStruct generates implementation at compile time
+- Replace all `mapper.map()` calls with generated mapper methods
+- Migrate custom converters to MapStruct `@AfterMapping` or custom methods
+
+- **Option B: ModelMapper** - Runtime mapping, easier migration
+- Replace Dozer with ModelMapper
+- Similar API, less refactoring needed
+- Lower performance than MapStruct
+
+**Files to Modify:**
+
+- All 69+ service classes using Dozer mapper
+- 
`airavata-api/src/main/java/org/apache/airavata/config/DozerMapperConfig.java` 
- Replace with MapStruct/ModelMapper config
+- `airavata-api/src/main/resources/dozer_mapping.xml` - Convert to MapStruct 
mappers or ModelMapper configuration
+- 
`airavata-api/src/main/java/org/apache/airavata/registry/utils/DozerConverter/*.java`
 - Convert to MapStruct custom methods
+- 
`airavata-api/src/main/java/org/apache/airavata/registry/utils/CustomBeanFactory.java`
 - May not be needed with MapStruct
+- Remove Dozer dependency from `pom.xml`
+
+---
+
+### 3. Commons DBCP2 → HikariCP (Spring Boot Default)
+
+**Current Usage:**
+
+- `JpaConfig.java` - Creates `BasicDataSource` from Commons DBCP2
+- `JPAUtils.java` - Uses DBCP2 driver name
+- `DBUtil.java` - Uses DBCP2
+- `MappingToolRunner.java` - Uses DBCP2
+
+**Migration Strategy:**
+
+- Replace `BasicDataSource` with HikariCP `HikariDataSource`
+- HikariCP is already included in Spring Boot starter
+- Update connection pool configuration
+- HikariCP has better performance and is Spring Boot default
+
+**Files to Modify:**
+
+- `airavata-api/src/main/java/org/apache/airavata/config/JpaConfig.java` - 
Replace `BasicDataSource` with `HikariDataSource`
+- `airavata-api/src/main/java/org/apache/airavata/common/utils/JPAUtils.java` 
- Update driver name
+- `airavata-api/src/main/java/org/apache/airavata/common/utils/DBUtil.java` - 
Update to HikariCP
+- 
`airavata-api/src/main/java/org/apache/airavata/registry/utils/migration/MappingToolRunner.java`
 - Update driver name
+- Remove `commons-dbcp2` and `commons-pool2` dependencies from `pom.xml`
+
+---
+
+### 4. Quartz → Spring Scheduling
+
+**Current Usage:**
+
+- `ComputationalResourceMonitoringService.java` - Uses Quartz for compute 
resource monitoring
+- `ClusterStatusMonitorJobScheduler.java` - Cluster status monitoring
+- `ProcessReschedulingService.java` - Process scanning jobs
+- `DataInterpreterService.java` - Data analysis jobs
+- Multiple job classes: `MonitoringJob`, `ClusterStatusMonitorJob`, 
`ProcessScannerImpl`, `DataAnalyzerImpl`
+
+**Migration Strategy:**
+
+- **Option A: Spring @Scheduled** - For simple periodic tasks
+- Use `@Scheduled` annotation on methods
+- Enable with `@EnableScheduling`
+- Convert job classes to Spring `@Component` with scheduled methods
+
+- **Option B: Spring Quartz Integration** - For complex scheduling needs
+- Use `spring-boot-starter-quartz`
+- Keep Quartz but integrate with Spring
+- Use Spring-managed job beans
+- Better for dynamic job scheduling
+
+**Recommendation:** Use Spring Quartz integration (Option B) since jobs are 
complex and need dynamic scheduling.
+
+**Files to Modify:**
+
+- 
`airavata-api/src/main/java/org/apache/airavata/monitor/compute/ComputationalResourceMonitoringService.java`
+- 
`airavata-api/src/main/java/org/apache/airavata/monitor/cluster/ClusterStatusMonitorJobScheduler.java`
+- 
`airavata-api/src/main/java/org/apache/airavata/metascheduler/process/scheduling/engine/rescheduler/ProcessReschedulingService.java`
+- 
`airavata-api/src/main/java/org/apache/airavata/metascheduler/metadata/analyzer/DataInterpreterService.java`
+- All job classes implementing `org.quartz.Job`
+- Add `spring-boot-starter-quartz` dependency
+- Keep `quartz` dependency but use Spring-managed version
+
+---
+
+### 5. Apache Shiro → Spring Security
+
+**Current Usage:**
+
+- `LDAPUserStore.java` - Uses Shiro `JndiLdapRealm` for LDAP authentication
+- `JDBCUserStore.java` - Uses Shiro `JdbcRealm` for JDBC authentication
+- Limited usage (only 2 classes)
+
+**Migration Strategy:**
+
+- Replace Shiro realms with Spring Security authentication providers
+- Use Spring Security LDAP support (`spring-boot-starter-security` + 
`spring-ldap-core`)
+- Use Spring Security JDBC authentication
+- Create custom `AuthenticationProvider` implementations
+
+**Files to Modify:**
+
+- 
`airavata-api/src/main/java/org/apache/airavata/security/userstore/LDAPUserStore.java`
 - Replace with Spring Security LDAP
+- 
`airavata-api/src/main/java/org/apache/airavata/security/userstore/JDBCUserStore.java`
 - Replace with Spring Security JDBC
+- Add Spring Security dependencies
+- Remove `shiro-core` dependency from `pom.xml`
+
+**Note:** This is a lower priority migration since Shiro usage is minimal and 
isolated.
+
+---
+
+### 6. Gson → Jackson (Already Available)
+
+**Current Usage:**
+
+- Gson dependency exists but usage is minimal (only in `pom.xml`, no actual 
usage found)
+
+**Migration Strategy:**
+
+- Remove Gson dependency
+- Use Jackson (already included via Spring Boot) for any JSON processing
+- Search for any Gson usage and replace with Jackson `ObjectMapper`
+
+**Files to Modify:**
+
+- Remove `gson` dependency from `pom.xml`
+- Search and replace any Gson usage with Jackson
+
+---
+
+## Migration Order (Recommended)
+
+1. **Gson → Jackson** (Simplest, no code changes if unused)
+2. **Commons DBCP2 → HikariCP** (Straightforward replacement)
+3. **Google Guice → Spring DI** (Medium complexity, affects security)
+4. **Quartz → Spring Quartz Integration** (Medium complexity, many files)
+5. **Dozer → MapStruct** (Most complex, 69+ files, but high value)
+6. **Apache Shiro → Spring Security** (Low priority, minimal usage)
+
+## Testing Strategy
+
+- Unit tests for each migrated component
+- Integration tests for security interceptor
+- Performance tests for mapper migration (MapStruct should be faster)
+- Verify all scheduled jobs still work
+- Test database connection pooling
+
+## Dependencies to Remove
+
+After migration, remove from `pom.xml`:
+
+- `com.google.inject:guice`
+- `com.github.dozermapper:dozer-core`
+- `org.apache.commons:commons-dbcp2`
+- `org.apache.commons:commons-pool2`
+- `com.google.code.gson:gson`
+- `org.apache.shiro:shiro-core` (after Shiro migration)
+
+## Dependencies to Add
+
+- `org.mapstruct:mapstruct` and `mapstruct-processor` (for Dozer replacement)
+- `org.springframework.boot:spring-boot-starter-quartz` (for Quartz 
integration)
+- `org.springframework.boot:spring-boot-starter-security` (for Shiro 
replacement)
+- `org.springframework.ldap:spring-ldap-core` (for LDAP support)
\ No newline at end of file
diff --git a/airavata-api/pom.xml b/airavata-api/pom.xml
index 3041d2e948..f259ae73c2 100644
--- a/airavata-api/pom.xml
+++ b/airavata-api/pom.xml
@@ -52,10 +52,7 @@ under the License.
       <groupId>org.apache.httpcomponents.core5</groupId>
       <artifactId>httpcore5</artifactId>
     </dependency>
-    <dependency>
-      <groupId>com.google.inject</groupId>
-      <artifactId>guice</artifactId>
-    </dependency>
+    <!-- Guice removed - using Spring DI and AOP -->
     <dependency>
       <groupId>com.fasterxml.jackson.core</groupId>
       <artifactId>jackson-databind</artifactId>
@@ -78,14 +75,7 @@ under the License.
     </dependency>
 
     <!-- Database & pooling -->
-    <dependency>
-      <groupId>org.apache.commons</groupId>
-      <artifactId>commons-dbcp2</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.commons</groupId>
-      <artifactId>commons-pool2</artifactId>
-    </dependency>
+    <!-- DBCP2 removed - using HikariCP (included in Spring Boot) -->
     <dependency>
       <groupId>org.apache.derby</groupId>
       <artifactId>derby</artifactId>
@@ -116,6 +106,7 @@ under the License.
       <groupId>commons-cli</groupId>
       <artifactId>commons-cli</artifactId>
     </dependency>
+    <!-- Dozer - being migrated to MapStruct -->
     <dependency>
       <groupId>com.github.dozermapper</groupId>
       <artifactId>dozer-core</artifactId>
@@ -126,6 +117,18 @@ under the License.
         </exclusion>
       </exclusions>
     </dependency>
+    <!-- MapStruct for object mapping (replacing Dozer) -->
+    <dependency>
+      <groupId>org.mapstruct</groupId>
+      <artifactId>mapstruct</artifactId>
+      <version>1.5.5.Final</version>
+    </dependency>
+    <dependency>
+      <groupId>org.mapstruct</groupId>
+      <artifactId>mapstruct-processor</artifactId>
+      <version>1.5.5.Final</version>
+      <scope>provided</scope>
+    </dependency>
     <dependency>
       <groupId>org.apache.openjpa</groupId>
       <artifactId>openjpa</artifactId>
@@ -136,10 +139,7 @@ under the License.
     </dependency>
 
     <!-- JSON, Kafka, XML -->
-    <dependency>
-      <groupId>com.google.code.gson</groupId>
-      <artifactId>gson</artifactId>
-    </dependency>
+    <!-- Gson removed - using Jackson (included in Spring Boot) -->
     <dependency>
       <groupId>org.apache.kafka</groupId>
       <artifactId>kafka-clients</artifactId>
@@ -197,9 +197,20 @@ under the License.
       <artifactId>amqp-client</artifactId>
     </dependency>
 
+    <!-- Shiro removed - using Spring Security -->
+    <!-- Spring Security for authentication -->
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-security</artifactId>
+    </dependency>
+    <!-- Spring LDAP for LDAP authentication -->
     <dependency>
-      <groupId>org.apache.shiro</groupId>
-      <artifactId>shiro-core</artifactId>
+      <groupId>org.springframework.ldap</groupId>
+      <artifactId>spring-ldap-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework.security</groupId>
+      <artifactId>spring-security-ldap</artifactId>
     </dependency>
 
     <dependency>
@@ -224,9 +235,10 @@ under the License.
       <artifactId>api-all</artifactId>
     </dependency>
 
+    <!-- Quartz - using Spring-managed version -->
     <dependency>
-      <groupId>org.quartz-scheduler</groupId>
-      <artifactId>quartz</artifactId>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-quartz</artifactId>
     </dependency>
     <dependency>
       <groupId>com.hierynomus</groupId>
diff --git 
a/airavata-api/src/main/java/org/apache/airavata/common/utils/DBUtil.java 
b/airavata-api/src/main/java/org/apache/airavata/common/utils/DBUtil.java
index 9732d2e83a..66eaa13773 100644
--- a/airavata-api/src/main/java/org/apache/airavata/common/utils/DBUtil.java
+++ b/airavata-api/src/main/java/org/apache/airavata/common/utils/DBUtil.java
@@ -19,6 +19,8 @@
 */
 package org.apache.airavata.common.utils;
 
+import com.zaxxer.hikari.HikariConfig;
+import com.zaxxer.hikari.HikariDataSource;
 import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.PreparedStatement;
@@ -28,7 +30,6 @@ import java.util.Properties;
 import javax.sql.DataSource;
 import org.apache.airavata.common.exception.ApplicationSettingsException;
 import org.apache.airavata.config.AiravataServerProperties;
-import org.apache.commons.dbcp2.BasicDataSource;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -216,18 +217,23 @@ public class DBUtil {
     }
 
     /**
-     * Gets a new DBCP data source.
+     * Gets a new HikariCP data source.
      *
      * @return A new data source.
      */
     public DataSource getDataSource() {
-        BasicDataSource ds = new BasicDataSource();
-        ds.setDriverClassName(this.driverName);
-        ds.setUsername(this.databaseUserName);
-        ds.setPassword(this.databasePassword);
-        ds.setUrl(this.jdbcUrl);
-
-        return ds;
+        HikariConfig config = new HikariConfig();
+        config.setDriverClassName(this.driverName);
+        config.setUsername(this.databaseUserName);
+        config.setPassword(this.databasePassword);
+        config.setJdbcUrl(this.jdbcUrl);
+        config.setMinimumIdle(2);
+        config.setMaximumPoolSize(10);
+        config.setConnectionTimeout(30000);
+        config.setIdleTimeout(600000);
+        config.setMaxLifetime(1800000);
+
+        return new HikariDataSource(config);
     }
 
     /**
diff --git 
a/airavata-api/src/main/java/org/apache/airavata/common/utils/JPAUtils.java 
b/airavata-api/src/main/java/org/apache/airavata/common/utils/JPAUtils.java
index d4fde12179..9bd35f4847 100644
--- a/airavata-api/src/main/java/org/apache/airavata/common/utils/JPAUtils.java
+++ b/airavata-api/src/main/java/org/apache/airavata/common/utils/JPAUtils.java
@@ -37,7 +37,7 @@ public class JPAUtils {
 
     static {
         Map<String, String> properties = new HashMap<String, String>();
-        properties.put("openjpa.ConnectionDriverName", 
"org.apache.commons.dbcp2.BasicDataSource");
+        properties.put("openjpa.ConnectionDriverName", 
"com.zaxxer.hikari.HikariDataSource");
         // Allow unenhanced classes at runtime - this is needed for Spring 
Data JPA integration
         // where metamodel is accessed before EntityManagerFactory is fully 
initialized
         // "supported" allows unenhanced classes but may have performance 
implications
diff --git 
a/airavata-api/src/main/java/org/apache/airavata/common/utils/JSONUtil.java 
b/airavata-api/src/main/java/org/apache/airavata/common/utils/JSONUtil.java
index 7ae435d81d..1223a0b726 100644
--- a/airavata-api/src/main/java/org/apache/airavata/common/utils/JSONUtil.java
+++ b/airavata-api/src/main/java/org/apache/airavata/common/utils/JSONUtil.java
@@ -19,71 +19,95 @@
 */
 package org.apache.airavata.common.utils;
 
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
-import com.google.gson.JsonPrimitive;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
 import java.io.File;
 import java.io.FileReader;
 import java.io.IOException;
 import java.io.Reader;
-import java.util.Map;
-import java.util.Set;
+import java.util.Iterator;
 
 public class JSONUtil {
+    private static final ObjectMapper objectMapper = new ObjectMapper();
 
-    public static void saveJSON(JsonElement jsonElement, File file) throws 
IOException {
-        IOUtil.writeToFile(jsonElementToString(jsonElement), file);
+    public static void saveJSON(JsonNode jsonNode, File file) throws 
IOException {
+        IOUtil.writeToFile(jsonNodeToString(jsonNode), file);
     }
 
-    public static JsonObject stringToJSONObject(String workflowString) {
-        return JsonParser.parseString(workflowString).getAsJsonObject();
+    public static ObjectNode stringToJSONObject(String workflowString) {
+        try {
+            JsonNode node = objectMapper.readTree(workflowString);
+            if (node.isObject()) {
+                return (ObjectNode) node;
+            }
+            throw new IllegalArgumentException("String does not represent a 
JSON object");
+        } catch (JsonProcessingException e) {
+            throw new RuntimeException("Failed to parse JSON string", e);
+        }
     }
 
-    public static JsonObject loadJSON(File file) throws IOException {
+    public static ObjectNode loadJSON(File file) throws IOException {
         return loadJSON(new FileReader(file));
     }
 
-    public static JsonObject loadJSON(Reader reader) throws IOException {
-        return JsonParser.parseReader(reader).getAsJsonObject();
+    public static ObjectNode loadJSON(Reader reader) throws IOException {
+        try {
+            JsonNode node = objectMapper.readTree(reader);
+            if (node.isObject()) {
+                return (ObjectNode) node;
+            }
+            throw new IllegalArgumentException("File does not contain a JSON 
object");
+        } catch (JsonProcessingException e) {
+            throw new IOException("Failed to parse JSON from reader", e);
+        }
     }
 
-    public static String jsonElementToString(JsonElement jsonElement) {
-        Gson gson = new GsonBuilder().setPrettyPrinting().create();
-        return gson.toJson(jsonElement);
+    public static String jsonNodeToString(JsonNode jsonNode) {
+        try {
+            return 
objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonNode);
+        } catch (JsonProcessingException e) {
+            throw new RuntimeException("Failed to convert JsonNode to string", 
e);
+        }
     }
 
-    public static boolean isEqual(JsonObject originalJsonObject, JsonObject 
newJsonObject) {
+    public static boolean isEqual(ObjectNode originalJsonObject, ObjectNode 
newJsonObject) {
         // TODO - Implement this method
         if (originalJsonObject == null && newJsonObject == null) {
             return true;
         } else if (originalJsonObject == null || newJsonObject == null) {
             return false;
         } else {
-            // check the number of childs
-            Set<Map.Entry<String, JsonElement>> entrySetOfOriginalJson = 
originalJsonObject.entrySet();
-            Set<Map.Entry<String, JsonElement>> entrySetOfNewJson = 
newJsonObject.entrySet();
-            if (entrySetOfOriginalJson.size() != entrySetOfNewJson.size()) {
+            // check the number of children
+            if (originalJsonObject.size() != newJsonObject.size()) {
                 return false;
             }
 
-            for (Map.Entry<String, JsonElement> keyString : 
entrySetOfOriginalJson) {
-                JsonElement valueOrig = keyString.getValue();
-                JsonElement valueNew = newJsonObject.get(keyString.getKey());
-                if (valueOrig instanceof JsonObject
-                        && valueNew instanceof JsonObject
-                        && !isEqual((JsonObject) valueOrig, (JsonObject) 
valueNew)) {
+            Iterator<String> fieldNames = originalJsonObject.fieldNames();
+            while (fieldNames.hasNext()) {
+                String key = fieldNames.next();
+                JsonNode valueOrig = originalJsonObject.get(key);
+                JsonNode valueNew = newJsonObject.get(key);
+                
+                if (valueNew == null) {
                     return false;
-                } else if (valueOrig instanceof JsonArray
-                        && valueNew instanceof JsonArray
-                        && !isEqual((JsonArray) valueOrig, (JsonArray) 
valueNew)) {
-                    return false;
-                } else if (valueOrig instanceof JsonPrimitive
-                        && valueNew instanceof JsonPrimitive
-                        && !isEqual((JsonPrimitive) valueOrig, (JsonPrimitive) 
valueNew)) {
+                }
+                
+                if (valueOrig.isObject() && valueNew.isObject()) {
+                    if (!isEqual((ObjectNode) valueOrig, (ObjectNode) 
valueNew)) {
+                        return false;
+                    }
+                } else if (valueOrig.isArray() && valueNew.isArray()) {
+                    if (!isEqual((ArrayNode) valueOrig, (ArrayNode) valueNew)) 
{
+                        return false;
+                    }
+                } else if (valueOrig.isValueNode() && valueNew.isValueNode()) {
+                    if (!isEqual(valueOrig, valueNew)) {
+                        return false;
+                    }
+                } else {
                     return false;
                 }
             }
@@ -91,29 +115,31 @@ public class JSONUtil {
         return true;
     }
 
-    private static boolean isEqual(JsonArray arrayOriginal, JsonArray 
arrayNew) {
+    private static boolean isEqual(ArrayNode arrayOriginal, ArrayNode 
arrayNew) {
         if (arrayOriginal == null && arrayNew == null) {
             return true;
         } else if (arrayOriginal == null || arrayNew == null) {
             return false;
         } else {
-            // check the number of element
+            // check the number of elements
             if (arrayOriginal.size() != arrayNew.size()) {
                 return false;
             } else if (arrayOriginal.size() == 0) {
                 return true;
             } else {
                 for (int i = 0; i < arrayOriginal.size(); i++) {
-                    JsonElement valueOrig = arrayOriginal.get(i);
-                    JsonElement valueNew = arrayNew.get(i);
-                    if (valueOrig instanceof JsonObject && valueNew instanceof 
JsonObject) {
-                        if (!isEqual((JsonObject) valueOrig, (JsonObject) 
valueNew)) {
+                    JsonNode valueOrig = arrayOriginal.get(i);
+                    JsonNode valueNew = arrayNew.get(i);
+                    if (valueOrig.isObject() && valueNew.isObject()) {
+                        if (!isEqual((ObjectNode) valueOrig, (ObjectNode) 
valueNew)) {
                             return false;
                         }
-                    } else if (valueOrig instanceof JsonPrimitive && valueNew 
instanceof JsonPrimitive) {
-                        if (!isEqual((JsonPrimitive) valueOrig, 
(JsonPrimitive) valueNew)) {
+                    } else if (valueOrig.isValueNode() && 
valueNew.isValueNode()) {
+                        if (!isEqual(valueOrig, valueNew)) {
                             return false;
                         }
+                    } else {
+                        return false;
                     }
                 }
             }
@@ -121,28 +147,21 @@ public class JSONUtil {
         return true;
     }
 
-    private static boolean isEqual(JsonPrimitive primitiveOrig, JsonPrimitive 
primitiveNew) {
-        if (primitiveOrig == null && primitiveNew == null) {
+    private static boolean isEqual(JsonNode nodeOrig, JsonNode nodeNew) {
+        if (nodeOrig == null && nodeNew == null) {
             return true;
-        } else if (primitiveOrig == null || primitiveNew == null) {
+        } else if (nodeOrig == null || nodeNew == null) {
             return false;
         } else {
-            if (primitiveOrig.isString() && primitiveNew.isString()) {
-                if 
(!primitiveOrig.getAsString().equals(primitiveNew.getAsString())) {
-                    return false;
-                }
-            } else if (primitiveOrig.isBoolean() && primitiveNew.isBoolean()) {
-                if 
((Boolean.valueOf(primitiveOrig.getAsBoolean()).compareTo(primitiveNew.getAsBoolean())
 != 0)) {
-                    return false;
-                }
-            } else if (primitiveOrig.isNumber() && primitiveNew.isNumber()) {
-                if 
(Double.valueOf(primitiveOrig.getAsDouble()).compareTo(primitiveNew.getAsDouble())
 != 0) {
-                    return false;
-                }
+            if (nodeOrig.isTextual() && nodeNew.isTextual()) {
+                return nodeOrig.asText().equals(nodeNew.asText());
+            } else if (nodeOrig.isBoolean() && nodeNew.isBoolean()) {
+                return nodeOrig.asBoolean() == nodeNew.asBoolean();
+            } else if (nodeOrig.isNumber() && nodeNew.isNumber()) {
+                return nodeOrig.asDouble() == nodeNew.asDouble();
             } else {
-                return primitiveOrig.isJsonNull() && primitiveNew.isJsonNull();
+                return nodeOrig.isNull() && nodeNew.isNull();
             }
         }
-        return true;
     }
 }
diff --git 
a/airavata-api/src/main/java/org/apache/airavata/config/JpaConfig.java 
b/airavata-api/src/main/java/org/apache/airavata/config/JpaConfig.java
index ca07715e90..736c29fcca 100644
--- a/airavata-api/src/main/java/org/apache/airavata/config/JpaConfig.java
+++ b/airavata-api/src/main/java/org/apache/airavata/config/JpaConfig.java
@@ -19,11 +19,12 @@
 */
 package org.apache.airavata.config;
 
+import com.zaxxer.hikari.HikariConfig;
+import com.zaxxer.hikari.HikariDataSource;
 import jakarta.persistence.EntityManager;
 import jakarta.persistence.EntityManagerFactory;
 import javax.sql.DataSource;
 import org.apache.airavata.common.utils.JPAUtils;
-import org.apache.commons.dbcp2.BasicDataSource;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Qualifier;
@@ -97,14 +98,18 @@ public class JpaConfig {
             throw new IllegalStateException(
                     "Database configuration for registry is missing or 
invalid. Check airavata.properties for database.registry.url");
         }
-        BasicDataSource dataSource = new BasicDataSource();
-        dataSource.setDriverClassName(db.driver);
-        dataSource.setUrl(db.url);
-        dataSource.setUsername(db.user);
-        dataSource.setPassword(db.password);
-        dataSource.setValidationQuery(properties.database.validationQuery);
-        dataSource.setTestOnBorrow(true);
-        return dataSource;
+        HikariConfig config = new HikariConfig();
+        config.setDriverClassName(db.driver);
+        config.setJdbcUrl(db.url);
+        config.setUsername(db.user);
+        config.setPassword(db.password);
+        config.setConnectionTestQuery(properties.database.validationQuery);
+        config.setMinimumIdle(2);
+        config.setMaximumPoolSize(10);
+        config.setConnectionTimeout(30000);
+        config.setIdleTimeout(600000);
+        config.setMaxLifetime(1800000);
+        return new HikariDataSource(config);
     }
 
     @Bean(name = "expCatalogEntityManagerFactory")
diff --git 
a/airavata-api/src/main/java/org/apache/airavata/helix/impl/task/parsing/models/ParsingTaskInputs.java
 
b/airavata-api/src/main/java/org/apache/airavata/helix/impl/task/parsing/models/ParsingTaskInputs.java
index f7f9f2bd4c..abae1b2968 100644
--- 
a/airavata-api/src/main/java/org/apache/airavata/helix/impl/task/parsing/models/ParsingTaskInputs.java
+++ 
b/airavata-api/src/main/java/org/apache/airavata/helix/impl/task/parsing/models/ParsingTaskInputs.java
@@ -19,7 +19,7 @@
 */
 package org.apache.airavata.helix.impl.task.parsing.models;
 
-import com.google.gson.Gson;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import java.util.ArrayList;
 import java.util.List;
 import org.apache.airavata.helix.task.api.TaskParamType;
@@ -42,12 +42,22 @@ public class ParsingTaskInputs implements TaskParamType {
 
     @Override
     public String serialize() {
-        return new Gson().toJson(this);
+        try {
+            ObjectMapper objectMapper = new ObjectMapper();
+            return objectMapper.writeValueAsString(this);
+        } catch (Exception e) {
+            throw new RuntimeException("Failed to serialize 
ParsingTaskInputs", e);
+        }
     }
 
     @Override
     public void deserialize(String content) {
-        ParsingTaskInputs parsingTaskInputs = new Gson().fromJson(content, 
ParsingTaskInputs.class);
-        this.inputs = parsingTaskInputs.getInputs();
+        try {
+            ObjectMapper objectMapper = new ObjectMapper();
+            ParsingTaskInputs parsingTaskInputs = 
objectMapper.readValue(content, ParsingTaskInputs.class);
+            this.inputs = parsingTaskInputs.getInputs();
+        } catch (Exception e) {
+            throw new RuntimeException("Failed to deserialize 
ParsingTaskInputs", e);
+        }
     }
 }
diff --git 
a/airavata-api/src/main/java/org/apache/airavata/helix/impl/task/parsing/models/ParsingTaskOutputs.java
 
b/airavata-api/src/main/java/org/apache/airavata/helix/impl/task/parsing/models/ParsingTaskOutputs.java
index c9d14ba6a6..17050d4172 100644
--- 
a/airavata-api/src/main/java/org/apache/airavata/helix/impl/task/parsing/models/ParsingTaskOutputs.java
+++ 
b/airavata-api/src/main/java/org/apache/airavata/helix/impl/task/parsing/models/ParsingTaskOutputs.java
@@ -19,7 +19,7 @@
 */
 package org.apache.airavata.helix.impl.task.parsing.models;
 
-import com.google.gson.Gson;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import java.util.ArrayList;
 import java.util.List;
 import org.apache.airavata.helix.task.api.TaskParamType;
@@ -41,12 +41,22 @@ public class ParsingTaskOutputs implements TaskParamType {
 
     @Override
     public String serialize() {
-        return new Gson().toJson(this);
+        try {
+            ObjectMapper objectMapper = new ObjectMapper();
+            return objectMapper.writeValueAsString(this);
+        } catch (Exception e) {
+            throw new RuntimeException("Failed to serialize 
ParsingTaskOutputs", e);
+        }
     }
 
     @Override
     public void deserialize(String content) {
-        ParsingTaskOutputs parsingTaskOutputs = new Gson().fromJson(content, 
ParsingTaskOutputs.class);
-        this.outputs = parsingTaskOutputs.getOutputs();
+        try {
+            ObjectMapper objectMapper = new ObjectMapper();
+            ParsingTaskOutputs parsingTaskOutputs = 
objectMapper.readValue(content, ParsingTaskOutputs.class);
+            this.outputs = parsingTaskOutputs.getOutputs();
+        } catch (Exception e) {
+            throw new RuntimeException("Failed to deserialize 
ParsingTaskOutputs", e);
+        }
     }
 }
diff --git 
a/airavata-api/src/main/java/org/apache/airavata/metascheduler/metadata/analyzer/DataInterpreterService.java
 
b/airavata-api/src/main/java/org/apache/airavata/metascheduler/metadata/analyzer/DataInterpreterService.java
index ae26f9d71c..c60d89ce1f 100644
--- 
a/airavata-api/src/main/java/org/apache/airavata/metascheduler/metadata/analyzer/DataInterpreterService.java
+++ 
b/airavata-api/src/main/java/org/apache/airavata/metascheduler/metadata/analyzer/DataInterpreterService.java
@@ -30,11 +30,10 @@ import org.quartz.JobBuilder;
 import org.quartz.JobDetail;
 import org.quartz.Scheduler;
 import org.quartz.SchedulerException;
-import org.quartz.SchedulerFactory;
 import org.quartz.SimpleScheduleBuilder;
 import org.quartz.Trigger;
 import org.quartz.TriggerBuilder;
-import org.quartz.impl.StdSchedulerFactory;
+import org.springframework.scheduling.quartz.SchedulerFactoryBean;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Component;
@@ -69,8 +68,9 @@ public class DataInterpreterService implements IServer {
     @Override
     public void start() throws Exception {
         jobTriggerMap.clear();
-        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
-        scheduler = schedulerFactory.getScheduler();
+        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
+        schedulerFactoryBean.afterPropertiesSet();
+        scheduler = schedulerFactoryBean.getScheduler();
 
         final int parallelJobs = 
properties.services.parser.scanningParallelJobs;
         final double scanningInterval = 
properties.services.parser.scanningInterval;
diff --git 
a/airavata-api/src/main/java/org/apache/airavata/metascheduler/process/scheduling/engine/rescheduler/ProcessReschedulingService.java
 
b/airavata-api/src/main/java/org/apache/airavata/metascheduler/process/scheduling/engine/rescheduler/ProcessReschedulingService.java
index 281167636e..6e504795cd 100644
--- 
a/airavata-api/src/main/java/org/apache/airavata/metascheduler/process/scheduling/engine/rescheduler/ProcessReschedulingService.java
+++ 
b/airavata-api/src/main/java/org/apache/airavata/metascheduler/process/scheduling/engine/rescheduler/ProcessReschedulingService.java
@@ -29,11 +29,10 @@ import org.quartz.JobBuilder;
 import org.quartz.JobDetail;
 import org.quartz.Scheduler;
 import org.quartz.SchedulerException;
-import org.quartz.SchedulerFactory;
 import org.quartz.SimpleScheduleBuilder;
 import org.quartz.Trigger;
 import org.quartz.TriggerBuilder;
-import org.quartz.impl.StdSchedulerFactory;
+import org.springframework.scheduling.quartz.SchedulerFactoryBean;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Component;
@@ -72,8 +71,9 @@ public class ProcessReschedulingService implements IServer {
     public void start() throws Exception {
 
         jobTriggerMap.clear();
-        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
-        scheduler = schedulerFactory.getScheduler();
+        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
+        schedulerFactoryBean.afterPropertiesSet();
+        scheduler = schedulerFactoryBean.getScheduler();
 
         final int parallelJobs = 
properties.services.scheduler.clusterScanningParallelJobs;
         final double scanningInterval = 
properties.services.scheduler.jobScanningInterval;
diff --git 
a/airavata-api/src/main/java/org/apache/airavata/monitor/cluster/ClusterStatusMonitorJobScheduler.java
 
b/airavata-api/src/main/java/org/apache/airavata/monitor/cluster/ClusterStatusMonitorJobScheduler.java
index 006d49d98d..4d9e3b810a 100644
--- 
a/airavata-api/src/main/java/org/apache/airavata/monitor/cluster/ClusterStatusMonitorJobScheduler.java
+++ 
b/airavata-api/src/main/java/org/apache/airavata/monitor/cluster/ClusterStatusMonitorJobScheduler.java
@@ -28,7 +28,7 @@ import org.quartz.JobDetail;
 import org.quartz.Scheduler;
 import org.quartz.SchedulerException;
 import org.quartz.Trigger;
-import org.quartz.impl.StdSchedulerFactory;
+import org.springframework.scheduling.quartz.SchedulerFactoryBean;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -38,9 +38,11 @@ public class ClusterStatusMonitorJobScheduler {
     Scheduler scheduler;
     private AiravataServerProperties properties;
 
-    public ClusterStatusMonitorJobScheduler(AiravataServerProperties 
properties) throws SchedulerException {
+    public ClusterStatusMonitorJobScheduler(AiravataServerProperties 
properties) throws Exception {
         this.properties = properties;
-        scheduler = StdSchedulerFactory.getDefaultScheduler();
+        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
+        schedulerFactoryBean.afterPropertiesSet();
+        scheduler = schedulerFactoryBean.getScheduler();
         scheduler.start();
     }
 
@@ -62,7 +64,7 @@ public class ClusterStatusMonitorJobScheduler {
         scheduler.scheduleJob(job, trigger);
     }
 
-    public static void main(String[] args) throws SchedulerException {
+    public static void main(String[] args) throws Exception {
         // Note: Properties should be loaded from Spring context in real usage
         // For main method, this is a placeholder
         ClusterStatusMonitorJobScheduler jobScheduler = new 
ClusterStatusMonitorJobScheduler(null);
diff --git 
a/airavata-api/src/main/java/org/apache/airavata/monitor/compute/ComputationalResourceMonitoringService.java
 
b/airavata-api/src/main/java/org/apache/airavata/monitor/compute/ComputationalResourceMonitoringService.java
index 22793ed50d..d153ae1124 100644
--- 
a/airavata-api/src/main/java/org/apache/airavata/monitor/compute/ComputationalResourceMonitoringService.java
+++ 
b/airavata-api/src/main/java/org/apache/airavata/monitor/compute/ComputationalResourceMonitoringService.java
@@ -30,11 +30,10 @@ import org.quartz.JobBuilder;
 import org.quartz.JobDetail;
 import org.quartz.Scheduler;
 import org.quartz.SchedulerException;
-import org.quartz.SchedulerFactory;
 import org.quartz.SimpleScheduleBuilder;
 import org.quartz.Trigger;
 import org.quartz.TriggerBuilder;
-import org.quartz.impl.StdSchedulerFactory;
+import org.springframework.scheduling.quartz.SchedulerFactoryBean;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -70,8 +69,9 @@ public class ComputationalResourceMonitoringService 
implements IServer {
     public void start() throws Exception {
 
         jobTriggerMap.clear();
-        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
-        scheduler = schedulerFactory.getScheduler();
+        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
+        schedulerFactoryBean.afterPropertiesSet();
+        scheduler = schedulerFactoryBean.getScheduler();
 
         // Note: These properties are not in AiravataServerProperties yet, 
using defaults
         // TODO: Add these to AiravataServerProperties if needed
diff --git 
a/airavata-api/src/main/java/org/apache/airavata/monitor/realtime/parser/RealtimeJobStatusParser.java
 
b/airavata-api/src/main/java/org/apache/airavata/monitor/realtime/parser/RealtimeJobStatusParser.java
index f420f517ad..b32b6002ef 100644
--- 
a/airavata-api/src/main/java/org/apache/airavata/monitor/realtime/parser/RealtimeJobStatusParser.java
+++ 
b/airavata-api/src/main/java/org/apache/airavata/monitor/realtime/parser/RealtimeJobStatusParser.java
@@ -19,8 +19,9 @@
 */
 package org.apache.airavata.monitor.realtime.parser;
 
-import com.google.gson.Gson;
-import com.google.gson.JsonSyntaxException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
@@ -63,7 +64,8 @@ public class RealtimeJobStatusParser {
     public JobStatusResult parse(String rawMessage, String publisherId, 
RegistryService registryService) {
 
         try {
-            Map asMap = new Gson().fromJson(rawMessage, Map.class);
+            ObjectMapper objectMapper = new ObjectMapper();
+            Map<String, Object> asMap = objectMapper.readValue(rawMessage, new 
TypeReference<Map<String, Object>>() {});
             if (asMap.containsKey("jobName") && asMap.containsKey("status")) {
                 String jobName = (String) asMap.get("jobName");
                 String status = (String) asMap.get("status");
@@ -115,7 +117,7 @@ public class RealtimeJobStatusParser {
                 logger.error("Data structure of message {} is not correct", 
rawMessage);
                 return null;
             }
-        } catch (JsonSyntaxException e) {
+        } catch (JsonProcessingException e) {
             logger.error("Failed to parse raw data {} to type Map", 
rawMessage, e);
             return null;
         }
diff --git 
a/airavata-api/src/main/java/org/apache/airavata/registry/utils/migration/MappingToolRunner.java
 
b/airavata-api/src/main/java/org/apache/airavata/registry/utils/migration/MappingToolRunner.java
index bc073feed3..81c9727fd7 100644
--- 
a/airavata-api/src/main/java/org/apache/airavata/registry/utils/migration/MappingToolRunner.java
+++ 
b/airavata-api/src/main/java/org/apache/airavata/registry/utils/migration/MappingToolRunner.java
@@ -48,7 +48,7 @@ public class MappingToolRunner {
                 dbInitConfig.getUser(),
                 dbInitConfig.getPassword(),
                 dbInitConfig.getValidationQuery()));
-        
jdbcConfiguration.setConnectionDriverName("org.apache.commons.dbcp2.BasicDataSource");
+        
jdbcConfiguration.setConnectionDriverName("com.zaxxer.hikari.HikariDataSource");
 
         Options options = new Options();
         options.put("sqlFile", outputFile);
diff --git 
a/airavata-api/src/main/java/org/apache/airavata/security/interceptor/SecurityCheck.java
 
b/airavata-api/src/main/java/org/apache/airavata/security/interceptor/SecurityCheck.java
index b527ea5020..8d7df2b6f0 100644
--- 
a/airavata-api/src/main/java/org/apache/airavata/security/interceptor/SecurityCheck.java
+++ 
b/airavata-api/src/main/java/org/apache/airavata/security/interceptor/SecurityCheck.java
@@ -19,7 +19,6 @@
 */
 package org.apache.airavata.security.interceptor;
 
-import com.google.inject.BindingAnnotation;
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -27,8 +26,8 @@ import java.lang.annotation.Target;
 
 /**
  * This is just the definition of the annotation used to mark the API methods 
to be intercepted.
+ * Methods annotated with this will be intercepted by Spring AOP for security 
checks.
  */
 @Retention(RetentionPolicy.RUNTIME)
 @Target({ElementType.METHOD})
-@BindingAnnotation
 public @interface SecurityCheck {}
diff --git 
a/airavata-api/src/main/java/org/apache/airavata/security/interceptor/SecurityModule.java
 
b/airavata-api/src/main/java/org/apache/airavata/security/interceptor/SecurityModule.java
index cbad2cafc1..2e143b7b39 100644
--- 
a/airavata-api/src/main/java/org/apache/airavata/security/interceptor/SecurityModule.java
+++ 
b/airavata-api/src/main/java/org/apache/airavata/security/interceptor/SecurityModule.java
@@ -11,40 +11,88 @@
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
-* software distributed under the License is distributed on an
-* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* software distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 
OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
 package org.apache.airavata.security.interceptor;
 
-import com.google.inject.AbstractModule;
-import com.google.inject.matcher.Matchers;
-import org.apache.airavata.config.AiravataServerProperties;
-import org.apache.airavata.security.AiravataSecurityManager;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
 
 /**
- * This does the plumbing work of integrating the interceptor with Guice 
framework for the methods to be
- * intercepted upon their invocation.
+ * Spring AOP aspect for security interception.
+ * Replaces the Guice-based SecurityModule with Spring AOP.
+ * Methods annotated with @SecurityCheck will be intercepted by this aspect.
  */
-public class SecurityModule extends AbstractModule {
+@Aspect
+@Component
+public class SecurityModule {
     private static final Logger logger = 
LoggerFactory.getLogger(SecurityModule.class);
 
-    private final AiravataSecurityManager securityManager;
-    private final AiravataServerProperties properties;
+    private final SecurityInterceptor securityInterceptor;
 
-    public SecurityModule(AiravataSecurityManager securityManager, 
AiravataServerProperties properties) {
-        this.securityManager = securityManager;
-        this.properties = properties;
+    public SecurityModule(SecurityInterceptor securityInterceptor) {
+        this.securityInterceptor = securityInterceptor;
+        logger.info("Security AOP aspect initialized");
     }
 
-    public void configure() {
-        logger.info("Security module reached...");
-        SecurityInterceptor interceptor = new 
SecurityInterceptor(securityManager, properties);
+    
@Pointcut("@annotation(org.apache.airavata.security.interceptor.SecurityCheck)")
+    public void securityCheckPointcut() {
+        // Pointcut definition for methods annotated with @SecurityCheck
+    }
+
+    @Around("securityCheckPointcut()")
+    public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable {
+        // Delegate to SecurityInterceptor which implements MethodInterceptor
+        return securityInterceptor.invoke(new 
MethodInvocationAdapter(joinPoint));
+    }
+
+    /**
+     * Adapter to convert ProceedingJoinPoint to MethodInvocation for 
SecurityInterceptor.
+     */
+    private static class MethodInvocationAdapter implements 
org.aopalliance.intercept.MethodInvocation {
+        private final ProceedingJoinPoint joinPoint;
+        private final java.lang.reflect.Method method;
+
+        public MethodInvocationAdapter(ProceedingJoinPoint joinPoint) {
+            this.joinPoint = joinPoint;
+            MethodSignature signature = (MethodSignature) 
joinPoint.getSignature();
+            this.method = signature.getMethod();
+        }
+
+        @Override
+        public Object proceed() throws Throwable {
+            return joinPoint.proceed();
+        }
+
+        @Override
+        public Object getThis() {
+            return joinPoint.getThis();
+        }
+
+        @Override
+        public java.lang.reflect.Method getMethod() {
+            return method;
+        }
+
+        @Override
+        public Object[] getArguments() {
+            return joinPoint.getArgs();
+        }
 
-        bindInterceptor(Matchers.any(), 
Matchers.annotatedWith(SecurityCheck.class), interceptor);
+        @Override
+        public java.lang.reflect.AccessibleObject getStaticPart() {
+            // Return the method as the static part - this is required by the 
interface
+            // but not actually used by SecurityInterceptor
+            return method;
+        }
     }
 }
diff --git 
a/airavata-api/src/main/java/org/apache/airavata/security/userstore/JDBCUserStore.java
 
b/airavata-api/src/main/java/org/apache/airavata/security/userstore/JDBCUserStore.java
index 4ef3e59830..063775e5e4 100644
--- 
a/airavata-api/src/main/java/org/apache/airavata/security/userstore/JDBCUserStore.java
+++ 
b/airavata-api/src/main/java/org/apache/airavata/security/userstore/JDBCUserStore.java
@@ -11,8 +11,7 @@
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
-* software distributed under the License is distributed on an
-* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* software distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 
OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
@@ -24,46 +23,53 @@ import 
org.apache.airavata.common.exception.ApplicationSettingsException;
 import org.apache.airavata.common.utils.DBUtil;
 import org.apache.airavata.security.UserStoreException;
 import org.apache.airavata.security.util.PasswordDigester;
-import org.apache.shiro.authc.AuthenticationException;
-import org.apache.shiro.authc.AuthenticationInfo;
-import org.apache.shiro.authc.AuthenticationToken;
-import org.apache.shiro.authc.UsernamePasswordToken;
-import org.apache.shiro.realm.jdbc.JdbcRealm;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.security.authentication.BadCredentialsException;
+import 
org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import 
org.springframework.security.authentication.dao.DaoAuthenticationProvider;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.crypto.password.PasswordEncoder;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 
 /**
  * The JDBC user store implementation.
+ * Migrated from Apache Shiro to Spring Security JDBC authentication.
  */
 public class JDBCUserStore extends AbstractJDBCUserStore {
 
     protected static Logger log = LoggerFactory.getLogger(JDBCUserStore.class);
 
-    private JdbcRealm jdbcRealm;
-
+    private DaoAuthenticationProvider authenticationProvider;
     private PasswordDigester passwordDigester;
+    private DataSource dataSource;
 
     public JDBCUserStore() {
-        jdbcRealm = new JdbcRealm();
+        // Constructor
     }
 
     @Override
     public boolean authenticate(String userName, Object credentials) throws 
UserStoreException {
-        AuthenticationToken authenticationToken =
-                new UsernamePasswordToken(userName, 
passwordDigester.getPasswordHashValue((String) credentials));
-
-        AuthenticationInfo authenticationInfo;
         try {
-
-            authenticationInfo = 
jdbcRealm.getAuthenticationInfo(authenticationToken);
-            return authenticationInfo != null;
-
-        } catch (AuthenticationException e) {
-            log.debug(e.getLocalizedMessage(), e);
+            String password = passwordDigester.getPasswordHashValue((String) 
credentials);
+            UsernamePasswordAuthenticationToken authRequest = 
+                new UsernamePasswordAuthenticationToken(userName, password);
+            
+            Authentication authentication = 
authenticationProvider.authenticate(authRequest);
+            return authentication != null && authentication.isAuthenticated();
+        } catch (BadCredentialsException e) {
+            log.debug("JDBC authentication failed for user: {}", userName, e);
             return false;
+        } catch (Exception e) {
+            log.error("Error during JDBC authentication", e);
+            throw new UserStoreException("Error during JDBC authentication", 
e);
         }
     }
 
@@ -147,26 +153,96 @@ public class JDBCUserStore extends AbstractJDBCUserStore {
     }
 
     protected void initializeDatabaseLookup(String passwordColumn, String 
userTable, String userNameColumn)
-            throws ApplicationSettingsException {
-        DBUtil dbUtil = new DBUtil(getDatabaseURL(), getDatabaseUserName(), 
getDatabasePassword(), getDatabaseDriver());
-        DataSource dataSource = dbUtil.getDataSource();
-        jdbcRealm.setDataSource(dataSource);
+            throws ApplicationSettingsException, UserStoreException {
+        try {
+            DBUtil dbUtil = new DBUtil(getDatabaseURL(), 
getDatabaseUserName(), getDatabasePassword(), getDatabaseDriver());
+            dataSource = dbUtil.getDataSource();
 
-        StringBuilder stringBuilder = new StringBuilder();
+            // Create user details service
+            UserDetailsService userDetailsService = new JdbcUserDetailsService(
+                dataSource, userTable, userNameColumn, passwordColumn);
 
-        stringBuilder
-                .append("SELECT ")
-                .append(passwordColumn)
-                .append(" FROM ")
-                .append(userTable)
-                .append(" WHERE ")
-                .append(userNameColumn)
-                .append(" = ?");
+            // Create password encoder adapter
+            PasswordEncoder passwordEncoder = new 
PasswordDigesterEncoder(passwordDigester);
 
-        jdbcRealm.setAuthenticationQuery(stringBuilder.toString());
+            // Create authentication provider
+            // Note: Using deprecated API for compatibility - Spring Security 
API has changed
+            authenticationProvider = new DaoAuthenticationProvider();
+            authenticationProvider.setUserDetailsService(userDetailsService);
+            authenticationProvider.setPasswordEncoder(passwordEncoder);
+        } catch (Exception e) {
+            throw new UserStoreException("Failed to initialize JDBC 
authentication", e);
+        }
     }
 
     public PasswordDigester getPasswordDigester() {
         return passwordDigester;
     }
+
+    /**
+     * UserDetailsService implementation for JDBC authentication
+     */
+    private static class JdbcUserDetailsService implements UserDetailsService {
+        private final JdbcTemplate jdbcTemplate;
+        private final String userTable;
+        private final String userNameColumn;
+        private final String passwordColumn;
+
+        public JdbcUserDetailsService(DataSource dataSource, String userTable, 
+                                     String userNameColumn, String 
passwordColumn) {
+            this.jdbcTemplate = new JdbcTemplate(dataSource);
+            this.userTable = userTable;
+            this.userNameColumn = userNameColumn;
+            this.passwordColumn = passwordColumn;
+        }
+
+        @Override
+        public UserDetails loadUserByUsername(String username) throws 
UsernameNotFoundException {
+            String sql = String.format("SELECT %s FROM %s WHERE %s = ?", 
+                passwordColumn, userTable, userNameColumn);
+            
+            try {
+                String password = jdbcTemplate.queryForObject(sql, 
String.class, username);
+                if (password == null) {
+                    throw new UsernameNotFoundException("User not found: " + 
username);
+                }
+                return User.withUsername(username)
+                    .password(password)
+                    .authorities("ROLE_USER")
+                    .build();
+            } catch (org.springframework.dao.EmptyResultDataAccessException e) 
{
+                throw new UsernameNotFoundException("User not found: " + 
username, e);
+            }
+        }
+    }
+
+    /**
+     * Password encoder adapter for PasswordDigester
+     */
+    private static class PasswordDigesterEncoder implements PasswordEncoder {
+        private final PasswordDigester passwordDigester;
+
+        public PasswordDigesterEncoder(PasswordDigester passwordDigester) {
+            this.passwordDigester = passwordDigester;
+        }
+
+        @Override
+        public String encode(CharSequence rawPassword) {
+            try {
+                return 
passwordDigester.getPasswordHashValue(rawPassword.toString());
+            } catch (UserStoreException e) {
+                throw new RuntimeException("Failed to encode password", e);
+            }
+        }
+
+        @Override
+        public boolean matches(CharSequence rawPassword, String 
encodedPassword) {
+            try {
+                String hashed = 
passwordDigester.getPasswordHashValue(rawPassword.toString());
+                return hashed.equals(encodedPassword);
+            } catch (UserStoreException e) {
+                throw new RuntimeException("Failed to match password", e);
+            }
+        }
+    }
 }
diff --git 
a/airavata-api/src/main/java/org/apache/airavata/security/userstore/LDAPUserStore.java
 
b/airavata-api/src/main/java/org/apache/airavata/security/userstore/LDAPUserStore.java
index f285ddbaa0..f948335351 100644
--- 
a/airavata-api/src/main/java/org/apache/airavata/security/userstore/LDAPUserStore.java
+++ 
b/airavata-api/src/main/java/org/apache/airavata/security/userstore/LDAPUserStore.java
@@ -11,8 +11,7 @@
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
-* software distributed under the License is distributed on an
-* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* software distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 
OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
@@ -22,43 +21,48 @@ package org.apache.airavata.security.userstore;
 import org.apache.airavata.security.UserStore;
 import org.apache.airavata.security.UserStoreException;
 import org.apache.airavata.security.util.PasswordDigester;
-import org.apache.shiro.authc.AuthenticationException;
-import org.apache.shiro.authc.AuthenticationInfo;
-import org.apache.shiro.authc.AuthenticationToken;
-import org.apache.shiro.authc.UsernamePasswordToken;
-import org.apache.shiro.realm.ldap.JndiLdapContextFactory;
-import org.apache.shiro.realm.ldap.JndiLdapRealm;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.ldap.core.support.LdapContextSource;
+import org.springframework.security.authentication.BadCredentialsException;
+import 
org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import 
org.springframework.security.ldap.authentication.LdapAuthenticationProvider;
+import 
org.springframework.security.ldap.authentication.PasswordComparisonAuthenticator;
+import org.springframework.security.ldap.search.FilterBasedLdapUserSearch;
+import 
org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 
 /**
  * A user store which talks to LDAP server. User credentials and user 
information are stored in a LDAP server.
+ * Migrated from Apache Shiro to Spring Security LDAP.
  */
 public class LDAPUserStore implements UserStore {
 
-    private JndiLdapRealm ldapRealm;
+    private LdapAuthenticationProvider ldapAuthenticationProvider;
+    private LdapContextSource contextSource;
 
     protected static Logger log = LoggerFactory.getLogger(LDAPUserStore.class);
 
     private PasswordDigester passwordDigester;
 
     public boolean authenticate(String userName, Object credentials) throws 
UserStoreException {
-
-        AuthenticationToken authenticationToken =
-                new UsernamePasswordToken(userName, 
passwordDigester.getPasswordHashValue((String) credentials));
-
-        AuthenticationInfo authenticationInfo;
         try {
-            authenticationInfo = 
ldapRealm.getAuthenticationInfo(authenticationToken);
-        } catch (AuthenticationException e) {
-            log.warn(e.getLocalizedMessage(), e);
+            String password = passwordDigester.getPasswordHashValue((String) 
credentials);
+            UsernamePasswordAuthenticationToken authRequest = 
+                new UsernamePasswordAuthenticationToken(userName, password);
+            
+            Authentication authentication = 
ldapAuthenticationProvider.authenticate(authRequest);
+            return authentication != null && authentication.isAuthenticated();
+        } catch (BadCredentialsException e) {
+            log.warn("LDAP authentication failed for user: {}", userName, e);
             return false;
+        } catch (Exception e) {
+            log.error("Error during LDAP authentication", e);
+            throw new UserStoreException("Error during LDAP authentication", 
e);
         }
-
-        return authenticationInfo != null;
     }
 
     @Override
@@ -123,19 +127,76 @@ public class LDAPUserStore implements UserStore {
     }
 
     protected void initializeLDAP(
-            String ldapUrl, String systemUser, String systemUserPassword, 
String userNameTemplate) {
+            String ldapUrl, String systemUser, String systemUserPassword, 
String userNameTemplate) throws UserStoreException {
+
+        try {
+            // Create LDAP context source
+            contextSource = new LdapContextSource();
+            contextSource.setUrl(ldapUrl);
+            contextSource.setUserDn(systemUser);
+            contextSource.setPassword(systemUserPassword);
+            contextSource.afterPropertiesSet();
+        } catch (Exception e) {
+            throw new UserStoreException("Failed to initialize LDAP context", 
e);
+        }
+
+        // Create user search - convert Shiro template format to Spring LDAP 
format
+        // Shiro: uid={0},ou=system -> Spring: (uid={0}) with base DN ou=system
+        String searchBase = "";
+        String searchFilter = userNameTemplate;
+        if (userNameTemplate.contains(",")) {
+            int commaIndex = userNameTemplate.indexOf(",");
+            searchBase = userNameTemplate.substring(commaIndex + 1);
+            searchFilter = userNameTemplate.substring(0, commaIndex);
+            // Convert format: uid={0} -> (uid={0})
+            if (!searchFilter.startsWith("(")) {
+                searchFilter = "(" + searchFilter + ")";
+            }
+        }
 
-        JndiLdapContextFactory jndiLdapContextFactory = new 
JndiLdapContextFactory();
+        FilterBasedLdapUserSearch userSearch = new FilterBasedLdapUserSearch(
+            searchBase, searchFilter, contextSource);
 
-        jndiLdapContextFactory.setUrl(ldapUrl);
-        jndiLdapContextFactory.setSystemUsername(systemUser);
-        jndiLdapContextFactory.setSystemPassword(systemUserPassword);
+        // Create authenticator
+        PasswordComparisonAuthenticator authenticator = new 
PasswordComparisonAuthenticator(contextSource);
+        authenticator.setUserSearch(userSearch);
+        authenticator.setPasswordEncoder(new 
PasswordDigesterEncoder(passwordDigester));
 
-        ldapRealm = new JndiLdapRealm();
+        // Create authorities populator (empty for now - can be extended)
+        DefaultLdapAuthoritiesPopulator authoritiesPopulator = 
+            new DefaultLdapAuthoritiesPopulator(contextSource, "");
 
-        ldapRealm.setContextFactory(jndiLdapContextFactory);
-        ldapRealm.setUserDnTemplate(userNameTemplate);
+        // Create authentication provider
+        ldapAuthenticationProvider = new 
LdapAuthenticationProvider(authenticator, authoritiesPopulator);
+    }
+
+    /**
+     * Password encoder adapter for PasswordDigester
+     */
+    private static class PasswordDigesterEncoder implements 
org.springframework.security.crypto.password.PasswordEncoder {
+        private final PasswordDigester passwordDigester;
 
-        ldapRealm.init();
+        public PasswordDigesterEncoder(PasswordDigester passwordDigester) {
+            this.passwordDigester = passwordDigester;
+        }
+
+        @Override
+        public String encode(CharSequence rawPassword) {
+            try {
+                return 
passwordDigester.getPasswordHashValue(rawPassword.toString());
+            } catch (UserStoreException e) {
+                throw new RuntimeException("Failed to encode password", e);
+            }
+        }
+
+        @Override
+        public boolean matches(CharSequence rawPassword, String 
encodedPassword) {
+            try {
+                String hashed = 
passwordDigester.getPasswordHashValue(rawPassword.toString());
+                return hashed.equals(encodedPassword);
+            } catch (UserStoreException e) {
+                throw new RuntimeException("Failed to match password", e);
+            }
+        }
     }
 }
diff --git a/pom.xml b/pom.xml
index 1a91ac20c1..64d5aac6c2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -384,6 +384,17 @@ under the License.
                 <artifactId>dozer-core</artifactId>
                 <version>7.0.0</version>
             </dependency>
+            <!-- MapStruct for object mapping (replacing Dozer) -->
+            <dependency>
+                <groupId>org.mapstruct</groupId>
+                <artifactId>mapstruct</artifactId>
+                <version>1.5.5.Final</version>
+            </dependency>
+            <dependency>
+                <groupId>org.mapstruct</groupId>
+                <artifactId>mapstruct-processor</artifactId>
+                <version>1.5.5.Final</version>
+            </dependency>
             <dependency>
                 <groupId>org.json</groupId>
                 <artifactId>json</artifactId>

Reply via email to