How to resolve Future[Any] in akka-http
I've created a route:
post {
path("validate" / Segment / Segment / Segment) { (userId, listId, prefix) =>
parameters('filter.?) { filter =>
def result = (
phoneValidationActor ? ValidateUserList(userId.toInt, listId.toInt, prefix.toUpperCase, filter)
)
complete(result)
}
}
}
And an actor
class PhoneNumberActor extends Actor with ActorLogging {
import PhoneNumberActor._
def receive: Receive = {
case ValidateUserList(userId, listId, prefix, filter) =>
sender() ! validateUserList(userId, listId, prefix, filter)
}
}
And a receive function for actor
def validateUserList(user_id: Int, list_id: Int, prefix: String, filter: Option[String]): Future[Seq[PhoneNumber]] = {
val prefixTrim = prefix.trim
val listContact = new ListContactRepository
listContact.getAllContacts(user_id, list_id).map { lines =>
lines.map { line =>
validateNumber(line.phone, prefixTrim)
}
}
}
In route, result is parsed as Future[Any]
instead of Future[Seq[PhoneNumber]]
Need help to resolve this issue
scala akka akka-http
add a comment |
I've created a route:
post {
path("validate" / Segment / Segment / Segment) { (userId, listId, prefix) =>
parameters('filter.?) { filter =>
def result = (
phoneValidationActor ? ValidateUserList(userId.toInt, listId.toInt, prefix.toUpperCase, filter)
)
complete(result)
}
}
}
And an actor
class PhoneNumberActor extends Actor with ActorLogging {
import PhoneNumberActor._
def receive: Receive = {
case ValidateUserList(userId, listId, prefix, filter) =>
sender() ! validateUserList(userId, listId, prefix, filter)
}
}
And a receive function for actor
def validateUserList(user_id: Int, list_id: Int, prefix: String, filter: Option[String]): Future[Seq[PhoneNumber]] = {
val prefixTrim = prefix.trim
val listContact = new ListContactRepository
listContact.getAllContacts(user_id, list_id).map { lines =>
lines.map { line =>
validateNumber(line.phone, prefixTrim)
}
}
}
In route, result is parsed as Future[Any]
instead of Future[Seq[PhoneNumber]]
Need help to resolve this issue
scala akka akka-http
add a comment |
I've created a route:
post {
path("validate" / Segment / Segment / Segment) { (userId, listId, prefix) =>
parameters('filter.?) { filter =>
def result = (
phoneValidationActor ? ValidateUserList(userId.toInt, listId.toInt, prefix.toUpperCase, filter)
)
complete(result)
}
}
}
And an actor
class PhoneNumberActor extends Actor with ActorLogging {
import PhoneNumberActor._
def receive: Receive = {
case ValidateUserList(userId, listId, prefix, filter) =>
sender() ! validateUserList(userId, listId, prefix, filter)
}
}
And a receive function for actor
def validateUserList(user_id: Int, list_id: Int, prefix: String, filter: Option[String]): Future[Seq[PhoneNumber]] = {
val prefixTrim = prefix.trim
val listContact = new ListContactRepository
listContact.getAllContacts(user_id, list_id).map { lines =>
lines.map { line =>
validateNumber(line.phone, prefixTrim)
}
}
}
In route, result is parsed as Future[Any]
instead of Future[Seq[PhoneNumber]]
Need help to resolve this issue
scala akka akka-http
I've created a route:
post {
path("validate" / Segment / Segment / Segment) { (userId, listId, prefix) =>
parameters('filter.?) { filter =>
def result = (
phoneValidationActor ? ValidateUserList(userId.toInt, listId.toInt, prefix.toUpperCase, filter)
)
complete(result)
}
}
}
And an actor
class PhoneNumberActor extends Actor with ActorLogging {
import PhoneNumberActor._
def receive: Receive = {
case ValidateUserList(userId, listId, prefix, filter) =>
sender() ! validateUserList(userId, listId, prefix, filter)
}
}
And a receive function for actor
def validateUserList(user_id: Int, list_id: Int, prefix: String, filter: Option[String]): Future[Seq[PhoneNumber]] = {
val prefixTrim = prefix.trim
val listContact = new ListContactRepository
listContact.getAllContacts(user_id, list_id).map { lines =>
lines.map { line =>
validateNumber(line.phone, prefixTrim)
}
}
}
In route, result is parsed as Future[Any]
instead of Future[Seq[PhoneNumber]]
Need help to resolve this issue
scala akka akka-http
scala akka akka-http
edited Dec 29 '18 at 16:59
Ivan Stanislavciuc
75849
75849
asked Dec 29 '18 at 13:30
Sujit BaniyaSujit Baniya
433417
433417
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
You need to call mapTo
on result of the ask call.
(phoneValidationActor ? ValidateUserList(userId.toInt, listId.toInt, prefix.toUpperCase, filter))).mapTo[Seq[PhoneNumber]]
and handle future inside the actor to avoid ClassCastException
class PhoneNumberActor extends Actor with ActorLogging {
import PhoneNumberActor._
def receive: Receive = {
case ValidateUserList(userId, listId, prefix, filter) =>
val theSender = sender() //do not call this method in callback function onSuccess as it breaks actor principles and can send message to a wrong sender
validateUserList(userId, listId, prefix, filter).onSuccess { phoneNumbers =>
theSender ! phoneNumbers
}
}
}
I tried to dodef result = (phoneValidationActor ? ValidateUserList(userId.toInt, listId.toInt, prefix.toUpperCase, filter)).mapTo[Seq[PhoneNumber]]
But receivedjava.lang.ClassCastException: Cannot cast scala.concurrent.impl.Promise$DefaultPromise to scala.collection.Seq
I'm wondering validateUserList already resulting in asFuture[Seq[PhoneNumber]]
. though it's not working
– Sujit Baniya
Dec 29 '18 at 13:56
The reason is that yourvalidateNumber
function returns are future. You need to returnSeq[PhoneNumber]
– Ivan Stanislavciuc
Dec 29 '18 at 13:57
Future[Seq[PhoneNumber]]
is returned by mongodb for its records. So if there's effective solution for this
– Sujit Baniya
Dec 29 '18 at 13:59
@SujitBaniya use map on Future or pipe pattern to resolve handling of the future inside of an actor.
– Ivan Stanislavciuc
Dec 29 '18 at 14:00
@SujitBaniya I'll update the answer with an example as soon as I get to my laptop
– Ivan Stanislavciuc
Dec 29 '18 at 14:01
|
show 6 more comments
Just like @Ivan Stanislavciuc said, you need to add the mapTo
method to safely cast a Future to an expected type which in this case is [Seq[PhoneNumber]]
.
for your route I'd update it to something like such:
post {
path("validate" / Segment / Segment / Segment) { (userId, listId, prefix) =>
parameters('filter.?) { filter =>
val result =
(phoneValidationActor ? ValidateUserList(userId.toInt, listId.toInt, prefix.toUpperCase, filter)).mapTo[Seq[PhoneNumber]]
onSuccess(result) { maybeResult =>
complete(maybeResult)
}
}
}
}
And if you'd like to handle a Success and Failure you can use onComplete
in place of onSuccess
and have something like:
onComplete(result) {
case scala.util.Success(res) => complete(res)
case scala.util.Failure(ex) => complete(StatusCodes.BadRequest, ex)}
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53970016%2fhow-to-resolve-futureany-in-akka-http%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
You need to call mapTo
on result of the ask call.
(phoneValidationActor ? ValidateUserList(userId.toInt, listId.toInt, prefix.toUpperCase, filter))).mapTo[Seq[PhoneNumber]]
and handle future inside the actor to avoid ClassCastException
class PhoneNumberActor extends Actor with ActorLogging {
import PhoneNumberActor._
def receive: Receive = {
case ValidateUserList(userId, listId, prefix, filter) =>
val theSender = sender() //do not call this method in callback function onSuccess as it breaks actor principles and can send message to a wrong sender
validateUserList(userId, listId, prefix, filter).onSuccess { phoneNumbers =>
theSender ! phoneNumbers
}
}
}
I tried to dodef result = (phoneValidationActor ? ValidateUserList(userId.toInt, listId.toInt, prefix.toUpperCase, filter)).mapTo[Seq[PhoneNumber]]
But receivedjava.lang.ClassCastException: Cannot cast scala.concurrent.impl.Promise$DefaultPromise to scala.collection.Seq
I'm wondering validateUserList already resulting in asFuture[Seq[PhoneNumber]]
. though it's not working
– Sujit Baniya
Dec 29 '18 at 13:56
The reason is that yourvalidateNumber
function returns are future. You need to returnSeq[PhoneNumber]
– Ivan Stanislavciuc
Dec 29 '18 at 13:57
Future[Seq[PhoneNumber]]
is returned by mongodb for its records. So if there's effective solution for this
– Sujit Baniya
Dec 29 '18 at 13:59
@SujitBaniya use map on Future or pipe pattern to resolve handling of the future inside of an actor.
– Ivan Stanislavciuc
Dec 29 '18 at 14:00
@SujitBaniya I'll update the answer with an example as soon as I get to my laptop
– Ivan Stanislavciuc
Dec 29 '18 at 14:01
|
show 6 more comments
You need to call mapTo
on result of the ask call.
(phoneValidationActor ? ValidateUserList(userId.toInt, listId.toInt, prefix.toUpperCase, filter))).mapTo[Seq[PhoneNumber]]
and handle future inside the actor to avoid ClassCastException
class PhoneNumberActor extends Actor with ActorLogging {
import PhoneNumberActor._
def receive: Receive = {
case ValidateUserList(userId, listId, prefix, filter) =>
val theSender = sender() //do not call this method in callback function onSuccess as it breaks actor principles and can send message to a wrong sender
validateUserList(userId, listId, prefix, filter).onSuccess { phoneNumbers =>
theSender ! phoneNumbers
}
}
}
I tried to dodef result = (phoneValidationActor ? ValidateUserList(userId.toInt, listId.toInt, prefix.toUpperCase, filter)).mapTo[Seq[PhoneNumber]]
But receivedjava.lang.ClassCastException: Cannot cast scala.concurrent.impl.Promise$DefaultPromise to scala.collection.Seq
I'm wondering validateUserList already resulting in asFuture[Seq[PhoneNumber]]
. though it's not working
– Sujit Baniya
Dec 29 '18 at 13:56
The reason is that yourvalidateNumber
function returns are future. You need to returnSeq[PhoneNumber]
– Ivan Stanislavciuc
Dec 29 '18 at 13:57
Future[Seq[PhoneNumber]]
is returned by mongodb for its records. So if there's effective solution for this
– Sujit Baniya
Dec 29 '18 at 13:59
@SujitBaniya use map on Future or pipe pattern to resolve handling of the future inside of an actor.
– Ivan Stanislavciuc
Dec 29 '18 at 14:00
@SujitBaniya I'll update the answer with an example as soon as I get to my laptop
– Ivan Stanislavciuc
Dec 29 '18 at 14:01
|
show 6 more comments
You need to call mapTo
on result of the ask call.
(phoneValidationActor ? ValidateUserList(userId.toInt, listId.toInt, prefix.toUpperCase, filter))).mapTo[Seq[PhoneNumber]]
and handle future inside the actor to avoid ClassCastException
class PhoneNumberActor extends Actor with ActorLogging {
import PhoneNumberActor._
def receive: Receive = {
case ValidateUserList(userId, listId, prefix, filter) =>
val theSender = sender() //do not call this method in callback function onSuccess as it breaks actor principles and can send message to a wrong sender
validateUserList(userId, listId, prefix, filter).onSuccess { phoneNumbers =>
theSender ! phoneNumbers
}
}
}
You need to call mapTo
on result of the ask call.
(phoneValidationActor ? ValidateUserList(userId.toInt, listId.toInt, prefix.toUpperCase, filter))).mapTo[Seq[PhoneNumber]]
and handle future inside the actor to avoid ClassCastException
class PhoneNumberActor extends Actor with ActorLogging {
import PhoneNumberActor._
def receive: Receive = {
case ValidateUserList(userId, listId, prefix, filter) =>
val theSender = sender() //do not call this method in callback function onSuccess as it breaks actor principles and can send message to a wrong sender
validateUserList(userId, listId, prefix, filter).onSuccess { phoneNumbers =>
theSender ! phoneNumbers
}
}
}
edited Dec 29 '18 at 16:01
answered Dec 29 '18 at 13:54
Ivan StanislavciucIvan Stanislavciuc
75849
75849
I tried to dodef result = (phoneValidationActor ? ValidateUserList(userId.toInt, listId.toInt, prefix.toUpperCase, filter)).mapTo[Seq[PhoneNumber]]
But receivedjava.lang.ClassCastException: Cannot cast scala.concurrent.impl.Promise$DefaultPromise to scala.collection.Seq
I'm wondering validateUserList already resulting in asFuture[Seq[PhoneNumber]]
. though it's not working
– Sujit Baniya
Dec 29 '18 at 13:56
The reason is that yourvalidateNumber
function returns are future. You need to returnSeq[PhoneNumber]
– Ivan Stanislavciuc
Dec 29 '18 at 13:57
Future[Seq[PhoneNumber]]
is returned by mongodb for its records. So if there's effective solution for this
– Sujit Baniya
Dec 29 '18 at 13:59
@SujitBaniya use map on Future or pipe pattern to resolve handling of the future inside of an actor.
– Ivan Stanislavciuc
Dec 29 '18 at 14:00
@SujitBaniya I'll update the answer with an example as soon as I get to my laptop
– Ivan Stanislavciuc
Dec 29 '18 at 14:01
|
show 6 more comments
I tried to dodef result = (phoneValidationActor ? ValidateUserList(userId.toInt, listId.toInt, prefix.toUpperCase, filter)).mapTo[Seq[PhoneNumber]]
But receivedjava.lang.ClassCastException: Cannot cast scala.concurrent.impl.Promise$DefaultPromise to scala.collection.Seq
I'm wondering validateUserList already resulting in asFuture[Seq[PhoneNumber]]
. though it's not working
– Sujit Baniya
Dec 29 '18 at 13:56
The reason is that yourvalidateNumber
function returns are future. You need to returnSeq[PhoneNumber]
– Ivan Stanislavciuc
Dec 29 '18 at 13:57
Future[Seq[PhoneNumber]]
is returned by mongodb for its records. So if there's effective solution for this
– Sujit Baniya
Dec 29 '18 at 13:59
@SujitBaniya use map on Future or pipe pattern to resolve handling of the future inside of an actor.
– Ivan Stanislavciuc
Dec 29 '18 at 14:00
@SujitBaniya I'll update the answer with an example as soon as I get to my laptop
– Ivan Stanislavciuc
Dec 29 '18 at 14:01
I tried to do
def result = (phoneValidationActor ? ValidateUserList(userId.toInt, listId.toInt, prefix.toUpperCase, filter)).mapTo[Seq[PhoneNumber]]
But received java.lang.ClassCastException: Cannot cast scala.concurrent.impl.Promise$DefaultPromise to scala.collection.Seq
I'm wondering validateUserList already resulting in as Future[Seq[PhoneNumber]]
. though it's not working– Sujit Baniya
Dec 29 '18 at 13:56
I tried to do
def result = (phoneValidationActor ? ValidateUserList(userId.toInt, listId.toInt, prefix.toUpperCase, filter)).mapTo[Seq[PhoneNumber]]
But received java.lang.ClassCastException: Cannot cast scala.concurrent.impl.Promise$DefaultPromise to scala.collection.Seq
I'm wondering validateUserList already resulting in as Future[Seq[PhoneNumber]]
. though it's not working– Sujit Baniya
Dec 29 '18 at 13:56
The reason is that your
validateNumber
function returns are future. You need to return Seq[PhoneNumber]
– Ivan Stanislavciuc
Dec 29 '18 at 13:57
The reason is that your
validateNumber
function returns are future. You need to return Seq[PhoneNumber]
– Ivan Stanislavciuc
Dec 29 '18 at 13:57
Future[Seq[PhoneNumber]]
is returned by mongodb for its records. So if there's effective solution for this– Sujit Baniya
Dec 29 '18 at 13:59
Future[Seq[PhoneNumber]]
is returned by mongodb for its records. So if there's effective solution for this– Sujit Baniya
Dec 29 '18 at 13:59
@SujitBaniya use map on Future or pipe pattern to resolve handling of the future inside of an actor.
– Ivan Stanislavciuc
Dec 29 '18 at 14:00
@SujitBaniya use map on Future or pipe pattern to resolve handling of the future inside of an actor.
– Ivan Stanislavciuc
Dec 29 '18 at 14:00
@SujitBaniya I'll update the answer with an example as soon as I get to my laptop
– Ivan Stanislavciuc
Dec 29 '18 at 14:01
@SujitBaniya I'll update the answer with an example as soon as I get to my laptop
– Ivan Stanislavciuc
Dec 29 '18 at 14:01
|
show 6 more comments
Just like @Ivan Stanislavciuc said, you need to add the mapTo
method to safely cast a Future to an expected type which in this case is [Seq[PhoneNumber]]
.
for your route I'd update it to something like such:
post {
path("validate" / Segment / Segment / Segment) { (userId, listId, prefix) =>
parameters('filter.?) { filter =>
val result =
(phoneValidationActor ? ValidateUserList(userId.toInt, listId.toInt, prefix.toUpperCase, filter)).mapTo[Seq[PhoneNumber]]
onSuccess(result) { maybeResult =>
complete(maybeResult)
}
}
}
}
And if you'd like to handle a Success and Failure you can use onComplete
in place of onSuccess
and have something like:
onComplete(result) {
case scala.util.Success(res) => complete(res)
case scala.util.Failure(ex) => complete(StatusCodes.BadRequest, ex)}
add a comment |
Just like @Ivan Stanislavciuc said, you need to add the mapTo
method to safely cast a Future to an expected type which in this case is [Seq[PhoneNumber]]
.
for your route I'd update it to something like such:
post {
path("validate" / Segment / Segment / Segment) { (userId, listId, prefix) =>
parameters('filter.?) { filter =>
val result =
(phoneValidationActor ? ValidateUserList(userId.toInt, listId.toInt, prefix.toUpperCase, filter)).mapTo[Seq[PhoneNumber]]
onSuccess(result) { maybeResult =>
complete(maybeResult)
}
}
}
}
And if you'd like to handle a Success and Failure you can use onComplete
in place of onSuccess
and have something like:
onComplete(result) {
case scala.util.Success(res) => complete(res)
case scala.util.Failure(ex) => complete(StatusCodes.BadRequest, ex)}
add a comment |
Just like @Ivan Stanislavciuc said, you need to add the mapTo
method to safely cast a Future to an expected type which in this case is [Seq[PhoneNumber]]
.
for your route I'd update it to something like such:
post {
path("validate" / Segment / Segment / Segment) { (userId, listId, prefix) =>
parameters('filter.?) { filter =>
val result =
(phoneValidationActor ? ValidateUserList(userId.toInt, listId.toInt, prefix.toUpperCase, filter)).mapTo[Seq[PhoneNumber]]
onSuccess(result) { maybeResult =>
complete(maybeResult)
}
}
}
}
And if you'd like to handle a Success and Failure you can use onComplete
in place of onSuccess
and have something like:
onComplete(result) {
case scala.util.Success(res) => complete(res)
case scala.util.Failure(ex) => complete(StatusCodes.BadRequest, ex)}
Just like @Ivan Stanislavciuc said, you need to add the mapTo
method to safely cast a Future to an expected type which in this case is [Seq[PhoneNumber]]
.
for your route I'd update it to something like such:
post {
path("validate" / Segment / Segment / Segment) { (userId, listId, prefix) =>
parameters('filter.?) { filter =>
val result =
(phoneValidationActor ? ValidateUserList(userId.toInt, listId.toInt, prefix.toUpperCase, filter)).mapTo[Seq[PhoneNumber]]
onSuccess(result) { maybeResult =>
complete(maybeResult)
}
}
}
}
And if you'd like to handle a Success and Failure you can use onComplete
in place of onSuccess
and have something like:
onComplete(result) {
case scala.util.Success(res) => complete(res)
case scala.util.Failure(ex) => complete(StatusCodes.BadRequest, ex)}
edited Dec 30 '18 at 21:42
answered Dec 30 '18 at 21:37
Ian ShiunduIan Shiundu
758
758
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53970016%2fhow-to-resolve-futureany-in-akka-http%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown