Package com.github.jknack.mwa

Source Code of com.github.jknack.mwa.WebDefaults$LogUncaughtException

package com.github.jknack.mwa;

import static com.github.jknack.mwa.ApplicationConstants.APP_STARTUP_CLASS;
import static org.apache.commons.lang3.Validate.notNull;

import java.beans.PropertyDescriptor;
import java.security.Principal;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration;
import org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver;
import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver;
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;

import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.introspect.VisibilityChecker;
import com.github.jknack.mwa.web.JacksonViewMethodProcessor;

/**
* Apply sensible defaults Spring MVC options, like:
* <ul>
* <li>Enable default servlet.
* <li>Get HandlerExceptionResolver from the Spring Application Context.
* </ul>
*
* @author edgar.espina
* @since 0.1
*/
@Configuration
class WebDefaults extends DelegatingWebMvcConfiguration implements
    InstantiationAwareBeanPostProcessor {

  /**
   * Log any uncaught exception.
   *
   * @author edgar.espina
   * @since 0.3.3
   */
  private static class LogUncaughtException extends DefaultHandlerExceptionResolver {

    /**
     * The logging system.
     */
    private Logger logger;

    /**
     * Creates a new exception handler.
     *
     * @param context The application's context. Required.
     */
    public LogUncaughtException(final ApplicationContext context) {
      notNull(context, "The application's context is required.");
      String rootClass = context.getEnvironment().getProperty(APP_STARTUP_CLASS);
      logger = LoggerFactory.getLogger(rootClass);
    }

    @Override
    protected void logException(final Exception ex, final HttpServletRequest request) {
      String message = "Handler execution resulted in exception\n"
          + "  uri: %s\n"
          + "  user: %s";
      String uri = request.getRequestURI();
      String queryString = request.getQueryString();
      if (queryString != null) {
        uri += "?" + queryString;
      }
      Principal principal = request.getUserPrincipal();
      String userName = principal == null ? "unknown" : principal.getName();
      logger.error(String.format(message, uri, userName), ex);
    }
  }

  /**
   * The jackson2 object mapper bean's name.
   */
  static final String OBJECT_MAPPER = "jackson2ObjectMapper";

  /**
   * The local bean validator.
   */
  private LocalValidatorFactoryBean localValidatorFactoryBean;

  /**
   * The application's context.
   */
  private ApplicationContext applicationContext;

  @Override
  public Object postProcessBeforeInitialization(final Object bean,
      final String beanName) {
    return BeanPostProcessors.get(bean).processBeforeInitialization(
        applicationContext, bean);
  }

  @Override
  public Object postProcessAfterInitialization(final Object bean,
      final String beanName) {
    return BeanPostProcessors.get(bean).processAfterInitialization(
        applicationContext, bean);
  }

  @Override
  public void setApplicationContext(final ApplicationContext applicationContext) {
    super.setApplicationContext(applicationContext);
    this.applicationContext = applicationContext;
  }

  @Override
  public Object postProcessBeforeInstantiation(final Class<?> beanClass,
      final String beanName) {
    return null;
  }

  @Override
  public boolean postProcessAfterInstantiation(final Object bean,
      final String beanName) {
    BeanPostProcessors.get(bean).processAfterInstantiation(
        applicationContext, bean);
    return true;
  }

  @Override
  public PropertyValues postProcessPropertyValues(final PropertyValues pvs,
      final PropertyDescriptor[] pds, final Object bean,
      final String beanName) {
    return pvs;
  }

  /**
   * Enable the default servlet. {@inheritDoc}
   */
  @Override
  public void configureDefaultServletHandling(
      final DefaultServletHandlerConfigurer configurer) {
    configurer.enable();
  }

  /**
   * Publish a new object mapper.
   *
   * @return A new object mapper.
   */
  @Bean(name = OBJECT_MAPPER)
  @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
  public ObjectMapper jackson2ObjectMapper() {
    ObjectMapper mapper = new ObjectMapper();
    SerializationConfig serializationConfig = mapper.getSerializationConfig();
    VisibilityChecker<?> visibilityChecker = serializationConfig.getDefaultVisibilityChecker();
    // Field visibility by default.
    mapper.setVisibilityChecker(visibilityChecker
        .withFieldVisibility(Visibility.ANY)
        .withGetterVisibility(Visibility.NONE)
        .withSetterVisibility(Visibility.NONE)
        .withCreatorVisibility(Visibility.PROTECTED_AND_PUBLIC)
        );
    return mapper;
  }

  /**
   * A return value processor for method marked with JsonView and ResponseBody.
   *
   * @return A return value processor for method marked with JsonView and
   *         ResponseBody.
   */
  @Bean
  @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
  public JacksonViewMethodProcessor jacksonViewMethodProcessor() {
    return new JacksonViewMethodProcessor(jackson2ObjectMapper());
  }

  @Override
  public void configureHandlerExceptionResolvers(
      final List<HandlerExceptionResolver> exceptionResolvers) {
    ExceptionHandlerExceptionResolver exceptionHandlerExceptionResolver =
        new ExceptionHandlerExceptionResolver();
    exceptionHandlerExceptionResolver.setMessageConverters(getMessageConverters());
    exceptionHandlerExceptionResolver.afterPropertiesSet();

    exceptionResolvers.add(exceptionHandlerExceptionResolver);
    exceptionResolvers.add(new ResponseStatusExceptionResolver());
    exceptionResolvers.add(new LogUncaughtException(applicationContext));
  }

  /**
   * Publish a {@link LocalValidatorFactoryBean}.
   *
   * @return A {@link LocalValidatorFactoryBean}.
   */
  @Bean
  @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
  public LocalValidatorFactoryBean localValidatorFactoryBean() {
    if (localValidatorFactoryBean == null) {
      localValidatorFactoryBean = new LocalValidatorFactoryBean();
    }
    return localValidatorFactoryBean;
  }

  @Override
  protected Validator getValidator() {
    return localValidatorFactoryBean();
  }

}
TOP

Related Classes of com.github.jknack.mwa.WebDefaults$LogUncaughtException

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.