Browse Source
Spring Framework 5 will support Jsonb as a HttpMessageConverter, this commit adds auto-configuration support. Also, support for Jsonb in the @JsonTest has been added. This implementation is running against Apache Johnzon See gh-9648pull/9635/head
22 changed files with 674 additions and 16 deletions
@ -0,0 +1,94 @@
@@ -0,0 +1,94 @@
|
||||
/* |
||||
* 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.http; |
||||
|
||||
import javax.json.bind.Jsonb; |
||||
|
||||
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
import org.springframework.boot.autoconfigure.condition.NoneNestedConditions; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Conditional; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.http.converter.json.JsonbHttpMessageConverter; |
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; |
||||
|
||||
/** |
||||
* Configuration for HTTP Message converters that use JSON-B. |
||||
* |
||||
* @author Eddú Meléndez |
||||
* @author 2.0.0 |
||||
*/ |
||||
@Configuration |
||||
@ConditionalOnClass(Jsonb.class) |
||||
class JsonbHttpMessageConvertersConfiguration { |
||||
|
||||
@Configuration |
||||
@ConditionalOnBean(Jsonb.class) |
||||
@Conditional(PreferJsonbOrMissingJacksonAndGsonCondition.class) |
||||
protected static class JsonbHttpMessageConverterConfiguration { |
||||
|
||||
@Bean |
||||
@ConditionalOnMissingBean |
||||
public JsonbHttpMessageConverter jsonbHttpMessageConverter(Jsonb jsonb) { |
||||
JsonbHttpMessageConverter converter = new JsonbHttpMessageConverter(); |
||||
converter.setJsonb(jsonb); |
||||
return converter; |
||||
} |
||||
|
||||
} |
||||
|
||||
private static class PreferJsonbOrMissingJacksonAndGsonCondition extends AnyNestedCondition { |
||||
|
||||
PreferJsonbOrMissingJacksonAndGsonCondition() { |
||||
super(ConfigurationPhase.REGISTER_BEAN); |
||||
} |
||||
|
||||
@ConditionalOnProperty(name = HttpMessageConvertersAutoConfiguration.PREFERRED_MAPPER_PROPERTY, havingValue = "jsonb", matchIfMissing = false) |
||||
static class JsonbPreferred { |
||||
|
||||
} |
||||
|
||||
@Conditional(JacksonAndGsonMissing.class) |
||||
static class JacksonGsonMissing { |
||||
|
||||
} |
||||
|
||||
} |
||||
|
||||
private static class JacksonAndGsonMissing extends NoneNestedConditions { |
||||
|
||||
JacksonAndGsonMissing() { |
||||
super(ConfigurationPhase.REGISTER_BEAN); |
||||
} |
||||
|
||||
@ConditionalOnBean(MappingJackson2HttpMessageConverter.class) |
||||
static class JacksonMissing { |
||||
|
||||
} |
||||
|
||||
@ConditionalOnProperty(name = HttpMessageConvertersAutoConfiguration.PREFERRED_MAPPER_PROPERTY, havingValue = "gson") |
||||
static class GsonMissing { |
||||
|
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,44 @@
@@ -0,0 +1,44 @@
|
||||
/* |
||||
* 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.jsonb; |
||||
|
||||
import javax.json.bind.Jsonb; |
||||
import javax.json.bind.JsonbBuilder; |
||||
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
|
||||
/** |
||||
* {@link EnableAutoConfiguration Auto-configuration} for JSON-B. |
||||
* |
||||
* @author Eddú Meléndez |
||||
* @since 2.0.0 |
||||
*/ |
||||
@Configuration |
||||
@ConditionalOnClass(Jsonb.class) |
||||
public class JsonbAutoConfiguration { |
||||
|
||||
@Bean |
||||
@ConditionalOnMissingBean |
||||
public Jsonb jsonb() { |
||||
return JsonbBuilder.create(); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
|
||||
/* |
||||
* 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. |
||||
*/ |
||||
|
||||
/** |
||||
* Auto-configuration for JSON-B. |
||||
*/ |
||||
package org.springframework.boot.autoconfigure.jsonb; |
||||
@ -0,0 +1,72 @@
@@ -0,0 +1,72 @@
|
||||
/* |
||||
* 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.jsonb; |
||||
|
||||
import javax.json.bind.Jsonb; |
||||
|
||||
import org.junit.After; |
||||
import org.junit.Before; |
||||
import org.junit.Test; |
||||
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
/** |
||||
* Tests for {@link JsonbAutoConfiguration}. |
||||
* |
||||
* @author Eddú Meléndez |
||||
*/ |
||||
public class JsonbAutoConfigurationTests { |
||||
|
||||
AnnotationConfigApplicationContext context; |
||||
|
||||
@Before |
||||
public void setUp() { |
||||
this.context = new AnnotationConfigApplicationContext(); |
||||
} |
||||
|
||||
@After |
||||
public void tearDown() { |
||||
if (this.context != null) { |
||||
this.context.close(); |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void jsonbRegistration() { |
||||
this.context.register(JsonbAutoConfiguration.class); |
||||
this.context.refresh(); |
||||
Jsonb jsonb = this.context.getBean(Jsonb.class); |
||||
assertThat(jsonb.toJson(new DataObject())).isEqualTo("{\"data\":\"hello\"}"); |
||||
} |
||||
|
||||
public class DataObject { |
||||
|
||||
@SuppressWarnings("unused") |
||||
private String data = "hello"; |
||||
|
||||
public String getData() { |
||||
return this.data; |
||||
} |
||||
|
||||
public void setData(String data) { |
||||
this.data = data; |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,128 @@
@@ -0,0 +1,128 @@
|
||||
/* |
||||
* 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.test.json; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.Reader; |
||||
|
||||
import javax.json.bind.Jsonb; |
||||
|
||||
import org.springframework.beans.factory.ObjectFactory; |
||||
import org.springframework.core.ResolvableType; |
||||
import org.springframework.util.Assert; |
||||
|
||||
/** |
||||
* AssertJ based JSON tester backed by Jsonb. Usually instantiated via |
||||
* {@link #initFields(Object, Jsonb)}, for example: <pre class="code"> |
||||
* public class ExampleObjectJsonTests { |
||||
* |
||||
* private JsonbTester<ExampleObject> json; |
||||
* |
||||
* @Before |
||||
* public void setup() { |
||||
* Jsonb jsonb = JsonbBuilder.create(); |
||||
* JsonbTester.initFields(this, jsonb); |
||||
* } |
||||
* |
||||
* @Test |
||||
* public void testWriteJson() throws IOException { |
||||
* ExampleObject object = // ...
|
||||
* assertThat(json.write(object)).isEqualToJson("expected.json"); |
||||
* } |
||||
* |
||||
* } |
||||
* </pre> |
||||
* |
||||
* See {@link AbstractJsonMarshalTester} for more details. |
||||
* |
||||
* @param <T> the type under test |
||||
* @author Eddú Meléndez |
||||
* @since 2.0.0 |
||||
*/ |
||||
public class JsonbTester<T> extends AbstractJsonMarshalTester<T> { |
||||
|
||||
private final Jsonb jsonb; |
||||
|
||||
/** |
||||
* Create a new uninitialized {@link JsonbTester} instance. |
||||
* @param jsonb the Jsonb instance |
||||
*/ |
||||
protected JsonbTester(Jsonb jsonb) { |
||||
Assert.notNull(jsonb, "Jsonb must not be null"); |
||||
this.jsonb = jsonb; |
||||
} |
||||
|
||||
/** |
||||
* Create a new {@link JsonbTester} instance. |
||||
* @param resourceLoadClass the source class used to load resources |
||||
* @param type the type under test |
||||
* @param jsonb the Jsonb instance |
||||
* @see #initFields(Object, Jsonb) |
||||
*/ |
||||
public JsonbTester(Class<?> resourceLoadClass, ResolvableType type, Jsonb jsonb) { |
||||
super(resourceLoadClass, type); |
||||
Assert.notNull(jsonb, "Jsonb must not be null"); |
||||
this.jsonb = jsonb; |
||||
} |
||||
|
||||
@Override |
||||
protected String writeObject(T value, ResolvableType type) throws IOException { |
||||
return this.jsonb.toJson(value, type.getType()); |
||||
} |
||||
|
||||
@Override |
||||
protected T readObject(Reader reader, ResolvableType type) throws IOException { |
||||
return this.jsonb.fromJson(reader, type.getType()); |
||||
} |
||||
|
||||
/** |
||||
* Utility method to initialize {@link JsonbTester} fields. See {@link JsonbTester |
||||
* class-level documentation} for example usage. |
||||
* @param testInstance the test instance |
||||
* @param jsonb the Jsonb instance |
||||
*/ |
||||
public static void initFields(Object testInstance, Jsonb jsonb) { |
||||
new JsonbFieldInitializer().initFields(testInstance, jsonb); |
||||
} |
||||
|
||||
/** |
||||
* Utility method to initialize {@link JsonbTester} fields. See {@link JsonbTester |
||||
* class-level documentation} for example usage. |
||||
* @param testInstance the test instance |
||||
* @param jsonb an object factory to create the Jsonb instance |
||||
*/ |
||||
public static void initFields(Object testInstance, ObjectFactory<Jsonb> jsonb) { |
||||
new JsonbTester.JsonbFieldInitializer().initFields(testInstance, jsonb); |
||||
} |
||||
|
||||
/** |
||||
* {@link FieldInitializer} for Jsonb. |
||||
*/ |
||||
private static class JsonbFieldInitializer extends FieldInitializer<Jsonb> { |
||||
|
||||
protected JsonbFieldInitializer() { |
||||
super(JsonbTester.class); |
||||
} |
||||
|
||||
@Override |
||||
protected AbstractJsonMarshalTester<Object> createTester( |
||||
Class<?> resourceLoadClass, ResolvableType type, Jsonb marshaller) { |
||||
return new JsonbTester<>(resourceLoadClass, type, marshaller); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,89 @@
@@ -0,0 +1,89 @@
|
||||
/* |
||||
* 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.test.json; |
||||
|
||||
import java.util.List; |
||||
|
||||
import javax.json.bind.Jsonb; |
||||
import javax.json.bind.JsonbBuilder; |
||||
|
||||
import org.junit.Test; |
||||
|
||||
import org.springframework.core.ResolvableType; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
/** |
||||
* Tests for {@link JsonbTester}. |
||||
* |
||||
* @author Eddú Meléndez |
||||
*/ |
||||
public class JsonbTesterTests extends AbstractJsonMarshalTesterTests { |
||||
|
||||
@Test |
||||
public void initFieldsWhenTestIsNullShouldThrowException() { |
||||
this.thrown.expect(IllegalArgumentException.class); |
||||
this.thrown.expectMessage("TestInstance must not be null"); |
||||
JsonbTester.initFields(null, JsonbBuilder.create()); |
||||
} |
||||
|
||||
@Test |
||||
public void initFieldsWhenMarshallerIsNullShouldThrowException() { |
||||
this.thrown.expect(IllegalArgumentException.class); |
||||
this.thrown.expectMessage("Marshaller must not be null"); |
||||
JsonbTester.initFields(new InitFieldsTestClass(), (Jsonb) null); |
||||
} |
||||
|
||||
@Test |
||||
public void initFieldsShouldSetNullFields() { |
||||
InitFieldsTestClass test = new InitFieldsTestClass(); |
||||
assertThat(test.test).isNull(); |
||||
assertThat(test.base).isNull(); |
||||
JsonbTester.initFields(test, JsonbBuilder.create()); |
||||
assertThat(test.test).isNotNull(); |
||||
assertThat(test.base).isNotNull(); |
||||
assertThat(test.test.getType().resolve()).isEqualTo(List.class); |
||||
assertThat(test.test.getType().resolveGeneric()).isEqualTo(ExampleObject.class); |
||||
} |
||||
|
||||
@Override |
||||
protected AbstractJsonMarshalTester<Object> createTester(Class<?> resourceLoadClass, |
||||
ResolvableType type) { |
||||
return new JsonbTester<>(resourceLoadClass, type, JsonbBuilder.create()); |
||||
} |
||||
|
||||
static abstract class InitFieldsBaseClass { |
||||
|
||||
public JsonbTester<ExampleObject> base; |
||||
|
||||
public JsonbTester<ExampleObject> baseSet = new JsonbTester<>( |
||||
InitFieldsBaseClass.class, ResolvableType.forClass(ExampleObject.class), |
||||
JsonbBuilder.create()); |
||||
|
||||
} |
||||
|
||||
static class InitFieldsTestClass extends InitFieldsBaseClass { |
||||
|
||||
public JsonbTester<List<ExampleObject>> test; |
||||
|
||||
public JsonbTester<ExampleObject> testSet = new JsonbTester<>( |
||||
InitFieldsBaseClass.class, ResolvableType.forClass(ExampleObject.class), |
||||
JsonbBuilder.create()); |
||||
|
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue