Создание прототипа многопользовательского приложения Sping Boot, JPA, Eclipselink и AbstractRoutingDataSource - PullRequest
0 голосов
/ 17 октября 2018

Я начал прототипирование https://github.com/spring-projects/spring-data-examples/tree/master/jpa/eclipselink и обновил example.springdata.jpa.eclipselink.Application с помощью пользовательского метода источника данных, как показано ниже, который возвращает подкласс org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource.

/*
 * Copyright 2015-2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package example.springdata.jpa.eclipselink;

import java.util.Collections;
import java.util.Map;

import javax.sql.DataSource;

import com.zaxxer.hikari.*;
import org.springframework.jdbc.datasource.lookup.*;
import org.springframework.boot.autoconfigure.*;
import org.springframework.boot.autoconfigure.jdbc.*;
import org.springframework.context.annotation.*;
import java.util.*;

import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers;
import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter;
import org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter;
import org.springframework.transaction.jta.JtaTransactionManager;

/**
 * Spring Boot application that uses EclipseLink as the JPA provider.
 *
 * @author Oliver Gierke
 * @author Jeremy Rickard
 * @author Mark Paluch
 */
@SpringBootApplication
@EnableAutoConfiguration(exclude = { //
    DataSourceAutoConfiguration.class, //
    DataSourceTransactionManagerAutoConfiguration.class })
public class Application extends JpaBaseConfiguration {

    /**
     * @param dataSource
     * @param properties
     * @param jtaTransactionManagerProvider
     */
    protected Application(DataSource dataSource, JpaProperties properties,
            ObjectProvider<JtaTransactionManager> jtaTransactionManagerProvider,
            ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
        super(dataSource, properties, jtaTransactionManagerProvider, transactionManagerCustomizers);
    }

    /*
     * (non-Javadoc)
     * @see org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration#createJpaVendorAdapter()
     */
    @Override
    protected AbstractJpaVendorAdapter createJpaVendorAdapter() {
        return new EclipseLinkJpaVendorAdapter();
    }

    /*
     * (non-Javadoc)
     * @see org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration#getVendorProperties()
     */
    @Override
    protected Map<String, Object> getVendorProperties() {

        // Turn off dynamic weaving to disable LTW lookup in static weaving mode
        return Collections.singletonMap("eclipselink.weaving", "false");
    }

    public static void main(String[] args) {

        CustomerRepository repository = SpringApplication.run(Application.class, args).getBean(CustomerRepository.class);
        repository.save(new Customer("Richard", "Feynman"));

        System.out.println(repository.findAll());
    }



  @Bean
  @Primary
  public DataSource dataSource() {

    // AbstractRoutingDataSource dataSource = new TenantAwareRoutingSource();

    // Map<Object,Object> targetDataSources = new HashMap<>();

    HikariDataSource dataSource1 = new HikariDataSource();

    dataSource1.setInitializationFailTimeout(0);
    dataSource1.setMaximumPoolSize(5);
    dataSource1.setDataSourceClassName("org.h2.Driver");
    dataSource1.addDataSourceProperty("url", "jdbc:h2:tcp://localhost/~/test;SCHEMA;cxcatalog_t1");
    dataSource1.addDataSourceProperty("user", "guest");
    dataSource1.addDataSourceProperty("password", "guest123");

    // targetDataSources.put("TenantOne", dataSource1);

    // HikariDataSource dataSource2 = new HikariDataSource();

    // dataSource2.setInitializationFailTimeout(0);
    // dataSource2.setMaximumPoolSize(5);
    // dataSource2.setDataSourceClassName("org.h2.Driver");
    // dataSource2.addDataSourceProperty("url", "jdbc:h2:tcp://localhost/~/test;SCHEMA;cxcatalog_t2");
    // dataSource2.addDataSourceProperty("user", "guest");
    // dataSource2.addDataSourceProperty("password", "guest123");

    // targetDataSources.put("TenantTwo", dataSource2);

    // dataSource.setTargetDataSources(targetDataSources);

    // dataSource.afterPropertiesSet();

    return dataSource1;
  }

}

TenantAwareRoutingSource в основном ищет источник данных, используя локальный идентификатор клиента потока.

Но я получаю ошибку запуска, так как bean-компонент источника данных не создается при запуске

[INFO] Attaching agents: [/home/sgokak/.m2/repository/org/springframework/spring-instrument/5.0.9.BUILD-SNAPSHOT/spring-instrument-5.0.9.BUILD-SNAPSHOT.jar]
10:23:41.471 [main] DEBUG org.springframework.boot.devtools.settings.DevToolsSettings - Included patterns for restart : []
10:23:41.475 [main] DEBUG org.springframework.boot.devtools.settings.DevToolsSettings - Excluded patterns for restart : [/spring-boot-starter-[\w-]+/, /spring-boot/target/classes/, /spring-boot-starter/target/classes/, /spring-boot-devtools/target/classes/, /spring-boot-actuator/target/classes/, /spring-boot-autoconfigure/target/classes/]
10:23:41.476 [main] DEBUG org.springframework.boot.devtools.restart.ChangeableUrls - Matching URLs for reloading : [file:/home/sgokak/myspace/myprojects/spring-data-examples-master/jpa/eclipselink/target/classes/]

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.5.RELEASE)

2018-10-17 10:23:42.105  INFO 8903 --- [  restartedMain] e.s.jpa.eclipselink.Application          : Starting Application on sgokak-ThinkPad-T450 with PID 8903 (/home/sgokak/myspace/myprojects/spring-data-examples-master/jpa/eclipselink/target/classes started by sgokak in /home/sgokak/myspace/myprojects/spring-data-examples-master/jpa/eclipselink)
2018-10-17 10:23:42.107  INFO 8903 --- [  restartedMain] e.s.jpa.eclipselink.Application          : No active profile set, falling back to default profiles: default
2018-10-17 10:23:42.192  INFO 8903 --- [  restartedMain] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@26df0bdc: startup date [Wed Oct 17 10:23:42 EDT 2018]; root of context hierarchy
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.springframework.cglib.core.ReflectUtils$1 (file:/home/sgokak/.m2/repository/org/springframework/spring-core/5.0.9.BUILD-SNAPSHOT/spring-core-5.0.9.BUILD-SNAPSHOT.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)
WARNING: Please consider reporting this to the maintainers of org.springframework.cglib.core.ReflectUtils$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
2018-10-17 10:23:43.478  WARN 8903 --- [  restartedMain] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'application': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'application': Requested bean is currently in creation: Is there an unresolvable circular reference?
2018-10-17 10:23:43.489  INFO 8903 --- [  restartedMain] ConditionEvaluationReportLoggingListener : 

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2018-10-17 10:23:43.493 ERROR 8903 --- [  restartedMain] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

The dependencies of some of the beans in the application context form a cycle:

┌─────┐
|  application
└─────┘

Что выглядитнапример, из-за требуемой зависимости источника данных в аргументах конструктора.

Я что-то здесь не так делаю? Есть ли альтернативное решение или подход для внедрения org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource datasource?

Я получил некоторую помощь и подсказки от https://bytefish.de/blog/spring_boot_multitenancy/

...