jakartaee / messaging

Jakarta Messaging
https://eclipse.org/ee4j/messaging
Other
39 stars 32 forks source link

MessagingClient #249

Open dblevins opened 4 years ago

dblevins commented 4 years ago

TODO

Proposals

https://github.com/tomitribe/jms-proposals/blob/master/messaging-client/src/test/java/org/example/BuildAndNotify.java

Related

t1 commented 3 years ago

I wrote on the mailing list:

CDI events would be one way, but I think this introduces too many technical details into the business domain objects. I’d prefer to take a similar approach as MP REST Client did: use an interface to describe the required business functionality, both on the sending and receiving side; and annotations (that can be extracted into stereotypes) for the technical details, when necessary. The main difference to MP REST Client is that messages don’t directly return a value ;-)

This had already been proposed for the JMS 2.0 spec back in 2011, but it was probably ahead of its time. For details see https://github.com/t1/message-api

@OndroMih wrote:

I think what you describe is very similar to https://github.com/eclipse-ee4j/jms-api/issues/249. The description of that github issue links to a similar proposal, which is newer and possibly more modern. Let's discuss on that github issue. Or, if emails are better for you, can you start a new thread about new annotation-based API?

I'm glad to continue the discussion here.

OndroMih commented 3 years ago

Hi @t1 ,

Did you review the proposal in https://github.com/tomitribe/jms-proposals/blob/master/messaging-client/src/test/java/org/example/BuildAndNotify.java? Do you think it's viable and close to what you expect and described on the mailing list?

There's an interface NotificationsClient, which contains annotations with the configuration. the builde rMessagingClientBuilder is used in the BuildAndNotify class to instantiate the client that implements the NotificationsClient interface. Calling methods on this client will send a message to a topic configured by the annotation.

I don't like the annotation names (the "Listener" part) because they indicate that the annotation is valid only for message receivers (MDBs). Using a "Listener" to send messages isn't intuitive. But otherwise I like it, it's very similar to how MicroProfile REST Client uses JAX-RS server annotations on a client interface.

It's worth noting that this proposal doesn't depend on CDI at all. The JMS implementation is responsible for scanning the annotations and providing the builder that is capable of creating the clients. In a CDI container, it would make sense to be able to inject the client instead of using the builder, but that would be optional and isn't covered by this proposal.

t1 commented 3 years ago

The type of API that I've had in mind would even more hide the fact that we are doing messaging, i.e. I'd define a business interface:

@MessageApi
public interface BuildNotification {
    public void statusUpdate(
        @MessageProperty URI buildId,
        @MessageProperty BuildStatus buildStatus,
        BuildTiming timing,
        BuildDetails details);
}

The message topic name is by default derived from the fully qualified interface name and the method name, but can be overridden with an annotation. The @MessageProperty parameters get their names by default from the javac parameter names (I still think this should be on by default), while the message body is a JSON object containing the other parameters:

{
    "timing": {
        "start": "2021-05-15T18:01:32",
        ...
    },
    "details": {
        "progress": 0.87,
        "stage": "AT",
        ...
    },
}

A sender simply injects that interface and calls the method:

@Inject BuildNotification buildNotification;

public void builder() {
    ...
    buildNotification.statusUpdate(build.getId(), build.getStatus(), build.getTiming(), build.getDetails());
    ...
}

The receiver defines a method with a subset of the parameters defined by the sender:

@MessageApi
public void statusUpdate(@MessageProperty URI buildId, BuildDetails details) {
    System.out.println("build " + buildId + " is " + details.getProgress()*100 + "% done");
}
OndroMih commented 3 years ago

OK. This sounds close to what is proposed in the tomitribe/jms-proposals repository, and specifies some default behavior so that annotations are applied only if needed.

To get things moving, I've copied the proposal from the tomitribe/jms-proposals repository and submitted it as a pull request here: https://github.com/eclipse-ee4j/jms-propsals/pull/2.

@t1 , can you compile a similar project for your proposal and submit is as a similar PR? Then we could compare them side by side and have a conversation about your proposal in your PR.