Spring Cloud Config Server + Wildfly JNDI (MySql) + Spring Data Jpa с Hibernate с обновлением DataSource

Из данного заголовка я получил рабочий образец без Spring Data Part, используя простой шаблон DataSource и JDBC с обновлением источника данных при нажатии на curl для обновления bean-компонента Datasource. Но не смог заставить его работать с Spring Data JPA, потратив бесчисленные часы поиска и просмотра различных сообщений в блоге, таких как https://www.baeldung.com/spring-persistence-jpa-jndi-datasource, https://www.jeejava.com/spring-boot-jndi-datasource/

Я объясню все шаги, а также свяжу проект git с работающим примером шаблона JDBC и проект JPA ниже. Все компоненты настроены локально для демонстрации.


Добавление источника данных JNDI MySql в Wildfly (финальная версия 10.1.10)

Благодаря следующему видео - 3 способа добавления источника данных в Wildfly 9, я добавил два источника данных MySql, указывающих на две разные базы данных на моем локальном сервере mysql, путем развертывания jar коннектора mysql и добавления источника данных с помощью консоли Wildfly, и тестирование обоих из консоли прошло успешно.,

Конфиг Сервер и Клиент

Оба из них настроены правильно и также проверены. Клиенты конфигурации jdbcConfigClient и jpaConfigClient читают свойство поиска JNDI с удаленного сервера конфигурации. MysqlConnector jar, ConfigClient и Config Server развернуты на локальном wildfly с помощью консоли Wildfly (только один клиент развернут для тестирования).

JdbcClient

Вот фрагмент конфигурации источника данных вместе с основным приложением и образцом контроллера для тестирования обновления источника данных:

    @SpringBootApplication
    @EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
    @RefreshScope
    public class ConfigclientApplication extends SpringBootServletInitializer      {

    public static void main(String[] args) {
        SpringApplication.run(ConfigclientApplication.class, args);
    }
}

@RefreshScope
@RestController
class MessageRestController {

@Autowired
SampleDao dao;

@Value("${message:Hello default}")
private String message;

@RequestMapping("/message")
public String getMessage() {
    return this.message;
}

@RequestMapping("/person")
public List<SampleEntity> getAll() {
    return dao.findAll();
}

}

@RefreshScope
@Configuration
class DataSourceConfig {


@Value("${jndi.datasource.name}")
private String jndiName;

//@RequestMapping("/jndi")
public String getJndiName() {
    return this.jndiName;
}

@Bean
@RefreshScope
public DataSource getDataSource() throws NamingException {
    JndiDataSourceLookup jndiDataSourceLookup = new JndiDataSourceLookup();
    System.out.println("Datasource jndi is "+getJndiName());
    //return (DataSource) new JndiTemplate().lookup(getJndiName());
    return jndiDataSourceLookup.getDataSource(getJndiName());
}

@Bean
@RefreshScope
public JdbcTemplate getJbdcTemplate() throws NamingException {
    return new JdbcTemplate(getDataSource());
}

Для тестирования я нажал на запрос Get /person, чтобы получить список людей, и смог успешно получить ответ с обновлением источника данных, а также с помощью запроса curl для настройки клиента, как это было предложено в Getting Started Centralized Config. Для полной проверки проекта jdbcConfigClient

JPA Config Client

Вот когда все стало проблематично. Я пробовал много разных вещей, но даже с жестко закодированным параметром JNDI приложение не запустилось из-за разных причин, таких как отсутствие параметра URL, недоступный компонент EntityManager или загрузка Hikari Config и сбой, даже если я не использую Hikari Источник данных в конфигурации Java Источник данных, который, как я полагаю, при загрузке Spring пытается загрузить по умолчанию. Я попытался исключить hikari cp из Spring data Starter, попытался исключить автоконфигурацию источника данных, используя свойство exlcude @EnableAutoConfiguration в основном приложении до сих пор нет смысла. Я использую конфигурацию источника данных Jpa в обычных проектах без JNDI и сервера конфигурации. Ниже приведен фрагмент конфигурации источника данных JPA с основным приложением:

    SpringBootApplication
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
@EnableAutoConfiguration
@RefreshScope
public class ConfigclientApplication extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(ConfigclientApplication.class, args);
    }
}

@RefreshScope
@RestController
class MessageRestController {

    @Autowired
    SampleDao dao;

    @Value("${message:Hello default}")
    private String message;

    @RequestMapping("/message")
    public String getMessage() {
        return this.message;
    }

    @RequestMapping("/person")
    public List<SampleEntity> getAll() {
        return dao.findAll();
    }

}

@RefreshScope
@Configuration
@EnableJpaRepositories("com.example.demo.dao")
@EnableTransactionManagement
/*@EntityScan("com.example.demo.entity")
@ComponentScan("com.example.demo")*/
class DataSourceConfig {

    @Value("${jndi.datasource.name}")
    private String jndiName;

    public String getJndiName() {
        return this.jndiName;
    }

    @Bean
    public DataSource getDataSource() throws NamingException {
        //JndiDataSourceLookup jndiDataSourceLookup = new JndiDataSourceLookup();
        //System.out.println("Datasource jndi is "+getJndiName());
        //return (DataSource) new JndiTemplate().lookup(getJndiName());
        //return jndiDataSourceLookup.getDataSource("java:/MySqlDS");
        JndiObjectFactoryBean bean = new JndiObjectFactoryBean();
        bean.setJndiName(getJndiName());
        bean.setProxyInterface(DataSource.class);
        bean.setLookupOnStartup(false);
        bean.afterPropertiesSet();
        return (DataSource)bean.getObject();
    }

    @Bean
    public EntityManagerFactory entityManagerFactory() throws NamingException {

        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
        factory.setDataSource(getDataSource());
        factory.setPackagesToScan("com.example.demo.entity");

        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setDatabase(Database.MYSQL);
        vendorAdapter.setShowSql(true);
        factory.setJpaVendorAdapter(vendorAdapter);
        factory.afterPropertiesSet();

        //HashMap<String, Object> properties = new HashMap<>();
        //properties.put("hibernate.generate-ddl", Boolean.TRUE.toString());
        //properties.put("hibernate.hbm2ddl.auto", "update");
        //properties.put("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
        //entityManagerContainer.setJpaPropertyMap(properties);

        return factory.getObject();

    }

    @Bean
    public PlatformTransactionManager transactionManager() throws NamingException {

        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactory());
        return transactionManager;
    }
}

Проект JPA можно найти здесь - JpaConfigClient. Если я полностью удаляю всю конфигурацию источника данных и просто задаю следующее свойство в файле удаленных свойств:

spring.datasource.jndi-name=java:/MySqlDs

Используя автоконфигурацию, конфигурация JPA завершается успешно, и я могу получить данные с помощью запроса почтальона, но это не мое требование, и я не могу обновить источник данных, так как он автоматически конфигурируется при загрузке. Также файл удаленных свойств с именем a-bootiful-client.properties содержит только следующие свойства:

#spring.datasource.jndi-name=java:/MySqlDs
jndi.datasource.name=java.name=java:comp/env/MySqlDs
message=Hi test

Когда приложение запускается, оно правильно ищет источник данных wildfly (я попытался назвать источник данных как java:comp/env/DatasourceName а также с использованием по умолчанию java:/DatasourceName также, но это не имело значения, и у меня были те же проблемы, о которых сообщалось выше. Не стесняйтесь раскошелиться на вышеупомянутый проект.

0 ответов

Другие вопросы по тегам