2 * Copyright 2017 ZTE Corporation.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org.onap.holmes.common.dropwizard.ioc.bundle;
18 import com.codahale.metrics.health.HealthCheck;
19 import com.fasterxml.jackson.databind.ObjectMapper;
20 import com.google.common.collect.Lists;
21 import io.dropwizard.Configuration;
22 import io.dropwizard.ConfiguredBundle;
23 import io.dropwizard.lifecycle.ServerLifecycleListener;
24 import io.dropwizard.servlets.tasks.Task;
25 import io.dropwizard.setup.Bootstrap;
26 import io.dropwizard.setup.Environment;
27 import java.lang.annotation.Annotation;
28 import java.lang.reflect.Field;
29 import java.util.Arrays;
30 import java.util.List;
32 import java.util.stream.Collectors;
33 import javax.ws.rs.Path;
34 import javax.ws.rs.ext.Provider;
35 import org.eclipse.jetty.util.component.LifeCycle;
36 import org.glassfish.hk2.api.ServiceLocator;
37 import org.glassfish.hk2.api.ServiceLocatorFactory;
38 import org.glassfish.hk2.utilities.ServiceLocatorUtilities;
39 import org.glassfish.hk2.utilities.binding.AbstractBinder;
40 import org.glassfish.jersey.servlet.ServletProperties;
41 import org.jvnet.hk2.annotations.Service;
42 import org.onap.holmes.common.dropwizard.ioc.annotation.BaseService;
43 import org.onap.holmes.common.dropwizard.ioc.annotation.Lazy;
44 import org.onap.holmes.common.dropwizard.ioc.annotation.PostBaseService;
45 import org.onap.holmes.common.dropwizard.ioc.annotation.PreBaseService;
46 import org.onap.holmes.common.dropwizard.ioc.annotation.PreLoad;
47 import org.onap.holmes.common.dropwizard.ioc.annotation.PreServiceLoad;
48 import org.onap.holmes.common.dropwizard.ioc.utils.ServiceBinder;
49 import org.onap.holmes.common.dropwizard.ioc.utils.ServiceLocatorHolder;
50 import org.reflections.Reflections;
51 import org.reflections.scanners.SubTypesScanner;
52 import org.reflections.scanners.TypeAnnotationsScanner;
53 import org.reflections.util.ClasspathHelper;
54 import org.reflections.util.ConfigurationBuilder;
55 import org.reflections.util.FilterBuilder;
56 import org.slf4j.Logger;
57 import org.slf4j.LoggerFactory;
60 * complete the integration of hK2 container and dropwizard
66 public class AutoConfigBundle<T extends Configuration> implements ConfiguredBundle<T> {
68 private static final Logger LOG = LoggerFactory.getLogger(AutoConfigBundle.class);
70 private ServiceLocator locator;
71 private Reflections reflections;
72 private Set<Class<?>> services;
74 private Bootstrap<?> bootstrap;
77 AutoConfigBundle(final String packageName) {
78 this(Lists.newArrayList(packageName));
81 AutoConfigBundle(List<String> packageNames) {
82 FilterBuilder filterBuilder = new FilterBuilder();
84 packageNames.stream().forEach(packageName -> {
85 filterBuilder.include(FilterBuilder.prefix(packageName));
87 ConfigurationBuilder reflectionCfg = new ConfigurationBuilder();
89 packageNames.stream().forEach(packageName -> {
90 reflectionCfg.addUrls(ClasspathHelper.forPackage(packageName));
93 reflectionCfg.filterInputsBy(filterBuilder).setScanners(new SubTypesScanner(),
94 new TypeAnnotationsScanner());
95 reflections = new Reflections(reflectionCfg);
97 locator = ServiceLocatorFactory.getInstance().create("dw-hk2");
99 ServiceLocatorHolder.setLocator(locator);
103 public static <T extends Configuration> AutoConfigBundleBuider<T> newBuilder() {
104 return new AutoConfigBundleBuider<T>();
108 public void initialize(final Bootstrap<?> bootstrap) {
110 this.bootstrap = bootstrap;
111 registerPreLoadService();
113 LOG.debug("Intialzing auto config bundle.");
116 private void registerPreLoadService() {
118 registerService(PreLoad.class);
124 public void run(final T configuration, final Environment environment) throws Exception {
126 registerConfigurationProvider(configuration, environment);
129 registerEnvironment(environment);
130 registerObjectMapper(environment);
132 environment.getApplicationContext().getServletContext()
133 .setAttribute(ServletProperties.SERVICE_LOCATOR, locator);
135 registerService(PreBaseService.class);
136 registerService(BaseService.class);
137 registerService(PostBaseService.class);
138 this.registerService(PreServiceLoad.class);
143 // registerManaged(environment);
144 registerLifecycle(environment);
145 registerServerLifecycleListeners(environment);
146 registerJettyLifeCycleListener(environment);
147 registerTasks(environment);
148 registerHealthChecks(environment);
149 registerProviders(environment);
150 registerResources(environment);
152 environment.lifecycle().manage(new ServiceLocatorManaged(locator));
158 private void registerProviders(Environment environment) {
159 reflections.getSubTypesOf(Provider.class).stream().filter(services::contains)
160 .forEach(providerKlass -> {
162 environment.jersey().register(locator.getService(providerKlass));
163 } catch (Exception e) {
167 LOG.info("Registering Dropwizard Provider, class name : {}", providerKlass.getName());
173 private void registerTasks(Environment environment) {
174 reflections.getSubTypesOf(Task.class).stream().filter(services::contains).forEach(taskKlass -> {
176 environment.admin().addTask(locator.getService(taskKlass));
177 } catch (Exception e) {
180 LOG.info("Registering Dropwizard Task, class name : {}", taskKlass.getName());
185 private void registerJettyLifeCycleListener(Environment environment) {
186 reflections.getSubTypesOf(LifeCycle.Listener.class).stream().filter(services::contains)
187 .forEach(lifecycleListenerKlass -> {
190 environment.lifecycle()
191 .addLifeCycleListener(locator.getService(lifecycleListenerKlass));
192 } catch (Exception e) {
195 LOG.info("Registering Dropwizard lifecycleListener, class name : {}",
196 lifecycleListenerKlass.getName());
201 private void registerServerLifecycleListeners(Environment environment) {
203 reflections.getSubTypesOf(ServerLifecycleListener.class).stream().filter(services::contains)
204 .forEach(serverLifecycleListenerKlass -> {
206 environment.lifecycle()
207 .addServerLifecycleListener(locator.getService(serverLifecycleListenerKlass));
208 } catch (Exception e) {
211 LOG.info("Registering Dropwizard serverLifecycleListener, class name : {}",
212 serverLifecycleListenerKlass.getName());
217 private void registerLifecycle(Environment environment) {
218 reflections.getSubTypesOf(LifeCycle.class).stream().filter(services::contains)
219 .forEach(lifeCycleKlass -> {
221 environment.lifecycle().manage(locator.getService(lifeCycleKlass));
222 } catch (Exception e) {
225 LOG.info("Registering Dropwizard LifeCycle, class name : {}", lifeCycleKlass.getName());
230 * private void registerManaged(Environment environment) {
232 * reflections.getSubTypesOf(Managed.class).stream().filter(services::contains)
233 * .forEach(managedKlass -> { try {
234 * environment.lifecycle().manage(locator.getService(managedKlass)); } catch (Exception e) {
235 * LOG.warn("", e); } LOG.info("Registering Dropwizard managed, class name : {}",
236 * managedKlass.getName()); });
241 private void registerObjectMapper(Environment environment) {
243 final ObjectMapper objectMapper = environment.getObjectMapper();
245 ServiceLocatorUtilities.bind(locator, new AbstractBinder() {
247 protected void configure() {
248 bind(objectMapper).to(ObjectMapper.class);
250 LOG.info("Registering Dropwizard objectMapper, class name : {}",
251 objectMapper.getClass().getName());
257 private void registerEnvironment(final Environment environment) {
259 ServiceLocatorUtilities.bind(locator, new AbstractBinder() {
261 protected void configure() {
262 bind(environment).to(Environment.class);
264 LOG.info("Registering Dropwizard environment, class name : {}",
265 environment.getClass().getName());
271 private void registerConfigurationProvider(final T configuration, final Environment environment) {
273 ServiceLocatorUtilities.bind(locator, new AbstractBinder() {
275 protected void configure() {
277 LOG.info("Registering Dropwizard Configuration class name:{}",
278 configuration.getClass().getName());
279 if (configuration instanceof Configuration) {
280 bind((Configuration) configuration).to(Configuration.class);
281 LOG.info("Registering Dropwizard Configuration class name:{}",
282 Configuration.class.getName());
288 registerSubConfigure(configuration, environment);
292 private void registerSubConfigure(final T configuration, final Environment environment) {
293 final List<Field> subDeclaredFields =
294 Arrays.asList(configuration.getClass().getDeclaredFields());
295 List<Field> parentDeclaredFields = Arrays.asList(Configuration.class.getDeclaredFields());
297 List<Field> filtersubDeclaredFields = subDeclaredFields.stream()
298 .filter(subDeclaredField -> !subDeclaredField.getType().isPrimitive())
299 .filter(subDeclaredField -> !subDeclaredField.getType().equals(String.class))
300 .filter(subDeclaredField -> !parentDeclaredFields.contains(subDeclaredField))
301 .collect(Collectors.toList());
303 ServiceLocatorUtilities.bind(locator, new AbstractBinder() {
305 protected void configure() {
306 filtersubDeclaredFields.forEach(subField -> {
307 subField.setAccessible(true);
309 Object subConfig = subField.get(configuration);
310 if (subConfig != null) {
312 LOG.info("Registering Dropwizard Sub Configuration class name {}",
313 subConfig.getClass().getName());
316 } catch (Exception e) {
317 LOG.error("bind sub config:{} fail", subField);
325 private void registerServices() {
326 services = this.reflections.getTypesAnnotatedWith(Service.class, true);
327 if (!services.isEmpty()) {
328 ServiceLocatorUtilities.bind(locator, new ServiceBinder(services));
330 services.forEach(s -> {
331 LOG.info("Registering Dropwizard service, class name : {}", s.getName());
334 services.stream().filter(serviceClazz -> (serviceClazz.getAnnotation(Lazy.class) == null))
335 .peek(serviceClazz -> LOG.info("active service, class name : {}", serviceClazz.getName()))
336 .forEach(serviceClazz -> {
338 long startTime = System.currentTimeMillis();
339 locator.getService(serviceClazz);
340 LOG.info("active service, class name : {},cost time:{}", serviceClazz.getName(),
341 (System.currentTimeMillis() - startTime));
342 } catch (Exception e) {
349 LOG.warn("Registering Dropwizard service is empty");
355 private void registerResources(final Environment environment) {
356 reflections.getTypesAnnotatedWith(Path.class).stream().forEach(resourceClass -> {
358 LOG.info("begin Registering Dropwizard resource, class name : {}", resourceClass.getName());
360 Object resourceObject = locator.getService(resourceClass);
361 if (resourceObject != null) {
362 environment.jersey().register(resourceObject);
363 LOG.info("Registering Dropwizard resource, class name : {}", resourceClass.getName());
365 LOG.warn(resourceClass.getName() + " not use Service annotation");
367 } catch (Exception e) {
375 private void registerHealthChecks(final Environment env) {
377 reflections.getSubTypesOf(HealthCheck.class).stream().filter(services::contains)
378 .forEach(healthCheckKlass -> {
380 env.healthChecks().register(healthCheckKlass.getName(),
381 locator.getService(healthCheckKlass));
382 } catch (Exception e) {
385 LOG.info("Registering Dropwizard healthCheck, class name : {}",
386 healthCheckKlass.getName());
393 private void registerService(Class<? extends Annotation> annotationClazz) {
395 Set<Class<?>> services = this.reflections.getTypesAnnotatedWith(annotationClazz, true);
396 if (!services.isEmpty()) {
397 ServiceLocatorUtilities.bind(locator, new ServiceBinder(services));
399 services.forEach(s -> {
400 LOG.info("{} Registering service, class name : {}", annotationClazz.getName(),
404 services.stream().filter(serviceClazz -> (serviceClazz.getAnnotation(Lazy.class) == null))
405 .peek(serviceClazz -> LOG.info("active service, class name : {}", serviceClazz.getName()))
406 .forEach(serviceClazz -> {
408 long startTime = System.currentTimeMillis();
409 locator.getService(serviceClazz);
410 LOG.info("active service, class name : {},cost time:{}", serviceClazz.getName(),
411 (System.currentTimeMillis() - startTime));
412 } catch (Exception e) {
419 LOG.warn("Registering {} service is empty", annotationClazz.getName());