WebSocket in Spring Boot app Could not autowire error - spring-boot

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
}

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("*");
}

Related

#ConfigurationProperties, #Value not Working YET Passing the Tests

I have a strange problem reading configuration, none of solutions I've seen seem to work. Here is my code:
#SpringBootApplication
#EnableConfigurationProperties
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Here is my properties class
#Component
#ConfigurationProperties(prefix = "my")
#Data
#ToString
#NoArgsConstructor
#AllArgsConstructor
public class MyProperties {
private String host;
private int port;
}
I then use MyProperties class in my class using #Autowired:
#Autowired
private MyProperties props;
However, I'm getting null for my props object.
Strangely, this is passing the tests just perfectly:
#SpringBootTest
class ApplicationTests {
#Autowired
private MyProperties props;
#Test
void test_configuration() {
Assertions.assertEquals(props.getHost(), "xx.xx.xx.xx");//pass!
Assertions.assertEquals(props.getPort(), xxxxxx);//pass!
}
}
It has totally refused to work, and so has #Value injection. What could I be missing?
EDIT
Here's complete code of how I'm using #Autowired on MyProperties (I've included #Value which is also not working)
#Slf4j
#Component //also tried #Configurable, #Service
public class MyService {
#Autowired
private MyProperties props;
#Value("localhost")
public String host;
public void post() {
log.info(host + props);// =null and null
}
}
EDIT2
However, I've noticed that on the controller, it works perfectly okay:
#Slf4j
#RestController
#Service
public class Main {
#Autowired
private MyProperties props;
#Value("localhost")
private String host;
#GetMapping("/post")
public void post() {
log.info(host + props);//=it's perfect!
new MyService().post();// calling MyService - where #Autowired or #Value is failing
}
}
The reason this isn't working is because the MyService you're using isn't a Spring bean, but an instance you created by yourself (using new MyService()).
To make this work, you should autowire MyService, in stead of creating your own instance:
#Slf4j
#RestController
public class Main {
#Autowired // Autowire MyService
private MyService myService;
#GetMapping("/post")
public void post() {
myService.post(); // Use the myService field
}
}
For more information, look at this Q&A: Why is my Spring #Autowired field null.
UPDATE:
new MyService() is not a "spring bean", thus can't be auto-wired with anything!;)
1. Lombok
Some people use Project Lombok to add getters and setters automatically. Make sure that Lombok does not generate any particular constructor for such a type, as it is used automatically by the container to instantiate the object.
With "such a type" ConfigurationProperties is referred in Externalized Configuration (one of my favorite chapters;) More Exact: 2.8.1. JavaBean properties binding, at the bottom of second "Note!" ;)
So this could be a reason (for strange behavior).

#Autowired not working in spring boot

I am working on spring-boot application. In that application #Autowired is not working for some classes.
I have below classes in spring boot application:
#Component
public class SessionUser {
private static final String SESSION_PRINCIPAL = "session.principal";
#Autowired
private HttpSession httpSession;
//more code
}
#RestController
public class RefreshUserPermissionsRequestHandler {
#Autowired
TaskTrigger taskTrigger;
#Autowired
private SessionUser sessionUser;
}
public class LocalFileUserProviderImpl {
#Autowired
private SessionUser sessionUser;
//more code
}
In RefreshUserPermissionsRequestHandler, the SessionUser bean is injecting properly, but in LocalFileUserProviderImpl it's not working. Even I tried to annotate LocalFileUserProviderImpl with #RestController and #Controller but both are not working.
Can anyone help me what is going wrong here? Please let me know if any further info is required.

How should I wire in Spring 4.2 ApplicationEventPublisher with out using autowire using xml constructor arg?

I see there are lots of implementations, but how do I use the default implementation without using autowire and using xml config?
There are several option, you can use annotations, implement and interface or explicitly declare the dependency in xml or java config.
To get the ApplicationEventPublisher you can implement the ApplicationEventPublisherAware and implement the method, the ApplicationContext knows about this interface and will call the setter to give you the ApplicationEventPublisher.
public SomeClass implementens ApplicationEventPublisherAware {
private ApplicationEventPublisher publisher;
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher= applicationEventPublisher;
}
}
With annotation you can just put #Autowired on the field
public SomeClass implementens ApplicationEventPublisherAware {
#Autowired
private ApplicationEventPublisher publisher;
}
If it is a required dependency I would suggest using constructor injection, added benefit (IMHO) is that you can make the field final and that you cannot construct an invalid instance.
public SomeClass implementens ApplicationEventPublisherAware {
private final ApplicationEventPublisher publisher;
#Autowired
public SomeClass(ApplicationEventPublisher applicationEventPublisher) {
this.publisher= applicationEventPublisher;
}
When using Java Config you can simply create a #Bean annotated method which takes an ApplicationEventPublisher as argument.
#Configuration
public class SomeConfiguration {
#Bean
public SomeClass someClass(ApplicationEventPublisher applicationEventPublisher) {
return new SomeClass(applicationEventPublisher);
}
}
For XML you would need to autowire the constructor, you can specify this on the specific bean element.
<bean id="someId" class="SomeClass" autowire="constructor" />

org.springframework.data.repository always null into custom UserDetailManager

In my project I've a DAO defined as a org.springframework.data.repository
#RepositoryRestResource(path = "/user")
public interface SymtUserDAO extends CrudRepository<User, Long>{
...
It works fine in controllers by #Autowired (Dependency Injection):
#Controller
public class ProveController {
#Autowired
private SymtUserDAO dao;
...
I need to use it in my custom UserDetailsManager but in here the dao is always null
public class SymtUserManager implements UserDetailsManager {
#Autowired
private SymtUserDAO dao;
I don't know if it matters but I instantiate my custom UserDetailManager in the AuthorizationServerConfigurerAdapter's constructor
/**
* This class is used to configure how our authorization server (the "/oauth/token" endpoint)
* validates client credentials.
*/
#Configuration
#EnableAuthorizationServer
#Order(Ordered.LOWEST_PRECEDENCE - 100)
protected static class OAuth2Config extends
AuthorizationServerConfigurerAdapter
{
....
public OAuth2Config() throws Exception {
UserDetailsService svc = new SymtUserManager(...
Why my working DAO (test passed in the controller) doesn't work ( it is always null) in the UserDetailsManager? what I have to do to use the DAO ( repository ) also into the UserDetailsManager?
EDIT: zeroflagL is right. I updated answer according to comments.
Your SymtUserManager is not s spring bean. Therefore it's not created and handeled by Spring bean container. Therefore spring can't inject dependency there.
You can autowire it into OAuth2Config constructor and pass it as constructor parameter to SymtUserManager:
#Configuration
#EnableAuthorizationServer
#Order(Ordered.LOWEST_PRECEDENCE - 100)
protected static class OAuth2Config extends
AuthorizationServerConfigurerAdapter
{
private SymtUserDAO dao;
#Autowire
public OAuth2Config(SymtUserDAO dao) throws Exception {
UserDetailsService svc = new SymtUserManager(dao, ...

How do I autowire dependencies into Spring #Configuration instances?

I need to inject an object into my No XML Spring #Configuration object as follows:
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "web.client")
public class WebApplicationConfiguration extends WebMvcConfigurerAdapter {
private static final Logger log = LoggerFactory.getLogger(WebApplicationConfiguration.class);
#Inject
private MonitoringExceptionResolver resolver; // always null
#Override
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
log.debug("configuring exception resolvers");
super.configureHandlerExceptionResolvers(exceptionResolvers);
exceptionResolvers.add(new DefaultHandlerExceptionResolver());
exceptionResolvers.add(new AnnotationMethodHandlerExceptionResolver());
exceptionResolvers.add(new ResponseStatusExceptionResolver());
exceptionResolvers.add(resolver); // passing null ref here
}
}
Where MonitoringExceptionResolver is defined as follows:
#Service
public class MonitoringExceptionResolver implements HandlerExceptionResolver {
private final Counters counters;
#Inject
public MonitoringExceptionResolver(Counters counters) {
super();
this.counters = counters;
}
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
Counter counter = counters.getCounterFor(ex.getClass());
if(counter != null) {
counter.increment();
}
return null;
}
}
However, I get NPE later in the execution chain because the "resolver" field above is null, even if I use #Autowired.
Other classes are being successfully wired in elsewhere using component scanning. Why is it always null in the above? Am I doing something wrong?
#Inject and #Autowired should work very similar in Spring.
Make sure that *BeanPostProcessor in use is aware of MonitoringExceptionResolver: mark it as #Component and make is subject of some #ComponentScan or make a #Bean factory method is some #Configuration class in use.

Resources