POST with Restlet framework for Java - java

I can make a GET with no problem at all.
When trying it with a POST request, I get this message:
Internal Server Error
The server encountered an unexpected condition which prevented it from fulfilling the request
I'm testing it with Simple REST Client extension for Chrome, but I get the same message in the real application.
This is my post:
#Post
public StringRepresentation pepe(Representation entity) {
StringRepresentation result = this.users();
// Parse the given representation and retrieve data
Form form = new Form(entity);
String action = form.getFirstValue("action");
if(action.equals("add")){
//nothing
}
Db.closeConnection();
return result;
}
And this is my #Get working properly:
#Get
public StringRepresentation pepe() {
String action = getQuery().getValues("action");
StringRepresentation result = null;
result = this.users();
Db.closeConnection();
return result;
}
And the funny thing is: whenever I remove the condition if(action.equals("add")){, (which was empty inside) the POST works correctly.
This would work:
#Post
public StringRepresentation pepe(Representation entity) {
StringRepresentation result = this.users();
// Parse the given representation and retrieve data
Form form = new Form(entity);
String action = form.getFirstValue("action");
Db.closeConnection();
return result;
}
What's going on? Looks so random!

Yes, your variable action will be null if you don't have an entry action within the form payload.
You can notice that Restlet provides a method getFirstValue with a default value parameter:
String action = form.getFirstValue("action", "defaultActionValue");
This could help you not to have NullPointerException.
Otherwise, it seems that you try to implement several actions for a method POST. I think that this blog post could give you some additional hints: https://templth.wordpress.com/2015/03/20/handling-multiple-actions-for-a-post-method/.
Hope it helps you,
Thierry

Related

Java DeleteMapping Method Not Allowed

I'm trying to create an api to delete a certain ID from the storage;
Here's my code.
API Controller:
#DeleteMapping("{cId}")
#ResponseStatus(HttpStatus.OK)
public String delete(#PathVariable String cId) {
compareService.delete(cId);
return "redirect:/compare";
}
Service:
public void delete(String cId) {
compareLogic.delete(cId);
}
Logic:
public void delete(String cId){
System.out.println("A: " + sessionModel.getCIds());
List<String> update = sessionModel.getCIds();
update.remove(new String(cId));
System.out.println("B: " + sessionModel.getCIds());
}
However when I execute the api it shows
{
success: false,
warning: false,
error: "405",
error_description: "Method Not Allowed"
}
Are there any possible reasons by just looking at the code?
Many thanks,
Just I have tired with simple code snippet , Could you please try to understand and (Try to follow my suggestion as well )
When you hit from browser side (From Address Bar), it won't work for POST/PUT/DELETE calls , it is actually working from browser, if you try to typing in address bar then it is a GET request then it will not supported to the other format
Just I have added two screenshot I have tired with Browser and PostMan
First I have tired with POSTMAN (it is working perfectly)
Second I have tired with Browser (It will throw not supported
exception )
I have tired with small code snippet just copy from your code and remove element from list
#DeleteMapping("{cId}")
public String delete(#PathVariable String cId) {
List<String> arr=new ArrayList<String>(3);
arr.add("A");
arr.add("B");
arr.add("C");
arr.remove(cId);
for (String string : arr) {
System.out.println(string);
}
return "redirect:/compare";
}
The reason for this error is sending the request with a non-supported method. 405 Status Code indicates that the server doesn't support the method or verb sent in the request.
Could you also provide the API call details like HTTP method and relative path ? recheck your API details, make sure you are using correct HTTP method.

Java Rest #GET works but #DELETE and #POST paths doesn't get hit

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...

JAX-RS via Jersey -> No Content Returned In HTTP Body (Method Completes Without Errors)

I am using JAX-RS via Jersey and I have hit a "bump in the road". I have a method that is supposed to return a JSON object following an HTTP POST. It does execute successfully, but does not return the JSON Object (Unless I do a work around). I am hoping someone can tell me why this does not work as I expect it to. See the following code:
#Path("chatroom")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public class ChatroomResource {
ChatroomService service = new ChatroomService();
//this works properly and returns the object as json
#GET
public List<Chatroom> getChatrooms() {
return service.getChatrooms();
}
/**********
* This works, but does not return any content in response body
*******/
#POST
public Chatroom addRoom(Chatroom room) {
return service.addChatroom(room);
/*
* This one does produce content body
* service.addChatroom(room);
* return room;
*/
}
}
The following Method is in the service object:
public Chatroom addChatroom(Chatroom room) {
return Cache.getChatrooms().put(room.getRoomName(), room);
}
What might be wrong and how to fix it
Based on the superficial details you've provided, I believe the following instruction is returning null:
return Cache.getChatrooms().put(room.getRoomName(), room);
In the put(String, Chatroom) method, I guess you are adding the Chatroom instance to the cache, but you are returning null instead of the Chatroom instance.
The following should work:
public Chatroom addChatroom(Chatroom room) {
Cache.getChatrooms().put(room.getRoomName(), room);
return room;
}
Update 1
As you mentioned in the comments, you are using a Hashtable to implement your cache.
Be aware the put(K, V) method returns the previous value of the specified key in the hashtable, or null if it did not have one. For more details, consider reading the documentation.
Update 2
Have you ever consider using a HashMap instead of a Hashtable?
If synchronization becomes an issue, you might be interested in a ConcurrentHashMap.

URL inside of another URL (as path)

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

REST GET/POST how to send and receive complex parameters?

I am using Jersey and converting my existing data services into RESTful data services. Most simple GETs and PUTs I could successfully convert. But following are some I am not able to convert:
X Get (T) // for complex queries with complex result
X Post (T) // for creating with complex result
X PUT (T) // for updating with some success message object
where T and X are a complex objects
I have tried #queryparam, #pathparam with complex objects on GET with #consume & #produce and those didn't work. Also tried POST (though I really needed GET) with url encoded and that didn't work too.
Please Help. I am in need of sample code that does it.
REST isn't designed to handle complex queries as the query is actually the URL. When you retrieve a resource you specify the ID of the resource you want. This is simply a number or string and is easily represented in the URL for example;
http://host/employee/57
would get you employee 57. If your requirements are more complicated then you might want to use a search method, where you pass several parameters. You could use #QueryParam here but this isn't really REST in a pure form.
If you are POSTing or PUTting data then you use the same URL as you would if you were doing a GET, only this time you send data in the content body. As you are able to serialize the object in order to return it to a GET request your client should also be able to serialize it to send it to you in a PUT or POST.
Here's an example of a GET and POST;
#XmlType
public class Employee {
private int id;
private String name;
//getters and setters
}
#Path("/employee")
public class EmployeeService {
#GET
#Path("/{id}")
#Produces(MediaType.APPLICATION_XML)
public Employee get(#PathParam("id") String id) {
Employee e = employeeDao.getEmployee(id);
if (e != null) {
return e;
} else {
throw new WebApplicationException(404);
}
}
#POST
#Consumes(MediaType.APPLICATION_XML)
#Produces(MediaType.APPLICATION_XML)
public Employee post(Employee employee) {
return employeeDao.insertEmployee(employee); //Assumes your DAO sets the ID
}
}

Categories