Different ObjectMapper / ObjectMapperCustomizer for client and service implementations - quarkus

Quarkus allows a program to use specify a custom Jackson ObjectMapper by using CDI producer method or customize the ObjectMapper with ObjectMapperCustomizer instances.
I need to have different behaviors for RestEasy Reactive Client use and RestEasy Reactive use. Specifically, I want the service implementation to be set with
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true) and the client to have .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
Is it possible to achieve this in Quarkus version 2.7.1.Final?

Related

How to get webflux webClient metrics from custom Webclient Builder

I have created a custom Webclient Builder instead of injecting the default builder.
#Configuration
public class WebClientConfig() {
#Bean(name = "myWebClientBuilder")
public Webclient.Builder customBuilder() {
return WebClient.builder();
}
}
I have multiple services where I use this bean myWebClientBuulder and do further customization with chain of ExchangeFilterFunction.
This might not be the recommended way of using the WebClient but I would like to get some insight if there is a way to get the downstream call metrics from the Webclient based on this configuration.
Actuator Endpoint: actuator/metrics/http.client.requests
Spring Boot auto-configured WebClient.Builder is way powerful than customized version.
I tried to configure the custom builder in WebClientConfig() but it started to structure just like a copy version of WebClientAutoConfiguration. I ended up going with the spring boot autoconfigured WebClient.Builder bean.
If it helps, you can study how WebClientAutoConfiguration tries to configure webClient customizers. For metrics, it would be MetricsWebClientCustomizer.

How can I force #AutoConfigureJsonTesters to use HAL format from spring-hateoas?

I have a small module that should only contain the resource model of my REST service. I want to create a test in this module to ensure that the resource model serializes and deserializes appropriate HAL format.
I have a single test and this is the configuration:
#RunWith(SpringRunner::class
#SpringBootTest
#AutoConfigureJsonTesters
class MyTest {
#Autowired
private lateinit var collectionTester: JacksonTester<Resources<Entity>>
....
}
and a very simple configuration
#SpringBootConfiguration
class TestConfig
When calling collectionTester.write on a list of Entity (which extends ResourceSupport) I don't get an _embedded field, instead I get
{"links":[],"content":[...]}
which is not HAL format.
How can I force #AutoConfigureJsonTesters to give me a JacksonTester with an ObjectMapper configured for HAL?
Spring Boot 2.0.0.RELEASE
Thanks!
The auto-configured JacksonTester will use the context’s ObjectMapper which won’t have any of the Spring HATEOAS stuff configured on it. You might be better creating a JacksonTester yourself and passing it an appropriately configured ObjectMapper to use.
I believe Spring HATEOAS has a module that it applies to the ObjectMapper to configure it. If you get stuck with that, asking in gitter/spring-projects/spring-data is probably your best bet as Spring HATEOAS is maintained by the Data team due to it being used by Spring Data REST.

Apache CXF ContainerRequestFilter with RSA and DS

I'm migrating CXF REST endpoints from blueprint to Declarative Services that runs on Apache Karaf. I use Aries RSA and DOSGI. In the old code ContainerRequestFilter is used (specified in blueprint), but I am not sure how it can be used with DS? From [0] I can see that javax.servlet.Filter can be registered and I wonder what is the right approach. Is it possible to register ContainerRequestFilter by using DS annotations?
[0] http://cxf.apache.org/distributed-osgi-reference.html
This is now possible using the JAX-RS Whiteboard from OSGi R7. Registering a JAX-RS extension is as simple as making it an OSGi service providing the relevant service interface(s) - in this case ContainerRequestFilter and adding the service property "osgi.jaxrs.extension=true".
By also using R7 features from Declarative Services and bnd 4.0.0 this service property can be applied to Declarative Services components using the new ComponentPropertyType meta-annotations. A standard annotation #JaxrsExtension is part of the JAX-RS whiteboard specification.
For example:
#JaxrsResource
#Component
public class MyRequestFilter implements ContainerRequestFilter {
// Implementation goes in here
}
The OSGi enRoute project provides other examples of using the JAX-RS whiteboard in its examples

java8 time deserialization in Websphere Liberty

I'm having trouble with my Websphere Liberty installation/IBM Bluemix instance. I'm using the new java.time classes (e.g. LocalDateTime) but the deserialized version using the Jackson 2.8 mapper results in badly handable results (full object deserialization instead of timestamps).
https://geowarin.github.io/jsr310-dates-with-jackson.html
But how can I do the same in Liberty?
e.g.: receive 2016-02-02T23:24:08.255+01:00 as the result in a deserialized JSON response
Thanks
The Liberty JAX-RS 2.0 feature includes Jackson to do basic serialization of Java Classes to JSON, but it doesn't expose any of the Jackson APIs.
If you want to change Jackson's behaviour, you should bundle these libraries in your application so that Liberty uses the Jackson that you've provided, rather than the one it has internally:
Jackson
Jackson providers
Then you can also include the Jackson JSR310 module to get your Java 8 times serialized as you want.
However, according to the documentation on that page, you need to register the module with your object mapper.
You want to call JacksonJsonProvider.setMapper() but this isn't straighforwards as usually this object gets instantiated automatically by Liberty and you never see it.
Instead, you can create a ContextProvider to tell the Jackson JAX-RS provider what ObjectMapper to use when it gets instantiated by Liberty.
Adapting the example from your link, you could write something like this:
#Provider
public class JSR310MapperProvider implements ContextResolver<ObjectMapper> {
#Override
public ObjectMapper getContext(Class<?> type) {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
return mapper;
}
}
That should create a configured mapper which should then be used by Jackson to serialize your Java 8 time objects.
Update: If you're overriding getClasses() in your Application class, then the JacksonJsonProvider and your JSR310MapperProvider won't be automatically discovered. You'll need to include both of these classes in the set you return from getClasses()

Using #Inject in Spring with appserver not compatible with Java EE 6

Can I use #Inject annotation in my Spring application, when I will deploy my application in Appserver that doesn't support Java EE 6?
#Inject is introduced in Java EE6 and it doesn't supported by Java EE 5
When you use #Inject in components managed by Spring (Spring beans) its functionality is implemented by Spring, therefore you don't need anything else to make it work.
#Inject support in JavaEE 6 is about components managed by application server (EJBs, etc).
Spring has a synonymous #Autowired annotation that has the same effect. Since it's provided by Spring itself, it should be available on any version of Java that supports annotations.
JSR 330's #Inject annotation can be used in place of Spring's #Autowired in the examples below. #Inject does not have a required property unlike Spring's #Autowire annotation which has a required property to indicate if the value being injected is optional. This behavior is enabled automatically if you have the JSR 330 JAR on the classpath.
spring documentation......
http://static.springsource.org/spring/docs/3.0.0.RC2/reference/html/ch03s09.html
In short, you can. If you are using Spring (>= version 3), Spring will perform its dependency injection base on the #Inject annotations of its beans.
In long, it all depends on what do you mean by "Can be used". Annotation is nothing but a meta data. No one stop you from using #Inject to perform a totally irrelevant function, as long as you inspect the annotation and do whatever you want

Resources