Я создаю REST API, используя Spring Boot с Shiro для аутентификации. Я получаю исключение NullPointerException, когда я пытаюсь Autowire репозиторий в моем коде домена. Автоустановка репозитория в другом месте не вызывает эту ошибку.Исключение Null Pointer When Autowiring Class
Вот моя санкционирования область:
@Component
public class CCDAuthorizingRealm extends AuthorizingRealm {
@Autowired
private UserRepository userRepository;
public CCDAuthorizingRealm() { }
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
AuthenticationInfo authenticationInfo = null;
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
String username = token.getUsername();
User user = null;
try {
user = userRepository.findByUsername(username);
} catch (Exception e) {
e.printStackTrace(System.err);
}
if (user != null) {
authenticationInfo = new SimpleAuthenticationInfo(
new SimplePrincipalCollection(username, username),
user.getPassword());
}
return authenticationInfo;
}
....
}
Исключение происходит, когда я пытаюсь вызвать метод findByUsername().
Вот код для репозитория, который я вводил.
@Transactional(readOnly=true)
@RepositoryRestResource(collectionResourceRel="users", path="users")
public interface UserRepository extends PagingAndSortingRepository<User, Long> {
User findByUsername(@Param("user") String user);
....
}
Чтобы проверить, я выполнил аутсорсинг репозитория в своем классе приложения и распечатал результаты, и у меня не было ошибок. Для полноты, вот код, который должен показать, что:
@SpringBootApplication
public class Application implements CommandLineRunner {
@Autowired
public UserRepository userRepository;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
public void run(String... strings) {
System.out.println("\nServer up\n");
User user = userRepository.findOne(new Long(1));
System.out.println(user.getUsername());
}
}
Любая помощь с благодарностью.
EDIT
Насколько я могу сказать, этот вопрос не является дубликатом, и ответ на другой вопрос не решить мою проблему. Я вставляю компонент и информирую контейнер IoC о компоненте, но автоустановка по-прежнему приводит к NPE.
Использование областей не помогает, поскольку мне нужен только один служебный объект. Конфигурируемый тег не нужен, потому что я выполняю аутоавтоматизацию и не нуждаюсь в создании нового объекта.
UPDATE
Вот где я звоню CCDAuthorizingRealm. Я новичок в использовании Сиро, но я уверен, что это правильно.
@RestController
@RequestMapping(produces="application/json")
public class AuthenticationController {
CCDAuthorizingRealm realm = new CCDAuthorizingRealm();
SecurityManager sm = new DefaultSecurityManager(realm);
public AuthenticationController() { }
/**
* Authenticate user with supplied credentials
*
* @param login - credentials
* @return success or failure message
*/
@RequestMapping(value = "/login", method = RequestMethod.POST, consumes="application/json")
public String login(@RequestBody LoginInfo login) {
String response;
UsernamePasswordToken token = new UsernamePasswordToken(
login.getUsername(),
login.getPassword(),
false);
try {
SecurityUtils.setSecurityManager(sm);
Subject currentUser = SecurityUtils.getSubject();
if (currentUser.isAuthenticated()) {
currentUser.logout();
}
currentUser.login(token);
response = token.toString();
} catch (AuthenticationException e) {
response = "Error: Incorrect username or password";
}
return response;
}
}
В настоящее время я пытаюсь создать новый экземпляр своего царства в контроллере. Я делаю это, потому что, когда я пытаюсь:
@Autowired
CCDAuthorizingRealm realm;
SecurityManager sm = new DefaultSecurityManager(realm);
Я хотел бы получить сообщение об ошибке выполнения при инициализации диспетчера безопасности, потому что он будет жаловаться на царство быть пустым. Однако я не понимаю, почему realm является нулевым, поскольку он аннотируется как компонент. Возможно, это корень моей проблемы.
Вы не указали, где вы вводите 'CCDAuthorizingRealm' в свой вызывающий. – chrylis
Нет, я сказал, что метод репозитория корректно работает при введении в класс Application. NPE возникает, когда я пытаюсь Autowire его в класс CCDAuthorizingRealm. Область аннотируется с @Component, поэтому, насколько мне известно, приложение должно найти ее, поскольку Spring Boot включает в себя компонентное сканирование. –
Не должен ли компонент, реализующий интерфейс UserRepository, вместо аннотации '@ Component'? –