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 bind((Configuration) configuration).to(Configuration.class);
280 LOG.info("Registering Dropwizard Configuration class name:{}",
281 Configuration.class.getName());
285 registerSubConfigure(configuration, environment);
289 private void registerSubConfigure(final T configuration, final Environment environment) {
290 final List<Field> subDeclaredFields =
291 Arrays.asList(configuration.getClass().getDeclaredFields());
292 List<Field> parentDeclaredFields = Arrays.asList(Configuration.class.getDeclaredFields());
294 List<Field> filtersubDeclaredFields = subDeclaredFields.stream()
295 .filter(subDeclaredField -> !subDeclaredField.getType().isPrimitive())
296 .filter(subDeclaredField -> !subDeclaredField.getType().equals(String.class))
297 .filter(subDeclaredField -> !parentDeclaredFields.contains(subDeclaredField))
298 .collect(Collectors.toList());
300 ServiceLocatorUtilities.bind(locator, new AbstractBinder() {
302 protected void configure() {
303 filtersubDeclaredFields.forEach(subField -> {
304 subField.setAccessible(true);
306 Object subConfig = subField.get(configuration);
307 if (subConfig != null) {
309 LOG.info("Registering Dropwizard Sub Configuration class name {}",
310 subConfig.getClass().getName());
313 } catch (Exception e) {
314 LOG.error("bind sub config:{} fail", subField);
322 private void registerServices() {
323 services = this.reflections.getTypesAnnotatedWith(Service.class, true);
324 if (!services.isEmpty()) {
325 ServiceLocatorUtilities.bind(locator, new ServiceBinder(services));
327 services.forEach(s -> {
328 LOG.info("Registering Dropwizard service, class name : {}", s.getName());
331 services.stream().filter(serviceClazz -> (serviceClazz.getAnnotation(Lazy.class) == null))
332 .peek(serviceClazz -> LOG.info("active service, class name : {}", serviceClazz.getName()))
333 .forEach(serviceClazz -> {
335 long startTime = System.currentTimeMillis();
336 locator.getService(serviceClazz);
337 LOG.info("active service, class name : {},cost time:{}", serviceClazz.getName(),
338 (System.currentTimeMillis() - startTime));
339 } catch (Exception e) {
346 LOG.warn("Registering Dropwizard service is empty");
352 private void registerResources(final Environment environment) {
353 reflections.getTypesAnnotatedWith(Path.class).stream().forEach(resourceClass -> {
355 LOG.info("begin Registering Dropwizard resource, class name : {}", resourceClass.getName());
357 Object resourceObject = locator.getService(resourceClass);
358 if (resourceObject != null) {
359 environment.jersey().register(resourceObject);
360 LOG.info("Registering Dropwizard resource, class name : {}", resourceClass.getName());
362 LOG.warn(resourceClass.getName() + " not use Service annotation");
364 } catch (Exception e) {
372 private void registerHealthChecks(final Environment env) {
374 reflections.getSubTypesOf(HealthCheck.class).stream().filter(services::contains)
375 .forEach(healthCheckKlass -> {
377 env.healthChecks().register(healthCheckKlass.getName(),
378 locator.getService(healthCheckKlass));
379 } catch (Exception e) {
382 LOG.info("Registering Dropwizard healthCheck, class name : {}",
383 healthCheckKlass.getName());
390 private void registerService(Class<? extends Annotation> annotationClazz) {
392 Set<Class<?>> services = this.reflections.getTypesAnnotatedWith(annotationClazz, true);
393 if (!services.isEmpty()) {
394 ServiceLocatorUtilities.bind(locator, new ServiceBinder(services));
396 services.forEach(s -> {
397 LOG.info("{} Registering service, class name : {}", annotationClazz.getName(),
401 services.stream().filter(serviceClazz -> (serviceClazz.getAnnotation(Lazy.class) == null))
402 .peek(serviceClazz -> LOG.info("active service, class name : {}", serviceClazz.getName()))
403 .forEach(serviceClazz -> {
405 long startTime = System.currentTimeMillis();
406 locator.getService(serviceClazz);
407 LOG.info("active service, class name : {},cost time:{}", serviceClazz.getName(),
408 (System.currentTimeMillis() - startTime));
409 } catch (Exception e) {
416 LOG.warn("Registering {} service is empty", annotationClazz.getName());