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

yasith pushed a commit to branch worktree-reliability+server-hardening
in repository https://gitbox.apache.org/repos/asf/airavata.git

commit e22676719df381e9d3b68130fb5afd00757ba4a6
Author: yasithdev <[email protected]>
AuthorDate: Mon Mar 30 12:05:36 2026 -0400

    refactor: switch to Spring Boot auto-configured JPA, remove manual 
EntityManagerFactory
    
    Replace the manual LocalContainerEntityManagerFactoryBean with Spring Boot's
    auto-configured JPA using @EntityScan("org.apache.airavata") and
    PhysicalNamingStrategyStandardImpl (set via application.yml). This resolves 
the
    Hibernate 6.6 DuplicateMappingException by ensuring @Column and @JoinColumn
    annotations use consistent logical names.
    
    Also fix SpringSettingsBridge ordering: use constructor injection + 
@DependsOn
    on AiravataServerHandler to ensure JDBC overrides are registered before any
    bean reads airavata.jdbc.* properties.
    
    Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
---
 .../airavata/common/db/SpringSettingsBridge.java   | 27 ++++++----------
 .../apache/airavata/server/AiravataServerMain.java | 36 ++--------------------
 airavata-server/src/main/resources/application.yml |  5 +++
 .../thrift/handler/AiravataServerHandler.java      |  1 +
 4 files changed, 19 insertions(+), 50 deletions(-)

diff --git 
a/airavata-api/src/main/java/org/apache/airavata/common/db/SpringSettingsBridge.java
 
b/airavata-api/src/main/java/org/apache/airavata/common/db/SpringSettingsBridge.java
index 1c7964ea46..e2d36389e7 100644
--- 
a/airavata-api/src/main/java/org/apache/airavata/common/db/SpringSettingsBridge.java
+++ 
b/airavata-api/src/main/java/org/apache/airavata/common/db/SpringSettingsBridge.java
@@ -19,34 +19,27 @@
 */
 package org.apache.airavata.common.db;
 
-import jakarta.annotation.PostConstruct;
 import org.apache.airavata.common.config.ApplicationSettings;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.Ordered;
+import org.springframework.core.annotation.Order;
 import org.springframework.stereotype.Component;
 
 /**
  * Bridges Spring datasource configuration into {@link ApplicationSettings} so 
that legacy code
  * reading {@code airavata.jdbc.*} transparently receives the same values as
- * {@code spring.datasource.*}. This eliminates the need to duplicate JDBC 
credentials in
- * {@code airavata-server.properties}.
+ * {@code spring.datasource.*}. Runs in the constructor (not @PostConstruct) 
to ensure values
+ * are available before any other bean reads them.
  */
 @Component
+@Order(Ordered.HIGHEST_PRECEDENCE)
 public class SpringSettingsBridge {
 
-    @Value("${spring.datasource.url}")
-    private String url;
-
-    @Value("${spring.datasource.username}")
-    private String username;
-
-    @Value("${spring.datasource.password}")
-    private String password;
-
-    @Value("${spring.datasource.driver-class-name}")
-    private String driverClassName;
-
-    @PostConstruct
-    public void bridge() {
+    public SpringSettingsBridge(
+            @Value("${spring.datasource.url}") String url,
+            @Value("${spring.datasource.username}") String username,
+            @Value("${spring.datasource.password}") String password,
+            @Value("${spring.datasource.driver-class-name}") String 
driverClassName) {
         ApplicationSettings.setOverride("airavata.jdbc.url", url);
         ApplicationSettings.setOverride("airavata.jdbc.user", username);
         ApplicationSettings.setOverride("airavata.jdbc.password", password);
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
index 11d7bdcfe8..509a7159b5 100644
--- 
a/airavata-server/src/main/java/org/apache/airavata/server/AiravataServerMain.java
+++ 
b/airavata-server/src/main/java/org/apache/airavata/server/AiravataServerMain.java
@@ -19,52 +19,22 @@
 */
 package org.apache.airavata.server;
 
-import javax.sql.DataSource;
-
 import org.apache.airavata.common.config.AiravataServerProperties;
 import org.apache.airavata.server.grpc.AiravataGrpcServerConfig;
 import org.apache.airavata.server.rest.AiravataRestServerConfig;
 import org.apache.airavata.server.thrift.AiravataThriftServerConfig;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
-import 
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
 import 
org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Import;
-import org.springframework.orm.jpa.JpaTransactionManager;
-import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
-import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
-import org.springframework.transaction.PlatformTransactionManager;
-
-import jakarta.persistence.EntityManagerFactory;
 
-@SpringBootApplication(
-    scanBasePackages = {"org.apache.airavata.server", 
"org.apache.airavata.common.db"},
-    exclude = {HibernateJpaAutoConfiguration.class}
-)
+@SpringBootApplication(scanBasePackages = {"org.apache.airavata.server", 
"org.apache.airavata.common.db"})
+@EntityScan("org.apache.airavata")
 @EnableConfigurationProperties(AiravataServerProperties.class)
 @Import({AiravataRestServerConfig.class, AiravataGrpcServerConfig.class, 
AiravataThriftServerConfig.class})
 public class AiravataServerMain {
     public static void main(String[] args) {
         SpringApplication.run(AiravataServerMain.class, args);
     }
-
-    @Bean
-    public LocalContainerEntityManagerFactoryBean 
entityManagerFactory(DataSource dataSource) {
-        var em = new LocalContainerEntityManagerFactoryBean();
-        em.setDataSource(dataSource);
-        // Scan all entity packages instead of using persistence.xml
-        em.setPackagesToScan("org.apache.airavata");
-        em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
-        em.getJpaPropertyMap().put("hibernate.hbm2ddl.auto", "none");
-        em.getJpaPropertyMap().put("hibernate.enable_lazy_load_no_trans", 
"true");
-        em.getJpaPropertyMap().put("hibernate.physical_naming_strategy",
-            
"org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl");
-        return em;
-    }
-
-    @Bean
-    public PlatformTransactionManager transactionManager(EntityManagerFactory 
emf) {
-        return new JpaTransactionManager(emf);
-    }
 }
diff --git a/airavata-server/src/main/resources/application.yml 
b/airavata-server/src/main/resources/application.yml
index 57f4b02c6e..a72bb11820 100644
--- a/airavata-server/src/main/resources/application.yml
+++ b/airavata-server/src/main/resources/application.yml
@@ -16,7 +16,12 @@ spring:
   jpa:
     hibernate:
       ddl-auto: none
+      naming:
+        physical-strategy: 
org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
     open-in-view: false
+    properties:
+      hibernate:
+        enable_lazy_load_no_trans: true
   servlet:
     multipart:
       max-file-size: 200MB
diff --git 
a/airavata-server/thrift/src/main/java/org/apache/airavata/server/thrift/handler/AiravataServerHandler.java
 
b/airavata-server/thrift/src/main/java/org/apache/airavata/server/thrift/handler/AiravataServerHandler.java
index 02a7b3bb55..2854ec67c1 100644
--- 
a/airavata-server/thrift/src/main/java/org/apache/airavata/server/thrift/handler/AiravataServerHandler.java
+++ 
b/airavata-server/thrift/src/main/java/org/apache/airavata/server/thrift/handler/AiravataServerHandler.java
@@ -97,6 +97,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Component;
 
 @Component
[email protected]("springSettingsBridge")
 public class AiravataServerHandler implements Airavata.Iface {
     private static final Logger logger = 
LoggerFactory.getLogger(AiravataServerHandler.class);
     private Publisher statusPublisher;

Reply via email to