001/* 002 * Copyright 2012-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.boot.jta.atomikos; 018 019import java.util.Arrays; 020import java.util.Collections; 021import java.util.LinkedHashSet; 022import java.util.List; 023import java.util.Set; 024 025import com.atomikos.icatch.jta.UserTransactionManager; 026 027import org.springframework.beans.BeansException; 028import org.springframework.beans.factory.config.BeanDefinition; 029import org.springframework.beans.factory.config.BeanFactoryPostProcessor; 030import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 031import org.springframework.core.Ordered; 032import org.springframework.util.StringUtils; 033 034/** 035 * {@link BeanFactoryPostProcessor} to automatically setup the recommended 036 * {@link BeanDefinition#setDependsOn(String[]) dependsOn} settings for 037 * <a href="http://www.atomikos.com/Documentation/SpringIntegration">correct Atomikos 038 * ordering</a>. 039 * 040 * @author Phillip Webb 041 * @since 1.2.0 042 */ 043public class AtomikosDependsOnBeanFactoryPostProcessor 044 implements BeanFactoryPostProcessor, Ordered { 045 046 private static final String[] NO_BEANS = {}; 047 048 private int order = Ordered.LOWEST_PRECEDENCE; 049 050 @Override 051 public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) 052 throws BeansException { 053 String[] transactionManagers = beanFactory 054 .getBeanNamesForType(UserTransactionManager.class, true, false); 055 for (String transactionManager : transactionManagers) { 056 addTransactionManagerDependencies(beanFactory, transactionManager); 057 } 058 addMessageDrivenContainerDependencies(beanFactory, transactionManagers); 059 } 060 061 private void addTransactionManagerDependencies( 062 ConfigurableListableBeanFactory beanFactory, String transactionManager) { 063 BeanDefinition bean = beanFactory.getBeanDefinition(transactionManager); 064 Set<String> dependsOn = new LinkedHashSet<>(asList(bean.getDependsOn())); 065 int initialSize = dependsOn.size(); 066 addDependencies(beanFactory, "javax.jms.ConnectionFactory", dependsOn); 067 addDependencies(beanFactory, "javax.sql.DataSource", dependsOn); 068 if (dependsOn.size() != initialSize) { 069 bean.setDependsOn(StringUtils.toStringArray(dependsOn)); 070 } 071 } 072 073 private void addMessageDrivenContainerDependencies( 074 ConfigurableListableBeanFactory beanFactory, String[] transactionManagers) { 075 String[] messageDrivenContainers = getBeanNamesForType(beanFactory, 076 "com.atomikos.jms.extra.MessageDrivenContainer"); 077 for (String messageDrivenContainer : messageDrivenContainers) { 078 BeanDefinition bean = beanFactory.getBeanDefinition(messageDrivenContainer); 079 Set<String> dependsOn = new LinkedHashSet<>(asList(bean.getDependsOn())); 080 dependsOn.addAll(asList(transactionManagers)); 081 bean.setDependsOn(StringUtils.toStringArray(dependsOn)); 082 } 083 } 084 085 private void addDependencies(ConfigurableListableBeanFactory beanFactory, String type, 086 Set<String> dependsOn) { 087 dependsOn.addAll(asList(getBeanNamesForType(beanFactory, type))); 088 } 089 090 private String[] getBeanNamesForType(ConfigurableListableBeanFactory beanFactory, 091 String type) { 092 try { 093 return beanFactory.getBeanNamesForType(Class.forName(type), true, false); 094 } 095 catch (ClassNotFoundException | NoClassDefFoundError ex) { 096 // Ignore 097 } 098 return NO_BEANS; 099 } 100 101 private List<String> asList(String[] array) { 102 return (array != null) ? Arrays.asList(array) : Collections.emptyList(); 103 } 104 105 @Override 106 public int getOrder() { 107 return this.order; 108 } 109 110 public void setOrder(int order) { 111 this.order = order; 112 } 113 114}