/* * Copyright 2014 Avanza Bank AB * * 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 com.avanza.astrix.context; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.avanza.astrix.beans.config.AstrixConfig; import com.avanza.astrix.beans.config.BeanConfiguration; import com.avanza.astrix.beans.core.AstrixBeanKey; import com.avanza.astrix.beans.core.AstrixSettings; import com.avanza.astrix.beans.factory.BeanFactory; import com.avanza.astrix.beans.factory.StandardFactoryBean; import com.avanza.astrix.beans.publish.ApiProviderClass; import com.avanza.astrix.beans.publish.BeanPublisher; import com.avanza.astrix.beans.service.ServiceDefinition; import com.avanza.astrix.beans.service.ServiceDefinitionSource; import com.avanza.astrix.beans.service.StatefulAstrixBean; import com.avanza.astrix.modules.Modules; import com.avanza.astrix.serviceunit.AstrixApplicationDescriptor; import com.avanza.astrix.serviceunit.ExportedServiceBeanDefinition; import com.avanza.astrix.serviceunit.ServiceAdministrator; import com.avanza.astrix.serviceunit.ServiceAdministratorVersioningConfigurer; import com.avanza.astrix.serviceunit.ServiceExporter; import com.avanza.astrix.versioning.core.ObjectSerializerDefinition; /** * An AstrixContextImpl is the runtime-environment for the astrix-framework. It is used * both by consuming applications as well as server applications. AstrixContextImpl providers access * to different Astrix-plugins at runtime and is used as a factory to create Astrix-beans. * * @author Elias Lindholm (elilin) */ final class AstrixContextImpl implements Astrix, AstrixApplicationContext { private final Logger log = LoggerFactory.getLogger(AstrixContextImpl.class); private final BeanFactory beanFactory; private final BeanPublisher beanPublisher; private final Modules modules; private final AstrixApplicationDescriptor applicationDescriptor; private final AstrixConfig config; public AstrixContextImpl(Modules modules, AstrixApplicationDescriptor applicationDescriptor) { this.modules = modules; this.applicationDescriptor = applicationDescriptor; this.config = modules.getInstance(AstrixConfig.class); this.beanPublisher = modules.getInstance(BeanPublisher.class); this.beanFactory = modules.getInstance(BeanFactory.class); } void register(ApiProviderClass apiProvider) { this.beanPublisher.publish(apiProvider); } <T> void registerBeanFactory(StandardFactoryBean<T> beanFactory) { this.beanFactory.registerFactory(beanFactory); } @Override public void destroy() { this.modules.destroy(); } @Override public void close() throws Exception { destroy(); } public BeanConfiguration getBeanConfiguration(AstrixBeanKey<?> beanKey) { return this.config.getBeanConfiguration(beanKey); } @Override public <T> T getBean(Class<T> beanType) { return getBean(beanType, null); } @Override public <T> T getBean(Class<T> beanType, String qualifier) { return beanFactory.getBean(AstrixBeanKey.create(beanType, qualifier)); } public <T> T getBean(AstrixBeanKey<T> beanKey) { return beanFactory.getBean(beanKey); } @Override public <T> T waitForBean(Class<T> beanType, long timeoutMillis) throws InterruptedException { return waitForBean(beanType, null, timeoutMillis); } @Override public <T> T waitForBean(Class<T> beanType, String qualifier, long timeoutMillis) throws InterruptedException { AstrixBeanKey<T> beanKey = AstrixBeanKey.create(beanType, qualifier); T bean = beanFactory.getBean(beanKey); for (AstrixBeanKey<?> dependencyKey : beanFactory.getDependencies(beanKey)) { Object dependency = beanFactory.getBean(dependencyKey); waitForBeanToBeBound(dependency, timeoutMillis); } waitForBeanToBeBound(bean, timeoutMillis); return bean; } private void waitForBeanToBeBound(Object bean, long timeoutMillis) throws InterruptedException { if (bean instanceof StatefulAstrixBean) { StatefulAstrixBean.class.cast(bean).waitUntilBound(timeoutMillis); } } /** * Returns an instance of an internal framework class. * @param classType * @return */ public final <T> T getInstance(final Class<T> classType) { return this.modules.getInstance(classType); } @Override public void startServicePublisher() { if (!isServer()) { throw new IllegalStateException("Server part not configured. Set AstrixConfigurer.setApplicationDescriptor to load server part of framework"); } ServiceExporter serviceExporter = getInstance(ServiceExporter.class); if (config.get(AstrixSettings.SERVICE_ADMINISTRATOR_EXPORTED).get()) { exportServiceAdministrator(serviceExporter); } else { log.info("Export of ServiceAdministrator service explicitly disabled. Won't export ServiceAdministrator service."); } serviceExporter.startPublishServices(); } private void exportServiceAdministrator(ServiceExporter serviceExporter) { String applicationInstanceId = config.get(AstrixSettings.APPLICATION_INSTANCE_ID).get(); serviceExporter.addServiceProvider(getInstance(ServiceAdministrator.class)); ObjectSerializerDefinition serializer = ObjectSerializerDefinition.versionedService(1, ServiceAdministratorVersioningConfigurer.class); AstrixBeanKey<ServiceAdministrator> serviceAdministratorQualifier = AstrixBeanKey.create(ServiceAdministrator.class, applicationInstanceId); ServiceDefinition<ServiceAdministrator> serviceDefinition = new ServiceDefinition<>(ServiceDefinitionSource.create("FrameworkServices"), serviceAdministratorQualifier, serializer, true); // isDynamicQualified String serviceAdministratorComponent = config.get(AstrixSettings.SERVICE_ADMINISTRATOR_COMPONENT).get(); ExportedServiceBeanDefinition<ServiceAdministrator> serviceAdminDefintion = new ExportedServiceBeanDefinition<>(serviceAdministratorQualifier, serviceDefinition, true, // isVersioned true, // alwaysActive serviceAdministratorComponent); serviceExporter.exportService(serviceAdminDefintion); log.info("Exported ServiceAdministrator service. component={} qualifier={}", serviceAdministratorComponent, serviceAdministratorQualifier); } private boolean isServer() { return this.applicationDescriptor != null; } }