1

I'm working on a multi project build using Spring Boot 2.1.5.RELEASE.

I shared an example at https://github.com/MBurchard/ACME

When running the test cases from the storage sub project, all YAML configurations from inside the storage project are found and used.

When running SpringBootApplication from web project with profile dev it shows an error.

spring:
  # PROFILES
  profiles:
    active: ${profile:dev}

Error cause

Caused by: java.lang.IllegalArgumentException: Not a managed type: class de.mbur.acme.User
at org.hibernate.metamodel.internal.MetamodelImpl.managedType(MetamodelImpl.java:552) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final]
at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.<init>(JpaMetamodelEntityInformation.java:74) ~[spring-data-jpa-2.1.8.RELEASE.jar:2.1.8.RELEASE]
at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getEntityInformation(JpaEntityInformationSupport.java:66) ~[spring-data-jpa-2.1.8.RELEASE.jar:2.1.8.RELEASE]

The reason is clear. it does not use the application.yml from the storage project.

When switching to dev-full-config everythink works fine

spring:
  # PROFILES
  profiles:
    active: ${profile:dev-full-config}

But I don't want to repeat the full configuraton for the database that is more or less internal.

What can I do to get this work without repeating the internal database configuration?

Nabor
  • 1,661
  • 3
  • 20
  • 45
  • I believe this is the solution may help you: https://stackoverflow.com/questions/30198688/merge-many-application-properties-files-instead-of-replace-on-spring-boot – viniciusjssouza May 17 '19 at 15:02
  • No, unfortunately it doesn't work for yaml files. I tried to rename the application.yml to dbproerties.yml and it won't be found anymore. The system should be smart enough to recognize the profile based yamls during the tests, i.e. dbproperties-MySQL-Test.yml – Nabor May 17 '19 at 19:39
  • I tired to convert the application.yml in the storage project into properties file with no luck. `spring.jpa.mapping-resources=hbm/user.xml` leads to `Caused by: java.lang.IllegalArgumentException: Not a managed type: class de.mbur.acme.User` – Nabor May 17 '19 at 19:54

1 Answers1

0

I solved this by writing an enhanced storage configuration to be able to find and use Hibernate mapping files but also respect external configuration of properties during test or runtime...

Details can be found at: https://github.com/MBurchard/ACME/commit/499dbb128efb08614145754dc54e2ae8d4fc5d00

package de.mbur.acme.storage;

import java.util.Collections;
import java.util.Map;
import java.util.Properties;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.sql.DataSource;

import org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl;
import org.slf4j.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;

import static org.slf4j.LoggerFactory.getLogger;

@Configuration
class MySQLConfig {
    private static final Map<String, String> HIBERNATE_MAPPINGS = Stream.of(new String[][]{
            {"hibernate.format_sql", "spring.jpa.properties.hibernate.format_sql"},
            {"hibernate.show_sql", "spring.jpa.show-sql"},
    }).collect(Collectors.collectingAndThen(
            Collectors.toMap(data -> data[0], data -> data[1]),
            Collections::<String, String>unmodifiableMap));
    private static final Logger LOG = getLogger(MySQLConfig.class);

    static {
        LOG.debug("Hier bin ich");
    }

    private final Environment env;

    MySQLConfig(final Environment env) {
        this.env = env;
    }

    private Properties additionalProperties() {
        final Properties properties = new Properties();
        HIBERNATE_MAPPINGS.entrySet().forEach(entry -> {
            final String property = env.getProperty(entry.getValue());
            if (property != null) {
                LOG.debug("{}: {}", entry.getValue(), property);
                properties.setProperty(entry.getKey(), property);
            }
        });
        return properties;
    }

    @Bean
    LocalContainerEntityManagerFactoryBean entityManagerFactory(final DataSource dataSource,
            final JpaVendorAdapter jpaVendorAdapter) {
        final LocalContainerEntityManagerFactoryBean factoryBean =
                new LocalContainerEntityManagerFactoryBean();
        factoryBean.setDataSource(dataSource);
        factoryBean.setMappingResources("hbm/user.xml");
        factoryBean.setJpaVendorAdapter(jpaVendorAdapter);
        factoryBean.setJpaProperties(additionalProperties());
        return factoryBean;
    }

}

As one can see, both the DataSource and the JpaVendorAdapter are simply taken from the Spring Boot autoconfiguration.

Nabor
  • 1,661
  • 3
  • 20
  • 45
  • I have a similar problem, but I think your solution is too big to solve such a problem. But I do not know how to solve it( – WBLord May 14 '21 at 07:58