无法在 GlassFish 中使用 Jersey 启用 REST(抛出与 JPA 相关的异常)

Unable to enable REST with Jersey in GlassFish (throw an exception relevant to JPA)

我不明白为什么我无法启动我的 REST 服务。该异常说明了一些关于 JPA 的信息,但没有提供太多关于导致它的原因的信息。

如果在地址栏中输入 url: localhost:8080/UsersControl/api/all,GlassFish returns 一个 404 错误。

用户实体:

@Entity
@Table(name="users")
public class User implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="user_id")
    private Short id;
    @Column(name="names")
    private String names;
    @Column(name="surnames")
    private String surnames;
    @Column(name="dni")
    private String dni;
    @Column(name="birth_date")
    @Temporal(TemporalType.DATE)
    private Date birthDate;
    @Column(name="address")
    private String address;
    @Column(name="state")
    private Boolean state;

    public User() {

    }
    public User(Short id, String names, String surnames, String dni, Date birthDate, String address) {
        this.id = id;
        this.names = names;
        this.surnames = surnames;
        this.dni = dni;
        this.birthDate = birthDate;
        this.address = address;
    }
    public Short getId() {
        return id;
    }
    public void setId(Short id) {
        this.id = id;
    }
    public String getNames() {
        return names;
    }
    public void setNames(String names) {
        this.names = names;
    }
    public String getSurnames() {
        return surnames;
    }
    public void setSurnames(String surnames) {
        this.surnames = surnames;
    }
    public String getDni() {
        return dni;
    }
    public void setDni(String dni) {
        this.dni = dni;
    }
    public Date getBirthDate() {
        return birthDate;
    }
    public void setBirthDate(Date birthDate) {
        this.birthDate = birthDate;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    public Boolean getState() {
        return state;
    }
    public void setState(Boolean state) {
        this.state = state;
    }
    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }
    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof User)) {
            return false;
        }
        User other = (User) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

}

用户登录实体

@Entity
@Table(name="user_login")
public class UserLogin implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="user_login_id")
    private Short id;
    @ManyToOne
    @JoinColumn(name="user_id")
    private User user;
    @Column(name="username")
    private String username;
    @Column(name="password")
    private String password;

    public Short getId() {
        return id;
    }
    public void setId(Short id) {
        this.id = id;
    }
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }
    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof UserLogin)) {
            return false;
        }
        UserLogin other = (UserLogin) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

}

抽象 GenericDao 实现

public abstract class GenericDaoImpl<T, PK extends Serializable> implements GenericDao<T, PK> {

    @PersistenceContext(unitName="ControlUsuarios-ServidorPU")
    protected EntityManager em;
    protected Class<T> clazz;

    public GenericDaoImpl() {
        ParameterizedType genericSuperclass = (ParameterizedType) getClass()
            .getGenericSuperclass();
       this.clazz = (Class<T>) genericSuperclass.getActualTypeArguments()[0];
    }
    @Override
    public T save(T t) {
        em.persist(t);
        return t;
    }
    @Override
    public T update(T t) {
        em.persist(t);
        return t;
    }
    @Override
    public T remove(T t) {
        em.remove(t);
        return t;
    }
    @Override
    public T find(PK id) {
        T t = (T) em.find(clazz, id);
        return t;
    }
    public abstract List<T> findAll();

}

用户 DAO

@RequestScoped
public class UserDao extends GenericDaoImpl<User, Short> implements Serializable {

    public UserDao() {
        super();
    }    
    @Override
    public List<User> findAll() {
        Query query = em.createNamedQuery("SELECT u FROM u");
        List<User> users = (List<User>) query.getResultList();
        return users;
    }

}

我的网络服务

@Path("/api")
public class UserService {   
    @Inject
    UserDao userDao;

    @POST
    @Path("/save")
    @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
    public void save(JSONObject user) {
        /*List<Object> userData = (List<Object>) user.get("user");
        for(Object o : userData) {
            System.out.println(o.getClass().getName());
        }*/
        System.out.println(user == null);
    }
    @PUT
    @Path("/update")
    @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
    public void update(JSONObject user) {

    }
    @DELETE
    @Path("/remove/{id}")
    public void delete(@PathParam("id") Short id) {

    }
    @GET
    @Produces(MediaType.TEXT_HTML)
    @Path("/all")
    public String findAll() {
        System.out.println("Recuperar todos!");
        return "<p>Accediendo a todos los usuarios...</p>";
    }
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/find/{i}")
    public void find(@PathParam("id") Short id) {

    }

}

