Spring and jackson, how to disable FAIL_ON_EMPTY_BEANS through #ResponseBody - spring

Is there a global configuration in spring that can disable spring FAIL_ON_EMPTY_BEANS for all controller annotated with #ResponseBody?

If you are using Spring Boot, you can set the following property in application.properties file.
spring.jackson.serialization.FAIL_ON_EMPTY_BEANS=false
Thanks to #DKroot for his valuable comment. But I believe this should be its own answer for others.

You can configure your object mapper when configuring configureMessageConverters
#Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
MappingJackson2HttpMessageConverter converter =
new MappingJackson2HttpMessageConverter(mapper);
return converter;
}
If you want to know how to do exactly in your application, please update your question with your configuration files (xml or java configs).
Here is a good article how to customize message converters.
Edit: If you are using XML instead of Java configs, you can create a custom MyJsonMapper class extending ObjectMapper with custom configuration, and then use it as follows
public class MyJsonMapper extends ObjectMapper {
public MyJsonMapper() {
this.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
}
}
In your XML:
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="jacksonObjectMapper" />
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<bean id="jacksonObjectMapper" class="com.mycompany.example.MyJsonMapper" >

cant find spring.jackson.serialization.FAIL_ON_EMPTY_BEANS=false in spring boot 2.2.5
I use this
#Configuration
public class SerializationConfiguration {
#Bean
public ObjectMapper objectMapper() {
return new ObjectMapper().disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
}
}

If you are using Spring Boot / JPA , you also have to observe if you are using
getOne (goes for jpa getReference ) for the findOne / enetiyManager.find(Clazz , id)
GetOne Relies on Persistence cached reference by ID that is designed to retrieve entity with only ID in it. Its use was mostly for indicating reference existed without the need to retrieve whole entity.
The find method is straight forward to persistence manager to obtain the persistent instance.
This second one will observe you annotation #JsonIgnore accordingly and will give you the expected result.
// On entity...
#JsonIgnore
#OneToMany(fetch = FetchType.LAZY, mappedBy = "foo")
private List<Foo> fooCollection;
// later on persistence impl
entityManager.find(Caso.class, id);
// or on serivce
casoRepository.findById(id); //...

For me, the Issue was with typecasting from org.json.JSONObject object to org.json.simple.JSONObject and I solved it by parsing value from org.json.JSONObject and then cast it to use as org.json.simple.JSONObject
JSONParser parser = new JSONParser();
org.json.simple.JSONObject xmlNodeObj = (org.json.simple.JSONObject) parser.parse(XMLRESPONSE.getJSONObject("xmlNode").toString());

Related

Spring Boot Quartz, Integration Inbound channel adapter and trigger bindings

