You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by ya...@apache.org on 2026/03/28 04:00:34 UTC

(airavata) branch master updated: refactor: unified transport servers — Spring module reorganization (#600)

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

yasith pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata.git


The following commit(s) were added to refs/heads/master by this push:
     new fdffece4ff refactor: unified transport servers — Spring module reorganization (#600)
fdffece4ff is described below

commit fdffece4ff7c95c7b79becb7f3ef66756fcf448f
Author: Yasith Jayawardana <ya...@gatech.edu>
AuthorDate: Fri Mar 27 23:00:28 2026 -0500

    refactor: unified transport servers — Spring module reorganization (#600)
    
    * feat: add @ConditionalOnServer, AiravataServerProperties, unified UserContext
    
    * refactor: migrate airavata-api from OpenJPA to Hibernate
    
    Replace OpenJPA dependency, bytecode enhancement plugin, and
    @ForeignKey annotations with Hibernate equivalents (@OnDelete).
    Delete persistence.xml — no longer needed with Hibernate runtime
    proxies. EntityManagerFactory usage in JPAUtils noted but left for
    the Spring Boot wrapping task.
    
    * refactor: convert research-service from standalone Boot app to plain library
    
    * refactor: convert agent-service from standalone Boot app to plain library
    
    - Remove spring-boot-maven-plugin, maven-assembly-plugin, and actuator dependency
    - Add AgentServiceConfig for component scanning, entity scanning, JPA repos
    - Add AgentProperties (@ConfigurationProperties) replacing @Value annotations
    - Replace local UserContext with unified org.apache.airavata.common.security.UserContext
    - Delete AgentServiceApplication, AuthzTokenFilter, application.yml, assembly descriptor
    
    * refactor: convert file-server to plain library, normalize paths to /api/v1/files/*
    
    * feat: create airavata-rest-server, absorb restproxy, centralize auth + OpenAPI
    
    * feat: create airavata-grpc-server with centralized gRPC auth interceptor
    
    * refactor: wrap airavata-thrift-server in Spring Boot with SmartLifecycle
    
    Replace the custom main() bootstrap in AiravataServer.java with
    Spring-managed components:
    
    - AiravataThriftServerConfig: @ConditionalOnServer("thrift") entry point
    - ThriftProcessorConfig: builds TMultiplexedProcessor as a @Bean
    - ThriftServerLifecycle: SmartLifecycle that manages TThreadPoolServer
    - BackgroundServicesConfig: @PostConstruct DB initialization
    
    All handlers annotated with @Component. OrchestratorServerHandler
    created via @Bean factory with graceful fallback on init failure.
    Background services (Helix, monitoring, etc.) deferred to future task.
    
    * feat: create unified airavata-server launcher with distribution assembly
    
    * refactor: update Tiltfile for unified server startup
    
    Replace 5 separate service definitions (airavata-server, research-service,
    agent-service, file-server, rest-proxy) with a single unified airavata-server
    entry. Update build deps to track new server modules.
    
    * chore: remove stale assembly descriptors from airavata-api
    
    The unified airavata-server module now produces the distribution tarball,
    so the assembly plugin and descriptor files in airavata-api are no longer needed.
---
 Tiltfile                                           |  86 +----
 airavata-api/pom.xml                               |  68 +---
 .../src/main/assembly/api-server-bin-assembly.xml  | 116 ------
 .../src/main/assembly/api-server-src-assembly.xml  |  81 -----
 .../common/config/AiravataServerProperties.java    |  16 +
 .../common/config/ConditionalOnServer.java         |  12 +
 .../airavata/common/config/OnServerCondition.java  |  19 +
 .../airavata/common/security/UserContext.java      |  41 +++
 .../compute/model/AppEnvironmentEntity.java        |   6 +-
 .../compute/model/ApplicationInputEntity.java      |   6 +-
 .../compute/model/ApplicationOutputEntity.java     |   6 +-
 .../model/BatchQueueResourcePolicyEntity.java      |   6 +-
 .../compute/model/ComputeResourcePolicyEntity.java |   6 +-
 .../model/ComputeResourceReservationEntity.java    |   6 +-
 .../model/GroupComputeResourcePrefEntity.java      |   6 +-
 .../model/GroupSSHAccountProvisionerConfig.java    |   6 +-
 .../compute/model/LibraryApendPathEntity.java      |   6 +-
 .../compute/model/LibraryPrependPathEntity.java    |   6 +-
 .../compute/model/ModuleLoadCmdEntity.java         |   6 +-
 .../compute/model/PostjobCommandEntity.java        |   6 +-
 .../compute/model/PrejobCommandEntity.java         |   6 +-
 .../handler/CredentialStoreServerHandler.java      |   2 +
 .../execution/handler/RegistryServerHandler.java   |   2 +
 .../handler/SharingRegistryServerHandler.java      |   2 +
 .../src/main/resources/META-INF/persistence.xml    | 203 -----------
 .../file-server => airavata-grpc-server}/pom.xml   | 101 +++---
 .../grpc/server/AiravataGrpcServerConfig.java      |  27 +-
 .../grpc/server/config/GrpcAuthInterceptor.java    | 104 ++++++
 .../file-server => airavata-rest-server}/pom.xml   | 120 ++++---
 .../rest/server/AiravataRestServerConfig.java      |  22 +-
 .../rest/server}/config/OpenApiConfig.java         |  82 ++---
 .../rest/server/config/SecurityConfig.java         | 132 +++++++
 .../airavata/rest/server}/config/WebMvcConfig.java |  19 +-
 .../server/controller/KafkaProxyController.java    |  35 +-
 {modules/restproxy => airavata-server}/pom.xml     |  78 ++---
 .../src/main/assembly/server-bin-assembly.xml      |  61 ++++
 airavata-server/src/main/bin/airavata.sh           |   8 +
 .../apache/airavata/server/AiravataServerMain.java |  41 +++
 .../src/main/resources/application-grpc.yml        |   4 +
 .../src/main/resources/application-rest.yml        |  14 +
 .../src/main/resources/application-thrift.yml      |   4 +
 airavata-server/src/main/resources/application.yml |  67 ++++
 airavata-thrift-server/pom.xml                     |  10 +
 .../apache/airavata/api/server/AiravataServer.java | 389 ---------------------
 .../api/server/handler/AiravataServerHandler.java  |   5 +
 .../handlers/GroupManagerServiceHandler.java       |   2 +
 .../profile/handlers/IamAdminServicesHandler.java  |   2 +
 .../handlers/TenantProfileServiceHandler.java      |   2 +
 .../handlers/UserProfileServiceHandler.java        |   2 +
 .../thrift/server/AiravataThriftServerConfig.java  |  28 +-
 .../server/config/BackgroundServicesConfig.java    |  69 ++++
 .../server/config/ThriftProcessorConfig.java       | 121 +++++++
 .../server/config/ThriftServerLifecycle.java       | 106 ++++++
 modules/agent-framework/agent-service/pom.xml      |  29 --
 .../main/assembly/agent-service-bin-assembly.xml   |  76 ----
 .../agent/connection/service/UserContext.java      |  53 ---
 .../connection/service/config/AgentProperties.java |  35 ++
 .../service/config/AgentServiceConfig.java         |  13 +
 .../service/config/AuthzTokenFilter.java           |  64 ----
 .../service/controllers/PlanController.java        |   6 +-
 .../service/handlers/AgentConnectionHandler.java   |  26 +-
 .../service/handlers/AgentManagementHandler.java   |  21 +-
 .../service/services/AiravataFileService.java      |   2 +-
 .../service/services/AiravataService.java          |  10 +-
 .../src/main/resources/application.yml             |  64 ----
 modules/file-server/pom.xml                        |  33 --
 .../main/assembly/file-service-bin-assembly.xml    |  75 ----
 .../file/server/FileServerApplication.java         |  35 --
 .../file/server/FileServerConfiguration.java       |   4 +-
 .../file/server/config/FileServerConfig.java       |   9 +
 .../file/server/controller/FileController.java     |   8 +-
 .../src/main/resources/application.properties      |  10 -
 .../research-framework/research-service/pom.xml    |  33 --
 .../assembly/research-service-bin-assembly.xml     |  76 ----
 .../airavata/research/service/AiravataService.java |   2 +-
 .../research/service/config/AuthzTokenFilter.java  | 122 -------
 .../service/config/DevDataInitializer.java         |  11 +-
 .../service/config/ResearchProperties.java         |  28 ++
 .../service/config/ResearchServiceConfig.java      |  15 +
 .../service/controller/SessionController.java      |   2 +-
 .../research/service/handlers/ProjectHandler.java  |   2 +-
 .../service/handlers/ResearchHubHandler.java       |  34 +-
 .../research/service/handlers/ResourceHandler.java |   2 +-
 .../research/service/handlers/SessionHandler.java  |   2 +-
 .../research/service/model/UserContext.java        |  62 ----
 .../src/main/resources/application.yml             |  76 ----
 .../src/main/assembly/restproxy-bin-assembly.xml   |  75 ----
 .../airavata/restproxy/RestProxyApplication.java   |  32 --
 .../src/main/resources/application.properties      |   4 -
 .../main/resources/distribution/bin/restproxy.sh   |  26 --
 .../src/main/resources/distribution/bin/setenv.sh  | 146 --------
 .../src/main/resources/distribution/conf/.gitkeep  |   0
 modules/restproxy/src/main/resources/log4j2.xml    |  39 ---
 pom.xml                                            |  14 +-
 94 files changed, 1358 insertions(+), 2399 deletions(-)

diff --git a/Tiltfile b/Tiltfile
index 7632a6a326..ad9700a596 100644
--- a/Tiltfile
+++ b/Tiltfile
@@ -13,91 +13,31 @@ local_resource(
         'airavata-api/pom.xml',
         'airavata-thrift-server/src',
         'airavata-thrift-server/pom.xml',
-        'modules/file-server/src',
-        'modules/file-server/pom.xml',
-        'modules/agent-framework/agent-service/src',
-        'modules/agent-framework/agent-service/pom.xml',
-        'modules/research-framework/research-service/src',
-        'modules/research-framework/research-service/pom.xml',
-        'modules/restproxy/src',
-        'modules/restproxy/pom.xml',
+        'airavata-rest-server/src',
+        'airavata-rest-server/pom.xml',
+        'airavata-grpc-server/src',
+        'airavata-grpc-server/pom.xml',
+        'airavata-server/src',
+        'airavata-server/pom.xml',
     ],
     labels=['build'],
 )
 
-# --- Airavata Thrift Server (port 8930 thrift, 9097 monitoring) ---
+# --- Airavata Server (unified: Thrift + REST + gRPC) ---
 local_resource(
     'airavata-server',
-    serve_cmd=' '.join([
-        'java',
-        '-cp', 'airavata-thrift-server/target/classes:airavata-api/target/classes:airavata-api/target/dependency/*',
-        '-Dlog4j.configurationFile=airavata-api/src/main/resources/log4j2.xml',
-        '-Dairavata.config.dir=airavata-api/src/main/resources',
-        'org.apache.airavata.api.server.AiravataServer',
-    ]),
-    readiness_probe=probe(
-        http_get=http_get_action(port=9097, path='/health/services'),
-        period_secs=5,
-        timeout_secs=5,
-        initial_delay_secs=15,
-    ),
-    resource_deps=['build', 'db', 'rabbitmq', 'zookeeper', 'kafka', 'keycloak'],
-    labels=['airavata'],
-)
-
-# --- Research Service (port 18889 HTTP, 19908 gRPC) ---
-local_resource(
-    'research-service',
-    serve_cmd='mvn spring-boot:run -pl modules/research-framework/research-service -q',
+    serve_cmd='java -jar airavata-server/target/airavata-server-0.21-SNAPSHOT.jar',
     readiness_probe=probe(
         http_get=http_get_action(port=18889, path='/actuator/health'),
-        period_secs=5,
-        timeout_secs=5,
-        initial_delay_secs=20,
-    ),
-    resource_deps=['build', 'airavata-server', 'db', 'keycloak'],
-    labels=['airavata'],
-)
-
-# --- Agent Service (port 18880 HTTP, 19900 gRPC) ---
-local_resource(
-    'agent-service',
-    serve_cmd='mvn spring-boot:run -pl modules/agent-framework/agent-service -q',
-    readiness_probe=probe(
-        http_get=http_get_action(port=18880, path='/actuator/health'),
-        period_secs=5,
-        timeout_secs=5,
         initial_delay_secs=20,
-    ),
-    resource_deps=['build', 'airavata-server', 'db'],
-    labels=['airavata'],
-)
-
-# --- File Server (port 8050) ---
-local_resource(
-    'file-server',
-    serve_cmd='mvn spring-boot:run -pl modules/file-server -q',
-    readiness_probe=probe(
-        http_get=http_get_action(port=8050, path='/actuator/health'),
-        period_secs=5,
-        timeout_secs=5,
-        initial_delay_secs=15,
-    ),
-    resource_deps=['build', 'airavata-server'],
-    labels=['airavata'],
-)
-
-# --- REST Proxy (port 8082) ---
-local_resource(
-    'rest-proxy',
-    serve_cmd='mvn spring-boot:run -pl modules/restproxy -q',
-    readiness_probe=probe(
-        http_get=http_get_action(port=8082, path='/actuator/health'),
         period_secs=5,
         timeout_secs=5,
-        initial_delay_secs=15,
     ),
-    resource_deps=['build', 'airavata-server', 'kafka'],
+    resource_deps=['build', 'db', 'rabbitmq', 'zookeeper', 'kafka', 'keycloak'],
+    links=[
+        link('http://localhost:18889/swagger-ui.html', 'Swagger UI'),
+        link('http://localhost:18889/actuator/health', 'Health'),
+    ],
     labels=['airavata'],
 )
 
diff --git a/airavata-api/pom.xml b/airavata-api/pom.xml
index 402d15879e..177e1462e4 100644
--- a/airavata-api/pom.xml
+++ b/airavata-api/pom.xml
@@ -111,8 +111,8 @@ under the License.
       </exclusions>
     </dependency>
     <dependency>
-      <groupId>org.apache.openjpa</groupId>
-      <artifactId>openjpa</artifactId>
+      <groupId>org.hibernate.orm</groupId>
+      <artifactId>hibernate-core</artifactId>
     </dependency>
     <dependency>
       <groupId>org.hibernate.validator</groupId>
@@ -331,6 +331,18 @@ under the License.
       <artifactId>commons-lang3</artifactId>
     </dependency>
 
+    <!-- Spring (optional, for @ConditionalOnServer and config properties) -->
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-autoconfigure</artifactId>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-context</artifactId>
+      <optional>true</optional>
+    </dependency>
+
     <dependency>
       <groupId>software.amazon.awssdk</groupId>
       <artifactId>ec2</artifactId>
@@ -487,35 +499,6 @@ under the License.
         </configuration>
       </plugin>
 
-      <!--  Enhance OpenJPA Entities  -->
-      <plugin>
-        <groupId>org.apache.openjpa</groupId>
-        <artifactId>openjpa-maven-plugin</artifactId>
-        <configuration>
-          <includes>**/entities/**/*.class,**/compute/model/*.class,**/storage/model/*.class,**/execution/model/*.class,**/execution/model/workflow/*.class,**/sharing/model/*.class,**/credential/model/*.class</includes>
-          <excludes>**/entities/**/XML*.class,**/entities/**/*PK.class,**/*PK.class</excludes>
-          <addDefaultConstructor>true</addDefaultConstructor>
-          <enforcePropertyRestrictions>true</enforcePropertyRestrictions>
-          <persistenceXmlFile>${project.basedir}/src/main/resources/META-INF/persistence.xml</persistenceXmlFile>
-        </configuration>
-        <executions>
-          <execution>
-            <id>enhancer</id>
-            <phase>process-classes</phase>
-            <goals>
-              <goal>enhance</goal>
-            </goals>
-          </execution>
-        </executions>
-        <dependencies>
-          <dependency>
-            <groupId>org.apache.openjpa</groupId>
-            <artifactId>openjpa</artifactId>
-            <version>4.1.1</version>
-          </dependency>
-        </dependencies>
-      </plugin>
-
       <!-- Run Tests  -->
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
@@ -543,29 +526,6 @@ under the License.
         </configuration>
       </plugin>
 
-      <!-- Package distribution (tarball) -->
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-assembly-plugin</artifactId>
-        <executions>
-          <execution>
-            <id>api-server-distribution-package</id>
-            <phase>package</phase>
-            <goals>
-              <goal>single</goal>
-            </goals>
-            <configuration>
-              <tarLongFileMode>posix</tarLongFileMode>
-              <finalName>${api.server.dist.name}</finalName>
-              <descriptors>
-                <descriptor>src/main/assembly/api-server-bin-assembly.xml</descriptor>
-              </descriptors>
-              <attach>false</attach>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-
       <!-- Copy runtime dependencies for classpath mode (Tiltfile) -->
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
diff --git a/airavata-api/src/main/assembly/api-server-bin-assembly.xml b/airavata-api/src/main/assembly/api-server-bin-assembly.xml
deleted file mode 100644
index a4ba2f2ae6..0000000000
--- a/airavata-api/src/main/assembly/api-server-bin-assembly.xml
+++ /dev/null
@@ -1,116 +0,0 @@
-<!--
-
-
-    Licensed to the Apache Software Foundation (ASF) under one
-    or more contributor license agreements.  See the NOTICE file
-    distributed with this work for additional information
-    regarding copyright ownership.  The ASF licenses this file
-    to you under the Apache License, Version 2.0 (the
-    "License"); you may not use this file except in compliance
-    with the License.  You may obtain a copy of the License at
-
-      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
-    KIND, either express or implied.  See the License for the
-    specific language governing permissions and limitations
-    under the License.
-
--->
-<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.2.0"
-  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.2.0 http://maven.apache.org/xsd/assembly-2.2.0.xsd">
-  <id>bin</id>
-  <includeBaseDirectory>true</includeBaseDirectory>
-  <formats>
-    <format>tar.gz</format>
-  </formats>
-
-  <fileSets>
-
-    <!-- ********************** copy metadata files ********************** -->
-    <fileSet>
-      <directory>..</directory>
-      <outputDirectory>.</outputDirectory>
-      <includes>
-        <include>INSTALL</include>
-        <include>LICENSE</include>
-        <include>NOTICE</include>
-        <include>RELEASE_NOTES</include>
-        <include>README.md</include>
-        <include>logo.txt</include>
-      </includes>
-    </fileSet>
-
-    <!-- ********************** copy keystore files ********************** -->
-    <fileSet>
-      <directory>../keystores</directory>
-      <outputDirectory>conf/keystores</outputDirectory>
-      <includes>
-        <include>*.jks</include>
-      </includes>
-    </fileSet>
-
-    <!-- ********************** copy config files ********************** -->
-    <fileSet>
-      <directory>src/main/resources</directory>
-      <outputDirectory>conf</outputDirectory>
-      <includes>
-        <include>META-INF/persistence.xml</include>
-        <include>templates/*.template</include>
-        <include>*.properties</include>
-        <include>*.xml</include>
-      </includes>
-    </fileSet>
-
-    <!-- ********************** copy database scripts ********************** -->
-    <fileSet>
-      <directory>src/main/resources/database_scripts</directory>
-      <outputDirectory>database_scripts</outputDirectory>
-      <includes>
-        <include>*.sql</include>
-      </includes>
-    </fileSet>
-
-    <!-- ********************** copy bin files ********************** -->
-    <fileSet>
-      <directory>src/main/resources/distribution/bin</directory>
-      <outputDirectory>bin</outputDirectory>
-      <fileMode>777</fileMode>
-      <includes>
-        <include>*.sh</include>
-        <include>*.bat</include>
-      </includes>
-    </fileSet>
-
-    <!-- ********************** copy config files ********************** -->
-    <fileSet>
-      <directory>src/main/resources/distribution/conf</directory>
-      <outputDirectory>conf</outputDirectory>
-      <includes>
-        <include>*</include>
-      </includes>
-    </fileSet>
-
-    <!-- ********************** copy logs ********************** -->
-    <fileSet>
-      <directory>./</directory>
-      <outputDirectory>logs</outputDirectory>
-      <excludes>
-        <exclude>*/**</exclude>
-      </excludes>
-    </fileSet>
-
-  </fileSets>
-
-  <dependencySets>
-    <dependencySet>
-      <useProjectArtifact>true</useProjectArtifact>
-      <outputDirectory>lib</outputDirectory>
-      <useTransitiveDependencies>true</useTransitiveDependencies>
-    </dependencySet>
-  </dependencySets>
-
-</assembly>
\ No newline at end of file
diff --git a/airavata-api/src/main/assembly/api-server-src-assembly.xml b/airavata-api/src/main/assembly/api-server-src-assembly.xml
deleted file mode 100644
index b33ff157ec..0000000000
--- a/airavata-api/src/main/assembly/api-server-src-assembly.xml
+++ /dev/null
@@ -1,81 +0,0 @@
-<!--
-
-
-    Licensed to the Apache Software Foundation (ASF) under one
-    or more contributor license agreements.  See the NOTICE file
-    distributed with this work for additional information
-    regarding copyright ownership.  The ASF licenses this file
-    to you under the Apache License, Version 2.0 (the
-    "License"); you may not use this file except in compliance
-    with the License.  You may obtain a copy of the License at
-
-      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
-    KIND, either express or implied.  See the License for the
-    specific language governing permissions and limitations
-    under the License.
-
--->
-<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.2.0"
-  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.2.0 http://maven.apache.org/xsd/assembly-2.2.0.xsd">
-  <id>src</id>
-  <includeBaseDirectory>true</includeBaseDirectory>
-  <baseDirectory>${api.server.dist.name}</baseDirectory>
-  <formats>
-    <format>tar.gz</format>
-  </formats>
-
-  <fileSets>
-
-    <!-- ********************** copy metadata files ********************** -->
-    <fileSet>
-      <directory>../..</directory>
-      <outputDirectory>.</outputDirectory>
-      <includes>
-        <include>INSTALL</include>
-        <include>LICENSE</include>
-        <include>NOTICE</include>
-        <include>RELEASE_NOTES</include>
-        <include>README.md</include>
-      </includes>
-    </fileSet>
-
-    <!-- ********************** copy source code ********************** -->
-    <fileSet>
-      <directory>../..</directory>
-      <outputDirectory></outputDirectory>
-      <useDefaultExcludes>true</useDefaultExcludes>
-      <includes>
-        <include>pom.xml</include>
-        <include>airavata-api/**</include>
-        <include>modules/**</include>
-        <include>examples/**</include>
-      </includes>
-      <excludes>
-        <!-- Exclusions from org.apache.resources:apache-source-release-assembly-descriptor.
-                     Note that they assume that all sources are located under an "src" directory. This
-                     is not the case for Axis2, which doesn't use the standard Maven 2 conventions.
-                     Thus we may still encounter some issues here. -->
-        <exclude>%regex[(?!((?!${project.build.directory}/)[^/]+/)*src/).*${project.build.directory}.*]</exclude>
-        <exclude>%regex[(?!((?!${project.build.directory}/)[^/]+/)*src/)(.*/)?maven-eclipse\.xml]</exclude>
-        <exclude>%regex[(?!((?!${project.build.directory}/)[^/]+/)*src/)(.*/)?\.project]</exclude>
-        <exclude>%regex[(?!((?!${project.build.directory}/)[^/]+/)*src/)(.*/)?\.classpath]</exclude>
-        <exclude>%regex[(?!((?!${project.build.directory}/)[^/]+/)*src/)(.*/)?[^/]*\.iws]</exclude>
-        <exclude>%regex[(?!((?!${project.build.directory}/)[^/]+/)*src/)(.*/)?[^/]*\.ipr]</exclude>
-        <exclude>%regex[(?!((?!${project.build.directory}/)[^/]+/)*src/)(.*/)?[^/]*\.iml]</exclude>
-        <exclude>%regex[(?!((?!${project.build.directory}/)[^/]+/)*src/)(.*/)?\.settings(/.*)?]</exclude>
-        <exclude>%regex[(?!((?!${project.build.directory}/)[^/]+/)*src/)(.*/)?\.externalToolBuilders(/.*)?]</exclude>
-        <exclude>%regex[(?!((?!${project.build.directory}/)[^/]+/)*src/)(.*/)?\.deployables(/.*)?]</exclude>
-        <exclude>%regex[(?!((?!${project.build.directory}/)[^/]+/)*src/)(.*/)?\.wtpmodules(/.*)?]</exclude>
-        <exclude>%regex[(?!((?!${project.build.directory}/)[^/]+/)*src/)(.*/)?cobertura\.ser]</exclude>
-        <exclude>%regex[(?!((?!${project.build.directory}/)[^/]+/)*src/)(.*/)?pom\.xml\.releaseBackup]</exclude>
-        <exclude>%regex[(?!((?!${project.build.directory}/)[^/]+/)*src/)(.*/)?release\.properties]</exclude>
-      </excludes>
-    </fileSet>
-
-  </fileSets>
-</assembly>
\ No newline at end of file
diff --git a/airavata-api/src/main/java/org/apache/airavata/common/config/AiravataServerProperties.java b/airavata-api/src/main/java/org/apache/airavata/common/config/AiravataServerProperties.java
new file mode 100644
index 0000000000..46ae58aa49
--- /dev/null
+++ b/airavata-api/src/main/java/org/apache/airavata/common/config/AiravataServerProperties.java
@@ -0,0 +1,16 @@
+package org.apache.airavata.common.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import java.util.List;
+
+/**
+ * Binds the {@code airavata.servers} list property.
+ * Consumers must register via {@code @EnableConfigurationProperties(AiravataServerProperties.class)}.
+ */
+@ConfigurationProperties(prefix = "airavata")
+public class AiravataServerProperties {
+    private List<String> servers = List.of("thrift", "rest", "grpc");
+
+    public List<String> getServers() { return servers; }
+    public void setServers(List<String> servers) { this.servers = servers; }
+}
diff --git a/airavata-api/src/main/java/org/apache/airavata/common/config/ConditionalOnServer.java b/airavata-api/src/main/java/org/apache/airavata/common/config/ConditionalOnServer.java
new file mode 100644
index 0000000000..015d919e40
--- /dev/null
+++ b/airavata-api/src/main/java/org/apache/airavata/common/config/ConditionalOnServer.java
@@ -0,0 +1,12 @@
+package org.apache.airavata.common.config;
+
+import org.springframework.context.annotation.Conditional;
+import java.lang.annotation.*;
+
+@Target({ElementType.TYPE, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Conditional(OnServerCondition.class)
+public @interface ConditionalOnServer {
+    String value();
+}
diff --git a/airavata-api/src/main/java/org/apache/airavata/common/config/OnServerCondition.java b/airavata-api/src/main/java/org/apache/airavata/common/config/OnServerCondition.java
new file mode 100644
index 0000000000..6356b9dc53
--- /dev/null
+++ b/airavata-api/src/main/java/org/apache/airavata/common/config/OnServerCondition.java
@@ -0,0 +1,19 @@
+package org.apache.airavata.common.config;
+
+import org.springframework.context.annotation.Condition;
+import org.springframework.context.annotation.ConditionContext;
+import org.springframework.core.type.AnnotatedTypeMetadata;
+import java.util.Arrays;
+import java.util.Map;
+
+public class OnServerCondition implements Condition {
+    @Override
+    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
+        Map<String, Object> attrs = metadata.getAnnotationAttributes(ConditionalOnServer.class.getName());
+        if (attrs == null) return false;
+        String requiredServer = (String) attrs.get("value");
+        String[] servers = context.getEnvironment().getProperty("airavata.servers", String[].class);
+        if (servers == null) return true; // Default: all enabled
+        return Arrays.asList(servers).contains(requiredServer);
+    }
+}
diff --git a/airavata-api/src/main/java/org/apache/airavata/common/security/UserContext.java b/airavata-api/src/main/java/org/apache/airavata/common/security/UserContext.java
new file mode 100644
index 0000000000..d67ed248dd
--- /dev/null
+++ b/airavata-api/src/main/java/org/apache/airavata/common/security/UserContext.java
@@ -0,0 +1,41 @@
+package org.apache.airavata.common.security;
+
+import org.apache.airavata.common.config.Constants;
+import org.apache.airavata.model.security.AuthzToken;
+import org.apache.airavata.security.profile.commons.user.entities.UserProfileEntity;
+
+import java.util.Map;
+
+public class UserContext {
+
+    private static final ThreadLocal<AuthzToken> AUTHZ_TOKEN = new ThreadLocal<>();
+    private static final ThreadLocal<UserProfileEntity> CURRENT_USER = new ThreadLocal<>();
+
+    private UserContext() {}
+
+    public static AuthzToken authzToken() { return AUTHZ_TOKEN.get(); }
+    public static void setAuthzToken(AuthzToken token) { AUTHZ_TOKEN.set(token); }
+    public static UserProfileEntity user() { return CURRENT_USER.get(); }
+    public static void setUser(UserProfileEntity user) { CURRENT_USER.set(user); }
+
+    public static String userId() {
+        var token = authzToken();
+        if (token == null) return null;
+        Map<String, String> claims = token.getClaimsMap();
+        return claims != null ? claims.get(Constants.USER_NAME) : null;
+    }
+
+    public static String gatewayId() {
+        var token = authzToken();
+        if (token == null) return null;
+        Map<String, String> claims = token.getClaimsMap();
+        return claims != null ? claims.get(Constants.GATEWAY_ID) : null;
+    }
+
+    public static boolean isAuthenticated() { return authzToken() != null; }
+
+    public static void clear() {
+        AUTHZ_TOKEN.remove();
+        CURRENT_USER.remove();
+    }
+}
diff --git a/airavata-api/src/main/java/org/apache/airavata/compute/model/AppEnvironmentEntity.java b/airavata-api/src/main/java/org/apache/airavata/compute/model/AppEnvironmentEntity.java
index c1b35a7eef..6f8ac4177e 100644
--- a/airavata-api/src/main/java/org/apache/airavata/compute/model/AppEnvironmentEntity.java
+++ b/airavata-api/src/main/java/org/apache/airavata/compute/model/AppEnvironmentEntity.java
@@ -21,8 +21,8 @@ package org.apache.airavata.compute.model;
 
 import jakarta.persistence.*;
 import java.io.Serializable;
-import org.apache.openjpa.persistence.jdbc.ForeignKey;
-import org.apache.openjpa.persistence.jdbc.ForeignKeyAction;
+import org.hibernate.annotations.OnDelete;
+import org.hibernate.annotations.OnDeleteAction;
 
 /**
  * The persistent class for the app_environment database table.
@@ -49,7 +49,7 @@ public class AppEnvironmentEntity implements Serializable {
 
     @ManyToOne(targetEntity = ApplicationDeploymentEntity.class)
     @JoinColumn(name = "DEPLOYMENT_ID", nullable = false, updatable = false)
-    @ForeignKey(deleteAction = ForeignKeyAction.CASCADE)
+    @OnDelete(action = OnDeleteAction.CASCADE)
     private ApplicationDeploymentEntity applicationDeployment;
 
     public AppEnvironmentEntity() {}
diff --git a/airavata-api/src/main/java/org/apache/airavata/compute/model/ApplicationInputEntity.java b/airavata-api/src/main/java/org/apache/airavata/compute/model/ApplicationInputEntity.java
index fc2c0705f1..9d8092a4c1 100644
--- a/airavata-api/src/main/java/org/apache/airavata/compute/model/ApplicationInputEntity.java
+++ b/airavata-api/src/main/java/org/apache/airavata/compute/model/ApplicationInputEntity.java
@@ -22,8 +22,8 @@ package org.apache.airavata.compute.model;
 import jakarta.persistence.*;
 import java.io.Serializable;
 import org.apache.airavata.model.application.io.DataType;
-import org.apache.openjpa.persistence.jdbc.ForeignKey;
-import org.apache.openjpa.persistence.jdbc.ForeignKeyAction;
+import org.hibernate.annotations.OnDelete;
+import org.hibernate.annotations.OnDeleteAction;
 
 /**
  * The persistent class for the application_input database table.
@@ -83,7 +83,7 @@ public class ApplicationInputEntity implements Serializable {
 
     @ManyToOne(targetEntity = ApplicationInterfaceEntity.class)
     @JoinColumn(name = "INTERFACE_ID", nullable = false, updatable = false)
-    @ForeignKey(deleteAction = ForeignKeyAction.CASCADE)
+    @OnDelete(action = OnDeleteAction.CASCADE)
     private ApplicationInterfaceEntity applicationInterface;
 
     public ApplicationInputEntity() {}
diff --git a/airavata-api/src/main/java/org/apache/airavata/compute/model/ApplicationOutputEntity.java b/airavata-api/src/main/java/org/apache/airavata/compute/model/ApplicationOutputEntity.java
index a405698780..b50ef9e7ae 100644
--- a/airavata-api/src/main/java/org/apache/airavata/compute/model/ApplicationOutputEntity.java
+++ b/airavata-api/src/main/java/org/apache/airavata/compute/model/ApplicationOutputEntity.java
@@ -22,8 +22,8 @@ package org.apache.airavata.compute.model;
 import jakarta.persistence.*;
 import java.io.Serializable;
 import org.apache.airavata.model.application.io.DataType;
-import org.apache.openjpa.persistence.jdbc.ForeignKey;
-import org.apache.openjpa.persistence.jdbc.ForeignKeyAction;
+import org.hibernate.annotations.OnDelete;
+import org.hibernate.annotations.OnDeleteAction;
 
 /**
  * The persistent class for the application_output database table.
@@ -75,7 +75,7 @@ public class ApplicationOutputEntity implements Serializable {
 
     @ManyToOne(targetEntity = ApplicationInterfaceEntity.class)
     @JoinColumn(name = "INTERFACE_ID", nullable = false, updatable = false)
-    @ForeignKey(deleteAction = ForeignKeyAction.CASCADE)
+    @OnDelete(action = OnDeleteAction.CASCADE)
     private ApplicationInterfaceEntity applicationInterface;
 
     public ApplicationOutputEntity() {}
diff --git a/airavata-api/src/main/java/org/apache/airavata/compute/model/BatchQueueResourcePolicyEntity.java b/airavata-api/src/main/java/org/apache/airavata/compute/model/BatchQueueResourcePolicyEntity.java
index 1a86d60591..64df10b84c 100644
--- a/airavata-api/src/main/java/org/apache/airavata/compute/model/BatchQueueResourcePolicyEntity.java
+++ b/airavata-api/src/main/java/org/apache/airavata/compute/model/BatchQueueResourcePolicyEntity.java
@@ -26,8 +26,8 @@ import jakarta.persistence.JoinColumn;
 import jakarta.persistence.ManyToOne;
 import jakarta.persistence.Table;
 import java.io.Serializable;
-import org.apache.openjpa.persistence.jdbc.ForeignKey;
-import org.apache.openjpa.persistence.jdbc.ForeignKeyAction;
+import org.hibernate.annotations.OnDelete;
+import org.hibernate.annotations.OnDeleteAction;
 
 /**
  * The persistent class for the batch_queue_resource_policy database table.
@@ -62,7 +62,7 @@ public class BatchQueueResourcePolicyEntity implements Serializable {
 
     @ManyToOne(targetEntity = GroupResourceProfileEntity.class)
     @JoinColumn(name = "GROUP_RESOURCE_PROFILE_ID", nullable = false, updatable = false)
-    @ForeignKey(deleteAction = ForeignKeyAction.CASCADE)
+    @OnDelete(action = OnDeleteAction.CASCADE)
     private GroupResourceProfileEntity groupResourceProfile;
 
     public BatchQueueResourcePolicyEntity() {}
diff --git a/airavata-api/src/main/java/org/apache/airavata/compute/model/ComputeResourcePolicyEntity.java b/airavata-api/src/main/java/org/apache/airavata/compute/model/ComputeResourcePolicyEntity.java
index 5a9eb51f6e..c43e400734 100644
--- a/airavata-api/src/main/java/org/apache/airavata/compute/model/ComputeResourcePolicyEntity.java
+++ b/airavata-api/src/main/java/org/apache/airavata/compute/model/ComputeResourcePolicyEntity.java
@@ -30,8 +30,8 @@ import jakarta.persistence.ManyToOne;
 import jakarta.persistence.Table;
 import java.io.Serializable;
 import java.util.List;
-import org.apache.openjpa.persistence.jdbc.ForeignKey;
-import org.apache.openjpa.persistence.jdbc.ForeignKeyAction;
+import org.hibernate.annotations.OnDelete;
+import org.hibernate.annotations.OnDeleteAction;
 
 /**
  * The persistent class for the compute_resource_policy database table.
@@ -62,7 +62,7 @@ public class ComputeResourcePolicyEntity implements Serializable {
 
     @ManyToOne(targetEntity = GroupResourceProfileEntity.class)
     @JoinColumn(name = "GROUP_RESOURCE_PROFILE_ID", nullable = false, updatable = false)
-    @ForeignKey(deleteAction = ForeignKeyAction.CASCADE)
+    @OnDelete(action = OnDeleteAction.CASCADE)
     private GroupResourceProfileEntity groupResourceProfile;
 
     public ComputeResourcePolicyEntity() {}
diff --git a/airavata-api/src/main/java/org/apache/airavata/compute/model/ComputeResourceReservationEntity.java b/airavata-api/src/main/java/org/apache/airavata/compute/model/ComputeResourceReservationEntity.java
index 2903981a1f..865f383f44 100644
--- a/airavata-api/src/main/java/org/apache/airavata/compute/model/ComputeResourceReservationEntity.java
+++ b/airavata-api/src/main/java/org/apache/airavata/compute/model/ComputeResourceReservationEntity.java
@@ -32,8 +32,8 @@ import jakarta.persistence.Table;
 import java.io.Serializable;
 import java.sql.Timestamp;
 import java.util.List;
-import org.apache.openjpa.persistence.jdbc.ForeignKey;
-import org.apache.openjpa.persistence.jdbc.ForeignKeyAction;
+import org.hibernate.annotations.OnDelete;
+import org.hibernate.annotations.OnDeleteAction;
 
 /**
  * The persistent class for the COMPUTE_RESOURCE_RESERVATION database table.
@@ -73,7 +73,7 @@ public class ComputeResourceReservationEntity implements Serializable {
                 nullable = false,
                 updatable = false)
     })
-    @ForeignKey(deleteAction = ForeignKeyAction.CASCADE)
+    @OnDelete(action = OnDeleteAction.CASCADE)
     private GroupComputeResourcePrefEntity groupComputeResourcePref;
 
     public ComputeResourceReservationEntity() {}
diff --git a/airavata-api/src/main/java/org/apache/airavata/compute/model/GroupComputeResourcePrefEntity.java b/airavata-api/src/main/java/org/apache/airavata/compute/model/GroupComputeResourcePrefEntity.java
index 8deec605b6..76277cbf8d 100644
--- a/airavata-api/src/main/java/org/apache/airavata/compute/model/GroupComputeResourcePrefEntity.java
+++ b/airavata-api/src/main/java/org/apache/airavata/compute/model/GroupComputeResourcePrefEntity.java
@@ -36,8 +36,8 @@ import jakarta.persistence.Table;
 import java.io.Serializable;
 import org.apache.airavata.model.appcatalog.computeresource.JobSubmissionProtocol;
 import org.apache.airavata.model.data.movement.DataMovementProtocol;
-import org.apache.openjpa.persistence.jdbc.ForeignKey;
-import org.apache.openjpa.persistence.jdbc.ForeignKeyAction;
+import org.hibernate.annotations.OnDelete;
+import org.hibernate.annotations.OnDeleteAction;
 
 /**
  * The persistent class for the group_compute_resource_preference database table.
@@ -81,7 +81,7 @@ public abstract class GroupComputeResourcePrefEntity implements Serializable {
 
     @ManyToOne(targetEntity = GroupResourceProfileEntity.class, cascade = CascadeType.PERSIST)
     @JoinColumn(name = "GROUP_RESOURCE_PROFILE_ID", nullable = false, updatable = false)
-    @ForeignKey(deleteAction = ForeignKeyAction.CASCADE)
+    @OnDelete(action = OnDeleteAction.CASCADE)
     private GroupResourceProfileEntity groupResourceProfile;
 
     public GroupComputeResourcePrefEntity() {}
diff --git a/airavata-api/src/main/java/org/apache/airavata/compute/model/GroupSSHAccountProvisionerConfig.java b/airavata-api/src/main/java/org/apache/airavata/compute/model/GroupSSHAccountProvisionerConfig.java
index 4def294703..0678f3f9b0 100644
--- a/airavata-api/src/main/java/org/apache/airavata/compute/model/GroupSSHAccountProvisionerConfig.java
+++ b/airavata-api/src/main/java/org/apache/airavata/compute/model/GroupSSHAccountProvisionerConfig.java
@@ -28,8 +28,8 @@ import jakarta.persistence.JoinColumns;
 import jakarta.persistence.ManyToOne;
 import jakarta.persistence.Table;
 import java.io.Serializable;
-import org.apache.openjpa.persistence.jdbc.ForeignKey;
-import org.apache.openjpa.persistence.jdbc.ForeignKeyAction;
+import org.hibernate.annotations.OnDelete;
+import org.hibernate.annotations.OnDeleteAction;
 
 /**
  * The persistent class for the grp_ssh_acc_prov_config database table.
@@ -64,7 +64,7 @@ public class GroupSSHAccountProvisionerConfig implements Serializable {
                 referencedColumnName = "GROUP_RESOURCE_PROFILE_ID",
                 nullable = false)
     })
-    @ForeignKey(deleteAction = ForeignKeyAction.CASCADE)
+    @OnDelete(action = OnDeleteAction.CASCADE)
     private GroupComputeResourcePrefEntity groupComputeResourcePref;
 
     public GroupSSHAccountProvisionerConfig() {}
diff --git a/airavata-api/src/main/java/org/apache/airavata/compute/model/LibraryApendPathEntity.java b/airavata-api/src/main/java/org/apache/airavata/compute/model/LibraryApendPathEntity.java
index 66520f6be1..02c787ec25 100644
--- a/airavata-api/src/main/java/org/apache/airavata/compute/model/LibraryApendPathEntity.java
+++ b/airavata-api/src/main/java/org/apache/airavata/compute/model/LibraryApendPathEntity.java
@@ -21,8 +21,8 @@ package org.apache.airavata.compute.model;
 
 import jakarta.persistence.*;
 import java.io.Serializable;
-import org.apache.openjpa.persistence.jdbc.ForeignKey;
-import org.apache.openjpa.persistence.jdbc.ForeignKeyAction;
+import org.hibernate.annotations.OnDelete;
+import org.hibernate.annotations.OnDeleteAction;
 
 /**
  * The persistent class for the library_apend_path database table.
@@ -46,7 +46,7 @@ public class LibraryApendPathEntity implements Serializable {
 
     @ManyToOne(targetEntity = ApplicationDeploymentEntity.class, cascade = CascadeType.MERGE)
     @JoinColumn(name = "DEPLOYMENT_ID")
-    @ForeignKey(deleteAction = ForeignKeyAction.CASCADE)
+    @OnDelete(action = OnDeleteAction.CASCADE)
     private ApplicationDeploymentEntity applicationDeployment;
 
     public LibraryApendPathEntity() {}
diff --git a/airavata-api/src/main/java/org/apache/airavata/compute/model/LibraryPrependPathEntity.java b/airavata-api/src/main/java/org/apache/airavata/compute/model/LibraryPrependPathEntity.java
index a1e261151b..986d411a6e 100644
--- a/airavata-api/src/main/java/org/apache/airavata/compute/model/LibraryPrependPathEntity.java
+++ b/airavata-api/src/main/java/org/apache/airavata/compute/model/LibraryPrependPathEntity.java
@@ -21,8 +21,8 @@ package org.apache.airavata.compute.model;
 
 import jakarta.persistence.*;
 import java.io.Serializable;
-import org.apache.openjpa.persistence.jdbc.ForeignKey;
-import org.apache.openjpa.persistence.jdbc.ForeignKeyAction;
+import org.hibernate.annotations.OnDelete;
+import org.hibernate.annotations.OnDeleteAction;
 
 /**
  * The persistent class for the library_apend_path database table.
@@ -47,7 +47,7 @@ public class LibraryPrependPathEntity implements Serializable {
 
     @ManyToOne(targetEntity = ApplicationDeploymentEntity.class, cascade = CascadeType.MERGE)
     @JoinColumn(name = "DEPLOYMENT_ID")
-    @ForeignKey(deleteAction = ForeignKeyAction.CASCADE)
+    @OnDelete(action = OnDeleteAction.CASCADE)
     private ApplicationDeploymentEntity applicationDeployment;
 
     public LibraryPrependPathEntity() {}
diff --git a/airavata-api/src/main/java/org/apache/airavata/compute/model/ModuleLoadCmdEntity.java b/airavata-api/src/main/java/org/apache/airavata/compute/model/ModuleLoadCmdEntity.java
index a8d549f179..79cfd0ed6a 100644
--- a/airavata-api/src/main/java/org/apache/airavata/compute/model/ModuleLoadCmdEntity.java
+++ b/airavata-api/src/main/java/org/apache/airavata/compute/model/ModuleLoadCmdEntity.java
@@ -21,8 +21,8 @@ package org.apache.airavata.compute.model;
 
 import jakarta.persistence.*;
 import java.io.Serializable;
-import org.apache.openjpa.persistence.jdbc.ForeignKey;
-import org.apache.openjpa.persistence.jdbc.ForeignKeyAction;
+import org.hibernate.annotations.OnDelete;
+import org.hibernate.annotations.OnDeleteAction;
 
 /**
  * The persistent class for the module_load_cmd database table.
@@ -46,7 +46,7 @@ public class ModuleLoadCmdEntity implements Serializable {
 
     @ManyToOne(targetEntity = ApplicationDeploymentEntity.class, cascade = CascadeType.MERGE)
     @JoinColumn(name = "APP_DEPLOYMENT_ID")
-    @ForeignKey(deleteAction = ForeignKeyAction.CASCADE)
+    @OnDelete(action = OnDeleteAction.CASCADE)
     private ApplicationDeploymentEntity applicationDeployment;
 
     public ModuleLoadCmdEntity() {}
diff --git a/airavata-api/src/main/java/org/apache/airavata/compute/model/PostjobCommandEntity.java b/airavata-api/src/main/java/org/apache/airavata/compute/model/PostjobCommandEntity.java
index bbc934f423..3c59bf2469 100644
--- a/airavata-api/src/main/java/org/apache/airavata/compute/model/PostjobCommandEntity.java
+++ b/airavata-api/src/main/java/org/apache/airavata/compute/model/PostjobCommandEntity.java
@@ -21,8 +21,8 @@ package org.apache.airavata.compute.model;
 
 import jakarta.persistence.*;
 import java.io.Serializable;
-import org.apache.openjpa.persistence.jdbc.ForeignKey;
-import org.apache.openjpa.persistence.jdbc.ForeignKeyAction;
+import org.hibernate.annotations.OnDelete;
+import org.hibernate.annotations.OnDeleteAction;
 
 /**
  * The persistent class for the postjob_command database table.
@@ -46,7 +46,7 @@ public class PostjobCommandEntity implements Serializable {
 
     @ManyToOne(targetEntity = ApplicationDeploymentEntity.class, cascade = CascadeType.MERGE)
     @JoinColumn(name = "APPDEPLOYMENT_ID")
-    @ForeignKey(deleteAction = ForeignKeyAction.CASCADE)
+    @OnDelete(action = OnDeleteAction.CASCADE)
     private ApplicationDeploymentEntity applicationDeployment;
 
     public PostjobCommandEntity() {}
diff --git a/airavata-api/src/main/java/org/apache/airavata/compute/model/PrejobCommandEntity.java b/airavata-api/src/main/java/org/apache/airavata/compute/model/PrejobCommandEntity.java
index fd6cfea735..3cd8a7c7e1 100644
--- a/airavata-api/src/main/java/org/apache/airavata/compute/model/PrejobCommandEntity.java
+++ b/airavata-api/src/main/java/org/apache/airavata/compute/model/PrejobCommandEntity.java
@@ -21,8 +21,8 @@ package org.apache.airavata.compute.model;
 
 import jakarta.persistence.*;
 import java.io.Serializable;
-import org.apache.openjpa.persistence.jdbc.ForeignKey;
-import org.apache.openjpa.persistence.jdbc.ForeignKeyAction;
+import org.hibernate.annotations.OnDelete;
+import org.hibernate.annotations.OnDeleteAction;
 
 /**
  * The persistent class for the prejob_command database table.
@@ -46,7 +46,7 @@ public class PrejobCommandEntity implements Serializable {
 
     @ManyToOne(targetEntity = ApplicationDeploymentEntity.class, cascade = CascadeType.MERGE)
     @JoinColumn(name = "APPDEPLOYMENT_ID")
-    @ForeignKey(deleteAction = ForeignKeyAction.CASCADE)
+    @OnDelete(action = OnDeleteAction.CASCADE)
     private ApplicationDeploymentEntity applicationDeployment;
 
     public PrejobCommandEntity() {}
diff --git a/airavata-api/src/main/java/org/apache/airavata/credential/handler/CredentialStoreServerHandler.java b/airavata-api/src/main/java/org/apache/airavata/credential/handler/CredentialStoreServerHandler.java
index f08ded5db4..dbbd1b6211 100644
--- a/airavata-api/src/main/java/org/apache/airavata/credential/handler/CredentialStoreServerHandler.java
+++ b/airavata-api/src/main/java/org/apache/airavata/credential/handler/CredentialStoreServerHandler.java
@@ -47,8 +47,10 @@ import org.apache.commons.codec.binary.Base64;
 import org.apache.thrift.TException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
 // import sun.security.provider.X509Factory;
 
+@Component
 public class CredentialStoreServerHandler implements CredentialStoreService.Iface {
     protected static Logger log = LoggerFactory.getLogger(CredentialStoreServerHandler.class);
     private DBUtil dbUtil;
diff --git a/airavata-api/src/main/java/org/apache/airavata/execution/handler/RegistryServerHandler.java b/airavata-api/src/main/java/org/apache/airavata/execution/handler/RegistryServerHandler.java
index bb6b7cb831..3a54bbadfb 100644
--- a/airavata-api/src/main/java/org/apache/airavata/execution/handler/RegistryServerHandler.java
+++ b/airavata-api/src/main/java/org/apache/airavata/execution/handler/RegistryServerHandler.java
@@ -78,7 +78,9 @@ import org.apache.airavata.storage.repository.StorageResourceRepository;
 import org.apache.thrift.TException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
 
+@Component
 public class RegistryServerHandler implements RegistryService.Iface {
     private static final Logger logger = LoggerFactory.getLogger(RegistryServerHandler.class);
 
diff --git a/airavata-api/src/main/java/org/apache/airavata/sharing/handler/SharingRegistryServerHandler.java b/airavata-api/src/main/java/org/apache/airavata/sharing/handler/SharingRegistryServerHandler.java
index 16afd1f3af..ec765ad396 100644
--- a/airavata-api/src/main/java/org/apache/airavata/sharing/handler/SharingRegistryServerHandler.java
+++ b/airavata-api/src/main/java/org/apache/airavata/sharing/handler/SharingRegistryServerHandler.java
@@ -35,7 +35,9 @@ import org.apache.commons.lang3.exception.ExceptionUtils;
 import org.apache.thrift.TException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
 
+@Component
 public class SharingRegistryServerHandler implements SharingRegistryService.Iface {
     private static final Logger logger = LoggerFactory.getLogger(SharingRegistryServerHandler.class);
 
diff --git a/airavata-api/src/main/resources/META-INF/persistence.xml b/airavata-api/src/main/resources/META-INF/persistence.xml
deleted file mode 100644
index 5714ac677c..0000000000
--- a/airavata-api/src/main/resources/META-INF/persistence.xml
+++ /dev/null
@@ -1,203 +0,0 @@
-<?xml version="1.0"?>
-<!--*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   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
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-* -->
-<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
-  <persistence-unit name="profile_service">
-    <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
-    <class>org.apache.airavata.security.profile.commons.user.entities.UserProfileEntity</class>
-    <class>org.apache.airavata.security.profile.commons.user.entities.NSFDemographicsEntity</class>
-    <class>org.apache.airavata.security.profile.commons.user.entities.CustomizedDashboardEntity</class>
-    <class>org.apache.airavata.security.profile.commons.tenant.entities.GatewayEntity</class>
-    <exclude-unlisted-classes>true</exclude-unlisted-classes>
-    <properties>
-      <property name="openjpa.jdbc.MappingDefaults"
-        value="ForeignKeyDeleteAction=cascade, JoinForeignKeyDeleteAction=cascade" />
-      <property name="openjpa.jdbc.DBDictionary" value="mysql" />
-    </properties>
-  </persistence-unit>
-  <persistence-unit name="appcatalog_data_new">
-    <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
-    <class>org.apache.airavata.storage.model.GridftpDataMovementEntity</class>
-    <class>org.apache.airavata.compute.model.ResourceJobManagerEntity</class>
-    <class>org.apache.airavata.compute.model.ComputeResourceEntity</class>
-    <class>org.apache.airavata.compute.model.ApplicationModuleEntity</class>
-    <class>org.apache.airavata.compute.model.ApplicationDeploymentEntity</class>
-    <class>org.apache.airavata.compute.model.ApplicationInterfaceEntity</class>
-    <class>org.apache.airavata.compute.model.GatewayGroupsEntity</class>
-    <class>org.apache.airavata.compute.model.GatewayProfileEntity</class>
-    <class>org.apache.airavata.storage.model.StorageResourceEntity</class>
-    <class>org.apache.airavata.storage.model.ScpDataMovementEntity</class>
-    <class>org.apache.airavata.compute.model.SshJobSubmissionEntity</class>
-    <class>org.apache.airavata.compute.model.GlobusSubmissionEntity</class>
-    <class>org.apache.airavata.compute.model.GsisshSubmissionEntity</class>
-    <class>org.apache.airavata.storage.model.GridftpEndpointEntity</class>
-    <class>org.apache.airavata.compute.model.ComputeResourcePreferenceEntity</class>
-    <class>org.apache.airavata.compute.model.JobSubmissionInterfaceEntity</class>
-    <class>org.apache.airavata.storage.model.DataMovementInterfaceEntity</class>
-    <class>org.apache.airavata.storage.model.StorageInterfaceEntity</class>
-    <class>org.apache.airavata.compute.model.LocalSubmissionEntity</class>
-    <class>org.apache.airavata.compute.model.GlobusGkEndpointEntity</class>
-    <class>org.apache.airavata.storage.model.UnicoreDatamovementEntity</class>
-    <class>org.apache.airavata.compute.model.UnicoreSubmissionEntity</class>
-    <class>org.apache.airavata.compute.model.GsisshPostjobcommandEntity</class>
-    <class>org.apache.airavata.compute.model.GsisshPrejobcommandEntity</class>
-    <class>org.apache.airavata.compute.model.GsisshExportEntity</class>
-    <class>org.apache.airavata.compute.model.LibraryApendPathEntity</class>
-    <class>org.apache.airavata.compute.model.LibraryPrependPathEntity</class>
-    <class>org.apache.airavata.compute.model.AppEnvironmentEntity</class>
-    <class>org.apache.airavata.compute.model.PrejobCommandEntity</class>
-    <class>org.apache.airavata.compute.model.PostjobCommandEntity</class>
-    <class>org.apache.airavata.compute.model.AppModuleMappingEntity</class>
-    <class>org.apache.airavata.compute.model.ApplicationInputEntity</class>
-    <class>org.apache.airavata.compute.model.ApplicationOutputEntity</class>
-    <class>org.apache.airavata.compute.model.BatchQueueEntity</class>
-    <class>org.apache.airavata.compute.model.ComputeResourceFileSystemEntity</class>
-    <class>org.apache.airavata.compute.model.CloudJobSubmissionEntity</class>
-    <class>org.apache.airavata.compute.model.JobManagerCommandEntity</class>
-    <class>org.apache.airavata.compute.model.ParallelismCommandEntity</class>
-    <class>org.apache.airavata.storage.model.LocalDataMovementEntity</class>
-    <class>org.apache.airavata.storage.model.StoragePreferenceEntity</class>
-    <class>org.apache.airavata.compute.model.SSHAccountProvisionerConfiguration</class>
-    <class>org.apache.airavata.compute.model.BatchQueueResourcePolicyEntity</class>
-    <class>org.apache.airavata.compute.model.ComputeResourcePolicyEntity</class>
-    <class>org.apache.airavata.compute.model.GroupComputeResourcePrefEntity</class>
-    <class>org.apache.airavata.compute.model.AWSGroupComputeResourcePrefEntity</class>
-    <class>org.apache.airavata.compute.model.SlurmGroupComputeResourcePrefEntity</class>
-    <class>org.apache.airavata.compute.model.GroupSSHAccountProvisionerConfig</class>
-    <class>org.apache.airavata.compute.model.GroupResourceProfileEntity</class>
-    <class>org.apache.airavata.compute.model.ModuleLoadCmdEntity</class>
-    <class>org.apache.airavata.compute.model.UserResourceProfileEntity</class>
-    <class>org.apache.airavata.compute.model.UserComputeResourcePreferenceEntity</class>
-    <class>org.apache.airavata.storage.model.UserStoragePreferenceEntity</class>
-    <class>org.apache.airavata.compute.model.ParserEntity</class>
-    <class>org.apache.airavata.compute.model.ParserInputEntity</class>
-    <class>org.apache.airavata.compute.model.ParserOutputEntity</class>
-    <class>org.apache.airavata.compute.model.ParsingTemplateEntity</class>
-    <class>org.apache.airavata.compute.model.ParsingTemplateInputEntity</class>
-    <class>org.apache.airavata.compute.model.ParserConnectorInputEntity</class>
-    <class>org.apache.airavata.compute.model.ParserConnectorEntity</class>
-    <class>org.apache.airavata.compute.model.ComputeResourceReservationEntity</class>
-    <exclude-unlisted-classes>true</exclude-unlisted-classes>
-    <properties>
-      <property name="openjpa.jdbc.MappingDefaults"
-        value="ForeignKeyDeleteAction=cascade, JoinForeignKeyDeleteAction=cascade" />
-      <property name="openjpa.jdbc.DBDictionary" value="mysql" />
-    </properties>
-  </persistence-unit>
-  <persistence-unit name="replicacatalog_data_new">
-    <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
-    <class>org.apache.airavata.storage.model.ConfigurationEntity</class>
-    <class>org.apache.airavata.storage.model.DataProductEntity</class>
-    <class>org.apache.airavata.storage.model.DataProductMetadataEntity</class>
-    <class>org.apache.airavata.storage.model.DataReplicaLocationEntity</class>
-    <class>org.apache.airavata.storage.model.DataReplicaMetadataEntity</class>
-    <exclude-unlisted-classes>true</exclude-unlisted-classes>
-    <properties>
-      <property name="openjpa.jdbc.MappingDefaults"
-        value="ForeignKeyDeleteAction=cascade, JoinForeignKeyDeleteAction=cascade" />
-      <property name="openjpa.jdbc.DBDictionary" value="mysql" />
-    </properties>
-  </persistence-unit>
-  <persistence-unit name="workflowcatalog_data_new">
-    <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
-    <class>org.apache.airavata.execution.model.workflow.AiravataWorkflowEntity</class>
-    <class>
-      org.apache.airavata.execution.model.workflow.AiravataWorkflowErrorEntity</class>
-    <class>
-      org.apache.airavata.execution.model.workflow.AiravataWorkflowStatusEntity</class>
-    <class>org.apache.airavata.execution.model.workflow.ApplicationErrorEntity</class>
-    <class>
-      org.apache.airavata.execution.model.workflow.ApplicationStatusEntity</class>
-    <class>org.apache.airavata.execution.model.workflow.HandlerErrorEntity</class>
-    <class>org.apache.airavata.execution.model.workflow.HandlerInputEntity</class>
-    <class>org.apache.airavata.execution.model.workflow.HandlerOutputEntity</class>
-    <class>org.apache.airavata.execution.model.workflow.HandlerStatusEntity</class>
-    <class>
-      org.apache.airavata.execution.model.workflow.WorkflowApplicationEntity</class>
-    <class>
-      org.apache.airavata.execution.model.workflow.WorkflowConnectionEntity</class>
-    <class>
-      org.apache.airavata.execution.model.workflow.WorkflowDataBlockEntity</class>
-    <class>org.apache.airavata.execution.model.workflow.WorkflowHandlerEntity</class>
-    <exclude-unlisted-classes>true</exclude-unlisted-classes>
-    <properties>
-      <property name="openjpa.jdbc.MappingDefaults"
-        value="ForeignKeyDeleteAction=cascade, JoinForeignKeyDeleteAction=cascade" />
-      <property name="openjpa.jdbc.DBDictionary" value="mysql" />
-    </properties>
-  </persistence-unit>
-  <persistence-unit name="experiment_data_new">
-    <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
-    <class>org.apache.airavata.execution.model.ExperimentEntity</class>
-    <class>org.apache.airavata.execution.model.ExperimentErrorEntity</class>
-    <class>org.apache.airavata.execution.model.ExperimentInputEntity</class>
-    <class>org.apache.airavata.execution.model.ExperimentOutputEntity</class>
-    <class>org.apache.airavata.execution.model.ExperimentStatusEntity</class>
-    <class>org.apache.airavata.execution.model.ExperimentSummaryEntity</class>
-    <class>org.apache.airavata.execution.model.GatewayEntity</class>
-    <class>org.apache.airavata.execution.model.GatewayWorkerEntity</class>
-    <class>org.apache.airavata.execution.model.GatewayUsageReportingCommandEntity</class>
-    <class>org.apache.airavata.execution.model.JobEntity</class>
-    <class>org.apache.airavata.execution.model.JobStatusEntity</class>
-    <class>org.apache.airavata.execution.model.NotificationEntity</class>
-    <class>org.apache.airavata.execution.model.ProcessEntity</class>
-    <class>org.apache.airavata.execution.model.ProcessErrorEntity</class>
-    <class>org.apache.airavata.execution.model.ProcessInputEntity</class>
-    <class>org.apache.airavata.execution.model.ProcessOutputEntity</class>
-    <class>org.apache.airavata.execution.model.ProcessResourceScheduleEntity</class>
-    <class>org.apache.airavata.execution.model.ProcessStatusEntity</class>
-    <class>org.apache.airavata.execution.model.ProcessWorkflowEntity</class>
-    <class>org.apache.airavata.execution.model.ProjectEntity</class>
-    <class>org.apache.airavata.execution.model.ProjectUserEntity</class>
-    <class>org.apache.airavata.execution.model.QueueStatusEntity</class>
-    <class>org.apache.airavata.execution.model.TaskEntity</class>
-    <class>org.apache.airavata.execution.model.TaskErrorEntity</class>
-    <class>org.apache.airavata.execution.model.TaskStatusEntity</class>
-    <class>org.apache.airavata.execution.model.UserConfigurationDataEntity</class>
-    <class>
-      org.apache.airavata.execution.model.ComputationalResourceSchedulingEntity</class>
-    <class>org.apache.airavata.execution.model.UserEntity</class>
-    <exclude-unlisted-classes>true</exclude-unlisted-classes>
-    <properties>
-      <property name="openjpa.jdbc.MappingDefaults"
-        value="ForeignKeyDeleteAction=cascade, JoinForeignKeyDeleteAction=cascade" />
-      <property name="openjpa.jdbc.DBDictionary" value="mysql" />
-    </properties>
-  </persistence-unit>
-  <persistence-unit name="airavata-sharing-registry">
-    <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
-    <class>org.apache.airavata.sharing.model.DomainEntity</class>
-    <class>org.apache.airavata.sharing.model.EntityEntity</class>
-    <class>org.apache.airavata.sharing.model.EntityTypeEntity</class>
-    <class>org.apache.airavata.sharing.model.GroupMembershipEntity</class>
-    <class>org.apache.airavata.sharing.model.PermissionTypeEntity</class>
-    <class>org.apache.airavata.sharing.model.SharingEntity</class>
-    <class>org.apache.airavata.sharing.model.UserEntity</class>
-    <class>org.apache.airavata.sharing.model.GroupAdminEntity</class>
-    <class>org.apache.airavata.sharing.model.UserGroupEntity</class>
-    <exclude-unlisted-classes>true</exclude-unlisted-classes>
-    <properties>
-      <property name="openjpa.jdbc.MappingDefaults"
-        value="ForeignKeyDeleteAction=cascade, JoinForeignKeyDeleteAction=cascade" />
-      <property name="openjpa.jdbc.DBDictionary" value="mysql" />
-    </properties>
-  </persistence-unit>
-</persistence>
\ No newline at end of file
diff --git a/modules/file-server/pom.xml b/airavata-grpc-server/pom.xml
similarity index 55%
copy from modules/file-server/pom.xml
copy to airavata-grpc-server/pom.xml
index 0276417a25..6852ae093d 100644
--- a/modules/file-server/pom.xml
+++ b/airavata-grpc-server/pom.xml
@@ -16,33 +16,57 @@ KIND, either express or implied. See the License for the
 specific language governing permissions and limitations
 under the License.
 -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
+
     <parent>
         <groupId>org.apache.airavata</groupId>
         <artifactId>airavata</artifactId>
         <version>0.21-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
+        <relativePath>../pom.xml</relativePath>
     </parent>
-    <artifactId>file-server</artifactId>
-    <name>Airavata File Server</name>
+
+    <artifactId>airavata-grpc-server</artifactId>
+    <name>Airavata gRPC Server</name>
 
     <dependencies>
+        <!-- Project modules -->
         <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-web</artifactId>
+            <groupId>org.apache.airavata</groupId>
+            <artifactId>airavata-api</artifactId>
+            <version>${project.version}</version>
             <exclusions>
                 <exclusion>
-                    <groupId>org.springframework.boot</groupId>
-                    <artifactId>spring-boot-starter-logging</artifactId>
+                    <groupId>ch.qos.logback</groupId>
+                    <artifactId>logback-classic</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>ch.qos.logback</groupId>
+                    <artifactId>logback-core</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-log4j12</artifactId>
                 </exclusion>
             </exclusions>
         </dependency>
         <dependency>
             <groupId>org.apache.airavata</groupId>
-            <artifactId>airavata-api</artifactId>
+            <artifactId>agent-service</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.airavata</groupId>
+            <artifactId>research-service</artifactId>
             <version>${project.version}</version>
+        </dependency>
+
+        <!-- gRPC -->
+        <dependency>
+            <groupId>net.devh</groupId>
+            <artifactId>grpc-server-spring-boot-starter</artifactId>
             <exclusions>
                 <exclusion>
                     <groupId>ch.qos.logback</groupId>
@@ -54,52 +78,45 @@ under the License.
                 </exclusion>
             </exclusions>
         </dependency>
+
+        <!-- Spring Boot -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-jpa</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-logging</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-actuator</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-logging</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <!-- Database -->
+        <dependency>
+            <groupId>org.mariadb.jdbc</groupId>
+            <artifactId>mariadb-java-client</artifactId>
         </dependency>
     </dependencies>
 
     <build>
         <plugins>
-            <plugin>
-                <groupId>org.springframework.boot</groupId>
-                <artifactId>spring-boot-maven-plugin</artifactId>
-            </plugin>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
                 <configuration>
-                    <compilerArgs>
-                        <arg>-parameters</arg>
-                    </compilerArgs>
+                    <release>17</release>
                 </configuration>
             </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-assembly-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>file-service-distribution-package</id>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>single</goal>
-                        </goals>
-                        <configuration>
-                            <tarLongFileMode>posix</tarLongFileMode>
-                            <finalName>${file.service.dist.name}</finalName>
-                            <descriptors>
-                                <descriptor>src/main/assembly/file-service-bin-assembly.xml</descriptor>
-                            </descriptors>
-                            <attach>false</attach>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
         </plugins>
     </build>
-
-    <properties>
-        <file.service.dist.name>apache-airavata-file-server-${project.version}</file.service.dist.name>
-    </properties>
 </project>
diff --git a/modules/restproxy/src/main/java/org/apache/airavata/restproxy/RestProxyConfiguration.java b/airavata-grpc-server/src/main/java/org/apache/airavata/grpc/server/AiravataGrpcServerConfig.java
similarity index 59%
rename from modules/restproxy/src/main/java/org/apache/airavata/restproxy/RestProxyConfiguration.java
rename to airavata-grpc-server/src/main/java/org/apache/airavata/grpc/server/AiravataGrpcServerConfig.java
index 65dbf83aa0..6bdc8c2fae 100644
--- a/modules/restproxy/src/main/java/org/apache/airavata/restproxy/RestProxyConfiguration.java
+++ b/airavata-grpc-server/src/main/java/org/apache/airavata/grpc/server/AiravataGrpcServerConfig.java
@@ -17,20 +17,19 @@
 * specific language governing permissions and limitations
 * under the License.
 */
-package org.apache.airavata.restproxy;
+package org.apache.airavata.grpc.server;
 
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.stereotype.Component;
+import org.apache.airavata.agent.connection.service.config.AgentServiceConfig;
+import org.apache.airavata.common.config.ConditionalOnServer;
+import org.apache.airavata.research.service.config.ResearchServiceConfig;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
 
-@Component
-@ConfigurationProperties
-public class RestProxyConfiguration {
-
-    @Value("${restproxy.broker.url:airavata.host:9092}")
-    private String brokerUrl;
-
-    public String getBrokerUrl() {
-        return brokerUrl;
-    }
+@Configuration
+@ConditionalOnServer("grpc")
+@Import({
+    AgentServiceConfig.class,
+    ResearchServiceConfig.class
+})
+public class AiravataGrpcServerConfig {
 }
diff --git a/airavata-grpc-server/src/main/java/org/apache/airavata/grpc/server/config/GrpcAuthInterceptor.java b/airavata-grpc-server/src/main/java/org/apache/airavata/grpc/server/config/GrpcAuthInterceptor.java
new file mode 100644
index 0000000000..142a3e78d0
--- /dev/null
+++ b/airavata-grpc-server/src/main/java/org/apache/airavata/grpc/server/config/GrpcAuthInterceptor.java
@@ -0,0 +1,104 @@
+/**
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* 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
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+package org.apache.airavata.grpc.server.config;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import io.grpc.ForwardingServerCallListener;
+import io.grpc.Metadata;
+import io.grpc.ServerCall;
+import io.grpc.ServerCallHandler;
+import io.grpc.ServerInterceptor;
+import io.grpc.Status;
+import net.devh.boot.grpc.server.interceptor.GrpcGlobalServerInterceptor;
+import org.apache.airavata.common.security.UserContext;
+import org.apache.airavata.model.security.AuthzToken;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@GrpcGlobalServerInterceptor
+public class GrpcAuthInterceptor implements ServerInterceptor {
+
+    private static final Logger log = LoggerFactory.getLogger(GrpcAuthInterceptor.class);
+    private static final ObjectMapper objectMapper = new ObjectMapper();
+
+    private static final Metadata.Key<String> AUTHORIZATION_KEY =
+            Metadata.Key.of("authorization", Metadata.ASCII_STRING_MARSHALLER);
+    private static final Metadata.Key<String> X_CLAIMS_KEY =
+            Metadata.Key.of("x-claims", Metadata.ASCII_STRING_MARSHALLER);
+
+    @Override
+    public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
+            ServerCall<ReqT, RespT> call,
+            Metadata headers,
+            ServerCallHandler<ReqT, RespT> next) {
+
+        String authHeader = headers.get(AUTHORIZATION_KEY);
+        String accessToken = null;
+        if (authHeader != null && authHeader.startsWith("Bearer ")) {
+            accessToken = authHeader.substring(7);
+        }
+
+        if (accessToken == null) {
+            call.close(Status.UNAUTHENTICATED.withDescription("Missing authorization metadata"), new Metadata());
+            return new ServerCall.Listener<>() {};
+        }
+
+        AuthzToken authzToken = new AuthzToken(accessToken);
+
+        Map<String, String> claimsMap = new HashMap<>();
+        String claimsHeader = headers.get(X_CLAIMS_KEY);
+        if (claimsHeader != null && !claimsHeader.isBlank()) {
+            try {
+                claimsMap = objectMapper.readValue(claimsHeader, new TypeReference<Map<String, String>>() {});
+            } catch (Exception e) {
+                log.warn("Failed to parse x-claims metadata: {}", e.getMessage());
+            }
+        }
+
+        authzToken.setClaimsMap(claimsMap);
+        UserContext.setAuthzToken(authzToken);
+
+        ServerCall.Listener<ReqT> delegate = next.startCall(call, headers);
+
+        return new ForwardingServerCallListener.SimpleForwardingServerCallListener<>(delegate) {
+            @Override
+            public void onComplete() {
+                try {
+                    super.onComplete();
+                } finally {
+                    UserContext.clear();
+                }
+            }
+
+            @Override
+            public void onCancel() {
+                try {
+                    super.onCancel();
+                } finally {
+                    UserContext.clear();
+                }
+            }
+        };
+    }
+}
diff --git a/modules/file-server/pom.xml b/airavata-rest-server/pom.xml
similarity index 51%
copy from modules/file-server/pom.xml
copy to airavata-rest-server/pom.xml
index 0276417a25..433a23fc2c 100644
--- a/modules/file-server/pom.xml
+++ b/airavata-rest-server/pom.xml
@@ -16,90 +16,118 @@ KIND, either express or implied. See the License for the
 specific language governing permissions and limitations
 under the License.
 -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
+
     <parent>
         <groupId>org.apache.airavata</groupId>
         <artifactId>airavata</artifactId>
         <version>0.21-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
+        <relativePath>../pom.xml</relativePath>
     </parent>
-    <artifactId>file-server</artifactId>
-    <name>Airavata File Server</name>
+
+    <artifactId>airavata-rest-server</artifactId>
+    <name>Airavata REST Server</name>
 
     <dependencies>
+        <!-- Project modules -->
         <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-web</artifactId>
+            <groupId>org.apache.airavata</groupId>
+            <artifactId>airavata-api</artifactId>
+            <version>${project.version}</version>
             <exclusions>
                 <exclusion>
-                    <groupId>org.springframework.boot</groupId>
-                    <artifactId>spring-boot-starter-logging</artifactId>
+                    <groupId>ch.qos.logback</groupId>
+                    <artifactId>logback-classic</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>ch.qos.logback</groupId>
+                    <artifactId>logback-core</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-log4j12</artifactId>
                 </exclusion>
             </exclusions>
         </dependency>
         <dependency>
             <groupId>org.apache.airavata</groupId>
-            <artifactId>airavata-api</artifactId>
+            <artifactId>research-service</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.airavata</groupId>
+            <artifactId>agent-service</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.airavata</groupId>
+            <artifactId>file-server</artifactId>
             <version>${project.version}</version>
+        </dependency>
+
+        <!-- Spring Boot -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
             <exclusions>
                 <exclusion>
-                    <groupId>ch.qos.logback</groupId>
-                    <artifactId>logback-classic</artifactId>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-logging</artifactId>
                 </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-jpa</artifactId>
+            <exclusions>
                 <exclusion>
-                    <groupId>ch.qos.logback</groupId>
-                    <artifactId>logback-core</artifactId>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-logging</artifactId>
                 </exclusion>
             </exclusions>
         </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-actuator</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-logging</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <!-- OpenAPI -->
+        <dependency>
+            <groupId>org.springdoc</groupId>
+            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
+        </dependency>
+
+        <!-- Kafka -->
+        <dependency>
+            <groupId>org.apache.kafka</groupId>
+            <artifactId>kafka-clients</artifactId>
+        </dependency>
+
+        <!-- Database -->
+        <dependency>
+            <groupId>org.mariadb.jdbc</groupId>
+            <artifactId>mariadb-java-client</artifactId>
         </dependency>
     </dependencies>
 
     <build>
         <plugins>
-            <plugin>
-                <groupId>org.springframework.boot</groupId>
-                <artifactId>spring-boot-maven-plugin</artifactId>
-            </plugin>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
                 <configuration>
-                    <compilerArgs>
-                        <arg>-parameters</arg>
-                    </compilerArgs>
+                    <release>17</release>
                 </configuration>
             </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-assembly-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>file-service-distribution-package</id>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>single</goal>
-                        </goals>
-                        <configuration>
-                            <tarLongFileMode>posix</tarLongFileMode>
-                            <finalName>${file.service.dist.name}</finalName>
-                            <descriptors>
-                                <descriptor>src/main/assembly/file-service-bin-assembly.xml</descriptor>
-                            </descriptors>
-                            <attach>false</attach>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
         </plugins>
     </build>
-
-    <properties>
-        <file.service.dist.name>apache-airavata-file-server-${project.version}</file.service.dist.name>
-    </properties>
 </project>
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/AgentServiceApplication.java b/airavata-rest-server/src/main/java/org/apache/airavata/rest/server/AiravataRestServerConfig.java
similarity index 56%
rename from modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/AgentServiceApplication.java
rename to airavata-rest-server/src/main/java/org/apache/airavata/rest/server/AiravataRestServerConfig.java
index 301fb03aad..eec0f97ca8 100644
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/AgentServiceApplication.java
+++ b/airavata-rest-server/src/main/java/org/apache/airavata/rest/server/AiravataRestServerConfig.java
@@ -17,16 +17,16 @@
 * specific language governing permissions and limitations
 * under the License.
 */
-package org.apache.airavata.agent.connection.service;
+package org.apache.airavata.rest.server;
 
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.apache.airavata.agent.connection.service.config.AgentServiceConfig;
+import org.apache.airavata.common.config.ConditionalOnServer;
+import org.apache.airavata.file.server.config.FileServerConfig;
+import org.apache.airavata.research.service.config.ResearchServiceConfig;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
 
-@SpringBootApplication
-@EnableJpaRepositories()
-public class AgentServiceApplication {
-    public static void main(String[] args) {
-        SpringApplication.run(AgentServiceApplication.class, args);
-    }
-}
+@Configuration
+@ConditionalOnServer("rest")
+@Import({ResearchServiceConfig.class, AgentServiceConfig.class, FileServerConfig.class})
+public class AiravataRestServerConfig {}
diff --git a/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/config/OpenApiConfig.java b/airavata-rest-server/src/main/java/org/apache/airavata/rest/server/config/OpenApiConfig.java
similarity index 52%
rename from modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/config/OpenApiConfig.java
rename to airavata-rest-server/src/main/java/org/apache/airavata/rest/server/config/OpenApiConfig.java
index db49d784c5..207bf18c1f 100644
--- a/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/config/OpenApiConfig.java
+++ b/airavata-rest-server/src/main/java/org/apache/airavata/rest/server/config/OpenApiConfig.java
@@ -17,18 +17,15 @@
 * specific language governing permissions and limitations
 * under the License.
 */
-package org.apache.airavata.research.service.config;
+package org.apache.airavata.rest.server.config;
 
+import io.swagger.v3.oas.models.Components;
 import io.swagger.v3.oas.models.OpenAPI;
 import io.swagger.v3.oas.models.info.Info;
-import io.swagger.v3.oas.models.media.StringSchema;
-import io.swagger.v3.oas.models.parameters.Parameter;
 import io.swagger.v3.oas.models.security.OAuthFlow;
 import io.swagger.v3.oas.models.security.OAuthFlows;
-import io.swagger.v3.oas.models.security.Scopes;
 import io.swagger.v3.oas.models.security.SecurityRequirement;
 import io.swagger.v3.oas.models.security.SecurityScheme;
-import org.springdoc.core.customizers.OpenApiCustomizer;
 import org.springdoc.core.models.GroupedOpenApi;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;
@@ -37,54 +34,57 @@ import org.springframework.context.annotation.Configuration;
 @Configuration
 public class OpenApiConfig {
 
-    @Value("${airavata.openid.url}")
-    private String openIdConfigURL;
+    @Value("${airavata.security.openid-url:}")
+    private String openIdUrl;
 
     @Bean
-    public GroupedOpenApi publicApi() {
-        return GroupedOpenApi.builder()
-                .group("public")
-                .pathsToMatch("/api/**")
-                .addOpenApiCustomizer(globalHeaderCustomizer())
-                .build();
-    }
-
-    @Bean
-    public OpenAPI researchServiceOpenAPI() {
+    public OpenAPI airavataOpenApi() {
         return new OpenAPI()
-                .info(new Info().title("Research Service API").version("1.0.0"))
-                .addSecurityItem(new SecurityRequirement().addList("oauth2-pkce"))
-                .components(new io.swagger.v3.oas.models.Components()
+                .info(new Info()
+                        .title("Airavata REST API")
+                        .version("0.21-SNAPSHOT")
+                        .description("Unified Airavata REST API"))
+                .components(new Components()
                         .addSecuritySchemes(
                                 "oauth2-pkce",
                                 new SecurityScheme()
                                         .type(SecurityScheme.Type.OAUTH2)
                                         .flows(new OAuthFlows()
                                                 .authorizationCode(new OAuthFlow()
-                                                        .authorizationUrl(
-                                                                openIdConfigURL + "/protocol/openid-connect/auth")
-                                                        .tokenUrl(openIdConfigURL + "/protocol/openid-connect/token")
-                                                        .scopes(new Scopes()
-                                                                .addString("openid", "openid")
-                                                                .addString("email", "email"))))));
+                                                        .authorizationUrl(openIdUrl + "/protocol/openid-connect/auth")
+                                                        .tokenUrl(openIdUrl + "/protocol/openid-connect/token")))))
+                .addSecurityItem(new SecurityRequirement().addList("oauth2-pkce"));
     }
 
     @Bean
-    public OpenApiCustomizer globalHeaderCustomizer() {
-        System.out.println("Applying global header customizer...");
-        return openApi -> {
-            Parameter claimsHeader = new Parameter()
-                    .in("header")
-                    .schema(new StringSchema())
-                    .name("X-Claims")
-                    .description("{userName: ..., gatewayID: ...}")
-                    .required(false);
+    public GroupedOpenApi researchGroup() {
+        return GroupedOpenApi.builder()
+                .group("research")
+                .pathsToMatch("/api/v1/rf/**")
+                .build();
+    }
 
-            openApi.getPaths().values().forEach(pathItem -> {
-                pathItem.readOperations().forEach(operation -> {
-                    operation.addParametersItem(claimsHeader);
-                });
-            });
-        };
+    @Bean
+    public GroupedOpenApi agentGroup() {
+        return GroupedOpenApi.builder()
+                .group("agent")
+                .pathsToMatch("/api/v1/agent/**", "/api/v1/plan/**", "/api/v1/exp/**")
+                .build();
+    }
+
+    @Bean
+    public GroupedOpenApi filesGroup() {
+        return GroupedOpenApi.builder()
+                .group("files")
+                .pathsToMatch("/api/v1/files/**")
+                .build();
+    }
+
+    @Bean
+    public GroupedOpenApi kafkaGroup() {
+        return GroupedOpenApi.builder()
+                .group("kafka")
+                .pathsToMatch("/api/v1/kafka/**")
+                .build();
     }
 }
diff --git a/airavata-rest-server/src/main/java/org/apache/airavata/rest/server/config/SecurityConfig.java b/airavata-rest-server/src/main/java/org/apache/airavata/rest/server/config/SecurityConfig.java
new file mode 100644
index 0000000000..8caed09b3a
--- /dev/null
+++ b/airavata-rest-server/src/main/java/org/apache/airavata/rest/server/config/SecurityConfig.java
@@ -0,0 +1,132 @@
+/**
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* 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
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+package org.apache.airavata.rest.server.config;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import org.apache.airavata.common.config.Constants;
+import org.apache.airavata.common.security.UserContext;
+import org.apache.airavata.model.security.AuthzToken;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class SecurityConfig {
+
+    private static final Logger log = LoggerFactory.getLogger(SecurityConfig.class);
+    private static final ObjectMapper objectMapper = new ObjectMapper();
+
+    private static final Set<String> SKIP_PREFIXES = Set.of("/swagger-ui", "/v3/api-docs", "/actuator");
+
+    @Bean
+    public FilterRegistrationBean<Filter> authFilter() {
+        FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>();
+        registration.setFilter(new AuthTokenFilter());
+        registration.addUrlPatterns("/api/*");
+        registration.setOrder(1);
+        return registration;
+    }
+
+    private static class AuthTokenFilter implements Filter {
+
+        @Override
+        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+                throws IOException, ServletException {
+            HttpServletRequest httpReq = (HttpServletRequest) request;
+            HttpServletResponse httpResp = (HttpServletResponse) response;
+
+            // Skip OPTIONS (CORS preflight)
+            if ("OPTIONS".equalsIgnoreCase(httpReq.getMethod())) {
+                chain.doFilter(request, response);
+                return;
+            }
+
+            // Skip swagger / api-docs / actuator
+            String path = httpReq.getRequestURI();
+            for (String prefix : SKIP_PREFIXES) {
+                if (path.startsWith(prefix)) {
+                    chain.doFilter(request, response);
+                    return;
+                }
+            }
+
+            try {
+                String authHeader = httpReq.getHeader("Authorization");
+                String accessToken = null;
+                if (authHeader != null && authHeader.startsWith("Bearer ")) {
+                    accessToken = authHeader.substring(7);
+                }
+
+                if (accessToken == null) {
+                    httpResp.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Missing Authorization header");
+                    return;
+                }
+
+                AuthzToken authzToken = new AuthzToken(accessToken);
+
+                // Parse X-Claims header if present (JSON map of claim key-values)
+                String claimsHeader = httpReq.getHeader("X-Claims");
+                Map<String, String> claimsMap = new HashMap<>();
+                if (claimsHeader != null && !claimsHeader.isBlank()) {
+                    try {
+                        claimsMap = objectMapper.readValue(claimsHeader, new TypeReference<Map<String, String>>() {});
+                    } catch (Exception e) {
+                        log.warn("Failed to parse X-Claims header: {}", e.getMessage());
+                    }
+                }
+
+                // Also accept individual headers as fallback
+                if (!claimsMap.containsKey(Constants.USER_NAME)) {
+                    String userName = httpReq.getHeader("X-User-Name");
+                    if (userName != null) {
+                        claimsMap.put(Constants.USER_NAME, userName);
+                    }
+                }
+                if (!claimsMap.containsKey(Constants.GATEWAY_ID)) {
+                    String gatewayId = httpReq.getHeader("X-Gateway-Id");
+                    if (gatewayId != null) {
+                        claimsMap.put(Constants.GATEWAY_ID, gatewayId);
+                    }
+                }
+
+                authzToken.setClaimsMap(claimsMap);
+                UserContext.setAuthzToken(authzToken);
+
+                chain.doFilter(request, response);
+            } finally {
+                UserContext.clear();
+            }
+        }
+    }
+}
diff --git a/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/config/WebMvcConfig.java b/airavata-rest-server/src/main/java/org/apache/airavata/rest/server/config/WebMvcConfig.java
similarity index 73%
rename from modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/config/WebMvcConfig.java
rename to airavata-rest-server/src/main/java/org/apache/airavata/rest/server/config/WebMvcConfig.java
index 06b393c56a..f6bc160386 100644
--- a/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/config/WebMvcConfig.java
+++ b/airavata-rest-server/src/main/java/org/apache/airavata/rest/server/config/WebMvcConfig.java
@@ -17,7 +17,7 @@
 * specific language governing permissions and limitations
 * under the License.
 */
-package org.apache.airavata.research.service.config;
+package org.apache.airavata.rest.server.config;
 
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Configuration;
@@ -27,17 +27,16 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 @Configuration
 public class WebMvcConfig implements WebMvcConfigurer {
 
-    @Value("${airavata.research-portal.url}")
-    private String deployedOrigin;
-
-    @Value("${airavata.research-portal.dev-url}")
-    private String devOrigin;
+    @Value("${airavata.cors.allowed-origins:*}")
+    private String allowedOrigins;
 
     @Override
     public void addCorsMappings(CorsRegistry registry) {
-        registry.addMapping("/**")
-                .allowedOrigins(deployedOrigin, devOrigin)
-                .allowedMethods("GET", "POST", "OPTIONS", "PATCH", "DELETE", "PUT")
-                .allowedHeaders("*");
+        registry.addMapping("/api/**")
+                .allowedOrigins(allowedOrigins.split(","))
+                .allowedMethods("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS")
+                .allowedHeaders("*")
+                .allowCredentials(true)
+                .maxAge(3600);
     }
 }
diff --git a/modules/restproxy/src/main/java/org/apache/airavata/restproxy/controller/ProxyController.java b/airavata-rest-server/src/main/java/org/apache/airavata/rest/server/controller/KafkaProxyController.java
similarity index 76%
rename from modules/restproxy/src/main/java/org/apache/airavata/restproxy/controller/ProxyController.java
rename to airavata-rest-server/src/main/java/org/apache/airavata/rest/server/controller/KafkaProxyController.java
index a7c7d8fa65..bf117c7d66 100644
--- a/modules/restproxy/src/main/java/org/apache/airavata/restproxy/controller/ProxyController.java
+++ b/airavata-rest-server/src/main/java/org/apache/airavata/rest/server/controller/KafkaProxyController.java
@@ -17,44 +17,52 @@
 * specific language governing permissions and limitations
 * under the License.
 */
-package org.apache.airavata.restproxy.controller;
+package org.apache.airavata.rest.server.controller;
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
 import java.util.Properties;
-import org.apache.airavata.restproxy.RestProxyConfiguration;
 import org.apache.kafka.clients.producer.KafkaProducer;
 import org.apache.kafka.clients.producer.ProducerConfig;
 import org.apache.kafka.clients.producer.ProducerRecord;
 import org.apache.kafka.common.serialization.StringSerializer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.*;
 
 @RestController
-public class ProxyController {
-    private static final Logger log = LoggerFactory.getLogger(ProxyController.class);
+@RequestMapping("/api/v1/kafka")
+public class KafkaProxyController {
+
+    private static final Logger log = LoggerFactory.getLogger(KafkaProxyController.class);
 
     private KafkaProducer<String, String> producer;
     private final ObjectMapper objectMapper = new ObjectMapper();
-    private final RestProxyConfiguration restProxyConfiguration;
 
-    public ProxyController(RestProxyConfiguration restProxyConfiguration) {
-        this.restProxyConfiguration = restProxyConfiguration;
-    }
+    @Value("${airavata.kafka.broker-url:localhost:9092}")
+    private String brokerUrl;
 
     @PostConstruct
     public void init() {
         Properties props = new Properties();
-        props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, restProxyConfiguration.getBrokerUrl());
-        props.put(ProducerConfig.CLIENT_ID_CONFIG, "RestProxyProducer");
+        props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, brokerUrl);
+        props.put(ProducerConfig.CLIENT_ID_CONFIG, "AiravataKafkaProxy");
         props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
         props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
         producer = new KafkaProducer<>(props);
     }
 
+    @PreDestroy
+    public void destroy() {
+        if (producer != null) {
+            producer.close();
+        }
+    }
+
     @PostMapping(value = "/topics/{topic}", consumes = "application/vnd.kafka.json.v2+json")
     public ResponseEntity<?> postToKafka(@PathVariable("topic") String topic, @RequestBody String body) {
         try {
@@ -64,16 +72,19 @@ public class ProxyController {
             }
             for (JsonNode record : root.get("records")) {
                 JsonNode valueNode = record.get("value");
-                if (valueNode == null) continue;
+                if (valueNode == null) {
+                    continue;
+                }
                 String valueStr = objectMapper.writeValueAsString(valueNode);
                 log.info("Received message for topic {}: {}", topic, valueStr);
                 var kafkaRecord = new ProducerRecord<String, String>(topic, valueStr);
                 producer.send(kafkaRecord).get();
-                log.info("RestProxyProducer posted to topic {}: {}", topic, valueStr);
+                log.info("Posted to topic {}: {}", topic, valueStr);
                 producer.flush();
             }
             return ResponseEntity.ok().build();
         } catch (Exception e) {
+            log.error("Failed to post to Kafka topic {}", topic, e);
             return ResponseEntity.internalServerError().body(e.getMessage());
         }
     }
diff --git a/modules/restproxy/pom.xml b/airavata-server/pom.xml
similarity index 58%
rename from modules/restproxy/pom.xml
rename to airavata-server/pom.xml
index 7a955a62de..3c3c88ada8 100644
--- a/modules/restproxy/pom.xml
+++ b/airavata-server/pom.xml
@@ -16,22 +16,44 @@ KIND, either express or implied. See the License for the
 specific language governing permissions and limitations
 under the License.
 -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
+
     <parent>
         <groupId>org.apache.airavata</groupId>
         <artifactId>airavata</artifactId>
         <version>0.21-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
+        <relativePath>../pom.xml</relativePath>
     </parent>
-    <artifactId>restproxy</artifactId>
-    <name>Airavata REST Proxy</name>
+
+    <artifactId>airavata-server</artifactId>
+    <name>Airavata Server</name>
+    <description>Unified launcher for all Airavata server modules</description>
 
     <dependencies>
+        <!-- Server modules -->
+        <dependency>
+            <groupId>org.apache.airavata</groupId>
+            <artifactId>airavata-rest-server</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.airavata</groupId>
+            <artifactId>airavata-grpc-server</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.airavata</groupId>
+            <artifactId>airavata-thrift-server</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <!-- Spring Boot -->
         <dependency>
             <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-web</artifactId>
+            <artifactId>spring-boot-starter</artifactId>
             <exclusions>
                 <exclusion>
                     <groupId>org.springframework.boot</groupId>
@@ -39,21 +61,9 @@ under the License.
                 </exclusion>
             </exclusions>
         </dependency>
-        <dependency>
-            <groupId>org.apache.kafka</groupId>
-            <artifactId>kafka-clients</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-databind</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>jakarta.annotation</groupId>
-            <artifactId>jakarta.annotation-api</artifactId>
-        </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-actuator</artifactId>
+            <artifactId>spring-boot-starter-log4j2</artifactId>
         </dependency>
     </dependencies>
 
@@ -65,38 +75,24 @@ under the License.
             </plugin>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
+                <artifactId>maven-assembly-plugin</artifactId>
                 <configuration>
-                    <compilerArgs>
-                        <arg>-parameters</arg>
-                    </compilerArgs>
+                    <descriptors>
+                        <descriptor>src/main/assembly/server-bin-assembly.xml</descriptor>
+                    </descriptors>
+                    <finalName>airavata-server-${project.version}</finalName>
+                    <appendAssemblyId>false</appendAssemblyId>
                 </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-assembly-plugin</artifactId>
                 <executions>
                     <execution>
-                        <id>file-service-distribution-package</id>
+                        <id>create-distribution</id>
                         <phase>package</phase>
                         <goals>
                             <goal>single</goal>
                         </goals>
-                        <configuration>
-                            <tarLongFileMode>posix</tarLongFileMode>
-                            <finalName>${restproxy.dist.name}</finalName>
-                            <descriptors>
-                                <descriptor>src/main/assembly/restproxy-bin-assembly.xml</descriptor>
-                            </descriptors>
-                            <attach>false</attach>
-                        </configuration>
                     </execution>
                 </executions>
             </plugin>
         </plugins>
     </build>
-
-    <properties>
-        <restproxy.dist.name>apache-airavata-restproxy-${project.version}</restproxy.dist.name>
-    </properties>
-</project>
\ No newline at end of file
+</project>
diff --git a/airavata-server/src/main/assembly/server-bin-assembly.xml b/airavata-server/src/main/assembly/server-bin-assembly.xml
new file mode 100644
index 0000000000..d976d54a89
--- /dev/null
+++ b/airavata-server/src/main/assembly/server-bin-assembly.xml
@@ -0,0 +1,61 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+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
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3
+                              http://maven.apache.org/xsd/assembly-1.1.3.xsd">
+    <id>bin</id>
+    <formats>
+        <format>tar.gz</format>
+    </formats>
+    <includeBaseDirectory>true</includeBaseDirectory>
+
+    <fileSets>
+        <!-- launcher script -->
+        <fileSet>
+            <directory>src/main/bin</directory>
+            <outputDirectory>bin</outputDirectory>
+            <fileMode>0755</fileMode>
+        </fileSet>
+        <!-- configuration files -->
+        <fileSet>
+            <directory>src/main/resources</directory>
+            <outputDirectory>conf</outputDirectory>
+            <includes>
+                <include>application*.yml</include>
+            </includes>
+        </fileSet>
+        <!-- empty logs directory -->
+        <fileSet>
+            <directory>.</directory>
+            <outputDirectory>logs</outputDirectory>
+            <excludes>
+                <exclude>**/*</exclude>
+            </excludes>
+        </fileSet>
+    </fileSets>
+
+    <!-- executable jar -->
+    <files>
+        <file>
+            <source>target/${project.artifactId}-${project.version}.jar</source>
+            <outputDirectory>lib</outputDirectory>
+        </file>
+    </files>
+</assembly>
diff --git a/airavata-server/src/main/bin/airavata.sh b/airavata-server/src/main/bin/airavata.sh
new file mode 100755
index 0000000000..4a12fa1e18
--- /dev/null
+++ b/airavata-server/src/main/bin/airavata.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+set -euo pipefail
+SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
+BASE_DIR="$(dirname "$SCRIPT_DIR")"
+CONF_DIR="$BASE_DIR/conf"
+LIB_DIR="$BASE_DIR/lib"
+JAVA_OPTS="${JAVA_OPTS:--Xms512m -Xmx2g}"
+exec java $JAVA_OPTS -jar "$LIB_DIR"/airavata-server-*.jar --spring.config.location="$CONF_DIR/" "$@"
diff --git a/airavata-server/src/main/java/org/apache/airavata/server/AiravataServerMain.java b/airavata-server/src/main/java/org/apache/airavata/server/AiravataServerMain.java
new file mode 100644
index 0000000000..620730e29f
--- /dev/null
+++ b/airavata-server/src/main/java/org/apache/airavata/server/AiravataServerMain.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * 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
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.airavata.server;
+
+import org.apache.airavata.common.config.AiravataServerProperties;
+import org.apache.airavata.grpc.server.AiravataGrpcServerConfig;
+import org.apache.airavata.rest.server.AiravataRestServerConfig;
+import org.apache.airavata.thrift.server.AiravataThriftServerConfig;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Import;
+
+@SpringBootApplication
+@EnableConfigurationProperties(AiravataServerProperties.class)
+@Import({
+    AiravataRestServerConfig.class,
+    AiravataGrpcServerConfig.class,
+    AiravataThriftServerConfig.class
+})
+public class AiravataServerMain {
+    public static void main(String[] args) {
+        SpringApplication.run(AiravataServerMain.class, args);
+    }
+}
diff --git a/airavata-server/src/main/resources/application-grpc.yml b/airavata-server/src/main/resources/application-grpc.yml
new file mode 100644
index 0000000000..3fb6e2171b
--- /dev/null
+++ b/airavata-server/src/main/resources/application-grpc.yml
@@ -0,0 +1,4 @@
+grpc:
+  server:
+    port: 19900
+    max-inbound-message-size: 20971520
diff --git a/airavata-server/src/main/resources/application-rest.yml b/airavata-server/src/main/resources/application-rest.yml
new file mode 100644
index 0000000000..8ece0266ff
--- /dev/null
+++ b/airavata-server/src/main/resources/application-rest.yml
@@ -0,0 +1,14 @@
+server:
+  port: 18889
+
+springdoc:
+  api-docs:
+    enabled: true
+  swagger-ui:
+    path: /swagger-ui.html
+    operationsSorter: alpha
+    tagsSorter: alpha
+    doc-expansion: none
+    oauth:
+      use-pkce-with-authorization-code-grant: true
+      client-id: data-catalog-portal
diff --git a/airavata-server/src/main/resources/application-thrift.yml b/airavata-server/src/main/resources/application-thrift.yml
new file mode 100644
index 0000000000..da6bd56712
--- /dev/null
+++ b/airavata-server/src/main/resources/application-thrift.yml
@@ -0,0 +1,4 @@
+airavata:
+  thrift:
+    port: 8930
+    min-threads: 50
diff --git a/airavata-server/src/main/resources/application.yml b/airavata-server/src/main/resources/application.yml
new file mode 100644
index 0000000000..e6e3ca7c98
--- /dev/null
+++ b/airavata-server/src/main/resources/application.yml
@@ -0,0 +1,67 @@
+airavata:
+  servers:
+    - thrift
+    - rest
+    - grpc
+
+spring:
+  datasource:
+    url: jdbc:mariadb://localhost:13306/airavata
+    username: airavata
+    password: ${AIRAVATA_DB_PASSWORD:123456}
+    driver-class-name: org.mariadb.jdbc.Driver
+    hikari:
+      pool-name: AiravataPool
+      leak-detection-threshold: 20000
+  jpa:
+    hibernate:
+      ddl-auto: update
+    open-in-view: false
+  servlet:
+    multipart:
+      max-file-size: 200MB
+      max-request-size: 200MB
+
+management:
+  endpoints:
+    web:
+      exposure:
+        include: health,info
+
+airavata.security:
+  openid-url: http://localhost:18080/realms/default
+
+airavata.cors:
+  allowed-origins: http://localhost:5173
+
+airavata.kafka:
+  broker-url: localhost:9092
+
+airavata.thrift:
+  host: localhost
+  port: 8930
+  min-threads: 50
+
+airavata.agent:
+  storage-resource-id: localhost_77116e91-f042-4d3a-ab9c-3e7b4ebcd5bd
+  storage-path: /tmp
+  cluster:
+    application-interface-id: AiravataAgent_f4313e4d-20c2-4bf6-bff1-8aa0f0b0c1d6
+  tunnel:
+    server-host: localhost
+    server-port: 17000
+    server-token: airavata
+    server-api-url: http://localhost:8000
+
+airavata.research:
+  hub-url: http://localhost:20000
+  portal-url: http://localhost:5173
+  dev-url: http://localhost:5173
+  dev-user: "airavata@apache.org"
+  admin-api-key: "JUPYTER_ADMIN_API_KEY"
+  limit: 10
+
+airavata.user-profile:
+  server:
+    url: localhost
+    port: 8930
diff --git a/airavata-thrift-server/pom.xml b/airavata-thrift-server/pom.xml
index 294e6ed356..f04088d66e 100644
--- a/airavata-thrift-server/pom.xml
+++ b/airavata-thrift-server/pom.xml
@@ -51,6 +51,16 @@ under the License.
       <groupId>org.mapstruct</groupId>
       <artifactId>mapstruct</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter</artifactId>
+      <exclusions>
+        <exclusion>
+          <groupId>org.springframework.boot</groupId>
+          <artifactId>spring-boot-starter-logging</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
   </dependencies>
 
   <build>
diff --git a/airavata-thrift-server/src/main/java/org/apache/airavata/api/server/AiravataServer.java b/airavata-thrift-server/src/main/java/org/apache/airavata/api/server/AiravataServer.java
deleted file mode 100644
index 9961c67aae..0000000000
--- a/airavata-thrift-server/src/main/java/org/apache/airavata/api/server/AiravataServer.java
+++ /dev/null
@@ -1,389 +0,0 @@
-/**
-*
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements. See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership. The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License. You may obtain a copy of the License at
-*
-* 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
-* KIND, either express or implied. See the License for the
-* specific language governing permissions and limitations
-* under the License.
-*/
-package org.apache.airavata.api.server;
-
-import java.net.InetSocketAddress;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.function.Supplier;
-import org.apache.airavata.api.Airavata;
-import org.apache.airavata.api.server.handler.AiravataServerHandler;
-import org.apache.airavata.api.server.util.Constants;
-import org.apache.airavata.common.config.ServerSettings;
-import org.apache.airavata.common.db.DBInitConfig;
-import org.apache.airavata.common.db.DBInitializer;
-import org.apache.airavata.common.exception.ApplicationSettingsException;
-import org.apache.airavata.common.server.IServer;
-import org.apache.airavata.common.server.MonitoringServer;
-import org.apache.airavata.common.server.ServiceRegistry;
-import org.apache.airavata.credential.handler.CredentialStoreServerHandler;
-import org.apache.airavata.credential.repository.util.CredentialStoreDBInitConfig;
-import org.apache.airavata.credential.store.cpi.CredentialStoreService;
-import org.apache.airavata.execution.handler.RegistryServerHandler;
-import org.apache.airavata.execution.monitor.ComputationalResourceMonitoringService;
-import org.apache.airavata.execution.monitor.EmailBasedMonitor;
-import org.apache.airavata.execution.monitor.RealtimeMonitor;
-import org.apache.airavata.execution.orchestrator.AbstractTask;
-import org.apache.airavata.execution.orchestrator.GlobalParticipant;
-import org.apache.airavata.execution.orchestrator.HelixController;
-import org.apache.airavata.execution.orchestrator.ParserWorkflowManager;
-import org.apache.airavata.execution.orchestrator.PostWorkflowManager;
-import org.apache.airavata.execution.orchestrator.PreWorkflowManager;
-import org.apache.airavata.execution.scheduler.DataInterpreterService;
-import org.apache.airavata.execution.scheduler.ProcessReschedulingService;
-import org.apache.airavata.execution.util.AppCatalogDBInitConfig;
-import org.apache.airavata.execution.util.ExpCatalogDBInitConfig;
-import org.apache.airavata.execution.util.ReplicaCatalogDBInitConfig;
-import org.apache.airavata.execution.util.WorkflowCatalogDBInitConfig;
-import org.apache.airavata.messaging.handler.DBEventManagerRunner;
-import org.apache.airavata.model.error.AiravataErrorType;
-import org.apache.airavata.model.error.AiravataSystemException;
-import org.apache.airavata.orchestrator.cpi.OrchestratorService;
-import org.apache.airavata.orchestrator.server.OrchestratorServerHandler;
-import org.apache.airavata.registry.api.RegistryService;
-import org.apache.airavata.security.profile.user.core.utils.UserProfileCatalogDBInitConfig;
-import org.apache.airavata.service.profile.groupmanager.cpi.GroupManagerService;
-import org.apache.airavata.service.profile.groupmanager.cpi.group_manager_cpiConstants;
-import org.apache.airavata.service.profile.handlers.GroupManagerServiceHandler;
-import org.apache.airavata.service.profile.handlers.IamAdminServicesHandler;
-import org.apache.airavata.service.profile.handlers.TenantProfileServiceHandler;
-import org.apache.airavata.service.profile.handlers.UserProfileServiceHandler;
-import org.apache.airavata.service.profile.iam.admin.services.cpi.IamAdminServices;
-import org.apache.airavata.service.profile.iam.admin.services.cpi.iam_admin_services_cpiConstants;
-import org.apache.airavata.service.profile.tenant.cpi.TenantProfileService;
-import org.apache.airavata.service.profile.tenant.cpi.profile_tenant_cpiConstants;
-import org.apache.airavata.service.profile.user.cpi.UserProfileService;
-import org.apache.airavata.service.profile.user.cpi.profile_user_cpiConstants;
-import org.apache.airavata.sharing.handler.SharingRegistryServerHandler;
-import org.apache.airavata.sharing.registry.service.cpi.SharingRegistryService;
-import org.apache.airavata.sharing.util.SharingRegistryDBInitConfig;
-import org.apache.thrift.TMultiplexedProcessor;
-import org.apache.thrift.server.TServer;
-import org.apache.thrift.server.TThreadPoolServer;
-import org.apache.thrift.transport.TServerSocket;
-import org.apache.thrift.transport.TServerTransport;
-import org.apache.thrift.transport.TTransportException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Consolidated Thrift server that hosts all Airavata services on a single multiplexed port.
- *
- * <p>Services registered on the TMultiplexedProcessor:
- * <ul>
- *   <li>"Airavata" → AiravataServerHandler (main API)</li>
- *   <li>"RegistryService" → RegistryServerHandler</li>
- *   <li>"SharingRegistry" → SharingRegistryServerHandler</li>
- *   <li>"CredentialStore" → CredentialStoreServerHandler</li>
- *   <li>Profile services (UserProfile, TenantProfile, IamAdminServices, GroupManager)</li>
- * </ul>
- *
- * <p>All services share the same port (default 8930, from {@code apiserver.port}).
- */
-public class AiravataServer {
-
-    private static final Logger logger = LoggerFactory.getLogger(AiravataServer.class);
-
-    private TServer server;
-    private final ServiceRegistry serviceRegistry = new ServiceRegistry();
-
-    private final List<DBInitConfig> dbInitConfigs = Arrays.asList(
-            new ExpCatalogDBInitConfig(),
-            new AppCatalogDBInitConfig(),
-            new ReplicaCatalogDBInitConfig(),
-            new WorkflowCatalogDBInitConfig(),
-            new CredentialStoreDBInitConfig(),
-            new UserProfileCatalogDBInitConfig());
-
-    public void start() throws Exception {
-        logger.info("Initializing databases...");
-        for (DBInitConfig dbInitConfig : dbInitConfigs) {
-            DBInitializer.initializeDB(dbInitConfig);
-        }
-        logger.info("Databases initialized successfully");
-
-        try {
-            final String serverHost = ServerSettings.getSetting(Constants.API_SERVER_HOST, null);
-            final int serverPort = Integer.parseInt(ServerSettings.getSetting(Constants.API_SERVER_PORT, "8930"));
-
-            // --- Instantiate handlers ---
-            CredentialStoreServerHandler credentialStoreServerHandler = new CredentialStoreServerHandler();
-            RegistryServerHandler registryServerHandler = new RegistryServerHandler();
-            SharingRegistryServerHandler sharingRegistryServerHandler =
-                    new SharingRegistryServerHandler(new SharingRegistryDBInitConfig());
-
-            // AiravataServerHandler constructor accepting in-process handler refs is added in Task 3.
-            // Until then this file will not compile.
-            AiravataServerHandler airavataServerHandler = new AiravataServerHandler(
-                    registryServerHandler, sharingRegistryServerHandler, credentialStoreServerHandler);
-            airavataServerHandler.initialize();
-
-            // --- Build processors ---
-            TMultiplexedProcessor multiplexedProcessor = new TMultiplexedProcessor();
-
-            multiplexedProcessor.registerProcessor("Airavata", new Airavata.Processor<>(airavataServerHandler));
-
-            multiplexedProcessor.registerProcessor(
-                    "RegistryService", new RegistryService.Processor<>(registryServerHandler));
-
-            multiplexedProcessor.registerProcessor(
-                    "SharingRegistry", new SharingRegistryService.Processor<>(sharingRegistryServerHandler));
-
-            multiplexedProcessor.registerProcessor(
-                    "CredentialStore", new CredentialStoreService.Processor<>(credentialStoreServerHandler));
-
-            // Profile services
-            multiplexedProcessor.registerProcessor(
-                    profile_user_cpiConstants.USER_PROFILE_CPI_NAME,
-                    new UserProfileService.Processor<>(new UserProfileServiceHandler()));
-
-            multiplexedProcessor.registerProcessor(
-                    profile_tenant_cpiConstants.TENANT_PROFILE_CPI_NAME,
-                    new TenantProfileService.Processor<>(new TenantProfileServiceHandler()));
-
-            multiplexedProcessor.registerProcessor(
-                    iam_admin_services_cpiConstants.IAM_ADMIN_SERVICES_CPI_NAME,
-                    new IamAdminServices.Processor<>(new IamAdminServicesHandler()));
-
-            multiplexedProcessor.registerProcessor(
-                    group_manager_cpiConstants.GROUP_MANAGER_CPI_NAME,
-                    new GroupManagerService.Processor<>(new GroupManagerServiceHandler()));
-
-            // Orchestrator service
-            try {
-                OrchestratorServerHandler orchestratorHandler = new OrchestratorServerHandler();
-                multiplexedProcessor.registerProcessor(
-                        "Orchestrator", new OrchestratorService.Processor<>(orchestratorHandler));
-                logger.info("Orchestrator service registered");
-            } catch (Exception e) {
-                logger.warn(
-                        "Orchestrator service failed to initialize (ZooKeeper/Helix may not be available): {}",
-                        e.getMessage());
-            }
-
-            // --- Transport and server ---
-            TServerTransport serverTransport;
-            if (serverHost == null) {
-                serverTransport = new TServerSocket(serverPort);
-            } else {
-                serverTransport = new TServerSocket(new InetSocketAddress(serverHost, serverPort));
-            }
-
-            TThreadPoolServer.Args options = new TThreadPoolServer.Args(serverTransport);
-            options.minWorkerThreads =
-                    Integer.parseInt(ServerSettings.getSetting(Constants.API_SERVER_MIN_THREADS, "50"));
-            server = new TThreadPoolServer(options.processor(multiplexedProcessor));
-
-            Thread serveThread = new Thread(
-                    () -> {
-                        server.serve();
-                        logger.info("Airavata Server stopped.");
-                    },
-                    "airavata-thrift-server");
-            serveThread.setDaemon(true);
-            serveThread.start();
-
-            new Thread(() -> {
-                        while (!server.isServing()) {
-                            try {
-                                Thread.sleep(500);
-                            } catch (InterruptedException e) {
-                                break;
-                            }
-                        }
-                        if (server.isServing()) {
-                            logger.info("Airavata Server started on port {}", serverPort);
-                            logger.info("Registered services: Airavata, RegistryService, SharingRegistry, "
-                                    + "CredentialStore, UserProfile, TenantProfile, IamAdminServices, GroupManager");
-                            startBackgroundServices();
-                        }
-                    })
-                    .start();
-
-        } catch (TTransportException | ApplicationSettingsException e) {
-            logger.error("Failed to start Airavata Server", e);
-            throw new AiravataSystemException(AiravataErrorType.INTERNAL_ERROR);
-        }
-    }
-
-    /**
-     * Starts background services after the Thrift server is ready.
-     * Each service has an independent lifecycle — failures are non-fatal
-     * and do not affect other services.
-     */
-    private void startBackgroundServices() {
-        logger.info("Starting background services...");
-
-        // DB Event Manager — processes async DB events
-        registerAndStart(new DBEventManagerRunner(), "db_event_manager");
-
-        // Monitoring Server — Prometheus metrics endpoint
-        try {
-            if (ServerSettings.getBooleanSetting("api.server.monitoring.enabled")) {
-                String monHost = ServerSettings.getSetting("api.server.monitoring.host", "localhost");
-                int monPort = Integer.parseInt(ServerSettings.getSetting("api.server.monitoring.port", "9097"));
-                MonitoringServer monitoringServer = new MonitoringServer(monHost, monPort);
-                monitoringServer.setServiceRegistry(serviceRegistry);
-                registerAndStart(monitoringServer, "monitoring_server");
-            }
-        } catch (Exception e) {
-            logger.warn("  monitoring_server: config error — {}", e.getMessage());
-            serviceRegistry.recordError("monitoring_server", e.getMessage());
-        }
-
-        // Cluster status monitoring — polls compute resource queue status
-        try {
-            if (ServerSettings.enableClusterStatusMonitoring()) {
-                registerAndStart(new ComputationalResourceMonitoringService(), "cluster_status_monitor");
-            }
-        } catch (Exception e) {
-            logger.warn("  cluster_status_monitor: config error — {}", e.getMessage());
-            serviceRegistry.recordError("cluster_status_monitor", e.getMessage());
-        }
-
-        // Data interpreter — metadata analysis for submitted jobs
-        try {
-            if (ServerSettings.enableDataAnalyzerJobScanning()) {
-                registerAndStart(new DataInterpreterService(), "data_interpreter");
-            }
-        } catch (Exception e) {
-            logger.warn("  data_interpreter: config error — {}", e.getMessage());
-            serviceRegistry.recordError("data_interpreter", e.getMessage());
-        }
-
-        // Process rescheduler — retries/reschedules failed processes
-        try {
-            if (ServerSettings.enableMetaschedulerJobScanning()) {
-                registerAndStart(new ProcessReschedulingService(), "process_rescheduler");
-            }
-        } catch (Exception e) {
-            logger.warn("  process_rescheduler: config error — {}", e.getMessage());
-            serviceRegistry.recordError("process_rescheduler", e.getMessage());
-        }
-
-        // Execution engine services — controller must initialize the cluster
-        // in ZooKeeper before participants and workflow managers can join
-        try {
-            registerAndStart(new HelixController(), "helix_controller");
-            waitForHelixCluster();
-        } catch (Exception e) {
-            logger.warn("  helix_controller: config error — {}", e.getMessage());
-            serviceRegistry.recordError("helix_controller", e.getMessage());
-        }
-        try {
-            ArrayList<Class<? extends AbstractTask>> taskClasses = new ArrayList<>();
-            for (String taskName : GlobalParticipant.TASK_CLASS_NAMES) {
-                taskClasses.add(Class.forName(taskName).asSubclass(AbstractTask.class));
-            }
-            registerAndStart(new GlobalParticipant(taskClasses, null), "helix_participant");
-        } catch (Exception e) {
-            logger.warn("  helix_participant: config error — {}", e.getMessage());
-            serviceRegistry.recordError("helix_participant", e.getMessage());
-        }
-        try {
-            registerAndStart(new PreWorkflowManager(), "pre_workflow_manager");
-        } catch (Exception e) {
-            logger.warn("  pre_workflow_manager: config error — {}", e.getMessage());
-            serviceRegistry.recordError("pre_workflow_manager", e.getMessage());
-        }
-        try {
-            registerAndStart(new PostWorkflowManager(), "post_workflow_manager");
-        } catch (Exception e) {
-            logger.warn("  post_workflow_manager: config error — {}", e.getMessage());
-            serviceRegistry.recordError("post_workflow_manager", e.getMessage());
-        }
-        try {
-            registerAndStart(new ParserWorkflowManager(), "parser_workflow_manager");
-        } catch (Exception e) {
-            logger.warn("  parser_workflow_manager: config error — {}", e.getMessage());
-            serviceRegistry.recordError("parser_workflow_manager", e.getMessage());
-        }
-
-        // Job monitors
-        try {
-            if (Boolean.parseBoolean(ServerSettings.getSetting("email.based.monitoring.enabled", "false"))) {
-                registerAndStart(new EmailBasedMonitor(), "email_monitor");
-            }
-        } catch (Exception e) {
-            logger.warn("  email_monitor: config error — {}", e.getMessage());
-            serviceRegistry.recordError("email_monitor", e.getMessage());
-        }
-        try {
-            registerAndStart(new RealtimeMonitor(), "realtime_monitor");
-        } catch (Exception e) {
-            logger.warn("  realtime_monitor: config error — {}", e.getMessage());
-            serviceRegistry.recordError("realtime_monitor", e.getMessage());
-        }
-
-        logger.info("Background services initialization complete");
-    }
-
-    private void waitForHelixCluster() {
-        String clusterName = ServerSettings.getSetting("helix.cluster.name", "AiravataCluster");
-        String zkUrl = ServerSettings.getSetting("zookeeper.server.connection", "localhost:2181");
-        logger.info("  Waiting for Helix cluster '{}' in ZooKeeper at {}...", clusterName, zkUrl);
-        for (int i = 0; i < 30; i++) {
-            try {
-                org.apache.helix.manager.zk.ZKHelixAdmin admin = new org.apache.helix.manager.zk.ZKHelixAdmin(zkUrl);
-                List<String> clusters = admin.getClusters();
-                admin.close();
-                if (clusters.contains(clusterName)) {
-                    logger.info("  Helix cluster '{}' is ready", clusterName);
-                    return;
-                }
-            } catch (Exception ignored) {
-            }
-            try {
-                Thread.sleep(1000);
-            } catch (InterruptedException e) {
-                return;
-            }
-        }
-        logger.warn("  Helix cluster '{}' not found after 30s — proceeding anyway", clusterName);
-    }
-
-    private void registerAndStart(IServer service, String label) {
-        registerAndStart(service, label, null);
-    }
-
-    private void registerAndStart(IServer service, String label, Supplier<IServer> factory) {
-        Thread t = new Thread(service, "airavata-" + label);
-        t.setDaemon(true);
-        t.start();
-        serviceRegistry.register(label, service, t, factory);
-        logger.info("  {}: started", label);
-    }
-
-    public void stop() throws Exception {
-        if (server != null && server.isServing()) {
-            server.stop();
-        }
-        serviceRegistry.stopAll();
-    }
-
-    public static void main(String[] args) {
-        try {
-            new AiravataServer().start();
-        } catch (Exception e) {
-            logger.error("Error starting Airavata Server", e);
-        }
-    }
-}
diff --git a/airavata-thrift-server/src/main/java/org/apache/airavata/api/server/handler/AiravataServerHandler.java b/airavata-thrift-server/src/main/java/org/apache/airavata/api/server/handler/AiravataServerHandler.java
index aab5021151..7489a40328 100644
--- a/airavata-thrift-server/src/main/java/org/apache/airavata/api/server/handler/AiravataServerHandler.java
+++ b/airavata-thrift-server/src/main/java/org/apache/airavata/api/server/handler/AiravataServerHandler.java
@@ -93,7 +93,11 @@ import org.apache.airavata.storage.service.DataProductService;
 import org.apache.thrift.TException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
 
+import jakarta.annotation.PostConstruct;
+
+@Component
 public class AiravataServerHandler implements Airavata.Iface {
     private static final Logger logger = LoggerFactory.getLogger(AiravataServerHandler.class);
     private Publisher statusPublisher;
@@ -155,6 +159,7 @@ public class AiravataServerHandler implements Airavata.Iface {
         this(new RegistryServerHandler(), new SharingRegistryServerHandler(), new CredentialStoreServerHandler());
     }
 
+    @PostConstruct
     public void initialize() {
         try {
             initSharingRegistry();
diff --git a/airavata-thrift-server/src/main/java/org/apache/airavata/service/profile/handlers/GroupManagerServiceHandler.java b/airavata-thrift-server/src/main/java/org/apache/airavata/service/profile/handlers/GroupManagerServiceHandler.java
index 7c505b19bf..c516376476 100644
--- a/airavata-thrift-server/src/main/java/org/apache/airavata/service/profile/handlers/GroupManagerServiceHandler.java
+++ b/airavata-thrift-server/src/main/java/org/apache/airavata/service/profile/handlers/GroupManagerServiceHandler.java
@@ -45,7 +45,9 @@ import org.apache.airavata.sharing.util.SharingRegistryServiceClientFactory;
 import org.apache.thrift.TException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
 
+@Component
 public class GroupManagerServiceHandler implements GroupManagerService.Iface {
 
     private static final Logger logger = LoggerFactory.getLogger(GroupManagerServiceHandler.class);
diff --git a/airavata-thrift-server/src/main/java/org/apache/airavata/service/profile/handlers/IamAdminServicesHandler.java b/airavata-thrift-server/src/main/java/org/apache/airavata/service/profile/handlers/IamAdminServicesHandler.java
index 39c2e0e1df..bc6b42a735 100644
--- a/airavata-thrift-server/src/main/java/org/apache/airavata/service/profile/handlers/IamAdminServicesHandler.java
+++ b/airavata-thrift-server/src/main/java/org/apache/airavata/service/profile/handlers/IamAdminServicesHandler.java
@@ -50,7 +50,9 @@ import org.apache.airavata.service.profile.iam.admin.services.cpi.iam_admin_serv
 import org.apache.thrift.TException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
 
+@Component
 public class IamAdminServicesHandler implements IamAdminServices.Iface {
 
     private static final Logger logger = LoggerFactory.getLogger(IamAdminServicesHandler.class);
diff --git a/airavata-thrift-server/src/main/java/org/apache/airavata/service/profile/handlers/TenantProfileServiceHandler.java b/airavata-thrift-server/src/main/java/org/apache/airavata/service/profile/handlers/TenantProfileServiceHandler.java
index a4d9b3a77e..e107bc323b 100644
--- a/airavata-thrift-server/src/main/java/org/apache/airavata/service/profile/handlers/TenantProfileServiceHandler.java
+++ b/airavata-thrift-server/src/main/java/org/apache/airavata/service/profile/handlers/TenantProfileServiceHandler.java
@@ -45,10 +45,12 @@ import org.apache.airavata.service.profile.tenant.cpi.profile_tenant_cpiConstant
 import org.apache.thrift.TException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
 
 /**
  * Created by goshenoy on 3/6/17.
  */
+@Component
 public class TenantProfileServiceHandler implements TenantProfileService.Iface {
 
     private static final Logger logger = LoggerFactory.getLogger(TenantProfileServiceHandler.class);
diff --git a/airavata-thrift-server/src/main/java/org/apache/airavata/service/profile/handlers/UserProfileServiceHandler.java b/airavata-thrift-server/src/main/java/org/apache/airavata/service/profile/handlers/UserProfileServiceHandler.java
index 303d5dd71b..510a438fdd 100644
--- a/airavata-thrift-server/src/main/java/org/apache/airavata/service/profile/handlers/UserProfileServiceHandler.java
+++ b/airavata-thrift-server/src/main/java/org/apache/airavata/service/profile/handlers/UserProfileServiceHandler.java
@@ -47,7 +47,9 @@ import org.apache.airavata.service.profile.user.cpi.profile_user_cpiConstants;
 import org.apache.thrift.TException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
 
+@Component
 public class UserProfileServiceHandler implements UserProfileService.Iface {
 
     private static final Logger logger = LoggerFactory.getLogger(UserProfileServiceHandler.class);
diff --git a/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/ResearchServiceApplication.java b/airavata-thrift-server/src/main/java/org/apache/airavata/thrift/server/AiravataThriftServerConfig.java
similarity index 53%
rename from modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/ResearchServiceApplication.java
rename to airavata-thrift-server/src/main/java/org/apache/airavata/thrift/server/AiravataThriftServerConfig.java
index c24f8e75c6..81af820223 100644
--- a/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/ResearchServiceApplication.java
+++ b/airavata-thrift-server/src/main/java/org/apache/airavata/thrift/server/AiravataThriftServerConfig.java
@@ -17,18 +17,22 @@
 * specific language governing permissions and limitations
 * under the License.
 */
-package org.apache.airavata.research.service;
+package org.apache.airavata.thrift.server;
 
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
-import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.apache.airavata.common.config.ConditionalOnServer;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
 
-@SpringBootApplication
-@EnableJpaRepositories()
-@EnableJpaAuditing
-public class ResearchServiceApplication {
-    public static void main(String[] args) {
-        SpringApplication.run(ResearchServiceApplication.class, args);
-    }
+@Configuration
+@ConditionalOnServer("thrift")
+@ComponentScan(basePackages = {
+    "org.apache.airavata.api.server.handler",
+    "org.apache.airavata.credential.handler",
+    "org.apache.airavata.execution.handler",
+    "org.apache.airavata.sharing.handler",
+    "org.apache.airavata.service.profile.handlers",
+    "org.apache.airavata.orchestrator.server",
+    "org.apache.airavata.thrift.server.config"
+})
+public class AiravataThriftServerConfig {
 }
diff --git a/airavata-thrift-server/src/main/java/org/apache/airavata/thrift/server/config/BackgroundServicesConfig.java b/airavata-thrift-server/src/main/java/org/apache/airavata/thrift/server/config/BackgroundServicesConfig.java
new file mode 100644
index 0000000000..0b24c263a5
--- /dev/null
+++ b/airavata-thrift-server/src/main/java/org/apache/airavata/thrift/server/config/BackgroundServicesConfig.java
@@ -0,0 +1,69 @@
+/**
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* 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
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+package org.apache.airavata.thrift.server.config;
+
+import java.util.Arrays;
+import java.util.List;
+import org.apache.airavata.common.db.DBInitConfig;
+import org.apache.airavata.common.db.DBInitializer;
+import org.apache.airavata.credential.repository.util.CredentialStoreDBInitConfig;
+import org.apache.airavata.execution.util.AppCatalogDBInitConfig;
+import org.apache.airavata.execution.util.ExpCatalogDBInitConfig;
+import org.apache.airavata.execution.util.ReplicaCatalogDBInitConfig;
+import org.apache.airavata.execution.util.WorkflowCatalogDBInitConfig;
+import org.apache.airavata.security.profile.user.core.utils.UserProfileCatalogDBInitConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.Configuration;
+
+import jakarta.annotation.PostConstruct;
+
+@Configuration
+public class BackgroundServicesConfig {
+
+    private static final Logger logger = LoggerFactory.getLogger(BackgroundServicesConfig.class);
+
+    private final List<DBInitConfig> dbInitConfigs = Arrays.asList(
+            new ExpCatalogDBInitConfig(),
+            new AppCatalogDBInitConfig(),
+            new ReplicaCatalogDBInitConfig(),
+            new WorkflowCatalogDBInitConfig(),
+            new CredentialStoreDBInitConfig(),
+            new UserProfileCatalogDBInitConfig());
+
+    @PostConstruct
+    public void initializeDatabases() {
+        logger.info("Initializing databases...");
+        for (DBInitConfig dbInitConfig : dbInitConfigs) {
+            DBInitializer.initializeDB(dbInitConfig);
+        }
+        logger.info("Databases initialized successfully");
+
+        // TODO: Migrate remaining background services to Spring-managed beans:
+        // - DBEventManagerRunner
+        // - MonitoringServer (Prometheus metrics)
+        // - ComputationalResourceMonitoringService
+        // - DataInterpreterService
+        // - ProcessReschedulingService
+        // - HelixController + GlobalParticipant
+        // - PreWorkflowManager, PostWorkflowManager, ParserWorkflowManager
+        // - EmailBasedMonitor, RealtimeMonitor
+    }
+}
diff --git a/airavata-thrift-server/src/main/java/org/apache/airavata/thrift/server/config/ThriftProcessorConfig.java b/airavata-thrift-server/src/main/java/org/apache/airavata/thrift/server/config/ThriftProcessorConfig.java
new file mode 100644
index 0000000000..7b888b1311
--- /dev/null
+++ b/airavata-thrift-server/src/main/java/org/apache/airavata/thrift/server/config/ThriftProcessorConfig.java
@@ -0,0 +1,121 @@
+/**
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* 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
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+package org.apache.airavata.thrift.server.config;
+
+import org.apache.airavata.api.Airavata;
+import org.apache.airavata.api.server.handler.AiravataServerHandler;
+import org.apache.airavata.credential.handler.CredentialStoreServerHandler;
+import org.apache.airavata.credential.store.cpi.CredentialStoreService;
+import org.apache.airavata.execution.handler.RegistryServerHandler;
+import org.apache.airavata.orchestrator.cpi.OrchestratorService;
+import org.apache.airavata.orchestrator.server.OrchestratorServerHandler;
+import org.apache.airavata.registry.api.RegistryService;
+import org.apache.airavata.service.profile.groupmanager.cpi.GroupManagerService;
+import org.apache.airavata.service.profile.groupmanager.cpi.group_manager_cpiConstants;
+import org.apache.airavata.service.profile.handlers.GroupManagerServiceHandler;
+import org.apache.airavata.service.profile.handlers.IamAdminServicesHandler;
+import org.apache.airavata.service.profile.handlers.TenantProfileServiceHandler;
+import org.apache.airavata.service.profile.handlers.UserProfileServiceHandler;
+import org.apache.airavata.service.profile.iam.admin.services.cpi.IamAdminServices;
+import org.apache.airavata.service.profile.iam.admin.services.cpi.iam_admin_services_cpiConstants;
+import org.apache.airavata.service.profile.tenant.cpi.TenantProfileService;
+import org.apache.airavata.service.profile.tenant.cpi.profile_tenant_cpiConstants;
+import org.apache.airavata.service.profile.user.cpi.UserProfileService;
+import org.apache.airavata.service.profile.user.cpi.profile_user_cpiConstants;
+import org.apache.airavata.sharing.handler.SharingRegistryServerHandler;
+import org.apache.airavata.sharing.registry.service.cpi.SharingRegistryService;
+import org.apache.thrift.TMultiplexedProcessor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class ThriftProcessorConfig {
+
+    private static final Logger logger = LoggerFactory.getLogger(ThriftProcessorConfig.class);
+
+    @Bean
+    public OrchestratorServerHandler orchestratorServerHandler() {
+        try {
+            OrchestratorServerHandler handler = new OrchestratorServerHandler();
+            logger.info("OrchestratorServerHandler initialized successfully");
+            return handler;
+        } catch (Exception e) {
+            logger.warn("Orchestrator service failed to initialize (ZooKeeper/Helix may not be available): {}",
+                    e.getMessage());
+            return null;
+        }
+    }
+
+    @Bean
+    public TMultiplexedProcessor thriftMultiplexedProcessor(
+            AiravataServerHandler airavataServerHandler,
+            RegistryServerHandler registryServerHandler,
+            SharingRegistryServerHandler sharingRegistryServerHandler,
+            CredentialStoreServerHandler credentialStoreServerHandler,
+            UserProfileServiceHandler userProfileServiceHandler,
+            TenantProfileServiceHandler tenantProfileServiceHandler,
+            IamAdminServicesHandler iamAdminServicesHandler,
+            GroupManagerServiceHandler groupManagerServiceHandler,
+            @Autowired(required = false) OrchestratorServerHandler orchestratorServerHandler) {
+
+        TMultiplexedProcessor processor = new TMultiplexedProcessor();
+
+        processor.registerProcessor("Airavata",
+                new Airavata.Processor<>(airavataServerHandler));
+
+        processor.registerProcessor("RegistryService",
+                new RegistryService.Processor<>(registryServerHandler));
+
+        processor.registerProcessor("SharingRegistry",
+                new SharingRegistryService.Processor<>(sharingRegistryServerHandler));
+
+        processor.registerProcessor("CredentialStore",
+                new CredentialStoreService.Processor<>(credentialStoreServerHandler));
+
+        processor.registerProcessor(profile_user_cpiConstants.USER_PROFILE_CPI_NAME,
+                new UserProfileService.Processor<>(userProfileServiceHandler));
+
+        processor.registerProcessor(profile_tenant_cpiConstants.TENANT_PROFILE_CPI_NAME,
+                new TenantProfileService.Processor<>(tenantProfileServiceHandler));
+
+        processor.registerProcessor(iam_admin_services_cpiConstants.IAM_ADMIN_SERVICES_CPI_NAME,
+                new IamAdminServices.Processor<>(iamAdminServicesHandler));
+
+        processor.registerProcessor(group_manager_cpiConstants.GROUP_MANAGER_CPI_NAME,
+                new GroupManagerService.Processor<>(groupManagerServiceHandler));
+
+        if (orchestratorServerHandler != null) {
+            processor.registerProcessor("Orchestrator",
+                    new OrchestratorService.Processor<>(orchestratorServerHandler));
+            logger.info("Orchestrator service registered on thrift processor");
+        } else {
+            logger.warn("Orchestrator service not available — skipping registration");
+        }
+
+        logger.info("Thrift TMultiplexedProcessor configured with services: "
+                + "Airavata, RegistryService, SharingRegistry, CredentialStore, "
+                + "UserProfile, TenantProfile, IamAdminServices, GroupManager");
+
+        return processor;
+    }
+}
diff --git a/airavata-thrift-server/src/main/java/org/apache/airavata/thrift/server/config/ThriftServerLifecycle.java b/airavata-thrift-server/src/main/java/org/apache/airavata/thrift/server/config/ThriftServerLifecycle.java
new file mode 100644
index 0000000000..9d5b1b429b
--- /dev/null
+++ b/airavata-thrift-server/src/main/java/org/apache/airavata/thrift/server/config/ThriftServerLifecycle.java
@@ -0,0 +1,106 @@
+/**
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* 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
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+package org.apache.airavata.thrift.server.config;
+
+import java.net.InetSocketAddress;
+import org.apache.thrift.TMultiplexedProcessor;
+import org.apache.thrift.server.TServer;
+import org.apache.thrift.server.TThreadPoolServer;
+import org.apache.thrift.transport.TServerSocket;
+import org.apache.thrift.transport.TServerTransport;
+import org.apache.thrift.transport.TTransportException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.SmartLifecycle;
+import org.springframework.stereotype.Component;
+
+@Component
+public class ThriftServerLifecycle implements SmartLifecycle {
+
+    private static final Logger logger = LoggerFactory.getLogger(ThriftServerLifecycle.class);
+
+    private final TMultiplexedProcessor processor;
+
+    @Value("${airavata.thrift.port:8930}")
+    private int port;
+
+    @Value("${airavata.thrift.host:#{null}}")
+    private String host;
+
+    @Value("${airavata.thrift.min-threads:50}")
+    private int minThreads;
+
+    private volatile TServer server;
+    private volatile boolean running;
+
+    public ThriftServerLifecycle(TMultiplexedProcessor processor) {
+        this.processor = processor;
+    }
+
+    @Override
+    public void start() {
+        try {
+            TServerTransport serverTransport;
+            if (host == null || host.isBlank()) {
+                serverTransport = new TServerSocket(port);
+            } else {
+                serverTransport = new TServerSocket(new InetSocketAddress(host, port));
+            }
+
+            TThreadPoolServer.Args options = new TThreadPoolServer.Args(serverTransport);
+            options.minWorkerThreads = minThreads;
+            server = new TThreadPoolServer(options.processor(processor));
+
+            Thread serveThread = new Thread(() -> {
+                logger.info("Airavata Thrift Server starting on port {}", port);
+                server.serve();
+                logger.info("Airavata Thrift Server stopped");
+            }, "airavata-thrift-server");
+            serveThread.setDaemon(true);
+            serveThread.start();
+
+            running = true;
+            logger.info("Airavata Thrift Server lifecycle started (port={})", port);
+        } catch (TTransportException e) {
+            throw new IllegalStateException("Failed to start Thrift server on port " + port, e);
+        }
+    }
+
+    @Override
+    public void stop() {
+        if (server != null && server.isServing()) {
+            server.stop();
+        }
+        running = false;
+        logger.info("Airavata Thrift Server lifecycle stopped");
+    }
+
+    @Override
+    public boolean isRunning() {
+        return running;
+    }
+
+    @Override
+    public int getPhase() {
+        // Start after other beans, stop before them
+        return Integer.MAX_VALUE - 100;
+    }
+}
diff --git a/modules/agent-framework/agent-service/pom.xml b/modules/agent-framework/agent-service/pom.xml
index 53db664256..2075ebf2b5 100644
--- a/modules/agent-framework/agent-service/pom.xml
+++ b/modules/agent-framework/agent-service/pom.xml
@@ -31,10 +31,6 @@ under the License.
   <artifactId>agent-service</artifactId>
   <name>Airavata Agent Service</name>
 
-  <properties>
-    <agent.service.dist.name>apache-airavata-agent-service-${project.version}</agent.service.dist.name>
-  </properties>
-
   <dependencies>
     <dependency>
       <groupId>org.mariadb.jdbc</groupId>
@@ -165,35 +161,10 @@ under the License.
         </exclusion>
       </exclusions>
     </dependency>
-    <dependency>
-      <groupId>org.springframework.boot</groupId>
-      <artifactId>spring-boot-starter-actuator</artifactId>
-    </dependency>
   </dependencies>
 
   <build>
     <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-assembly-plugin</artifactId>
-        <executions>
-          <execution>
-            <id>agent-service-distribution-package</id>
-            <phase>package</phase>
-            <goals>
-              <goal>single</goal>
-            </goals>
-            <configuration>
-              <tarLongFileMode>posix</tarLongFileMode>
-              <finalName>${agent.service.dist.name}</finalName>
-              <descriptors>
-                <descriptor>src/main/assembly/agent-service-bin-assembly.xml</descriptor>
-              </descriptors>
-              <attach>false</attach>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
       <plugin>
         <groupId>io.github.ascopes</groupId>
         <artifactId>protobuf-maven-plugin</artifactId>
diff --git a/modules/agent-framework/agent-service/src/main/assembly/agent-service-bin-assembly.xml b/modules/agent-framework/agent-service/src/main/assembly/agent-service-bin-assembly.xml
deleted file mode 100644
index d890127838..0000000000
--- a/modules/agent-framework/agent-service/src/main/assembly/agent-service-bin-assembly.xml
+++ /dev/null
@@ -1,76 +0,0 @@
-
-<!--
-
-    Licensed to the Apache Software Foundation (ASF) under one
-    or more contributor license agreements.  See the NOTICE file
-    distributed with this work for additional information
-    regarding copyright ownership.  The ASF licenses this file
-    to you under the Apache License, Version 2.0 (the
-    "License"); you may not use this file except in compliance
-    with the License.  You may obtain a copy of the License at
-
-      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
-    KIND, either express or implied.  See the License for the
-    specific language governing permissions and limitations
-    under the License.
-
--->
-<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.2.0"
-  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.2.0 http://maven.apache.org/xsd/assembly-2.2.0.xsd">
-  <id>bin</id>
-  <includeBaseDirectory>true</includeBaseDirectory>
-  <baseDirectory>${agent.service.dist.name}</baseDirectory>
-  <formats>
-    <format>tar.gz</format>
-  </formats>
-
-  <fileSets>
-    <fileSet>
-      <directory>src/main/resources/distribution/bin</directory>
-      <outputDirectory>bin</outputDirectory>
-      <fileMode>777</fileMode>
-      <includes>
-        <include>*.sh</include>
-      </includes>
-    </fileSet>
-    <fileSet>
-      <directory>src/main/resources/distribution/conf</directory>
-      <outputDirectory>conf</outputDirectory>
-      <includes>
-        <include>application.yml</include>
-        <include>airavata.p12</include>
-        <include>log4j2.xml</include>
-      </includes>
-    </fileSet>
-    <fileSet>
-      <directory>./</directory>
-      <outputDirectory>logs</outputDirectory>
-      <excludes>
-        <exclude>*/**</exclude>
-      </excludes>
-    </fileSet>
-    <fileSet>
-      <directory>target</directory>
-      <outputDirectory>lib</outputDirectory>
-      <includes>
-        <include>*.jar</include>
-      </includes>
-    </fileSet>
-  </fileSets>
-
-  <dependencySets>
-    <dependencySet>
-      <useProjectArtifact>false</useProjectArtifact>
-      <outputDirectory>lib</outputDirectory>
-      <includes>
-        <include>*</include>
-      </includes>
-    </dependencySet>
-  </dependencySets>
-
-</assembly>
\ No newline at end of file
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/UserContext.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/UserContext.java
deleted file mode 100644
index 0a43f0c675..0000000000
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/UserContext.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/**
-*
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements. See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership. The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License. You may obtain a copy of the License at
-*
-* 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
-* KIND, either express or implied. See the License for the
-* specific language governing permissions and limitations
-* under the License.
-*/
-package org.apache.airavata.agent.connection.service;
-
-import java.util.Map;
-import org.apache.airavata.model.security.AuthzToken;
-
-public class UserContext {
-
-    private static final ThreadLocal<AuthzToken> AUTHZ_TOKEN = new ThreadLocal<>();
-
-    public static AuthzToken authzToken() {
-        return AUTHZ_TOKEN.get();
-    }
-
-    public static void setAuthzToken(AuthzToken token) {
-        AUTHZ_TOKEN.set(token);
-    }
-
-    public static String username() {
-        return getClaim("userName");
-    }
-
-    public static String gatewayId() {
-        return getClaim("gatewayID");
-    }
-
-    private static String getClaim(String claimId) {
-        return AUTHZ_TOKEN.get().getClaimsMap().entrySet().stream()
-                .filter(entry -> entry.getKey().equalsIgnoreCase(claimId))
-                .map(Map.Entry::getValue)
-                .findFirst()
-                .orElseThrow(() ->
-                        new IllegalArgumentException("Missing '" + claimId + "' claim in the authentication token"));
-    }
-}
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/config/AgentProperties.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/config/AgentProperties.java
new file mode 100644
index 0000000000..9656de4723
--- /dev/null
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/config/AgentProperties.java
@@ -0,0 +1,35 @@
+package org.apache.airavata.agent.connection.service.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@Component
+@ConfigurationProperties(prefix = "airavata.agent")
+public class AgentProperties {
+    private String storageResourceId;
+    private String storagePath;
+    private Tunnel tunnel = new Tunnel();
+
+    public String getStorageResourceId() { return storageResourceId; }
+    public void setStorageResourceId(String s) { this.storageResourceId = s; }
+    public String getStoragePath() { return storagePath; }
+    public void setStoragePath(String s) { this.storagePath = s; }
+    public Tunnel getTunnel() { return tunnel; }
+    public void setTunnel(Tunnel t) { this.tunnel = t; }
+
+    public static class Tunnel {
+        private String serverHost;
+        private int serverPort;
+        private String serverToken;
+        private String serverApiUrl;
+
+        public String getServerHost() { return serverHost; }
+        public void setServerHost(String s) { this.serverHost = s; }
+        public int getServerPort() { return serverPort; }
+        public void setServerPort(int p) { this.serverPort = p; }
+        public String getServerToken() { return serverToken; }
+        public void setServerToken(String s) { this.serverToken = s; }
+        public String getServerApiUrl() { return serverApiUrl; }
+        public void setServerApiUrl(String s) { this.serverApiUrl = s; }
+    }
+}
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/config/AgentServiceConfig.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/config/AgentServiceConfig.java
new file mode 100644
index 0000000000..35b82a1136
--- /dev/null
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/config/AgentServiceConfig.java
@@ -0,0 +1,13 @@
+package org.apache.airavata.agent.connection.service.config;
+
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+
+@Configuration
+@ComponentScan(basePackages = "org.apache.airavata.agent.connection.service")
+@EntityScan(basePackages = "org.apache.airavata.agent.connection.service")
+@EnableJpaRepositories(basePackages = "org.apache.airavata.agent.connection.service")
+public class AgentServiceConfig {
+}
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/config/AuthzTokenFilter.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/config/AuthzTokenFilter.java
deleted file mode 100644
index afe1e44b11..0000000000
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/config/AuthzTokenFilter.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
-*
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements. See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership. The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License. You may obtain a copy of the License at
-*
-* 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
-* KIND, either express or implied. See the License for the
-* specific language governing permissions and limitations
-* under the License.
-*/
-package org.apache.airavata.agent.connection.service.config;
-
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import jakarta.servlet.FilterChain;
-import jakarta.servlet.ServletException;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.util.Map;
-import org.apache.airavata.agent.connection.service.UserContext;
-import org.apache.airavata.model.security.AuthzToken;
-import org.springframework.stereotype.Component;
-import org.springframework.web.filter.OncePerRequestFilter;
-
-@Component
-public class AuthzTokenFilter extends OncePerRequestFilter {
-
-    @Override
-    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
-            throws ServletException, IOException {
-
-        String authorizationHeader = request.getHeader("Authorization");
-        String xClaimsHeader = request.getHeader("X-Claims");
-
-        if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ") && xClaimsHeader != null) {
-            try {
-                String accessToken = authorizationHeader.substring(7); // Remove "Bearer " prefix
-                ObjectMapper objectMapper = new ObjectMapper();
-                Map<String, String> claimsMap = objectMapper.readValue(xClaimsHeader, new TypeReference<>() {});
-
-                AuthzToken authzToken = new AuthzToken();
-                authzToken.setAccessToken(accessToken);
-                authzToken.setClaimsMap(claimsMap);
-
-                UserContext.setAuthzToken(authzToken);
-            } catch (Exception e) {
-                response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid authorization data");
-                return;
-            }
-        }
-
-        filterChain.doFilter(request, response);
-    }
-}
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/controllers/PlanController.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/controllers/PlanController.java
index e99766db9d..6f70dedc18 100644
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/controllers/PlanController.java
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/controllers/PlanController.java
@@ -22,7 +22,7 @@ package org.apache.airavata.agent.connection.service.controllers;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import java.util.List;
-import org.apache.airavata.agent.connection.service.UserContext;
+import org.apache.airavata.common.security.UserContext;
 import org.apache.airavata.agent.connection.service.db.entity.Plan;
 import org.apache.airavata.agent.connection.service.handlers.PlanHandler;
 import org.slf4j.Logger;
@@ -60,7 +60,7 @@ public class PlanController {
 
             Plan plan = new Plan();
             plan.setId(planId);
-            plan.setUserId(UserContext.username());
+            plan.setUserId(UserContext.userId());
             plan.setGatewayId(UserContext.gatewayId());
             plan.setData(dataAsString);
 
@@ -75,7 +75,7 @@ public class PlanController {
 
     @GetMapping("/user")
     public ResponseEntity<List<Plan>> getPlansByUserId() {
-        List<Plan> plans = planHandler.getAllPlansByUserId(UserContext.username(), UserContext.gatewayId());
+        List<Plan> plans = planHandler.getAllPlansByUserId(UserContext.userId(), UserContext.gatewayId());
         return ResponseEntity.ok(plans);
     }
 
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/handlers/AgentConnectionHandler.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/handlers/AgentConnectionHandler.java
index 56a8f54fce..e62279a05d 100644
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/handlers/AgentConnectionHandler.java
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/handlers/AgentConnectionHandler.java
@@ -30,15 +30,17 @@ import net.devh.boot.grpc.server.service.GrpcService;
 import org.apache.airavata.agent.*;
 import org.apache.airavata.agent.AsyncCommand;
 import org.apache.airavata.agent.connection.service.models.*;
+import org.apache.airavata.agent.connection.service.config.AgentProperties;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Value;
 
 @GrpcService
 public class AgentConnectionHandler extends AgentCommunicationServiceGrpc.AgentCommunicationServiceImplBase {
 
     private static final Logger logger = LoggerFactory.getLogger(AgentConnectionHandler.class);
 
+    private final AgentProperties agentProperties;
+
     // <streamId, StreamObserver>
     private final Map<String, StreamObserver<ServerMessage>> ACTIVE_STREAMS = new ConcurrentHashMap<>();
 
@@ -57,17 +59,9 @@ public class AgentConnectionHandler extends AgentCommunicationServiceGrpc.AgentC
     private final Map<String, PythonExecutionResponse> PYTHON_EXECUTION_RESPONSE_CACHE = new ConcurrentHashMap<>();
     private final Map<String, TunnelCreationResponse> TUNNEL_CREATION_RESPONSE_CACHE = new ConcurrentHashMap<>();
 
-    @Value("${airavata.tunnel.serverHost}")
-    private String tunnelServerHost;
-
-    @Value("${airavata.tunnel.serverPort}")
-    private int tunnelServerPort;
-
-    @Value("${airavata.tunnel.serverApiUrl}")
-    private String tunnelServerApiUrl;
-
-    @Value("${airavata.tunnel.serverToken}")
-    private String tunnelServerToken;
+    public AgentConnectionHandler(AgentProperties agentProperties) {
+        this.agentProperties = agentProperties;
+    }
 
     // response handling
     public AgentInfoResponse isAgentUp(String agentId) {
@@ -479,10 +473,10 @@ public class AgentConnectionHandler extends AgentCommunicationServiceGrpc.AgentC
                                 .setExecutionId(executionId)
                                 .setLocalPort(tunnelRequest.getLocalPort())
                                 .setLocalBindHost(tunnelRequest.getLocalBindHost())
-                                .setTunnelServerHost(tunnelServerHost)
-                                .setTunnelServerPort(tunnelServerPort)
-                                .setTunnelServerApiUrl(tunnelServerApiUrl)
-                                .setTunnelServerToken(tunnelServerToken)
+                                .setTunnelServerHost(agentProperties.getTunnel().getServerHost())
+                                .setTunnelServerPort(agentProperties.getTunnel().getServerPort())
+                                .setTunnelServerApiUrl(agentProperties.getTunnel().getServerApiUrl())
+                                .setTunnelServerToken(agentProperties.getTunnel().getServerToken())
                                 .build())
                         .build());
             } catch (Exception e) {
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/handlers/AgentManagementHandler.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/handlers/AgentManagementHandler.java
index a976a7db8e..9939d25c30 100644
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/handlers/AgentManagementHandler.java
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/handlers/AgentManagementHandler.java
@@ -23,7 +23,8 @@ import java.nio.file.Paths;
 import java.util.List;
 import java.util.UUID;
 import java.util.stream.Collectors;
-import org.apache.airavata.agent.connection.service.UserContext;
+import org.apache.airavata.agent.connection.service.config.AgentProperties;
+import org.apache.airavata.common.security.UserContext;
 import org.apache.airavata.agent.connection.service.config.ClusterApplicationConfig;
 import org.apache.airavata.agent.connection.service.models.AgentLaunchRequest;
 import org.apache.airavata.agent.connection.service.models.AgentLaunchResponse;
@@ -55,19 +56,15 @@ public class AgentManagementHandler {
     private static final Logger LOGGER = LoggerFactory.getLogger(AgentManagementHandler.class);
     private final AiravataService airavataService;
     private final ClusterApplicationConfig clusterApplicationConfig;
-
-    @Value("${airavata.storageResourceId}")
-    private String storageResourceId;
-
-    @Value("${airavata.storagePath}")
-    private String storagePath;
+    private final AgentProperties agentProperties;
 
     @Value("${grpc.server.host}")
     private String grpcHost;
 
-    public AgentManagementHandler(AiravataService airavataService, ClusterApplicationConfig clusterApplicationConfig) {
+    public AgentManagementHandler(AiravataService airavataService, ClusterApplicationConfig clusterApplicationConfig, AgentProperties agentProperties) {
         this.airavataService = airavataService;
         this.clusterApplicationConfig = clusterApplicationConfig;
+        this.agentProperties = agentProperties;
     }
 
     public AgentTerminateResponse terminateExperiment(String experimentId) {
@@ -216,7 +213,7 @@ public class AgentManagementHandler {
         String projectDir = projectName.replace(" ", "_");
         String projectId = airavataService.getProjectId(airavataClient, projectName);
         AuthzToken authzToken = UserContext.authzToken();
-        String userName = UserContext.username();
+        String userName = UserContext.userId();
         String gatewayId = UserContext.gatewayId();
         String appInterfaceId = clusterApplicationConfig.getApplicationInterfaceId();
         ExperimentModel experimentModel = new ExperimentModel();
@@ -247,10 +244,10 @@ public class AgentManagementHandler {
         userConfigurationDataModel.setAiravataAutoSchedule(false);
         userConfigurationDataModel.setOverrideManualScheduledParams(false);
         userConfigurationDataModel.setInputStorageResourceId(
-                StringUtils.isNotBlank(req.getInputStorageId()) ? req.getInputStorageId() : storageResourceId);
+                StringUtils.isNotBlank(req.getInputStorageId()) ? req.getInputStorageId() : agentProperties.getStorageResourceId());
         userConfigurationDataModel.setOutputStorageResourceId(
-                StringUtils.isNotBlank(req.getOutputStorageId()) ? req.getInputStorageId() : storageResourceId);
-        String experimentDataDir = Paths.get(storagePath, gatewayId, userName, projectDir, experimentName)
+                StringUtils.isNotBlank(req.getOutputStorageId()) ? req.getInputStorageId() : agentProperties.getStorageResourceId());
+        String experimentDataDir = Paths.get(agentProperties.getStoragePath(), gatewayId, userName, projectDir, experimentName)
                 .toString();
         userConfigurationDataModel.setExperimentDataDir(experimentDataDir);
         userConfigurationDataModel.setGroupResourceProfileId(groupCompResourcePref.getGroupResourceProfileId());
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/services/AiravataFileService.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/services/AiravataFileService.java
index 0e0b61733e..cf990fc8e8 100644
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/services/AiravataFileService.java
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/services/AiravataFileService.java
@@ -28,7 +28,7 @@ import java.util.List;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import org.apache.airavata.agent.ServerMessage;
-import org.apache.airavata.agent.connection.service.UserContext;
+import org.apache.airavata.common.security.UserContext;
 import org.apache.airavata.agent.connection.service.models.DirectoryInfo;
 import org.apache.airavata.agent.connection.service.models.ExperimentStorageResponse;
 import org.apache.airavata.agent.connection.service.models.FileInfo;
diff --git a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/services/AiravataService.java b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/services/AiravataService.java
index f00d71a667..5df63cc194 100644
--- a/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/services/AiravataService.java
+++ b/modules/agent-framework/agent-service/src/main/java/org/apache/airavata/agent/connection/service/services/AiravataService.java
@@ -25,7 +25,7 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
-import org.apache.airavata.agent.connection.service.UserContext;
+import org.apache.airavata.common.security.UserContext;
 import org.apache.airavata.api.Airavata;
 import org.apache.airavata.common.util.AiravataClientFactory;
 import org.apache.airavata.model.appcatalog.groupresourceprofile.GroupComputeResourcePreference;
@@ -69,7 +69,7 @@ public class AiravataService {
 
         while (true) {
             List<Project> userProjects = airavataClient.getUserProjects(
-                    UserContext.authzToken(), UserContext.gatewayId(), UserContext.username(), limit, offset);
+                    UserContext.authzToken(), UserContext.gatewayId(), UserContext.userId(), limit, offset);
             Optional<Project> defaultProject = userProjects.stream()
                     .filter(project -> projectName.equals(project.getName()))
                     .findFirst();
@@ -84,7 +84,7 @@ public class AiravataService {
         }
 
         throw new RuntimeException(
-                "Could not find project: " + projectName + " for the user: " + UserContext.username());
+                "Could not find project: " + projectName + " for the user: " + UserContext.userId());
     }
 
     public GroupComputeResourcePreference extractGroupComputeResourcePreference(
@@ -99,7 +99,7 @@ public class AiravataService {
                         .filter(preference -> preference.getComputeResourceId().startsWith(remoteCluster)))
                 .findFirst()
                 .orElseThrow(() -> new RuntimeException("Could not find a matching Compute Resource Preference in the "
-                        + groupProfileName + " group resource profile for the user: " + UserContext.username()));
+                        + groupProfileName + " group resource profile for the user: " + UserContext.userId()));
     }
 
     public List<String> getUserExperimentIDs(Airavata.Client airavataClient) throws TException {
@@ -113,7 +113,7 @@ public class AiravataService {
                         return airavataClient.searchExperiments(
                                 UserContext.authzToken(),
                                 UserContext.gatewayId(),
-                                UserContext.username(),
+                                UserContext.userId(),
                                 filters,
                                 limit,
                                 offset);
diff --git a/modules/agent-framework/agent-service/src/main/resources/application.yml b/modules/agent-framework/agent-service/src/main/resources/application.yml
deleted file mode 100644
index 45de80b923..0000000000
--- a/modules/agent-framework/agent-service/src/main/resources/application.yml
+++ /dev/null
@@ -1,64 +0,0 @@
-#  Licensed to the Apache Software Foundation (ASF) under one or more
-#  contributor license agreements.  See the NOTICE file distributed with
-#  this work for additional information regarding copyright ownership.
-#  The ASF licenses this file to You under the Apache License, Version 2.0
-#  (the "License"); you may not use this file except in compliance with
-#  the License.  You may obtain a copy of the License at
-#
-#      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 KIND, either express or implied.
-#  See the License for the specific language governing permissions and
-#  limitations under the License.
-#
-
-grpc:
-  server:
-    host: localhost
-    port: 19900
-    max-inbound-message-size: 20971520
-
-server:
-  port: 18880
-  address: localhost
-
-spring:
-  servlet:
-    multipart:
-      max-file-size: 200MB
-      max-request-size: 200MB
-  datasource:
-    url: "jdbc:mariadb://localhost:13306/airavata"
-    username: "airavata"
-    password: "123456"
-    driver-class-name: org.mariadb.jdbc.Driver
-    hikari:
-      pool-name: AppCatalogPool
-      leak-detection-threshold: 20000
-  jpa:
-    hibernate:
-      ddl-auto: update
-    open-in-view: false
-
-airavata:
-  server:
-    url: localhost
-    port: 8930
-    secure: false
-  storageResourceId: localhost_77116e91-f042-4d3a-ab9c-3e7b4ebcd5bd
-  storagePath: /tmp
-  cluster:
-    applicationInterfaceId: AiravataAgent_f4313e4d-20c2-4bf6-bff1-8aa0f0b0c1d6
-  tunnel:
-    serverHost: localhost
-    serverPort: 17000
-    serverToken: airavata
-    serverApiUrl: http://localhost:8000
-
-management:
-  endpoints:
-    web:
-      exposure:
-        include: health
diff --git a/modules/file-server/pom.xml b/modules/file-server/pom.xml
index 0276417a25..07d8d06268 100644
--- a/modules/file-server/pom.xml
+++ b/modules/file-server/pom.xml
@@ -54,18 +54,10 @@ under the License.
                 </exclusion>
             </exclusions>
         </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-actuator</artifactId>
-        </dependency>
     </dependencies>
 
     <build>
         <plugins>
-            <plugin>
-                <groupId>org.springframework.boot</groupId>
-                <artifactId>spring-boot-maven-plugin</artifactId>
-            </plugin>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
@@ -75,31 +67,6 @@ under the License.
                     </compilerArgs>
                 </configuration>
             </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-assembly-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>file-service-distribution-package</id>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>single</goal>
-                        </goals>
-                        <configuration>
-                            <tarLongFileMode>posix</tarLongFileMode>
-                            <finalName>${file.service.dist.name}</finalName>
-                            <descriptors>
-                                <descriptor>src/main/assembly/file-service-bin-assembly.xml</descriptor>
-                            </descriptors>
-                            <attach>false</attach>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
         </plugins>
     </build>
-
-    <properties>
-        <file.service.dist.name>apache-airavata-file-server-${project.version}</file.service.dist.name>
-    </properties>
 </project>
diff --git a/modules/file-server/src/main/assembly/file-service-bin-assembly.xml b/modules/file-server/src/main/assembly/file-service-bin-assembly.xml
deleted file mode 100644
index d925f39ab5..0000000000
--- a/modules/file-server/src/main/assembly/file-service-bin-assembly.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-
-<!--
-
-    Licensed to the Apache Software Foundation (ASF) under one
-    or more contributor license agreements.  See the NOTICE file
-    distributed with this work for additional information
-    regarding copyright ownership.  The ASF licenses this file
-    to you under the Apache License, Version 2.0 (the
-    "License"); you may not use this file except in compliance
-    with the License.  You may obtain a copy of the License at
-
-      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
-    KIND, either express or implied.  See the License for the
-    specific language governing permissions and limitations
-    under the License.
-
--->
-<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.2.0"
-  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.2.0 http://maven.apache.org/xsd/assembly-2.2.0.xsd">
-  <id>bin</id>
-  <includeBaseDirectory>true</includeBaseDirectory>
-  <baseDirectory>${file.service.dist.name}</baseDirectory>
-  <formats>
-    <format>tar.gz</format>
-  </formats>
-
-  <fileSets>
-    <fileSet>
-      <directory>src/main/resources/distribution/bin</directory>
-      <outputDirectory>bin</outputDirectory>
-      <fileMode>777</fileMode>
-      <includes>
-        <include>*.sh</include>
-      </includes>
-    </fileSet>
-    <fileSet>
-      <directory>src/main/resources/distribution/conf</directory>
-      <outputDirectory>conf</outputDirectory>
-      <includes>
-        <include>application.properties</include>
-        <include>log4j2.xml</include>
-      </includes>
-    </fileSet>
-    <fileSet>
-      <directory>./</directory>
-      <outputDirectory>logs</outputDirectory>
-      <excludes>
-        <exclude>*/**</exclude>
-      </excludes>
-    </fileSet>
-    <fileSet>
-      <directory>target</directory>
-      <outputDirectory>lib</outputDirectory>
-      <includes>
-        <include>*.jar</include>
-      </includes>
-    </fileSet>
-  </fileSets>
-
-  <dependencySets>
-    <dependencySet>
-      <useProjectArtifact>false</useProjectArtifact>
-      <outputDirectory>lib</outputDirectory>
-      <includes>
-        <include>*</include>
-      </includes>
-    </dependencySet>
-  </dependencySets>
-
-</assembly>
\ No newline at end of file
diff --git a/modules/file-server/src/main/java/org/apache/airavata/file/server/FileServerApplication.java b/modules/file-server/src/main/java/org/apache/airavata/file/server/FileServerApplication.java
deleted file mode 100644
index 81561ec160..0000000000
--- a/modules/file-server/src/main/java/org/apache/airavata/file/server/FileServerApplication.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
-*
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements. See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership. The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License. You may obtain a copy of the License at
-*
-* 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
-* KIND, either express or implied. See the License for the
-* specific language governing permissions and limitations
-* under the License.
-*/
-package org.apache.airavata.file.server;
-
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-
-@SpringBootApplication(
-        scanBasePackages = "org.apache.airavata.file.server",
-        exclude = {GroovyTemplateAutoConfiguration.class})
-@EnableConfigurationProperties(FileServerConfiguration.class)
-public class FileServerApplication {
-    public static void main(String[] args) {
-        SpringApplication.run(FileServerApplication.class, args);
-    }
-}
diff --git a/modules/file-server/src/main/java/org/apache/airavata/file/server/FileServerConfiguration.java b/modules/file-server/src/main/java/org/apache/airavata/file/server/FileServerConfiguration.java
index f89823bd2e..69db3671b8 100644
--- a/modules/file-server/src/main/java/org/apache/airavata/file/server/FileServerConfiguration.java
+++ b/modules/file-server/src/main/java/org/apache/airavata/file/server/FileServerConfiguration.java
@@ -39,10 +39,10 @@ public class FileServerConfiguration {
         return AdaptorSupportImpl.getInstance();
     }
 
-    @Value("${airavata.server.host:localhost}")
+    @Value("${airavata.thrift.host:localhost}")
     private String airavataServerHost;
 
-    @Value("${airavata.server.port:8930}")
+    @Value("${airavata.thrift.port:8930}")
     private int airavataServerPort;
 
     @Bean
diff --git a/modules/file-server/src/main/java/org/apache/airavata/file/server/config/FileServerConfig.java b/modules/file-server/src/main/java/org/apache/airavata/file/server/config/FileServerConfig.java
new file mode 100644
index 0000000000..fd80405546
--- /dev/null
+++ b/modules/file-server/src/main/java/org/apache/airavata/file/server/config/FileServerConfig.java
@@ -0,0 +1,9 @@
+package org.apache.airavata.file.server.config;
+
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ComponentScan(basePackages = "org.apache.airavata.file.server")
+public class FileServerConfig {
+}
diff --git a/modules/file-server/src/main/java/org/apache/airavata/file/server/controller/FileController.java b/modules/file-server/src/main/java/org/apache/airavata/file/server/controller/FileController.java
index c433817021..fd17237392 100644
--- a/modules/file-server/src/main/java/org/apache/airavata/file/server/controller/FileController.java
+++ b/modules/file-server/src/main/java/org/apache/airavata/file/server/controller/FileController.java
@@ -30,11 +30,11 @@ import org.springframework.core.io.Resource;
 import org.springframework.core.io.UrlResource;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.ResponseEntity;
-import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
-@Controller
+@RestController
+@RequestMapping("/api/v1/files")
 public class FileController {
 
     private static final Logger logger = LoggerFactory.getLogger(FileController.class);
@@ -43,7 +43,6 @@ public class FileController {
     private AirvataFileService fileService;
 
     @GetMapping("/list/{live}/{processId}")
-    @ResponseBody
     public Object listFilesRoot(@PathVariable String live, @PathVariable String processId) throws Exception {
         String relPath = "/";
         try {
@@ -55,7 +54,6 @@ public class FileController {
     }
 
     @GetMapping("/list/{live}/{processId}/{*subPath}")
-    @ResponseBody
     public Object listFiles(@PathVariable String live, @PathVariable String processId, @PathVariable String subPath)
             throws Exception {
         String relPath = subPath.startsWith("/") ? subPath : "/" + subPath;
@@ -73,7 +71,6 @@ public class FileController {
     }
 
     @GetMapping("/download/{live}/{processId}/{*subPath}")
-    @ResponseBody
     public ResponseEntity downloadFile(
             @PathVariable String live, @PathVariable String processId, @PathVariable String subPath) {
         String relPath = subPath.startsWith("/") ? subPath : "/" + subPath;
@@ -92,7 +89,6 @@ public class FileController {
     }
 
     @PostMapping("/upload/{live}/{processId}/{*subPath}")
-    @ResponseBody
     public ResponseEntity uploadFile(
             @PathVariable String live,
             @PathVariable String processId,
diff --git a/modules/file-server/src/main/resources/application.properties b/modules/file-server/src/main/resources/application.properties
deleted file mode 100644
index 44675bb7ba..0000000000
--- a/modules/file-server/src/main/resources/application.properties
+++ /dev/null
@@ -1,10 +0,0 @@
-spring.servlet.multipart.max-file-size=10MB
-spring.servlet.multipart.max-request-size=10MB
-
-# Unified Airavata server (all services on single port)
-airavata.server.host=localhost
-airavata.server.port=8930
-
-server.port=8050
-
-management.endpoints.web.exposure.include=health
diff --git a/modules/research-framework/research-service/pom.xml b/modules/research-framework/research-service/pom.xml
index 1c799544a1..d6796746f4 100644
--- a/modules/research-framework/research-service/pom.xml
+++ b/modules/research-framework/research-service/pom.xml
@@ -31,10 +31,6 @@ under the License.
   <artifactId>research-service</artifactId>
   <name>Airavata Research Service</name>
 
-  <properties>
-    <research.service.dist.name>apache-airavata-research-service-${project.version}</research.service.dist.name>
-  </properties>
-
   <dependencies>
     <dependency>
       <groupId>org.mariadb.jdbc</groupId>
@@ -173,35 +169,10 @@ under the License.
         </exclusion>
       </exclusions>
     </dependency>
-    <dependency>
-      <groupId>org.springframework.boot</groupId>
-      <artifactId>spring-boot-starter-actuator</artifactId>
-    </dependency>
   </dependencies>
 
   <build>
     <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-assembly-plugin</artifactId>
-        <executions>
-          <execution>
-            <id>research-service-distribution-package</id>
-            <phase>package</phase>
-            <goals>
-              <goal>single</goal>
-            </goals>
-            <configuration>
-              <tarLongFileMode>posix</tarLongFileMode>
-              <finalName>${research.service.dist.name}</finalName>
-              <descriptors>
-                <descriptor>src/main/assembly/research-service-bin-assembly.xml</descriptor>
-              </descriptors>
-              <attach>false</attach>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
       <plugin>
         <groupId>io.github.ascopes</groupId>
         <artifactId>protobuf-maven-plugin</artifactId>
@@ -235,10 +206,6 @@ under the License.
           <release>17</release>
         </configuration>
       </plugin>
-      <plugin>
-        <groupId>org.springframework.boot</groupId>
-        <artifactId>spring-boot-maven-plugin</artifactId>
-      </plugin>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-surefire-plugin</artifactId>
diff --git a/modules/research-framework/research-service/src/main/assembly/research-service-bin-assembly.xml b/modules/research-framework/research-service/src/main/assembly/research-service-bin-assembly.xml
deleted file mode 100644
index 46bd0b32ff..0000000000
--- a/modules/research-framework/research-service/src/main/assembly/research-service-bin-assembly.xml
+++ /dev/null
@@ -1,76 +0,0 @@
-
-<!--
-
-    Licensed to the Apache Software Foundation (ASF) under one
-    or more contributor license agreements.  See the NOTICE file
-    distributed with this work for additional information
-    regarding copyright ownership.  The ASF licenses this file
-    to you under the Apache License, Version 2.0 (the
-    "License"); you may not use this file except in compliance
-    with the License.  You may obtain a copy of the License at
-
-      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
-    KIND, either express or implied.  See the License for the
-    specific language governing permissions and limitations
-    under the License.
-
--->
-<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.2.0"
-  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.2.0 http://maven.apache.org/xsd/assembly-2.2.0.xsd">
-  <id>bin</id>
-  <includeBaseDirectory>true</includeBaseDirectory>
-  <baseDirectory>${research.service.dist.name}</baseDirectory>
-  <formats>
-    <format>tar.gz</format>
-  </formats>
-
-  <fileSets>
-    <fileSet>
-      <directory>src/main/resources/distribution/bin</directory>
-      <outputDirectory>bin</outputDirectory>
-      <fileMode>777</fileMode>
-      <includes>
-        <include>*.sh</include>
-      </includes>
-    </fileSet>
-    <fileSet>
-      <directory>src/main/resources/distribution/conf</directory>
-      <outputDirectory>conf</outputDirectory>
-      <includes>
-        <include>application.yml</include>
-        <include>airavata.p12</include>
-        <include>log4j2.xml</include>
-      </includes>
-    </fileSet>
-    <fileSet>
-      <directory>./</directory>
-      <outputDirectory>logs</outputDirectory>
-      <excludes>
-        <exclude>*/**</exclude>
-      </excludes>
-    </fileSet>
-    <fileSet>
-      <directory>target</directory>
-      <outputDirectory>lib</outputDirectory>
-      <includes>
-        <include>*.jar</include>
-      </includes>
-    </fileSet>
-  </fileSets>
-
-  <dependencySets>
-    <dependencySet>
-      <useProjectArtifact>false</useProjectArtifact>
-      <outputDirectory>lib</outputDirectory>
-      <includes>
-        <include>*</include>
-      </includes>
-    </dependencySet>
-  </dependencySets>
-
-</assembly>
\ No newline at end of file
diff --git a/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/AiravataService.java b/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/AiravataService.java
index 67f8493ac6..2dc09ed6a5 100644
--- a/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/AiravataService.java
+++ b/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/AiravataService.java
@@ -21,7 +21,7 @@ package org.apache.airavata.research.service;
 
 import org.apache.airavata.model.security.AuthzToken;
 import org.apache.airavata.model.user.UserProfile;
-import org.apache.airavata.research.service.model.UserContext;
+import org.apache.airavata.common.security.UserContext;
 import org.apache.airavata.security.profile.client.ProfileServiceClientFactory;
 import org.apache.airavata.service.profile.user.cpi.UserProfileService;
 import org.apache.airavata.service.profile.user.cpi.exception.UserProfileServiceException;
diff --git a/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/config/AuthzTokenFilter.java b/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/config/AuthzTokenFilter.java
deleted file mode 100644
index fa55625547..0000000000
--- a/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/config/AuthzTokenFilter.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/**
-*
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements. See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership. The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License. You may obtain a copy of the License at
-*
-* 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
-* KIND, either express or implied. See the License for the
-* specific language governing permissions and limitations
-* under the License.
-*/
-package org.apache.airavata.research.service.config;
-
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import jakarta.servlet.FilterChain;
-import jakarta.servlet.ServletException;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.util.Map;
-import org.apache.airavata.model.security.AuthzToken;
-import org.apache.airavata.model.user.UserProfile;
-import org.apache.airavata.research.service.AiravataService;
-import org.apache.airavata.research.service.model.UserContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-import org.springframework.web.filter.OncePerRequestFilter;
-
-@Component
-public class AuthzTokenFilter extends OncePerRequestFilter {
-
-    private static final Logger LOGGER = LoggerFactory.getLogger(AuthzTokenFilter.class);
-    private static final String USERNAME_CLAIM = "userName";
-    private static final String GATEWAY_CLAIM = "gatewayID";
-
-    private final AiravataService airavataService;
-
-    @Value("${airavata.research-hub.url}")
-    private String csHubUrl;
-
-    public AuthzTokenFilter(AiravataService airavataService) {
-        this.airavataService = airavataService;
-    }
-
-    @Override
-    protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
-        String path = request.getRequestURI();
-
-        if (request.getMethod().equalsIgnoreCase("POST")
-                || request.getMethod().equalsIgnoreCase("PUT")
-                || request.getMethod().equalsIgnoreCase("PATCH")
-                || request.getMethod().equalsIgnoreCase("DELETE")) {
-            return false; // mutation requests should be authenticated
-        }
-
-        return path.startsWith("/swagger")
-                || path.startsWith("/v2/api-docs")
-                || path.startsWith("/v3/api-docs")
-                || path.startsWith("/swagger-ui")
-                || path.startsWith("/swagger-resources")
-                || path.startsWith("/webjars/");
-    }
-
-    @Override
-    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
-            throws ServletException, IOException {
-        try {
-            String authorizationHeader = request.getHeader("Authorization");
-            String xClaimsHeader = request.getHeader("X-Claims");
-
-            if (request.getMethod().equals("OPTIONS")) {
-                filterChain.doFilter(request, response);
-                return;
-            }
-
-            if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ") && xClaimsHeader != null) {
-                try {
-                    String accessToken = authorizationHeader.substring(7); // Remove "Bearer " prefix
-                    ObjectMapper objectMapper = new ObjectMapper();
-                    Map<String, String> claimsMap = objectMapper.readValue(xClaimsHeader, new TypeReference<>() {});
-
-                    AuthzToken authzToken = new AuthzToken();
-                    authzToken.setAccessToken(accessToken);
-                    authzToken.setClaimsMap(claimsMap);
-                    UserContext.setAuthzToken(authzToken);
-
-                    UserProfile userProfile = airavataService.getUserProfile(
-                            authzToken, getClaim(authzToken, USERNAME_CLAIM), getClaim(authzToken, GATEWAY_CLAIM));
-                    UserContext.setUser(userProfile);
-                } catch (Exception e) {
-                    LOGGER.error("Invalid authorization data", e);
-                    response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid authorization data");
-                    return;
-                }
-            }
-
-            filterChain.doFilter(request, response);
-        } finally {
-            UserContext.clear();
-        }
-    }
-
-    private static String getClaim(AuthzToken authzToken, String claimId) {
-        return authzToken.getClaimsMap().entrySet().stream()
-                .filter(entry -> entry.getKey().equalsIgnoreCase(claimId))
-                .map(Map.Entry::getValue)
-                .findFirst()
-                .orElseThrow(() ->
-                        new IllegalArgumentException("Missing '" + claimId + "' claim in the authentication token"));
-    }
-}
diff --git a/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/config/DevDataInitializer.java b/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/config/DevDataInitializer.java
index ceb321fbbf..8576d0b214 100644
--- a/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/config/DevDataInitializer.java
+++ b/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/config/DevDataInitializer.java
@@ -30,7 +30,6 @@ import org.apache.airavata.research.service.model.entity.Tag;
 import org.apache.airavata.research.service.model.repo.ProjectRepository;
 import org.apache.airavata.research.service.model.repo.ResourceRepository;
 import org.apache.airavata.research.service.model.repo.TagRepository;
-import org.springframework.beans.factory.annotation.Value;
 import org.springframework.boot.CommandLineRunner;
 import org.springframework.context.annotation.Profile;
 import org.springframework.stereotype.Component;
@@ -42,15 +41,17 @@ public class DevDataInitializer implements CommandLineRunner {
     private final ProjectRepository projectRepository;
     private final ResourceRepository resourceRepository;
     private final TagRepository tagRepository;
-
-    @Value("${airavata.research-hub.dev-user}")
-    private String devUserEmail;
+    private final ResearchProperties researchProperties;
 
     public DevDataInitializer(
-            ProjectRepository projectRepository, ResourceRepository resourceRepository, TagRepository tagRepository) {
+            ProjectRepository projectRepository,
+            ResourceRepository resourceRepository,
+            TagRepository tagRepository,
+            ResearchProperties researchProperties) {
         this.projectRepository = projectRepository;
         this.resourceRepository = resourceRepository;
         this.tagRepository = tagRepository;
+        this.researchProperties = researchProperties;
     }
 
     private void createProject(
diff --git a/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/config/ResearchProperties.java b/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/config/ResearchProperties.java
new file mode 100644
index 0000000000..f289ecabe1
--- /dev/null
+++ b/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/config/ResearchProperties.java
@@ -0,0 +1,28 @@
+package org.apache.airavata.research.service.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@Component
+@ConfigurationProperties(prefix = "airavata.research")
+public class ResearchProperties {
+    private String hubUrl;
+    private String portalUrl;
+    private String devUrl;
+    private String devUser;
+    private String adminApiKey;
+    private int limit = 10;
+
+    public String getHubUrl() { return hubUrl; }
+    public void setHubUrl(String hubUrl) { this.hubUrl = hubUrl; }
+    public String getPortalUrl() { return portalUrl; }
+    public void setPortalUrl(String portalUrl) { this.portalUrl = portalUrl; }
+    public String getDevUrl() { return devUrl; }
+    public void setDevUrl(String devUrl) { this.devUrl = devUrl; }
+    public String getDevUser() { return devUser; }
+    public void setDevUser(String devUser) { this.devUser = devUser; }
+    public String getAdminApiKey() { return adminApiKey; }
+    public void setAdminApiKey(String adminApiKey) { this.adminApiKey = adminApiKey; }
+    public int getLimit() { return limit; }
+    public void setLimit(int limit) { this.limit = limit; }
+}
diff --git a/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/config/ResearchServiceConfig.java b/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/config/ResearchServiceConfig.java
new file mode 100644
index 0000000000..2ba233945c
--- /dev/null
+++ b/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/config/ResearchServiceConfig.java
@@ -0,0 +1,15 @@
+package org.apache.airavata.research.service.config;
+
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+
+@Configuration
+@ComponentScan(basePackages = "org.apache.airavata.research.service")
+@EntityScan(basePackages = "org.apache.airavata.research.service")
+@EnableJpaRepositories(basePackages = "org.apache.airavata.research.service")
+@EnableJpaAuditing
+public class ResearchServiceConfig {
+}
diff --git a/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/controller/SessionController.java b/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/controller/SessionController.java
index 521acad8a5..4396f50c2a 100644
--- a/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/controller/SessionController.java
+++ b/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/controller/SessionController.java
@@ -24,7 +24,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
 import java.util.List;
 import org.apache.airavata.research.service.enums.SessionStatusEnum;
 import org.apache.airavata.research.service.handlers.SessionHandler;
-import org.apache.airavata.research.service.model.UserContext;
+import org.apache.airavata.common.security.UserContext;
 import org.apache.airavata.research.service.model.entity.Session;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
diff --git a/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/handlers/ProjectHandler.java b/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/handlers/ProjectHandler.java
index 9fca965303..0106ebce34 100644
--- a/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/handlers/ProjectHandler.java
+++ b/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/handlers/ProjectHandler.java
@@ -28,7 +28,7 @@ import java.util.stream.Collectors;
 import org.apache.airavata.research.service.dto.CreateProjectRequest;
 import org.apache.airavata.research.service.enums.ResourceTypeEnum;
 import org.apache.airavata.research.service.enums.StateEnum;
-import org.apache.airavata.research.service.model.UserContext;
+import org.apache.airavata.common.security.UserContext;
 import org.apache.airavata.research.service.model.entity.DatasetResource;
 import org.apache.airavata.research.service.model.entity.Project;
 import org.apache.airavata.research.service.model.entity.RepositoryResource;
diff --git a/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/handlers/ResearchHubHandler.java b/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/handlers/ResearchHubHandler.java
index 3cecf1c512..c5a583c81c 100644
--- a/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/handlers/ResearchHubHandler.java
+++ b/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/handlers/ResearchHubHandler.java
@@ -25,14 +25,14 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
 import org.apache.airavata.research.service.enums.SessionStatusEnum;
-import org.apache.airavata.research.service.model.UserContext;
+import org.apache.airavata.common.security.UserContext;
 import org.apache.airavata.research.service.model.entity.DatasetResource;
 import org.apache.airavata.research.service.model.entity.Project;
 import org.apache.airavata.research.service.model.entity.Session;
 import org.apache.airavata.research.service.model.repo.ProjectRepository;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Value;
+import org.apache.airavata.research.service.config.ResearchProperties;
 import org.springframework.http.HttpEntity;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpMethod;
@@ -53,29 +53,25 @@ public class ResearchHubHandler {
     private final ProjectHandler projectHandler;
     private final SessionHandler sessionHandler;
     private final ProjectRepository projectRepository;
-
-    @Value("${airavata.research-hub.url}")
-    private String csHubUrl;
-
-    @Value("${airavata.research-hub.adminApiKey}")
-    private String adminApiKey;
-
-    @Value("${airavata.research-hub.limit}")
-    private int maxRHubSessions;
+    private final ResearchProperties researchProperties;
 
     public ResearchHubHandler(
-            ProjectHandler projectHandler, SessionHandler sessionHandler, ProjectRepository projectRepository) {
+            ProjectHandler projectHandler,
+            SessionHandler sessionHandler,
+            ProjectRepository projectRepository,
+            ResearchProperties researchProperties) {
         this.projectHandler = projectHandler;
         this.sessionHandler = sessionHandler;
         this.projectRepository = projectRepository;
+        this.researchProperties = researchProperties;
     }
 
     public boolean stopSession(String sessionId) {
         String userId = UserContext.userId();
-        String url = String.format(SERVERS_API_URL, csHubUrl, userId, sessionId);
+        String url = String.format(SERVERS_API_URL, researchProperties.getHubUrl(), userId, sessionId);
 
         HttpHeaders headers = new HttpHeaders();
-        headers.set("Authorization", "token " + adminApiKey);
+        headers.set("Authorization", "token " + researchProperties.getAdminApiKey());
         HttpEntity<Void> request = new HttpEntity<>(headers);
 
         ResponseEntity<Void> response = new RestTemplate().exchange(url, HttpMethod.DELETE, request, Void.class);
@@ -90,10 +86,10 @@ public class ResearchHubHandler {
 
     public boolean deleteSession(String sessionId) {
         String userId = UserContext.userId();
-        String url = String.format(SERVERS_API_URL, csHubUrl, userId, sessionId);
+        String url = String.format(SERVERS_API_URL, researchProperties.getHubUrl(), userId, sessionId);
 
         HttpHeaders headers = new HttpHeaders();
-        headers.set("Authorization", "token " + adminApiKey);
+        headers.set("Authorization", "token " + researchProperties.getAdminApiKey());
 
         Map<String, Object> body = new HashMap<>();
         body.put("remove", true);
@@ -113,7 +109,7 @@ public class ResearchHubHandler {
     public String spinRHubSession(String projectId, String sessionName) {
         String userId = UserContext.userId();
         int alreadyCreated = sessionHandler.countSessionsByUserIdAndStatus(userId, SessionStatusEnum.CREATED);
-        if (alreadyCreated >= maxRHubSessions) {
+        if (alreadyCreated >= researchProperties.getLimit()) {
             throw new RuntimeException(
                     "Max number of active sessions (10) has already been reached. Please terminate or delete a session to continue.");
         }
@@ -126,7 +122,7 @@ public class ResearchHubHandler {
 
         String baseSpawnUrl = String.format(
                 RH_SPAWN_URL,
-                csHubUrl,
+                researchProperties.getHubUrl(),
                 UserContext.userId(),
                 session.getId(),
                 project.getRepositoryResource().getRepositoryUrl());
@@ -153,7 +149,7 @@ public class ResearchHubHandler {
         // TODO restrict this execution for owner
         Session session = sessionHandler.findSession(sessionId);
 
-        String sessionUrl = String.format(RH_SESSION_URL, csHubUrl, UserContext.userId(), session.getId());
+        String sessionUrl = String.format(RH_SESSION_URL, researchProperties.getHubUrl(), UserContext.userId(), session.getId());
         LOGGER.debug("Generated the session url: {} for the user: {}", sessionUrl, UserContext.userId());
         return sessionUrl;
     }
diff --git a/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/handlers/ResourceHandler.java b/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/handlers/ResourceHandler.java
index d76b11aae6..02c30e963e 100644
--- a/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/handlers/ResourceHandler.java
+++ b/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/handlers/ResourceHandler.java
@@ -34,7 +34,7 @@ import org.apache.airavata.research.service.enums.PrivacyEnum;
 import org.apache.airavata.research.service.enums.ResourceTypeEnum;
 import org.apache.airavata.research.service.enums.StateEnum;
 import org.apache.airavata.research.service.enums.StatusEnum;
-import org.apache.airavata.research.service.model.UserContext;
+import org.apache.airavata.common.security.UserContext;
 import org.apache.airavata.research.service.model.entity.RepositoryResource;
 import org.apache.airavata.research.service.model.entity.Resource;
 import org.apache.airavata.research.service.model.entity.ResourceStar;
diff --git a/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/handlers/SessionHandler.java b/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/handlers/SessionHandler.java
index ae25f0caaf..6c1d442a44 100644
--- a/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/handlers/SessionHandler.java
+++ b/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/handlers/SessionHandler.java
@@ -23,7 +23,7 @@ import jakarta.persistence.EntityNotFoundException;
 import java.util.List;
 import java.util.UUID;
 import org.apache.airavata.research.service.enums.SessionStatusEnum;
-import org.apache.airavata.research.service.model.UserContext;
+import org.apache.airavata.common.security.UserContext;
 import org.apache.airavata.research.service.model.entity.Project;
 import org.apache.airavata.research.service.model.entity.Session;
 import org.apache.airavata.research.service.model.repo.SessionRepository;
diff --git a/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/model/UserContext.java b/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/model/UserContext.java
deleted file mode 100644
index b6c1b52887..0000000000
--- a/modules/research-framework/research-service/src/main/java/org/apache/airavata/research/service/model/UserContext.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
-*
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements. See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership. The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License. You may obtain a copy of the License at
-*
-* 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
-* KIND, either express or implied. See the License for the
-* specific language governing permissions and limitations
-* under the License.
-*/
-package org.apache.airavata.research.service.model;
-
-import org.apache.airavata.model.security.AuthzToken;
-import org.apache.airavata.model.user.UserProfile;
-
-public class UserContext {
-
-    private static final ThreadLocal<AuthzToken> AUTHZ_TOKEN = new ThreadLocal<>();
-    private static final ThreadLocal<UserProfile> CURRENT_USER = new ThreadLocal<>();
-
-    public static AuthzToken authzToken() {
-        return AUTHZ_TOKEN.get();
-    }
-
-    public static void setAuthzToken(AuthzToken token) {
-        AUTHZ_TOKEN.set(token);
-    }
-
-    public static UserProfile user() {
-        return CURRENT_USER.get();
-    }
-
-    public static void setUser(UserProfile user) {
-        CURRENT_USER.set(user);
-    }
-
-    public static String userId() {
-        return CURRENT_USER.get().getUserId();
-    }
-
-    public static String gatewayId() {
-        return CURRENT_USER.get().getGatewayId();
-    }
-
-    public static boolean isAuthenticated() {
-        return AUTHZ_TOKEN.get() != null;
-    }
-
-    public static void clear() {
-        AUTHZ_TOKEN.remove();
-        CURRENT_USER.remove();
-    }
-}
diff --git a/modules/research-framework/research-service/src/main/resources/application.yml b/modules/research-framework/research-service/src/main/resources/application.yml
deleted file mode 100644
index 64657d99e0..0000000000
--- a/modules/research-framework/research-service/src/main/resources/application.yml
+++ /dev/null
@@ -1,76 +0,0 @@
-#  Licensed to the Apache Software Foundation (ASF) under one or more
-#  contributor license agreements.  See the NOTICE file distributed with
-#  this work for additional information regarding copyright ownership.
-#  The ASF licenses this file to You under the Apache License, Version 2.0
-#  (the "License"); you may not use this file except in compliance with
-#  the License.  You may obtain a copy of the License at
-#
-#      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 KIND, either express or implied.
-#  See the License for the specific language governing permissions and
-#  limitations under the License.
-#
-
-grpc:
-  server:
-    port: 19908
-
-server:
-  port: 18889
-  address: localhost
-
-airavata:
-  research-hub:
-    url: http://localhost:20000
-    dev-user: "airavata@apache.org"
-    adminApiKey: "JUPYTER_ADMIN_API_KEY"
-    limit: 10
-  research-portal:
-    url: http://localhost:5173
-    dev-url: http://localhost:5173
-  openid:
-    url: "http://localhost:18080/realms/default"
-  user-profile:
-    server:
-      url: localhost
-      port: 8930
-
-spring:
-  servlet:
-    multipart:
-      max-file-size: 200MB
-      max-request-size: 200MB
-  datasource:
-    url: "jdbc:mariadb://localhost:13306/airavata"
-    username: "airavata"
-    password: "123456"
-    driver-class-name: org.mariadb.jdbc.Driver
-    hikari:
-      pool-name: ResearchCatalogPool
-      leak-detection-threshold: 20000
-  jpa:
-    hibernate:
-      ddl-auto: update
-    open-in-view: false
-
-springdoc:
-  api-docs:
-    enabled: true
-  swagger-ui:
-    path: /swagger-ui.html
-    operationsSorter: alpha
-    tagsSorter: alpha
-    doc-expansion: none
-    oauth:
-      use-pkce-with-authorization-code-grant: true
-      client-id: data-catalog-portal
-
-management:
-  endpoints:
-    web:
-      exposure:
-        include: health
-
diff --git a/modules/restproxy/src/main/assembly/restproxy-bin-assembly.xml b/modules/restproxy/src/main/assembly/restproxy-bin-assembly.xml
deleted file mode 100644
index de44ec314e..0000000000
--- a/modules/restproxy/src/main/assembly/restproxy-bin-assembly.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-
-<!--
-
-    Licensed to the Apache Software Foundation (ASF) under one
-    or more contributor license agreements.  See the NOTICE file
-    distributed with this work for additional information
-    regarding copyright ownership.  The ASF licenses this file
-    to you under the Apache License, Version 2.0 (the
-    "License"); you may not use this file except in compliance
-    with the License.  You may obtain a copy of the License at
-
-      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
-    KIND, either express or implied.  See the License for the
-    specific language governing permissions and limitations
-    under the License.
-
--->
-<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.2.0"
-  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.2.0 http://maven.apache.org/xsd/assembly-2.2.0.xsd">
-  <id>bin</id>
-  <includeBaseDirectory>true</includeBaseDirectory>
-  <baseDirectory>${restproxy.dist.name}</baseDirectory>
-  <formats>
-    <format>tar.gz</format>
-  </formats>
-
-  <fileSets>
-    <fileSet>
-      <directory>src/main/resources/distribution/bin</directory>
-      <outputDirectory>bin</outputDirectory>
-      <fileMode>777</fileMode>
-      <includes>
-        <include>*.sh</include>
-      </includes>
-    </fileSet>
-    <fileSet>
-      <directory>src/main/resources/distribution/conf</directory>
-      <outputDirectory>conf</outputDirectory>
-      <includes>
-        <include>application.properties</include>
-        <include>log4j2.xml</include>
-      </includes>
-    </fileSet>
-    <fileSet>
-      <directory>./</directory>
-      <outputDirectory>logs</outputDirectory>
-      <excludes>
-        <exclude>*/**</exclude>
-      </excludes>
-    </fileSet>
-    <fileSet>
-      <directory>target</directory>
-      <outputDirectory>lib</outputDirectory>
-      <includes>
-        <include>*.jar</include>
-      </includes>
-    </fileSet>
-  </fileSets>
-
-  <dependencySets>
-    <dependencySet>
-      <useProjectArtifact>false</useProjectArtifact>
-      <outputDirectory>lib</outputDirectory>
-      <includes>
-        <include>*</include>
-      </includes>
-    </dependencySet>
-  </dependencySets>
-
-</assembly>
\ No newline at end of file
diff --git a/modules/restproxy/src/main/java/org/apache/airavata/restproxy/RestProxyApplication.java b/modules/restproxy/src/main/java/org/apache/airavata/restproxy/RestProxyApplication.java
deleted file mode 100644
index 9cf5dbee33..0000000000
--- a/modules/restproxy/src/main/java/org/apache/airavata/restproxy/RestProxyApplication.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
-*
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements. See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership. The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License. You may obtain a copy of the License at
-*
-* 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
-* KIND, either express or implied. See the License for the
-* specific language governing permissions and limitations
-* under the License.
-*/
-package org.apache.airavata.restproxy;
-
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-
-@SpringBootApplication
-@EnableConfigurationProperties(RestProxyConfiguration.class)
-public class RestProxyApplication {
-    public static void main(String[] args) {
-        SpringApplication.run(RestProxyApplication.class, args);
-    }
-}
diff --git a/modules/restproxy/src/main/resources/application.properties b/modules/restproxy/src/main/resources/application.properties
deleted file mode 100644
index 4c3005b8b6..0000000000
--- a/modules/restproxy/src/main/resources/application.properties
+++ /dev/null
@@ -1,4 +0,0 @@
-restproxy.broker.url=localhost:9092
-server.port=8082
-
-management.endpoints.web.exposure.include=health
diff --git a/modules/restproxy/src/main/resources/distribution/bin/restproxy.sh b/modules/restproxy/src/main/resources/distribution/bin/restproxy.sh
deleted file mode 100644
index 708d53aac4..0000000000
--- a/modules/restproxy/src/main/resources/distribution/bin/restproxy.sh
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env bash
-
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# 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
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-. $(dirname $0)/setenv.sh
-
-SERVICE_NAME="rest-proxy"
-MAIN_CLASS="org.apache.airavata.restproxy.RestProxyApplication"
-JAVA_OPTS="-Dairavata.config.dir=${AIRAVATA_HOME}/conf -Dairavata.home=${AIRAVATA_HOME} -Dlog4j.configurationFile=file:${AIRAVATA_HOME}/conf/log4j2.xml -Dspring.config.location=${AIRAVATA_HOME}/conf/"
-
-run_service "$SERVICE_NAME" "$MAIN_CLASS" "$JAVA_OPTS" "$@"
diff --git a/modules/restproxy/src/main/resources/distribution/bin/setenv.sh b/modules/restproxy/src/main/resources/distribution/bin/setenv.sh
deleted file mode 100644
index 9024de1d7b..0000000000
--- a/modules/restproxy/src/main/resources/distribution/bin/setenv.sh
+++ /dev/null
@@ -1,146 +0,0 @@
-#!/bin/bash
-
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# 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
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-# Resolve symlinks to get the real script location
-PRG="$0"
-while [ -L "$PRG" ]; do
-  PRG=$(readlink "$PRG")
-done
-PRGDIR=$(dirname "$PRG")
-
-# Set AIRAVATA_HOME if not already set
-[ -z "$AIRAVATA_HOME" ] && AIRAVATA_HOME=$(cd "$PRGDIR/.." && pwd)
-
-# Build CLASSPATH from all JAR files
-CLASSPATH=$(printf "%s:" "$AIRAVATA_HOME"/lib/*.jar)
-CLASSPATH=${CLASSPATH%:} # Remove trailing colon
-
-export AIRAVATA_HOME CLASSPATH
-
-# Common function to run Airavata services
-# Usage: run_service <service_name> <main_class> <java_opts>
-run_service() {
-  local SERVICE_NAME="$1" MAIN_CLASS="$2" JAVA_OPTS="$3"
-  # Export SERVICE_NAME as environment variable for log4j2 configuration
-  export SERVICE_NAME
-  local CWD="$PWD" PID_PATH_NAME="${AIRAVATA_HOME}/bin/pid-${SERVICE_NAME}"
-  local DEFAULT_LOG_FILE="${AIRAVATA_HOME}/logs/${SERVICE_NAME}.log"
-  local LOG_FILE="$DEFAULT_LOG_FILE" DAEMON_MODE=false EXTRA_ARGS=""
-
-  # Help text
-  local HELP_TEXT="Usage: ${SERVICE_NAME}.sh
-
-command options:
-  -d                  Run in daemon mode
-  -xdebug             Start ${SERVICE_NAME} under JPDA debugger
-  -log <LOG_FILE>     Where to redirect stdout/stderr (defaults to $DEFAULT_LOG_FILE)
-  -h                  Display this help and exit
-
-Daemon mode commands (use with -d):
-  start               Start server in daemon mode
-  stop                Stop server running in daemon mode
-  restart             Restart server in daemon mode"
-
-  cd "${AIRAVATA_HOME}/bin"
-
-  # Helper function to stop daemon process
-  stop_daemon() {
-    if [[ -f "$PID_PATH_NAME" ]]; then
-      local PID=$(cat "$PID_PATH_NAME")
-      echo "$SERVICE_NAME stopping..."
-      pkill -P "$PID"
-      kill "$PID"
-
-      local retry=0
-      while kill -0 "$PID" 2>/dev/null && ((retry++ < 20)); do
-        echo "[PID: $PID] Waiting for process to stop..."
-        sleep 1
-      done
-
-      if kill -0 "$PID" 2>/dev/null; then
-        echo "[PID: $PID] Forcefully killing non-responsive process..."
-        pkill -9 -P "$PID"
-        kill -9 "$PID"
-      fi
-
-      echo "$SERVICE_NAME is now stopped."
-      rm "$PID_PATH_NAME"
-      return 0
-    else
-      echo "$SERVICE_NAME is not running."
-      return 1
-    fi
-  }
-
-  # Helper function to start daemon process
-  start_daemon() {
-    echo "Starting $SERVICE_NAME ..."
-    if [[ ! -f "$PID_PATH_NAME" ]]; then
-      nohup java $JAVA_OPTS -classpath "$CLASSPATH" "$MAIN_CLASS" "$@" >"$LOG_FILE" 2>&1 &
-      echo $! >"$PID_PATH_NAME"
-      echo "$SERVICE_NAME now running: PID $(cat "$PID_PATH_NAME")"
-    else
-      echo "$SERVICE_NAME already running: PID $(cat "$PID_PATH_NAME")"
-    fi
-  }
-
-  # Parse command arguments
-  while (($# > 0)); do
-    case "$1" in
-    -d) DAEMON_MODE=true ;;
-    -xdebug) JAVA_OPTS+=" -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,address=*:8000" ;;
-    -log)
-      shift
-      LOG_FILE="$1"
-      [[ "$LOG_FILE" != /* ]] && LOG_FILE="${CWD}/${LOG_FILE}"
-      ;;
-    start | stop | restart)
-      if [[ "$DAEMON_MODE" == true ]]; then
-        case "$1" in
-        start) start_daemon "$@" ;;
-        stop) stop_daemon ;;
-        restart)
-          stop_daemon
-          start_daemon "$@"
-          ;;
-        esac
-        exit 0
-      else
-        EXTRA_ARGS+=" $1"
-      fi
-      ;;
-    -h)
-      echo "$HELP_TEXT"
-      exit 0
-      ;;
-    *) EXTRA_ARGS+=" $1" ;;
-    esac
-    shift
-  done
-
-  # Validate daemon mode usage
-  if [[ "$DAEMON_MODE" == true ]]; then
-    echo "Error: Daemon mode (-d) requires one of: start, stop, restart"
-    echo "Use -h for help"
-    exit 1
-  fi
-
-  # Run in foreground mode
-  java $JAVA_OPTS -classpath "$CLASSPATH" "$MAIN_CLASS" $EXTRA_ARGS
-}
diff --git a/modules/restproxy/src/main/resources/distribution/conf/.gitkeep b/modules/restproxy/src/main/resources/distribution/conf/.gitkeep
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/modules/restproxy/src/main/resources/log4j2.xml b/modules/restproxy/src/main/resources/log4j2.xml
deleted file mode 100644
index 6e085a7f43..0000000000
--- a/modules/restproxy/src/main/resources/log4j2.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
-
-    Licensed to the Apache Software Foundation (ASF) under one
-    or more contributor license agreements.  See the NOTICE file
-    distributed with this work for additional information
-    regarding copyright ownership.  The ASF licenses this file
-    to you under the Apache License, Version 2.0 (the
-    "License"); you may not use this file except in compliance
-    with the License.  You may obtain a copy of the License at
-
-      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
-    KIND, either express or implied.  See the License for the
-    specific language governing permissions and limitations
-    under the License.
-
--->
-<Configuration status="WARN">
-    <Appenders>
-        <Console name="Console" target="SYSTEM_OUT">
-            <PatternLayout pattern="%d [%t] %-5p %c{30} %X - %m%n" />
-        </Console>
-    </Appenders>
-    <Loggers>
-        <logger name="ch.qos.logback" level="WARN" />
-        <logger name="org.apache.helix" level="WARN" />
-        <logger name="org.apache.zookeeper" level="ERROR" />
-        <logger name="org.apache.airavata" level="INFO" />
-        <logger name="org.hibernate" level="ERROR" />
-        <Root level="INFO">
-            <AppenderRef ref="Console" />
-        </Root>
-    </Loggers>
-</Configuration>
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 7c9fdd3dca..95789968d7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -74,7 +74,9 @@ under the License.
         <module>modules/file-server</module>
         <module>modules/agent-framework/agent-service</module>
         <module>modules/research-framework/research-service</module>
-        <module>modules/restproxy</module>
+        <module>airavata-rest-server</module>
+        <module>airavata-grpc-server</module>
+        <module>airavata-server</module>
     </modules>
 
     <properties>
@@ -252,11 +254,6 @@ under the License.
                 <artifactId>helix-core</artifactId>
                 <version>1.4.3</version>
             </dependency>
-            <dependency>
-                <groupId>org.apache.openjpa</groupId>
-                <artifactId>openjpa</artifactId>
-                <version>4.1.1</version>
-            </dependency>
             <dependency>
                 <groupId>org.apache.shiro</groupId>
                 <artifactId>shiro-core</artifactId>
@@ -760,11 +757,6 @@ under the License.
                     <artifactId>replacer</artifactId>
                     <version>1.5.3</version>
                 </plugin>
-                <plugin>
-                    <groupId>org.apache.openjpa</groupId>
-                    <artifactId>openjpa-maven-plugin</artifactId>
-                    <version>4.1.1</version>
-                </plugin>
                 <plugin>
                     <groupId>org.codehaus.mojo</groupId>
                     <artifactId>exec-maven-plugin</artifactId>