1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.bremersee.exception.spring.boot.autoconfigure.reactive;
18
19 import org.apache.commons.logging.Log;
20 import org.apache.commons.logging.LogFactory;
21 import org.bremersee.exception.RestApiExceptionMapper;
22 import org.bremersee.exception.spring.boot.autoconfigure.RestApiExceptionMapperBootProperties;
23 import org.springframework.beans.factory.ObjectProvider;
24 import org.springframework.boot.autoconfigure.AutoConfiguration;
25 import org.springframework.boot.autoconfigure.AutoConfigureAfter;
26 import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
27 import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
28 import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
29 import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
30 import org.springframework.boot.autoconfigure.web.WebProperties;
31 import org.springframework.boot.context.event.ApplicationReadyEvent;
32 import org.springframework.boot.context.properties.EnableConfigurationProperties;
33 import org.springframework.boot.webflux.error.ErrorAttributes;
34 import org.springframework.context.ApplicationContext;
35 import org.springframework.context.annotation.Bean;
36 import org.springframework.context.event.EventListener;
37 import org.springframework.core.annotation.Order;
38 import org.springframework.http.codec.ServerCodecConfigurer;
39 import org.springframework.util.Assert;
40 import org.springframework.util.ClassUtils;
41
42
43
44
45
46
47 @ConditionalOnWebApplication(type = Type.REACTIVE)
48 @ConditionalOnClass(name = {
49 "tools.jackson.databind.ObjectMapper",
50 "org.bremersee.exception.RestApiExceptionMapper"
51 })
52 @ConditionalOnBean({
53 ErrorAttributes.class,
54 WebProperties.class,
55 ServerCodecConfigurer.class
56 })
57 @AutoConfigureAfter({
58 RestApiExceptionMapperForWebFluxAutoConfiguration.class
59 })
60 @AutoConfiguration
61 @EnableConfigurationProperties({RestApiExceptionMapperBootProperties.class})
62 public class ApiExceptionHandlerAutoConfiguration {
63
64 private static final Log log = LogFactory.getLog(ApiExceptionHandlerAutoConfiguration.class);
65
66 private final RestApiExceptionMapperBootProperties properties;
67
68
69
70
71
72
73 public ApiExceptionHandlerAutoConfiguration(
74 RestApiExceptionMapperBootProperties properties) {
75 this.properties = properties;
76 }
77
78
79
80
81 @EventListener(ApplicationReadyEvent.class)
82 public void init() {
83 log.info(String.format("""
84
85 *********************************************************************************
86 * %s
87 *********************************************************************************
88 * apiPaths = %s
89 *********************************************************************************""",
90 ClassUtils.getUserClass(getClass()).getSimpleName(),
91 properties.getApiPaths()));
92 }
93
94
95
96
97
98
99
100
101
102
103
104 @Bean
105 @Order(-2)
106 public ApiExceptionHandler apiExceptionHandler(
107 ObjectProvider<ErrorAttributes> errorAttributes,
108 ObjectProvider<WebProperties> webProperties,
109 ApplicationContext applicationContext,
110 ObjectProvider<ServerCodecConfigurer> serverCodecConfigurer,
111 ObjectProvider<RestApiExceptionMapper> restApiExceptionMapper) {
112
113 Assert.notNull(
114 errorAttributes.getIfAvailable(),
115 "Error attributes must be present.");
116 Assert.notNull(
117 serverCodecConfigurer.getIfAvailable(),
118 "Server codec configurer must be present.");
119 Assert.notNull(
120 restApiExceptionMapper.getIfAvailable(),
121 "Rest api exception mapper must be present.");
122
123 return new ApiExceptionHandler(
124 properties.getApiPaths(),
125 errorAttributes.getIfAvailable(),
126 webProperties.getIfAvailable(WebProperties::new).getResources(),
127 applicationContext,
128 serverCodecConfigurer.getIfAvailable(),
129 restApiExceptionMapper.getIfAvailable());
130 }
131
132 }