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.autoconfigure.data.neo4j;
018
019import java.util.List;
020
021import org.apache.commons.logging.Log;
022import org.apache.commons.logging.LogFactory;
023import org.neo4j.ogm.session.SessionFactory;
024import org.neo4j.ogm.session.event.EventListener;
025
026import org.springframework.beans.factory.ObjectProvider;
027import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
028import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
029import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
030import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
031import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
032import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
033import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
034import org.springframework.boot.autoconfigure.domain.EntityScanPackages;
035import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers;
036import org.springframework.boot.context.properties.EnableConfigurationProperties;
037import org.springframework.context.ApplicationContext;
038import org.springframework.context.annotation.Bean;
039import org.springframework.context.annotation.Configuration;
040import org.springframework.context.annotation.Import;
041import org.springframework.data.neo4j.transaction.Neo4jTransactionManager;
042import org.springframework.data.neo4j.web.support.OpenSessionInViewInterceptor;
043import org.springframework.transaction.PlatformTransactionManager;
044import org.springframework.util.StringUtils;
045import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
046import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
047
048/**
049 * {@link EnableAutoConfiguration Auto-configuration} for Spring Data Neo4j.
050 *
051 * @author Michael Hunger
052 * @author Josh Long
053 * @author Vince Bickers
054 * @author Stephane Nicoll
055 * @author Kazuki Shimizu
056 * @since 1.4.0
057 */
058@Configuration
059@ConditionalOnClass({ SessionFactory.class, Neo4jTransactionManager.class,
060                PlatformTransactionManager.class })
061@ConditionalOnMissingBean(SessionFactory.class)
062@EnableConfigurationProperties(Neo4jProperties.class)
063@Import(Neo4jBookmarkManagementConfiguration.class)
064public class Neo4jDataAutoConfiguration {
065
066        @Bean
067        @ConditionalOnMissingBean
068        public org.neo4j.ogm.config.Configuration configuration(Neo4jProperties properties) {
069                return properties.createConfiguration();
070        }
071
072        @Bean
073        public SessionFactory sessionFactory(org.neo4j.ogm.config.Configuration configuration,
074                        ApplicationContext applicationContext,
075                        ObjectProvider<EventListener> eventListeners) {
076                SessionFactory sessionFactory = new SessionFactory(configuration,
077                                getPackagesToScan(applicationContext));
078                eventListeners.stream().forEach(sessionFactory::register);
079                return sessionFactory;
080        }
081
082        @Bean
083        @ConditionalOnMissingBean(PlatformTransactionManager.class)
084        public Neo4jTransactionManager transactionManager(SessionFactory sessionFactory,
085                        Neo4jProperties properties,
086                        ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
087                return customize(new Neo4jTransactionManager(sessionFactory),
088                                transactionManagerCustomizers.getIfAvailable());
089        }
090
091        private Neo4jTransactionManager customize(Neo4jTransactionManager transactionManager,
092                        TransactionManagerCustomizers customizers) {
093                if (customizers != null) {
094                        customizers.customize(transactionManager);
095                }
096                return transactionManager;
097        }
098
099        private String[] getPackagesToScan(ApplicationContext applicationContext) {
100                List<String> packages = EntityScanPackages.get(applicationContext)
101                                .getPackageNames();
102                if (packages.isEmpty() && AutoConfigurationPackages.has(applicationContext)) {
103                        packages = AutoConfigurationPackages.get(applicationContext);
104                }
105                return StringUtils.toStringArray(packages);
106        }
107
108        @Configuration
109        @ConditionalOnWebApplication(type = Type.SERVLET)
110        @ConditionalOnClass({ WebMvcConfigurer.class, OpenSessionInViewInterceptor.class })
111        @ConditionalOnMissingBean(OpenSessionInViewInterceptor.class)
112        @ConditionalOnProperty(prefix = "spring.data.neo4j", name = "open-in-view", havingValue = "true", matchIfMissing = true)
113        protected static class Neo4jWebConfiguration {
114
115                @Configuration
116                protected static class Neo4jWebMvcConfiguration implements WebMvcConfigurer {
117
118                        private static final Log logger = LogFactory
119                                        .getLog(Neo4jWebMvcConfiguration.class);
120
121                        private final Neo4jProperties neo4jProperties;
122
123                        protected Neo4jWebMvcConfiguration(Neo4jProperties neo4jProperties) {
124                                this.neo4jProperties = neo4jProperties;
125                        }
126
127                        @Bean
128                        public OpenSessionInViewInterceptor neo4jOpenSessionInViewInterceptor() {
129                                if (this.neo4jProperties.getOpenInView() == null) {
130                                        logger.warn("spring.data.neo4j.open-in-view is enabled by default."
131                                                        + "Therefore, database queries may be performed during view "
132                                                        + "rendering. Explicitly configure "
133                                                        + "spring.data.neo4j.open-in-view to disable this warning");
134                                }
135                                return new OpenSessionInViewInterceptor();
136                        }
137
138                        @Override
139                        public void addInterceptors(InterceptorRegistry registry) {
140                                registry.addWebRequestInterceptor(neo4jOpenSessionInViewInterceptor());
141                        }
142
143                }
144
145        }
146
147}