All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.hateoas.config.WebMvcHateoasConfiguration Maven / Gradle / Ivy

Go to download

Library to support implementing representations for hyper-text driven REST web services.

There is a newer version: 2.4.0
Show newest version
/*
 * Copyright 2019-2024 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
 *
 *      https://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.hateoas.config;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.hateoas.server.RepresentationModelProcessor;
import org.springframework.hateoas.server.core.DummyInvocationUtils;
import org.springframework.hateoas.server.mvc.RepresentationModelProcessorHandlerMethodReturnValueHandler;
import org.springframework.hateoas.server.mvc.RepresentationModelProcessorInvoker;
import org.springframework.hateoas.server.mvc.UriComponentsContributor;
import org.springframework.hateoas.server.mvc.WebMvcLinkBuilderFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.lang.NonNull;
import org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;

/**
 * Spring MVC HATEOAS Configuration
 *
 * @author Greg Turnquist
 * @author Oliver Drotbohm
 */
@Configuration(proxyBeanMethods = false)
@Import(WebMvcEntityLinksConfiguration.class)
class WebMvcHateoasConfiguration {

	@Bean
	HypermediaWebMvcConfigurer hypermediaWebMvcConfigurer(WebConverters converters) {
		return new HypermediaWebMvcConfigurer(converters);
	}

	@Bean
	RepresentationModelProcessorInvoker representationModelProcessorInvoker(
			List> processors) {
		return new RepresentationModelProcessorInvoker(processors);
	}

	@Bean
	static HypermediaRepresentationModelBeanProcessorPostProcessor hypermediaRepresentionModelProcessorConfigurator(
			ObjectProvider invoker) {

		return new HypermediaRepresentationModelBeanProcessorPostProcessor(invoker);
	}

	@Bean
	WebMvcLinkBuilderFactory webMvcLinkBuilderFactory(ObjectProvider contributors) {

		WebMvcLinkBuilderFactory factory = new WebMvcLinkBuilderFactory();
		factory.setUriComponentsContributors(contributors.stream().collect(Collectors.toList()));

		return factory;
	}

	/**
	 * @author Oliver Gierke
	 * @author Greg Turnquist
	 */
	static class HypermediaWebMvcConfigurer implements WebMvcConfigurer {

		private final @NonNull WebConverters hypermediaConverters;

		public HypermediaWebMvcConfigurer(WebConverters hypermediaConverters) {
			this.hypermediaConverters = hypermediaConverters;
		}

		/*
		 * (non-Javadoc)
		 * @see org.springframework.web.servlet.config.annotation.WebMvcConfigurer#extendMessageConverters(java.util.List)
		 */
		@Override
		public void extendMessageConverters(List> converters) {
			hypermediaConverters.augmentServer(converters);
		}

		/*
		 * (non-Javadoc)
		 * @see org.springframework.web.servlet.config.annotation.WebMvcConfigurer#addInterceptors(org.springframework.web.servlet.config.annotation.InterceptorRegistry)
		 */
		@Override
		public void addInterceptors(InterceptorRegistry registry) {
			registry.addInterceptor(DummyInvocationUtilsCacheClearer.INSTANCE);
		}
	}

	/**
	 * @author Greg Turnquist
	 * @author Oliver Drotbohm
	 */
	static class HypermediaRepresentationModelBeanProcessorPostProcessor implements BeanPostProcessor {

		private final ObjectProvider invoker;

		public HypermediaRepresentationModelBeanProcessorPostProcessor(
				ObjectProvider invoker) {
			this.invoker = invoker;
		}

		/*
		 * (non-Javadoc)
		 * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String)
		 */
		@NonNull
		@Override
		public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

			if (RequestMappingHandlerAdapter.class.isInstance(bean)) {

				RequestMappingHandlerAdapter adapter = (RequestMappingHandlerAdapter) bean;

				HandlerMethodReturnValueHandlerComposite delegate = new HandlerMethodReturnValueHandlerComposite();
				delegate.addHandlers(adapter.getReturnValueHandlers());

				RepresentationModelProcessorHandlerMethodReturnValueHandler handler = new RepresentationModelProcessorHandlerMethodReturnValueHandler(
						delegate, () -> invoker.getObject());

				adapter.setReturnValueHandlers(Collections.singletonList(handler));
			}

			return bean;
		}
	}

	/**
	 * {@link HandlerInterceptor} to clear the cache in {@link DummyInvocationUtils}.
	 *
	 * @author Oliver Drotbohm
	 */
	enum DummyInvocationUtilsCacheClearer implements HandlerInterceptor {

		INSTANCE;

		/*
		 * (non-Javadoc)
		 * @see org.springframework.web.servlet.HandlerInterceptor#afterCompletion(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, java.lang.Exception)
		 */
		@Override
		public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
				throws Exception {

			DummyInvocationUtils.resetCache();
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy