I want to use Resilience4J's retry logic in my call api function, but I got error below, how to fix this?
val reversalRequestResult = Decorators.ofSupplier {
() => {
determinationService.getTax(getTaxRequest, runID) match {
case Success(getTaxResponse) =>
if (vertexComplianceExceptionHandler.containsGrpcResponseExceptions(getTaxResponse)) {
LOGGER.error("Response has a failure/unsuccessful status for a invoice request")
Some(vertexComplianceExceptionHandler.handleGrpcResponseExceptions(getTaxResponse))
//got error: type mismatch required: Supplier[T_], found: Some[(String, String)]
} else {
// Inserting records into tables
eventInfoCase.record_status = VertexComplianceConstant.RECORD_STATUS_SUCCESS
None
//got error: type mismatch required: Supplier[T_], found: None type
}
case Failure(exception) =>
Some(vertexComplianceExceptionHandler.handleHardGrpcExceptions(exception))
//got error: type mismatch required: Supplier[T_], found: Some[(String, String)]
}
}
}.withRetry(vertexGetTaxResilience.getDefaultRetryInstance())
//error: required: Supplier[T_], found: Function0[Optio(String, String)]
.get()
Related
I am new to Scala and to akka i am trying to publish endpoint. Following compilation error is occurring.
found: akka.http.scaladsl.server.StandardRoute
[error] required: scala.util.Try[Option[com.activegrid.entities.AuthSettings]] => (akka.http.scaladsl.server.RequestContext => scala.concurrent.Future[akka.http.scaladsl.server.RouteResult])
Case class
case class AuthSettings(authType:String,authLevel:String,scope:String);
Enpoint
pathPrefix("config") {
path("settings"/"auth") {
post {
entity(as[AuthSettings]) { authSettings =>
val save: Future[AuthSettings] = persistance.persistAuthSettings(authSettings)
onComplete(save) {
complete("To insert app settings")
}
}
}
}
persistAuthSettings definition
def persistAuthSettings(authSettings: AuthSettings) : Future[AuthSettings] = Future {
//Neo4j Operations
authSettings;
}
What is going wrong in my code?
onComplete extracts the value from the future, and requires a function which operates on this value:
onComplete(save) { appSettings =>
complete("To insert app settings")
}
Give then following code:
AccountsDAO.scala:
def find(id: EntityId): Future[Option[Account]] =
collection.find(Json.obj(Fields.Id -> id)).one[Account]
And AccountService.scala:
def getAccount(id: Option[Credentials]) = id.flatMap {
accountId => accountDAO.find(accountId.accountId) //Throws an error
}
The commented line above throws this error:
type mismatch; found : scala.concurrent.Future[Option[models.Account]] required: Option[?]
What am I missing? Why does flattop return an Option[?]. If I change the return type of the getAccount method as:
def getAccount(id: Option[Credentials]): Future[Option[Account]] = id.flatMap {
accountId => accountDAO.find(accountId.accountId) //Still throws an error
}
I get the error below:
type mismatch; found : Option[Nothing] required: scala.concurrent.Future[Option[models.Account]]
What is going on? What am I missing?
Thanks in advance.
Edit : Here's the code in the controller and what I'm trying to do:
def auth = Action.async(parse.json) { request =>
{
val authRequest = request.body.validate[AuthRequest]
authRequest.fold(
errors => Future(BadRequest),
auth => {
//First verify username and password
val authRequestResult = for {
validCredentials <- credentialsManager.checkEmailPassword(auth.email, auth.password)
account:Option[Account] <- accountManager.getAccount(validCredentials)
session:Session <- sessionManager.createSession(account.get.id, account.get.roles)
touchedSession <- sessionManager.TouchSession(session.id)
} yield AuthResponse(session.id, session.token, account.get.id, account.get.roles)
authRequestResult map {
case res: AuthResponse => Ok(Json.toJson(res))
case _ => NotFound
}
})
}
}
The checkEmailPassword method above returns a Future[Option]:
def checkEmailPassword(email: String, password: String) =
for {
credentials <- credentialsDAO.find(AuthType.EmailPassword, email)
validPassword <- BCrypt.checkFuture(password, credentials)
} yield (credentials)
And credentialsDAO.find:
def find(authType: AuthType.Value, authAccountId: String) =
collection.find(
Json.obj(Fields.AuthType → authType,
Fields.AuthAccountId → authAccountId)).one[Credentials].recover(wrapLastError)
So when checkEmailPassword returns an Option[Credentials] object, is it okay to assume the for comprehension in the controller will not execute any further if it returns a None? Then I could just say something like account:Option[Account] <- accountManager.getAccount(validCredentials.get.id). Is there a better way to structure/organize this code? Any patterns that I can follow/use?
I have one compilation error that I cannot solved yet. It's about an action adding a new patient into mongo if he is not already in the database. First the model :
case class PatientData(id : String)
object PatientData {
implicit val PatientDataFormat = Json.format[PatientData]
}
The function searching the patient in mongo :
def findPatientById(mode : String, id : String) : Future[Option[PatientData]] = {
val collection = getPatientCollection(mode)
collection.find(Json.obj("id" -> id)).one[PatientData]
}
The Play action :
def create(patientId: String) = Action.async(parse.json) { request =>
val token = "dummy"
isAuthorized(token) match { // always return Some(thing)
case None => Future.successful(Unauthorized("Invalid token " + token))
case Some(_) =>
request.body.validate[PatientData] map {
patientData =>
findPatientById(mode,patientId) map { finded =>
finded match {
case Some(_) => Future.successful(NotAcceptable("The patient is already exist."))
case None =>
Logger.info("Create the patient .. ")
Future.successful(Created)
}
}
} getOrElse {
Future.successful(BadRequest)
}
}
I know that I can solve this problem using a call to Await.result in the function findPatientById but I want avoid this solution and let the Future doing his job. The problem is that I get a compilation error :
[error] /home/afk/git/bioserenity/bioserenity-backend/app/controllers/MedataController.scala:90: type mismatch;
[error] found : scala.concurrent.Future[Object]
[error] required: scala.concurrent.Future[play.api.mvc.Result]
[error] } getOrElse {
[error] ^
[error] one error found
[error] (compile:compileIncremental) Compilation failed
Anyone have an idea to solve this issue ?
You should probably try to use
findPatientById(mode,patientId) flatMap { ...
instead of original line. Here, the map call is replaced by flatMap so that the instance returned by that block of code is Future[Something] rather than Future[Future[Something]].
UserGetResponse and GeneralResponse are sublclasses of BaseResponse, which is as follows:
abstract class BaseResponse()
And the function I use to retrieve users is as follows:
def userGet(userId: Int)(implicit ec: ExecutionContext): Future[BaseResponse] = Future {
val response = users.get(userId) map { user =>
val userRes = new UserResponse(user.id, user.firstname, user.lastname, user.organisationid, user.email, user.password, user.usertype)
new UserGetResponse(1, "Successful retrieved the user.", userRes)
} getOrElse {
GeneralResponse(0, s"Error retrieving user. User does not exist.")
}
}
where users is another class with methods get, insert etc. defined. I am getting the following compilation error:
type mismatch;
[error] found : Unit
[error] required: package.name.BaseResponse
[error] }
What am I doing wrong?
The closure inside the Future is not returning anything, so the compiler infers that it's return type is Unit, and complains because it should be BaseResponse.
Removing val response = from the beginning of the function (or adding response before the end) should fix it.
I am having issues trying to write a method to return a Future[Map[Int,Long]].
I was in some iteration of this getting back a Future[Future[..]]. So I tried the flatMap identity.
Please see below for my code and error messages I am getting now. I am not sure what is going on here at the moment.
def aggregate(permissions: Vector[Permission]): Map[Int, Long]
def calculate(roleProfile: RoleProfile): Future[Map[Int, Long]] = {
val roleIds = roleProfile.roles.map(r => r.id)
db.run(permissionDao.getByRoles(roleIds.toList)).map {
permissions =>
aggregate(permissions)
}
}
def generate(roleGroupId: Int): Future[Map[Int, Long]] = {
for {
roleGroup <- roleGroupService.getById(roleGroupId)
roles <- roleGroupService.getRolesByGroupId(roleGroupId)
} yield {
calculate(RoleProfile(roleGroup.get.id, roles.toSet)) //flatMap identity
}
}
I am getting an error message for method 'calculate':
type mismatch;
[error] found : scala.concurrent.Future[Map[Int,Long]]
[error] required: Map[Int,Long]
[error] calculate(RoleProfile(roleGroup.get.id, roles.toSet)) //flatMap identity
Now if remove the comments for 'flatMap identity' I get this error:
type mismatch;
[error] found : Map[Int,Long] => Map[Int,Long]
[error] required: Map[Int,Long] => scala.concurrent.Future[?]
[error] calculate(RoleProfile(roleGroup.get.id, roles.toSet)) flatMap identity
I'm very confused, how can I get this to return Future[Map[Int, Long]].
And more importantly, what is going on here that I just don't seem to understand. Please break things down if you can much appreciated.
Since calculate, like your getById etc calls, returns a Future, you should be able to simply add it into the main part of the for-comprehension, eg:
def generate(roleGroupId: Int): Future[Map[Int, Long]] = {
for {
roleGroup <- roleGroupService.getById(roleGroupId)
roles <- roleGroupService.getRolesByGroupId(roleGroupId)
profile <- calculate(RoleProfile(roleGroup.get.id, roles.toSet))
} yield { profile }
}