Why does Quarkus complain about my (unused) #ApplicationScoped data class with a #ConfigProperty property? - kotlin

This kotlin data class is part of an internal library used in some Quarkus microservices (Quarkus 2.0.0.Final):
#ApplicationScoped
data class FooConfiguration(
#ConfigProperty(name = "foo.bar")
val fooBar: String
)
The library is used in a few microservices, and most of them do use that configuration. But some are not. For those, the foo.bar property is not defined in the application.properties. I would expect this to not matter at all, as those services are never injecting a FooConfiguration, so I'd expect that to never be constructed.
However, the application refuses startup with this error message:
SRCFG00014: The config property foo.bar is required but it could not be found in any config source
I know how to workaround this issue (simply supplying a nonsense value), but I currently wonder why this is an issue in the first place. The configuration bean should never get constructed. Why is this happening?

This is a MicroProfile Config-related issue.
Your foo.bar property is optional, not required, in the parlance of the MicroProfile Config specification, because a value for it is not present in any configuration source, as you have indicated. To inject a value for an optional MicroProfile Config configuration property, you need to use java.util.Optional. I don't know Kotlin, so here is what it would look like in Java:
#Inject
#ConfigProperty(name = "foo.bar")
private Optional<String> fooBar;

Related

#field:JsonProperty vs #JsonProperty at runtime vs swagger doc

I'm writing a new app with Quarkus framework and Kotlin languague. If that matters, Gradle is configured with the quarkus reactive libraries but i'm not using them for now.
So i had this bean as input of a REST resource :
#JsonInclude(JsonInclude.Include.NON_EMPTY)
data class DemoRestRequest(
#JsonProperty("public_name")
val internalName: String?,
#JsonProperty("public_day")
val internalDay: LocalDate
}
used by an endpoint declared as such :
#Path("/bean")
#POST
fun testBeanValidationException(
bean: DemoRestRequest
): RestResponse<DemoRestResponse> { ... }
The HTTP endpoint is functional when called. Especially, the mandatory member "public_day" is indeed mandatory.
Issue A/ (apparently solved)
I noticed that the Swagger documention referenced the internal names of the members, which is bad, until I randomly experimented with
#JsonInclude(JsonInclude.Include.NON_EMPTY)
data class DemoRestRequest(
#field:JsonProperty("public_name")
val internalName: String?,
#field:JsonProperty("public_day")
val internalDay: LocalDate
}
With this change, the Swagger doc was fine.
Issue B/
Then at runtime when calling the endpoint, i received a 400 Bad Request by the framework because the mandatory field of the bean was considered missing, even though I provided it under the name "public_name". The call was OK if I provided the field with its internal name.
Considering the starting point, i tried this :
#JsonInclude(JsonInclude.Include.NON_EMPTY)
data class DemoRestRequest(
#field:JsonProperty("public_name")
val internalName: String?,
#field:JsonProperty("public_day")
#JsonProperty("public_day")
val internalDay: LocalDate
}
and now, both Swagger and the framework at runtime are OK.
Can somebody explains me why i need two annotations for those 2 differents needs and why the behaviour of a nullable vs non nullable fields is different ?
Issue C (bonus)/
That one is a bonus as i guess it's related the web frameworks themselves rather than languages.
If I put JPA annotation to the bean fields, or simply if I don't provide the mandatory field, the Java exception that bubble up to the end user with a "400 Bad Request" will contain the internal name of the invalid/missing field(s).
I can imagine this is understandable given we are now under the hood and not anymore at mapping time between public and internal names.
Nevertheless, i'd like to provide my application's clients a nice XP and tell them which field is generating a 400. Thus i need to get the public name... Not sure how to do that without reimplementing a web framework...

Injected messages returning null in eclipse e4

