Spring Data JPA + OpenJPA @autowired repository field null in webapp but fine for junit [duplicate]

StackOverflow https://stackoverflow.com/questions/21871497

  •  13-10-2022
  •  | 
  •  

سؤال

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p" xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beans   
http://www.springframework.org/schema/beans/spring-beans.xsd   
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd   
http://www.springframework.org/schema/aop    
http://www.springframework.org/schema/aop/spring-aop.xsd   
http://www.springframework.org/schema/tx    
http://www.springframework.org/schema/tx/spring-tx.xsd    
http://www.springframework.org/schema/cache    
http://www.springframework.org/schema/cache/spring-cache.xsd    
http://www.springframework.org/schema/data/jpa    
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">    

<context:annotation-config />

<context:component-scan base-package="com.company" />

<!-- 定义实体管理器工厂 -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="eipjpa" />
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<tx:annotation-driven transaction-manager="transactionManager" />

<jpa:repositories base-package="com.company.repository" />

persistence.xml

    <?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence  
    http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
    version="1.0">
        <persistence-unit name="eipjpa" transaction-type="RESOURCE_LOCAL">
            <provider>  
                org.apache.openjpa.persistence.PersistenceProviderImpl  
            </provider>
            <class>com.company.domain.User</class>
            <properties>
                <property name="openjpa.ConnectionURL" value="jdbc:mysql://localhost:3306/eipdb?characterEncoding=utf-8" />
                <property name="openjpa.ConnectionUserName" value="root" />
                <property name="openjpa.ConnectionPassword" value="passw0rd" />
                <property name="openjpa.Log" value="DefaultLevel=WARN, Runtime=INFO, Tool=INFO, SQL=TRACE" />
                <property name="openjpa.DynamicEnhancementAgent" value="true"/>
            </properties>
        </persistence-unit>
    </persistence>  

Domain Class - User (omit constructor, get, set)

@Entity
@Table(name = "user")
public class User implements java.io.Serializable{

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id;
    private String username;
    private String password;
    private String type;

}

Repository interface

@Repository
public interface UserRepository extends CrudRepository<User, Integer> {

    List<User> findUserByUsernameAndPassword(String username, String password);
}

UserService Interface

public interface UserService {

    void saveUser(User user);

    User findUserById(Integer id);

    void updateUser(User user);

    void deleteUserById(Integer id);

    public boolean checkUserLogin(User user);
}

Implementation of UserService

@Service("userService")
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Override
    @Transactional
    public void saveUser(User user) {
        userRepository.save(user);

    }

    @Override
    @Transactional(readOnly = true)
    public User findUserById(Integer id) {
        return userRepository.findOne(id);
    }

    @Override
    @Transactional
    public void updateUser(User user) {
        userRepository.save(user);
    }

    @Override
    @Transactional
    public void deleteUserById(Integer id) {
        userRepository.delete(id);
    }

    @Override
    @Transactional(readOnly = true)
    public boolean checkUserLogin(User user) {
        System.out.println(userRepository);
        return userRepository.findUserByUsernameAndPassword(user.getUsername(), user.getPassword()).size() == 0 ? false
                : true;
    }

Problem

When I test it by junit, it works fine.

@Test
public void login() {
    User user = new User();
    user.setUsername("Annie");
    user.setPassword("passw0rd");
    UserService service = ctx.getBean(UserService.class);
    Assert.assertTrue(service.checkUserLogin(user));
    user.setPassword("password");
    Assert.assertFalse(service.checkUserLogin(user));
}

But when I try it in webapp, below error occurred... I checked that the userRepository in UserServiceImpl class is null... I don't know how to fix it...

Feb 19, 2014 12:25:53 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/EIP] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
java.lang.NullPointerException
    at com.company.service.impl.UserServiceImpl.checkUserLogin(UserServiceImpl.java:53)
    at com.company.controller.UserController.login(UserController.java:30)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:436)
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:424)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:409)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1044)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:313)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
    at java.lang.Thread.run(Thread.java:695)
هل كانت مفيدة؟

المحلول

Spring will never leave an injection target like this one

@Autowired
private UserRepository userRepository;

null. If it can't resolve the dependency it will throw all sorts of exceptions.

In other words, in your web application, Spring must not be involved in creating your UserServiceImpl object. I'm going to guess you are creating it yourself with new. You should instead be injecting it with @Autowired or at least getting it from the ApplicationContext directly (bad practice).

In your test case however, you are clearly getting the instance from the ApplicationContext, so it is a managed bean and its dependencies have been resolved.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top