Spring Cloud Config Server + Wildfly JNDI (MySql) + Spring Data Jpa с Hibernate с обновлением DataSource - PullRequest
0 голосов
/ 08 ноября 2018

Из данного заголовка я получил рабочий образец без Spring Data Part, используя простой шаблон DataSource и JDBC с обновлением источника данных на , нажимая curl , чтобы также обновить компонент Datasource. Но не смог заставить его работать с Spring Data JPA, потратив бесчисленные часы поиска и просмотра различных сообщений в блоге, таких как spring-persistence-jpa-jndi-datasource , 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 и ConfigServer развернуты на локальном 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, попытался исключить автоконфигурацию Datasource, используя свойство exlcude, равное @EnableAutoConfiguration, в основном приложении до сих пор бесполезно. Я использую конфигурацию Jpa Datasource в обычных проектах без 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, но это не имело значения, и я получил те же проблемы, что и сообщалось выше. Не стесняйтесь раскошелиться на вышеуказанный проект.

...