简体   繁体   中英

Adding new methods to RESTful web service (error)

I have a MySQL database that has two tables content and message . I have tried to expose these two tables as a Restful web service using netbeans. I followed this tutorial. https://netbeans.org/kb/docs/websvc/rest.html

The application works well with the generated methods and classes, but I wanted to add an extra method to get a list of messages by two other parameters "senders" and "receivers". When I add it I get the following error in Glassfish and the server does not start.

The method that I added is named findConversation .

[#|2013-05-02T00:09:18.609+0300|SEVERE|glassfish3.1.2|javax.enterprise.system.container.web.com.sun.enterprise.web|_ThreadID=133;_ThreadName=Thread-2;|WebModule[/backendCT]StandardWrapper.Throwable
com.sun.jersey.spi.inject.Errors$ErrorMessagesException     at com.sun.jersey.spi.inject.Errors.processErrorMessages(Errors.java:170)
    at com.sun.jersey.spi.inject.Errors.postProcess(Errors.java:136)    at com.sun.jersey.spi.inject.Errors.processWithErrors(Errors.java:199)
    at com.sun.jersey.server.impl.application.WebApplicationImpl.initiate(WebApplicationImpl.java:771)
    at com.sun.jersey.server.impl.application.WebApplicationImpl.initiate(WebApplicationImpl.java:766)
    at com.sun.jersey.spi.container.servlet.ServletContainer.initiate(ServletContainer.java:488)
    at com.sun.jersey.spi.container.servlet.ServletContainer$InternalWebComponent.initiate(ServletContainer.java:318)
    at com.sun.jersey.spi.container.servlet.WebComponent.load(WebComponent.java:609)
    at com.sun.jersey.spi.container.servlet.WebComponent.init(WebComponent.java:210)
    at com.sun.jersey.spi.container.servlet.ServletContainer.init(ServletContainer.java:373)
    at com.sun.jersey.spi.container.servlet.ServletContainer.init(ServletContainer.java:556)
    at javax.servlet.GenericServlet.init(GenericServlet.java:244)   at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1453)
    at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:1093)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:189)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:161)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
    at com.sun.enterprise.v3.services.impl.ContainerMapper$AdapterCallable.call(ContainerMapper.java:317)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)
    at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:860)
    at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:757)
    at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1056)
    at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:229)
    at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
    at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
    at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
    at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
    at com.sun.grizzly.ContextTask.run(ContextTask.java:71)     at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
    at java.lang.Thread.run(Thread.java:722) |#]

this is the message class (I have manually added findcoversation NamedQuery)

 package myentities;

 import java.io.Serializable;
 import java.util.Date;
 import javax.persistence.Basic;
 import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.GeneratedValue;
 import javax.persistence.GenerationType;
 import javax.persistence.Id;
 import javax.persistence.NamedQueries;
 import javax.persistence.NamedQuery;
 import javax.persistence.Table;
 import javax.persistence.Temporal;
 import javax.persistence.TemporalType;
 import javax.validation.constraints.NotNull;
 import javax.validation.constraints.Size;
 import javax.xml.bind.annotation.XmlRootElement;

 @Entity
 @Table(name = "message")
 @XmlRootElement
 @NamedQueries({
     @NamedQuery(name = "Message.findAll", query = "SELECT m FROM Message m"),
     @NamedQuery(name = "Message.findById", query = "SELECT m FROM Message m WHERE m.id = :id"),
     @NamedQuery(name = "Message.findBySender", query = "SELECT m FROM Message m WHERE m.sender = :sender"),
     @NamedQuery(name = "Message.findByReceiver", query = "SELECT m FROM Message m WHERE m.receiver = :receiver"),
     @NamedQuery(name = "Message.findConversation", query = "SELECT m FROM Message m WHERE m.receiver = :receiver and m.sender = :sender"),
     @NamedQuery(name = "Message.findByMessageHTML", query = "SELECT m FROM Message m WHERE m.messageHTML = :messageHTML"),
     @NamedQuery(name = "Message.findByDate", query = "SELECT m FROM Message m WHERE m.date = :date")})
 public class Message implements Serializable {
     private static final long serialVersionUID = 1L;

     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     @Basic(optional = false)
     @Column(name = "ID")
     private Integer id;

     @Basic(optional = false)
     @NotNull
     @Size(min = 1, max = 20)
     @Column(name = "Sender")
     private String sender;

     @Basic(optional = false)
     @NotNull
     @Size(min = 1, max = 20)
     @Column(name = "Receiver")
     private String receiver;

     @Basic(optional = false)
     @NotNull
     @Size(min = 1, max = 200)
     @Column(name = "MessageHTML")
     private String messageHTML;

     @Basic(optional = false)
     @NotNull
     @Column(name = "Date")
     @Temporal(TemporalType.TIMESTAMP)
     private Date date;

     public Message() {
     }

     public Message(Integer id) {
         this.id = id;
     }

     public Message(Integer id, String sender, String receiver, String messageHTML, Date date) {
         this.id = id;
         this.sender = sender;
         this.receiver = receiver;
         this.messageHTML = messageHTML;
         this.date = date;
     }

     public Integer getId() {
         return id;
     }

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

     public String getSender() {
         return sender;
     }

     public void setSender(String sender) {
         this.sender = sender;
     }

     public String getReceiver() {
         return receiver;
     }

     public void setReceiver(String receiver) {
         this.receiver = receiver;
     }

     public String getMessageHTML() {
         return messageHTML;
     }

     public void setMessageHTML(String messageHTML) {
         this.messageHTML = messageHTML;
     }

     public Date getDate() {
         return date;
     }

     public void setDate(Date date) {
         this.date = date;
     }

     @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 Message)) {
             return false;
         }
         Message other = (Message) object;
         if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
             return false;
         }
         return true;
     }

     @Override
     public String toString() {
         return "myentities.Message[ id=" + id + " ]";
     }

  }