In my plugin, I have created separate packages for maintaining the messages.properties.In that same package I have created my Mesages.java class as well. Following is my message class
#Message(contributionURI="platform:/plugin/com.chinna.test.properties.messages")
public class Messages {
public String test1;
public String test2;
}
Then injected the message in a different package of the same plugin. like follows. The class in which injected is singleton class.
#Inject
#Translation
Messages messages;
after I injected it I tried access messages.properties in the code like follows
messages.test1
But my application is throwing Null-Pointer exception. since the "messages" is null.
even though I injected, I do not know why "messages" is null.
Could any please help me?
You can only use this in classes which are injected.
Injection is only done on classes referenced in the Application.e4xmi, some extension points or created/injected using the ContextInjectionFactory make or inject methods.
For other classes the older style of messages file extending NLS and calling NLS.initializeMessages can be used.

How to define aspects and pointcuts in WildFly?

We are migrating from JBoss 5 to WildFly 8.2. Still using Spring 3.1. Suddenly none of our aspects can be found when application starts.
We might have solved (partially) the XML configuration (by placing more wildcards around), but annotation based configuration of aspects cannot be solved the same way (no wildcard possible for aspect itself since this is annotated class). Here is the Aspect class definition:
package com.mycompany.session;
#Aspect
#Component("mySessionManager")
public class SessionManager {
// intercepting any class, any method starting with com.mycompany.some
#Pointcut("execution(* com.mycompany.some.*.*(..))")
public void myPointcut() {}
#Around(value="myPointcut()")
public Object process(ProceedingJoinPoint jointPoint)
throws Throwable
{ ... the rest of code }
}
When starting this code without changes under WildFly we get this error:
java.lang.IllegalArgumentException: warning can't determine implemented interfaces of missing type com.mycompany.session.SessionManager
Anything wrong with code? Anything needs to be different in WildFly versus older jboss?
Thanks,
Nikolay

In JAX-RS 2.0, how do I set a property on a FeatureContext from within a DynamicFeature so that the provider being registered can read it?

I have a JAX-RS 2.0 DynamicFeature that registers a response filter on certain classes.
As part of that registration, I'd like the DynamicFeature implementation to set a property that can then be retrieved by the filter instance.
It looks like I should be able to do this. In my DynamicFeature implementation, I should be able to call:
featureContext.property("foo", "bar");
...and it's my understanding that that property is supposed to be durable.
Then, in my filter, I should be able to do:
#Context
private Configuration myConfiguration;
...and should be able to read that property in my filter method:
if (this.myConfiguration != null) {
final Object propertyValue = this.myConfiguration.getProperty("foo");
if ("bar".equals(propertyValue)) {
// Hooray
}
}
But this doesn't work. The Configuration instance that is injected into my filter is non-null, which is good, but contains one irrelevant property in it that I didn't set.
I know that I could accomplish something similar by using an injected ServletContext as the go-between, but I was hoping to avoid using the Servlet APIs here, since this seemed like a "clean" JAX-RS mechanism.
Am I misunderstanding how the Configuration object reachable from within a DynamicFeature's configure method is to be used?

Ninject Conditional injection problems

I have the following bindings declared
Bind<IDataSource>().To<DataSourceOne>();
Bind<ISettings>().To<DataSourceSettings>
.WhenInjectedInto<DataSourceOne>();
Bind<ISettings>().To<Settings>();
now I call
Kernel.Get<IDataSourc>();
Ninject correctly injects a DataSourceSettings, but I need to pass a constructor argument to Settings and DataSourceSettings based on data from a config file. so I've changed the IDataSouce binding as follows
Kernel.Bind<IDataSource>().To<DataSourceOne>()
.WithConstructorArgument("settings", Kernel.Get<ISettings>(
new ConstructorArgument("data", objectContainingConfigFileData)
)
);
in that case Ninject injects Settings class instead of DataSourceSettings class. I assume the problem is that the ISettings is getting resolved before it is injected into the DataSourceSettings class so Ninject does not use the binding I intended it to. Is there a way to get around this. I haven't found anything yet.
It should work if you define the constructor argument for the ISettings binding and not for the DataSource binding. Assuming you already know the object with the config file data in the module. Otherwise maybe a factory would be more appropriate.
kernel.Bind<IDataSource>().To<DataSourceOne>();
kernel.Bind<ISettings>().To<DataSourceSettings>()
.WhenInjectedInto<DataSourceOne>()
.WithConstructorArgument("data", objectContainingConfigFileData);
kernel.Bind<ISettings>().To<Settings>();