Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in / Register
Toggle navigation
S
spring-boot
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
DEMO
spring-boot
Commits
85fb1cba
Commit
85fb1cba
authored
Dec 16, 2013
by
Phillip Webb
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Rework HttpMessageConverters
parent
983ef16e
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
183 additions
and
83 deletions
+183
-83
EndpointWebMvcAutoConfiguration.java
...ctuate/autoconfigure/EndpointWebMvcAutoConfiguration.java
+1
-1
HttpMessageConverters.java
...amework/boot/autoconfigure/web/HttpMessageConverters.java
+110
-64
WebMvcAutoConfiguration.java
...ework/boot/autoconfigure/web/WebMvcAutoConfiguration.java
+1
-1
HttpMessageConvertersAutoConfigurationTests.java
...gure/web/HttpMessageConvertersAutoConfigurationTests.java
+3
-1
HttpMessageConvertersTests.java
...rk/boot/autoconfigure/web/HttpMessageConvertersTests.java
+67
-14
WebMvcAutoConfigurationTests.java
.../boot/autoconfigure/web/WebMvcAutoConfigurationTests.java
+1
-2
No files found.
spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcAutoConfiguration.java
View file @
85fb1cba
...
@@ -96,7 +96,7 @@ public class EndpointWebMvcAutoConfiguration implements ApplicationContextAware,
...
@@ -96,7 +96,7 @@ public class EndpointWebMvcAutoConfiguration implements ApplicationContextAware,
public
EndpointHandlerAdapter
endpointHandlerAdapter
(
public
EndpointHandlerAdapter
endpointHandlerAdapter
(
final
HttpMessageConverters
messageConverters
)
{
final
HttpMessageConverters
messageConverters
)
{
EndpointHandlerAdapter
adapter
=
new
EndpointHandlerAdapter
();
EndpointHandlerAdapter
adapter
=
new
EndpointHandlerAdapter
();
adapter
.
setMessageConverters
(
messageConverters
.
get
Message
Converters
());
adapter
.
setMessageConverters
(
messageConverters
.
getConverters
());
return
adapter
;
return
adapter
;
}
}
...
...
spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/HttpMessageConverters.java
View file @
85fb1cba
...
@@ -17,95 +17,141 @@
...
@@ -17,95 +17,141 @@
package
org
.
springframework
.
boot
.
autoconfigure
.
web
;
package
org
.
springframework
.
boot
.
autoconfigure
.
web
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Collection
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.Collections
;
import
java.util.
LinkedHashSet
;
import
java.util.
Iterator
;
import
java.util.List
;
import
java.util.List
;
import
org.springframework.beans.factory.InitializingBean
;
import
org.springframework.http.converter.HttpMessageConverter
;
import
org.springframework.http.converter.HttpMessageConverter
;
import
org.springframework.http.converter.xml.AbstractXmlHttpMessageConverter
;
import
org.springframework.http.converter.xml.AbstractXmlHttpMessageConverter
;
import
org.springframework.util.Assert
;
import
org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport
;
import
org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport
;
/**
/**
* Convenient utility for adding and merging additional {@link HttpMessageConverter} in an
* Bean used to manage the {@link HttpMessageConverter}s used in a Spring Boot
* application context. It also modifies the default converters a bit (putting XML
* application. Provides a convenient way to add and merge additional
* converters at the back of the list if they are present).
* {@link HttpMessageConverter}s to a web application.
* <p>
* An instance of this bean can be registered with specific
* {@link #HttpMessageConverters(HttpMessageConverter...) additional converters} if
* needed, otherwise default converters will be used.
* <p>
* NOTE: The default converters used are the same as standard Spring MVC (see
* {@link WebMvcConfigurationSupport#getMessageConverters} with some slight re-ordering to
* put XML converters at the back of the list.
*
*
* @author Dave Syer
* @author Dave Syer
* @author Phillip Webb
* @see #HttpMessageConverters(HttpMessageConverter...)
* @see #HttpMessageConverters(Collection)
* @see #getConverters()
* @see #setConverters(List)
*/
*/
public
class
HttpMessageConverters
{
public
class
HttpMessageConverters
implements
Iterable
<
HttpMessageConverter
<?>>,
InitializingBean
{
private
List
<
HttpMessageConverter
<?>>
defaults
;
private
List
<
HttpMessageConverter
<?>>
converters
;
private
List
<
HttpMessageConverter
<?>>
overrides
;
private
Object
lock
=
new
Object
()
;
private
boolean
initialized
;
private
List
<
HttpMessageConverter
<?>>
converters
;
/**
* Create a new {@link HttpMessageConverters} instance with the specified additional
* converters.
* @param additionalConverters additional converters to be added. New converters will
* be added to the front of the list, overrides will replace existing items without
* changing the order. The {@link #getConverters()} methods can be used for further
* converter manipulation.
*/
public
HttpMessageConverters
(
HttpMessageConverter
<?>...
additionalConverters
)
{
this
(
Arrays
.
asList
(
additionalConverters
));
}
public
HttpMessageConverters
()
{
/**
this
(
Collections
.<
HttpMessageConverter
<?>>
emptyList
());
* Create a new {@link HttpMessageConverters} instance with the specified additional
* converters.
* @param additionalConverters additional converters to be added. New converters will
* be added to the front of the list, overrides will replace existing items without
* changing the order. The {@link #getConverters()} methods can be used for further
* converter manipulation.
*/
public
HttpMessageConverters
(
Collection
<
HttpMessageConverter
<?>>
additionalConverters
)
{
this
.
converters
=
new
ArrayList
<
HttpMessageConverter
<?>>();
List
<
HttpMessageConverter
<?>>
defaultConverters
=
getDefaultConverters
();
for
(
HttpMessageConverter
<?>
converter
:
additionalConverters
)
{
int
defaultConverterIndex
=
indexOfItemClass
(
defaultConverters
,
converter
);
if
(
defaultConverterIndex
==
-
1
)
{
this
.
converters
.
add
(
converter
);
}
else
{
defaultConverters
.
set
(
defaultConverterIndex
,
converter
);
}
}
this
.
converters
.
addAll
(
defaultConverters
);
}
}
public
HttpMessageConverters
(
Collection
<
HttpMessageConverter
<?>>
overrides
)
{
private
List
<
HttpMessageConverter
<?>>
getDefaultConverters
()
{
this
.
overrides
=
new
ArrayList
<
HttpMessageConverter
<?>>(
overrides
);
List
<
HttpMessageConverter
<?>>
converters
=
new
ArrayList
<
HttpMessageConverter
<?>>();
converters
.
addAll
(
new
WebMvcConfigurationSupport
()
{
public
List
<
HttpMessageConverter
<?>>
defaultMessageConverters
()
{
return
super
.
getMessageConverters
();
}
}.
defaultMessageConverters
());
reorderXmlConvertersToEnd
(
converters
);
return
converters
;
}
}
public
List
<
HttpMessageConverter
<?>>
getMessageConverters
()
{
private
void
reorderXmlConvertersToEnd
(
List
<
HttpMessageConverter
<?>>
converters
)
{
if
(
this
.
converters
==
null
)
{
List
<
HttpMessageConverter
<?>>
xml
=
new
ArrayList
<
HttpMessageConverter
<?>>();
synchronized
(
this
.
lock
)
{
for
(
Iterator
<
HttpMessageConverter
<?>>
iterator
=
converters
.
iterator
();
iterator
if
(
this
.
converters
==
null
)
{
.
hasNext
();)
{
getDefaultMessageConverters
();
// ensure they are available
HttpMessageConverter
<?>
converter
=
iterator
.
next
();
Collection
<
HttpMessageConverter
<?>>
fallbacks
=
new
LinkedHashSet
<
HttpMessageConverter
<?>>();
if
(
converter
instanceof
AbstractXmlHttpMessageConverter
)
{
for
(
HttpMessageConverter
<?>
fallback
:
this
.
defaults
)
{
xml
.
add
(
converter
);
boolean
overridden
=
false
;
iterator
.
remove
();
for
(
HttpMessageConverter
<?>
converter
:
this
.
overrides
)
{
if
(
fallback
.
getClass
()
.
isAssignableFrom
(
converter
.
getClass
()))
{
if
(!
fallbacks
.
contains
(
converter
))
{
fallbacks
.
add
(
converter
);
overridden
=
true
;
}
}
}
if
(!
overridden
)
{
fallbacks
.
add
(
fallback
);
}
}
Collection
<
HttpMessageConverter
<?>>
converters
=
new
LinkedHashSet
<
HttpMessageConverter
<?>>(
this
.
overrides
);
converters
.
addAll
(
fallbacks
);
this
.
converters
=
new
ArrayList
<
HttpMessageConverter
<?>>(
converters
);
}
}
}
}
}
return
this
.
converters
;
converters
.
addAll
(
xml
)
;
}
}
public
List
<
HttpMessageConverter
<?>>
getDefaultMessageConverters
()
{
private
<
E
>
int
indexOfItemClass
(
List
<
E
>
list
,
E
item
)
{
if
(
this
.
defaults
==
null
)
{
Class
<?
extends
Object
>
itemClass
=
item
.
getClass
();
synchronized
(
this
.
lock
)
{
for
(
int
i
=
0
;
i
<
list
.
size
();
i
++)
{
if
(
this
.
defaults
==
null
)
{
if
(
list
.
get
(
i
).
getClass
().
isAssignableFrom
(
itemClass
))
{
this
.
defaults
=
new
ArrayList
<
HttpMessageConverter
<?>>();
return
i
;
this
.
defaults
.
addAll
(
new
WebMvcConfigurationSupport
()
{
public
List
<
HttpMessageConverter
<?>>
defaultMessageConverters
()
{
return
super
.
getMessageConverters
();
}
}.
defaultMessageConverters
());
List
<
HttpMessageConverter
<?>>
xmls
=
new
ArrayList
<
HttpMessageConverter
<?>>();
for
(
HttpMessageConverter
<?>
converter
:
this
.
defaults
)
{
// Shift XML converters to the back of the list so they only get
// used if nothing else works...
if
(
converter
instanceof
AbstractXmlHttpMessageConverter
)
{
xmls
.
add
(
converter
);
}
}
this
.
defaults
.
removeAll
(
xmls
);
this
.
defaults
.
addAll
(
xmls
);
}
}
}
}
}
return
Collections
.
unmodifiableList
(
this
.
defaults
)
;
return
-
1
;
}
}
}
@Override
\ No newline at end of file
public
Iterator
<
HttpMessageConverter
<?>>
iterator
()
{
return
getConverters
().
iterator
();
}
/**
* Return a mutable list of the converters in the order that they will be registered.
* Values in the list cannot be modified once the bean has been initialized.
* @return the converters
*/
public
List
<
HttpMessageConverter
<?>>
getConverters
()
{
return
this
.
converters
;
}
/**
* Set the converters to use, replacing any existing values. This method can only be
* called before the bean has been initialized.
* @param converters the converters to set
*/
public
void
setConverters
(
List
<
HttpMessageConverter
<?>>
converters
)
{
Assert
.
state
(!
this
.
initialized
,
"Unable to set converters once initialized"
);
this
.
converters
=
converters
;
}
@Override
public
void
afterPropertiesSet
()
throws
Exception
{
this
.
initialized
=
true
;
this
.
converters
=
Collections
.
unmodifiableList
(
this
.
converters
);
}
}
spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java
View file @
85fb1cba
...
@@ -133,7 +133,7 @@ public class WebMvcAutoConfiguration {
...
@@ -133,7 +133,7 @@ public class WebMvcAutoConfiguration {
@Override
@Override
public
void
configureMessageConverters
(
List
<
HttpMessageConverter
<?>>
converters
)
{
public
void
configureMessageConverters
(
List
<
HttpMessageConverter
<?>>
converters
)
{
converters
.
addAll
(
this
.
messageConverters
.
get
Message
Converters
());
converters
.
addAll
(
this
.
messageConverters
.
getConverters
());
}
}
@Bean
@Bean
...
...
spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/HttpMessageConvertersAutoConfigurationTests.java
View file @
85fb1cba
...
@@ -42,6 +42,8 @@ import static org.mockito.Matchers.argThat;
...
@@ -42,6 +42,8 @@ import static org.mockito.Matchers.argThat;
import
static
org
.
mockito
.
Mockito
.
verify
;
import
static
org
.
mockito
.
Mockito
.
verify
;
/**
/**
* Tests for {@link HttpMessageConvertersAutoConfiguration}.
*
* @author Dave Syer
* @author Dave Syer
*/
*/
public
class
HttpMessageConvertersAutoConfigurationTests
{
public
class
HttpMessageConvertersAutoConfigurationTests
{
...
@@ -67,7 +69,7 @@ public class HttpMessageConvertersAutoConfigurationTests {
...
@@ -67,7 +69,7 @@ public class HttpMessageConvertersAutoConfigurationTests {
converter
.
getObjectMapper
());
converter
.
getObjectMapper
());
HttpMessageConverters
converters
=
this
.
context
HttpMessageConverters
converters
=
this
.
context
.
getBean
(
HttpMessageConverters
.
class
);
.
getBean
(
HttpMessageConverters
.
class
);
assertTrue
(
converters
.
get
Message
Converters
().
contains
(
converter
));
assertTrue
(
converters
.
getConverters
().
contains
(
converter
));
}
}
@Test
@Test
...
...
spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/HttpMessageConvertersTests.java
View file @
85fb1cba
...
@@ -16,43 +16,96 @@
...
@@ -16,43 +16,96 @@
package
org
.
springframework
.
boot
.
autoconfigure
.
web
;
package
org
.
springframework
.
boot
.
autoconfigure
.
web
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
java.util.List
;
import
org.junit.Rule
;
import
org.junit.Test
;
import
org.junit.Test
;
import
org.mockito.Mockito
;
import
org.junit.rules.ExpectedException
;
import
org.springframework.http.converter.ByteArrayHttpMessageConverter
;
import
org.springframework.http.converter.HttpMessageConverter
;
import
org.springframework.http.converter.HttpMessageConverter
;
import
org.springframework.http.converter.ResourceHttpMessageConverter
;
import
org.springframework.http.converter.StringHttpMessageConverter
;
import
org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
;
import
org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
;
import
org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter
;
import
org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter
;
import
org.springframework.http.converter.xml.SourceHttpMessageConverter
;
import
static
org
.
hamcrest
.
Matchers
.
equalTo
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assert
False
;
import
static
org
.
junit
.
Assert
.
assert
That
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
mockito
.
Mockito
.
mock
;
/**
/**
* @author Dave Syer
* @author Dave Syer
* @author Phillip Webb
*/
*/
public
class
HttpMessageConvertersTests
{
public
class
HttpMessageConvertersTests
{
@Rule
public
ExpectedException
thrown
=
ExpectedException
.
none
();
@Test
public
void
containsDefaults
()
throws
Exception
{
HttpMessageConverters
converters
=
new
HttpMessageConverters
();
List
<
Class
<?>>
converterClasses
=
new
ArrayList
<
Class
<?>>();
for
(
HttpMessageConverter
<?>
converter
:
converters
)
{
converterClasses
.
add
(
converter
.
getClass
());
}
assertThat
(
converterClasses
,
equalTo
(
Arrays
.<
Class
<?>>
asList
(
ByteArrayHttpMessageConverter
.
class
,
StringHttpMessageConverter
.
class
,
ResourceHttpMessageConverter
.
class
,
SourceHttpMessageConverter
.
class
,
AllEncompassingFormHttpMessageConverter
.
class
,
MappingJackson2HttpMessageConverter
.
class
,
Jaxb2RootElementHttpMessageConverter
.
class
)));
}
@Test
public
void
canModifyBeforeInitialize
()
throws
Exception
{
HttpMessageConverters
converters
=
new
HttpMessageConverters
();
HttpMessageConverter
<?>
converter
=
mock
(
HttpMessageConverter
.
class
);
converters
.
getConverters
().
add
(
converter
);
assertThat
(
converters
.
getConverters
().
contains
(
converter
),
equalTo
(
true
));
}
@Test
public
void
cannotModifyAfterInitialize
()
throws
Exception
{
HttpMessageConverters
converters
=
new
HttpMessageConverters
();
converters
.
afterPropertiesSet
();
this
.
thrown
.
expect
(
UnsupportedOperationException
.
class
);
converters
.
getConverters
().
add
(
mock
(
HttpMessageConverter
.
class
));
}
@Test
public
void
canSetBeforeInitialize
()
throws
Exception
{
HttpMessageConverters
converters
=
new
HttpMessageConverters
();
converters
.
setConverters
(
new
ArrayList
<
HttpMessageConverter
<?>>());
assertThat
(
converters
.
getConverters
().
size
(),
equalTo
(
0
));
}
@Test
@Test
public
void
defaultsCreated
()
{
public
void
cannotSetAfterInitailzie
()
throws
Exception
{
HttpMessageConverters
messageConverters
=
new
HttpMessageConverters
();
HttpMessageConverters
converters
=
new
HttpMessageConverters
();
assertFalse
(
messageConverters
.
getDefaultMessageConverters
().
isEmpty
());
converters
.
afterPropertiesSet
();
this
.
thrown
.
expect
(
IllegalStateException
.
class
);
converters
.
setConverters
(
new
ArrayList
<
HttpMessageConverter
<?>>());
}
}
@Test
@Test
public
void
overrideExistingConverter
()
{
public
void
overrideExistingConverter
()
{
MappingJackson2HttpMessageConverter
converter
=
new
MappingJackson2HttpMessageConverter
();
MappingJackson2HttpMessageConverter
converter
=
new
MappingJackson2HttpMessageConverter
();
HttpMessageConverters
messageConverters
=
new
HttpMessageConverters
(
HttpMessageConverters
converters
=
new
HttpMessageConverters
(
converter
);
Arrays
.<
HttpMessageConverter
<?>>
asList
(
converter
));
assertTrue
(
converters
.
getConverters
().
contains
(
converter
));
assertTrue
(
messageConverters
.
getMessageConverters
().
contains
(
converter
));
}
}
@Test
@Test
public
void
addNewOne
()
{
public
void
addNewConverter
()
{
HttpMessageConverter
<?>
converter
=
Mockito
.
mock
(
HttpMessageConverter
.
class
);
HttpMessageConverter
<?>
converter
=
mock
(
HttpMessageConverter
.
class
);
HttpMessageConverters
messageConverters
=
new
HttpMessageConverters
(
HttpMessageConverters
converters
=
new
HttpMessageConverters
(
converter
);
Arrays
.<
HttpMessageConverter
<?>>
asList
(
converter
));
assertTrue
(
converters
.
getConverters
().
contains
(
converter
));
assertTrue
(
messageConverters
.
getMessageConverters
().
contains
(
converter
));
assertEquals
(
converter
,
converters
.
getConverters
().
get
(
0
));
assertEquals
(
converter
,
messageConverters
.
getMessageConverters
().
get
(
0
));
}
}
}
}
spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfigurationTests.java
View file @
85fb1cba
...
@@ -83,8 +83,7 @@ public class WebMvcAutoConfigurationTests {
...
@@ -83,8 +83,7 @@ public class WebMvcAutoConfigurationTests {
assertEquals
(
3
,
this
.
context
.
getBeanNamesForType
(
HandlerAdapter
.
class
).
length
);
assertEquals
(
3
,
this
.
context
.
getBeanNamesForType
(
HandlerAdapter
.
class
).
length
);
assertFalse
(
this
.
context
.
getBean
(
RequestMappingHandlerAdapter
.
class
)
assertFalse
(
this
.
context
.
getBean
(
RequestMappingHandlerAdapter
.
class
)
.
getMessageConverters
().
isEmpty
());
.
getMessageConverters
().
isEmpty
());
assertEquals
(
this
.
context
.
getBean
(
HttpMessageConverters
.
class
)
assertEquals
(
this
.
context
.
getBean
(
HttpMessageConverters
.
class
).
getConverters
(),
.
getMessageConverters
(),
this
.
context
.
getBean
(
RequestMappingHandlerAdapter
.
class
)
this
.
context
.
getBean
(
RequestMappingHandlerAdapter
.
class
)
.
getMessageConverters
());
.
getMessageConverters
());
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment