Я нашел причину, по которой мое приложение ведет себя не так, как мне хотелось бы, но я не знаю, как решить проблему.Подводя итог, мое приложение имеет пользовательский обработчик ошибок, который вызывается при возникновении ошибки.Обработчик ошибок отправляет json
сообщений.Но в одном случае ошибки запуска приложения (Future
не удается) я хочу Redirect
пользователя на домашнюю страницу вместо отправки json
сообщения. Но этого не происходит, потому что пользовательский обработчик ошибок отправляет сообщение json
раньшеЯ могу отправить Redirect
от Future
recover
.
Одной из функций приложения является проверка регистрации.Пользователь нажимает на url
, у которого есть токен.При нажатии url
вызывается verifyUser
Action
.Он выполняет некоторые проверки (с использованием запросов к базе данных с использованием Future
s) и в зависимости от успеха или неудачи отправляет атрибут Redirect
с signup=success
или signup=error
(здесь не решается вопрос об ошибке, основываясь на том, существует ли что-то в базе данных)или нет).Однако, если Future
не удается (я запросил неправильное поле, которое не является частью схемы базы данных), я хочу снова Redirect
, но это не работает, так как пользовательский обработчик ошибок вызывается до recover
.Как я могу сделать свое приложение Redirect?
val result:Future[Result] = for{tokenOption:Option[UserToken] <- userTokenRepo.findOne(UserTokenKey(UUID.fromString(token))) //generator 1 - get token from database
userOption:Option[User] <- if (tokenOption.isDefined) userRepo.findOne(tokenOption.get.userKeys) else Future.successful(None) //generator2. found token, look for corresponding user to which the token belongs
modifiedUser:Option[User] <- if (userOption.isDefined) confirmSignupforUser(userOption.get) else Future.successful(None) //generator 3. found user and token. Update profile
deletedToken:Option[UserTokenKey] <- if(modifiedUser.isDefined) userTokenRepo.delete(UserTokenKey(UUID.fromString(token))) else Future.successful(None)
}
yield { //check if we have user and token and modified user here. If any is missing, return error else success
println("db query results tokenOption: "+tokenOption+", userOption: "+userOption+" : modifiedUserOption: "+modifiedUser+", deletedToken: "+deletedToken)
if(tokenOption.isDefined && userOption.isDefined && modifiedUser.isDefined && deletedToken.isDefined)
Redirect("http://localhost:9000/home"+";signup=success")//TODOM - pick from config
else
/*TODOM - when redirecting with error, can provide additional info why sign up failed*/
if(tokenOption.isEmpty)
Redirect("http://localhost:9000/home"+";signup=error")//TODOM - pick from config
else if(userOption.isEmpty)
Redirect("http://localhost:9000/home"+";signup=error")//TODOM - pick from config
else if(modifiedUser.isEmpty)
Redirect("http://localhost:9000/home"+";signup=error")//TODOM - pick from config
else //this shouldn't happen. Unexpected
Redirect("http://localhost:9000/home"+";signup=error")//TODOM - pick from config
}
result.recover { case x => {
println("Future failed in validateUserSession. Recovering. Returning Internal Server Error" + x)
//before this Redirect, the custom error handler sends json response
Redirect("http://localhost:9000/home"+";signup=error")//TODOM - pick from config
}
}
Пользовательский обработчик ошибок
class CustomHttpErrorHandler extends HttpErrorHandler {
def onClientError(request: RequestHeader, statusCode: Int, message: String) = {
println("client error: request "+request+", statusCode: "+statusCode+", message:"+message)
Future.successful(
Status(statusCode)(Json.toJson(JsonResultError(message)))
)
}
def onServerError(request: RequestHeader, exception: Throwable) = {
println("server error: request: "+request+", exception: "+exception.getMessage)
Future.successful(
InternalServerError(Json.toJson(JsonResultError(exception.getMessage)))
)
}
}
Я могу проверить isse, когда вижу две отладки (одна из пользовательского обработчика ошибок и другая из восстановления)
server error: request: GET /ws/users/signup/312c9eaf-f27b-43c7-8dac-445a628c3be8, exception: bucket_id is not a column defined in this metadata
Future failed in validateUserSession. Recovering. Returning Internal Server Errorjava.lang.IllegalArgumentException: bucket_id is not a column defined in this metadata
Я мог бы попытаться проверить, основываясь на исключении, полученном в пользовательском обработчике ошибок, но я думаю, что оно слишком универсальное и не может быть хорошим подходом к проектированию.