JAM - examples

Printer-friendly versionPrinter-friendly version
How to use the JAM framework

 

To receive these new LongOffers we implement the new LongConsumer interface in any class we like and subscribe that LongConsumer in the same manner as the TextConsumer before. Then we can fire our first LongOffer:

Publish.offer(new LongOffer(new Long(100)));

Of course, in a real-world scenario we do not just send a Long or the like, because it does not provide any context information to the receiver. We rather implement any kind of specialized bean or business object. But thanks to the possibility to implement own announcement types, we can also use these own announcement types as specialized beans by adding the properties that provide context information accordingly.

 

In case we already have a specialized object type that makes sense for receivers we might want to announce it directly without any added boilerplate code. Moreover, we might have individual announcements which are published just seldom and therefore the effort of implementing an own announcement type feels disproportionate perhaps. Fortunately, JAM let us announce any arbitrary object in a generic manner:

Publish.offerThat(new Long(100));

We just used Long again to keep this example simple. To receive that Long object we need again, you can guess it already, a Consumer. This time with a small, but important change: we do not implement our own new Consumer interface, but we implement the interface GenericConsumer, which requires to implement additionally the operation getContentType().

public class OurLongProcessor implements GenericConsumer<Long, OurLongProcessor> {
    
    @Override
    public Class<Long> getContentType() {
        return Long.class;
    }

    
    @Override
    public boolean acceptsSubtopics() {
        return true;
    }
    
    @Override
    public void accept(Topic topic, GenericOffer<Long, OurLongProcessor> offer) {
        Long long = offer.getContent();
        // we process "long" here
    }
    
}

We implemented the GenericConsumer interface, providing as generic parameters the type of object we receive and the type of our own implementation. The method getContentType() returns the type of object we receive, because we do not receive a specialized announcement type and with the content type we tell JAM which type of object we want to receive.

 

As you can see, we can publish any arbitrary object as convenient as a simple text and same type safe as well. So why should we implement own announcements anyway? The generic way of publishing objects has a loss of performance. Just a small loss, but if we publish that way a huge number of objects, that can play a role depending on our use case and overall architecture. That loss of performance can be mitigated in most cases by publishing concurrently:

PublishParallel.offerThat(new Long(100));

Therefore it is recommended to implement own announcement types for those content types that we publish often at runtime, unless we are sure it does not play any role, and to use the generic way of publishing for those content types which are fired just seldom.

As an aside: JAM tries to provide us type safety all the way and the best performance possible for its compex functionality, and therefore tries to avoid to use reflections internally where it might impact the performance, instead using Java generics in an extreme manner (kept under the hood, so won't bother us), shifting performance costs from the runtime to the compile time. For the generic way of publishing as seen above that is not fully possible anymore, because it needs some sort of rocket science algorithm   wink   for the automatic detection of (nested) generic parameters in depth at runtime. Hence it looses performance in comparison to defined announcements.

 

Pages