View Javadoc
1   package cn.home1.oss.lib.errorhandle.starter;
2   
3   import com.google.common.collect.ImmutableMap;
4   
5   import cn.home1.oss.lib.errorhandle.api.ApplicationException;
6   import cn.home1.oss.lib.errorhandle.api.ConcreteExceptionResolver;
7   import cn.home1.oss.lib.errorhandle.api.ExceptionResolver;
8   import cn.home1.oss.lib.errorhandle.api.ExceptionTranslator;
9   import cn.home1.oss.lib.errorhandle.api.StackTraceIndicator;
10  import cn.home1.oss.lib.errorhandle.internal.CompositeExceptionResolver;
11  import cn.home1.oss.lib.errorhandle.internal.resolver.ApplicationErrorExceptionResolver;
12  import cn.home1.oss.lib.errorhandle.internal.resolver.ConstraintViolationExceptionResolver;
13  import cn.home1.oss.lib.errorhandle.internal.resolver.DefaultExceptionResolver;
14  import cn.home1.oss.lib.errorhandle.internal.resolver.HttpMediaTypeNotSupportedExceptionResolver;
15  import cn.home1.oss.lib.errorhandle.internal.resolver.HttpRequestMethodNotSupportedExceptionResolver;
16  import cn.home1.oss.lib.errorhandle.internal.resolver.MethodArgumentNotValidExceptionResolver;
17  
18  import lombok.Setter;
19  import lombok.extern.slf4j.Slf4j;
20  
21  import org.springframework.beans.factory.FactoryBean;
22  import org.springframework.beans.factory.annotation.Autowired;
23  import org.springframework.core.convert.ConversionService;
24  import org.springframework.core.convert.support.DefaultConversionService;
25  import org.springframework.util.ClassUtils;
26  import org.springframework.web.HttpMediaTypeNotSupportedException;
27  import org.springframework.web.HttpRequestMethodNotSupportedException;
28  import org.springframework.web.bind.MethodArgumentNotValidException;
29  
30  import java.util.Map;
31  
32  @Setter
33  @Slf4j
34  public class CompositeExceptionResolverFactoryBean implements FactoryBean<ExceptionResolver<Throwable>> {
35  
36    public static final String CONSTRAINT_VIOLATION_EXCEPTION = "javax.validation.ConstraintViolationException";
37  
38    @Autowired
39    private ExceptionTranslator exceptionTranslator;
40    @Autowired
41    private StackTraceIndicator stackTraceIndicator;
42  
43    @SuppressWarnings({"rawtypes", "unchecked"})
44    static Map<Class<? extends Throwable>, ConcreteExceptionResolver> buildInResolvers( //
45      final ConversionService conversionService, //
46      final ExceptionTranslator exceptionTranslator, //
47      final StackTraceIndicator stackTraceIndicator //
48    ) {
49      final ImmutableMap.Builder<Class<? extends Throwable>, ConcreteExceptionResolver> builder = ImmutableMap.builder();
50  
51      if (ClassUtils.isPresent( //
52        CONSTRAINT_VIOLATION_EXCEPTION, //
53        Thread.currentThread().getContextClassLoader() //
54      )) {
55        try {
56          final Class clazz = Class.forName(CONSTRAINT_VIOLATION_EXCEPTION);
57          builder.put(clazz, new ConstraintViolationExceptionResolver());
58        } catch (final ClassNotFoundException ex) {
59          // ignore
60          if (log.isDebugEnabled()) {
61            log.debug("class {} not found", CONSTRAINT_VIOLATION_EXCEPTION, ex);
62          }
63        }
64      }
65  
66      builder.put(HttpMediaTypeNotSupportedException.class, new HttpMediaTypeNotSupportedExceptionResolver());
67      builder.put(HttpRequestMethodNotSupportedException.class, new HttpRequestMethodNotSupportedExceptionResolver());
68      builder.put(MethodArgumentNotValidException.class, new MethodArgumentNotValidExceptionResolver());
69      builder.put(ApplicationException.class, new ApplicationErrorExceptionResolver());
70  
71      final Map<Class<? extends Throwable>, ConcreteExceptionResolver> map = builder.build();
72      map.values().forEach(exceptionResolver -> {
73        exceptionResolver.setConversionService(conversionService);
74        exceptionResolver.setExceptionTranslator(exceptionTranslator);
75        exceptionResolver.setStackTraceIndicator(stackTraceIndicator);
76      });
77  
78      return map;
79    }
80  
81    @Override
82    public ExceptionResolver<Throwable> getObject() {
83      final ConversionService conversionService = new DefaultConversionService(); // TODO conversionService
84  
85      @SuppressWarnings("rawtypes")
86      final Map<Class<? extends Throwable>, ConcreteExceptionResolver> buildInResolvers = buildInResolvers( //
87        conversionService, //
88        this.exceptionTranslator, //
89        this.stackTraceIndicator //
90      );
91  
92      final DefaultExceptionResolver defaultResolver = new DefaultExceptionResolver();
93      defaultResolver.setConversionService(conversionService);
94      defaultResolver.setExceptionTranslator(this.exceptionTranslator);
95      defaultResolver.setStackTraceIndicator(this.stackTraceIndicator);
96  
97      final CompositeExceptionResolver compositeExceptionResolver = new CompositeExceptionResolver();
98      compositeExceptionResolver.setDefaultResolver(defaultResolver);
99      compositeExceptionResolver.setResolverMap(buildInResolvers);
100 
101     return compositeExceptionResolver;
102   }
103 
104   @Override
105   public Class<?> getObjectType() {
106     return ExceptionResolver.class;
107   }
108 
109   @Override
110   public boolean isSingleton() {
111     return false;
112   }
113 }