org.springframework.cloud.dataflow.server.config.web.WebConfiguration.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.cloud.dataflow.server.config.web.WebConfiguration.java

Source

/*
 * Copyright 2015 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springframework.cloud.dataflow.server.config.web;

import java.util.Arrays;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

import org.springframework.batch.core.StepExecution;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
import org.springframework.cloud.dataflow.rest.job.support.ISO8601DateFormatWithMilliSeconds;
import org.springframework.cloud.dataflow.server.job.support.ExecutionContextJacksonMixIn;
import org.springframework.cloud.dataflow.server.job.support.StepExecutionJacksonMixIn;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.hateoas.core.DefaultRelProvider;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

/**
 * @author Mark Fisher
 * @author Marius Bogoevici
 * @author Patrick Peralta
 * @author Gunnar Hillert
 * @author Ilayaperumal Gopinathan
 */
@Configuration
@ConditionalOnWebApplication
public class WebConfiguration {

    private static final String SPRING_HATEOAS_OBJECT_MAPPER = "_halObjectMapper";

    private static final String REL_PROVIDER_BEAN_NAME = "defaultRelProvider";

    /**
     * Obtains the Spring Hateos Object Mapper so that we can apply SCDF Batch Mixins to
     * ignore the JobExecution in StepExecution to prevent infinite loop.
     * {@see https://github.com/spring-projects/spring-hateoas/issues/333}
     */
    @Autowired
    @Qualifier(SPRING_HATEOAS_OBJECT_MAPPER)
    private ObjectMapper springHateoasObjectMapper;

    @Bean
    @Primary
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = springHateoasObjectMapper;
        setupObjectMapper(objectMapper);
        return objectMapper;
    }

    @Bean
    public HttpMessageConverters messageConverters() {
        final ObjectMapper objectMapper = new ObjectMapper();
        setupObjectMapper(objectMapper);
        return new HttpMessageConverters(
                // Prevent default converters
                false,
                // Have Jackson2 converter as the sole converter
                Arrays.<HttpMessageConverter<?>>asList(new MappingJackson2HttpMessageConverter(objectMapper)));
    }

    @Bean
    public WebMvcConfigurer configurer() {
        return new WebMvcConfigurerAdapter() {

            @Override
            public void configurePathMatch(PathMatchConfigurer configurer) {
                configurer.setUseSuffixPatternMatch(false);
            }
        };
    }

    private void setupObjectMapper(ObjectMapper objectMapper) {
        objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        objectMapper.setDateFormat(new ISO8601DateFormatWithMilliSeconds());
        objectMapper.addMixIn(StepExecution.class, StepExecutionJacksonMixIn.class);
        objectMapper.addMixIn(ExecutionContext.class, ExecutionContextJacksonMixIn.class);
    }

    @Bean
    public BeanPostProcessor relProviderOverridingBeanPostProcessor() {
        return new BeanPostProcessor() {
            @Override
            public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
                // Override the RelProvider to DefaultRelProvider
                // Since DataFlow UI expects DefaultRelProvider to be used, override any
                // other instance of
                // DefaultRelProvider (EvoInflectorRelProvider for instance) with the
                // DefaultRelProvider.
                if (beanName != null && beanName.equals(REL_PROVIDER_BEAN_NAME)) {
                    return new DefaultRelProvider();
                }
                return bean;
            }

            @Override
            public Object postProcessAfterInitialization(Object bean, String s) throws BeansException {
                return bean;
            }
        };
    }

    @Bean
    public MethodValidationPostProcessor methodValidationPostProcessor() {
        return new MethodValidationPostProcessor();
    }

}