We have Quartz Job + File Integration adapter using XML configurations and is working fine, however since trying to move to Spring Boot and these configurations to annotations
Below is the XML configuration for which I am looking for equivalent annotations and bindings
<bean id="scheduler"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="schedulerContextAsMap">
<map>
<entry key="inboundadapterendpoint"><ref bean="incomingfiles" /></entry>
<entry key="inboundendpointtrigger"><ref bean="incomingfiles-trigger"/></entry>
</map>
</property>
</bean>
<bean id="inboundendpointtrigger" class="abc.xyz.Trigger" />
<file:inbound-channel-adapter id="incomingfiles" channel="xyz" directory="" scanner="recursiveScanner" auto-startup="false" prevent-duplicates="false">
<integration:poller task-executor="fileChannelTaskExecutor" trigger="incomingfiles-trigger" max-messages-per-poll="1">
</integration:poller>
</file:inbound-channel-adapter>
How do we get the Inbound Adapter Bean & poller trigger
created using annotations below is injected during scheduler factory creation in spring Boot quartz config
#Bean
#InboundChannelAdapter(poller = #Poller(trigger="customTrigger")
public MessageSource<File> fileReadingMessageSource() {
}
Thanks in advance for any help or suggestions regarding the same
Artem Bilan, thanks very much for the response.
Follow up question post trying out the code provided in response
#Configuration
public class QuartzConfig {
#Autowired
private CustomTrigger inboundEndPointTrigger;
#Autowired
private AbstractEndpoint incomingFiles;
#Bean
public SchedulerFactoryBean schedulerFactoryBean() {
System.out.println("incomingFiles value is " + incomingFiles);
}
}
#Bean(name = "incomingFiles")
#InboundChannelAdapter(autoStartup = "false", value = "xyz", poller = #Poller(trigger = "inboundEndPointTrigger", maxMessagesPerPoll = "2", errorChannel = "abc"))
public MessageSource<File> fileReadingMessageSource() {
}
Output of above is reference for errorLogger instead of Inbound Channel Adapter.
incomingFiles value is bean '_org.springframework.integration.errorLogger'
How do i bind the exact Inbound Adapter with name incomingFiles to scheduler factory ?
Update after trying out with #EndPointId...
#Bean
#EndPointId("incomingFiles")
#InboundChannelAdapter(autoStartup = "false", value = "xyz", poller = #Poller(trigger = "inboundEndPointTrigger", maxMessagesPerPoll = "2", errorChannel = "abc"))
public MessageSource<File> fileReadingMessageSource() {
}
System.out.println("incomingFiles value is " + incomingFiles); print in QuartzConfig class above is still giving a reference to Logger object
incomingFiles value is bean '_org.springframework.integration.errorLogger'
Found the response in below SO (Spring Cloud Stream + Quartz ) on how the bean will be created for Inbound Channel Adapter.
Since the AbstractEndPoint is returning the logger reference instead of InboundChannelAdapter ,
is it ok to get the Inbound Adapter channel bean reference via application context in scheduler factory ? are there any issues with this ?
try {
ApplicationContext applicationContext = (ApplicationContext) context.getScheduler().getContext().get("applicationContext");
AbstractEndpoint abstractEndPoint = (AbstractEndpoint) applicationContext
.getBean("fileConfig.fileReadingMessageSource.inboundChannelAdapter");
} catch(SchedulerException ex) {
}
fileConfig is the Spring File integration configuration class name where InboundChannelAdapter is defined..
I'm not sure why you have closed your old question - you could just edit it properly and we would have a link to other question. But anyway, the answer is like this:
Any XML bean definition could be declared in Java & annotation config with a #Bean method definition.
So, that <bean id="inboundendpointtrigger" class="abc.xyz.Trigger" /> would be in Java like this:
#Bean
Trigger customTrigger() {
return new abc.xyz.Trigger();
}
You already use its bean name as a reference in the #Poller.
The same you do for the SchedulerFactoryBean and configure its setSchedulerContextAsMap() in that #Bean method. You have already a customTrigger() bean for reference and do get access to the SourcePollingChannelAdapter endpoint based on the #InboundChannelAdapter, you need to inject into a #Bean method. Kinda this:
#Bean
SchedulerFactoryBean schedulerFactory(Trigger trigger, SourcePollingChannelAdapter endpoint) {
}
Don't forget to use an #InboundChannelAdapter(autoStartup = "false") as Gary recommends in other SO question.

Wiring multiple beans with the same dependency via Spring Boot #Configuration

In older Spring MVC apps, where you'd specify application.xml and declare your app's beans so that Spring DI could instantiate them and wire them together, you might have something like this:
<bean id="chargeFactory" class="com.example.myapp.ChargeFactory" />
<bean id="paymentService" class="com.example.myapp.DefaultPaymentService">
<ref id="chargeFactory"/>
</bean>
<bean id="chargeAuditor" class="com.example.myapp.ChargeAuditor">
<ref id="chargeFactory"/>
</bean>
Which might help wire up the following code:
public interface PaymentService {
public void makePayment(Payment payment);
}
public class DefaultPaymentService implements PaymentService {
#Autowired
private ChargeFactory chargeFactory;
#Override
public void makePayment(Payment payment, String key) {
Charge charge = chargeFactory.createCharge(key);
charge.doCharge(payment);
}
}
public class ChargeAuditor {
#Autowired
private ChargeFactory chargeFactory;
public void auditAllCharges(String key) {
List<Charge> charges = chargeFactory.getAllCharges(key);
// blah whatever
}
}
How do you accomplish the same bean wiring in Spring Boot with the #Configuration class? For example:
#Configuration
public class MyAppInjector {
#Bean
public ChargeFactory chargeFactory() {
return new ChargeFactory();
}
#Bean
public PaymentService paymentService() {
return new DefaultPaymentService(chargeFactory());
}
#Bean
public ChargeAuditor chargeAuditor() {
return new ChargeAuditor(chargeFactory());
}
}
This might work but introduces some issues:
It would force me to have to write value constructors for all my classes, which goes against everything I see in literally every tutorial/article I've come across. Plus, if I had to do that, then there's no real value to #Autowired anyways...
At this point I'm essentially doing "DIY DI", which is OK, except I'm trying to deliberately use Spring DI :-)
Every time I call chargeFactory() I'm getting a new (prototype-style) ChargeFactory instance. Maybe I want a singleton. Using this approach I have to hand-roll my own singleton implementation.
Sure, I can do all of this, but I feel like I'm flagrantly misusing/misunderstanding how #Configuration is supposed to be used, because it seems like I'm introducing a whole lot of DIY/homegrown code to solve something Spring DI should be able to do for me.
How would I reference the chargeFactory bean and wire it into both the "provider methods" for the paymentService and chargeAuditor beans? Again, looking for the Java-based #Configuration solution instead of writing an XML document to define the wirings.
I found this article which seems to be the only tutorial/documentation (surprisingly) on wiring Spring Boot apps via #Configuration (which leads me to believe there might be other/better methods...), but it does not address:
How to specify singleton vs prototype bean instantiation patterns
If multiple instances of a bean-class exist, how do I specify which instance gets wired into which dependency?
How do I get around not defining value constructors for all my classes, and just let Spring/#Autowired inject fields automagically?
When you call chargeFactory() , spring won't create new instance everytime. Give it a try and see. Same object will be returned. Anyways
You can do something like this.
#Bean
public PaymentService paymentService(ChargeFactory chargeFactory) { return new DefaultPaymentService(chargeFactory); }

Using spring to load properties as System properties

I'm using Spring 4.1.6.
I have something like the following:
foo.properties:
valueX=a
valueY=b
Spring bean:
<context:property-placeholder location="classpath:foo.properties" ignore-unresolvable="false" ignore-resource-not-found="false" />
<bean id="foo" class="com.foo.bar.MyClass" >
<property name="someValue" value="${valueX}" />
</bean>
I have a non-Spring class which also needs to use a value from foo.properties.
Non Spring Class:
public void doSomething() {
String valueY = System.getProperty("valueY");
}
When Spring loads foo.properties, is there a way to populate all the properties into System properties so that I can get "valueY" using System.getProperty("valueY").
I don't want to load foo.properties again in my non-Spring class.
The context:property-placeholder will create a PropertySourcesPlaceholderConfigurer config bean for you. You cannot access the properties from this bean programatically as stated here.
What you can do is to load the properties into a separate spring bean as given below.
#Bean(name = "mapper")
public PropertiesFactoryBean mapper() {
PropertiesFactoryBean bean = new PropertiesFactoryBean();
bean.setLocation(new ClassPathResource("application.properties"));
return bean;
}
and then set the system property when the context load is finished using a listener as given below. Got the code from this answer
#Component
public class YourJobClass implements ApplicationListener<ContextRefreshedEvent> {
#Resource(name = "mapper")
private Properties myTranslator;
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
System.setProperties(myTranslator);
}
}

How to avoid lazy fetch in JSON serialization using Spring Data JPA + Spring Web MVC?

