Skip to content

Commit d5e7198

Browse files
committed
#288 - Polishing.
Moved RenderSingleLinks enum into HalConfiguration. Simplified HalConfiguration setup by moving the default into the class. The lookup of a user-provided HalConfiguration is now handled on the bean name level to avoid premature initialization of a potentially defined bean. Formatting. Original pull request: #295 Related issues: #291
1 parent 5eee301 commit d5e7198

File tree

7 files changed

+59
-84
lines changed

7 files changed

+59
-84
lines changed

src/main/java/org/springframework/hateoas/RenderSingleLinks.java

-32
This file was deleted.

src/main/java/org/springframework/hateoas/config/EnableHypermediaSupport.java

-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
import org.springframework.context.annotation.Import;
2626
import org.springframework.hateoas.EntityLinks;
2727
import org.springframework.hateoas.LinkDiscoverer;
28-
import org.springframework.hateoas.RenderSingleLinks;
2928

3029
/**
3130
* Activates hypermedia support in the {@link ApplicationContext}. Will register infrastructure beans available for

src/main/java/org/springframework/hateoas/config/HypermediaSupportBeanDefinitionRegistrar.java

+7-12
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.springframework.beans.BeansException;
2929
import org.springframework.beans.factory.BeanFactory;
3030
import org.springframework.beans.factory.BeanFactoryAware;
31+
import org.springframework.beans.factory.ListableBeanFactory;
3132
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
3233
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
3334
import org.springframework.beans.factory.config.BeanDefinition;
@@ -46,7 +47,6 @@
4647
import org.springframework.hateoas.LinkDiscoverer;
4748
import org.springframework.hateoas.LinkDiscoverers;
4849
import org.springframework.hateoas.RelProvider;
49-
import org.springframework.hateoas.RenderSingleLinks;
5050
import org.springframework.hateoas.ResourceSupport;
5151
import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType;
5252
import org.springframework.hateoas.core.AnnotationRelProvider;
@@ -91,8 +91,8 @@ class HypermediaSupportBeanDefinitionRegistrar implements ImportBeanDefinitionRe
9191
private static final boolean EVO_PRESENT = ClassUtils.isPresent("org.atteo.evo.inflector.English", null);
9292

9393
private final ImportBeanDefinitionRegistrar linkBuilderBeanDefinitionRegistrar = new LinkBuilderBeanDefinitionRegistrar();
94-
95-
private BeanFactory beanFactory;
94+
95+
private ListableBeanFactory beanFactory;
9696

9797
/*
9898
* (non-Javadoc)
@@ -130,14 +130,9 @@ public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionR
130130
registerSourcedBeanDefinition(builder, metadata, registry);
131131
}
132132

133-
try {
134-
this.beanFactory.getBean(HalConfiguration.class);
135-
} catch (BeansException e) {
136-
137-
// If no HalConfiguration bean, create a default one.
138-
BeanDefinitionBuilder defaultHalConfiguration = rootBeanDefinition(HalConfiguration.class);
139-
defaultHalConfiguration.addPropertyValue("renderSingleLinks", RenderSingleLinks.AS_SINGLE);
140-
registerSourcedBeanDefinition(defaultHalConfiguration, metadata, registry);
133+
// If no HalConfiguration bean, create a default one.
134+
if (this.beanFactory.getBeanNamesForType(HalConfiguration.class).length == 0) {
135+
registerSourcedBeanDefinition(rootBeanDefinition(HalConfiguration.class), metadata, registry);
141136
}
142137
}
143138

@@ -159,7 +154,7 @@ public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionR
159154

160155
@Override
161156
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
162-
this.beanFactory = beanFactory;
157+
this.beanFactory = (ListableBeanFactory) beanFactory;
163158
}
164159

165160
/**

src/main/java/org/springframework/hateoas/hal/HalConfiguration.java

+19-6
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,34 @@
1515
*/
1616
package org.springframework.hateoas.hal;
1717

18+
import lombok.AccessLevel;
1819
import lombok.AllArgsConstructor;
1920
import lombok.Getter;
2021
import lombok.NoArgsConstructor;
21-
import lombok.Setter;
2222
import lombok.experimental.Wither;
2323

24-
import org.springframework.hateoas.HypermediaConfiguration;
25-
import org.springframework.hateoas.RenderSingleLinks;
24+
import org.springframework.hateoas.Link;
2625

