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.
Related
Day 1: Added below rest endpoint for delete operation.
#Path("/company/v1/department")
#Component
public class ManageResource {
#DELETE
#Path("/{identifier}/{identifier_value}/employee")
public void delete(#PathParam("identifier") String identifier,
#PathParam("identifier_value") final String identifierValue,
#QueryParam("age") final String age) {
//delete operation
}
}
I was able to invoke DELETE endpoint using postman with below request:
DELETE: http://localhost:8080/company/v1/department/name/baner/employee?age=50
Day 2: Added below rest endpoint for the update operation in the same resource.
#Path("/company/v1/department")
#Component
public class ManageResource {
#DELETE
#Path("/{identifier}/{identifier_value}/employee")
public void delete(#PathParam("identifier") String identifier,
#PathParam("identifier_value") final String identifierValue,
#QueryParam("age") final String age) {
//delete operation
}
#PUT
#Path("/empid/{value}/employee")
#Consumes(MediaType.APPLICATION_JSON)
public void update(#PathParam("value") final String identifierValue,
#RequestBody final EmployeeUpdateRequest request) {
//update operation
}
}
After adding this new endpoint, I am able to invoke PUT using postman with below request:
PUT: http://localhost:8080/company/v1/department/empid/epid-123/employee
{
//Json request body
}
But when I try to invoke Delete endpoint it is giving me 405 (Method Not Allowed) error.
If I comment my new Put method, then the Delete method works fine.
Also, if I replace Path for Put method to "/{identifier}/{identifier_value}/employee" then both Delete and Put method works fine.
I am using Jersey 1.19 with tomcat.
Can someone help me with this?
Your Paths are in conflict with each other. Let me try to explain:
DELETE = /{identifier}/{identifier_value}/employee
PUT = /empid/{value}/employee
That means when we evaluate the path from left to right, we can either have
{identifier} which is anything or
"empid" which is a fixed string
Jersey always tries to find the "most perfect" match for a REST endpoint. It does so by evaluating the path from left to right.
Fixed strings always take precedence before random variables!
Basically that means when you want to call a DELETE, you cannot have the value "empid" for the variable "{identifier}" because then you are already out-of-scope
So the DELETE call to
http://localhost:8080/company/v1/department/empid/empid-123/employee
will not work as Jersey had to make a decision whether "empid" in the request matches "{identifier}" (DELETE) or "empid" (PUT). And as i tried to explain above, fixed strings take a higher priority.
In contrast, any other DELETE request where
http://localhost:8080/company/v1/department/{identifier}/empid-123/employee
and
{identifier} != "empid"
works.
Possible solution:
make your rest endpoints resource-oriented
DELETE:
/employee/{employee-id}
PUT:
/employee/{employee-id}
Notice how the endpoints are identical, since other than the ID in most systems, no information is needed to identify an entity.
I'm quite new to reactor and I've been stuck for too much time with the following code that doesn't work for me and I don't know what to do next.
I have simplified my code as follow :
#RestController
public class HelloController {
#Autowired
#Qualifier("currentUserService")
private CurrentUserContextService userContextService;
#GetMapping("/v1/hello2")
public Mono<PulseUser> getHello2() {
final Mono<PulseUser> currentUser2 = Mono
.just(new PulseUser("login", "pasdsword", Collections.emptyList(), 65));
currentUser2.subscribe(user -> {
System.out.println("+++++++++" + user);
});
userContextService.getCurrentUser().subscribe(user -> {
System.out.println("*************" + user);
});
return userContextService.getCurrentUser();
}
}
with userContextService like this :
#Service("currentUserService")
public class CurrentUserContextServiceImpl implements CurrentUserContextService {
#Override
public Mono<PulseUser> getCurrentUser() {
final Mono<SecurityContext> context = ReactiveSecurityContextHolder.getContext();
return context.map(security -> {
final PulseUser details = (PulseUser) security.getAuthentication().getDetails();
return details;
});
}
}
With this, code, here what I get :
If I hit /v1/hello2, I get a json response with the current User : OK
I also get the 1st Sysout , the one with the "+++" delimiter : OK
But I don't get the second one, the one with the "****" delimiter : KO
Which I diagnose this way :
I get the json response, proving that getCurrentUser() does work.
I get the first sysout, that proves that the subscribe code does work
I don't get the second sysout which I absolutly cannot understand.
Obviously, I'm interested in the 2nd sysout, because it looks like the code I'd like to get to work, which is :
call the myMethod(PulseUser myUser) where myUser comes from the userContextService.getCurrentUser().
A bit clearer :
public void touch(MyData data) {
//use the mono value of userContextService.getCurrentUser()
//and call a method on data using the current PulseUser of the Mono
}
Can someone wise help me please ?
Finally, solution was found using this post ReactiveSecurityContextHolder is empty in Spring WebFlux
I was trying to access the security context outside of the flux, which caused an empty Mono.
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 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
I'm writing applications with Java backend and frontend in AngularJS. My problem is that I can not get data in JavaScript Controller. Although Java server sends the data correctly.
Java - Service:
#GET
#Path("/get/list/{id}")
#Produces("application/json")
public List<Room> getList(#PathParam("id") int id) {
List<Room> list = service.getList(id);
return list;
}
JavaScript - Service:
app.factory("BuildingService", function($resource, $q) {
var BuildingService,
Rooms = $resource("/api/rest/room/get/list/:id", {
id: "#id"
});
BuildingService = {
getListRooms: function(id) {
return Rooms.get({id: id}).$promise;
}
};
return BuildingService;
});
JavaScript - Controller:
app.controller("BuildingController", function($scope, $routeParams, BuildingService) {
BuildingService.getListRooms($routeParams.id).then(function(list) {
$scope.rooms = list;
}, function(err) {
console.error(err);
});
});
error in console:
Error: [$resource:badcfg] http://errors.angularjs.org/1.2.14/$resource/badcfg?p0=object&p1=array
I do not understand this error.
Please help
Regards,
You are returning from backend side List i.e. collection of rooms , so you should use query method of angular js instead of get. In your BuildingRoomService change get to query
The link that the angular error tells you what the problem is
"To resolve this error, make sure your $resource configuration matches
the actual format of the data returned from the server."
the $resource call is expecting a json array response but apparently receives an object. Check to see what is actually returned by the server, the actual json response.
Your issue may be related to this other issue: Spring 3 ArrayList serialization to JSON with Jackson without wrapping to object (without name)