/* * Copyright 2012-2017 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.boot.autoconfigure.jdbc; import java.beans.PropertyDescriptor; import java.io.IOException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.BeanDescription; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationConfig; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; import com.fasterxml.jackson.databind.ser.BeanSerializerFactory; import com.fasterxml.jackson.databind.ser.BeanSerializerModifier; import com.fasterxml.jackson.databind.ser.SerializerFactory; import org.apache.tomcat.jdbc.pool.DataSource; import org.junit.Test; import org.springframework.beans.BeanUtils; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; import static org.assertj.core.api.Assertions.assertThat; /** * Test that a {@link DataSource} can be exposed as JSON for actuator endpoints. * * @author Dave Syer */ public class DataSourceJsonSerializationTests { @Test public void serializerFactory() throws Exception { DataSource dataSource = new DataSource(); SerializerFactory factory = BeanSerializerFactory.instance .withSerializerModifier(new GenericSerializerModifier()); ObjectMapper mapper = new ObjectMapper(); mapper.setSerializerFactory(factory); String value = mapper.writeValueAsString(dataSource); assertThat(value.contains("\"url\":")).isTrue(); } @Test public void serializerWithMixin() throws Exception { DataSource dataSource = new DataSource(); ObjectMapper mapper = new ObjectMapper(); mapper.addMixIn(DataSource.class, DataSourceJson.class); String value = mapper.writeValueAsString(dataSource); assertThat(value.contains("\"url\":")).isTrue(); assertThat(StringUtils.countOccurrencesOf(value, "\"url\"")).isEqualTo(1); } @JsonSerialize(using = TomcatDataSourceSerializer.class) protected interface DataSourceJson { } protected static class TomcatDataSourceSerializer extends JsonSerializer<DataSource> { private ConversionService conversionService = new DefaultConversionService(); @Override public void serialize(DataSource value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { jgen.writeStartObject(); for (PropertyDescriptor property : BeanUtils .getPropertyDescriptors(DataSource.class)) { Method reader = property.getReadMethod(); if (reader != null && property.getWriteMethod() != null && this.conversionService.canConvert(String.class, property.getPropertyType())) { jgen.writeObjectField(property.getName(), ReflectionUtils.invokeMethod(reader, value)); } } jgen.writeEndObject(); } } protected static class GenericSerializerModifier extends BeanSerializerModifier { private ConversionService conversionService = new DefaultConversionService(); @Override public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) { List<BeanPropertyWriter> result = new ArrayList<>(); for (BeanPropertyWriter writer : beanProperties) { AnnotatedMethod setter = beanDesc.findMethod( "set" + StringUtils.capitalize(writer.getName()), new Class<?>[] { writer.getType().getRawClass() }); if (setter != null && this.conversionService.canConvert(String.class, writer.getType().getRawClass())) { result.add(writer); } } return result; } } }