2

我刚刚开始学习 JAX-RS,并正在尝试修改 O'Reilly RESTful Java with JAX-RS 书中的一些示例。我遇到了一个问题,当我尝试将 XML 文件发布到我的 JAX-RS 服务之一时,我得到了一个空指针异常。我要发布的特定资源使用 JPA 将信息持久保存到 derby 数据库。在阅读了其他几个问题/回复和教程后,我确信我的代码是正确的,但也许我缺少一些配置。即使我有适当的注释,似乎由于某种原因没有注入实体管理器。对我的问题的任何意见将不胜感激。请参阅以下我认为有用的项目摘录:

持久性.xml

 <?xml version="1.0" encoding="UTF-8"?>
   <persistence version="2.0" 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">
   <persistence-unit name="jpa-example" transaction-type="JTA">
    <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
    <jta-data-source>java:comp/env/jdbc/DerbyConnection</jta-data-source>
    <class>com.example.persistence.UserEntity</class>
    <class>com.example.persistence.SearchEntity</class>
    <properties>
      <property name="openjpa.TransactionMode" value="managed"/>
      <property name="openjpa.ConnectionFactoryMode" value="managed"/>
      <property name="openjpa.LockTimeout" value="30000"/>
      <property name="openjpa.jdbc.TransactionIsolation" value="read-committed"/>
      <property name="openjpa.Log" value="TRACE"/>
      <property name="openjpa.jdbc.UpdateManager" value="operation-order"/>
     </properties>
   </persistence-unit>
 </persistence>

服务器.xml

<server description="new server">

    <!-- Enable features -->
    <featureManager>
        <feature>jsp-2.2</feature>
        <feature>jdbc-4.0</feature>
        <feature>jpa-2.0</feature>
        <feature>localConnector-1.0</feature>
        <feature>jaxrs-1.1</feature>
        <feature>ejbLite-3.1</feature>
    </featureManager>

    <httpEndpoint host="localhost" httpPort="9080" httpsPort="9443" id="defaultHttpEndpoint"/>


    <jdbcDriver id="derbyJDBCDriver">
        <library name="DerbyLib">
            <fileset dir="/Users/jackson/Documents/db-derby-10.10.1.1-bin/lib" includes="derby.jar"/>
        </library>
    </jdbcDriver>
    <dataSource id="DerbyConnection" jdbcDriverRef="derbyJDBCDriver" jndiName="jdbc/DerbyConnection">
        <properties.derby.embedded createDatabase="create" databaseName="example"/>
    </dataSource>

    <applicationMonitor updateTrigger="mbean"/>

    <webApplication id="REST" location="REST.war" name="REST"/>
</server>

web.xml

 <?xml version="1.0" encoding="UTF-8"?>
 <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<display-name>REST</display-name>
<servlet>
    <description>
    JAX-RS Tools Generated - Do not modify</description>
    <servlet-name>JAX-RS Servlet</servlet-name>
    <servlet-class>com.ibm.websphere.jaxrs.server.IBMRestServlet</servlet-class>
    <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>com.example.services.RESTConfig</param-value>
        </init-param>
    <load-on-startup>1</load-on-startup>
    <enabled>true</enabled>
    <async-supported>false</async-supported>
</servlet>
<servlet-mapping>
    <servlet-name>JAX-RS Servlet</servlet-name>
    <url-pattern>
    /rest/*</url-pattern>
</servlet-mapping>

<ejb-local-ref>
    <ejb-ref-name>ejb/UserResource</ejb-ref-name>
    <ejb-ref-type>Session</ejb-ref-type>
    <local>com.example.services.UserResource</local>
    <ejb-link>
        com.example.services.UserResourceBean
    </ejb-link>
</ejb-local-ref>

 </web-app>

RESTConfig.java

    package com.example.services;

import java.util.HashSet;
import java.util.Set;

import javax.ws.rs.core.Application;

public class RESTConfig extends Application {
    public Set<Class<?>> getClasses() {
        Set<Class<?>> classes = new HashSet<Class<?>>();
        classes.add(HelloWorld.class);
        classes.add(UserResourceBean.class);
        return classes;
    }

}

用户实体.java

 package com.example.persistence;

 import javax.persistence.Entity;
 import javax.persistence.GeneratedValue;
 import javax.persistence.Id;

 @Entity(name = "User")
 public class UserEntity {
private long id;
private String login;
private String password;
private String firstName;
private String lastName;
private String email;
private String role;
private String status;

 @Id
 @GeneratedValue
 public long getId()
 {
  return id;
 }

 public void setId(long id)
 {
  this.id = id;
 }

 public String getLogin() {
return login;
 } 

 public void setLogin(String login) {
this.login = login;
 }

 public String getPassword() {
return password;
 }

 public void setPassword(String password) {
this.password = password;
 }

 public String getFirstName() {
return firstName;
 }

 public void setFirstName(String firstName) {
this.firstName = firstName;
 }

 public String getLastName() {
return lastName;
 }

 public void setLastName(String lastName) {
this.lastName = lastName;
 }

 public String getEmail() {
return email;
 }

 public void setEmail(String email) {
this.email = email;
 }

 public String getRole() {
return role;
 }

 public void setRole(String role) {
this.role = role;
 }

 public String getStatus() {
return status;
 }

 public void setStatus(String status) {
this.status = status;
 }

 @Override
 public String toString()
 {
  return "UserEntity {" +
       "id=" + id +
       ", email='" + email + '\'' +
       ", password='" + password + '\'' +
       ", firstName='" + firstName + '\'' +
       ", lastName='" + lastName + '\'' +
       ", email='" + email + '\'' +
       ", role='" + role + '\'' +
       ", status='" + status + '\'' +
       '}';
  }   
 } 

用户资源.java

        package com.example.services;

    import javax.ws.rs.Consumes;
    import javax.ws.rs.DefaultValue;
    import javax.ws.rs.GET;
    import javax.ws.rs.POST;
    import javax.ws.rs.Path;
    import javax.ws.rs.PathParam;
    import javax.ws.rs.Produces;
    import javax.ws.rs.QueryParam;
    import javax.ws.rs.core.Context;
    import javax.ws.rs.core.Response;
    import javax.ws.rs.core.UriInfo;

    import com.example.domain.User;
    import com.example.domain.Users;


    @Path("/users")
    public interface UserResource
    {
       @POST
       @Consumes("application/xml")
       Response createUser(User user, @Context UriInfo uriInfo);

       @GET
       @Produces("application/xml")
       //@Formatted
       Users getUsers(@QueryParam("start") int start,
                              @QueryParam("size") @DefaultValue("10") int size,
                              @QueryParam("firstName") String firstName,
                              @QueryParam("lastName") String lastName,
                              @Context UriInfo uriInfo);

       @GET
       @Path("{id}")
       @Produces("application/xml")
       User getUser(@PathParam("id") long id);
    }

用户资源Bean.java

package com.example.services;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;

import com.example.domain.Link;
import com.example.domain.User;
import com.example.domain.Users;
import com.example.persistence.UserEntity;

import java.net.URI;
import java.util.ArrayList;
import java.util.List;

@Stateless
public class UserResourceBean implements UserResource
{
   @PersistenceContext(unitName="jpa-example")
   private EntityManager em;

   public Response createUser(User user, UriInfo uriInfo)
   {
      UserEntity entity = new UserEntity();
      domain2entity(entity, user);
      System.out.println(entity);
      em.persist(entity);
      em.flush();

      System.out.println("Created user " + entity.getId());
      UriBuilder builder = uriInfo.getAbsolutePathBuilder();
      builder.path(Long.toString(entity.getId()));
      return Response.created(builder.build()).build();

   }

   public User getUser(long id)
   {
      UserEntity user = em.getReference(UserEntity.class, id);
      return entity2domain(user);
   }

   public static void domain2entity(UserEntity entity, User user)
   {
      entity.setId(user.getId());
      entity.setLogin(user.getLogin());
      entity.setPassword(user.getPassword());
      entity.setFirstName(user.getFirstName());
      entity.setLastName(user.getLastName());
      entity.setEmail(user.getEmail());
      entity.setRole(user.getRole());
      entity.setStatus(user.getStatus());
   }

   public static User entity2domain(UserEntity entity)
   {
      User u = new User();
      u.setId(entity.getId());
      u.setLogin(entity.getLogin());
      u.setPassword(entity.getPassword());
      u.setFirstName(entity.getFirstName());
      u.setLastName(entity.getLastName());
      u.setEmail(entity.getEmail());
      u.setRole(entity.getRole());
      u.setStatus(entity.getStatus());
      return u;
   }

   public Users getUsers(int start,
                                 int size,
                                 String firstName,
                                 String lastName,
                                 UriInfo uriInfo)
   {
      UriBuilder builder = uriInfo.getAbsolutePathBuilder();
      builder.queryParam("start", "{start}");
      builder.queryParam("size", "{size}");

      ArrayList<User> list = new ArrayList<User>();
      ArrayList<Link> links = new ArrayList<Link>();

      Query query = null;
      if (firstName != null && lastName != null)
      {
         query = em.createQuery("select u from Users u where u.firstName=:first and u.lastName=:last");
         query.setParameter("first", firstName);
         query.setParameter("last", lastName);

      }
      else if (lastName != null)
      {
         query = em.createQuery("select u from Users u where u.lastName=:last");
         query.setParameter("last", lastName);
      }
      else
      {
         query = em.createQuery("select u from Users u");
      }

      List userEntities = query.setFirstResult(start)
              .setMaxResults(size)
              .getResultList();

      for (Object obj : userEntities)
      {
         UserEntity entity = (UserEntity) obj;
         list.add(entity2domain(entity));
      }
      // next link
      // If the size returned is equal then assume there is a next
      if (userEntities.size() == size)
      {
         int next = start + size;
         URI nextUri = builder.clone().build(next, size);
         Link nextLink = new Link("next", nextUri.toString(), "application/xml");
         links.add(nextLink);
      }
      // previous link
      if (start > 0)
      {
         int previous = start - size;
         if (previous < 0) previous = 0;
         URI previousUri = builder.clone().build(previous, size);
         Link previousLink = new Link("previous", previousUri.toString(), "application/xml");
         links.add(previousLink);
      }
      Users users = new Users();
      users.setUsers(list);
      users.setLinks(links);
      return users;
   }

}

正是在最后一个文件中出现了 NPE。特别是在函数 createUser 中,以下代码会抛出 NPE:em.persist(entity);

4

1 回答 1

3

我通过将 RESTconfig.java 中的代码更改为如下所示解决了注入问题:

 package com.example.services;

 import java.util.HashSet;
 import java.util.Set;

 import javax.naming.InitialContext;
 import javax.ws.rs.core.Application;

 public class RESTConfig extends Application {

  public Set<Object> getSingletons()
   {
      HashSet<Object> set = new HashSet();
      try
      {
         InitialContext ctx = new InitialContext();

         obj = ctx.lookup(
                 "java:comp/env/ejb/UserResource");
         set.add(obj);

      }
      catch (Exception ex)
      {
         throw new RuntimeException(ex);
      }
      return set;
   }

 }
于 2013-07-11T22:25:05.533 回答