I have a solution using Spring Data JPA and a REST Controller in Spring Web MVC. The persistence provider is Hibernate.
The persistence layer is built using Spring Repositories and between de REST Controller and the repository exists a Service Layer:
Entity <--> Repository <--> Service <--> Controller
At entity level, I have #OneToMany fields with FetchType = LAZY.
When the REST Controller make the serialization, the fetching is made, but this is undesirable in some cases.
I already tried with #JSONInclude Jackson annotation and the serialization still occurs.
Can somebody help me with a proved solution?
If I understood you properly, you want to serialize only when the lazy loaded collection is fetched, but you don't want the serialization to trigger the fetching.
If that is the case you should use the jackson-datatype-hibernate, and added as their docs already explains
public class HibernateAwareObjectMapper extends ObjectMapper {
public HibernateAwareObjectMapper() {
registerModule(new Hibernate4Module());
}
}
than register
<mvc:annotation-driven>
<mvc:message-converters>
<!-- Use the HibernateAware mapper instead of the default -->
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="path.to.your.HibernateAwareObjectMapper" />
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
The module has a Feature.FORCE_LAZY_LOADING settings, that tells whether the object should be forced to be loaded and then serialized, which is by default set to false which I believe is the behaviour you need
Simple architectural solution is not to use model Entity as Data Transfer Object. Make Simple POJO as Data transfer Object. In the conversion logic you could easily put try and catch block for LazyInitializationException. And thus your POJO is always serializable and You can use it on your controller.
Use the #JsonIgnore annotation if you ALWAYS want to skip this particular field. use #JsonView if you want to dynamically determine which field(s) to skip. Note that #JsonView is a Jackson specific annotation, but since you're already using Jackson, things should be fine.
We can do this by adding Hibernate4Module (which support Lazy objects) to the default MappingJackson2HttpMessageConverter that Spring already provide and by adding it to HttpMessageConverters.
So we need to extend our spring config class from WebMvcConfigurerAdapter and override the method configureMessageConverters and add MappingJackson2HttpMessageConverter with the Hibernate4Module registered in it.
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
//Here we add our custom-configured HttpMessageConverter
converters.add(jacksonMessageConverter());
super.configureMessageConverters(converters);
}
// Here we register the Hibernate4Module into an ObjectMapper,
// then use this custom ObjectMapper
// to the MessageConverter
public MappingJackson2HttpMessageConverter jacksonMessageConverter(){
MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper mapper = new ObjectMapper();
//Registering Hibernate4Module to support lazy objects
mapper.registerModule(new Hibernate4Module());
messageConverter.setObjectMapper(mapper);
return messageConverter;
}
You can solve this problem with wit 2 steps with jackson-datatype-hibernate:
kotlin example
Add In build.gradle.kts:
implementation("com.fasterxml.jackson.datatype:jackson-datatype-hibernate5:$jacksonHibernate")
Create #Bean
#Bean
fun hibernate5Module(): Module = Hibernate5Module()
Notice that Module is com.fasterxml.jackson.databind.Module, not java.util.Module
Also good practice is to add #JsonBackReference & #JsonManagedReference to #OneToMany & #ManyToOne relationships.

Dynamically load spring bean properties from database or Java Objects )

I have a scenario where I need to load properties from database or java object into beans.
Consider the example:
<bean id="ConfigAsstDemoBeanParent" class="gps.springconfig.DemoClass" lazy-init="true">
<property name="demoValueFromBean" value="demoValue"></property>
<property name="demoValueForKeyFromProperties" value="${DEMO_KEY}"></property>
</bean>
and instead of the ${DEMO_KEY} property placeholder, which loads a value from the property file, I need to load a value from the database, which I retrieve using a stored procedure from a Java class.
Please suggest me a mechanism which I can leverage for the above scenario. Currently I am investigating extending SpringMain and/or PropertyPlaceholderConfigurer class and write my own custom BootStrapper.
Also please suggest hints on writing a BootStrapper for the above mentioned scenario.
One of the cases where Java configuration seems to be a great alternative:
#Configuration
public class Config {
#Resource
private DataSource dataSource;
#Bean
#Lazy
public DemoClass configAsstDemoBeanParent() {
DemoClass demo = new DemoClass();
demo.setDemoValueFromBean("demoValue");
demo.demoValueForKeyFromProperties( /* query the database here */);
return demo;
}
}
Note that you can inject DataSource (or JdbcTemplate) to your #Configuration class providing it was defined elsewhere.

Resources