2013-07-11 48 views
2

我剛開始學習JAX-RS,並試圖用JAX-RS書籍修改O'Reilly RESTful Java中的一些示例。我遇到了一個問題,當我試圖將XML文件發佈到我的JAX-RS服務之一時,出現空指針異常。我發佈的特定資源使用JPA將信息保存到德比數據庫。在閱讀其他幾個問題/迴應和教程後,我確信我的代碼是正確的,但也許我錯過了一些配置。看起來實體經理並沒有因爲某種原因被注入,即使我有適當的註釋。任何關於我的問題的意見將不勝感激。請參閱我的項目的以下摘錄,我認爲將是有益的:EntityManager爲空。在WAS-Liberty上使用JAX-RS和JPA

的persistence.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> 

server.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; 
    } 

} 

UserEntity.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 + '\'' + 
     '}'; 
    } 
} 

UserResource.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); 
    } 

UserResourceBean.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);

+0

您的server.xml中的內容也將是有益的,看看。 – Rick

+0

我已經包含了server.xml文件。 – cjackson

回答

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; 
    } 

} 
+0

請你詳細說明如何調用方法getSingletons,因爲我有同樣的錯誤。 – User