2016-04-22 6 views
0

Ich verwende Play Framework, um einen Server zu entwickeln. In einigen meiner Methoden muss ich einige vorhergehende Maßnahmen durchführen (im Grunde Eingangsüberprüfung), also denke ich, der beste Weg, dies zu tun ist Action Composition.Wiederholen Sie die gleiche Aktion, wenn Sie in Play Framework Kompositionsaktionen ausführen

kann ich mehrere Anmerkungen verwenden, ohne Problem

@Action1 // <---------------------------------------- This action is executed 
@Action2(value = "someValue") // <------------------- This action is executed 
public CompletionStage<Result> doSomething() { 
    ... 
} 

aber sobald ich versuche, eine dieser Aktionen zu wiederholen, dass konkrete Maßnahmen nicht ausgeführt:

@Action1 // <---------------------------------------- This action is executed 
@Action2(value = "someValue") // <------------------- This action is not executed 
@Action2(value = "someOtherValue") // <-------------- This action is not executed 
public CompletionStage<Result> doSomething() { 
    ... 
} 

Meine Action1 Anmerkung sieht aus wie die VerboseAnnotation der Play Framework example also ich denke nicht, dass es wert ist, es hier zu schreiben. Da meine Action2 Anmerkung wiederholt werden kann, habe ich eine RepeatableAction2 Anmerkung wie folgt erklärt:

@With(Action2Impl.class) 
@Target({ElementType.TYPE, ElementType.METHOD}) 
@Retention(RetentionPolicy.RUNTIME) 
@Repeatable(value = RepeatableAction2.class) 
public @interface Action2 { 
    String value(); 
} 

Das Verfahren ist korrekt kommentiert:

@Target({ElementType.TYPE, ElementType.METHOD}) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface RepeatableAction2 { 
    Action2[] value() default {}; 
} 

und Action2 sieht wie folgt aus. Als ich hinzufügen:

for (Method m : Application.class.getDeclaredMethods()) { 
    RequiredJsonValues reqs = m.getAnnotation(RequiredJsonValues.class); 
    for (RequiredJsonValue req : reqs.value()) { 
     System.out.println("Method: " + m + " annotation: " + req); 
    } 
} 

zu Beginn des Verfahrens erhalte ich

Method: public java.util.concurrent.CompletionStage controllers.SomeController.doSomething() annotation: @util.Action2(value=someValue) 
Method: public java.util.concurrent.CompletionStage controllers.SomeController.doSomething() annotation: @util.Action2(value=someOtherValue) 

Also, was mache ich falsch? Gibt es eine andere Möglichkeit, dieselbe Aktion mehrmals mit unterschiedlichen Werten zu verketten?

Antwort

0

Schließlich habe ich es arbeiten

Wie erklärt in here die Java 8 Compiler muss nicht die RepeatableAction2 geschrieben werden, aber es fügt es bei der Kompilierung, so brauchte ich eine Implementierung für diese Anmerkung hinzuzufügen:

@With(RepeatableAction2Impl.class) 
@Target({ElementType.TYPE, ElementType.METHOD}) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface RepeatableAction2 { 
    Action2[] value() default {}; 
} 

und bei der Umsetzung alles, was ich die Aktionen manuell Kette:

public class RepeatableAction2Impl extends Action<RepeatableAction2> { 

    @Override 
    public CompletionStage<Result> call(Http.Context ctx) { 
     if (configuration.value().length > 0) { 
      int actions = configuration.value().length; 
      List<Action<Action2>> actionList = new ArrayList<>(); 
      // Create actions 
      for (int i = 0; i < actions; i++) { 
       Action2Impl action2Impl = new Action2Impl(); 
       action2Impl.configuration = configuration.value()[i]; 
       actionList.add(action2Impl); 
      } 
      // Chaining 
      actionList.get(actions - 1).delegate = delegate; 
      for (int i = 0; i < actions - 1; i++) { 
       actionList.get(i).delegate = actionList.get(i + 1); 
      } 
      // Delegate the work to actions 
      return actionList.get(0).call(ctx); 
     } else { 
      return delegate.call(ctx); 
     } 
    } 

} 

Obwohl es sich um eine Arbeitslösung ist stil es ist Ich finde es ein bisschen hässlich für mich. Gibt es einen anderen Weg, der mir fehlt?

Verwandte Themen