I have a play framework that uses the play actor integration to reference and communicate with a remote akka system. Looks like I am not getting the remote referencing right. First the remote akka implements the bootable interface and It has a master node that creates a child actor system.
the play actor system then references the remote system. the code snippets are presented below.
this is the Play framework node that creates the local actor system
public void connectMaster (final String classname)
{
localActor.tell(classname);
}
public void connectMaster ()
{
//localActor.tell(getByte(new Coordinates()));
}
public void connectMaster (final WebSocket.In<JsonNode> in, final WebSocket.Out<JsonNode> out )
{
in.onMessage(new Callback<JsonNode>() {
public void invoke(JsonNode event) throws JsonParseException, JsonMappingException, IOException {
ObjectMapper mapper = new ObjectMapper();
#SuppressWarnings("unchecked")
Map<String,ArrayList<Object>> jsonMap = mapper.readValue(event, Map.class);
GesturePoints gp = new GesturePoints();
gp.setPoints(jsonMap);
localActor.tell(gp);
}
}); }
this is the local Actor system in play framework
package controllers;
import Com.RubineEngine.GesturePoints.*;
import akka.actor.ActorRef;
import akka.actor.UntypedActor;
import akka.event.Logging;
import akka.event.LoggingAdapter;
public class LocalActor extends UntypedActor {
/**
*
*/
ActorRef masterActor; // = getContext().actorFor("akka://MasterNode#127.0.0.1:2552/user/masterActor");
LoggingAdapter log = Logging.getLogger(getContext().system(), this);
#Override
public void onReceive(Object arg) throws Exception {
System.out.println(" Local Actor 1");
if(arg instanceof GesturePoints)
{ System.out.println(" local Actor 2");
masterActor.tell(arg , getSelf());
System.out.println(" Local Actor 3");}
else
{unhandled(arg);}
}
public void preStart()
{
masterActor = getContext().actorFor("akka://MasterNode#127.0.0.1:2552/user/masterActor");
}
}
this is the remote akka system master Node that creates the master actor
package Rubine_Cluster;
import java.util.Arrays;
import com.typesafe.config.ConfigFactory;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;
import akka.kernel.Bootable;
/**
* Hello world!
*
*/
public class MasterNode implements Bootable
{
final ActorSystem system;
ActorRef masterActor;
public MasterNode() {
//Create a child actor of this actor upon initialization
system = ActorSystem.create("MasterNode", ConfigFactory.load()
.getConfig("masterNode"));
masterActor = system.actorOf(new Props(MasterActor.class),"masterActor");
}
public void startup() {
}
public void shutdown() {
system.shutdown();
}
}
this is the remote actor system created by the MasterNode
public class MasterActor extends UntypedActor {
/**
*
*/
ActorSystem system = ActorSystem.create("container");
ActorRef worker1;
//public MasterActor(){}
#Override
public void onReceive(Object message) throws Exception {
System.out.println(" Master Actor 5");
if(message instanceof GesturePoints)
{ //GesturePoints gp = (GesturePoints) message;
System.out.println(" Master Actor 1");
try { worker1.tell(message, getSelf());
System.out.println(" Master Actor 2");
} catch (Exception e) {
getSender().tell(new akka.actor.Status.Failure(e), getSelf());
throw e;
}
}
else{ unhandled(message);}
}
public void preStart()
{
worker1 = getContext().actorFor("akka://WorkerNode#127.0.0.1:2553/user/workerActor");
}
}
I think I got the referencing wrong or probably were to send the message any suggestion is welcome
Related
I am using IntelliJ as my IDE and the code below runs alright if they are in the same src folder. However, what I want is to call the sayHello() method in another project. Is that possible? I thought this is possible since this is what RMI enables, but am I wrong?
I tried to create another project that contains a Main java class and has the same code as the Client Test Drive below, hoping to call the sayHello() method by utilizing Naming.lookup() but it doesn't work! If I try to run it, I was given a java.rmi.UnmarshalException: error unmarshalling return; exception. What am I missing?
How can I call the sayHello() method "remotely"?
Remote Interface:
package Remote;
import java.rmi.*;
public interface HelloRemote extends Remote {
String sayHello() throws RemoteException;
}
Remote Implementation
package Remote;
import java.rmi.*;
import java.rmi.registry.*;
import java.rmi.server.*;
public class HelloRemoteImpl extends UnicastRemoteObject implements HelloRemote{
public HelloRemoteImpl() throws RemoteException {};
#Override
public String sayHello() throws RemoteException {
return "Server says, \"Hello!\"";
}
public static void main(String[] args) {
try {
// 2.3 register the service
HelloRemote service = new HelloRemoteImpl();
final int PORT = 1888;
Registry registry = LocateRegistry.createRegistry(PORT);
registry.rebind("hello", service);
System.out.println("Service running on PORT: " + PORT);
} catch(Exception e) {
e.printStackTrace();
}
}
}
Client Test Drive
package Remote;
import java.rmi.Naming;
public class SayHelloTest {
public static void main(String[] args) {
try {
HelloRemote service = (HelloRemote) Naming.lookup("rmi://127.0.0.1:1888/hello");
String helloStr = service.sayHello();
System.out.println(helloStr);
} catch (Exception e) {
e.printStackTrace();
}
}
}
I am using the below code sample where I am calling the cancelWF method to cancel the execution of workflow. The onCatch method is successfully invoked with the RuntimeException("Simply cancel"), but on the Amazon SWF console the WF does not end immediately, it waits will timeout and ends with a WorkflowExecutionTerminated event.
The whole project is available here if you want more info.
package aws.swf;
import aws.swf.common.Constants;
import aws.swf.common.DelayRequest;
import aws.swf.common.MyActivityClient;
import aws.swf.common.MyActivityClientImpl;
import aws.swf.common.MyWorkflow;
import aws.swf.common.SWFClient;
import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflow;
import com.amazonaws.services.simpleworkflow.flow.WorkflowWorker;
import com.amazonaws.services.simpleworkflow.flow.annotations.Asynchronous;
import com.amazonaws.services.simpleworkflow.flow.core.Promise;
import com.amazonaws.services.simpleworkflow.flow.core.TryCatch;
import java.util.concurrent.CancellationException;
public class D_CancelWorkflow implements MyWorkflow {
private TryCatch tryCatch;
private final MyActivityClient activityClient = new MyActivityClientImpl();
#Override
public void sum() {
tryCatch = new TryCatch() {
#Override
protected void doTry() throws Throwable {
System.out.printf("[WF %s] Started exec\n", D_CancelWorkflow.this);
Promise<Integer> result = activityClient.getNumWithDelay(new DelayRequest("req1", 1));
cancelWF(result);
newDelayRequest(result);
}
#Override
protected void doCatch(Throwable e) throws Throwable {
if (e instanceof CancellationException) {
System.out.printf("[WF %s] Cancelled With message [%s]\n",
D_CancelWorkflow.this, e.getCause().getMessage());
} else {
e.printStackTrace();
}
rethrow(e);
}
};
}
#Asynchronous
private void newDelayRequest(Promise<Integer> num) {
activityClient.getNumWithDelay(new DelayRequest("req2", 1));
}
#Asynchronous
private void cancelWF(Promise<Integer> ignore) {
System.out.printf("[WF %s] Cancelling WF\n", D_CancelWorkflow.this);
this.tryCatch.cancel(new RuntimeException("Simply cancel"));
}
public static void main(String[] args) throws Exception {
AmazonSimpleWorkflow awsSwfClient = new SWFClient().getClient();
WorkflowWorker workflowWorker =
new WorkflowWorker(awsSwfClient, Constants.DOMAIN, Constants.TASK_LIST);
workflowWorker.addWorkflowImplementationType(D_CancelWorkflow.class);
workflowWorker.start();
}
}
This is the event history for one of my execution,
Asterisk 11.4.0
Asterisk-java: 1.0.0.CI-SNAPSHOT
I've try to run this code:
import org.asteriskjava.live.AsteriskChannel;
import org.asteriskjava.live.AsteriskQueue;
import org.asteriskjava.live.AsteriskQueueEntry;
import org.asteriskjava.live.internal.AsteriskAgentImpl;
import org.asteriskjava.live.AsteriskServer;
import org.asteriskjava.live.AsteriskServerListener;
import org.asteriskjava.live.DefaultAsteriskServer;
import org.asteriskjava.live.ManagerCommunicationException;
import org.asteriskjava.live.MeetMeRoom;
import org.asteriskjava.live.MeetMeUser;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
public class HelloLiveEverything implements AsteriskServerListener, PropertyChangeListener
{
private AsteriskServer asteriskServer;
public HelloLiveEverything()
{
asteriskServer = new DefaultAsteriskServer("localhost", "manager", "password");
}
public void run() throws ManagerCommunicationException
{
// listen for new events
asteriskServer.addAsteriskServerListener(this);
// add property change listeners to existing objects
for (AsteriskChannel asteriskChannel : asteriskServer.getChannels())
{
System.out.println(asteriskChannel);
asteriskChannel.addPropertyChangeListener(this);
}
}
public void onNewAsteriskChannel(AsteriskChannel channel)
{
System.out.println(channel);
channel.addPropertyChangeListener(this);
}
public void onNewMeetMeUser(MeetMeUser user)
{
System.out.println(user);
user.addPropertyChangeListener(this);
}
public void onNewQueueEntry(AsteriskQueueEntry user)
{
System.out.println(user);
user.addPropertyChangeListener(this);
}
public void onNewAgent(AsteriskAgentImpl user)
{
System.out.println(user);
user.addPropertyChangeListener(this);
}
public void propertyChange(PropertyChangeEvent propertyChangeEvent)
{
System.out.println(propertyChangeEvent);
}
public static void main(String[] args) throws Exception
{
HelloLiveEverything helloLiveEverything = new HelloLiveEverything();
helloLiveEverything.run();
while (true) {
}
}
}
When executed, connectios is OK. This code show me current channels but never show me new channels when callers make a calls.
I need to catch the events when new asterisk channels are opening.
What I made wrong?
Thank you
Try This:
Your Class HelloLiveEverything should implement ManagerEventListener
then override the onManagerEvent method
#Override
public void onManagerEvent(ManagerEvent event) {
String event_name = event.getClass().getSimpleName();
if (event_name.equals("DialEvent")) {
DialEvent e = (DialEvent) event;
System.out.println(e.getCallerIdNum());//caller number
System.out.println(e.getDestination());//Called number
//do something here
}
}
edit asterisk manager.conf :
[manager]
secret = password
deny=0.0.0.0/0.0.0.0
permit=209.16.236.73/255.255.255.0; change this ip with one your java app is using permit=127.0.0.1/255.255.255.0
read = system,call,log,verbose,command,agent,user,originate; add full permission
write = system,call,log,verbose,command,agent,user,originate; add full permission
I am new to Akka and am not familiar with Scala at all. I am trying to use the Akka+Java for running a project on multiple machines. I was able to successfully run Akka Java examples locally but when I tried to run any of them on two machine, the code stops working. I've looked at the Akka-Sample-Remote source code as well. It also works on a single machine but breaks when used on more than one machine. I think the problem is with the way I set the configurations. I have summarized the problem into a simple HelloWorld problem as below.
There code is divided into two projects with two separate configuration files: a Hello Actor project and a World Actor project. World Actor waits for receiving the Hello Message from the Hello Actor and then prints out the "Hello World". Here below you can see the code and the configuration for these two projects. As you can see, the World Actor is started on port 1719 and the Hello Actor starts on port 1720 and tries to connect to the World Actor using "akka.tcp://WorldApplication#192.27.336.187:1719/user/WorldActor" . Any idea on what is wrong with he code/configuration?
JWorld.java:
public class JWorld {
public static void main(String[] args) {
JWorldApplication app = new JWorldApplication();
System.out.println("Started World Application - waiting for Hello message");
}
}
JWorldApplication.java:
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;
import com.typesafe.config.ConfigFactory;
public class JWorldApplication {
private ActorSystem system;
public JWorldApplication() {
system = ActorSystem.create("WorldApplication", ConfigFactory.load()
.getConfig("WorldConfig"));
ActorRef actor = system.actorOf(new Props(JWorldActor.class),
"WorldActor");
}
}
JWolrdActor.java:
import akka.actor.UntypedActor;
public class JWorldActor extends UntypedActor {
#Override
public void onReceive(Object message) {
if (message instanceof HelloMessage) {
HelloMessage recMsg = (HelloMessage) message;
System.out.println("Received Message: " + recMsg.getText());
System.out.println("***** Hello World! ******" );
} else {
System.out.println("UnHandled Message Received" );
unhandled(message);
}
}
}
HelloMessage.java:
import akka.actor.ActorRef;
public class HelloMessage{
private ActorRef receiver;
private String text;
HelloMessage() {}
HelloMessage(ActorRef receiver){ this.receiver = receiver;}
public ActorRef getReceiver(){ return receiver;}
public void setText(String text) { this.text = text;}
public String getText() {return text;}
}
Application.conf:
WorldConfig {
actor {
provider = "akka.remote.RemoteActorRefProvider"
}
remote {
netty.tcp {
hostname="192.27.336.187"
port=1719
}
}
}
JHello.java:
public class JHello {
public static void main(String[] args) {
JHelloApplication testApp = new JHelloApplication();
System.out.println("Started Hello Application - Sending Hello Message");
testApp.sayHello();
}
}
JHelloApplication.java:
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;
import com.typesafe.config.ConfigFactory;
public class JHelloApplication {
private ActorSystem system;
private ActorRef remoteActor, myActor;
public JHelloApplication() {
system = ActorSystem.create("HelloApplication", ConfigFactory.load()
.getConfig("HelloConfig"));
myActor = system.actorOf(new Props(JHelloActor.class),"HelloActor");
remoteActor = system
.actorFor("akka.tcp://WorldApplication#192.27.336.187:1719/user/WorldActor");
}
public void sayHello() {
myActor.tell(new HelloMessage(remoteActor));
}
}
JHelloActor.java:
import akka.actor.ActorRef;
import akka.actor.UntypedActor;
public class JHelloActor extends UntypedActor {
#Override
public void onReceive(Object message) {
if (message instanceof HelloMessage) {
HelloMessage msg = (HelloMessage) message;
if (msg.getReceiver() !=null){
msg.setText("Hello");
msg.getReceiver().tell(msg, getSelf());
}
} else {
System.out.println("UnHandled Message Received" );
unhandled(message);
}
}
}
application.conf:
HelloConfig {
actor {
provider = "akka.remote.RemoteActorRefProvider"
}
remote {
netty.tcp {
hostname="192.27.336.187"
port=1720
}
}
}
As mentioned by Patrcik the question is finally answered by Patrik on Akka groups. The problem was that the Akka{} tag is missing in both configuration files. Adding this tag solves the problem.
I am trying to use Akka future with play framework to connect to a remote akka system
. After running the system the akka future gives me a warning that one argument is left.
the code are below :
this is the [lay controller code:
p
ackage controllers;
import com.typesafe.config.ConfigFactory;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;
import play.*;
import play.mvc.*;
import views.html.*;
public class Application extends Controller {
public static Result index() throws InterruptedException {
System.out.println(" Local Node Called0");
ActorSystem csystem = ActorSystem.create("Application", ConfigFactory.load().getConfig("LocalNode"));
ActorRef localNode = csystem.actorOf(new Props(LocalNode.class));
System.out.println(" Local Node Called1");
localNode.tell("Hello");
System.out.println(" Local Node Called2");
Thread.sleep(5000);
csystem.shutdown();
return ok(index.render("I am OK"));
}
}
this is the play framework local actor node
package controllers;
import akka.actor.;
import akka.dispatch.Await;
import akka.dispatch.Future;
import akka.event.Logging;
import akka.event.LoggingAdapter;
import akka.util.Duration;
import akka.util.Timeout;
import akka.pattern.;
public class LocalNode extends UntypedActor {
LoggingAdapter log = Logging.getLogger(getContext().system(), this);
Timeout timeout = new Timeout(Duration.parse("20 seconds"));
ActorRef masterActor;
public void preStart()
{
/* Get reference to Master Node*/
masterActor =
getContext().actorFor("akka://MasterNode#127.0.0.1:2552/user/masterActor");
}
#Override
public void onReceive(Object message) throws Exception {
System.out.println(" Future called ");
Future<Object> future = Patterns.ask(masterActor , message.toString(), timeout);
String result = (String) Await.result(future, timeout.duration());
log.info("Messagefrom Server", result.toString());
}
}
this is the remote akka system master nide
package Rubine_Cluster;
import com.typesafe.config.ConfigFactory;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;
import akka.actor.UntypedActor;
import akka.kernel.Bootable;
/**
* Hello world!
*
*/
public class MasterNode implements Bootable
{
final ActorSystem system;
public MasterNode() {
system = ActorSystem.create("MasterNode", ConfigFactory.load()
.getConfig("masterNode"));
ActorRef masterActor = system.actorOf(new Props(MasterActor.class),"masterActor");
System.out.println(" Master Node is called ");
}
public void startup() {
}
public void shutdown() {
system.shutdown();
}
}
this is the akka remote system MasterActor
package Rubine_Cluster;
import akka.actor.*;
public class MasterActor extends UntypedActor {
#Override
public void onReceive(Object message) throws Exception {
if (message instanceof String) {
// Get reference to the message sender and reply back
getSender().tell(message + " got something");
}
}
}
this is the message from the play framewrok
[INFO] [09/30/2012 16:47:25.669] [Application-akka.actor.default-dispatcher-1] [
akka://Application/user/$a] Messagefrom Server WARNING arguments left: 1
help is needed cos I am suppose to meet the assignment deadline
thanks to all
The "arguments left: 1" warning is due to the following line:
log.info("Messagefrom Server", result.toString())
You're passing unused params to the logger. It should be this instead:
log.info("Messagefrom Server {}", result.toString())
Try to give a name to your actor in Play:
ActorRef localNode = csystem.actorOf(new Props(LocalNode.class), "localNode");
And also note that if you need to access the Akka system from Play, it is better to use:
ActorSystem csystem = Akka.system();
instead of:
ActorSystem csystem = ActorSystem.create("Application", ConfigFactory.load().getConfig("LocalNode"));