I created a simple scenario.
The following actor systems:
akka.tcp://TestSystem#127.0.0.1:2560
akka.tcp://TestSystem#127.0.0.1:2570
akka.tcp://TestSystem#127.0.0.1:2580
The idea is to create an "SampleActor" from 127.0.0.1:2570 but deploy the actor creation to 127.0.0.1:2560 using the configuration stated on the documentation: Creating Actors Remotely
akka {
actor {
deployment {
/sampleActor {
remote = "akka.tcp://TestSystem#127.0.0.1:2560"
}
}
}
}
And then on 127.0.0.1:2570:
system.actorOf(Props.create(SampleActor.class), "sampleActor");
Now from 127.0.0.1:2580 I wan to find the remote deployed actor and send a message. According to the docs: Looking up Remote Actors
ActorSelection selection =
system.actorSelection("akka.tcp://TestSystem#127.0.0.1:2560/user/sampleActor");
selection.tell("Pretty slick", ActorRef.noSender());
However this does not work. It cannot find the actor on 127.0.0.1:2560. But it works if I change to:
ActorSelection selection =
system.actorSelection("akka.tcp://TestSystem#127.0.0.1:2570/user/sampleActor");
selection.tell("Pretty slick", ActorRef.noSender());
The difference is that on the first one I am looking for the actor where it is deployed, in this case in 127.0.0.1:2560, as the docs say, and on the second case I am looking for the actor where the actor creation was defined, in this case is 127.0.0.1:2570. Why is this happening?, it doesn't make sense, if I am looking for a remote actor then I should look at the place where it was deployed right?
Also when printing the parent at the deployed actor I get:
akka://TestSystem/remote/akka.tcp/TestSystem#127.0.0.1:2570/user
This makes it more confusing as it is not the same as described on the docs: The Interplay with Remote Deployment All of this makes it really confusing, the docs are really long and don't explain properly how to do some basic things properly. Can someone please help me understand this issue?
Well apparently that is just how akka works, it is quite confusing. At the end you should always send messages to the "deployer" not to the deployee. The "deployer" will in turn send the message to the "deployee". Same principle for everything related to remote deployment.
Related
I am struggling to find a fully fledged example of how to use Apache Camel in Spring Boot framework for the purpose of a polling consumer.
I have looked at this: https://camel.apache.org/manual/latest/polling-consumer.html as well as this: https://camel.apache.org/components/latest/timer-component.html but the code examples are not wide enough for me to understand what it is that I need to do to accomplish my task in Java.
I'm typically a C# developer, so a lot of these small references to things don't make sense.
I am seeking an example of the following to do in Java including all the imports and other dependencies that are required to get this to work.
What I am trying to do, is the following
A web request is made to an endpoint, which should trigger the start of a polling consumer
The polling consumer needs to poll another web endpoint with a provided "ID" that needs to be sent to the consumer at the time that it is trigger.
The polling consumer should poll every X seconds (let's say 5 seconds).
Once a specific successful response is received from the endpoint we are polling, the consumer should stop polling and send a message to another web endpoint.
I would like to know if this is possible, and if so, can you provide a small example of everything that is needed to achieve this (as the documentation from the Camel website is extremely sparse in terms of imports and class structure etc.)?
After discussions with some fellow Java colleagues, they have assured me that this use case is not one that Camel is designed for. This is reason it was so difficult to find anything on the internet before I posted this question.
For those that are seeking this answer via Google, the best suggested approach is to use a different tool or just use standard java.
In my case, I ended up using plain old Java thread to achieve what was required. Once the request is received I simply start a new Runnable thread, that handles the checking of the result from the other service, sleeps for X seconds, and terminates when the response is successful.
A simple example is below:
Runnable runner = new Runnable() {
#Override
public void run() {
boolean cont = true;
while (cont) {
cont = getResponseFromServer();
try {
Thread.sleep(5000);
} catch (Exception e) {
// we don't care about this, it just means this time it didn't sleep
}
}
}
}
new Thread(runner).start();
I have a problem while trying my hands on the Hello World example explained here.
Kindly note that I have just modified the HelloEntity.java file to be able to return something other than "Hello, World!". Most certain my changes are taking time and hence I am getting the below Timeout error.
I am currently trying (doing a PoC) on a single node to understand the Lagom framework and do not have liberty to deploy multiple nodes.
I have also tried modifying the default lagom.circuit-breaker in application.conf "call-timeout = 100s" however, this does not seem to have helped.
Following is the exact error message for your reference:
{"name":"akka.pattern.AskTimeoutException: Ask timed out on [Actor[akka://hello-impl-application/system/sharding/HelloEntity#1074448247]] after [5000 ms]. Sender[null] sent message of type \"com.lightbend.lagom.javadsl.persistence.CommandEnvelope\".","detail":"akka.pattern.AskTimeoutException: Ask timed out on [Actor[akka://hello-impl-application/system/sharding/HelloEntity#1074448247]] after [5000 ms]. Sender[null] sent message of type \"com.lightbend.lagom.javadsl.persistence.CommandEnvelope\".\n\tat akka.pattern.PromiseActorRef$.$anonfun$defaultOnTimeout$1(AskSupport.scala:595)\n\tat akka.pattern.PromiseActorRef$.$anonfun$apply$1(AskSupport.scala:605)\n\tat akka.actor.Scheduler$$anon$4.run(Scheduler.scala:140)\n\tat scala.concurrent.Future$InternalCallbackExecutor$.unbatchedExecute(Future.scala:866)\n\tat scala.concurrent.BatchingExecutor.execute(BatchingExecutor.scala:109)\n\tat scala.concurrent.BatchingExecutor.execute$(BatchingExecutor.scala:103)\n\tat scala.concurrent.Future$InternalCallbackExecutor$.execute(Future.scala:864)\n\tat akka.actor.LightArrayRevolverScheduler$TaskHolder.executeTask(LightArrayRevolverScheduler.scala:328)\n\tat akka.actor.LightArrayRevolverScheduler$$anon$4.executeBucket$1(LightArrayRevolverScheduler.scala:279)\n\tat akka.actor.LightArrayRevolverScheduler$$anon$4.nextTick(LightArrayRevolverScheduler.scala:283)\n\tat akka.actor.LightArrayRevolverScheduler$$anon$4.run(LightArrayRevolverScheduler.scala:235)\n\tat java.lang.Thread.run(Thread.java:748)\n"}
Question: Is there a way to increase the akka Timeout by modifying the application.conf or any of the java source files in the Hello World project? Can you please help me with the exact details.
Thanks in advance for you time and help.
The call timeout is the timeout for circuit breakers, which is configured using lagom.circuit-breaker.default.call-timeout. But that's not what is timing out above, the thing that is timing out above is the request to your HelloEntity, that timeout is configured using lagom.persistence.ask-timeout. The reason why there's a timeout on requests to entities is because in a multi-node environment, your entities are sharded across nodes, so an ask on them may go to another node, which is why a timeout is needed in case that node is not responding.
All that said, I don't think changing the ask-timeout will solve your problem. If you have a single node, then your entities should respond instantly if everything is working ok.
Is that the only error you're seeing in the logs?
Are you seeing this in devmode (ie, using the runAll command), or are you running the Lagom service some other way?
Is your database responding?
Thanks James for the help/pointer.
Adding following lines to resources/application.conf did the trick for me:
lagom.persistence.ask-timeout=30s
hello {
..
..
call-timeout = 30s
call-timeout = ${?CIRCUIT_BREAKER_CALL_TIMEOUT}
..
}
A Call is a Service-to-Service communication. That’s a SeviceClient communicating to a remote server. It uses a circuit breaker. It is a extra-service call.
An ask (in the context of lagom.persistence) is sending a command to a persistent entity. That happens across the nodes insied your Lagom service. It is not using circuit breaking. It is an intra-service call.
I'm currently working with Akka Streams (in Java) for a personal project and I'm having a hard time understanding how to send element to a Source.
The idea is to use a WebSocket to push content into the user's web browser. I've managed to use Akka Streams to create a request-response system, following the Akka HTTP documentation, but this is not what I want to do.
Looking into the Akka Streams documentation, I saw that there is Source.queue and Source.actorRef. But I don't understand how to put an element into the Source. Source.queue and Source.actorRef return a Source, which doesn't have the method offer (for Source.queue) or tell (for Source.actorRef).
My question is: how do I get the ActorRef for the Source created by Source.actorRef or the SourceQueueWithComplete for a Source created with Source.queue, to be able to send elements to my Source?
I searched the various Akka documentation but found no method to do that. And the majority of the code I found on the Internet is written in Scala, which doesn't seem to have the same problem.
The actor and queue from Source.actorRef and Source.queue, respectively, are the materialized values of those sources, meaning that they can be obtained only if the stream is running. For example:
final ActorRef actor =
Source.actorRef(Integer.MAX_VALUE, OverflowStrategy.fail())
.to(Sink.foreach(m -> System.out.println(m)))
.run(materializer);
actor.tell("do something", ActorRef.noSender());
It's no different in Scala:
implicit val materializer = ActorMaterializer()
val actor =
Source.actorRef(Int.MaxValue, OverflowStrategy.fail)
.to(Sink.foreach(println))
.run()
actor ! "do something"
I am intercepting messages that are sent through JBossESB. I am using pipeline interceptors to do so.
The problem is, that altough the sender is a service (for example PortReference < logical:BlueServiceESB#BlueListener >), the name of the receiver is a queue (not a service). That is logical because in some case, multiple services can receive messages from a given queue, but usually, each queue is mapped to only one service.
I would like to know which queue is mapped to which service, so I can display/save this information and have it displayed like message: service ---> service (not service ---> queue).
I know that I can get the name of the queue mapped to a service using the registry like this:
System.setProperty("javax.xml.registry.ConnectionFactoryClass", "org.apache.ws.scout.registry.ConnectionFactoryImpl");
// Retrieving information from the ESB Registry
Registry reg = RegistryFactory.getRegistry();
System.out.println(reg.findAllServices());
List<EPR> eprs = reg.findEPRs("FirstServiceESB", "SimpleListener");
System.out.println(eprs);
I would like to reverse this approach - queue is the input and service (EPR = end point reference = service) is the output. Is there any way how to do this or am I just trying to do the impossible here. I have found no tutorials or questions on this topic whatsoever.
Thanks for any tips!
As this question has 25 up-votes, this seems to be an useful feature. JBossESB is open source software. Thus, implement the feature yourself and commit it to the community! Or just create a change request hopping that somebody else will do it...
Try querying for all of the queues and building a reverse-lookup map. But I don't think there is any function that allows searching for services using a queue.
I am starting to learn Akka by migrating an existing Java SE app to it. I am using Akka 2.0.3.
At one point I need to send a PoisonPill through the message queue to stop the actors. My actor is instantiated thus:
ActorRef myActor = actorSystem.actorOf(new Props(MyActor.class), "myActor");
to which I try to send the PoisonPill:
myActor.tell(PoisonPill.getInstance());
But I get the following compiler error:
'tell(java.lang.Object)' in 'akka.actor.ActorRef' cannot be applied to '(akka.actor.PoisonPill$)'
What am I doing wrong? I'm running Java 1.6.0_26 in Idea (which I am also learning after a lifetime in Eclipse).
Edit:
I have also tried this approach, which is in the documentation, but I get the same compiler error and Idea warns me that the Actors class is deprecated.
import static akka.actor.Actors.*;
extractionActor.tell(poisonPill());
Please read the Akka documentation, we've spent a lot of time creating it:
PoisonPill
You can also send an actor the akka.actor.PoisonPill
message, which will stop the actor when the message is processed.
PoisonPill is enqueued as ordinary messages and will be handled after
messages that were already queued in the mailbox.
Use it like this:
import static akka.actor.Actors.*;
myActor.tell(poisonPill());
http://doc.akka.io/docs/akka/2.0.3/java/untyped-actors.html#PoisonPill
The above approach has been deprecated since 2.0.2, this is the new API:
ActorRef ref = system.actorOf(new Props(JavaAPITestActor.class));
ref.tell(PoisonPill.getInstance());
The above compiles on my machine so you might have some issue in IDEA? Try to compile it with javac and see if that works.
As mentioned in my reply to the comment above, this does not work in Idea or when using gradle to compile. It is in fact a compilation error since the sender ActorRef is required. I know the previous answers are old, and i'm not sure if this was a change in the api, so for anyone having a similar issue you should be using :
target.tell(PoisonPill.getInstance(), ActorRef.noSender());
For reference see : http://doc.akka.io/docs/akka/snapshot/java/lambda-actors.html#PoisonPill
UPDATE FROM 25.03.2019
The good answers from #Viktor Klang and #yash.vyas are a bit out of date. Here is the current working syntax of Scala 2.12.8 and JDK8 (1.8.0_172):
val accountB = context.actorOf(Props[BankAccount], "accountB")
accountB ! PoisonPill
You could also write:
...
accountB ! PoisonPill.getInstance
The default call of the tell-Method is also working:
...
accountB.tell(PoisonPill.getInstance,ActorRef.noSender)