Skip to content

Commit

Permalink
Merge pull request #1109 from Dockbox-OSS/feature/#1001-property-mana…
Browse files Browse the repository at this point in the history
…gement

#1001 Application-level profile and property management
  • Loading branch information
GuusLieben authored Dec 24, 2024
2 parents 8b8bd3a + 14b5be7 commit 836bb99
Show file tree
Hide file tree
Showing 142 changed files with 6,213 additions and 521 deletions.
8 changes: 8 additions & 0 deletions hartshorn-assembly/pom.assembly.xml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@
<groupId>org.dockbox.hartshorn</groupId>
<artifactId>hartshorn-reporting</artifactId>
</dependency>
<dependency>
<groupId>org.dockbox.hartshorn</groupId>
<artifactId>hartshorn-profiles</artifactId>
</dependency>
<dependency>
<groupId>org.dockbox.hartshorn</groupId>
<artifactId>hartshorn-properties</artifactId>
</dependency>
<dependency>
<groupId>org.dockbox.hartshorn</groupId>
<artifactId>hartshorn-util</artifactId>
Expand Down
12 changes: 11 additions & 1 deletion hartshorn-bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
<javax.inject.version>1</javax.inject.version>
<javax.annotations.version>1.3.2</javax.annotations.version>
<junit.version>5.10.3</junit.version>
<logback.version>1.5.6</logback.version>
<logback.version>1.5.15</logback.version>
<mockito.version>5.12.0</mockito.version>
<slf4j.version>2.0.13</slf4j.version>
</properties>
Expand All @@ -47,6 +47,16 @@
<artifactId>hartshorn-util</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.dockbox.hartshorn</groupId>
<artifactId>hartshorn-properties</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.dockbox.hartshorn</groupId>
<artifactId>hartshorn-profiles</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.dockbox.hartshorn</groupId>
<artifactId>hartshorn-spi</artifactId>
Expand Down
4 changes: 4 additions & 0 deletions hartshorn-inject-configurations/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
<groupId>org.dockbox.hartshorn</groupId>
<artifactId>hartshorn-inject</artifactId>
</dependency>
<dependency>
<groupId>org.dockbox.hartshorn</groupId>
<artifactId>hartshorn-properties</artifactId>
</dependency>

<dependency>
<groupId>org.dockbox.hartshorn</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.dockbox.hartshorn.inject.condition.Condition;
import org.dockbox.hartshorn.inject.condition.ConditionContext;
import org.dockbox.hartshorn.inject.condition.ConditionResult;
import org.dockbox.hartshorn.properties.ValueProperty;
import org.dockbox.hartshorn.util.option.Option;

