2015-02-19 3 views
0

Я отрывал свои волосы тем, что должно быть довольно распространенным вариантом использования для веб-приложения. У меня есть приложение Spring-загрузка, который использует REST Хранилище, JPA и т.д. Проблема заключается в том, что у меня есть два источника данных:Весенняя загрузка с источником данных на основе сеанса

  • Встроенного источник данных H2 информация об аутентификации, содержащего пользователя
  • источника данных MySQL для фактических данных, специфичен для аутентифицированного пользователя

Поскольку второй источник данных специфичен для аутентифицированного пользователя, я пытаюсь использовать AbstractRoutingDataSource для маршрутизации к правильному источнику данных в соответствии с Основным пользователем после аутентификации.

Что абсолютно сводит меня с ума, так это то, что Spring-Boot борется со мной зубами и гвоздями, чтобы создать этот источник данных при запуске. Я пробовал все, о чем я могу думать, включая аннотации Lazy и Scope. Если я использую область сеанса, приложение выдает ошибку об отсутствии сеанса, существующего при запуске. @Lazy вообще не помогает. Независимо от того, какие аннотации я использую, база данных создается при запуске Spring Boot и не находит никакого ключевого ключа поиска, который по существу сбой всего приложения.

Другая проблема заключается в том, что API-хранилище репозитория имеет IMO - ужасное средство указания фактического источника данных, который будет использоваться. Если у вас несколько источников данных с Spring Boot, вы должны жонглировать аннотации Квалификатора, которые представляют собой кошмар отладки во время выполнения.

Любой совет будет очень признателен.

+0

Что происходит, так это то, что вторая Spring-Boot инициализирует встроенный источник данных (не ленив), он сканирует и находит другой источник данных. EntityManager запутывается, потому что во время сканирования обнаружено несколько источников данных, и хотя они имеют разные квалификаторы, он не знает об этом и выдает ошибку о нескольких доступных источниках. Однако, если я использую Первичную аннотацию для указания, это также отменяет любые попытки @Lazy init и Spring-Boot немедленно инициировать Первичный. – robross0606

+0

Я не думаю, что '@ Primary' и' @ Lazy' несовместимы или что-то еще. Но я не совсем уверен, что вы пытаетесь сделать. Может быть, если вы создадите небольшой проект с 2 'DataSources' и JPA, а не что-то еще, и вставьте ссылку здесь, кто-то может попробовать и проверить, что вам нужно. –

+0

Я подготовлю проект. Однако мне нужен проект Spring-Boot с двумя базами данных. Одно соединение сразу доступно. Другой источник данных «Маршрутизация» должен быть создан только и использоваться с областью сеанса ПОСЛЕ ПОЛЬЗОВАНИЯ пользователем. Я должен отметить, что это работает отлично с регулярной весной, но полностью увязано с Spring-Boot, потому что это SO-намерение для автоматической конфигурации ВСЕГО. – robross0606

ответ

1

Ваша проблема связана с конфигурацией менеджера аутентификации. Все образцы и направляющие устанавливают это в GlobalAuthenticationConfigurerAdapter, например. это будет выглядеть так, как внутренний класс вашего SimpleEmbeddedSecurityConfiguration:

@Configuration 
public static class AuthenticationConfiguration extends GlobalAuthenticationConfigurerAdapter 
{ 
    @Bean(name = Global.AUTHENTICATION_DATA_QUALIFIER + "DataSource") 
    public DataSource dataSource() 
    { 
     return new EmbeddedDatabaseBuilder().setName("authdb").setType(EmbeddedDatabaseType.H2).addScripts("security/schema.sql", "security/data.sql").build(); 
    } 

    @Override 
    public void init(AuthenticationManagerBuilder auth) throws Exception 
    { 
      auth.jdbcAuthentication().dataSource(dataSource()).passwordEncoder(passwordEncoder()); 
    } 
} 

Если вы не используете GlobalAuthenticationConfigurerAdapter то DataSource получает подхвачено Spring Data REST при создании фильтров безопасности (до @PrimaryDataSource боба даже зарегистрирован), и вся инициализация JPA начинается очень рано (плохая идея).

ОБНОВЛЕНИЕ: диспетчер аутентификации не является единственной проблемой. Если вам нужно обладать областью @PrimaryDataSource (довольно необычно, я бы сказал), вам нужно отключить все, что хочет получить доступ к базе данных при запуске (Hibernate и Spring Boot в разных местах). Пример:

spring.datasource.initialize: false 
spring.jpa.hibernate.ddlAuto: none 
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults: false 
spring.jpa.properties.hibernate.dialect: H2 

ДАЛЕЕ UPDATE: если вы используете привод он также хочет использовать первичный источник данных при запуске для индикатора состояния. Вы можете переопределить это, разделив компонент того же типа, например.

@Bean 
@Scope(value="session", proxyMode=ScopedProxyMode.TARGET_CLASS) 
@Lazy 
public DataSourcePublicMetrics dataSourcePublicMetrics() { 
    return new DataSourcePublicMetrics(); 
} 

P.S. Я считаю, что GlobalAuthenticationConfigurerAdapter может не понадобиться в Spring Boot 1.2.2, но он находится в 1.2.1 или 1.1.10.

+0

Спасибо, я проверю это. Более фундаментально, но как это будет работать, если у вас есть разные источники данных, и один из них не нужен для аутентификации? Что, если у меня действительно было несколько разных источников данных, которые мне нужны для REST? Кроме того, я не уверен, что это решение решит мою проблему с Spring-Boot с ранним запуском, где он игнорирует @Lazy в службе REST, но я обязательно попробую. – robross0606

+0

Вы действительно внесли изменения в этот проект и запустили его? Насколько я могу судить, это не помогло решить проблему. Проблема в том, что я не могу заставить Spring-Boot НЕ запускать UserSpecificDataSource при запуске. На самом деле это должна быть конфигурация с ограниченным сеансом, но Spring-Boot терпит неудачу, если вы установите эту область, потому что она пытается создать экземпляр в любом случае. На самом деле, я не могу заставить Spring-Boot принять ANY @Configuration с областью сеанса. Он запускается при запуске, а затем терпит неудачу. – robross0606

+0

'@ Конфигурация' с областью сеанса не имеет смысла (по крайней мере для меня), поэтому я либо преобразовал их в' @ Component', либо удалил их. Я могу опубликовать ваш код (сильно измененный, поскольку он не был действительно «минимальным»), если хотите. (Но область видимости сеанса не имеет ничего общего с проблемой JPA.) –

Смежные вопросы