我问你如何使用camelContext获取事件触发的路由名称,更详细的说明,如何在camelContext中使用任何类型的鉴别器属性x进行谓词判断(如果x = 1则为.. else。 。) 例如:
我有这样的路线:
//this route use the forst database
from("direct:csvprocessor1")
.routeId("tenant1")
.from("file:src/main/resources/data/1?move=OUT&moveFailed=REFUSED")
.unmarshal(csv)
.to("bean:myCsvHandler?method=doHandleCsvData")
.setBody(constant("OK VB"))
.setHeader(Exchange.HTTP_RESPONSE_CODE, constant(200))
.setHeader(Exchange.CONTENT_TYPE, constant("text/html"));
和另一条路线:
//this route use tenant2, the second database
from("direct:csvprocessor1")
.routeId("tenant2")
.from("file:src/main/resources/data/2?move=OUT&moveFailed=REFUSED")
.unmarshal(csv)
.to("bean:myCsvHandler?method=doHandleCsvData")
.setBody(constant("OK 2"))
.setHeader(Exchange.HTTP_RESPONSE_CODE, constant(200))
.setHeader(Exchange.CONTENT_TYPE, constant("text/html"));
当我拿起1个文件夹中的文件时,第一个名为“tenant1”的路径启动,同样的情况发生在2中拾取文件时,第二个路径tenant2启动。它读取csv内容,内容必须使用jpa写入right tenantX(数据库)
我必须在另一个类中检索routeid名称,但是这个类在camel Context开始之前实例化,所以我不能注入上下文(因为这个类“BatchCurrentTenantIdentifierResolverImpl”属于Spring数据库初始化器)。我尝试添加方法“of”来设置camelContext,但我只获得tenant1,当路由2启动时,所以无法从租户切换到另一个租户(租户是数据库,我有两个数据库):
@Component
public class BatchTenantContext {
private static final Logger log = LoggerFactory.getLogger(BatchTenantContext.class);
// don't Inject, use method Of because injecton was null
CamelContext cctx;
public BatchTenantContext(){getInstance();}
private final static BatchTenantContext instance = new BatchTenantContext();
public static BatchTenantContext getInstance(){
return instance;
}
public synchronized String get() {
if (cctx != null){
Route val = cctx.getRoute("tenant1");
if (val == null){
val = cctx.getRoute("tenant2");
if (val == null){
return "";
}
else {
return "tenant_2";
}
}
else return "tenant_1";
}
return "";
}
public synchronized void of(CamelContext ctx){
cctx = ctx;
}
public CamelContext getCamelContext()
{
return cctx;
}
}
//multitenant approach, switch from one database to another
//based on BatchTenantContext resolution..
public class BatchCurrentTenantIdentifierResolverImpl implements CurrentTenantIdentifierResolver {
static final Logger log = LoggerFactory.getLogger(BatchCurrentTenantIdentifierResolverImpl.class);
@Override
public String resolveCurrentTenantIdentifier() {
String val = BatchTenantContext.getInstance().get();
log.info("*** get tenant " + val);
return val;
}
@Override
public boolean validateExistingCurrentSessions() {
return true;
}
}
那么,如何知道路线如何火?请注意,上面的类是单身..我正确的方式? 我使用jpa whitin hibernate提供程序,使用rhe multitenant配置配置如下:http://tech.asimio.net/2017/01/17/Multitenant-applications-using-Spring-Boot-JPA-Hibernate-and-Postgres.html 该应用程序在spring-boot运行时环境中或与Tomcat应用程序服务器一起工作。
关于所有的想法?
非常感谢!
拉吉
我添加此代码:
@Configuration
@EnableConfigurationProperties({ MultiTenantAfSissProperties.class, JpaProperties.class })
@ImportResource(locations = { "classpath:applicationContent.xml" })
@EnableTransactionManagement
public class MultiTenantJpaConfiguration {
static final Logger logger = LoggerFactory.getLogger(MultiTenantJpaConfiguration.class);
@Inject
private JpaProperties jpaProperties;
@Inject
MultiTenantAFSISSProperties multiTenantAFSISSProperties; //lista dei datasources collegati ai tenant
@Bean
public Map<String, DataSource> dataSourceRetrieval(){
Map<String, DataSource> result = new HashMap<>();
for (DataSourceProperties dsProperties : this.multiTenantAFSISSProperties.getDataSources()) {
DataSourceBuilder factory = DataSourceBuilder
.create()
.url(dsProperties.getUrl())
.username(dsProperties.getUsername())
.password(dsProperties.getPassword())
.driverClassName(dsProperties.getDriverClassName());
result.put(dsProperties.getTenantId(), factory.build());
}
return result;
}
/**
*
* @return
*/
@Bean
public MultiTenantConnectionProvider multiTenantConnectionProvider(){
return new AfsissMultiTenantConnectionProviderImpl();
}
/**
*
* @return
*/
@Bean
public CurrentTenantIdentifierResolver currentTenantIdentifierResolver(){
return new BatchCurrentTenantIdentifierResolverImpl();
}
/**
*
* @param multiTenantConnectionProvider
* @param currentTenantIdentifierResolver
* @return
*/
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(MultiTenantConnectionProvider multiTenantConnectionProvider,
CurrentTenantIdentifierResolver currentTenantIdentifierResolver) {
Map<String, Object> hibernateProps = new LinkedHashMap<>();
hibernateProps.putAll(this.jpaProperties.getProperties());
Map<String,String> all = this.jpaProperties.getProperties();
for ( Map.Entry<String, String> prop : all.entrySet()){
System.out.println(" " + prop.getKey() + " = " + prop.getValue());
}
hibernateProps.put(Environment.MULTI_TENANT, MultiTenancyStrategy.DATABASE);
hibernateProps.put(Environment.MULTI_TENANT_CONNECTION_PROVIDER, multiTenantConnectionProvider);
hibernateProps.put(Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, currentTenantIdentifierResolver);
// No dataSource is set to resulting entityManagerFactoryBean
LocalContainerEntityManagerFactoryBean result = new LocalContainerEntityManagerFactoryBean();
result.setPackagesToScan(new String[] { AfFileEntity.class.getPackage().getName() });
result.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
result.setJpaPropertyMap(hibernateProps);
return result;
}
/**
* crea la factory per ricavare l'entity manager
* @param entityManagerFactoryBean
* @return
*/
@Bean
public EntityManagerFactory entityManagerFactory(LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) {
return entityManagerFactoryBean.getObject();
}
/**
* get transaction manager
* @param entityManagerFactory
* @return
*/
@Bean
public PlatformTransactionManager txManager(EntityManagerFactory entityManagerFactory) {
SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
HibernateTransactionManager result = new HibernateTransactionManager();
result.setAutodetectDataSource(false);
result.setSessionFactory(sessionFactory);
return result;
}
}
在applicationContent.xml中:
<jpa:repositories base-package="com.xxx.dao" transaction-manager-ref="txManager" />
<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true" />
每次我在csvHanlder中使用实体管理器和事务管理器时,spring transaction manager会在currentTenantIdentifierResolver()方法中调用类BatchCurrentTenantIdentifierResolverImpl:
@Component
@Transactional(propagation = Propagation.REQUIRED)
public class MyCsvHandler {
@Inject
AFMOVCrudRepository _entitymanagerMov; //it extends JpaRepository
@Inject
AFVINCCrudRepository _entityManagerVINC;//it extends JpaRepository
@Inject
AFFileCrudRepository _entityManagerAfFile;//it extends JpaRepository
static final Logger logger = LoggerFactory.getLogger(MyCsvHandler.class);
//save csv data on the right table on the right tenant
public void doHandleCsvData(List<List<String>> csvData) throws FileNotEvaluableException
{
//System.out.println("stampo..");
boolean status = true;
if (csvData.size() > 0){
AfFileEntity afbean = new AfFileEntity();
afbean.setNomeFile("test");
afbean.setDataImport(new java.sql.Timestamp(System.currentTimeMillis()));
afbean.setTipoFile("M");
afbean.setAfStatoFlusso("I");
_entityManagerAfFile.save(afbean);
long pkfile = afbean.getId();
logger.info("pkfile: " + pkfile);
int i = 1;
logger.info("file size:" + csvData.size());
for (List<String> rows : csvData){
//for (int j = 0; i < rows.size(); j++){
if (rows.get(2).trim().equalsIgnoreCase(...)){
MovEntity mbean = new MovEntity();
setMovFields(mbean, rows);
mbean.setAfFileId(afbean);
logger.info(String.valueOf((i++)) + " " + mbean);
_entitymanagerMov.save(mbean);
}
else if (rows.get(2).trim().equalsIgnoreCase(..) || rows.get(2).trim().equalsIgnoreCase(..) ) {
VincEntity vincBean = new VincEntity();
setVincFields(vincBean, rows);
vincBean.setAfFileId(afbean);
logger.info(String.valueOf((i++)) + " " + vincBean);
_entityManagerVINC.save(vincBean);
}
else {
status = false;
break;
}
}
if (!status) throw new FileNotEvaluableException("error file format");
}
}
private void setVincFields(VincEntity vincBean, List<String> rows) {
vincBean.setXXX().. and others methods
}
private void setMovFields(MovEntity mbean, List<String> rows) {
mbean.setStxxx() and other .. methods
}
return new
答案 0 :(得分:0)
你的路线中的这类东西
from("direct:csvprocessor1").routeId("tenant2").process((Exchange e)-> {
BatchCurrentTenantIdentifierResolverImpl.tenant.set("tenant_1");
})
.from("file:src/main/resources/data/2?move=OUT&moveFailed=REFUSED")
.unmarshal().csv()
.to("bean:myCsvHandler?method=doHandleCsvData")
.setBody(constant("OK 2"))
.setHeader(Exchange.HTTP_RESPONSE_CODE, constant(200))
.setHeader(Exchange.CONTENT_TYPE, constant("text/html"));
并在BatchCurrentTenantIdentifierResolverImpl
中将其作为公共
class BatchCurrentTenantIdentifierResolverImpl {
public static ThreadLocal<String> tenant = new ThreadLocal<String>();
static final Logger log = LoggerFactory.getLogger(BatchCurrentTenantIdentifierResolverImpl.class);
@Override
public String resolveCurrentTenantIdentifier() {
String val = tenant.get();
log.info("*** get tenant " + val);
return val;
}
@Override
public boolean validateExistingCurrentSessions() {
return true;
}
}