Spring conversion: converters and formatters, part 2.
Contents
This is a continuing of the previous reading about the core functionality of the Spring Framework
provided for types conversion. Here we’ll take a look at the concepts of Converters
and Formatters
.
Short reminding - the project serving as a victim for the conversion executions could be found here.
Converter<,>
The Converter
concept
is a more general one, it allows you to convert data between any two types. This means that you can use not only for the web-layer for converting
from String
but some more general conversion logic. Let’s start with this type-to-type example…
ConversionService direct usage
First, we would need the target property to be converted, let’s use for it the enum BookStatus
:
|
|
As you can see it’s already part of our data model - Book
. Every registered converter could be used by means of Spring’s ConversionService
bean. I will write the code without the converter yet and run it to be sure, that we have a problem:
|
|
when running, in the log we can see this:
|
|
I have tried to convert Long
to BookStatus
. I used the Long
instead of Integer
for example because Spring has already predefined some
converters implementation and IntegerToEnum
is one of them.
Well, let’s fix the problem and create the converter from Long
:
|
|
Registering
Now, we need to register our converter somehow. We can either create the bean of ConverstionService
by means of ConverstionServiceFactoryBean
or directly instantiating the @Bean
of that type.
Also, Spring boot
registers beans implementing Converter
automatically. Let’s use this option, for the converter which we created.
Adding @Component
to the converter and running the application once again:
|
|
Formatter
Ok, that was nice. Now let’s talk a bit about the last but not least option for conversion - Formatter
.
As it’s written in the documentation, this concept is dedicated to the conversion in client-facing interfaces (like our Web app, for example).
It can be used for converting from String
and use the Locale
of the client to provide integration with i18n.
In our Book
model we have an issuedDate
of Date
type, so if we send a request like this:
|
|
The server will throw an exception into us:
1
|
Field error in object 'book' on field 'issueDate': rejected value [1592009798000] |
Well, let’s fix it using Formatter
:
|
|
It’s easy to notice here, that for parsing and printing you can use the Locale
object, which makes it possible to provide i18n service.
Besides, there is only one generic type being accepted - the type of target class.
Registering
The registration could be done by means of :
* just creating a bean from formatter class, if it’s a boot-application;
* creating FormattingConversionService
directly or;
* using FormattingConversionServiceFactoryBean
, which in the end is the same;
* directly in controller binder method (@InitBinder
and WebDataBinder
);
* using WebMvcConfigurer
, which is broadly being used to configure MVC-specific stuff.
So many options, you can choose whatever fits better for your case. For example, I’ll use the last one, but with small improvement - I’ll show how
registrar
concept could be used in case of formatters, quite similar to what we had for editors in the previous reading.
Registrar with our formatter:
|
|
Registration itself:
|
|
Let’s run one more time the POST request with issuedDate, and we will see:
1 2 |
c.e.demo.formatters.IssuedDateFormatter : Parsing date from 1592009798000 c.e.demo.controllers.GeneralController : Created book: com.example.demo.model.Book(123, Sat Jun 13 02:56:38 CEST 2020, com.example.demo.model.Author(Alex), null) |
Annotation-driven formatting
Finishing the topic with formatters, I should mention the subclass of it - AnnotationFormatterFactory
This is a very convenient way of applying conversion according to the custom annotation, which could be put just right on top of the field.
This approach is very explicit and allows us to see the conversion configuration in place - in your model data.
Besides, Spring has a few predefined annotation-based formatter, which you probably saw before.
An example from the documentation:
|
|
Unfortunately, this theme is quite wide and a bit more in details of one particular option of conversion types, so I’ll just mention it and will not cover it in more detail.
Conclusion
These type conversion concepts are basic things in Spring, but they lay down in the foundation of many other abstractions and services, which people get from Spring. Thus, it’s quite important to understand them well and be able to use them. I hope this reading helped to build a more structured picture of Spring type conversion option for you.
Author Relaximus
LastMod 2020-06-20