Skip to content

Commit

Permalink
Allow multiple and implement PR feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
wied03 committed Oct 25, 2024
1 parent 67de9bf commit 6130538
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,18 @@
import java.lang.annotation.Target;

/**
* Tells Prime MVC to customize message resource behavior for an action class
* Customize message resource behavior for an action class
*
* @author Brady Wied
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MessageResources {
public @interface AlternateMessageResources {
/**
* @return Prime MVC, by default, will look for messages, via the {@link org.primeframework.mvc.message.l10n.MessageProvider}
* @return By default, will look for messages, via the {@link org.primeframework.mvc.message.l10n.MessageProvider}
* interface, in an implementation specific search path (see {@link org.primeframework.mvc.message.l10n.ResourceBundleMessageProvider} for an
* example).
* If you want an additional action's messages in the search path, use this attribute.
*/
Class<?> fallback();
Class<?>[] actions();
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public class ActionConfiguration {

public final Map<HTTPMethod, ExecuteMethodConfiguration> executeMethods;

public final String fallbackMessageResourcesPath;
public final List<String> fallbackActionMessageURIs;

public final Map<String, FileUpload> fileUploadMembers;

Expand Down Expand Up @@ -125,15 +125,15 @@ public ActionConfiguration(Class<?> actionClass,
List<Method> preValidationMethods,
Field unknownParametersField,
Set<String> validContentTypes,
String fallbackMessageResourcesPath) {
List<String> fallbackActionMessageURIs) {
Objects.requireNonNull(actionClass);

this.actionClass = actionClass;
this.allowUnknownParameters = allowUnknownParameters;
this.constraintValidationMethods = constraintValidationMethods;
this.formPrepareMethods = formPrepareMethods;
this.authorizationMethods = authorizationMethods;
this.fallbackMessageResourcesPath = fallbackMessageResourcesPath;
this.fallbackActionMessageURIs = fallbackActionMessageURIs;
this.jwtAuthorizationMethods = jwtAuthorizationMethods;
this.preValidationMethods = preValidationMethods;
this.postValidationMethods = postValidationMethods;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Function;
Expand All @@ -44,7 +45,7 @@
import org.primeframework.mvc.action.ValidationMethodConfiguration;
import org.primeframework.mvc.action.annotation.Action;
import org.primeframework.mvc.action.annotation.AllowUnknownParameters;
import org.primeframework.mvc.action.annotation.MessageResources;
import org.primeframework.mvc.action.annotation.AlternateMessageResources;
import org.primeframework.mvc.action.result.annotation.ResultAnnotation;
import org.primeframework.mvc.action.result.annotation.ResultContainerAnnotation;
import org.primeframework.mvc.content.ValidContentTypes;
Expand Down Expand Up @@ -137,13 +138,13 @@ public ActionConfiguration build(Class<?> actionClass) {
Field unknownParametersField = findUnknownParametersField(actionClass);
Set<String> validContentTypes = findAllowedContentTypes(actionClass);

MessageResources messageResources = actionClass.getAnnotation(MessageResources.class);
String fallbackMessageResourcesPath = null;
if (messageResources != null) {
fallbackMessageResourcesPath = uriBuilder.build(messageResources.fallback());
}
List<String> fallbackActionMessageURIs = Optional.ofNullable(actionClass.getAnnotation(AlternateMessageResources.class))
.map(alternates -> Arrays.stream(alternates.actions())
.map(uriBuilder::build)
.toList())
.orElse(List.of());

return new ActionConfiguration(actionClass, allowKnownParameters, constraintValidationMethods, executeMethods, validationMethods, formPrepareMethods, authorizationMethods, jwtAuthorizationMethods, postValidationMethods, preParameterMethods, postParameterMethods, resultAnnotations, preParameterMembers, preRenderMethodsMap, fileUploadMembers, memberNames, securitySchemes, scopeFields, additionalConfiguration, uri, preValidationMethods, unknownParametersField, validContentTypes, fallbackMessageResourcesPath);
return new ActionConfiguration(actionClass, allowKnownParameters, constraintValidationMethods, executeMethods, validationMethods, formPrepareMethods, authorizationMethods, jwtAuthorizationMethods, postValidationMethods, preParameterMethods, postParameterMethods, resultAnnotations, preParameterMembers, preRenderMethodsMap, fileUploadMembers, memberNames, securitySchemes, scopeFields, additionalConfiguration, uri, preValidationMethods, unknownParametersField, validContentTypes, fallbackActionMessageURIs);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@
import java.util.Formatter;
import java.util.LinkedList;
import java.util.MissingResourceException;
import java.util.Objects;
import java.util.Queue;
import java.util.ResourceBundle;
import java.util.ResourceBundle.Control;

import com.google.inject.Inject;
import org.primeframework.mvc.action.ActionInvocation;
import org.primeframework.mvc.action.ActionInvocationStore;
import org.primeframework.mvc.action.annotation.AlternateMessageResources;
import org.primeframework.mvc.action.config.ActionConfiguration;
import org.primeframework.mvc.locale.LocaleProvider;
import org.slf4j.Logger;
Expand Down Expand Up @@ -121,7 +123,7 @@ protected Queue<String> determineBundles(String bundle) {

/**
* Finds the message in a resource bundle using the search method described in the class comment.
* If the action was annotated with a {@link org.primeframework.mvc.action.annotation.MessageResources} annotation
* If the action was annotated with a {@link AlternateMessageResources} annotation
* and the message was not found with the request's action, that action will be searched as well.
*
* @param actionInvocation The action invocation.
Expand All @@ -135,8 +137,12 @@ protected String findMessage(ActionInvocation actionInvocation, String key) {
}

ActionConfiguration config = actionInvocation.configuration;
if (config != null && config.fallbackMessageResourcesPath != null) {
return findMessage(config.fallbackMessageResourcesPath, key);
if (config != null) {
return config.fallbackActionMessageURIs.stream()
.map(uri -> findMessage(uri, key))
.filter(Objects::nonNull)
.findFirst()
.orElse(null);
}

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,37 +18,34 @@
import com.google.inject.Inject;
import org.example.action.nested.NestedMessageAction;
import org.primeframework.mvc.action.annotation.Action;
import org.primeframework.mvc.action.annotation.MessageResources;
import org.primeframework.mvc.action.annotation.AlternateMessageResources;
import org.primeframework.mvc.action.result.annotation.Status;
import org.primeframework.mvc.message.MessageStore;
import org.primeframework.mvc.message.MessageType;
import org.primeframework.mvc.message.SimpleMessage;
import org.primeframework.mvc.message.l10n.MessageProvider;
import org.primeframework.mvc.message.l10n.MissingMessageException;

@Action
@Status
@MessageResources(fallback = NestedMessageAction.class)
public class MessageResourcesAnnotatedAction {
@AlternateMessageResources(actions = NestedMessageAction.class)
public class AlternateMessageResourcesAnnotatedAction {
private final MessageProvider messageProvider;

private final MessageStore messageStore;

public String messageKey;

@Inject
public MessageResourcesAnnotatedAction(MessageProvider messageProvider, MessageStore messageStore) {
public AlternateMessageResourcesAnnotatedAction(MessageProvider messageProvider, MessageStore messageStore) {
this.messageProvider = messageProvider;
this.messageStore = messageStore;
}

public String get() {
try {
// this message exists in a standard path by convention - src/test/web/messages/message-resources-annotated.properties
messageStore.add(new SimpleMessage(MessageType.INFO, "normal_message", messageProvider.getMessage("normal_message")));
// this message only exists in NestedMessageAction's path - in src/test/web/messages/nested/nested-message.properties
messageStore.add(new SimpleMessage(MessageType.INFO, "nested_message", messageProvider.getMessage("nested_message")));
} catch (MissingMessageException e) {
e.printStackTrace();
throw new RuntimeException(e);
messageStore.add(new SimpleMessage(MessageType.INFO, messageKey, messageProvider.getMessage(messageKey)));
} catch (Exception e) {
messageStore.add(new SimpleMessage(MessageType.ERROR, messageKey, "not found"));
}
return "success";
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (c) 2024, Inversoft Inc., All Rights Reserved
*
* 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
*
* http://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.primeframework.mvc.message;

import org.primeframework.mvc.PrimeBaseTest;
import org.testng.annotations.Test;

public class AlternateMessageResourcesTest extends PrimeBaseTest {
@Test
public void action_has_message() {
// this message exists in a standard path by convention - src/test/web/messages/message-resources-annotated.properties
simulator.test("/alternate-message-resources-annotated")
.withParameter("messageKey", "normal_message")
.get()
.assertStatusCode(200)
.assertContainsGeneralMessageCodes(MessageType.INFO, "normal_message");
}

@Test
public void none_of_them_have_message() {
simulator.test("/alternate-message-resources-annotated")
.withParameter("messageKey", "foobar")
.get()
.assertStatusCode(200)
.assertContainsGeneralMessageCodes(MessageType.ERROR, "foobar");
}

@Test
public void other_action_has_message() {
// this message only exists in NestedMessageAction's path - in src/test/web/messages/nested/nested-message.properties
simulator.test("/alternate-message-resources-annotated")
.withParameter("messageKey", "nested_message")
.get()
.assertStatusCode(200)
.assertContainsGeneralMessageCodes(MessageType.INFO, "nested_message");
}
}

This file was deleted.

0 comments on commit 6130538

Please sign in to comment.