IKavaldzhiev
IKavaldzhiev

Reputation: 13

@Autowired does not inject Spring Data JPA Repository - NullPointerException

I'm doing a GWTP project and use Spring Data JPA for a connection with an oracle database. I've read several tutorials in which a repository interface is used directly without the use of implementation. It was @Autowired where needed and it worked fine. I've tried to use the same strategy but it seems the @Autowired annotation is not working at all.

Here is my Repository :

@Repository
public interface BugRepository extends JpaRepository<Bug, Long> {
  List<Bug> findAll();
.....
}

I try to inject it with @Autowired in my service implementation (I use RESTful services) :

@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/bugs")
@Component
public class BugServiceImpl{
    @Autowired
    private BugRepository bugRepository;

    @GET
    @Path("/findAll")
    public List<Bug> findAll() {
    return bugRepository.findAll();
    }
}

Here is my Entity :

@Entity
@Table(name = "BUGS")
@SequenceGenerator(name = "BUG_SEQUENCE", sequenceName = "BUG_SEQUENCE")
public class Bug implements Serializable { 

   @Id
   @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "BUG_SEQUENCE")
   @Column(name="BUG_ID")
   private Long bugId;

   @Column(name="BUG_NAME")
   private String bugName;

   @OneToOne
   @PrimaryKeyJoinColumn
   @Column(name="CREATED_BY")
   private User createdBy;

   @OneToOne
   @PrimaryKeyJoinColumn
   @Column(name="ASSIGNED_TO")
   private User assignedTo;

   @Column(name="CREATION_DATE")
   private Date creationDate;

   @Column(name="LAST_UPDATE_DATE")
   private Date lastUpdateDate;

   @Column(name="BUG_COMMENT")
   private String bugComment;

   @OneToOne(cascade = CascadeType.ALL, optional = false, fetch = FetchType.EAGER, orphanRemoval = true)
   @PrimaryKeyJoinColumn
   @Column(name="PRIORITY_ID")
   private Priority priority;

   @OneToOne
   @PrimaryKeyJoinColumn
   private Status status;

   public Bug() {
   }
}

I also have applicationContext.xml and persistence.xml in main/resources/META-INF. Here is my 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:tx="http://www.springframework.org/schema/tx"
   xmlns:jpa="http://www.springframework.org/schema/data/jpa"
   xmlns:jdbc="http://www.springframework.org/schema/jdbc"
   xmlns:p="http://www.springframework.org/schema/p"

   xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
   http://www.springframework.org/schema/context
   http://www.springframework.org/schema/context/spring-context-3.0.xsd
   http://www.springframework.org/schema/tx
   http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
   http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans.xsd
   http://www.springframework.org/schema/data/jpa
   http://www.springframework.org/schema/data/jpa/spring-jpa-1.0.xsd
   http://www.springframework.org/schema/jdbc
   http://www.springframework.org/schema/jdbc/spring-jdbc.xsd">

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

<jpa:repositories base-package="com.edu.server.repositories" />

<context:annotation-config />

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="oracle.jdbc.OracleDriver" />
    <property name="url" value="***"/>
    <property name="username" value="***"/>
    <property name="password" value="***"/>
</bean>

<!-- EntityManagerFactory -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
      p:packagesToScan="com.edu.shared.entity"
      p:dataSource-ref="dataSource"
>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="generateDdl" value="true" />
            <property name="showSql" value="false" />
        </bean>
    </property>
</bean>

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

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

My persistence.xml :

<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_2_0.xsd"
         version="2.0">

<!-- oracle -->

<persistence-unit name="oracle">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>

    <class>com.edu.server.service.BugServiceImpl</class>
    <class>com.edu.server.repositories.BugRepository</class>
    <class>com.edu.shared.entity.Bug</class>

    <properties>
        <property name="hibernate.archive.autodetection" value="class" />
        <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
        <property name="hibernate.connection.driver_class" value="oracle.jdbc.OracleDriver" />
        <property name="hibernate.connection.url" value="***" />
        <property name="hibernate.connection.username" value="***" />
        <property name="hibernate.connection.password" value="***" />
        <property name="hibernate.flushMode" value="FLUSH_AUTO" />
        <property name="hibernate.hbm2ddl.auto" value="update" />
    </properties>
</persistence-unit>

And finally the exception I get is :

java.lang.NullPointerException
com.edu.server.service.BugServiceImpl.findAll(BugServiceImpl.java:39)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:606)
...

When I debug the code and put a breakpoint to the autowired repository it appears to be null so I suppose it's not injected properly and that's why invoking the method findAll fires the NullPointerException. So, why do you think the @Autowired annotation is not working?

Upvotes: 0

Views: 11040

Answers (3)

