Skip to content

Commit

Permalink
Fix detecting bean for @ConfigurationInject injection (#8234)
Browse files Browse the repository at this point in the history
  • Loading branch information
dstepanov committed Oct 26, 2022
1 parent 2659dfa commit a2c0a8b
Show file tree
Hide file tree
Showing 4 changed files with 302 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
package io.micronaut.inject.processing;

import io.micronaut.context.BeanProvider;
import io.micronaut.context.annotation.Bean;
import io.micronaut.context.annotation.ConfigurationBuilder;
import io.micronaut.context.annotation.ConfigurationInject;
import io.micronaut.context.annotation.ConfigurationReader;
Expand All @@ -40,6 +42,7 @@
import io.micronaut.inject.configuration.PropertyMetadata;
import io.micronaut.inject.visitor.VisitorContext;
import io.micronaut.inject.writer.BeanDefinitionVisitor;
import jakarta.inject.Provider;

import java.time.Duration;
import java.util.Arrays;
Expand Down Expand Up @@ -90,11 +93,11 @@ protected void applyConfigurationInjectionIfNecessary(BeanDefinitionVisitor visi
return;
}
}
processConfigurationInjectionConstructor(visitor, constructor);
processConfigurationInjectionPoint(visitor, constructor);
}

private void processConfigurationInjectionConstructor(BeanDefinitionVisitor visitor,
MethodElement constructor) {
private void processConfigurationInjectionPoint(BeanDefinitionVisitor visitor,
MethodElement constructor) {
for (ParameterElement parameter : constructor.getParameters()) {
if (CONSTRUCTOR_PARAMETERS_INJECTION_ANN.stream().noneMatch(parameter::hasStereotype)) {
processConfigurationConstructorParameter(parameter);
Expand All @@ -106,7 +109,7 @@ private void processConfigurationInjectionConstructor(BeanDefinitionVisitor visi
}

private void processConfigurationConstructorParameter(ParameterElement parameter) {
if (!parameter.hasStereotype(AnnotationUtil.SCOPE)) {
if (isPropertyParameter(parameter)) {
final PropertyMetadata pm = metadataBuilder.visitProperty(
parameter.getMethodElement().getOwningType(),
parameter.getMethodElement().getDeclaringType(),
Expand All @@ -118,6 +121,16 @@ private void processConfigurationConstructorParameter(ParameterElement parameter
}
}

private boolean isPropertyParameter(ParameterElement parameter) {
ClassElement parameterType = parameter.getGenericType();
if (parameterType.isOptional() || parameterType.isAssignable(BeanProvider.class) || parameterType.isAssignable(Provider.class)) {
parameterType = parameterType.getFirstTypeArgument().orElse(parameterType);
// Get the class with type annotations
parameterType = visitorContext.getClassElement(parameterType.getCanonicalName()).orElse(parameterType);
}
return !parameterType.hasStereotype(AnnotationUtil.SCOPE) && !parameterType.hasStereotype(Bean.class);
}

public static boolean isConfigurationProperties(ClassElement classElement) {
return classElement.hasStereotype(ConfigurationReader.class);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package io.micronaut.inject.configproperties

import io.micronaut.annotation.processing.test.AbstractTypeElementSpec
import io.micronaut.context.ApplicationContext

class ConfigurationPropertiesInjectSpec extends AbstractTypeElementSpec {

void "test @ConfigurationInject constructor with beans and other configs"() {
given:
when:
def context = ApplicationContext.run(['spec': getClass().getSimpleName(), 'foo.bar.host': 'test', 'foo.bar.server-port': '123', 'xyz.name': "33"])
def config = context.getBean(MyConfigWithConstructorConfigurationInject)

then:
config.host == 'test'
config.serverPort == 123
config.otherBean
config.otherConfig.name == "33"
config.otherMissingConfig
config.otherSingleton
config.optionalOtherSingleton.get()
config.otherSingletonBeanProvider.get() == config.otherSingleton
config.otherSingletonProvider.get() == config.otherSingleton

cleanup:
context.close()
}

void "test @ConfigurationInject method with beans and other configs"() {
given:
when:
def context = ApplicationContext.run(['spec': getClass().getSimpleName(), 'foo.bar.host': 'test', 'foo.bar.server-port': '123', 'xyz.name': "33"])
def config = context.getBean(MyConfigWithMethodConfigurationInject)

then:
config.host == 'test'
config.serverPort == 123
config.otherBean
config.otherConfig.name == "33"
config.otherMissingConfig
config.otherSingleton
config.optionalOtherSingleton.get()
config.otherSingletonBeanProvider.get() == config.otherSingleton
config.otherSingletonProvider.get() == config.otherSingleton

cleanup:
context.close()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package io.micronaut.inject.configproperties;

import io.micronaut.context.BeanProvider;
import io.micronaut.context.annotation.Bean;
import io.micronaut.context.annotation.ConfigurationInject;
import io.micronaut.context.annotation.ConfigurationProperties;
import io.micronaut.context.annotation.Requires;
import jakarta.inject.Provider;
import jakarta.inject.Singleton;

import java.util.Optional;

@Requires(property = "spec", value = "ConfigurationPropertiesInjectSpec")
@ConfigurationProperties("foo.bar")
class MyConfigWithConstructorConfigurationInject {
private String host;
private int serverPort;
private MI_OtherConfig otherConfig;
private MI_OtherMissingConfig otherMissingConfig;
private MI_OtherBean otherBean;
private MI_OtherSingleton otherSingleton;
private Optional<MI_OtherSingleton> optionalOtherSingleton;
private BeanProvider<MI_OtherSingleton> otherSingletonBeanProvider;
private Provider<MI_OtherSingleton> otherSingletonProvider;

@ConfigurationInject
MyConfigWithConstructorConfigurationInject(String host,
int serverPort,
MI_OtherConfig otherConfig,
MI_OtherMissingConfig otherMissingConfig,
MI_OtherBean otherBean,
MI_OtherSingleton otherSingleton,
Optional<MI_OtherSingleton> optionalOtherSingleton,
BeanProvider<MI_OtherSingleton> otherSingletonBeanProvider,
Provider<MI_OtherSingleton> otherSingletonProvider) {
this.host = host;
this.serverPort = serverPort;
this.otherConfig = otherConfig;
this.otherMissingConfig = otherMissingConfig;
this.otherBean = otherBean;
this.otherSingleton = otherSingleton;
this.optionalOtherSingleton = optionalOtherSingleton;
this.otherSingletonBeanProvider = otherSingletonBeanProvider;
this.otherSingletonProvider = otherSingletonProvider;
}

public String getHost() {
return host;
}

public int getServerPort() {
return serverPort;
}

public MI_OtherBean getOtherBean() {
return otherBean;
}

public MI_OtherConfig getOtherConfig() {
return otherConfig;
}

public MI_OtherMissingConfig getOtherMissingConfig() {
return otherMissingConfig;
}

public MI_OtherSingleton getOtherSingleton() {
return otherSingleton;
}

public Optional<MI_OtherSingleton> getOptionalOtherSingleton() {
return optionalOtherSingleton;
}

public BeanProvider<MI_OtherSingleton> getOtherSingletonBeanProvider() {
return otherSingletonBeanProvider;
}

public Provider<MI_OtherSingleton> getOtherSingletonProvider() {
return otherSingletonProvider;
}
}

@ConfigurationProperties("xyz")
class CI_OtherConfig {

String name;

public void setName(String name) {
this.name = name;
}

public String getName() {
return name;
}
}

@ConfigurationProperties("abc")
class CI_OtherMissingConfig {

String name;

public void setName(String name) {
this.name = name;
}

public String getName() {
return name;
}
}

@Bean
class CI_OtherBean {
}

@Singleton
class CI_OtherSingleton {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package io.micronaut.inject.configproperties;

import io.micronaut.context.BeanProvider;
import io.micronaut.context.annotation.Bean;
import io.micronaut.context.annotation.ConfigurationInject;
import io.micronaut.context.annotation.ConfigurationProperties;
import io.micronaut.context.annotation.Requires;
import jakarta.inject.Provider;
import jakarta.inject.Singleton;

import java.util.Optional;

@Requires(property = "spec", value = "ConfigurationPropertiesInjectSpec")
@ConfigurationProperties("foo.bar")
class MyConfigWithMethodConfigurationInject {
private String host;
private int serverPort;
private MI_OtherConfig otherConfig;
private MI_OtherMissingConfig otherMissingConfig;
private MI_OtherBean otherBean;
private MI_OtherSingleton otherSingleton;
private Optional<MI_OtherSingleton> optionalOtherSingleton;
private BeanProvider<MI_OtherSingleton> otherSingletonBeanProvider;
private Provider<MI_OtherSingleton> otherSingletonProvider;

@ConfigurationInject
void inject(String host,
int serverPort,
MI_OtherConfig otherConfig,
MI_OtherMissingConfig otherMissingConfig,
MI_OtherBean otherBean,
MI_OtherSingleton otherSingleton,
Optional<MI_OtherSingleton> optionalOtherSingleton,
BeanProvider<MI_OtherSingleton> otherSingletonBeanProvider,
Provider<MI_OtherSingleton> otherSingletonProvider) {
this.host = host;
this.serverPort = serverPort;
this.otherConfig = otherConfig;
this.otherMissingConfig = otherMissingConfig;
this.otherBean = otherBean;
this.otherSingleton = otherSingleton;
this.optionalOtherSingleton = optionalOtherSingleton;
this.otherSingletonBeanProvider = otherSingletonBeanProvider;
this.otherSingletonProvider = otherSingletonProvider;
}

public String getHost() {
return host;
}

public int getServerPort() {
return serverPort;
}

public MI_OtherBean getOtherBean() {
return otherBean;
}

public MI_OtherConfig getOtherConfig() {
return otherConfig;
}

public MI_OtherMissingConfig getOtherMissingConfig() {
return otherMissingConfig;
}

public MI_OtherSingleton getOtherSingleton() {
return otherSingleton;
}

public Optional<MI_OtherSingleton> getOptionalOtherSingleton() {
return optionalOtherSingleton;
}

public BeanProvider<MI_OtherSingleton> getOtherSingletonBeanProvider() {
return otherSingletonBeanProvider;
}

public Provider<MI_OtherSingleton> getOtherSingletonProvider() {
return otherSingletonProvider;
}
}

@ConfigurationProperties("xyz")
class MI_OtherConfig {

String name;

public void setName(String name) {
this.name = name;
}

public String getName() {
return name;
}
}

@ConfigurationProperties("abc")
class MI_OtherMissingConfig {

String name;

public void setName(String name) {
this.name = name;
}

public String getName() {
return name;
}
}

@Bean
class MI_OtherBean {
}

@Singleton
class MI_OtherSingleton {
}

0 comments on commit a2c0a8b

Please sign in to comment.