Spring Boot 3 native image with Jackson - spring-boot

I'm trying to setup a new application with latest SpringBoot 3 and everything works fine until I try to create and run my application with Native compilation. Just for your reference here is error that I receive from running unit tests:
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `*****`: cannot deserialize from Object value (no delegate- or property-based Creator): this appears to be a native image, in which case you may need to configure reflection for the class that is to be deserialized
at [Source: (String)"[{"T":"success","msg":"authenticated"}]"; line: 1, column: 3] (through reference chain: java.util.ArrayList[0])
com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1909)
com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:408)
com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1349)
com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1417)
com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:352)
I'm trying to convert JSON string to Object. It works fine when I run it as regular JAR , but it fails with I compile with Navite (GraalVM).

in spring native, Jackson doesn't know how to serialize/deserialize objects without prior knowledge about them, since it must know all the types in compile time.
to run your app in a native mode, you will need to register hints with knowledge about needed proxies, reflected methods, additional resource files/paths, or objects to serialize/deserialize.
to do so, implement the RuntimeHintsRegistrar interface. you can see an example in the docs

Related

How to deserialize json object referring related data using hal links with Jackson and GraalVm?

I'm currently struggling to implement a restfull api using
-> Spring Boot 3.0.0, using spring data rest and spring hateoas
-> Spring native support
Basically, I would like to patch an entity, submitting a new value for a field (pointing to an existing entity in Database).
The reference is handled with an hal link. below is the Json object I "PATCH" to my EntityRepository controller:
{
"shouldBeChecked": true,
"name": "Amical6",
"parent": null,
"authority": "https://myurl/api/authorities/e52cdfb6-6f3c-4552-8ea4-e1357b5d052c"
}
Everything is fine when I run the app from my IDE (without GraalVM Native compilation). But when I go live on my test environment (copiled with GraalVM), I get the following errors :
in the web navigator (running the client app):
{"cause":{"cause":null,"message":"Cannot construct instance of `org.[xxx].Authority` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('https://myurl/api/authorities/e52cdfb6-6f3c-4552-8ea4-e1357b5d052c')\n at [Source: UNKNOWN; byte offset: #UNKNOWN] (through reference chain: org.[xxx].MyObject[\"authority\"])"},"message":"Could not read payload"}
And, in my application logs :
Failed to evaluate Jackson deserialization for type [[simple type, class org.springframework.data.rest.webmvc.PersistentEntityResource]]: java.lang.NullPointerException
I'm pretty sure I've got to add some Native Hints related to Jackson (or maybe Spring hateoas ?). Could someone help me with this?
Regards,
EDIT 2022.11.30
Please find below a small reproducer project:
https://github.com/mathieupedreropro/spring-hal-jackson-graalvm
TLDR
I tried to use Spring Hateoas link handling to patch data to my Rest Webservice in a Native compiled Spring boot 3.0.0 application.
It fails at runtime, when the same application works like a charm using a traditional JDK

Get Jackson ObjectMapper in Quarkus

I am writing a custom OpenApiConfigurator that adds some examples to my api dynamically.
When I add the examples using the value field of io.smallrye.openapi.api.models.examples.ExampleImpl, which is an object, the example is null in swagger-ui. It only works when I added the actual json.
To add the actual json I have to generate it from my response dto using Jackson. But how can I access the quarkus object mapper, for which I have some customisations using ObjectMapperCustomizer, if in the OpenApiConfigurator CDI is not available?
It's actually possible to access the CDI container statically with Arc.container().instance(ObjectMapper::class.java).get()
That solved it for me.

Mule Expression component not able to fetch value from properties file

I want to fetch values dynamically from properties so I have implemented one poc. In that poc I have declared one object with value in mule expression component. After that I am fetching the value key from properties file. It is showing exceptions while testing the application.
Exception MSG: Root Exception stack trace: unresolvable property or identifier: $
EX-1:
flowVars.deptCode=21432143;
property3=${flowVars.deptCode};
EX-2:
property3=${21432143};
In the above two examples ex-2 has worked fine and ex-1 has failed .
Please let me know if anyone have clarity on that.
Thanks,
Praveen
Mule is using Spring Properties which can be kept in a seperate properties file and then retrieved/used in your application via ${propertyName}.
A property placeholder is used to define where you keep those properties.
Ex 1 is not possible because properties are not aware at all of any variables or properties inside of your Mule application.
Another issue is that those files will be loaded when the application is started.
If you change the value of a property a restart of your application is needed, so your approach isn't going to work.
More info in the docs here:
https://docs.mulesoft.com/mule-user-guide/v/3.8/configuring-properties
You can use dataweave script to dynamically read values from property file
#[dw("p(flowVars.deptCode)")]

Getting NoSuchMethodError in Kafka Consumer v0.10.0.1

I am trying to move to KafkaClient 0.10.0.1 from 0.9.0.0. The code is working fine in production with 0.9.0.0. Now the same code in development platform throwing exception when a consumer is started with following exception
javax.servlet.ServletException: java.lang.NoSuchMethodError: org/apache/kafka/clients/consumer/KafkaConsumer.subscribe(Ljava/util/List;)V (loaded from file:/home/vcap/app/wlp/usr/shared/config/lib/global/kafka-clients-0.10.0.1.jar by com.ibm.ws.classloading.internal.AppClassLoader#7a0d5027) called from class com.ibm.b2b.msghub.helper.AbstractB2BConsumer (loaded from file:/home/vcap/app/wlp/usr/shared/config/lib/global/B2BBlueMixLib-1.0.jar by com.ibm.ws.classloading.internal.AppClassLoader#7a0d5027).
Madhu
The client API has slightly changed between Kafka 0.9 and 0.10.
The definition of KafkaConsumer.subscribe() has changed. The first argument is now of type Collection instead of List.
This was done to make the API more consistent as now most (all?) calls take a Collection object whereas before it was a mix of several types.

NullPointerException com.liferay.portal.spring.util.SpringFactoryImpl.setBeanDefinitions

I'm using springFramework and I try to setBeanDefinitions, the problem is that this methode need a Map beanDefinition as a param... could U tell me plz how I could instantiate this param?
NullPointerException at com.liferay.portal.spring.util.SpringFactoryImpl.setBeanDefinitions(SpringFactoryImpl.java:56)
additional information:
I try to deploy a liferay project without using liferay configuration files (only springFramework libraries), I created my own sessionFactory, my own dataSource ... etc!!
when I run the program, I'm able to create dataBase Schema basing on portlet-hbm.xml information... well now I try to instantiate beans for portal-spring.xml.. (which are xxxxpersistance.java)! those latters told me that they use 'com.liferay.portal.kernel.dao.orm.SessionFactory' as a required type and it can not convert property value of type 'org.hibernate.impl.SessionFactoryImpl'!! so I tried to use the liferay libraries only for those beans and I try to instanciate them manually... but I wasn't able to setBeanDefinitions cause I need a Map beanDefinition as a param... I don't know if there is a way to get them using sessionFactory or not!!
Thanks again
You only mention junit in the tags to your question. I'd recommend to write unit tests without relying on the whole Liferay infrastructure. That will tremendously lower your required setup efforts and simplify your life a lot.

Resources