how to delete data from a table? - spring

I'm a laravel programmer and I have to develop a project for college in spring.
I am not able to delete data from the table.
In laravel, to delete data from the table, you have to create a form and inside this form you can pass the delete method.
I've done a lot of research but the examples don't show the html.
Controller:
// Delete
#DeleteMapping("/autor/deletar/{id}")
public void delete(#PathVariable("id") long id)
{
authorservice.delete(id);
}
AuthorServiceImplement
#Override
public void delete(Long id) {
repositorio.delete(repositorio.findById(id).get());
}
Html
<a th:href="#{/autor/deletar/{id}(id=${author.id})}">
Deletar
</a>
When I try to delete, I get an error "get method not supported". Do I have to change anything in html anyway or is there something wrong with my code?

If you are testing it via a web browser, it's always using the HTTP Method GET. You need to use Postman or Insomnia for exemple to send HTTP requests.
As you are using #DeleteMapping("/autor/deletar/{id}") it says that this function is called when doing an HTTP request to /autor/deletar/{id} with the method DELETE
EDIT
If you just want to test it via your web browser, you can always replace #DeleteMapping("/autor/deletar/{id}") by #GetMapping("/autor/deletar/{id}")

Related

Spring MVC - Error handling with redirect if download not possible

in my Spring Boot application you can download some documents, by pressing a button. This leads to the following user experience: If the user presses the button, either a download is triggered or nothing happens.
Currently, the backend is either returning the bytes or 404:
#GetMapping("/download")
public ResponseEntity<byte[]> download() {
Optional<byte[]> data = service.getDocumentData();
return data.map(bytes -> new ResponseEntity<>(bytes, headers(), OK))
.orElseGet(() -> ResponseEntity.notFound().build());
}
Now we want to achieve, that the user is redirected to an error page, if no file can be downloaded.
With Spring MVC I would just return the error template like
public String notFound() {
return "error/404"; // the custom template
}
But now I need to mix two different concerns. Returning template or returning a ResponseEntity. For this i stumbled above the following answer, which uses Generics. However, I don't think its a good practice. So i thought about other ways.
My first idea was to use HTTP location header for redirecting on the frontend side, but I never used it before. Do you think this is a good way? Do you have other ideas?
Suggestion 1:
In the download() method, add HttpServletResponse response as the parameter and call response.sendRedirect("http://somewhere/404.html"); when the document requested is not found.
In addition, you can also change the status code in the response as response.setStatus(HttpServletResponse.SC_NOT_FOUND);
Suggestion 2:
Throw a custom exception, for e.g. FileNotFoundException and handle the exception in the #ExceptionHandler to return the error page in the ResponseEntity.
Refer - https://howtodoinjava.com/spring-core/spring-exceptionhandler-annotation/

Why is the ID in the URL checked against the ID in the model/hidden input when posting an edit action in scaffodled code?

If you create an "MVC Controller with view, using Entity Framework" using Visual Studio scaffolded code, an Edit method is created to respond to POST. This method contains a the check if (id != movie.ID) which appears to have no real value. This same pattern is used in the ASP.NET Core 3.1 tutorial:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ID,Title,ReleaseDate,Genre,Price")] Movie movie)
{
if (id != movie.ID)
{
return NotFound();
}
...
The docs state
The HttpGet Edit method takes the movie ID parameter, looks up the movie using the Entity Framework FindAsync method, and returns the selected movie to the Edit view. If a movie cannot be found, NotFound (HTTP 404) is returned.
What is the purpose of this check?
It appears to have no real value - the client appears to be sending both values.
Should I remove it? Should I keep it?
I think this is just a sanity check, to make sure the ID the client is posting to matches the ID in the data the client attaches in the POST request.
If the user is using the form from the view to submit the POST request, I don't see how you can get different value for the ID. But just in case of a client submitting the form without using your view, those ID values could be different. One of the examples could be using Postman.
If the POST URL is /movie/edit/7, but ID from the post body is 6 for example, your application/you will need to decide what to do. So it's you, as the developer, to determine whether it has value or not to add a check like that.
I usually just ignore the ID from the URL if it's a POST request. There shouldn't be an ID on the URL if it's well constructed RESTful API endpoint anyway. So instead, my Controller will only work with the data from the posted-back view model:
[HttpPost]
//[ValidateAntiForgeryToken] - I think ASP.NET Core MVC automatically has that on
public async Task<IActionResult> Edit(MovieViewModel vm)
{
if (ModelState.IsValid)
{
...
}
...
}
According to Microsoft
The scaffolder generates that. Feel free to remove it. In some cases it may be needed.

which crud operation in rest to use post or delete?

i have created a bank application where i want to write a rest service to delete account . so for that we need an account no . for that i think for security reasons i cant pass account no in url . so i am passing it in request body . i think if i try using it with delete it runs fine but again that could be a security issue .
so in that case will i need to use post instead of delete so that i can pass account no in request body ?
#PostMapping("/account")
public void deleteAccount(#RequestBody #Valid final AccountNoDto accountNoDto) {
return accountService.deleteAccount(accountNoDto);
}
or
#DeleteMapping("/account/{accountNo}")
public void deleteAccount(#PathVariable Long accountNo) {
return accountService.deleteAccount(accountNo);
}
You should use #DeleteMapping because you are deleting a record.
The HTTP verbs should be compliant with what the function does.
But dont send the account Number along with the endPoint.
Write the endpoint as -
#DeleteMapping("/account")
The Account Number should be retrived at the backend from the token you will be sending along with the request.So All requests GET,POST,PUT,DELETE will have the same uri and the account number will be fetched from the token at the backend.
If you want to know how it is done in spring read about SecurityContextHolder class
Idealy we use #DeleteMapping for delete operation and we use #PostMapping for new creation and updation of data . I dont think account id is that much sensitive information to reveal in url. You can go for #DeleteMapping

How to call the WebApi,Implemented with AttributeRouting for each action methods,calling it from my client and passing the Query parameters in url?

I have implemented attribute routing for each of action methods in My Webapi.
Example of action method is:-
[Route("api/DocumentApi/DeleteDocument/{fileInfoId}/{customerAccountName}")]
[HttpDelete]
public HttpResponseMessage DeleteDocument(int fileInfoId, string customerAccountName)
{
//***
//*** Some body contents
//***
}
Now i want to call the above action method from the client example( Fiddler Web debugger),or browser and want to pass the Url request in the below pattern:-
http://{localhost:9791}/api/DocumentApi/DeleteDocument?fileInfoId=12&customerAccountName="Manish"
Currently i am not able to hit the above action method by the above specified url request.
But if i use the url pattern like below:-
http://{localhost:9791}/api/DocumentApi/DeleteDocument/12/Manish
I am able to hit the above action method.But for my project requirement,I need to use the Url with query parameters only.
Please suggest me the approach,how to achieve this?
Any response will be greatly appreciated.
Route templates in Web API do not support specifying query string parameters. For your scenario, do not define fileInfoId and customerAccountName as part of your route template as doing so makes Web API to strictly look for 5 segments(the text between the / characters in your route template) in your request url...so just modify your route template to [Route("api/DocumentApi/DeleteDocument")] and keep the parameters on the actions as it is...
Use like following code :
[Route("api/DocumentApi/DeleteDocument/{fileInfoId}/{customerAccountName}")]
public HttpResponseMessage TestAction(string fileInfoId,string customerAccountName)
{

REST, Spring MVC 3 and PUT request with AJAX

I guess I'm looking more for advice than any specific coding solutions. Here's the scenario:
I have a form where a new user can be created
This form is accessed via a GET request through a Spring controller
#RequestMapping(value = "/secure/clients", method = RequestMethod.GET)
public String prepareNewClient(final Principal principal, final ModelMap map) {
map.addAttribute("client", new Client());
return "secure/clients";
}
The form is presented, all works fine and I submit the new client using $.ajax({})
The submission triggers a POST request using the same URL to the following method on my controller
#RequestMapping(value = "/secure/clients", method = RequestMethod.POST)
public #ResponseBody JsonResponse saveClient(
#ModelAttribute("client") final Client client,
final BindingResult result,
final Principal principal,
final ModelMap map) {
// validate input
// save client
// prepare JsonResponse object
return jsonResponse;
}
After completion, I want to keep the user on the same screen and have the form trigger a PUT instead of a POST. Which is fine, I can achieve that with jQuery, but as soon as I submit the form again, the client is not on the ModelMap anymore.
I have even tried adding the saved client to the ModelMap of my POST method but even that didn't work.
I'm not entirely sure if I'm doing it the right way. To be honest, every tutorial I've seen uses more or less what I'm doing but NONE of them have a PUT request - mostly deal with creation of objects, which I don't have an issue.
What I have in mind is that I might need to have a controller method mapping to /secure/clients/{clientId} with HTTP.GET and another controller method mapping /secure/clients/{clientId} with HTTP.PUT.
But I'm not sure if that makes sense, so I'm a bit lost.
Should I create my controllers entirely on JSON calls?
Should I redirect the user and forget about AJAX calls in this scenario?
Suggestions are more than appreciated. Thank you!
HttpMethod are not enterely support by web browsers. PUT requesr works great when two applications are working with Restfull API's, but for browser compatibility, it is better to limit yourself to POST or GET request.
You can also put a override parameter in your form to instruct the web server to handle the post as the desired method.
<input type="hidden" name="_method" value="put"/> would do the job.
Spring sf namespace takes care of that hidden field for you.
<sf:form method="put">
....
</sf:form>
In addition, you can test your controller with restclient-ui to see if the problem comes from your WebServer or your client.
I agree with #Daniel.
But you can use HiddenHttpMethodFilter available in Spring. That should make your work easy. You will no longer need to put the hidden filed every time.
Hope that helped. Cheers.
#Daniel and #Japan thank you very much for your answers.
I figured what you said #Daniel and I ended up stepping out of the box and thinking differently - and it worked great.
Just to give you an idea:
Instead of staying on the page, when a new client is inserted I actually refresh the browser
After the function is called the user gets redirected to /secure/clients/{clientId}
From there on a new function is mapped, along with a new POST request
It worked for me. And leveraging from Knockout.JS helped a lot as well.
Thanks again!

Resources