*Hi, happy sunday,
I'm on fire with Jax Rs, I've configurated and tested Arun Gupta blog
reader writer example.
Here are my impressions and feedback,
Regards,
Jaime.
*
*FIRST: ON THE SERVER SIDE, WE REGISTER OUR OBJECTS: RESOURCE, READER,
WRITER. I THINK WE USE CDI FOR PROVIDE VISIBILITY TO GLASSFISF ON RUNTIME
CYCLE TO REGISTER THIS RESOURCES. I THINK WE USE APPLICATIONPATH
"WEBRESOURCES" AS ESTANDAR IN THIS CASE BETWEEN JAX RS 2 AND THE SERVER
SIDE (NOT SO GOOD EXPLAIN MYSELF, SORRY ;))
*
package org.sample.readerwriter;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
/**
* @author Arun Gupta
*/
@ApplicationPath("
webresources")
public class MyApplication extends Application {
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new java.util.HashSet<>();
resources.add(MyResource.class);
resources.add(MyReader.class);
resources.add(MyWriter.class);
return resources;
}
}
*SECOND: JAX RS SERVICE
*
*Servicio Rest publicado en el path @fruits, que define el método post, que
consume un objeto de tipo mime_type, y un segundo método post con path
fruit int
FIRST: WE DEFINE A REST SERVICE PUBLISHED IN FRUIT PATH, WHICH DEFINES POST
METHOD WHICH CONSUME MYOBJECT (CUSTOM OBJECT), AND ANOTHER METHOD PUBLISHED
UN A SUBPATH FRUITINT, WHICH CONSUMES A JAVA PRIMITIVE*
package org.sample.readerwriter;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
/**
* @author Arun Gupta
*/
@Path("fruits")
public class MyResource {
private String[] response = { "apple", "banana", "mango" };
@POST
@Consumes(value=MyObject.MIME_TYPE)
public String getFruit(MyObject mo) {
System.out.println("endpoint invoked (getFruit(" + mo.getIndex() +
"))");
return response[Integer.valueOf(mo.getIndex()) % 3];
}
@POST
@Path("fruitInt")
public String getFruit2(int index) {
return response[index % 3];
}
}
**
*SECOND: MYREADER, WHICH IMPLEMENTS MESSAGEBODYREADER, IT GIVES THE
POSIBILITY TO READ HTTP REQUEST WITH THS OBJECT AS PARAM.*
*
*package org.sample.readerwriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ws.rs.Consumes;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.Provider;
/**
* @author Arun Gupta
*/
@Provider
@Consumes(MyObject.MIME_TYPE)
public class MyReader implements MessageBodyReader<MyObject> {
@Override
public boolean isReadable(Class<?> type, Type type1, Annotation[]
antns, MediaType mt) {
return MyObject.class.isAssignableFrom(type);
}
@Override
public MyObject readFrom(Class<MyObject> type,
Type type1,
Annotation[] antns,
MediaType mt, MultivaluedMap<String, String> mm,
InputStream in) throws IOException, WebApplicationException
{
try {
ObjectInputStream ois = new ObjectInputStream(in);
return (MyObject)ois.readObject();
} catch (ClassNotFoundException ex) {
Logger.getLogger(MyReader.class.getName()).log(Level.SEVERE,
null, ex);
}
return null;
}
}
*
THIRD: MYWRITER OBJECT, THE SAME, AS WRITER, FOR MAKE HTTP REQUEST WITH
THIS OBJECT
*package org.sample.readerwriter;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
/**
* @author Arun Gupta
*/
@Provider
@Produces(MyObject.MIME_TYPE)
public class MyWriter implements MessageBodyWriter<MyObject> {
@Override
public boolean isWriteable(Class<?> type, Type type1, Annotation[]
antns, MediaType mt) {
return MyObject.class.isAssignableFrom(type);
}
@Override
public long getSize(MyObject t, Class<?> type, Type type1, Annotation[]
antns, MediaType mt) {
// As of JAX-RS 2.0, the method has been deprecated and the
// value returned by the method is ignored by a JAX-RS runtime.
// All MessageBodyWriter implementations are advised to return -1
from
// the method.
return -1;
}
@Override
public void writeTo(MyObject t,
Class<?> type,
Type type1,
Annotation[] antns,
MediaType mt,
MultivaluedMap<String, Object> mm,
OutputStream out) throws IOException,
WebApplicationException {
ObjectOutputStream oos = new ObjectOutputStream(out);
oos.writeObject(t);
}
}
*THE OBJECT WE WANT TO USE*
package org.sample.readerwriter;
import java.io.Serializable;
/**
* @author Arun Gupta
*/
public class MyObject implements Serializable {
public static final String MIME_TYPE = "application/myType";
private int index;
public MyObject() {
}
public MyObject(int index) {
this.index = index;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
}
*
TEST SERVLET*
package org.sample.readerwriter;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientFactory;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
/**
* @author Arun Gupta
*/
@WebServlet(name = "TestServlet", urlPatterns = {"/TestServlet"})
public class TestServlet extends HttpServlet {
/**
* Processes requests for both HTTP
* <code>GET</code> and
* <code>POST</code> methods.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
protected void processRequest(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet TestServlet</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>Servlet TestServlet at " +
request.getContextPath() + "</h1>");
*//CREATING A CLIENT*
Client client = ClientFactory.newClient();
*
//REGISTERING PROVIDER*
client
.configuration()
.register(MyReader.class)
.register(MyWriter.class);
*//DEFINING TARGET CLIENT, SERVER NAME, PORT, CONTEXT PATH AND RESOURCE URI
* WebTarget target = client.target("http://"
+ request.getServerName()
+ ":"
+ request.getServerPort()
+ request.getContextPath()
+ "/webresources/fruits");
System.out.println("POST request");
*//MAKING FIRST CLIENT HTTP REQUEST, USING MYOBJECT AS ARG
* String fruit = target
.request()
.post(Entity.entity(new MyObject(1), MyObject.MIME_TYPE),
String.class);
out.println("Received response: " + fruit + "<br><br>");
*
///MAKING ANOTHER HTTP REQUEST, USING PLAIN OBJECT, ALSO USING ANOTHER
SUBPATH*
fruit = target
.path("fruitInt")
.request()
.post(Entity.text("1"), String.class);
out.println("Received response: " + fruit + "<br><br>");
out.println("Check server.log for client/server interceptor
output.");
out.println("</body>");
out.println("</html>");
}
// <editor-fold defaultstate="collapsed" desc="HttpServlet methods.
Click on the + sign on the left to edit the code.">
/**
* Handles the HTTP
* <code>GET</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse
response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Handles the HTTP
* <code>POST</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse
response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Returns a short description of the servlet.
*
* @return a String containing servlet description
*/
@Override
public String getServletInfo() {
return "Short description";
}// </editor-fold>
}
COMMENTS
1) I DONT UNDESRTAND WHY IN READER OBJECT WE MAKE MYOBJECT CAST, BUT NOT IN
WRITER. LATER, I'VE SEEN THAT READER NEEDS TO CAST THE OBJECT AND PUT IN IN
JAVA OBECT TO USE UTSELF, BUT WRITER ONLY NEEDS WRITE THIS INFORMATION IN
HTTP REQUEST, NO MORE. SO THAT'S OK
2) IN CLIENT HTTP REQUEST, WE'VE SEEN THE NEXT LINES:
String fruit = target
.request()
.post(Entity.entity(new MyObject(1), MyObject.MIME_TYPE),
String.class);
fruit = target
.path("fruitInt")
.request()
.post(Entity.text("1"), String.class);
I'VE BEEN SURPRISED FOR WHY WE USE ENTITY IN ANY CASE TO GIVE THE
PARAMETER, WHY NOT USE, IN SECOND CASE, WE WANT TO SEND AN INT VALUE, ONLY
THE INT VALUE?
fruit = target
.path("fruitInt")
.request()
.post(1, String.class);
ALSO, WHY ARE SENDING A "1" WHEN WE WANT TO SEND AND INT, IT'S NOT SO
INTUITIVE, IT REQUIRES THE PROGRAMMERS THINKS IN HTTP REQUEST AND LATER,
THIS PARAMETER HAS TO BE ENCAPSULATED IN INT OBJECT, I THINK IT COULD BE NO
SO INTUITIVE AND REQUIRES AND ADDITIONAL EFFORT TO THE PROGRAMMER
REGARDS,
JAIME