0

this is actually working, but sonar complains about not using generics .. I tried my best to handle this but....

The Problem itself:

first of all I have an interface of a service:

public interface QueueMessageReceiver<T extends QueueMessage> {

    boolean onMessage(T queueMessage);

    Class<T> getQueueMessageType();

}

compiles nice an smooth with generics

second I have several Services that implements that interface I added one example, there are more (3 more)

@Component
public class DBoxCreateMessageReceiver implements QueueMessageReceiver<DBoxCreateMessageDTO> {

    @Autowired
    private DatabaseService databaseService;

    @Override
    public boolean onMessage(DBoxCreateMessageDTO queueMessage) {
        String uuid = databaseService.createMessage(queueMessage);
        if (uuid == null) {
            return false;
        }
        return true;

    }

    @Override
    public Class<DBoxCreateMessageDTO> getQueueMessageType() {
        return DBoxCreateMessageDTO.class;
    }

}

DBoxCreateMessageDTO extends of course QueueMessage

next I have a component which holds all Service implementations and decides on incoming message type which implementation has to deal with the current message

queueMessageReceivers gets all Implementing Components via Spring autowireing

but i have a compile error on the line: queueMessageReceiver.onMessage(queueMessage) which says: The method onMessage(capture#3-of ?) in the type QueueMessageReceiver<capture#3-of ?> is not applicable for the arguments (QueueMessage)

    @Autowired
    private QueueMessageReceiver<?>[] queueMessageReceivers;

    @SuppressWarnings("unchecked")
    @Override
    public boolean onMessage(QueueMessage queueMessage) {
        for (QueueMessageReceiver<?> queueMessageReceiver : queueMessageReceivers) {
            if (queueMessageReceiver.getQueueMessageType().equals(queueMessage.getClass())) {
                return queueMessageReceiver.onMessage(queueMessage);
            }
        }
        return false;
    }

what is the right way, to call the explicit implementation in this generic implementation?

If I remove all generics from the Classes it works pretty well, but sonar complains about code smells... So if someone knows how to deal with that WITH generics , would be help full.

Thanks a lot

beagle
  • 137
  • 1
  • 12

1 Answers1

0

Using <T extends QueueMessage> only guarantees you that you'll read a QueueMessage not any subtype. More info and explanation here Difference between <? super T> and <? extends T> in Java

Therefor the

boolean onMessage(T queueMessage);

should be

boolean onMessage(QueueMessage queueMessage);

and

@Autowired
private QueueMessageReceiver<?>[] queueMessageReceivers;

should be

@Autowired
private QueueMessageReceiver<? extends QueueMessage>[] queueMessageReceivers;

and in receivers, cast the object to what you need

@Override
    public boolean onMessage(DBoxCreateMessageDTO queueMessage) {
        String uuid = databaseService.createMessage(queueMessage);

to

@Override
    public boolean onMessage(QueueMessage queueMessage) {
        DBoxCreateMessageDTO d = (DBoxCreateMessageDTO) queueMessage;
        String uuid = databaseService.createMessage(d);
ALex
  • 673
  • 1
  • 6
  • 19