Play 2.6执行Action时出现无可用HTTP Context错误求助
Hey there! Let's break down why you're hitting this error and walk through practical fixes—since you're new to Play and async programming, this is a super common pitfall, so don't worry!
Common Causes & Solutions
1. You're accessing the HTTP Context outside the request thread (async callbacks)
Play's HTTP Context is tied to the thread handling the incoming request. If you run async code (like thenApply on a CompletionStage) without preserving this context, the thread switching will make the context disappear.
Fix: Use AsyncHttpExecutionContext to wrap your async logic, which keeps the HTTP Context attached to the thread.
First, inject it into your controller:
private final ListBillGroupRepository groupRepository; private final ListBillExtractDetailRepository extractRepository; private final FormFactory formFactory; private final AsyncHttpExecutionContext asyncHttpExecutionContext; // Constructor injection public YourController(ListBillGroupRepository groupRepository, ListBillExtractDetailRepository extractRepository, FormFactory formFactory, AsyncHttpExecutionContext asyncHttpExecutionContext) { this.groupRepository = groupRepository; this.extractRepository = extractRepository; this.formFactory = formFactory; this.asyncHttpExecutionContext = asyncHttpExecutionContext; }
Then use its executor for your async work:
public CompletionStage<Result> yourAction() { return groupRepository.fetchGroups() .thenApplyAsync(groups -> { // Now you can safely access context-related data here String userId = Http.Context.current().session().get("userId"); return ok(Json.toJson(groups)); }, asyncHttpExecutionContext.current()); }
2. You're trying to access Context in non-request code (e.g., Repositories)
If you're calling Http.Context.current() directly in your repositories or service classes (instead of your controller's action methods), that's a problem—these classes don't run in the request thread context by default.
Fix: Pass the data you need from the context into your services/repositories, instead of having them fetch the context themselves.
Bad practice (will throw the error):
// In your ListBillGroupRepository public CompletionStage<List<BillGroup>> getUserGroups() { String userId = Http.Context.current().session().get("userId"); // ❌ No context here return db.find(BillGroup.class).where().eq("userId", userId).findListAsync(); }
Good practice:
// In your controller action public CompletionStage<Result> yourAction() { // Grab needed data from the request/context first String userId = request().session().get("userId"); return groupRepository.getUserGroups(userId) .thenApply(groups -> ok(Json.toJson(groups))); } // Updated repository method public CompletionStage<List<BillGroup>> getUserGroups(String userId) { return db.find(BillGroup.class).where().eq("userId", userId).findListAsync(); // ✅ No context needed }
3. You're using deprecated Context access (Play 2.6+)
Http.Context.current() is deprecated in newer Play versions. Instead, you can directly inject the Http.Request into your action method to get request/session data without relying on the global context.
Example:
public CompletionStage<Result> yourAction(Http.Request request) { String userId = request.session().get("userId"); return extractRepository.getDetails(userId) .thenApply(details -> ok(Json.toJson(details))); }
Quick Recap
- Never access
Http.Context.current()in async callbacks unless you useAsyncHttpExecutionContext - Pass context-specific data from your controller to services/repositories instead of letting them fetch the context
- Prefer injecting
Http.Requestinto actions over using the global context (modern Play best practice)
内容的提问来源于stack exchange,提问作者DasYones