/**
Expand All @@ -39,23 +40,35 @@ public class PropertyCondition implements Condition {
public ConditionResult matches(ConditionContext context) {
return context.annotatedElement().annotations().get(RequiresProperty.class).map(condition -> {
String name = condition.name();
Option<String> result = context.application().properties().property(name);
Option<ValueProperty> result = context.application()
.environment()
.propertyRegistry()
.get(name);
if (result.absent()) {
if (condition.matchIfMissing()) {
return ConditionResult.matched();
}
return ConditionResult.notFound("property", name);
}

String value = result.get();
if (condition.matchIfMissing()) {
return ConditionResult.found("property", name, value);
ValueProperty property = result.get();
Option<String> value = property.value();
if (condition.matchIfMissing() && value.present()) {
return ConditionResult.found("property", name, value.get());
}

if (condition.withValue().isEmpty()) {
return ConditionResult.matched();
}
return condition.withValue().equals(value) ? ConditionResult.matched() : ConditionResult.notEqual("property", condition.withValue(), value);
else if (value.absent()) {
return ConditionResult.notFound("property", name);
}
else {
String actualValue = value.get();
return condition.withValue().equals(actualValue)
? ConditionResult.matched()
: ConditionResult.notEqual("property", condition.withValue(), actualValue);
}
}).orCompute(() -> ConditionResult.invalidCondition("property")).get();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,20 @@

package org.dockbox.hartshorn.inject.condition.support;

import org.dockbox.hartshorn.inject.condition.RequiresCondition;
import org.dockbox.hartshorn.properties.PropertyRegistry;
import org.dockbox.hartshorn.util.introspect.annotations.AttributeAlias;
import org.dockbox.hartshorn.util.introspect.annotations.Extends;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.dockbox.hartshorn.inject.ApplicationPropertyHolder;
import org.dockbox.hartshorn.inject.condition.RequiresCondition;
import org.dockbox.hartshorn.util.introspect.annotations.AttributeAlias;
import org.dockbox.hartshorn.util.introspect.annotations.Extends;

/**
* A condition that requires a property to be present in the application's {@link ApplicationPropertyHolder}.
* The property is resolved by name, and optionally by value. If the value is not specified, the property is
* required to be present and have any value.
* A condition that requires a property to be present in the application's {@link PropertyRegistry}. The property
* is resolved by name, and optionally by value. If the value is not specified, the property is required to be
* present and have any value.
*
* @see PropertyCondition
*
Expand Down
4 changes: 4 additions & 0 deletions hartshorn-inject/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
<groupId>org.dockbox.hartshorn</groupId>
<artifactId>hartshorn-spi</artifactId>
</dependency>
<dependency>
<groupId>org.dockbox.hartshorn</groupId>
<artifactId>hartshorn-properties</artifactId>
</dependency>

<dependency>
<groupId>org.dockbox.hartshorn</groupId>
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,4 @@ public interface InjectionCapableApplication extends Context {
ComponentProvider defaultProvider();

HierarchicalBinder defaultBinder();

ApplicationPropertyHolder properties();
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import org.dockbox.hartshorn.inject.targets.ComponentInjectionPoint;
import org.dockbox.hartshorn.inject.targets.ComponentInjectionPointsResolver;
import org.dockbox.hartshorn.properties.PropertyRegistry;
import org.dockbox.hartshorn.proxy.ProxyOrchestrator;
import org.dockbox.hartshorn.util.introspect.Introspector;

Expand Down Expand Up @@ -69,5 +70,7 @@ public interface InjectorEnvironment {

InjectorConfiguration configuration();

PropertyRegistry propertyRegistry();

ExceptionHandler exceptionHandler();
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import org.dockbox.hartshorn.inject.annotations.Named;
import org.dockbox.hartshorn.util.TypeUtils;
import org.dockbox.hartshorn.util.stream.EntryStream;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
Expand Down Expand Up @@ -139,8 +140,8 @@ public int hashCode() {

@Override
public String toString() {
String metaString = this.meta.entrySet().stream()
.map(entry -> "%s=%s".formatted(entry.getKey(), entry.getValue()))
String metaString = EntryStream.of(this.meta)
.map((key, value) -> "%s=%s".formatted(key, value))
.collect(Collectors.joining(", "));
return "%s{%s}".formatted(this.type.getSimpleName(), metaString);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,6 @@

package org.dockbox.hartshorn.inject;

import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.Set;
import java.util.stream.Collectors;

import org.dockbox.hartshorn.inject.annotations.Initialize;
import org.dockbox.hartshorn.inject.annotations.Priority;
import org.dockbox.hartshorn.inject.annotations.Qualifier;
Expand All @@ -38,6 +33,10 @@
import org.dockbox.hartshorn.util.introspect.view.TypeView;
import org.dockbox.hartshorn.util.option.Option;

import java.util.Collection;
import java.util.Set;
import java.util.stream.Collectors;

/**
* A {@link ComponentKeyResolver} that resolves the {@link ComponentKey} of a component based on the
* presence of annotations on the component type. The key is resolved as follows:
Expand Down Expand Up @@ -114,8 +113,7 @@ protected void configureQualifiers(ComponentKey.Builder<?> builder, ElementAnnot
* @return the resolved qualifiers
*/
protected Set<QualifierKey<?>> resolveQualifiers(ElementAnnotationsIntrospector annotations) {
Set<Annotation> metaQualifiers = annotations.annotedWith(Qualifier.class);
return metaQualifiers.stream()
return annotations.annotedWith(Qualifier.class).stream()
.map(QualifierKey::of)
.collect(Collectors.toSet());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Copyright 2019-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.dockbox.hartshorn.inject.annotations;

import org.dockbox.hartshorn.properties.ListProperty;
import org.dockbox.hartshorn.properties.ObjectProperty;
import org.dockbox.hartshorn.properties.ValueProperty;
import org.dockbox.hartshorn.util.introspect.annotations.Extends;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Indicates that the annotated field or parameter should be injected with a value from the {@link
* org.dockbox.hartshorn.properties.PropertyRegistry}. If no value is found, the {@link PropertyValue#defaultValue()} is used.
*
* <p>Properties in the property registry may have been obtained from various sources, such as configuration files or
* environment variables. The {@link PropertyValue} annotation is a convenient way to inject these values into components.
* Alternatively, the {@link org.dockbox.hartshorn.properties.PropertyRegistry} can be used directly to obtain values.
*
* <p>Parameters with literal {@link ValueProperty}, {@link ListProperty}, or {@link ObjectProperty} types will be
* resolved directly from the registry. Other types will be resolved in their raw form from the property registry, and
* will be converted by the {@link org.dockbox.hartshorn.util.introspect.convert.ConversionService}.
*
* <p>For example, the following code snippet demonstrates how to inject a property into a component:
* <pre>{@code
* @Component
* public class MyComponent {
*
* @Value(name = "sample.message", defaultValue = "Hello world!")
* private String message;
*
* @Value(name = "sample.enum", defaultValue = "FIRST")
* private SampleEnum enumValue;
* }}</pre>
*
* @since 0.7.0
*
* @author Guus Lieben
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Extends(Inject.class)
public @interface PropertyValue {

/**
* The name of the property to inject. If no property with this name is found, the {@link PropertyValue#defaultValue()} is
* used.
*
* @return the name of the property to inject
*/
String name();

/**
* The default value to use if no property with the name {@link PropertyValue#name()} is found.
*
* @return the default value to use
*/
String defaultValue() default "";
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@

package org.dockbox.hartshorn.inject.annotations;

import org.dockbox.hartshorn.inject.QualifierKey;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.dockbox.hartshorn.inject.QualifierKey;

/**
* Meta annotation to mark annotations as qualifiers. Qualifier annotations allow for the creation of
* multiple bindings for the same type, which can be distinguished by the qualifier annotation and potential
Expand All @@ -32,7 +32,7 @@
* that allows you to bind different implementations for each version:
*
* <pre>{@code
* @MetaQualifier
* @Qualifier
* @Retention(RetentionPolicy.RUNTIME)
* @Target(...)
* public @interface VersionQualifier {
Expand Down
Loading

0 comments on commit 836bb99

Please sign in to comment.