Spring 4 Rest RequestMappingHandlerAdapter not Saving Configured MessageConverters - spring

I am having a problem with configuring the RequestMappingHandlerAdapter; which is used in a Spring 4.1.4 Restful WebService configuration. When I configure the RequestMappingHandlerAdapter message converters, it doesn't not use the message converters that I've configured. I put break points in the RequestMappingHandlerAdapter.setMessageConverters(List<HttpMessageConverter<?>> messageConverters) method and on application startup I see this method being called three times. The first two times this method is called it has the pre-configured message converters, one of which is the Jaxb2RootElementHttpMessageConverter. On the third time, this method is called with my manually configured message converters via application-context.xml bean configuration. At this point, I am thinking that I have successfully reset the message converters with my own configuration; but that is not so because when I invoke my Restful WebService, Spring is calling the Jaxb2RootElementHttpMessageConverter instead of the MarshallingHttpMessageConverter that I manually configured via application-context.xml.
So I need to know how to:
How to tell Jaxb2RootElementHttpMessageConverter to use my configured JAXB2Marshaller; which is configured to work with JAXBIntroductions,
Unregister the Jaxb2RootElementHttpMessageConverter in Spring 4.1.4,
Tell Spring 4.1.4 when it see XML data to use MarshallingHttpMessageConverter instead of the Jaxb2RootElementHttpMessageConverter,
Create my own custom version of Jaxb2RootElementHttpMessageConverter so I can give it the correct JAXB2 Marshaller; which is configured to work with JAXBIntroductions, or
Get the RequestMappingHandlerAdapter to only used the configuration that I give it.
Any help with any of the five options above would be greatly appreciated.
Thank you.
Tonté

I too faced same issue.
You have to remove from the context file.
Its overriding the converters even if we specified list of converters.

I too faced same issue.
You have to remove mvcannotationDriven from the context file.
Its overriding the converters even if we specified list of converters.

Related

MappingJackson2HttpMessageConverter isn't using the ObjectMapper configured by a #Bean

i am using spring-boot 3.0.2 and have created a custom jackson serializer and registered it using #JsonComponent. i have confirmed it is registered in the ObjectMapper instance that gets injected using #Autowire. when i go to invoke the rest endpoint that will return an object that should be handled by the custom serializer, it is never by the RequestResponseBodyMethodProcessor.
after doing some digging it seems only the default set of converters created in WebMvcConfigurationSupport are being used and nothing else. i have tried registering my own instance of MappingJackson2HttpMessageConverter as a #Bean but it is never used.
the only way i have found to fix this issue is to replace whatever default is being created using extendMessageConverters in WebMvcConfigurer.
can anyone offer any suggestions? from the various blog posts i've read, this should just work but appears not to.
i expect json that looks like this:
["fqdn":"test.com"]
but instead get:
["fqdn:{"idnEncoded":false,"domainName":"test","tldName":"com"}]

Configuring custom Kafka Consumer Deserializer in application.properties file. [spring boot]

I want to consume avro messages and deserialize them without using the Confluent schema registry. I have the schema locally. So, for that, I followed this https://medium.com/#mailshine/apache-avro-quick-example-in-kafka-7b2909396c02 for Consumer part only. Now, I want to configure this deserializer in the application.properties file (the Spring boot way).
I tried adding
spring.kafka.consumer.value-deserializer=com.example.AvroDeserializer
But this results in error saying "Could not find a public no-argument constructor for com.example.AvroDeserializer".
Is there any way to call the constructor with argument from application.properties configuration.
Or
Do I need to configure this in Code instead of properties?
Thanks in advance!!
You can do it using properties, but you have to do it via the configure method (with a no-arg constructor) - this is because Kafka instantiates the deserializer, not Spring.
See the org.springframework.kafka.support.serializer.JsonDeserializer source code for an example.
Otherwise, you can just inject your Deserializer into the consumer factory...
#Bean
MyDeserializer(DefaultKafkaConsumerFactory<String, Foo> factory) {
MyDeserializer<Foo> deser = new MyDeserializer<>(...);
factory.setValueDeserializer(deser);
return deser;
}

SpringMVC global setting for ignoring unknown properties during deserialization

Spring Boot sets "spring.jackson.deserialization.fail-on-unknown-properties=false" by default. I have a library that works fine in Spring Boot, but when used in an existing SpringMVC app it throws "Unrecognized field, not marked as ignorable". Is there some comparable global setting for SpringMVC I can set in the config or otherwise?
edit: spring webmvc version 3.2.15.RELEASE
You can annotate the mapped classes with
#JsonIgnoreProperties(ignoreUnknown = true)
or create add the following configuration to the ObjectMapper as follows:
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
You can follow two method that I have mention in this answer. If I'm not wrong either one will work for you. (But method 1 won't work if your clinet class does not have a no-arg default constructor)

Using both WebApplicationInitializer and web.xml in spring mvc+spring security+spring session redis web application

I'm trying to implement Spring redis session in an existing Spring MVC (ver 5.1.6) application. In web.xml we have ContextLoaderListener, DispatcherServlet and contextConfigLocation are all defined.
After required dependencies are included and suggested code changes are done, i'm getting below error:
Caused by: java.lang.IllegalStateException: Cannot initialize context because there is already a root application context present - check whether you have multiple ContextLoader definitions in your web.xml!"}}*
As part of code changes i'm extending the class "AbstractHttpSessionApplicationInitializer",(from Spring session core library) which internally implements WebApplicationInitializer. Seems like that is trying to create another context and throwing the above error. We cannot avoid extending this class, as this does the job of registering redisHttpSession to context.
Most of the examples available are all with spring boot. So there they wouldn't have faced this issue.
Any solution, other than completely replacing web.xml and use only WebApplicationInitializer?
Just want to provide an update. Instead of extending AbstractHttpSessionApplicationInitializer abtract class, i have taken a different approach by initializing bean RedisHttpSessionConfiguration thru XML bean definition.
This approach worked.
Followed the steps mentioned in the below thread;
How to configure Spring sessions to work with Redis in xml?
Along with that we need to serialize the cookie as well;
#Bean
public CookieSerializer cookieSerializer() {
DefaultCookieSerializer serializer = new DefaultCookieSerializer();
serializer.setCookieName("SESSIONID");
serializer.setCookiePath("/");
serializer.setDomainNamePattern("^.+?\\.(\\w+\\.[a-z]+)$");
return serializer;
}

Implementation provided for BatchConfigurer is not connsidered when using #EnableBatchProcessing(modular=true)

I am developing a sample application that Spring Batch with Spring Boot. My requirement is:
Have my own implementation of BasicBatchConfigurer so that I can configure AsyncTaskExecutor and my own dataSource as I am using SAP HANA as DB for which databaseType is not supported.
I want to use #EnableBatchProcessing(modular=true) so that I can register multiple jobs and launch them with separate Child Context
I have added all the required configurations. Without setting modular=true the Job is Launched and works as expected. It initializes the beans defined from my implementation of BasicBatchConfigurer.
However, once modular=true is set, the beans from my implementation are not initialized.
The code is hosted here: https://github.com/VKJEY/spring-framework-evaluation
I debugged further into the issue:
Looks like, When we set modular=true, BatchConfigurationSelector uses ModularBatchConfiguration
In ModularBatchConfiguration, there's a field Collection<BatchConfigurer> configurers. This has been annotated as #autowired.
I assume that this field is auto initialized if I provided a implementation
of BatchConfigurer as it has been mentioned in the comments of ModularBatchConfiguration class as well
However, While debugging I realized that the above field is still null beacuse of which, It loads DefaultBatchConfigurer and follows the default flow.
My question is why is that field configurers not being initialized in ModularBatchConfiguration? Am I missing something?
I am using Spring boot 2.1.2.
My question is why is that field configurers not being initialized in ModularBatchConfiguration? Am I missing something?
You are hitting a lifecycle issue between Spring Boot custom auto-configuration that you defined in the META-INF/spring.factories file and Spring Batch configuration.
I debugged your code and here is how to fix the issue:
remove org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.job.data.persistence.config.AsyncBatchConfigurer
from META-INF/spring.factories file. This is not needed as Spring Batch
will detect the AsyncBatchConfigurer when it is declared as a bean.
You can even remove this spring.factories file
remove #ConditionalOnMissingBean(BatchConfigurer.class) from AsyncBatchConfigurer:
Since you declared this class as a #Configuration class, it will also be defined as a bean of type BatchConfigurer and will be detected by ModularBatchConfiguration
With these two changes, the field configurers in ModularBatchConfiguration is correctly autowired with your AsyncBatchConfigurer.
As a side note, you don't need the AsyncBatchConfigurer#configurers method as Spring will do the work of injecting all BatchConfigurer beans in ModularBatchConfiguration.
Hope this helps.

Resources