Add RelaxedDataSourceFactory

This commit is contained in:
Dave Syer 2014-05-12 15:03:12 +01:00
parent 9e56c38b7a
commit 1b284a0619
2 changed files with 206 additions and 0 deletions

View File

@ -0,0 +1,78 @@
/*
* Copyright 2012-2013 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 javax.sql.DataSource;
import org.springframework.beans.BeanUtils;
import org.springframework.boot.bind.PropertySourcesPropertyValues;
import org.springframework.boot.bind.RelaxedDataBinder;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.util.ClassUtils;
/**
* @author Dave Syer
*/
public class RelaxedDataSourceFactory {
private static final String[] DATA_SOURCE_TYPE_NAMES = new String[] {
"com.zaxxer.hikari.HikariDataSource",
"org.apache.tomcat.jdbc.pool.DataSource",
"org.apache.commons.dbcp.BasicDataSource" };
private Class<? extends DataSource> type;
private ConfigurableEnvironment environment;
public static RelaxedDataSourceFactory create(ConfigurableEnvironment environment) {
return new RelaxedDataSourceFactory(environment);
}
public RelaxedDataSourceFactory(ConfigurableEnvironment environment) {
this.environment = environment;
}
public DataSource build(String prefix) {
Class<? extends DataSource> type = getType();
DataSource result = BeanUtils.instantiate(type);
RelaxedDataBinder binder = new RelaxedDataBinder(result, prefix);
binder.bind(new PropertySourcesPropertyValues(this.environment
.getPropertySources()));
return result;
}
public RelaxedDataSourceFactory type(Class<? extends DataSource> type) {
this.type = type;
return this;
}
private Class<? extends DataSource> getType() {
if (this.type != null) {
return this.type;
}
for (String name : DATA_SOURCE_TYPE_NAMES) {
if (ClassUtils.isPresent(name, null)) {
@SuppressWarnings("unchecked")
Class<DataSource> resolved = (Class<DataSource>) ClassUtils
.resolveClassName(name, null);
return resolved;
}
}
throw new IllegalStateException("No supported DataSource type found");
}
}

View File

@ -0,0 +1,128 @@
/*
* Copyright 2012-2013 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 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 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 static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* @author Dave Syer
*/
public class JsonSerializationTests {
@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);
assertTrue(value.contains("\"url\":"));
}
@Test
public void serializerWithMixin() throws Exception {
DataSource dataSource = new DataSource();
ObjectMapper mapper = new ObjectMapper();
mapper.addMixInAnnotations(DataSource.class, DataSourceJson.class);
String value = mapper.writeValueAsString(dataSource);
System.err.println(value);
assertTrue(value.contains("\"url\":"));
assertEquals(1, StringUtils.countOccurrencesOf(value, "\"url\""));
}
@JsonSerialize(using = TomcatDataSourceSerializer.class)
protected static 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<BeanPropertyWriter>();
for (BeanPropertyWriter writer : beanProperties) {
AnnotatedMethod setter = beanDesc.findMethod(
"set" + StringUtils.capitalize(writer.getName()),
new Class<?>[] { writer.getPropertyType() });
if (setter != null
&& this.conversionService.canConvert(String.class,
writer.getPropertyType())) {
result.add(writer);
}
}
return result;
}
}
}