Improve JerseyConfiguration by use of generics 17/73917/7
authorkurczews <krzysztof.kurczewski@nokia.com>
Thu, 29 Nov 2018 09:45:45 +0000 (10:45 +0100)
committerkurczews <krzysztof.kurczewski@nokia.com>
Wed, 5 Dec 2018 12:59:01 +0000 (13:59 +0100)
Issue-ID: AAI-1974
Change-Id: If48cc66b19aa2fdb6f6e64ddbd6059a88fe7296f
Signed-off-by: kurczews <krzysztof.kurczewski@nokia.com>
aai-resources/src/main/java/org/onap/aai/web/JerseyConfiguration.java

index 4cd09bf..9592639 100644 (file)
  */
 package org.onap.aai.web;
 
+import static java.lang.Boolean.parseBoolean;
+import static java.util.Comparator.comparingInt;
+
+import java.lang.reflect.AnnotatedElement;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Set;
+import java.util.logging.Logger;
+import javax.annotation.Priority;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ContainerResponseFilter;
+import jersey.repackaged.com.google.common.collect.Sets;
 import org.glassfish.jersey.filter.LoggingFilter;
 import org.glassfish.jersey.server.ResourceConfig;
-import org.onap.aai.rest.*;
+import org.onap.aai.rest.BulkAddConsumer;
+import org.onap.aai.rest.BulkProcessConsumer;
+import org.onap.aai.rest.ExampleConsumer;
+import org.onap.aai.rest.LegacyMoxyConsumer;
+import org.onap.aai.rest.URLFromVertexIdConsumer;
+import org.onap.aai.rest.VertexIdConsumer;
 import org.onap.aai.rest.bulk.BulkSingleTransactionConsumer;
 import org.onap.aai.rest.util.EchoResponse;
 import org.reflections.Reflections;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Profile;
 import org.springframework.core.env.Environment;
-import org.springframework.stereotype.Component;
 
