playframework/playframework
Injection parameters to methods of controllers
オープン
#10,873 opened on 2021/05/25
help wanted
Repository metrics
- Stars
- (12,623 個のスター)
- PR merge metrics
- (平均マージ 10d 17h) (30d で 69 merged PRs)
説明
Maybe it relates to #2983 (in some way). We use multi-tenant data isolation. Our main entity is AcHost. We need to transfer it in many controllers without copy/paste. We use action composition .
Our current solution works like that:
- Our Action (play.mvc.Action) put some params to request like that:
public OurAction extends Action<OurCustomAnnotation> {
// constructor and dependencies
@Override
public CompletionStage<Result> call(Request request) {
String clientKey = // receive client key from jwt
ACHost acHost = ourService.getACHost(clientKey).orElseThrow(() -> new RuntimeException("Not found " + clientKey));
Request newly = request.addAttr(AC_HOST_PARAM, acHost);
return delegate.call(newly);
}
}
- Then we use it in controllers
public OurController {
public CompletionStage<Result> updateCreationRestrictions(Request request) {
ACHost acHost = request.attrs().getOptional(AC_HOST_PARAM).get(); // for example call Optional.get()
// our busines logic
}
}
And it looks really bad.
It will be cool to inject our entity directly in controller like that:
public class OurController {
public CompletionStage<Result> creationRestrictionsPage(ACHost acHost) {
// our business logic
}
}
Is it possible to implement?
We have some idea about API for the feature (maybe it will be useful)
- Play Framework provides some interface (PlayInjector for example).
interface PlayInjector {
CompletionStage<Http.Request> fillRequest(Http.Request request);
}
- We implement the interface like that (spring bean for example):
@Singleton
public class AcHostInjector implements PlayInjector {
// constructor and dependencies
@Override
public Http.Request fillRequest(Http.Request request) {
String clientKey = // receive client key from jwt
ACHost acHost = ac.getACHost(clientKey).orElseThrow(() -> new RuntimeException("Not found " + clientKey));
// part from #2983
Request newly = request.addAttr(SOME_PARAM_NAME, acHost);
return delegate.call(newly);
}
}
- Play detects our PlayInjector-implementation, does some "magic" actions and we can inject our AcHost in controller like that:
public class OurController {
public CompletionStage<Result> creationRestrictionsPage(ACHost acHost) {
// our business logic
}
}
-
Declare in routes-file
GET /some/url controllers.CreationRestrictionsController.creationRestrictionsPage(acHost: AcHost) -
Use in jsRoutes
jsRoutes.controllers.CreationRestrictionsController.creationRestrictionsPage() // without additional params
It would be really useful for our team.
Kind regards