2015-05-15 3 views
0

Я создаю 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 является нулевым, поскольку он аннотируется как компонент. Возможно, это корень моей проблемы.

+0

Вы не указали, где вы вводите 'CCDAuthorizingRealm' в свой вызывающий. – chrylis

+0

Нет, я сказал, что метод репозитория корректно работает при введении в класс Application. NPE возникает, когда я пытаюсь Autowire его в класс CCDAuthorizingRealm. Область аннотируется с @Component, поэтому, насколько мне известно, приложение должно найти ее, поскольку Spring Boot включает в себя компонентное сканирование. –

+0

Не должен ли компонент, реализующий интерфейс UserRepository, вместо аннотации '@ Component'? –

ответ

1

Я нашел ответ на свою проблему. Вот что я имел в моем applicationContext.xml:

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> 
    <property name="securityManager" ref="securityManager" /> 
    <property name="loginUrl" value="/login" /> 
    <property name="successUrl" value="/home" /> 
    <property name="unauthorizedUrl" value="/login" /> 
    <property name="filterChainDefinitions"> 
     <value> 
      /login = authc 
     </value> 
    </property> 
</bean> 

Проблемы с этой конфигурацией является то, что Логин URL был отфильтровывается. Исправление было просто изменить значение дома, как так:

<value> 
    /home = authc 
</value> 

который я считаю, устанавливает домашний URL позади фильтра, вместо этого.