jagan chary
jagan chary

Reputation: 1

Restlet-Convert form encoded body to Pojo

I am building web services using restlet2.3 and accessing user input as (content-type =application/x-www-form-urlencoded) i.e key1=value1&key2=value2 and we have been reading this at ServerResource as form.getFirstValue("key1")...

public class ServerResource{
@Post()
doPost(Form form){
form.getParameter("key1")
}

}

But I don't want this, instead I would to like this to be converted as pojo by restlet

i.e pojo look like

class InputRequest{
String key1;
String key2

getKey1(){

}
}

and at server resource read the values from pojo

public class ServerResource{

@Post()
doPost(InputRequest request){
request.getKey1()
}

}

So, my question is,does restlet has built-in converter do this or do we need write our own converter and register with restlet.

Upvotes: 0

Views: 414

Answers (2)

Abhishek Oza
Abhishek Oza

Reputation: 3480

For me, this was possible only after overriding the org.restlet.resource.Resource.toObject(Representation, Class<T>) method.

Suppose this is my POJO:

package com.blogspot.javarestlet.form2pojo.server;

public class MyPOJO implements java.io.Serializable{

    private static final long serialVersionUID = 1L;
    private String myName;
    public String getMyName() {
        return myName;
    }
    public void setMyName(String myName) {
        this.myName = myName;
    }
    public MyPOJO() {
    }
}

And this is my resource (without overriding org.restlet.resource.Resource.toObject(Representation, Class<T>)):

package com.blogspot.javarestlet.form2pojo.server;

import org.restlet.resource.Post;
import org.restlet.resource.ServerResource;

public class MyResource extends ServerResource{
    @Post("form:txt")
    public String postFormTxt(MyPOJO myPojo){
        return "Hello "+myPojo.getMyName();
    }
}

And this is my server-application(standalone):

package com.blogspot.javarestlet.form2pojo.server;

import org.restlet.Application;
import org.restlet.Component;
import org.restlet.Restlet;
import org.restlet.data.Protocol;
import org.restlet.routing.Router;

public class ServerApp extends Application {

    /**
     * When launched as a standalone application.
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        Component component = new Component();
        component.getServers().add(Protocol.HTTP, 8080);
        component.getDefaultHost().attach(new ServerApp());
        component.start();
    }

    @Override
    public Restlet createInboundRoot() {
        Router router = new Router(getContext());
        router.attach("/a", MyResource.class);
        return router;
    }

}

The output I got was this:

Java 1.7 and Restlet 2.3

C:\Users\abhishek>curl -i -H "Content-Type: application/x-www-form-urlencoded" -H "Accept: text/plain" "http://localhost:8080/a" -d "myName=Abhishek"
HTTP/1.1 422
Content-type: text/html; charset=UTF-8
Content-length: 541
Server: Restlet-Framework/2.3.9
Accept-ranges: bytes
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
Date: Thu, 16 Mar 2017 07:08:43 GMT

<html>
<head>
   <title>Status page</title>
</head>
<body style="font-family: sans-serif;">
<p style="font-size: 1.2em;font-weight: bold;margin: 1em 0px;">Unprocessable Entity</p>
<p>The server understands the content type of the request entity and the syntax of the request entity is correct but was unable to process the contained instructions
</p>
<p>You can get technical details <a href="http://www.webdav.org/specs/rfc2518.html#STATUS_422">here</a>.<br>
Please continue your visit at our <a href="/">home page</a>.
</p>
</body>
</html>

Java 1.6 and Restlet 2.0:

C:\Users\abhishek>curl -i -H "Content-Type: application/x-www-form-urlencoded" -H "Accept: text/plain" "http://localhost:8080/a" -d "myName=Abhishek"
HTTP/1.1 415 Unsupported Media Type
Date: Thu, 16 Mar 2017 07:23:43 GMT
Accept-Ranges: bytes
Server: Restlet-Framework/2.0.15
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
Content-Length: 554
Content-Type: text/html; charset=UTF-8

<html>
<head>
   <title>Status page</title>
</head>
<body style="font-family: sans-serif;">
<p style="font-size: 1.2em;font-weight: bold;margin: 1em 0px;">Unsupported Media Type</p>
<p>The server is refusing to service the request because the entity of the request is in a format not supported by the requested resource for the requested method</p
>
<p>You can get technical details <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.16">here</a>.<br>
Please continue your visit at our <a href="/">home page</a>.
</p>
</body>
</html>

But when I changed my resource to this:

Java 6, Restlet 2.0.15

package com.blogspot.javarestlet.form2pojo.server;

import org.restlet.data.Form;
import org.restlet.representation.Representation;
import org.restlet.resource.Post;
import org.restlet.resource.ResourceException;
import org.restlet.resource.ServerResource;

public class MyResource extends ServerResource{
    @SuppressWarnings("unchecked")
    @Override
    protected <T> T toObject(Representation r, Class<T> c) throws ResourceException {
        if(MyPOJO.class.equals(c)){
            try {
                MyPOJO myPojo = (MyPOJO) c.newInstance();
                Form form = new Form(r.getText());
                myPojo.setMyName(form.getFirstValue("myName"));
                return (T) myPojo;
            } catch (Exception e) {
                new ResourceException(e);
            }
        }
        return super.toObject(r, c);
    }
    @Post("form:txt")
    public String postFormTxt(MyPOJO myPojo){
        return "Hello "+myPojo.getMyName();
    }
}

Java 7, Restlet 2.3

package com.blogspot.javarestlet.form2pojo.server;

import org.restlet.data.Form;
import org.restlet.representation.Representation;
import org.restlet.resource.Post;
import org.restlet.resource.ResourceException;
import org.restlet.resource.ServerResource;

public class MyResource extends ServerResource{
    @SuppressWarnings("unchecked")
    @Override
    public <T> T toObject(Representation r, Class<T> c) throws ResourceException {
        if(MyPOJO.class.equals(c)){
            try {
                MyPOJO myPojo = (MyPOJO) c.newInstance();
                Form form = new Form(r.getText());
                myPojo.setMyName(form.getFirstValue("myName"));
                return (T) myPojo;
            } catch (Exception e) {
                new ResourceException(e);
            }
        }
        return super.toObject(r, c);
    }
    @Post("form:txt")
    public String postFormTxt(MyPOJO myPojo){
        return "Hello "+myPojo.getMyName();
    }
}

I got the output as desired:

C:\Users\abhishek>curl -i -H "Content-Type: application/x-www-form-urlencoded" -H "Accept: text/plain" "http://localhost:8080/a" -d "myName=Abhishek"
HTTP/1.1 200 OK
Date: Thu, 16 Mar 2017 07:29:24 GMT
Accept-Ranges: bytes
Server: Restlet-Framework/2.0.15
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
Content-Length: 14
Content-Type: text/plain; charset=UTF-8

Hello Abhishek

If you want to avoid overriding toObject method in each resource, then there are 2 alternatives:

  1. Have a common parent class for all resources & override toObject in that parent class.
  2. (I have not tried this 2nd one) There is a toObject(Representation, Class<T>, Resource) method in org.restlet.service.ConverterService. Try to override that method and then add it in you application by calling org.restlet.Application.setConverterService(ConverterService)

Note: There is another toObject(Representation) method. I did not try to change it.

Upvotes: 0

Igor
Igor

Reputation: 866

I have an answer for you if you are using post with json body, not sure if it will work for a Form

This is your resource method:

@Post
public Representation insert(GeneralTO to) {
  .
  .
  .
}

This is your transfer object, keep in mind you must have setters for it:

public class GeneralTO {

  private int id;
  private String name;

  public int getId() {
    return brand_id;
  }

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

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

}

Hope it helps

Upvotes: 0

Related Questions