I'm reading Akka documentation and now I'm at the section about UntypedActors. I decided to try some examples:
Here are my actors:
Parent
private static class MyUntypedActor extends UntypedActor{
public void onReceive(Object message) throws Exception {
System.out.println("Recieved: " + message);
}
#Override
public void preStart(){
getContext().actorOf(AnotherUntypedActor.props()).tell("Process it", getSelf());
}
public static Props props(){
return Props.create(MyUntypedActor.class);
}
}
Child
private static class AnotherUntypedActor extends UntypedActor{
public static Props props(){
return Props.create(AnotherUntypedActor.class);
}
public void onReceive(Object message) throws Exception {
System.out.println("My: " + message);
throw new RuntimeException("Crashed: " + getSelf());
}
}
main:
public static void main(String[] args) throws TimeoutException {
ActorSystem system = ActorSystem.create();
Inbox inbox = Inbox.create(system);
ActorRef actorRef = system.actorOf(MyUntypedActor.props());
inbox.send(actorRef, "Message");
}
so, my child actors experienced failure and I thought the it should have notified the parent somehow.
But what I recieved was this:
Recieved: Message
My: Process it
[ERROR] [07/14/2016 19:05:13.726] [default-akka.actor.default-dispatcher-4] [akka://default/user/$a/$a] Crashed: Actor[akka://default/user/$a/$a#-950392568]
What does the supervision do actually? Child actor had faulted and what? I got just an error message in a log. What does supervisorStrategy mean? It's by default set to
OneForOneStrategy(-1,Duration.Inf,true)
By using supervisor strategy, you decide what should be done with supervised actor if it fails. You have to override supervisionStrategy() method within your parent actor and define strategy. I.e. (not sure if it's correct since I use Scala for Akka)
#Override
public SupervisorStrategy supervisorStrategy() {
return strategy;
}
private static SupervisorStrategy strategy =
new OneForOneStrategy(10, Duration.create("1 minute"),
t -> {
if (t instanceof SomeException) {
return restart();
} else {
return stop();
}
});
In this case, if SomeException occurs, actor will be restarted. Otherwise, it will be stopped. You can choose one of four strategies.
Read documentation
Tip: Create specific exceptions!
Related
I am using smtp api which throws MessageException and IOException
But in our application, we need to have wrapper exception for both.
Is it possible to write wrapper exception for this? like custom exception?
Sure. Exceptions just are, and can wrap anything; you don't need to write them as specifically wrapping only IOException or MessageExceptions.
public class MyCustomException extends Exception {
public MyCustomException(String msg) {
super(msg);
}
public MyCustomException(String msg, Throwable cause) {
super(msg, cause);
}
}
The above is what all custom exceptions look like (where relevant they might have a few more fields that register specific info for a specific failure, e.g. SQLException has methods to ask for the DB 'error code'), but they all at least have the above.
Then, to wrap:
public void myMethod() throws MyException {
try {
stuffThatThrowsIOEx();
stuffThatThrowsMessageEx();
} catch (MessageException | IOException e) {
throw new MyException("Cannot send foo", e);
}
}
NB: The string you pass to your MyException should be short, should not use either caps or exclamation points, or for that matter any other punctuation at the end of it. In addition, include actual relevant content there too: For example, the user you tried to send a message for (the point is, whatever you include there as a string constant needs to be simple, short, and not end in punctuation).
Consider to create a root Exception container as
public class GeneralExceptionContainer extends RuntimeException{
private Integer exceptionCode;
private String message;
public GeneralExceptionContainer(String argMessage, Integer exceptionCode) {
super(argMessage);
this.exceptionCode = exceptionCode;
this.message = argMessage;
}
public GeneralExceptionContainer(Throwable cause, Integer exceptionCode, String argMessage) {
super(argMessage, cause);
this.exceptionCode = exceptionCode;
this.message = argMessage;
}
}
With some enumeration or serialization requirement you can add exceptionCode as well
public enum ExceptionCode {
SECTION_LOCKED(-0),
MAPPING_EXCEPTION(-110)
private final int value;
public int getValue() {
return this.value;
}
ExceptionCode(int value) {
this.value = value;
}
public static ExceptionCode findByName(String name) {
for (ExceptionCode v : values()) {
if (v.name().equals(name)) {
return v;
}
}
return null;
}
}
Then extend your customException from root GeneralException Containner
public class CustomException extends GeneralExceptionContainer {
public MappingException(ExceptionCode exceptionCode) {
super(exceptionCode.name(), exceptionCode.getValue());
}
}
I'm trying to create a javac plugin which will do some simple source validation for test classes. Essentially I want to ensure that this piece of code is invalid:
#RunWith(Parameterized.class)
class Test {
}
i.e. The RunWith annotation must not contain a Parameterized value. I'm able to get to the point of detecting this but I'm unsure how to produce an error correctly; I want the compile to fail with an error. Of course I can throw an exception, but that doesn't seem right.
I'm following the excellent examples from http://www.baeldung.com/java-build-compiler-plugin. My code currently looks like this:
public class EnsureCorrectRunsWithPlugin implements Plugin {
public static final String NAME = "MyPlugin";
private Context context;
public String getName() {
return NAME;
}
public void init(JavacTask task, String... args) {
context = ((BasicJavacTask) task).getContext();
log("Hello from " + getName());
task.addTaskListener(new TaskListener() {
public void started(TaskEvent e) {
// no-op
}
public void finished(TaskEvent e) {
if (e.getKind() != TaskEvent.Kind.PARSE) {
return;
}
e.getCompilationUnit().accept(new TreeScanner<Void, Void>() {
#Override
public Void visitAnnotation(AnnotationTree annotation, Void aVoid) {
if (annotation.getAnnotationType().toString().equals(RunWith.class.getSimpleName())) {
log("visiting annotation: " + annotation.getAnnotationType());
List<? extends ExpressionTree> args = annotation.getArguments();
for (ExpressionTree arg : args) {
log(" value: " + arg.toString());
if (arg.toString().equals(Parameterized.class.getSimpleName())) {
// Produce an error here...
}
}
}
return super.visitAnnotation(annotation, aVoid);
}
#Override
public Void visitClass(ClassTree node, Void aVoid) {
log("visiting class: " + node);
return super.visitClass(node, aVoid);
}
}, null);
}
});
}
private void log(String message) {
Log.instance(context).printRawLines(Log.WriterKind.NOTICE, message);
}
}
Thanks for any guidance.
You can use Trees.printMessage to output an error message. The first argument controls whether its a warning or an error, and Kind.Error will generate an error.
So assuming you stashed Trees into a variable trees, you can do something like:
this.trees.printMessage(Kind.Error, "Error from JavaC plugin", tree, compilationUnitTree)
The third variable, tree, indicates the error span.
I have some messaging application which needs at-least-once guaranties.
As I understand from documentation: the akka-persistence - is about the actor state. And it uses some layer-by-layer ideology to deal with that state.
In the documentation I found some AbstractPersistentActorWithAtLeastOnceDelivery which seems to be proposing this guaranty. But now I have some doubts about the conception in general:
My actor is a simple transmitter and all I need - is delivery guaranty. So I don't actually care about the actor state and all that layering which consumes precious memory. Can the extensive journal be the reason of problems?
The actor:
public class SafeSenderActor extends AbstractPersistentActorWithAtLeastOnceDelivery {
private String persistenceId;
private ActorSelection destination;
public SafeSenderActor() {
System.out.println("SafeSenderActor created");
this.persistenceId = "safe-persistent-actor-id-" + UUID.randomUUID();
destination = context().actorSelection("/user/safeReceiverRouter");
}
#Override
public String persistenceId() {
return persistenceId;
}
#Override
public AbstractActor.Receive createReceive() {
return ReceiveBuilder.create()
.match(SenderTaskMessage.class, msg -> {
persistAsync(new MsgSentEvent(msg.getTestMessage()), this::updateState);
})
.match(ConfirmRobustMessageDelivery.class, ack -> {
persistAsync(new MsgConfirmEvent(ack.getMessageId(), ack.getLocalMessageNumber()), this::updateState);
})
.build();
}
#Override
public Receive createReceiveRecover() {
return receiveBuilder().match(Object.class, this::updateState).build();
}
private void updateState(Object event) {
if (event instanceof MsgSentEvent) {
MsgSentEvent ev = (MsgSentEvent) event;
deliver(destination, deliveryId -> new RobustTestMessage(deliveryId, ev.getMessage()));
} else if (event instanceof MsgConfirmEvent) {
MsgConfirmEvent ev = (MsgConfirmEvent) event;
confirmDelivery(ev.getDeliveryId());
}
}
}
After some continuous messaging I get the error:
[ERROR] [07/06/2017 01:40:33.446] [sender-system-akka.actor.default-dispatcher-50] [akka://sender-system#127.0.0.1:6666/user/safeSendersRouter/$d] Failed to persist event type [com.test.common.events.MsgSentEvent] with sequence number [358698] for persistenceId [safe-persistent-actor-id-648ec66d-7b7f-4291-b3a2-9bd395d92dc7]. (akka.pattern.CircuitBreaker$$anon$1: Circuit Breaker Timed out.)
I'm using the leveldb as a journal.
It might be a long time but maybe it is still useful to answer it. You can override the methods onPersistFailure and onPersistRejected to investigate the error that you mentioned. The onPersistFailure method is called if persisting failed. The actor will be stooped. BEst practice is to start the actor again after a while and use Backoff supervisor. The onPersistRejected method is called if the JOURNAl fails to persist the event. The actor is RESUMED.
public class SafeSenderActor extends AbstractPersistentActorWithAtLeastOnceDelivery implements ActorLogging {
...
...
...
#Override
public void onPersistFailure(Throwable cause, Object event, long seqNr) {
log().error("fail to persist $event because of: {}", cause);
super.onPersistFailure(cause, event, seqNr);
}
#Override
public void onPersistRejected(Throwable cause, Object event, long seqNr) {
log().error("persist rejected for {} because of: {}", event, cause);
super.onPersistRejected(cause, event, seqNr);
}
}
I'm getting some weirdness when I'm casting a Dynamic Proxy Class to the object I want it to be. At runtime, under certain conditions, I receive a ClassCastException.
In order to explain this better, here are the definitions for the classes/interfaces I want to use. Brackets have been put around any extended interfaces that (should be) irrelevant.
public interface CommandSender (extends Permissible)
public interface ConsoleCommandSender extends CommandSender, (Conversable)
public interface Player extends (HumanEntity, Conversable), CommandSender, (OfflinePlayer, PluginMessageRecipient)
Full Javadocs can be found here: http://jd.bukkit.org/apidocs/org/bukkit/command/CommandSender.html
Now, here is the code for my proxy class:
public class CommandSignsMessagingProxy implements InvocationHandler {
private Object sender;
private Object receiver;
private boolean silent;
public static Object newInstance(Object proxy) {
return newInstance(proxy, proxy, false);
}
public static Object newInstance(Object proxy, boolean silent) {
return newInstance(proxy, proxy, silent);
}
public static Object newInstance(Object sender, Object receiver) {
return newInstance(sender, receiver, false);
}
public static Object newInstance(Object sender, Object receiver, boolean silent) {
return Proxy.newProxyInstance(
sender.getClass().getClassLoader(),
sender.getClass().getInterfaces(),
new CommandSignsMessagingProxy(sender, receiver, silent));
}
private CommandSignsMessagingProxy(Object sender, Object receiver, boolean silent) {
this.sender = sender;
this.receiver = receiver;
this.silent = silent;
}
// Is called whenever a method is invoked
public Object invoke(Object p, Method m, Object[] args) throws Throwable {
Object result = null;
try {
String name = m.getName();
// If the receiver is being sent a message, only do so if the silent flag is not set
if (name == "sendMessage" || name == "sendRawMessage") {
if (!silent && receiver != null)
result = m.invoke(receiver, args);
} else {
result = m.invoke(sender, args);
}
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Exception e) {
throw new RuntimeException("Unexpected invocation exception: " + e.getMessage());
}
return result;
}
}
And here is a fully working instance of the class:
Player proxy = (Player)CommandSignsMessagingProxy.newInstance(player, false);
proxy.sendMessage("Hi! Silent is turned off, so you can see this!");
proxy.setOp(true);
proxy.other_stuff();
Yet, this one doesn't work:
ConsoleCommandSender ccs = plugin.getServer().getConsoleSender();
CommandSender cs = (CommandSender)CommandSignsMessagingProxy.newInstance(ccs, false);
At run time, this example would produce the following:
java.lang.ClassCastException: $Proxy18 cannot be cast to org.bukkit.command.CommandSender
The created proxy class need to pass the interfaces it suppose to implement,
return Proxy.newProxyInstance(
sender.getClass().getClassLoader(),
sender.getClass().getInterfaces(),
new CommandSignsMessagingProxy(sender, receiver, silent));
failure seems to happen because CommandSender interface may not be returned from the call sender.getClass().getInterfaces() method. So try to see if it properly passes by debugging. If not try sending the interface manually to the method and see if it works.
I'm already working on this for weeks to get it working but without success. I'm using Javafx and java for implementing a small chat programm using the smack API (xmpp). The problem is how to get the received messages from java to javafx. The code below is actualy working when I have variable with a static string like "test message" and calling postMessage in java to send it to javafx. But how do I get another object (MessageListener) from java calling postMessage?
public class Java_callback implements RunnableFuture {
FXListener listener;
public String testmsg;
public Java_callback(FXListener listener) {
this.listener = listener;
}
#Override
public void run() throws Exception {
postMessage(testmsg);
}
public void postMessage(final String msg) {
Entry.deferAction(new Runnable() {
#Override
public void run() {
listener.callback(msg);
}
});
}
}
Here the code for processing the message. This part somehow need to call postMessage from the code above.
public void xmpp_create_chat(String msg) {
ChatManager chatmanager = connection.getChatManager();
Chat newChat = chatmanager.createChat("admin#unfc", new MessageListener() {
#Override
public void processMessage(Chat chat, Message message) {
//msgArray.add( new String("Received message: " + message.getBody()) );
//msg_return = "blabla";
//java_callback.postMessage(msg_return);
//test.postMessage(message.getBody());
//System.out.println("Received message: " + message);
}
});
If you make postMessage() static, as in:
public static void postMessage(final String msg);
... then you can make a static method call to it from processMessage(), as in:
Java_callback.postMessage(msg_return);
UPDATE: Change your initializion of listener as well.
private static FXListener listener;
Hopefully this doesn't break something outside of the provided code :)
The class containing your second function has to have a reference to the first object, so that it can make the call.
What needs here is so basic that it's hard to figure out what an example might be.
something like this for your second class:
class MessageReceiver {
private Java_callback callback;
public void setJava_callback(Java_callback callback) {
this.callback = callback;
}
....
void process_message(...) { // inside your inner class
calllback.postMessage(msg);
}
}
Is the magic recipe that inner classes can refer to fields of their containing class?