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.
Related
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("*");
}
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).
I got pretty confused now, I would like to use #Autowired MongoClient attribute in one of my Controller classes, but without success. The tricky part of it is that #Autowired is working from my #RestController.
#RestController
public final class WebController {
/** mongoClient */
#Autowired
private MongoClient mongoClient; <- here it's working ...
...
}
but:
#Controller
public final class MongoUsersDAO {
/** mongoClient */
#Autowired
private MongoClient mongoClient; <- not working ...
...
}
here I get null.
I do not think that the problem would be the component scan while my #SpringBootApplication is located at x.y.z, my #RestController at x.y.z.t and my #Controller at x.y.z.k packages, hence booth of them should be scanned by Spring.
(The Eclipse also marks my #Controller as a Spring class)
What else could be the problem then ?
Note:
If I add this to my #Controller it's working fine but the #Autowired still wount work:
#PostConstruct
public void init() {
System.out.println("INIT");
}
Note: In the mentioned MongoUsersDAO the autowired thing is not working at all, I've tried to get a simple property as well from the application.properties, without success.
Your problem occured because you have called new MongoUserDAO() inside your WebController class as you mentioned in the comment below your question. If you instantiate an object by hand and you have field annotated with #Autowired then this field won't be instantiated with expected instance.
Inject MongoUsersDAO directly to your WebController class as shown below, Spring will handle injecting MongoClient to MongoUserDAO class for you.
WebController :
#RestController
public final class WebController {
/** Service/Repository class*/
#Autowired
private MongoUsersDAO dao;
#GetMapping("/all")
public String getAll(){
dao.callSomeMethod();
}
}
MongoUsersDAO:
#Repository
public final class MongoUsersDAO {
/** mongoClient */
#Autowired
private MongoClient mongoClient;
...
}
I'm trying to autowire a service in my rest controller like these:
rest controller:
#ApplicationPath("/greetings")
#Component(immediate = true, service = Application.class)
public class RestControllerApplication extends Application {
#Autowired
private MyService myService;
public Set<Object> getSingletons() {
return Collections.<Object>singleton(this);
}
#POST
#Path("/getUploadType")
#Produces("application/json")
public JsonObject getUploadType() {
...
myService.findUploadTypes();
...
}
}
service:
#Component
public class UploadService {
private static final Logger log = Logger.getLogger(UploadService.class);
#Autowired
private OneDAO oneDAO;
#Autowired
private TwoDAO twoDAO;
...
}
but in my rest controller, uploade service is null. Why?
Spring uses its own set of annotations. Instead of #Path plus #[HTTP method] you should use #RequestMapping.
You can find an example here
There is also an extended example here
I have got access to my bean, with these few line of code:
WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();
MyService myService = context.getBean(MyService.class);
You are declaring a UploadService as #Component but trying to autowire a MyService instance in your controller...
There are two options: you can declare correct service type in your controller or you can make UploadService inheriting from MyService.
I have a problem with my custom Spring Security PermissionEvaluator. So,
the CustomPermissionEvaluator needs that service to do its work.
#Service
public class MyService {
// methods....
}
And here's the evaluator itself.
public class CustomPermissionEvaluator implements PermissionEvaluator {
private MyService service;
public CustromPermissionEvaluator( MyService service ) {
this.service = service;
}
// hasPermission methods...
}
And here's configurations
#Configuration
#EnableGlobalMethodSecurity( prePostEnabled = true )
public class MethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {
#Autowired
private MyService service;
#Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
CustomPermissionEvaluator permissionEvaluator = new CustomPermissionEvaluator( service );
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
expressionHandler.setPermissionEvaluator( permissionEvaluator );
return expressionHandler;
}
}
So when #PreAuthorize( "hasPermission( ... )" ) should be invoked, nothing happens. But when I put that dependency straight to the CustomPermissionEvaluator's constructor, without ApplicationContext and autowiring, everything works perfect. I have printed service object to the log file and it is not null. So, what is wrong?
I had this same problem and had to use the #Lazy annotation:
#Lazy #Autowired
private MyService service;
It appears the security stuff is bootstrapped before the rest of the Spring config. I guess #Lazy allows a reference to be injected but not actually resolved until used.
After spending hours , this is the only solution solution worked for me. thanks #hvgotcodes.
so what i did is
annotate the CustomPermissionEvaluator with #component.
and annotate MyService with #Lazy #Autowired
#Component
Class CustomPermissionEvaluator {
#Lazy #Autowired
private MyService service;
}
If I user the #Lazy #Autowired in configuration MethodSecurityConfiguration then it does not worked