Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix check for configuration properties #11379

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,7 @@ private sealed interface MappingBuilder<B> permits DefaultMappingBuilder, MergeM
@NonNull Argument<?>[] getBuilderArguments();

/**
* Get the argument index based on its name
* Get the argument index based on its name.
*
* @param name The argument name
* @return The index
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,13 @@ public PropertyMetadata visitProperty(ClassElement owningType,
PropertyMetadata metadata = new PropertyMetadata();
metadata.declaringType = declaringType.getName();
metadata.name = name;
metadata.path = NameUtils.hyphenate(buildPropertyPath(owningType, declaringType, name), true);
metadata.path = propertyType.stringValue(ConfigurationReader.class, ConfigurationReader.PREFIX)
.orElseGet(() -> NameUtils.hyphenate(buildPropertyPath(owningType, declaringType, name), true));
if (propertyType.hasStereotype(ConfigurationReader.class)) {
metadata.path = ConfigurationUtils.getRequiredTypePath(propertyType);
} else {
metadata.path = NameUtils.hyphenate(buildPropertyPath(owningType, declaringType, name), true);
}
metadata.type = propertyType.getType().getName();
metadata.description = description;
metadata.defaultValue = defaultValue;
Expand All @@ -192,7 +198,7 @@ public PropertyMetadata visitProperty(ClassElement owningType,
*/
@SuppressWarnings("MagicNumber")
static String quote(String string) {
if (string == null || string.length() == 0) {
if (string == null || string.isEmpty()) {
return "\"\"";
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,13 +158,15 @@ private void build(BeanDefinitionVisitor visitor) {
if (processAsProperties()) {
memberQuery = memberQuery.excludePropertyElements();
for (PropertyElement propertyElement : classElement.getBeanProperties()) {
propertyElement.getField().ifPresent(processedFields::add);
visitPropertyInternal(visitor, propertyElement);
if (visitPropertyInternal(visitor, propertyElement)) {
propertyElement.getField().ifPresent(processedFields::add);
}
}
} else {
for (PropertyElement propertyElement : classElement.getSyntheticBeanProperties()) {
propertyElement.getField().ifPresent(processedFields::add);
visitPropertyInternal(visitor, propertyElement);
if (visitPropertyInternal(visitor, propertyElement)) {
propertyElement.getField().ifPresent(processedFields::add);
}
}
}
List<MemberElement> memberElements = new ArrayList<>(classElement.getEnclosedElements(memberQuery));
Expand Down Expand Up @@ -195,13 +197,14 @@ private void visitMethodInternal(BeanDefinitionVisitor visitor, MethodElement me
}
}

private void visitPropertyInternal(BeanDefinitionVisitor visitor, PropertyElement propertyElement) {
private boolean visitPropertyInternal(BeanDefinitionVisitor visitor, PropertyElement propertyElement) {
boolean claimed = visitProperty(visitor, propertyElement);
if (claimed) {
propertyElement.getReadMethod().ifPresent(element -> addOriginatingElementIfNecessary(visitor, element));
propertyElement.getWriteMethod().ifPresent(element -> addOriginatingElementIfNecessary(visitor, element));
propertyElement.getField().ifPresent(element -> addOriginatingElementIfNecessary(visitor, element));
}
return claimed;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
import io.micronaut.http.filter.HttpFilterResolver;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.List;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,11 @@ public final ByteBufAllocator alloc() {
return (ByteBufAllocator) bootstrap.config().options().getOrDefault(ChannelOption.ALLOCATOR, ByteBufAllocator.DEFAULT);
}

/**
* Returns event loop group.
*
* @return the group
*/
EventLoopGroup getGroup() {
return group;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public RequestAttributeAnnotationBinder(ConversionService conversionService) {

/**
* @param conversionService conversionService
* @param argument argument
*/
public RequestAttributeAnnotationBinder(ConversionService conversionService,
Argument<T> argument) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,17 @@ protected void disregardBackpressureThisSide() {
}
}

public record UpstreamPair(BufferConsumer.Upstream left, BufferConsumer.Upstream right) {
/**
* Pair of {@link BufferConsumer.Upstream} objects.
*
* @param left left {@link BufferConsumer.Upstream} object
* @param right right {@link BufferConsumer.Upstream} object
*/
public record UpstreamPair(
BufferConsumer.Upstream left,
BufferConsumer.Upstream right
) {

UpstreamPair flip() {
return new UpstreamPair(right, left);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,4 +215,248 @@ interface Foo {
ctx.close()
}

void "test @Inject with nested configurationProperties"() {
given:
ApplicationContext ctx = buildContext("test.NestedConfig", '''
package test;

import io.micronaut.context.annotation.ConfigurationProperties;
import jakarta.inject.Inject;

@ConfigurationProperties("product-aggregator")
class NestedConfig {

@Inject
LevelOne levelOnez = new LevelOne();

public LevelOne getLevelOnez() {
return levelOnez;
}

public void setLevelOnez(LevelOne levelOnez) {
this.levelOnez = levelOnez;
}

@ConfigurationProperties("level-one")
static class LevelOne {

String levelOneValue;

@Inject
LevelTwo levelTwo = new LevelTwo();

public String getLevelOneValue() {
return levelOneValue;
}

public void setLevelOneValue(String levelOneValue) {
this.levelOneValue = levelOneValue;
}

public LevelTwo getLevelTwo() {
return levelTwo;
}

public void setLevelTwo(LevelTwo levelTwo) {
this.levelTwo = levelTwo;
}

@ConfigurationProperties("level-two")
static class LevelTwo {

private String levelTwoValue;

public String getLevelTwoValue() {
return levelTwoValue;
}

public void setLevelTwoValue(String levelTwoValue) {
this.levelTwoValue = levelTwoValue;
}
}
}
}
''')
ctx.getEnvironment().addPropertySource(PropertySource.of([
'product-aggregator.level-one.level-one-value': 'ONE',
'product-aggregator.level-one.level-two.level-two-value': 'TWO',
]))

when:
Class<?> testProps = ctx.classLoader.loadClass("test.NestedConfig")
def testPropBean = ctx.getBean(testProps)
def definition = ctx.getBeanDefinition(testProps)

then:
noExceptionThrown()

definition.properties.injectedFields.size() == 1
definition.properties.injectedFields[0].name == "levelOnez"

testPropBean.getLevelOnez().getLevelOneValue() == "ONE"
testPropBean.getLevelOnez().getLevelTwo()
testPropBean.getLevelOnez().getLevelTwo().getLevelTwoValue() == "TWO"

cleanup:
ctx.close()
}

void "test @Inject with nested configurationProperties - method injection"() {
given:
ApplicationContext ctx = buildContext("test.NestedConfig", '''
package test;

import io.micronaut.context.annotation.ConfigurationProperties;
import io.micronaut.core.annotation.Nullable;import jakarta.inject.Inject;

@ConfigurationProperties("product-aggregator")
class NestedConfig {

private LevelOne levelOnez = new LevelOne();

public LevelOne getLevelOnez() {
return levelOnez;
}

public void setLevelOnez(LevelOne levelOnez) {
this.levelOnez = levelOnez;
}

@ConfigurationProperties("level-one")
static class LevelOne {

String levelOneValue;

@Inject
LevelTwo levelTwo = new LevelTwo();

public String getLevelOneValue() {
return levelOneValue;
}

public void setLevelOneValue(String levelOneValue) {
this.levelOneValue = levelOneValue;
}

public LevelTwo getLevelTwo() {
return levelTwo;
}

public void setLevelTwo(LevelTwo levelTwo) {
this.levelTwo = levelTwo;
}

@ConfigurationProperties("level-two")
static class LevelTwo {

private String levelTwoValue;

public String getLevelTwoValue() {
return levelTwoValue;
}

public void setLevelTwoValue(String levelTwoValue) {
this.levelTwoValue = levelTwoValue;
}
}
}
}
''')
ctx.getEnvironment().addPropertySource(PropertySource.of([
'product-aggregator.level-one.level-one-value': 'ONE',
'product-aggregator.level-one.level-two.level-two-value': 'TWO',
]))

when:
Class<?> testProps = ctx.classLoader.loadClass("test.NestedConfig")
def testPropBean = ctx.getBean(testProps)

then:
noExceptionThrown()

testPropBean.getLevelOnez().getLevelOneValue() == "ONE"
testPropBean.getLevelOnez().getLevelTwo()
testPropBean.getLevelOnez().getLevelTwo().getLevelTwoValue() == "TWO"

cleanup:
ctx.close()
}

void "test @Inject with nested configurationProperties - field only"() {
given:
ApplicationContext ctx = buildContext("test.NestedConfig", '''
package test;

import io.micronaut.context.annotation.ConfigurationProperties;
import jakarta.inject.Inject;

@ConfigurationProperties("product-aggregator")
class NestedConfig {

@Inject
LevelOne levelOnez = new LevelOne();

@ConfigurationProperties("level-one")
static class LevelOne {

String levelOneValue;

@Inject
LevelTwo levelTwo = new LevelTwo();

public String getLevelOneValue() {
return levelOneValue;
}

public void setLevelOneValue(String levelOneValue) {
this.levelOneValue = levelOneValue;
}

public LevelTwo getLevelTwo() {
return levelTwo;
}

public void setLevelTwo(LevelTwo levelTwo) {
this.levelTwo = levelTwo;
}

@ConfigurationProperties("level-two")
static class LevelTwo {

private String levelTwoValue;

public String getLevelTwoValue() {
return levelTwoValue;
}

public void setLevelTwoValue(String levelTwoValue) {
this.levelTwoValue = levelTwoValue;
}
}
}
}
''')
ctx.getEnvironment().addPropertySource(PropertySource.of([
'product-aggregator.level-one.level-one-value': 'ONE',
'product-aggregator.level-one.level-two.level-two-value': 'TWO',
]))

when:
Class<?> testProps = ctx.classLoader.loadClass("test.NestedConfig")
def testPropBean = ctx.getBean(testProps)
def definition = ctx.getBeanDefinition(testProps)

then:
noExceptionThrown()

definition.properties.injectedFields.size() == 1
definition.properties.injectedFields[0].name == "levelOnez"

testPropBean.levelOnez.getLevelOneValue() == "ONE"
testPropBean.levelOnez.getLevelTwo()
testPropBean.levelOnez.getLevelTwo().getLevelTwoValue() == "TWO"

cleanup:
ctx.close()
}
}
Loading
Loading