2726
/**
2827
* @author Greg Turnquist
28+
* @author Oliver Gierke
2929
*/
30-
@AllArgsConstructor
3130
@NoArgsConstructor
32-
public class HalConfiguration implements HypermediaConfiguration {
31+
@AllArgsConstructor(access = AccessLevel.PRIVATE)
32+
public class HalConfiguration {
3333

34-
private @Wither @Getter @Setter RenderSingleLinks renderSingleLinks;
34+
private @Wither @Getter RenderSingleLinks renderSingleLinks = RenderSingleLinks.AS_SINGLE;
35+
36+
public enum RenderSingleLinks {
37+
38+
/**
39+
* A single {@link Link} is rendered as a JSON object.
40+
*/
41+
AS_SINGLE,
42+
43+
/**
44+
* A single {@link Link} is rendered as a JSON Array.
45+
*/
46+
AS_ARRAY
47+
}
3548
}

src/main/java/org/springframework/hateoas/hal/Jackson2HalModule.java

+13-9
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@
3232
import org.springframework.hateoas.Link;
3333
import org.springframework.hateoas.Links;
3434
import org.springframework.hateoas.RelProvider;
35-
import org.springframework.hateoas.RenderSingleLinks;
3635
import org.springframework.hateoas.Resource;
3736
import org.springframework.hateoas.ResourceSupport;
3837
import org.springframework.hateoas.Resources;
38+
import org.springframework.hateoas.hal.HalConfiguration.RenderSingleLinks;
3939
import org.springframework.util.Assert;
4040

4141
import com.fasterxml.jackson.annotation.JsonInclude;
@@ -126,7 +126,8 @@ public static class HalLinkListSerializer extends ContainerSerializer<List<Link>
126126
private final MessageSourceAccessor accessor;
127127
private final HalConfiguration halConfiguration;
128128

129-
public HalLinkListSerializer(CurieProvider curieProvider, EmbeddedMapper mapper, MessageSourceAccessor accessor, HalConfiguration halConfiguration) {
129+
public HalLinkListSerializer(CurieProvider curieProvider, EmbeddedMapper mapper, MessageSourceAccessor accessor,
130+
HalConfiguration halConfiguration) {
130131
this(null, curieProvider, mapper, accessor, halConfiguration);
131132
}
132133

@@ -201,7 +202,8 @@ public void serialize(List<Link> value, JsonGenerator jgen, SerializerProvider p
201202
JavaType mapType = typeFactory.constructMapType(HashMap.class, keyType, valueType);
202203

203204
MapSerializer serializer = MapSerializer.construct(new String[] {}, mapType, true, null,
204-
provider.findKeySerializer(keyType, null), new OptionalListJackson2Serializer(property, halConfiguration), null);
205+
provider.findKeySerializer(keyType, null), new OptionalListJackson2Serializer(property, halConfiguration),
206+
null);
205207

206208
serializer.serialize(sortedLinks, jgen, provider);
207209
}
@@ -430,8 +432,7 @@ public ContainerSerializer<?> _withValueTypeSerializer(TypeSerializer vts) {
430432
* @see com.fasterxml.jackson.databind.ser.std.StdSerializer#serialize(java.lang.Object, com.fasterxml.jackson.core.JsonGenerator, com.fasterxml.jackson.databind.SerializerProvider)
431433
*/
432434
@Override
433-
public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider)
434-
throws IOException {
435+
public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
435436

436437
List<?> list = (List<?>) value;
437438

@@ -695,12 +696,14 @@ public HalHandlerInstantiator(RelProvider provider, CurieProvider curieProvider,
695696
this(provider, curieProvider, accessor, true, beanFactory, halConfiguration);
696697
}
697698

698-
public HalHandlerInstantiator(RelProvider provider, CurieProvider curieProvider, MessageSourceAccessor messageSourceAccessor, AutowireCapableBeanFactory beanFactory) {
699+
public HalHandlerInstantiator(RelProvider provider, CurieProvider curieProvider,
700+
MessageSourceAccessor messageSourceAccessor, AutowireCapableBeanFactory beanFactory) {
699701
this(provider, curieProvider, messageSourceAccessor, beanFactory, beanFactory.getBean(HalConfiguration.class));
700702
}
701703

702-
public HalHandlerInstantiator(RelProvider provider, CurieProvider curieProvider, MessageSourceAccessor messageSourceAccessor) {
703-
this(provider, curieProvider, messageSourceAccessor, new HalConfiguration().withRenderSingleLinks(RenderSingleLinks.AS_SINGLE));
704+
public HalHandlerInstantiator(RelProvider provider, CurieProvider curieProvider,
705+
MessageSourceAccessor messageSourceAccessor) {
706+
this(provider, curieProvider, messageSourceAccessor, new HalConfiguration());
704707
}
705708

706709
/**
@@ -743,7 +746,8 @@ private HalHandlerInstantiator(RelProvider provider, CurieProvider curieProvider
743746
this.delegate = delegate;
744747

745748
this.serializers.put(HalResourcesSerializer.class, new HalResourcesSerializer(mapper));
746-
this.serializers.put(HalLinkListSerializer.class, new HalLinkListSerializer(curieProvider, mapper, accessor, halConfiguration));
749+
this.serializers.put(HalLinkListSerializer.class,
750+
new HalLinkListSerializer(curieProvider, mapper, accessor, halConfiguration));
747751
}
748752

749753
/*

src/test/java/org/springframework/hateoas/config/EnableHypermediaSupportIntegrationTest.java

+7-11
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import static org.hamcrest.Matchers.*;
1919
import static org.junit.Assert.*;
20+
import static org.springframework.hateoas.hal.HalConfiguration.RenderSingleLinks.*;
2021

2122
import java.lang.reflect.Method;
2223
import java.util.List;
@@ -37,7 +38,6 @@
3738
import org.springframework.hateoas.LinkDiscoverers;
3839
import org.springframework.hateoas.MediaTypes;
3940
import org.springframework.hateoas.RelProvider;
40-
import org.springframework.hateoas.RenderSingleLinks;
4141
import org.springframework.hateoas.ResourceSupport;
4242
import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType;
4343
import org.springframework.hateoas.config.HypermediaSupportBeanDefinitionRegistrar.Jackson2ModuleRegisteringBeanPostProcessor;
@@ -99,8 +99,7 @@ public void halSetupIsAppliedToAllTransitiveComponentsInRequestMappingHandlerAda
9999

100100
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(HalConfig.class);
101101

102-
Jackson2ModuleRegisteringBeanPostProcessor postProcessor =
103-
new HypermediaSupportBeanDefinitionRegistrar.Jackson2ModuleRegisteringBeanPostProcessor();
102+
Jackson2ModuleRegisteringBeanPostProcessor postProcessor = new HypermediaSupportBeanDefinitionRegistrar.Jackson2ModuleRegisteringBeanPostProcessor();
104103
postProcessor.setBeanFactory(context.getAutowireCapableBeanFactory());
105104

106105
RequestMappingHandlerAdapter adapter = context.getBean(RequestMappingHandlerAdapter.class);
@@ -165,25 +164,23 @@ public void verifyDefaultHalConfigurationRendersSingleItemAsSingleItem() throws
165164
ResourceSupport resourceSupport = new ResourceSupport();
166165
resourceSupport.add(new Link("localhost").withSelfRel());
167166

168-
assertThat(mapper.writeValueAsString(resourceSupport),
169-
is("{\"_links\":{\"self\":{\"href\":\"localhost\"}}}"));
167+
assertThat(mapper.writeValueAsString(resourceSupport), is("{\"_links\":{\"self\":{\"href\":\"localhost\"}}}"));
170168

171169
context.close();
172170
}
173171

174-
175172
@Test
176173
public void verifyRenderSingleLinkAsArrayViaOverridingBean() throws JsonProcessingException {
177174

178-
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(RenderLinkAsSingleLinksConfig.class);
175+
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
176+
RenderLinkAsSingleLinksConfig.class);
179177

180178
ObjectMapper mapper = context.getBean("_halObjectMapper", ObjectMapper.class);
181179

182180
ResourceSupport resourceSupport = new ResourceSupport();
183181
resourceSupport.add(new Link("localhost").withSelfRel());
184182

185-
assertThat(mapper.writeValueAsString(resourceSupport),
186-
is("{\"_links\":{\"self\":[{\"href\":\"localhost\"}]}}"));
183+
assertThat(mapper.writeValueAsString(resourceSupport), is("{\"_links\":{\"self\":[{\"href\":\"localhost\"}]}}"));
187184

188185
context.close();
189186
}
@@ -273,13 +270,12 @@ static class RenderLinkAsSingleLinksConfig {
273270

274271
@Bean
275272
HalConfiguration halConfiguration() {
276-
return new HalConfiguration().withRenderSingleLinks(RenderSingleLinks.AS_ARRAY);
273+
return new HalConfiguration().withRenderSingleLinks(AS_ARRAY);
277274
}
278275

279276
@Bean
280277
public RequestMappingHandlerAdapter rmh() {
281278
return new RequestMappingHandlerAdapter();
282279
}
283-
284280
}
285281
}

src/test/java/org/springframework/hateoas/hal/Jackson2HalIntegrationTest.java

+13-13
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727

2828
import org.junit.Before;
2929
import org.junit.Test;
30-
3130
import org.springframework.context.MessageSource;
3231
import org.springframework.context.i18n.LocaleContextHolder;
3332
import org.springframework.context.support.MessageSourceAccessor;
@@ -37,13 +36,13 @@
3736
import org.springframework.hateoas.Links;
3837
import org.springframework.hateoas.PagedResources;
3938
import org.springframework.hateoas.PagedResources.PageMetadata;
40-
import org.springframework.hateoas.RenderSingleLinks;
4139
import org.springframework.hateoas.Resource;
4240
import org.springframework.hateoas.ResourceSupport;
4341
import org.springframework.hateoas.Resources;
4442
import org.springframework.hateoas.UriTemplate;
4543
import org.springframework.hateoas.core.AnnotationRelProvider;
4644
import org.springframework.hateoas.core.EmbeddedWrappers;
45+
import org.springframework.hateoas.hal.HalConfiguration.RenderSingleLinks;
4746
import org.springframework.hateoas.hal.Jackson2HalModule.HalHandlerInstantiator;
4847

4948
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -82,12 +81,13 @@ public class Jackson2HalIntegrationTest extends AbstractJackson2MarshallingInteg
8281

8382
static final String SINGLE_WITH_ONE_EXTRA_ATTRIBUTES = "{\"_links\":{\"self\":{\"href\":\"localhost\",\"title\":\"the title\"}}}";
8483
static final String SINGLE_WITH_ALL_EXTRA_ATTRIBUTES = "{\"_links\":{\"self\":{\"href\":\"localhost\",\"hreflang\":\"en\",\"title\":\"the title\",\"type\":\"the type\",\"deprecation\":\"/customers/deprecated\"}}}";
85-
84+
8685
@Before
8786
public void setUpModule() {
8887

8988
mapper.registerModule(new Jackson2HalModule());
90-
mapper.setHandlerInstantiator(new HalHandlerInstantiator(new AnnotationRelProvider(), null, null, new HalConfiguration().withRenderSingleLinks(RenderSingleLinks.AS_SINGLE)));
89+
mapper.setHandlerInstantiator(
90+
new HalHandlerInstantiator(new AnnotationRelProvider(), null, null, new HalConfiguration()));
9191
}
9292

9393
/**
@@ -109,12 +109,12 @@ public void rendersSingleLinkAsObject() throws Exception {
109109
public void rendersAllExtraRFC5988Attributes() throws Exception {
110110

111111
ResourceSupport resourceSupport = new ResourceSupport();
112-
resourceSupport.add(new Link("localhost", "self")
113-
.withHreflang("en")
114-
.withTitle("the title")
115-
.withType("the type")
116-
.withMedia("the media")
117-
.withDeprecation("/customers/deprecated"));
112+
resourceSupport.add(new Link("localhost", "self") //
113+
.withHreflang("en") //
114+
.withTitle("the title") //
115+
.withType("the type") //
116+
.withMedia("the media") //
117+
.withDeprecation("/customers/deprecated"));
118118

119119
assertThat(write(resourceSupport), is(SINGLE_WITH_ALL_EXTRA_ATTRIBUTES));
120120
}
@@ -123,8 +123,7 @@ public void rendersAllExtraRFC5988Attributes() throws Exception {
123123
public void rendersWithOneExtraRFC5988Attribute() throws Exception {
124124

125125
ResourceSupport resourceSupport = new ResourceSupport();
126-
resourceSupport.add(new Link("localhost", "self")
127-
.withTitle("the title"));
126+
resourceSupport.add(new Link("localhost", "self").withTitle("the title"));
128127

129128
assertThat(write(resourceSupport), is(SINGLE_WITH_ONE_EXTRA_ATTRIBUTES));
130129
}
@@ -415,7 +414,8 @@ public void rendersTitleIfMessageSourceResolvesLocalKey() throws Exception {
415414
@Test
416415
public void rendersSingleLinkAsArrayWhenConfigured() throws Exception {
417416

418-
mapper.setHandlerInstantiator(new HalHandlerInstantiator(new AnnotationRelProvider(), null, null, new HalConfiguration().withRenderSingleLinks(RenderSingleLinks.AS_ARRAY)));
417+
mapper.setHandlerInstantiator(new HalHandlerInstantiator(new AnnotationRelProvider(), null, null,
418+
new HalConfiguration().withRenderSingleLinks(RenderSingleLinks.AS_ARRAY)));
419419

420420
ResourceSupport resourceSupport = new ResourceSupport();
421421
resourceSupport.add(new Link("localhost").withSelfRel());

0 commit comments

Comments
 (0)