Issue
I have a spring boot app that I want to handle both rest calls and websockets. In my RestController I am able to define an instance of my GameUnitService as autowired, and it works as expected. ie: Gets populated and I can use it.
@Autowired private GameUnitService gameUnitService;
But when I try to autowire the above service in my websocket config, I get the error Could not autowire. No beans of 'GameUnitService' type found.. No error on the ApplicationContext.
However when I run the app after I remove the autowired from GameUnitService, the appContext is null when McpWebSocketConfig gets constructed.
@Configuration
@EnableWebSocket
public class McpWebSocketConfig implements WebSocketConfigurer {
private static final Logger log = LoggerFactory.getLogger(McpWebSocketConfig.class);
@Autowired private GameUnitService gameUnitService; //error: Could not autowire
@Autowired private ApplicationContext appContext; //this will end up null
public McpWebSocketConfig() {
//appContext is null
}
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new McpWebSocketHandler(), "/socket").setAllowedOrigins("*");
registry.addHandler(new McpWebSocketHandler(), "/").setAllowedOrigins("*");
}
I had also tried moving the GameUnitService into the handler, and while the bean error was no longer present, the gameUnitService is null.
public class McpWebSocketHandler extends AbstractWebSocketHandler {
@Autowired
private GameUnitService gameUnitService;
public McpWebSocketHandler() {
// gameUnitService is null
}
Solution
To find the bean (You will need the bean of GameUnitService for Autowire), you need to enable the behavior to scan your classpath which spring does not do by default.
@ComponentScan is the annotation to scan for components declared in your code . by default, @ComponentScan only scans the package and all the sub-packages of its annotated class. This means you need to tell the @ComponentScan to scan different packages, preferably your root package .
So you will need an additional annotation.
@ComponentScan(basePackageClasses = ApplicationLauncher.class)
ApplicationLauncher is the class annotated with @SpringBootApplication
Change your configuration class to read like so:
@Configuration
@EnableWebSocket
@ComponentScan(basePackageClasses = ApplicationLauncher.class)
public class McpWebSocketConfig implements WebSocketConfigurer {
private static final Logger log = LoggerFactory.getLogger(McpWebSocketConfig.class);
@Autowired private GameUnitService gameUnitService; //error: Could not autowire
@Autowired private ApplicationContext appContext; //this will end up null
public McpWebSocketConfig() {
//appContext is null
}
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new McpWebSocketHandler(), "/socket").setAllowedOrigins("*");
registry.addHandler(new McpWebSocketHandler(), "/").setAllowedOrigins("*");
}
Answered By - Kazi Asif Jawwad
Answer Checked By - Marilyn (JavaFixing Volunteer)