persistence.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.1" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
  <persistence-unit name="ControlUsuarios-ServidorPU" transaction-type="JTA">
    <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
    <jta-data-source>jdbc/userscontrol</jta-data-source>

    <class>com.company.userscontrol.model.entities.User</class>
    <class>com.company.userscontrol.model.entities.UserLogin</class>  

    <properties>
      <property name="javax.persistence.schema-generation.database.action" value="none"/>
    </properties>
  </persistence-unit>
</persistence>

web.xml

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
     version="3.1">
    <servlet>
        <servlet-name>Jersey REST Service</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.company.userscontrol.rest</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Jersey REST Service</servlet-name>
        <url-pattern>/api/*</url-pattern>
    </servlet-mapping>

</web-app>

当运行应用时,GlassFish抛出如下异常:

Advertencia:   Exception while dispatching an event
java.lang.NullPointerException
    at org.hibernate.engine.transaction.internal.jta.JtaStatusHelper.getStatus(JtaStatusHelper.java:76)
    at org.hibernate.engine.transaction.internal.jta.JtaStatusHelper.isActive(JtaStatusHelper.java:118)
    at org.hibernate.engine.transaction.internal.jta.CMTTransaction.join(CMTTransaction.java:149)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.joinTransaction(AbstractEntityManagerImpl.java:1602)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.postInit(AbstractEntityManagerImpl.java:210)
    at org.hibernate.jpa.internal.EntityManagerImpl.<init>(EntityManagerImpl.java:91)
    at org.hibernate.jpa.internal.EntityManagerFactoryImpl.internalCreateEntityManager(EntityManagerFactoryImpl.java:345)
    at org.hibernate.jpa.internal.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:313)
    at org.glassfish.persistence.jpa.JPADeployer.visitPUD(JPADeployer.java:451)
    at org.glassfish.persistence.jpa.JPADeployer$PersistenceUnitDescriptorIterator.iteratePUDs(JPADeployer.java:510)
    at org.glassfish.persistence.jpa.JPADeployer.iterateInitializedPUsAtApplicationPrepare(JPADeployer.java:492)
    at org.glassfish.persistence.jpa.JPADeployer.event(JPADeployer.java:398)
    at org.glassfish.kernel.event.EventsImpl.send(EventsImpl.java:131)
    at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:487)
    at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:219)
    at org.glassfish.deployment.admin.DeployCommand.execute(DeployCommand.java:491)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl.run(CommandRunnerImpl.java:539)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl.run(CommandRunnerImpl.java:535)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.Subject.doAs(Subject.java:360)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl.execute(CommandRunnerImpl.java:534)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl.run(CommandRunnerImpl.java:565)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl.run(CommandRunnerImpl.java:557)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.Subject.doAs(Subject.java:360)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:556)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:1464)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl.access00(CommandRunnerImpl.java:109)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1846)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1722)
    at org.glassfish.deployment.admin.ReDeployCommand.execute(ReDeployCommand.java:131)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl.run(CommandRunnerImpl.java:539)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl.run(CommandRunnerImpl.java:535)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.Subject.doAs(Subject.java:360)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl.execute(CommandRunnerImpl.java:534)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl.run(CommandRunnerImpl.java:565)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl.run(CommandRunnerImpl.java:557)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.Subject.doAs(Subject.java:360)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:556)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:1464)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl.access00(CommandRunnerImpl.java:109)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1846)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1722)
    at com.sun.enterprise.v3.admin.AdminAdapter.doCommand(AdminAdapter.java:534)
    at com.sun.enterprise.v3.admin.AdminAdapter.onMissingResource(AdminAdapter.java:224)
    at org.glassfish.grizzly.http.server.StaticHttpHandlerBase.service(StaticHttpHandlerBase.java:189)
    at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167)
    at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:201)
    at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:175)
    at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)
    at org.glassfish.grizzly.filterchain.ExecutorResolver.execute(ExecutorResolver.java:119)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
    at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:561)
    at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access0(WorkerThreadIOStrategy.java:56)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545)
    at java.lang.Thread.run(Thread.java:745)

额外信息: 我将这些库放入我的项目中:

¿我做错了什么?感谢您的帮助和时间。

我想这只是答案的一半,因为它没有解决异常问题,但显然 REST 应用程序仍在运行,并进行了以下修复。

From comment:

Not sure about the exception, put your path is wrong. You define /api/ as the root application path in the web.xml. Then you define /api again in the @Path for the UserService. So it should be /api/api. But you most likely want to change the @Path to /users and use /api/users