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

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, ...

Related

WebSocket in Spring Boot app Could not autowire error

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

Spring Boot and/or Vaadin autowiring behaviors I do not understand

I am working on a Spring Boot application an am having issues where items are not being auto-wired as I expect. What is adding to this confusion is that I have another Spring Boot application that also happens to involve Vaadin. In this application, auto-wiring seems more "automated".
Here is what I mean. In the Vaadin app, a #Service object, is injected into a Vaadin "view" with little effort. Additionally, the service object itself is injected with a Repository object. I need to do almost nothing to make this all happen.
In my other non-Vaadin application, I set up the code to do similar things, but in this case, it does not work. The application fails to start and complains as below:
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in com.mycompany.app.backend.service.TaskMasterService required a bean of type 'com.mycompany.app.backend.repository.TaskMasterRepository' that could not be found.
Action:
Consider defining a bean of type 'com.mycompany.app.backend.repository.TaskMasterRepository' in your configuration.
I assume that I'm missing some configuration somewhere, or that the Vaadin application has "extra" functionality added that makes this work.
Here are snippets of the Vaadin application:
TasksView.java:
#Route("main")
public class TasksView extends VerticalLayout {
private final TaskService taskService;
private final TaskNoteService noteService;
public TasksView(TaskService taskService, TaskNoteService noteService) {
this.taskService = taskService;
this.noteService = noteService;
}
...
}
TaskService.java:
#Service
#Transactional
public class TaskService {
private TaskRepository taskRepo;
public TaskService(TaskRepository taskRepo) {
this.taskRepo = taskRepo;
}
...
}
TaskRepository.java:
public interface TaskRepository extends JpaRepository<Task, Long>, TaskRepositoryCustom {
...
}
I don't need to #Autowired anything or provide a #Configuration class or define a #Bean anywhere. It just works.
Here are some snippets from the non-Vaadin application:
IngesterRunner.java:
#Service
public class IngesterRunner {
private TaskMasterService tmService;
private TaskRelationshipService trService;
private VariantDetailService vdService;
public IngesterRunner(TaskMasterService tmService, TaskRelationshipService trService,
VariantDetailService vdService) {
this.tmService = tmService;
this.trService = trService;
this.vdService = vdService;
}
...
}
TaskMasterService.java:
#Service
#Transactional
public class TaskMasterService {
private final TaskMasterRepository repo;
public TaskMasterService(TaskMasterRepository repo) {
this.repo = repo;
}
...
}
TaskMasterRepository.java:
package com.mycompany.app.backend.repository;
public interface TaskMasterRepository extends JpaRepository<TaskMaster, Long> {
}
JPAConfiguration.java:
#Configuration
#EnableJpaRepositories(basePackages = "com.mycompany.app.backend.repository", transactionManagerRef = "jpaTransactionManager")
#EnableTransactionManagement
public class JPAConfiguration {
private static final String[] ENTITY_PACKAGES_TO_SCAN = {
"com.mycompany.app.backend.entity" };
...
}
I don't understand what is different about the first application that makes auto-wiring work so much more smoothly. Is it something I have in my pom.xml? Is it some sort of extra support provided by Vaadin?
If requested, I can try to include the POM files if that will help.
Update:
I have tried a number of suggestions, but none seem to have any effect. I added #Autowired annotations, but it makes no difference.
#Service
public class IngesterRunner {
private TaskMasterService tmService;
private TaskRelationshipService trService;
private VariantDetailService vdService;
public IngesterRunner(#Autowired TaskMasterService tmService,
#Autowired TaskRelationshipService trService, #Autowired VariantDetailService vdService) {
this.tmService = tmService;
this.trService = trService;
this.vdService = vdService;
}
...
}
#Service
#Transactional
public class TaskMasterService {
private final TaskMasterRepository repo;
public TaskMasterService(#Autowired TaskMasterRepository repo) {
this.repo = repo;
}
...
}
#Repository annotation in TaskMasterRepository.java, like
#Repository
public interface TaskMasterRepository extends JpaRepository<TaskMaster, Long> {
}

#Autowired is not working for CrudRepository

I have problems injecting a repository, there is no problem injecting a Service. Im injecting the repo in a service:
#Service
public class AuthorService {
#Autowired
private AuthorRepository repository;
public String getAll(){return "XXXXX";}
}
and the repository is:
public interface AuthorRepository extends CrudRepository<Author, Integer> {
}
And my code structure is the following:
with the main class:
#SpringBootApplication
public class AuthorBookGraphqlApplication {
public static void main(String[] args) {
SpringApplication.run(AuthorBookGraphqlApplication.class, args);
}
}
the error is thrown on start:
Field repository in com.author.book.graphql.demo.service.AuthorService required a bean of type 'com.author.book.graphql.demo.repository.AuthorRepository' that could not be found.
Update code as below
Spring will automatically import the beans into the container and inject to dependencies with these annotations.
#Component, #Controller, #Service and #Repository - Helps to define the beans so the container is aware of them and can inject them for you with #Autowired.
#Autowired - Handles only wiring part here.
#Service
public class AuthorService {
#Autowired
private AuthorRepository repository;
public String getAll(){return "XXXXX";}
}
#Repository
public interface AuthorRepository extends CrudRepository<Author, Integer> {}
Before class AuthorRepository, Let's put more annotation #Repository.

Spring Boot - Autowired MongoClient

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;
...
}

Why spring #autowired is null?

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.

Resources