diff --git a/docs/modules/ROOT/pages/servlet/integrations/mvc.adoc b/docs/modules/ROOT/pages/servlet/integrations/mvc.adoc index 604f8219cf7..92223407e21 100644 --- a/docs/modules/ROOT/pages/servlet/integrations/mvc.adoc +++ b/docs/modules/ROOT/pages/servlet/integrations/mvc.adoc @@ -503,6 +503,126 @@ open fun findMessagesForUser(@CurrentUser customUser: CustomUser?): ModelAndView ---- ====== +Once it is a meta-annotation, parameterization is also available to you. + +For example, consider when you have a JWT as your principal and you want to say which claim to retrieve. +As a meta-annotation, you might do: + +[tabs] +====== +Java:: ++ +[source,java,role="primary"] +---- +@Target({ElementType.PARAMETER, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@AuthenticationPrincipal(expression = "claims['sub']") +public @interface CurrentUser {} +---- + +Kotlin:: ++ +[source,kotlin,role="secondary"] +---- +@Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.TYPE) +@Retention(AnnotationRetention.RUNTIME) +@MustBeDocumented +@AuthenticationPrincipal(expression = "claims['sub']") +annotation class CurrentUser +---- +====== + +which is already quite powerful. +But, it is also limited to retrieving the `sub` claim. + +To make this more flexible, first publish the `AnnotationTemplateExpressionDefaults` bean like so: + +[tabs] +====== +Java:: ++ +[source,java,role="primary"] +---- +@Bean +public AnnotationTemplateExpressionDefaults templateDefaults() { + return new AnnotationTemplateExpressionDeafults(); +} +---- + +Kotlin:: ++ +[source,kotlin,role="secondary"] +---- +@Bean +fun templateDefaults(): AnnotationTemplateExpressionDefaults { + return AnnotationTemplateExpressionDeafults() +} +---- + +Xml:: ++ +[source,xml,role="secondary"] +---- + +---- +====== + +and then you can supply a parameter to `@CurrentUser` like so: + +[tabs] +====== +Java:: ++ +[source,java,role="primary"] +---- +@Target({ElementType.PARAMETER, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@AuthenticationPrincipal(expression = "claims['{claim}']") +public @interface CurrentUser { + String claim() default 'sub'; +} +---- + +Kotlin:: ++ +[source,kotlin,role="secondary"] +---- +@Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.TYPE) +@Retention(AnnotationRetention.RUNTIME) +@MustBeDocumented +@AuthenticationPrincipal(expression = "claims['{claim}']") +annotation class CurrentUser(val claim: String = "sub") +---- +====== + +This will allow you more flexibility across your set of applications in the following way: + +[tabs] +====== +Java:: ++ +[source,java,role="primary"] +---- +@RequestMapping("/messages/inbox") +public ModelAndView findMessagesForUser(@CurrentUser("user_id") String userId) { + + // .. find messages for this user and return them ... +} +---- + +Kotlin:: ++ +[source,kotlin,role="secondary"] +---- +@RequestMapping("/messages/inbox") +open fun findMessagesForUser(@CurrentUser("user_id") userId: String?): ModelAndView { + + // .. find messages for this user and return them ... +} +---- +====== [[mvc-async]] == Spring MVC Async Integration