This is the facade class, where I have put in the findConversation method:

 package service;

 import java.util.List;
 import javax.ejb.Stateless;
 import javax.persistence.EntityManager;
 import javax.persistence.PersistenceContext;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import myentities.Message;

  /**
    *
    * @author Arabic
    */
  @Stateless @Path("myentities.message")
  public class MessageFacadeREST extends AbstractFacade<Message {
     @PersistenceContext(unitName = "backendCTPU")
     private EntityManager em;

     public MessageFacadeREST() {
         super(Message.class);
     }

     @POST
     @Override
     @Consumes({"application/xml", "application/json"})
     public void create(Message entity) {
         super.create(entity);
     }

     @PUT
     @Override
     @Consumes({"application/xml", "application/json"})
     public void edit(Message entity) {
         super.edit(entity);
     }

     @DELETE
     @Path("{id}")
     public void remove(@PathParam("id") Integer id) {
         super.remove(super.find(id));
     }

     @GET
     @Path("{id}")
     @Produces({"application/xml", "application/json"})
     public Message find(@PathParam("id") Integer id) {
         return super.find(id);
     }

     @GET
     @Override
     @Produces({"application/xml", "application/json"})
     public List<Message findAll() {
         return super.findAll();
     }

     @GET
     @Path("{from}/{to}")
     @Produces({"application/xml", "application/json"})
     public List<Message findRange(@PathParam("from") Integer from, @PathParam("to") Integer to) {
         return super.findRange(new int[]{from, to});
     }

     @GET
     @Path("count")
     @Produces("text/plain")
     public String countREST() {
         return String.valueOf(super.count());
     }

     @GET
     @Path("{Receiver}/{Sender}")
     @Produces({"application/xml", "application/json"})
     public Message findConversation(@PathParam("Receiver") String receiver,@PathParam("Sender") String sender ) {     
         //return new Message();
         return (Message) em.createNamedQuery("Message.findConversation").setParameter("Sender",sender).setParameter("Receiver", receiver);
     } 

     @Override
     protected EntityManager getEntityManager() {
         return em;
     }
  }

The path of findConversation isn't unique.

This is an overview over all services:

  • base path: myentities.message/
    • POST: void create(Message entity)
    • PUT: void edit(Message entity)
    • GET: List<Message> findAll()
  • count: myentities.message/count
    • GET: String countREST()
  • base path + id: myentities.message/{id}
    • DELETE: void remove(@PathParam("id") Integer id)
    • GET: Message find(@PathParam("id") Integer id)
  • base path + 2 parameters: myentities.message/{param1}/{param2}
    • GET: List<Message> findRange(@PathParam("from") Integer from, @PathParam("to")Integer to)
    • GET: Message findConversation(@PathParam("Receiver") String receiver,@PathParam("Sender") String sender )

You can easily see, that findRange and findConversation use the same path and the same method.

For REST services it's common to use an human readable format, although not required. For example you could use query parameters for the findRange and findConversation methods, that would even allow you to combine the search parameters:

.../myentities.message/?from=1000&to=2000&receiver=0815&sender=0911

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM