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:
myentities.message/
void create(Message entity)
void edit(Message entity)
List<Message> findAll()
myentities.message/count
String countREST()
myentities.message/{id}
void remove(@PathParam("id") Integer id)
Message find(@PathParam("id") Integer id)
myentities.message/{param1}/{param2}
List<Message> findRange(@PathParam("from") Integer from, @PathParam("to")Integer to)
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.