Skip to content

Commit

Permalink
order const. param to ResourceBundleMessageSource
Browse files Browse the repository at this point in the history
This pull-request adds a `order` constructor parameter to `ResourceBundleMessageSource`. it is used to override the `Ordered::getOrder`. Currently, users which defined a MessageSource with cannot customize the `order`

```
    @factory
    static class MessageSourceFactory {

        @singleton
        MessageSource createMessageSource() {
            return new MessageSource() {
                private final MessageSource delegate = new ResourceBundleMessageSource("i18n.messages");

                @OverRide
                public @nonnull Optional<String> getRawMessage(@nonnull String code, @nonnull MessageContext context) {
                    return delegate.getRawMessage(code, context);
                }

                @OverRide
                public @nonnull String interpolate(@nonnull String template, @nonnull MessageContext context) {
                    return delegate.interpolate(template, context);
                }

                @OverRide
                public int getOrder() {
                    return HIGHEST_PRECEDENCE;
                }
            };
        }
    }
```
  • Loading branch information
sdelamo committed Jan 31, 2025
1 parent 85fa094 commit bbdc1e8
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 6 deletions.
5 changes: 4 additions & 1 deletion context/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ dependencies {
testImplementation project(":core-reactive")
testImplementation project(":inject-java-test")
testImplementation libs.logback.classic

testImplementation(libs.micronaut.test.junit5) {
exclude group: 'io.micronaut'
}
testImplementation(libs.junit.jupiter.api)
}

spotless {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package io.micronaut.runtime.context;

import io.micronaut.context.MessageSource;
import io.micronaut.context.StaticMessageSource;
import io.micronaut.context.annotation.Factory;
import io.micronaut.context.annotation.Property;
import io.micronaut.context.annotation.Requires;
import io.micronaut.context.i18n.ResourceBundleMessageSource;
import io.micronaut.core.annotation.NonNull;
import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
import jakarta.inject.Singleton;
import org.junit.jupiter.api.Test;

import java.util.Locale;
import java.util.Optional;

import static io.micronaut.core.order.Ordered.HIGHEST_PRECEDENCE;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

@Property(name = "spec.name", value = "CompositeMessageSourceTest")
@MicronautTest(startApplication = false)
class CompositeMessageSourceTest {
private static final Locale SPANISH = new Locale("es", "ES");

@Test
void messageSourcesAreSorted(MessageSource messageSource) {
String code = "jakarta.validation.constraints.Positive.message";
Optional<String> messageOptional = messageSource.getMessage(code, Locale.ENGLISH);
assertTrue(messageOptional.isPresent());
assertEquals("Must be positive", messageOptional.get());
messageOptional = messageSource.getMessage(code, SPANISH);
assertTrue(messageOptional.isPresent());
assertEquals("Debe ser positivo", messageOptional.get());
}

@Requires(property = "spec.name", value = "CompositeMessageSourceTest")
@Factory
static class MessageSourceFactory {
@Singleton
MessageSource createMessageSource() {
return new ResourceBundleMessageSource("i18n.messages", HIGHEST_PRECEDENCE);
}
}

@Requires(property = "spec.name", value = "CompositeMessageSourceTest")
@Singleton
static class DefaultMessages extends StaticMessageSource {
DefaultMessages() {
addMessage("jakarta.validation.constraints.Positive.message", "must be greater than 0");
}
}
}
1 change: 1 addition & 0 deletions context/src/test/resources/i18n/messages.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
jakarta.validation.constraints.Positive.message=Must be positive
2 changes: 2 additions & 0 deletions context/src/test/resources/i18n/messages_es.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
jakarta.validation.constraints.Positive.message=Debe ser positivo

Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package io.micronaut.context.i18n;

import io.micronaut.context.AbstractMessageSource;
import io.micronaut.core.order.Ordered;
import io.micronaut.core.util.ArgumentUtils;
import io.micronaut.core.util.clhm.ConcurrentLinkedHashMap;
import org.slf4j.Logger;
Expand All @@ -35,12 +36,14 @@
public class ResourceBundleMessageSource extends AbstractMessageSource {

private static final Logger LOG = LoggerFactory.getLogger(ResourceBundleMessageSource.class);
private static final int DEFAULT_ORDER = 0;
private final String baseName;
private final Map<MessageKey, Optional<String>> messageCache =
buildMessageCache();
private final Map<MessageKey, Optional<ResourceBundle>> bundleCache =
buildBundleCache();
private final @Nullable ResourceBundle defaultBundle;
private final int order;

/**
* Default constructor.
Expand All @@ -50,12 +53,32 @@ public ResourceBundleMessageSource(@NonNull String baseName) {
this(baseName, null);
}

/**
* Default constructor.
* @param baseName The base name of the message bundle
* @param order used for the implementation of the {@link Ordered#getOrder()} method
*/
public ResourceBundleMessageSource(@NonNull String baseName, int order) {
this(baseName, null, order);
}

/**
* Default constructor.
* @param baseName The base name of the message bundle
* @param defaultLocale The default locale to use if no message is found for the given locale
*/
public ResourceBundleMessageSource(@NonNull String baseName, @Nullable Locale defaultLocale) {
this(baseName, defaultLocale, DEFAULT_ORDER);
}

/**
* Default constructor.
* @param baseName The base name of the message bundle
* @param defaultLocale The default locale to use if no message is found for the given locale
* @param order used for the implementation of the {@link Ordered#getOrder()} method
*/
public ResourceBundleMessageSource(@NonNull String baseName, @Nullable Locale defaultLocale, int order) {
this.order = order;
ArgumentUtils.requireNonNull("baseName", baseName);
this.baseName = baseName;
ResourceBundle defaultBundle;
Expand All @@ -74,6 +97,11 @@ public ResourceBundleMessageSource(@NonNull String baseName, @Nullable Locale de
this.defaultBundle = defaultBundle;
}

@Override
public int getOrder() {
return order;
}

@NonNull
@Override
@SuppressWarnings("java:S2789") // performance optimization
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ package io.micronaut.docs.i18n
import io.micronaut.context.MessageSource
import io.micronaut.context.annotation.Factory
import io.micronaut.context.i18n.ResourceBundleMessageSource
import io.micronaut.core.order.Ordered
import jakarta.inject.Singleton

@Factory
class MessageSourceFactory {
@Singleton
MessageSource createMessageSource() {
new ResourceBundleMessageSource("io.micronaut.docs.i18n.messages")
new ResourceBundleMessageSource("io.micronaut.docs.i18n.messages", Ordered.HIGHEST_PRECEDENCE)
}
}
//end::clazz[]
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ package io.micronaut.docs.i18n
import io.micronaut.context.MessageSource
import io.micronaut.context.annotation.Factory
import io.micronaut.context.i18n.ResourceBundleMessageSource
import io.micronaut.core.order.Ordered
import jakarta.inject.Singleton

@Factory
internal class MessageSourceFactory {
@Singleton
fun createMessageSource(): MessageSource = ResourceBundleMessageSource("io.micronaut.docs.i18n.messages")
fun createMessageSource(): MessageSource =
ResourceBundleMessageSource("io.micronaut.docs.i18n.messages", Ordered.HIGHEST_PRECEDENCE)
}
//end::clazz[]
//end::clazz[]
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
import io.micronaut.context.MessageSource;
import io.micronaut.context.annotation.Factory;
import io.micronaut.context.i18n.ResourceBundleMessageSource;
import io.micronaut.core.order.Ordered;
import jakarta.inject.Singleton;

@Factory
class MessageSourceFactory {
@Singleton
MessageSource createMessageSource() {
return new ResourceBundleMessageSource("io.micronaut.docs.i18n.messages");
return new ResourceBundleMessageSource("io.micronaut.docs.i18n.messages", Ordered.HIGHEST_PRECEDENCE);
}
}
//end::clazz[]
//end::clazz[]

0 comments on commit bbdc1e8

Please sign in to comment.