-import javax.annotation.Priority;
-import javax.ws.rs.container.ContainerRequestFilter;
-import javax.ws.rs.container.ContainerResponseFilter;
-import java.util.List;
-import java.util.Set;
-import java.util.logging.Logger;
-import java.util.stream.Collectors;
-
-@Component
-public class JerseyConfiguration extends ResourceConfig {
+@Configuration
+public class JerseyConfiguration {
 
     private static final Logger log = Logger.getLogger(JerseyConfiguration.class.getName());
 
-    private Environment env;
+    private static final String LOGGING_ENABLED_PROPERTY = "aai.request.logging.enabled";
+    private static final String INTERCEPTOR_PACKAGE = "org.onap.aai.interceptors";
+    private static final boolean ENABLE_RESPONSE_LOGGING = false;
+
+    private final Reflections reflections = new Reflections(INTERCEPTOR_PACKAGE);
+    private final Environment environment;
 
     @Autowired
-    public JerseyConfiguration(Environment env) {
-
-        this.env = env;
-
-        register(EchoResponse.class);
-        register(VertexIdConsumer.class);
-        register(ExampleConsumer.class);
-        register(BulkAddConsumer.class);
-        register(BulkProcessConsumer.class);
-        register(BulkSingleTransactionConsumer.class);
-        register(LegacyMoxyConsumer.class);
-        register(URLFromVertexIdConsumer.class);
-
-        //Request Filters
-        registerFiltersForRequests();
-        // Response Filters
-        registerFiltersForResponses();
-
-        // Following registers the request headers and response headers
-        // If the LoggingFilter second argument is set to true, it will print response value as well
-        if ("true".equalsIgnoreCase(env.getProperty("aai.request.logging.enabled"))) {
-            register(new LoggingFilter(log, false));
+    public JerseyConfiguration(Environment environment) {
+        this.environment = environment;
+    }
+
+    @Bean
+    public ResourceConfig resourceConfig() {
+        ResourceConfig resourceConfig = new ResourceConfig();
+
+        Set<Class<?>> classes = Sets.newHashSet(
+            EchoResponse.class,
+            VertexIdConsumer.class,
+            ExampleConsumer.class,
+            BulkAddConsumer.class,
+            BulkProcessConsumer.class,
+            BulkSingleTransactionConsumer.class,
+            LegacyMoxyConsumer.class,
+            URLFromVertexIdConsumer.class
+        );
+        resourceConfig.registerClasses(classes);
+        registerFiltersForClasses(resourceConfig, ContainerRequestFilter.class, ContainerResponseFilter.class);
+
+        if (isLoggingEnabled()) {
+            logRequests(resourceConfig);
         }
+
+        return resourceConfig;
     }
 
-    public void registerFiltersForRequests() {
+    private void registerFiltersForClasses(ResourceConfig resourceConfig, Class<?>... classes) {
+        for (Class<?> clazz : classes) {
+            registerFiltersFor(clazz, resourceConfig);
+        }
+    }
+
+    private <T> void registerFiltersFor(Class<T> clazz, ResourceConfig resourceConfig) {
+        Set<Class<? extends T>> filters = reflections.getSubTypesOf(clazz);
 
-        // Find all the classes within the interceptors package
-        Reflections reflections = new Reflections("org.onap.aai.interceptors");
-        // Filter them based on the clazz that was passed in
-        Set<Class<? extends ContainerRequestFilter>> filters = reflections.getSubTypesOf(ContainerRequestFilter.class);
+        throwIfPriorityAnnotationAbsent(filters);
 
+        filters.stream()
+            .filter(this::isEnabledByActiveProfiles)
+            .sorted(priorityComparator())
+            .forEach(resourceConfig::register);
+    }
 
-        // Check to ensure that each of the filter has the @Priority annotation and if not throw exception
-        for (Class filterClass : filters) {
-            if (filterClass.getAnnotation(Priority.class) == null) {
-                throw new RuntimeException("Container filter " + filterClass.getName() + " does not have @Priority annotation");
+    private <T> void throwIfPriorityAnnotationAbsent(Collection<Class<? extends T>> classes) {
+        for (Class clazz : classes) {
+            if (!clazz.isAnnotationPresent(Priority.class)) {
+                throw new MissingFilterPriorityException(clazz);
             }
         }
+    }
 
-        // Turn the set back into a list
-        List<Class<? extends ContainerRequestFilter>> filtersList = filters
-                .stream()
-                .filter(f -> {
-                    if (f.isAnnotationPresent(Profile.class)
-                            && !env.acceptsProfiles(f.getAnnotation(Profile.class).value())) {
-                        return false;
-                    }
-                    return true;
-                })
-                .collect(Collectors.toList());
-
-        // Sort them by their priority levels value
-        filtersList.sort((c1, c2) -> Integer.valueOf(c1.getAnnotation(Priority.class).value()).compareTo(c2.getAnnotation(Priority.class).value()));
-
-        // Then register this to the jersey application
-        filtersList.forEach(this::register);
+    private <T> Comparator<Class<? extends T>> priorityComparator() {
+        return comparingInt(clazz -> clazz.getAnnotation(Priority.class).value());
     }
 
-    public void registerFiltersForResponses() {
+    private void logRequests(ResourceConfig resourceConfig) {
+        resourceConfig.register(new LoggingFilter(log, ENABLE_RESPONSE_LOGGING));
+    }
 
-        // Find all the classes within the interceptors package
-        Reflections reflections = new Reflections("org.onap.aai.interceptors");
-        // Filter them based on the clazz that was passed in
-        Set<Class<? extends ContainerResponseFilter>> filters = reflections.getSubTypesOf(ContainerResponseFilter.class);
+    private boolean isLoggingEnabled() {
+        return parseBoolean(environment.getProperty(LOGGING_ENABLED_PROPERTY));
+    }
 
+    private boolean isEnabledByActiveProfiles(AnnotatedElement annotatedElement) {
+        return !annotatedElement.isAnnotationPresent(Profile.class) ||
+            environment.acceptsProfiles(annotatedElement.getAnnotation(Profile.class).value());
+    }
 
-        // Check to ensure that each of the filter has the @Priority annotation and if not throw exception
-        for (Class filterClass : filters) {
-            if (filterClass.getAnnotation(Priority.class) == null) {
-                throw new RuntimeException("Container filter " + filterClass.getName() + " does not have @Priority annotation");
-            }
+    private class MissingFilterPriorityException extends RuntimeException {
+        private MissingFilterPriorityException(Class<?> clazz) {
+            super("Container filter " + clazz.getName() + " does not have @Priority annotation");
         }
-
-        // Turn the set back into a list
-        List<Class<? extends ContainerResponseFilter>> filtersList = filters.stream()
-                .filter(f -> {
-                    if (f.isAnnotationPresent(Profile.class)
-                            && !env.acceptsProfiles(f.getAnnotation(Profile.class).value())) {
-                        return false;
-                    }
-                    return true;
-                })
-                .collect(Collectors.toList());
-
-        // Sort them by their priority levels value
-        filtersList.sort((c1, c2) -> Integer.valueOf(c1.getAnnotation(Priority.class).value()).compareTo(c2.getAnnotation(Priority.class).value()));
-
-        // Then register this to the jersey application
-        filtersList.forEach(this::register);
     }
-}
+}
\ No newline at end of file