Search code examples
javaspring-data-restspring-hateoas

Constructor injection preventing custom resource processing


In my (non-trivial) Spring Boot 1.5.4 application with Spring Data REST and HATEOAS leveraging Spring websockets, I have some custom resource processors, some custom controllers, and some custom repositories. Sadly, when I use constructor injection in one particular Spring @Service class for a MessageSendingOperations dependency, my custom resource processors no longer get invoked. Reverting the constructor injection restores the execution of my custom resource processors, i.e. reverting from:

private final MessageSendingOperations<String> messageTemplate;

@Autowired
public ChannelHandler(MessageSendingOperations<String> messageTemplate) {
    this.messageTemplate = messageTemplate;
}

to:

@Autowired
private MessageSendingOperations<String> messageTemplate;

"re-enables" my custom resource processors which results in a null messageTemplate. So, there's a problem somewhere...but where??? Any ideas how to track this down?


Solution

  • Have you tried making messageTemplate a lazily injected proxy? For example:

    public ChannelHandler(@Lazy MessageSendingOperations<String> messageTemplate) {
        this.messageTemplate = requireNonNull(messageTemplate, "messageTemplate");
    }
    

    From the Javadoc:

    In addition to its role for component initialization, this annotation may also be placed on injection points marked with Autowired or Inject: In that context, it leads to the creation of a lazy-resolution proxy for all affected dependencies, as an alternative to using ObjectFactory or Provider.

    This usually affects the initialization order of your beans, in this case allowing ChannelHandler to be initialized before MessageSendingOperations. Without @Lazy, MessageSendingOperations will be initialized first.

    Also: as of Spring 4.3, @Autowired is no longer required for single argument constructors.

    +1 for using constructor injection and final fields.