This is an automated email from the ASF dual-hosted git repository. yasith pushed a commit to branch feat/single-jvm in repository https://gitbox.apache.org/repos/asf/airavata.git
commit bb29ae7c4dae3f873906f1e95fa99ba2962906ab Author: yasithdev <[email protected]> AuthorDate: Wed Mar 25 23:35:04 2026 -0500 feat: add AiravataUnifiedServer consolidating all Thrift services Creates AiravataUnifiedServer.java hosting Airavata, RegistryService, SharingRegistry, CredentialStore, and all four profile services on a single TMultiplexedProcessor bound to port 8930 (apiserver.port). Does not compile until Task 3 adds the AiravataServerHandler constructor that accepts in-process handler references. Co-Authored-By: Claude Sonnet 4.6 <[email protected]> --- .../airavata/api/server/AiravataUnifiedServer.java | 246 +++++++++++++++++++++ 1 file changed, 246 insertions(+) diff --git a/airavata-api/src/main/java/org/apache/airavata/api/server/AiravataUnifiedServer.java b/airavata-api/src/main/java/org/apache/airavata/api/server/AiravataUnifiedServer.java new file mode 100644 index 0000000000..f2dc3e045c --- /dev/null +++ b/airavata-api/src/main/java/org/apache/airavata/api/server/AiravataUnifiedServer.java @@ -0,0 +1,246 @@ +/** +* +* 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.Arrays; +import java.util.List; +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.exception.ApplicationSettingsException; +import org.apache.airavata.common.utils.DBInitConfig; +import org.apache.airavata.common.utils.DBInitializer; +import org.apache.airavata.common.utils.IServer; +import org.apache.airavata.common.utils.ServerSettings; +import org.apache.airavata.credential.store.cpi.CredentialStoreService; +import org.apache.airavata.credential.store.server.CredentialStoreServerHandler; +import org.apache.airavata.model.error.AiravataErrorType; +import org.apache.airavata.model.error.AiravataSystemException; +import org.apache.airavata.registry.api.RegistryService; +import org.apache.airavata.registry.api.service.handler.RegistryServerHandler; +import org.apache.airavata.registry.core.utils.AppCatalogDBInitConfig; +import org.apache.airavata.registry.core.utils.ExpCatalogDBInitConfig; +import org.apache.airavata.registry.core.utils.ReplicaCatalogDBInitConfig; +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.core.utils.UserProfileCatalogDBInitConfig; +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.registry.db.utils.SharingRegistryDBInitConfig; +import org.apache.airavata.sharing.registry.server.SharingRegistryServerHandler; +import org.apache.airavata.sharing.registry.service.cpi.SharingRegistryService; +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 AiravataUnifiedServer implements IServer { + + private static final Logger logger = LoggerFactory.getLogger(AiravataUnifiedServer.class); + private static final String SERVER_NAME = "Airavata Unified Server"; + private static final String SERVER_VERSION = "1.0"; + + private ServerStatus status; + private TServer server; + + private final List<DBInitConfig> dbInitConfigs = Arrays.asList( + new ExpCatalogDBInitConfig(), + new AppCatalogDBInitConfig(), + new ReplicaCatalogDBInitConfig(), + new UserProfileCatalogDBInitConfig()); + + public AiravataUnifiedServer() { + setStatus(ServerStatus.STOPPED); + } + + @Override + public void start() throws Exception { + setStatus(ServerStatus.STARTING); + + 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( + credentialStoreServerHandler, registryServerHandler, sharingRegistryServerHandler); + + // --- 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 (multiplexed on the same port as the existing ProfileServiceServer) + 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())); + + // --- 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)); + + new Thread(() -> { + server.serve(); + setStatus(ServerStatus.STOPPED); + logger.info("Airavata Unified Server stopped."); + }) + .start(); + + new Thread(() -> { + while (!server.isServing()) { + try { + Thread.sleep(500); + } catch (InterruptedException e) { + break; + } + } + if (server.isServing()) { + setStatus(ServerStatus.STARTED); + logger.info("Airavata Unified Server started on port {}", serverPort); + logger.info("Registered services: Airavata, RegistryService, SharingRegistry, " + + "CredentialStore, UserProfile, TenantProfile, IamAdminServices, GroupManager"); + } + }) + .start(); + + } catch (TTransportException | ApplicationSettingsException e) { + logger.error("Failed to start Airavata Unified Server", e); + setStatus(ServerStatus.FAILED); + throw new AiravataSystemException(AiravataErrorType.INTERNAL_ERROR); + } + } + + @Override + public void stop() throws Exception { + if (server != null && server.isServing()) { + setStatus(ServerStatus.STOPING); + server.stop(); + } + } + + @Override + public void restart() throws Exception { + stop(); + start(); + } + + @Override + public void configure() throws Exception {} + + @Override + public ServerStatus getStatus() throws Exception { + return status; + } + + @Override + public String getName() { + return SERVER_NAME; + } + + @Override + public String getVersion() { + return SERVER_VERSION; + } + + private void setStatus(ServerStatus stat) { + status = stat; + status.updateTime(); + } + + public static void main(String[] args) { + try { + new AiravataUnifiedServer().start(); + } catch (Exception e) { + logger.error("Error starting Airavata Unified Server", e); + } + } +}