IKavaldzhiev
IKavaldzhiev

Reputation: 13

I want to thank all for the help. I solved my problem. There were problems in my configuration files.

First of all, I really didn't need any persistence.xml because I've created a dataSource bean in my applicationContext.xml which contains all of the needed information regarding the connection with my database. You shouldn't mix the both things, I suppose.

Secondly, you should properly configure the link between Spring and Jersey. I had to add some new dependencies in my pom.xml which were needed for linking Spring and Jersey (there is a jersey-spring3 dependency which I didn't know existed). So, now all of the dependencies I use, concerning Spring and Jersey are these:

       <dependency>
            <groupId>javax.ws.rs</groupId>
            <artifactId>javax.ws.rs-api</artifactId>
            <version>${javax.rs.version}</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet</artifactId>
            <version>${jersey.version}</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-server</artifactId>
            <version>${jersey.version}</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-json-jackson</artifactId>
            <version>${jersey.version}</version>
        </dependency>

        <dependency>
            <groupId>org.fusesource.restygwt</groupId>
            <artifactId>restygwt</artifactId>
            <version>1.4</version>
       </dependency>

       <dependency>
           <groupId>io.spring.platform</groupId>
           <artifactId>platform-bom</artifactId>
           <version>1.1.2.RELEASE</version>
           <type>pom</type>
           <!--<scope>import</scope>-->
           <scope>compile</scope>
       </dependency>

        <!-- DataSource (HikariCP) -->
        <dependency>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
            <version>2.2.5</version>
        </dependency>

        <!-- JPA Provider (Hibernate) -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>4.3.8.Final</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>1.10.2.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc6</artifactId>
            <version>12.1.0.2</version>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>4.3.8.Final</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-orm</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.glassfish.jersey.ext</groupId>
        <artifactId>jersey-spring3</artifactId>
        <version>${jersey.version}</version>
        <exclusions>
            <exclusion>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
            </exclusion>
            <exclusion>
            <groupId>org.springframework</groupId>
                <artifactId>spring-web</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.springframework</groupId>
                <artifactId>spring-beans</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

In addition, I had to configure my web.xml so that Jersey could read the applicationContext.xml. Without configuring my web.xml the applicationContext.xml was useless and that's why the annotations and the connection with the database didn't work. Here is my web.xml :

 <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns="http://java.sun.com/xml/ns/javaee"
          xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
          version="2.5">

        <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
        </listener>

        <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        </welcome-file-list>

        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:META-INF/applicationContext.xml</param-value>
        </context-param>

        <servlet>
            <servlet-name>jersey-serlvet</servlet-name>
            <servlet-class>
             org.glassfish.jersey.servlet.ServletContainer
            </servlet-class>
        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>com.edu</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
        </servlet>

        <servlet-mapping>
            <servlet-name>jersey-serlvet</servlet-name> 
            <url-pattern>/rest/*</url-pattern> 
        </servlet-mapping>
    </web-app>

As far as I understood the ContextLoadListener makes sure the web configuration "listens" for other configuration xml files and that's how the applicationContext.xml is now read and used. And with these settings

 <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>com.edu</param-value>

I make sure that my packages would be scanned for @Provider and @Path annotations and without these piece of my code my services would not be active. More about this Provider Packages setting can be read here :

https://jersey.java.net/apidocs/2.23.2/jersey/org/glassfish/jersey/server/ServerProperties.html#PROVIDER_PACKAGES

I hope my issue and this answer are useful for all with similar configuration problems.

Upvotes: 0

Mechkov
Mechkov

Reputation: 4324

First problem that i see is you have annotated your interface with @Repository

You shouldn't do that, but as follows:

//no annotation here
public interface BugRepository extends JpaRepository<Bug, Long> {
  List<Bug> findAll();
.....
}

Secondly, make sure your BugRepository interface is in the package below, or else it wont work:

<jpa:repositories base-package="com.edu.server.repositories" />

Third thing i noticed is in your persistance.xml, you have noted NOT only @Entity beans, but @Service and a @Repository. You are supposed to only have @Entity beans (which are to be managed)

Lastly, you seem to be mixing Spring and Jersey, so make sure you have your Spring container (application/web context) properly set up, so it can manage (inject) your beans/repos/services.

Upvotes: 0

Petar Petrov
Petar Petrov

Reputation: 596

I think you're mixing two ways of Spring/JPA configuration. Last time when i configured Spring/JPA project with XML I use only DataSource bean without persistence.xml configuration for connection to the database. I can suggest you to read the official documentation of Spring Data. The community has one of the best documentation.

http://docs.spring.io/spring/docs/current/spring-framework-reference/html/orm.html

Upvotes: 1

Related Questions