Created
March 8, 2017 06:41
-
-
Save duergner/fb2e9a81faf5ab833ae9a24c99ff8c2f to your computer and use it in GitHub Desktop.
A very minimalistic configuration showing how zalando-incubator/json-fields can be used with a Spring Boot application
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.zalando.demo.boot.jsonfields; | |
import com.fasterxml.jackson.databind.ObjectMapper; | |
import com.google.common.base.Supplier; | |
import org.springframework.boot.autoconfigure.SpringBootApplication; | |
import org.springframework.boot.web.servlet.FilterRegistrationBean; | |
import org.springframework.context.annotation.Bean; | |
import org.springframework.context.annotation.Configuration; | |
import org.springframework.http.converter.HttpMessageConverter; | |
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; | |
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; | |
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; | |
import org.zalando.guild.api.json.fields.jackson.JsonFieldsModule; | |
import org.zalando.guild.api.json.fields.jackson.ThreadLocalContextProvider; | |
import org.zalando.guild.api.json.fields.java.expression.ParserFramework; | |
import org.zalando.guild.api.json.fields.java.model.FieldPredicate; | |
import org.zalando.guild.api.json.fields.java.model.FieldPredicates; | |
import javax.servlet.Filter; | |
import javax.servlet.FilterChain; | |
import javax.servlet.FilterConfig; | |
import javax.servlet.ServletException; | |
import javax.servlet.ServletRequest; | |
import javax.servlet.ServletResponse; | |
import java.io.IOException; | |
import java.util.List; | |
@SpringBootApplication | |
public class JsonFieldsApplication { | |
@Configuration | |
static final class WebMvcConfiguration extends WebMvcConfigurerAdapter { | |
@Override | |
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { | |
converters.add(mappingJackson2HttpMessageConverter()); | |
} | |
@Bean | |
public FilterRegistrationBean fieldsFilter() { | |
FilterRegistrationBean registration = new FilterRegistrationBean(); | |
registration.setFilter(new FieldsFilter()); | |
registration.addUrlPatterns("/*"); | |
registration.setName("fieldsFilter"); | |
return registration; | |
} | |
private MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() { | |
MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter(); | |
ObjectMapper objectMapper = new Jackson2ObjectMapperBuilder() | |
.modules( | |
JsonFieldsModule.createJsonFieldsModule( | |
FieldsFilter.FIELD_PREDICATE_SUPPLIER, | |
ThreadLocalContextProvider.getInstance())) | |
.build(); | |
jsonConverter.setObjectMapper(objectMapper); | |
return jsonConverter; | |
} | |
/** | |
* A plain Servlet Filter that will parse the configured parameter from the incoming request and | |
* expose it afterwards via a {@link ThreadLocal} variable. | |
*/ | |
static final class FieldsFilter implements Filter { | |
/** | |
* {@link ThreadLocal} based implementation for a {@link Supplier<FieldPredicate>} as | |
* needed by | |
* the <i>json-fields</i> library | |
*/ | |
public static final Supplier<FieldPredicate> FIELD_PREDICATE_SUPPLIER = new Supplier<FieldPredicate>() { | |
@Override | |
public FieldPredicate get() { | |
return FIELD_PREDICATE.get(); | |
} | |
}; | |
/** | |
* Default filter which will not alter the original reponse | |
*/ | |
private static final FieldPredicate DEFAULT_FIELDS_PREDICATE = FieldPredicates.alwaysTrue(); | |
/** | |
* {@link ThreadLocal} variable which holds the parsed filter expression | |
*/ | |
private static final ThreadLocal<FieldPredicate> FIELD_PREDICATE = new InheritableThreadLocal<FieldPredicate>() { | |
@Override | |
protected FieldPredicate initialValue() { | |
return DEFAULT_FIELDS_PREDICATE; | |
} | |
}; | |
private final String parameter; | |
public FieldsFilter() { | |
this("fields"); | |
} | |
public FieldsFilter(String parameter) { | |
this.parameter = parameter; | |
} | |
@Override | |
public void init(FilterConfig filterConfig) throws ServletException { | |
} | |
@Override | |
public void doFilter( | |
ServletRequest servletRequest, | |
ServletResponse servletResponse, | |
FilterChain filterChain) throws IOException, ServletException { | |
final String fields = servletRequest.getParameter(parameter); | |
if (fields == null || fields.isEmpty()) { | |
FIELD_PREDICATE.set(DEFAULT_FIELDS_PREDICATE); | |
} else { | |
try { | |
final FieldPredicate fieldsExpression = ParserFramework.parseFieldsExpression(fields); | |
FIELD_PREDICATE.set(fieldsExpression); | |
} catch (RuntimeException ignore) { | |
FIELD_PREDICATE.set(DEFAULT_FIELDS_PREDICATE); | |
} | |
} | |
filterChain.doFilter(servletRequest, servletResponse); | |
} | |
@Override | |
public void destroy() { | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment