I'd like to write a MessageConverter class that can wrap another MessageConverter. This MessageConverter would call the child converter, which is assumed to generate a TextMessage. It would take the payload and GZIP compress it, creating a BytesMessage which is ultimately returned to the sender.
The problem is in writing fromMessage(). I can convert the payload back into the string, but then I want to create a "dummy" TextMessage to stuff the string into to then pass to the child MessageConverter's fromMessage() method. There I'm hitting a brick wall because I can't create a TextMessage without a JMS session object, and it appears that there is no way at all to get a session in this context.
I could create additional properties to wire up more stuff to this class, but it doesn't look like I can easily even obtain a session from a JMSTemplate object, and I can't imagine what else I'd need to have.
I am on the verge of creating a private TextMessage implementation within this code just for the purpose of wrapping a string for the child MessageConverter. That class will require tons of dummy methods to flesh out the Interface, and all of that typing makes baby Jesus cry.
Can anyone suggest a better way?
Do you really wanna wrap MessageConverter instances inside other MessageConverter instances? The whole point of a MessageConverter is to turn a Message into something else (that is not a JMS Message). Its not really designed to chain them (each step making a fake JMS message).
Why not just introduce your own interface
interface MessageBodyConverter {
/** return a converted body of the original message */
Object convert(Object body, Message originalMessage);
}
You then can create a MessageConverter invoking one of these (which can then nest as deep as you like)
class MyMessageConverter implements MessageConverter {
private final MessageBodyConverter converter;
public Object fromMessage(Message message) {
if (message instanceof ObjectMessage) {
return converter.convert(objectMessage.getObject(), message);
...
}
}
You can then chain those MessageBodyConverter objects as deep as you like - plus you have access to the original JMS message (to get headers and so forth) without having to try create pseudo (probably not JMS compliant) implementations of Message?
So I did, in fact, make one of these:
private static class FakeTextMessage implements TextMessage {
public FakeTextMessage(Message m) { this.childMessage = m; }
private String text;
private Message childMessage;
public void setText(String t) { this.text = t; }
public String getText() { return this.text; }
// All the rest of the methods are simply pass-through
// implementations of the rest of the interface, handing off to the child message.
public void acknowledge() throws JMSException { this.childMessage.acknowledge(); }
public void clearBody() throws JMSException { this.childMessage.clearBody(); }
public void clearProperties() throws JMSException { this.childMessage.clearProperties(); }
public Enumeration getPropertyNames() throws JMSException { return this.childMessage.getPropertyNames(); }
public boolean propertyExists(String pn) throws JMSException { return this.childMessage.propertyExists(pn); }
// and so on and so on
}
Makes me long for Objective C. How is THAT possible? :)
Related
In akka-typed, the convention is to create Behavior classes with static inner classes that represent the messages that they receive. Heres a simple example
public class HTTPCaller extends AbstractBehavior<HTTPCaller.MakeRequest> {
public interface Command {}
// this is the message the HTTPCaller receives
public static final class MakeRequest implements Command {
public final String query;
public final ActorRef<Response> replyTo;
public MakeRequest(String query, ActorRef<Response> replyTo) {
this.query = query;
this.replyTo = replyTo;
}
}
// this is the response message
public static final class Response implement Command {
public final String result;
public Response(String result) {
this.result = result;
}
}
public static Behavior<Command> create() {
return Behaviors.setup(HTTPCaller::new);
}
private HTTPCaller(ActorContext<Command> context) {
super(context);
}
#Override
public Receive<Command> createReceive() {
return newReceiveBuilder()
.onMessage(MakeRequest.class, this::onMakeRequest).build();
}
private Behavior<MakeRequest> onMakeRequest(MakeRequest message) {
String result = // make HTTP request here using message.query
message.replyTo.tell(new Response(result));
return Behaviors.same();
}
}
Let's say that 20 other actors send MakeRequest messages to the single HTTPCaller actor. Now, each of these other actors have inner classes that implement their own Command. Since MakeRequest is being used by all 20 classes it must be a subtype of all 20 of those actors' Command inner interface.
This is not ideal. I'm wondering what the Akka way of getting around this is.
There's no requirement that a message (e.g. a command) which an actor sends (except for messages to itself...) have to conform to that actor's incoming message type. The commands sent to the HTTPCaller actor only have to (and in this case only do) extend HTTPCaller.Command.
So imagine that we have something like
public class SomeOtherActor extends AbstractBehavior<SomeOtherActor.Command> {
public interface Command;
// yada yada yada
ActorRef<HTTPCaller.Command> httpCallerActor = ...
httpCallerActor.tell(new HTTPCaller.MakeRequest("someQuery", getContext().getSystem().ignoreRef());
}
In general, when defining messages which are sent in reply, those are not going to extend the message type of the sending actor. In HTTPCaller, for instance, Response probably shouldn't implements Command: it can be a standalone class (alternatively, if it is something that might be received by the HTTPCaller actor, it should be handled in the receive builder).
My code above does bring up one question: if Response is to be received by SomeOtherActor, how can it extend SomeOtherActor.Command?
The solution there is message adaptation: a function to convert a Response to a SomeOtherActorCommand. For example
// in SomeOtherActor
// the simplest possible adaptation:
public static final class ResponseFromHTTPCaller implements Command {
public final String result;
public ResponseFromHTTPCaller(HTTPCaller.Response response) {
result = response.result;
}
// at some point before telling the httpCallerActor...
// apologies if the Java lambda syntax is messed up...
ActorRef<HTTPCaller.Response> httpCallerResponseRef =
getContext().messageAdapter(
HTTPCaller.Response.class,
(response) -> { new ResponseFromHTTPCaller(response) }
);
httpCallerActor.tell(new HTTPCaller.MakeRequest("someQuery", httpCallerResponseRef);
There is also the ask pattern, which is more useful for one-shot interactions between actors where there's a timeout.
I am on a project using Java and Spring Boot that processes several different message types from the same queue. Each message gets processed conditionally based on the message type, using an implementation of MessageProcessingService abstract class for each message type.
As of now, we have 5 different message types coming into the same consumer. We are using the same queue because we leverage group policies in JMS, and each message type has the same business key as the group policy.
So what we end up with is that every time a requirement requires receiving a new message type, we add a new implementation of a MessageProcessingService and another dependency to the consumer object. I want to find a better strategy to selectively choose the message processing
Here is an example similar to what we are doing. I do not guarantee the syntax is compilable or syntactically perfect, just demonstrating the problem. Notice all the messages resolve around a person
Consumer:
#Component
public class PersonMessageConsumer {
private MessageProcessingService<HeightUpdate> heightUpdateMessageProcessingService;
private MessageProcessingService<WeightUpdate> weightUpdateMessageProcessingService;
private MessageProcessingService<NameUpdate> nameUpdateMessageProcessingService;
private MessageProcessingService<ShowSizeUpdate> shoeSizeUpdateMessageProcessingService;
public PersonMessageConsumer(
MessageProcessingService<HeightUpdate> heightUpdateMessageProcessingService,
MessageProcessingService<WeightUpdate> weightUpdateMessageProcessingService,
MessageProcessingService<NameUpdate> nameUpdateMessageProcessingService,
MessageProcessingService<ShowSizeUpdate> shoeSizeUpdateMessageProcessingService) {
this.heightUpdateMessageProcessingService = heightUpdateMessageProcessingService;
this.weightUpdateMessageProcessingService = weightUpdateMessageProcessingService;
this.nameUpdateMessageProcessingService = nameUpdateMessageProcessingService;
this.shoeSizeUpdateMessageProcessingService = shoeSizeUpdateMessageProcessingService;
}
#JmsListener(destination = "${queueName}")
public void receiveMessage(TextMessage message) {
String messageType = message.getHeader("MessageType");
switch (messageType) {
case "HeightUpdate":
heightUpdateMessageProcessingService.processMessage(message.getText());
return;
case "WeightUpdate":
weightUpdateMessageProcessingServivce.processMessage(message.getText());
return;
// And other message types
default:
throw new UnknownMessageTypeException(messageType);
}
}
Message POJO example
public class HeightUpdate implements PersonMessage {
#Getter
#Setter
private int height;
}
PersonMessage interface
public interface PersonMessage {
int getPersonId();
}
MessageProcessingService
public abstract class MessageProcessingService<T extends PersonMessage> {
public void processMessage(String messageText) {
//Common message processing, we do some more involved work here but just as a simple example
T message = new ObjectMapper.readValue(messageText, getClassType());
Person person = personRepository.load(message.getPersonId());
Person originalPerson = person.deepCopy();
processMessageLogic(person, message);
if (originalPerson.isDifferentFrom(person)) {
personRespository.update(person);
}
}
protected abstract void processMessageLogic(Person person, T message);
protected abstract Class getClassType();
}
Abstract class implementation example
#Service("heightUpdateMessageProcessingService")
public class HeightUpdateMessageProcessingService extends MessageProcessingService<HeightUpdate> {
#Override
protected void processMessageLogic(Person person, HeightUpdate update) {
person.setHeight(update.getHeight());
}
#Override
protected Class getMessageType() {
return HeightUpdate.getClass();
}
}
So my question is whether or not there is a better design pattern or way of coding this in java and spring that is a little easier to clean and maintain and keeps SOLID principles in mind
Add an abstract method in the MessageProcessingService to return the messageType that each concrete implementation can handle.
Rather than wiring each individual service into PersonMessageConsumer, wire in a List<MessageProcessingService> so that you get all of them at once.
Transform that List into a Map<String, MessageProcessingService>, using the messageType as the key.
Replace the switch statement by looking up the appropriate service in the Map and then invoking its processMessage method.
In the future you can add new instances of MessageProcessingService without having to edit PersonMessageConsumer because Spring will automatically add those new instances to the List<MessageProcessingService> that you wire in.
I was reading documentation on Akka actors implementation in Playframework,
https://www.playframework.com/documentation/2.4.x/JavaAkka
One of the paragraphs talk about message class best practice as following:
"Another best practice shown here is that the messages that HelloActor sends and receives are defined as static inner classes of another class calledHelloActorProtocol:"
Can some one please elaborate and explain this best practice and what are the benefits of this pattern? Why message should be defined as static nested class of other class?
Thank you in advance!
I believe the main idea behind this is to isolate the scope of messages sent to a specific actor. Having typed protocols helps cut down on sending an unexpected Protocol (or message) to the actor. Keeping them in one class is a nice way to capture all the actions related to that specific domain, like EmployeeProtocol helps enforce EmployeeActor to receive expected messages. However, you still have the responsibility to send them correctly:
Here is our controller call to the EmployeeActor using the protocol:
public class EmployeeController extends Controller {
return Promise.wrap(ask(employeeActorRef,
new GetCurrentEmployees(), 5000))
.map(response -> ok((JsonNode)response));
}
}
EmployeeActor processes its messages based on the received protocol:
public class EmployeeActor extends UntypedActor {
#Override
public void onReceive(Object message) throws Exception {
if (message instanceof GetCurrentEmployees) {
//do things related to this task
} else if (message instanceof CreateNewEmployee) {
//do things related to this task
} else if (message instanceof RemoveEmployee) {
//do things related to this task
}
}
}
Here protocols are defined for actions on the employee and can hold typed fields so we know what to expect. The fact that we use static final fields in the protocol will enforce immutability of the messages:
public class EmployeeProtocol {
public static class GetCurrentEmployees {}
public static class CreateNewEmployee {
private final String name;
public CreateNewEmployee(String name) {
this.name = name;
}
//getter
}
public static class RemoveEmployee {
public final String uuidToRemove;
public RemoveEmployee(String uuidToRemove) {
this.uuidToRemove = uuidToRemove;
}
//getter
}
}
Akka-Typed is being developed in akka scala which can be used to send messages of only a specific type so that if you attempt to send an incorrect message type the compiler will complain. Akka-typed - http://doc.akka.io/docs/akka/snapshot/scala/typed.html#typed-scala
Maybe they wanted us to use this best practice because we'll be able to make it type safe in the future... There was also mention of this coming to java here in this podcast: https://www.typesafe.com/resources/video/akka-2-4-plus-new-commercial-features-in-typesafe-reactive-platform
I'm very new with Akka and I'm trying to write some unit tests in Java. Consider the following actor:
public class Worker extends UntypedActor {
#Override
public void onReceive(Object message) throws Exception {
if (message instanceof Work) {
Work work = (Work) message;
Result result = new Helper().processWork(work);
getSender().tell(result, getSelf());
} else {
unhandled(message);
}
}
}
What is the proper way to intercept the call new Helper().processWork(work)? On a side note, is there any recommended way to achieve dependency injection within Akka actors with Java?
Thanks in advance.
Your code is already properly testable:
you can test your business logic separately, since you can just instantiate your Helper outside of the actor
once you are sure that the Helper does what it is supposed to do, just send some inputs to the actor and observe that the right replies come back
Now if you need to have a “mocked” Worker to test some other component, just don’t use a Worker at all, use a TestProbe instead. Where you would normally get the ActorRef of the Worker, just inject probe.getRef().
So, how to inject that?
I’ll assume that your other component is an Actor (because otherwise you won’t have trouble applying whatever injection technique you normally use). Then there are three basic choices:
pass it in as constructor argument
send it within a message
if the actor creates the ref as its child, pass in the Props, possibly in an alternative constructor
The third case is probably what you are looking at (I’m guessing based on the actor class’ name):
public class MyParent extends UntypedActor {
final Props workerProps;
public MyParent() {
workerProps = new Props(...);
}
public MyParent(Props p) {
workerProps = p;
}
...
getContext().actorOf(workerProps, "worker");
}
And then you can inject a TestProbe like this:
final TestProbe probe = new TestProbe(system);
final Props workerMock = new Props(new UntypedActorFactory() {
public UntypedActor create() {
return new UntypedActor() {
#Override
public void onReceive(Object msg) {
probe.getRef().tell(msg, getSender());
}
};
}
});
final ActorRef parent = system.actorOf(new Props(new UntypedActorFactory() {
public UntypedActor create() {
return new MyParent(workerMock);
}
}), "parent");
I have the following situation where a client class executes different behavior based on the type of message it receives. I'm wondering if there is a better way of doing this since I don't like the instanceof and the if statements.
One thing I thought of doing was pulling the methods out of the client class and putting them into the messages. I would put a method like process() in the IMessage interface and then put the message specific behavior in each of the concrete message types. This would make the client simple because it would just call message.process() rather than checking types. However, the only problem with this is that the behavior contained in the conditionals has to do with operations on data contained within the Client class. Thus, if I did implement a process method in the concrete message classes I would have to pass it the client and I don't know if this really makes sense either.
public class Client {
messageReceived(IMessage message) {
if(message instanceof concreteMessageA) {
concreteMessageA msg = (concreteMessageA)message;
//do concreteMessageA operations
}
}
if (message instanceof concreteMessageB) {
concreteMessageb msg = (concreteMessageB)message;
//do concreteMessageB operations
}
}
The simple way to avoid instanceof testing is to dispatch polymorphicly; e.g.
public class Client {
void messageReceived(IMessage message) {
message.doOperations(this);
}
}
where each message class defines an appropriate doOperations(Client client) method.
EDIT: second solution which better matches the requirements.
An alternative that replaces a sequence of 'instanceof' tests with a switch statement is:
public class Client {
void messageReceived(IMessage message) {
switch (message.getMessageType()) {
case TYPE_A:
// process type A
break;
case TYPE_B:
...
}
}
}
Each IMessage class needs to define an int getMessageType() method to return the appropriate code. Enums work just as well ints, and are more more elegant, IMO.
One option here is a handler chain. You have a chain of handlers, each of which can handle a message (if applicable) and then consume it, meaning it won't be passed further down the chain. First you define the Handler interface:
public interface Handler {
void handle(IMessage msg);
}
And then the handler chain logic looks like:
List<Handler> handlers = //...
for (Handler h : handlers) {
if (!e.isConsumed()) h.handle(e);
}
Then each handler can decide to handle / consume an event:
public class MessageAHandler implements Handler {
public void handle(IMessage msg) {
if (msg instanceof MessageA) {
//process message
//consume event
msg.consume();
}
}
}
Of course, this doesn't get rid of the instanceofs - but it does mean you don't have a huge if-elseif-else-if-instanceof block, which can be unreadable
What type of message system are you using?
Many have options to add a filter to the handlers based on message header or content. If this is supported, you simply create a handler with a filter based on message type, then your code is nice and clean without the need for instanceof or checking type (since the messaging system already checked it for you).
I know you can do this in JMS or the OSGi event service.
Since you are using JMS, you can basically do the following to register your listeners. This will create a listener for each unique message type.
String filterMsg1 = "JMSType='messageType1'";
String filterMsg2 = "JMSType='messageType2'";
// Create a receiver using this filter
Receiver receiverType1 = session.createReceiver(queue, filterMsg1);
Receiver receiverType2 = session.createReceiver(queue, filterMsg2);
receiverType1.setMessageHandler(messageType1Handler);
receiverType2.setMessageHandler(messageType2Handler);
Now each handler will receive the specific message type only (no instanceof or if-then), assuming of course that the sender sets the type via calls to setJMSType() on the outgoing message.
This method is built into message, but you can of course create your own header property and filter on that instead as well.
//Message.java
abstract class Message{
public abstract void doOperations();
}
//MessageA.java
class MessageA extends Message{
public void doOperations(){
//do concreteMessageA operations ;
}
}
//MessageB.java
class MessageB extends Message {
public void doOperations(){
//do concreteMessageB operations
}
}
//MessageExample.java
class MessageExample{
public static void main(String[] args) {
doSmth(new MessageA());
}
public static void doSmth(Message message) {
message.doOperations() ;
}
}
A Java 8 solution that uses double dispatch. Doesn't get rid of instanceof completely but does only require one check per message instead of an if-elseif chain.
public interface Message extends Consumer<Consumer<Message>> {};
public interface MessageA extends Message {
#Override
default void accept(Consumer<Message> consumer) {
if(consumer instanceof MessageAReceiver){
((MessageAReceiver)consumer).accept(this);
} else {
Message.super.accept(this);
}
}
}
public interface MessageAReceiver extends Consumer<Message>{
void accept(MessageA message);
}
With JMS 2.0 you can use:
consumer.receiveBody(String.class)
For more information you can refer here: