View Javadoc
1   /*
2   * Copyright 2020-2026 the original author or authors.
3    *
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
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
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.
15   */
16  
17  package org.bremersee.xml.spring.boot.http.codec;
18  
19  import java.util.AbstractCollection;
20  import java.util.HashSet;
21  import java.util.Objects;
22  import java.util.Set;
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.bremersee.xml.JaxbContextBuilder;
26  import org.bremersee.xml.http.codec.ReactiveJaxbDecoder;
27  import org.bremersee.xml.http.codec.ReactiveJaxbEncoder;
28  import org.bremersee.xml.spring.boot.JaxbContextBuilderAutoConfiguration;
29  import org.bremersee.xml.spring.boot.http.JaxbReadWriteConfigurer;
30  import org.jspecify.annotations.NonNull;
31  import org.springframework.beans.factory.ObjectProvider;
32  import org.springframework.boot.autoconfigure.AutoConfiguration;
33  import org.springframework.boot.autoconfigure.AutoConfigureAfter;
34  import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
35  import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
36  import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
37  import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
38  import org.springframework.boot.context.event.ApplicationReadyEvent;
39  import org.springframework.context.event.EventListener;
40  import org.springframework.http.codec.ServerCodecConfigurer;
41  import org.springframework.util.ClassUtils;
42  import org.springframework.web.reactive.config.WebFluxConfigurer;
43  
44  /**
45   * The Jaxb 2 http message codec autoconfiguration.
46   *
47   * @author Christian Bremer
48   */
49  @ConditionalOnWebApplication(type = Type.REACTIVE)
50  @ConditionalOnClass({WebFluxConfigurer.class, JaxbContextBuilder.class})
51  @ConditionalOnBean(JaxbContextBuilder.class)
52  @AutoConfigureAfter(JaxbContextBuilderAutoConfiguration.class)
53  @AutoConfiguration
54  public class Jaxb2HttpMessageCodecAutoConfiguration implements WebFluxConfigurer {
55  
56    private static final Log log = LogFactory.getLog(Jaxb2HttpMessageCodecAutoConfiguration.class);
57  
58    private final JaxbContextBuilder jaxbContextBuilder;
59  
60    private final Set<Class<?>> ignoreReadingClasses;
61  
62    private final Set<Class<?>> ignoreWritingClasses;
63  
64    /**
65     * Instantiates a new Jaxb 2 http message codec autoconfiguration.
66     *
67     * @param jaxbContextBuilder the jaxb context builder
68     * @param readWriteConfigurers the read write configurers
69     */
70    public Jaxb2HttpMessageCodecAutoConfiguration(
71        ObjectProvider<JaxbContextBuilder> jaxbContextBuilder,
72        ObjectProvider<JaxbReadWriteConfigurer> readWriteConfigurers) {
73      this.jaxbContextBuilder = jaxbContextBuilder.getIfAvailable();
74      this.ignoreReadingClasses = readWriteConfigurers
75          .stream()
76          .collect(
77              HashSet::new,
78              (a, b) -> a.addAll(b.getIgnoreReadingClasses()),
79              AbstractCollection::addAll);
80      this.ignoreWritingClasses = readWriteConfigurers
81          .stream()
82          .collect(
83              HashSet::new,
84              (a, b) -> a.addAll(b.getIgnoreWritingClasses()),
85              AbstractCollection::addAll);
86    }
87  
88    /**
89     * Init.
90     */
91    @EventListener(ApplicationReadyEvent.class)
92    public void init() {
93      log.info(String.format("""
94              
95              *********************************************************************************
96              * %s
97              *********************************************************************************
98              * jaxbContextBuilder = %s
99              * ignoreReadingClasses = %s
100             * ignoreWritingClasses = %s
101             *********************************************************************************""",
102         ClassUtils.getUserClass(getClass()).getSimpleName(),
103         jaxbContextBuilder, ignoreReadingClasses, ignoreWritingClasses));
104   }
105 
106   @Override
107   public void configureHttpMessageCodecs(@NonNull ServerCodecConfigurer configurer) {
108     if (Objects.nonNull(jaxbContextBuilder)) {
109       log.info("Registering jaxb encoder and decoder.");
110       configurer
111           .customCodecs()
112           .registerWithDefaultConfig(new ReactiveJaxbEncoder(
113               jaxbContextBuilder, ignoreWritingClasses));
114       configurer
115           .customCodecs()
116           .registerWithDefaultConfig(new ReactiveJaxbDecoder(
117               jaxbContextBuilder, ignoreReadingClasses));
118     }
119   }
120 
121 }