Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JMS 3.0 [proposal] @MessageConverter Annotation and interface #259

Open
exabrial opened this issue Feb 13, 2020 · 7 comments
Open

JMS 3.0 [proposal] @MessageConverter Annotation and interface #259

exabrial opened this issue Feb 13, 2020 · 7 comments

Comments

@exabrial
Copy link

exabrial commented Feb 13, 2020

@dblevins I'm not sure if this is the correct place to raise an idea, please let me know. This is related to #243

After reading through the spec, one thing I think is missing is the concept of message body converters. JAX-RS has the ability to allow people to create JSON, XML, FormURLEconding, YAML, etc representations and automatically convert them to Java objects before the developer's code is called.

Why is this important?

Interaction with third party systems! For instance, if you're communicating with a ruby or python program at the other end of your message broker, you're definitely not going to be using Java serialization.

Another very important reason is viewing of messages on the Message Broker itself. Most message broker consoles allow you to peer into the contents of a message. Having first class support for encoding Java objects as JSON, XML, or whatever allows a developer to have them in a human readable format, more aligned with RESTful principles.

I would propose a @MessageConverter annotation that takes a class argument (works well for non-CDI environments). A CDI-ish way to bind a bean as a converter would also be nice so we can support injection on Converters.

@Destination("event.queue")
@DestinationType(Queue.class)
@MessageType(TextMessage.class)
@MessageConverter(type = MessageDirection.Ingress, class=JsonConverter.class)
public void recvEvent(MyEvent myEvent){
}
public interface JmsMessageConverter<T extends Message> {
	<K> K convert(T message, Class<K> targetClass);
}
public class JsonMessageConverter implements JmsMessageConverter<TextMessage> {
	@Override
	public <K> K convert(TextMessage message, Class<K> targetClass) {
		// TODO magic, convert textMessage containing json to Java object
		K myEvent = ....from json
		return  myEvent;
	}
}
@clebertsuconic
Copy link

what you have in mind? some sort of interceptor? where you would add such converter?

would it be like connection.addConverter(converter);

or would be at the consumer level?

some brokers have interceptor and plugins as a feature.. having this kind of thing could be a valid enhancement for the API if you are talking about interceptors.

but if what you have in mind is at the handler's level.. it could be something only towards MDBs? (that's a question really)

@exabrial
Copy link
Author

Actually now that you mention it, it is sort of like an interceptor, but really it modifying the message before it's handed off to the POJO... so kinda.

I think it would definitely be on a consumer level, not a connection level (maybe). You can have multiple consumers on a connection, and the current proposal is to have consumers/MDBs be more like POJOs. Since POJOs can take object arguments, I think it makes sense to have a step to marshal to/from an arbitrary format, much in the way JAX-RS marshals textual representations of objects into a Java objects before handing them off to user code

@exabrial
Copy link
Author

Opened pull request #264 :)

@dblevins
Copy link
Contributor

@exabrial Message conversion is definitely needed. I sent a message to the dev@ list titled 'Proposals repository'

When that gets created, let's have you redo the PR over there.

@hantsy
Copy link

hantsy commented Apr 28, 2023

I would like use the @Payload and @Header on arguments of message listener method directly. That means for the payload, if it is a POJO, use JSON-B to se/deserialize the data, like #247

If no any annotations, treat the listener arguments as subclass of Message.

@mattrpav
Copy link

mattrpav commented Dec 2, 2023

How about reducing the number of annotations down to one?

@MessageListener(destination="queue://event.queue", converter=MyEventConverter.class)
  1. Destination can use fully qualified (or default to queue)
  2. Message Type detection should be deferred to the converter. This would allow apps to dynamically switch between message types

@hantsy
Copy link

hantsy commented Dec 3, 2023

Make it is simple as possible.

  1. a global MessageConverter bean for JMS
  2. a converter property as @mattrpav
@JmsListener(
  destination="hello", // queue or topic name declared by CDI bean names, or by @JMSDestinationDefinition
  converter=MyEventConverter.class,
  acknowledgmentMode=...,
  replyDestination=..., // if return a none-void result
  condition="headers['xxx']=='yyyy' && payload.type!='test'" // an el to determine execute the method.
  properties={
     @JmsListener.Property("maxSessions", "100"), 
     @JmsListener.Property(name, value)
  }
)
void receiveMessage(@Payload OrderConfirmedEvent data, @Headers Map<String, Object> headers, @Header("someHeaderProperty") String someheader)
// or
void receiveMessage(OrderConfirmedEvent data) // treat as payload by default
// or
void receiveMessage(TextMessage message)
// or
OtherMessage receiveMessage(TextMessage message) // if set the replyDestination

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants