Just startred using restlet with java and was pleasently surprised how easy it was. However this was with puts. I then started to work with get but couldn't work out how to pass infromation with the get.
With the put it was easy as:
#Put
public Boolean store(Contact contact);
But when i try and do this with get it doesnt work. From reading around i think i have to not pass it any parameters and just have this:
#Get
public Contact retrieve();
and then pass the parameters in a url or something?
But i cant find any info on how to do this. As with put i could just use:
resource.store(user1);
Any help please?
Im pretty sure this is the kind of thing i just need to see an example of and then ill be able to do it easily. Example of how to get the infromation out of the url at the other side would be very helpful aswell.
Thanks
I now have on my client side:
String username = "tom";
ClientResource cr2 = new ClientResource("http://.../ContactManager/contacts/" + username);
ContactResource resource2 = cr2.wrap(ContactResource.class);
resource2.logIn();
On the server side i have:
#Get
public Contact logIn(){
System.out.println("name is " + resource.getAttributes().get("contactId"));
return null;
}
But i am not sure what resource is? It doesnt exist in my program and am not sure what type it needs to be or where to declare it.
A good approach with REST is to specify this contact id within the URI. Something like that: /contacts/mycontactid.
When attaching your resources within the application class, you can define this segment as an attribute (the contact id one in your case).
public class ContactsApplication extends Application {
public Restlet createInboundRoot() {
Router router = new Router(getContext());
router.attach("/contacts/", ContactsServerResource.class);
router.attach("/contacts/{contactId}", ContactServerResource.class);
return router;
}
}
Then you can have the code provided by Richard in his answer.
Hope it helps you.
Thierry
I know this question was asked along time ago but the answer I think you are looking for is:
Application Code
public class ContactsApplication extends Application {
public Restlet createInboundRoot() {
Router router = new Router(getContext());
router.attach("/user/", ContactsServerResource.class);
router.attach("/user/{user}", ContactServerResource.class);
return router;
}
}
Resource Code
#Get
public void login()
String userName = (String)this.getRequestAttributes().get("user");
The (String)this.getRequestAttributes().get("user"); allows you extract details from the URL.
Hope this helps
It seems that what you are looking for is something like:
public final Representation get() {
String contactId = request.getAttributes().get("contactId"));
// Find the Contact object with that id
JacksonRepresentation<Contact> result =
new JacksonRepresentation<Contact>(contact);
return result;
}
Also see: how to pass parameters to RESTlet webservice from android? for a similar approach.
Related
There is a scenario which I'm currently facing where I have to manually create an instance of the spark.Request & spark.Responseobject. Can anyone help me with this?
I am creating both request and response objects for testing purposes.
My implementation looks like this
package spark;
public class RequestStub extends Request {
// Implement the methods needed
// I fake my return values
}
This works well for testing.
If this isn't what you need, then please share more details and perhaps a code sample to describe your problem.
In your derived classes you can override body() body(String text), status(), status(int stat) etc - all the methods you need. Like this for the Request body say...
class RequestStub extends Request
{
private String _body;
RequestStub(String body)
{
_body = body;
}
public String body()
{
return _body;
}
}
So you get to do something like this...
Request rq = new RequestStub(readFile("./src/test/resources/nested-test.txt"));
Response rp = new ResponseStub();
String result = (String)Controller.Post.handle(rq,rp);
I have a simple REST client with GET POST and DELETE methods.
Weird things is that only GET methods work, neither POST nor DELETE doesn't even get hit and response is "404 Not Found" of course.
Here's my REST service and the client:
Interface:
public interface MyInterface {
#GET
#Path("/content")
#Produces(MediaType.APPLICATION_JSON)
Response getAirports();
#DELETE
#Path("/content/{id}")
#Produces(MediaType.APPLICATION_JSON)
Response deleteAirport(#PathParam("id") String id);
}
Implementation:
#Path("/source")
public class SourceService extends AbstractService implements MyInterface {
#Override
public Response getContent() {
DBCollection collection = getDBCollection("content");
DBCursor cursor = collection.find();
String serialize = JSON.serialize(cursor);
return Response.status(Response.Status.OK).entity(serialize).build();
}
#Override
public Response deleteContent(#PathParam("id") Integer id) {
DBCollection collection = getDBCollection("content");
BasicDBObject query = new BasicDBObject();
query.append("id", id);
collection.remove(query);
return Response.status(Response.Status.OK).build();
}
}
Client:
// This is working
public void getContent() {
WebTarget path = collect.path("/content");
Response response = path.request().get();
LOGGER.info("collect.ping: " + response.readEntity(String.class) + "\n");
}
// This is not working
public void deleteContent(Integer id) {
WebTarget path = collect.path("/content/"+id);
Response response = path.request(MediaType.APPLICATION_JSON).delete();
System.out.println("object deleted:"+response);
}
I've tried requesting with jersey or apache clients but all of them return 404 and I'm like hopeless now.
Hope you can give me a direction.
This looks like a possible duplicate of Inheritance with JAX-RS. Have you tried replicating all annotations in the subclass or none, means do not use #PathParam in the implementation class at all?
If you actually can debug your client and you are indeed able to "Step through" the client code?
If you place a break-point within your server code and you never actually "break" on it? Then the problem is with the way you are exposing your web service and how you are then trying to consume it.
Try to change the parameter type expected by the Server and the type you pass from your client.
If you can change it on the server and client to a simpler type.. i.e.. an integer.. and then you can actually capture a breakpoint in both client and server, then you know that the problem is in your types.
I hope you can understand what I'm saying? You really need to simplify your parameters and/or try it without parameters first.
When you get something simpler working, then you can extend it to something else.
try just changing it to a string... such as "airport" Also, you are passing a parameter in the client as this:
public void deleteAirport(String iata) {
But you don't use "iata" in your client code...
I want to use the following type of URL in Restlet: http://url.com/http://www.anotherurl.com/path
As a result I want to get http://www.anotherurl.com/path as a parameter.
However it does nothing.
Also, if I use http://url.com/path , then I receive "path" without problems. http://url.com/www.anotherurl.com gives me www.anotherurl.com. However http://url.com/www.anotherurl.com/path is 404.
You need to encode the parameter special characters properly. Use URLEncoder to do so.
In fact, there are two parts here.
The URL building using the Reference class:
Reference ref = new Reference();
ref.setScheme("http");
ref.setHostDomain("localhost");
ref.setHostPort(8182);
ref.addSegment("test");
ref.addSegment("http://test");
ClientResource cr = new ClientResource(ref);
cr.get();
Getting the value as a path parameter and decode it. Here is the routing configuration in the application class:
public Restlet createInboundRoot() {
Router router = new Router(getContext());
router.attach("/test/{id}", MyServerResource.class);
return router;
}
And the corresponding code in the server resource:
public class MyServerResource extends ServerResource {
#Get
public Representation get() {
String id = getAttribute("id");
// Prints http%3A%2F%2Ftest
System.out.println("id = "+id);
// Prints http://test
System.out.println("id = "+Reference.decode(id));
return new EmptyRepresentation();
}
}
Hope it helps you,
Thierry
So I am new with restlet. I am creating a Android application that can communicate with a GAE server (with objectify DB)
I Did this very good tutorial to learn:
http://www.tutos-android.com/webservice-rest-android-appengine-restlet-objectify
It's working very well but do very little.
Onely 2 methods:
public interface UserControllerInterface {
#Put
void create(User user);
#Get
Container getAllUsers();
}
For my application its more complicated so I add many more methods:
public interface UserControllerInterface {
#Put
public void createUser(ObagooUser user);
#Put
public void createMessage(ObagooUser user, String message);
#Put
public void updateMessage(ObagooMessage message);
#Get
public List<ObagooUser> getAllUser();
#Get
public ObagooUser getUserById(String id);
#Get
public List<ObagooMessage> getAllMessage();
#Get
public List<ObagooMessage> getAllMessageFromSender(ObagooUser sender);
#Get
public ObagooMessage getFreeMessage(ObagooUser user);
}
Each of these mothds working server side (I tested with Junit).
Now I am coding the android part and I am having problems.
When I do a simple call to getAllMessage() I get an error:
java.lang.IllegalArgumentException: id cannot be zero
at com.google.appengine.api.datastore.KeyFactory.createKey(KeyFactory.java:44)
at com.googlecode.objectify.ObjectifyFactory.typedKeyToRawKey(ObjectifyFactory.java:269)
at com.googlecode.objectify.impl.ObjectifyImpl.find(ObjectifyImpl.java:159)
at com.googlecode.objectify.impl.ObjectifyImpl.find(ObjectifyImpl.java:183)
at com.obagoo.dao.ObagooUserDAO.getUserById(ObagooUserDAO.java:43)
at com.obagoo.controller.ObagooController.getUserById(ObagooController.java:47)
It's going in the wrong method (getUserById).
I put a break point in my getAllMessage and it's going in, but it is also going in other methods.
If I test many times, sometimes it's calling, createUser or another random method.
Do you see what I am doind wrong?
Adding the getAllMessage code:
public List<ObagooMessage> getAllMessage() {
// logger.debug("Getting all Obagoo Messages");
List<ObagooMessage> msg = new ArrayList<ObagooMessage>();
Objectify ofy = ObjectifyService.begin();
Query<ObagooMessage> q = ofy.query(ObagooMessage.class);
for (ObagooMessage u : q) {
msg.add(u);
}
return msg;
}
In the examples that I've seen, its always shown that you should separate the controller/resource handling the URI for the list resource from the single item (id/name based) resource. So you would have something like:
router.attach("/users", UsersController.class);
router.attach("/users/{id}", UserController.class
router.attach("/messages", MessagesController.class);
Notice the plural naming on the first class: UsersController, and singular naming on the the second class: UserController. The first class would handle cases where no id was being provided, such as a get of all users. Also, note when the id is provided in the URI, it can be automatically mapped into an id field on the class. So the Get method has no parameters on the method call.
As for handling a subset, then for messages from a specific user, that could be handled with query parameters. For instance when calling via a URI with /messages?sender=id, the MessagesController.class would use the following in the method handling the Get:
Form queryParams = getRequest().getResourceRef().getQueryAsForm();
String id = queryParams.getFirstValue("sender");
Hope that helps. I'm no expert, so anyone feel free to correct me.
As error says: you are creating a key with zero Id.
My gues is that your ObagoMessage Id field is long? You should make it Long. Primitive long Id values are not autogenerated, while object type Long are. See the docs.
I have writing Java code Using Jersey library to call Rest APIs.
For my first method to display all blogs i have written the code like
return webResource.path(ConfigurationUtil.LIST_BLOGS).header(ConfigurationUtil.AUTHENTICATION_HEADER, authentication)
.accept(MediaType.APPLICATION_XML_TYPE).get(new GenericType<List<CommunityBean>>() {
});
which lists all the blogs.. As my LIST_BLOGS string is like
public static final String LIST_BLOGS = "api/blogs.xml";
Its works fine..
Now I'm trying to write a code for a method where I want to extract only 2 blogs and not all
so my url will be like
public static final String LIST_BLOGS = "api/blogs.xml?limit=2";
As I am not able to send the parameter from the wrapper file to ConfigurationUtil file and I used the way as
public List<BlogBean> searchBlogsXml(String limit) {
final String SEARCH_BLOGS="api/blogs.xml?limit="+limit;
return webResource.path(SEARCH_BLOGS).header(ConfigurationUtil.AUTHENTICATION_HEADER, authentication)
.accept(MediaType.APPLICATION_XML_TYPE).get(new GenericType<List<BlogBean>>() {
});
}
When i used like above i am getting 406 error..
Why so how to avoid this ?
Please give suggestions..
You can attach a query param like this;
resource.queryParam("limit", 2).get(MyObject.class);