@@ -503,6 +503,119 @@ open fun findMessagesForUser(@CurrentUser customUser: CustomUser?): ModelAndView
503
503
----
504
504
======
505
505
506
+ Once it is a meta-annotation, parameterization is also available to you.
507
+
508
+ For example, consider when you have a JWT as your principal and you want to say which claim to retrieve.
509
+ As a meta-annotation, you might do:
510
+
511
+ [tabs]
512
+ ======
513
+ Java::
514
+ +
515
+ [source,java,role="primary"]
516
+ ----
517
+ @Target({ElementType.PARAMETER, ElementType.TYPE})
518
+ @Retention(RetentionPolicy.RUNTIME)
519
+ @Documented
520
+ @AuthenticationPrincipal(expression = "claims['sub']")
521
+ public @interface CurrentUser {}
522
+ ----
523
+
524
+ Kotlin::
525
+ +
526
+ [source,kotlin,role="secondary"]
527
+ ----
528
+ @Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.TYPE)
529
+ @Retention(AnnotationRetention.RUNTIME)
530
+ @MustBeDocumented
531
+ @AuthenticationPrincipal(expression = "claims['sub']")
532
+ annotation class CurrentUser
533
+ ----
534
+ ======
535
+
536
+ which is already quite powerful.
537
+ But, it is also limited to retrieving the `sub` claim.
538
+
539
+ To make this more flexible, first publish the `AnnotationTemplateExpressionDefaults` bean like so:
540
+
541
+ [tabs]
542
+ ======
543
+ Java::
544
+ +
545
+ [source,java,role="primary"]
546
+ ----
547
+ @Bean
548
+ public AnnotationTemplateExpressionDefaults templateDefaults() {
549
+ return new AnnotationTemplateExpressionDeafults();
550
+ }
551
+ ----
552
+
553
+ Kotlin::
554
+ +
555
+ [source,kotlin,role="secondary"]
556
+ ----
557
+ @Bean
558
+ fun templateDefaults(): AnnotationTemplateExpressionDefaults {
559
+ return AnnotationTemplateExpressionDeafults()
560
+ }
561
+ ----
562
+ ======
563
+
564
+ and then you can supply a parameter to `@CurrentUser` like so:
565
+
566
+ [tabs]
567
+ ======
568
+ Java::
569
+ +
570
+ [source,java,role="primary"]
571
+ ----
572
+ @Target({ElementType.PARAMETER, ElementType.TYPE})
573
+ @Retention(RetentionPolicy.RUNTIME)
574
+ @Documented
575
+ @AuthenticationPrincipal(expression = "claims['{claim}']")
576
+ public @interface CurrentUser {
577
+ String claim() default 'sub';
578
+ }
579
+ ----
580
+
581
+ Kotlin::
582
+ +
583
+ [source,kotlin,role="secondary"]
584
+ ----
585
+ @Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.TYPE)
586
+ @Retention(AnnotationRetention.RUNTIME)
587
+ @MustBeDocumented
588
+ @AuthenticationPrincipal(expression = "claims['{claim}']")
589
+ annotation class CurrentUser(val claim: String = "sub")
590
+ ----
591
+ ======
592
+
593
+ This will allow you more flexibility across your set of applications in the following way:
594
+
595
+ [tabs]
596
+ ======
597
+ Java::
598
+ +
599
+ [source,java,role="primary"]
600
+ ----
601
+ @RequestMapping("/messages/inbox")
602
+ public ModelAndView findMessagesForUser(@CurrentUser("user_id") String userId) {
603
+
604
+ // .. find messages for this user and return them ...
605
+ }
606
+ ----
607
+
608
+ Kotlin::
609
+ +
610
+ [source,kotlin,role="secondary"]
611
+ ----
612
+ @RequestMapping("/messages/inbox")
613
+ open fun findMessagesForUser(@CurrentUser("user_id") userId: String?): ModelAndView {
614
+
615
+ // .. find messages for this user and return them ...
616
+ }
617
+ ----
618
+ ======
506
619
507
620
[[mvc-async]]
508
621
== Spring MVC Async Integration
0 commit comments