Request method 'POST' not supported, but the method for creating objects works - postgresql

I create a CRUD application using SpringBoot. I use PostgreSQL as a database. My application also uses SpringSecurity. The methods of displaying and creating objects work perfectly. But for some reason, updating and deleting the same objects gives an error:
2022-11-01 08:51:14.602 WARN 12149 --- [io-8080-exec-10] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported]
I think the problem is in the html code. I use Thymeleaf.
**My Student Controller:
**
package ru.connor.FirstSecurityApp.controllers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import ru.connor.FirstSecurityApp.model.Student;
import ru.connor.FirstSecurityApp.services.StudentService;
import javax.validation.Valid;
import java.util.Optional;
#Controller
#RequestMapping("/students")
#RequiredArgsConstructor
public class StudentController {
private final StudentService studentService;
#GetMapping()
public String showAllClasses(Model model) {
model.addAttribute("students", studentService.showAllStudent());
return "main/AllClasses";
}
#GetMapping("/{id}")
public String showById(#PathVariable("id") int id, Model model){
Optional<Student> student = Optional.ofNullable(studentService.showStudentById(id));
if (student.isEmpty()){
return "main/students/errorPage";
}else model.addAttribute("student", student);
return "main/students/index";
}
#GetMapping("/add")
public String addStudent(#ModelAttribute("student") Student student) {
return "main/students/new";
}
#PostMapping()
public String create(#ModelAttribute("student") #Valid Student student,
BindingResult bindingResult) {
if (bindingResult.hasErrors())
return "main/students/new";
studentService.addStudent(student);
return "redirect:/students";
}
#GetMapping("/{id}/edit")
public String edit(Model model, #PathVariable("id") int id) {
model.addAttribute("student", studentService.showStudentById(id));
return "main/students/edit";
}
#PatchMapping("/{id}")
public String update(#ModelAttribute("student") #Valid Student student, BindingResult bindingResult, #PathVariable("id") int id) {
if (bindingResult.hasErrors()){
return "main/students/edit";}
studentService.update(id, student);
return "redirect:/students";
}
#DeleteMapping("/{id}")
public String delete(#PathVariable("id") int id){
Optional<Student> student = Optional.ofNullable(studentService.showStudentById(id));
if (student.isPresent()){
studentService.delete(id);
return "redirect:/students";
}
return "main/students/index";
}
}
Student Service:
package ru.connor.FirstSecurityApp.services;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ru.connor.FirstSecurityApp.model.Student;
import ru.connor.FirstSecurityApp.repository.StudentsRepository;
import java.util.List;
import java.util.Optional;
#Service
#RequiredArgsConstructor
#SuppressWarnings("unused")
#Transactional(readOnly = true)
public class StudentService {
private final StudentsRepository studentsRepository;
public List<Student> showAllStudent(){
return studentsRepository.findAll();
}
public Student showStudentById(int id){
Optional<Student> foundPerson = studentsRepository.findById(id);
return foundPerson.orElse(null);
}
#Transactional
public void addStudent(Student student){
studentsRepository.save(student);
}
#Transactional
public void update(int id, Student person){
person.setId(id);
studentsRepository.save(person);
}
#Transactional
public boolean delete(int id){
if (studentsRepository.findById(id).isPresent()){
studentsRepository.deleteById(id);
return true;
}
return false;
}
}
**HTML view where the delete form is specified:
**
<!DOCTYPE html>
<html lang="en" xmlns:th="https://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Student</title>
</head>
<body>
<h1 th:text="${student.get().getFullStudentName()}"></h1>
<hr>
<form method="post" th:action="#{/students/{id}(id=${student.get().getId()})}">
<input type="submit" value="Delete">
</form>
</body>
</html>

As you have mentioned #PatchMapping for updates then you need the HTTP PATCH method instead of POST. The same goes for delete you have used #DeleteMapping, so you need to use the HTTP DELETE method instead of POST.
Create -> POST
Read -> GET
Update -> PUT/PATCH
Delete -> DELETE
With form submit I don't think PATCH/PUT/DELETE will work so in that case you need to change #PatchMapping/#DeleteMapping to #PostMapping and update the URL so it will be unique for update/delete.
PUT/PATCH/DELETE will work with REST API only.

Related

Post get data from request body, and return json Jakarta.ws.rs

I am tasked with creating a simple web api using JAVA EE and I cant use other external frameworks such as Spring Boot.
I got the get requests to work that was simple, however when I try to return a JSON to the api all I see is {} in postman or browser even though I created a user.
here is my current code
package ab.service;
import jakarta.ws.rs.ApplicationPath;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.Application;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
#Path("/MyRestService")
#ApplicationPath("resources")
public class RestService extends Application {
// http://localhosts:8080/BankTaskV1/ressources/MyRestService/sayHello
#GET
#Path("/sayHello")
public String getHelloMsg() {
return "Hello World";
}
#GET
#Path("/echo")
public Response getEchoMsg(#QueryParam("message") String msg) {
return Response.ok("you message was: " + msg).build();
}
#GET
#Path("/User")
public Response getUser() {
// Gson gson = new Gson();
User user = new User(1, "Ahmad");
return Response.status(Response.Status.OK).entity(user).type(MediaType.APPLICATION_JSON).build();
// return gson.toJson(user);
}
#POST
#Path("/CreateUser")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public void createUser(UserRequest requestBody) {
System.out.println("create ran");
System.out.println(requestBody.UserName);
}
}
as you can see in the User endpoint I used GSON to convert user object to a json string and that worked, however I read online that it should work without it if I did it by returning an entity, something called POJO?
but that just gives me an empty {}
furthermore in the endpoint CreateUser I set it to consume json and gave it a request body with class that i defined. but when I try to print the username it gives me null, andd the create ran system output shows that the function ran.
here is my User class
package ab.service;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class User {
private int id;
private String name;
public User() {
}
public User(int id, String name) {
super();
this.id = id;
this.name = name;
}
String getName() {
return name;
}
void setName(String name) {
this.name = name;
}
int getId() {
return id;
}
void setId(int id) {
this.id = id;
}
}
and my userrequest class
package ab.service;
import javax.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.XmlElement;
#XmlRootElement
public class UserRequest {
#XmlElement
String UserName;
#XmlElement
int Id;
}

Drools : Getting the catched word in a list in THEN

Below is my pojo class
-----------------------------------pojo_Classes2.RootDoc.java-----------------------------------
package pojo_Classes2;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"content",
"person"
})
public class RootDoc {
#JsonProperty("content")
private String content;
#JsonProperty("person")
private List<String> person = null;
#JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
#JsonProperty("content")
public String getContent() {
return content;
}
#JsonProperty("content")
public void setContent(String content) {
this.content = content;
}
#JsonProperty("person")
public List<String> getPerson() {
return person;
}
#JsonProperty("person")
public void setPerson(List<String> person) {
this.person = person;
}
#JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
#JsonAnySetter
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
}
Here is the type of rule which i want to apply
$list1=[gaurav,gagan,anshu....]
...................................................................................................................
Rule1
If
content contains any of the above $list1
Then
Retrieve which name was captured in content and set person the person name in then
............................................................................................................
For eg. gaurav and gagan were captured in content then set get that gaurav and gagan were matched in content and get them back in then part.
Is it possible in drools
Yes, but create object of your class like:
when
$rd : Rootdoc(****your query****);
then
rd.setPerson(query);
end

Why #Autowired not working all the time?

Im trying to setup mongodb with SpringBoot and im not using context.xml but trying to configure with configuration class and annotations.
package com.configuration;
import com.mongodb.Mongo;
import com.mongodb.MongoClient;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
#Configuration
#EnableMongoRepositories(basePackages = "com.mongo")
public class MongoConfig extends AbstractMongoConfiguration {
#Override
protected String getDatabaseName() {
return "mongodbname";
}
#Override
public Mongo mongo() throws Exception {
return new MongoClient("127.0.0.1", 27017);
}
#Override
protected String getMappingBasePackage() {
return "com.mongo";
}
}
My repository looks like this :
package com.mongo.repositories;
import com.mongo.documents.Sequence;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Repository;
import java.util.List;
#Repository("sequenceRepository")
public class SequenceRepository{
#Autowired
private MongoTemplate mongoTemplate;
public Sequence findOne(Query query){
return this.mongoTemplate.findOne(query,Sequence.class);
}
public List<Sequence> find(Query query){
return this.mongoTemplate.find(query,Sequence.class);
}
public void save(Sequence object){
this.mongoTemplate.save(object);
}
public void delete(Sequence object){
this.mongoTemplate.remove(object);
}
}
If i use like this in the rest controller it is working properly :
package com.controllers;
import com.mongo.documents.Sequence;
import com.mongo.repositories.SequenceRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class IndexController {
#Autowired
private SequenceRepository sequenceRepository;
#RequestMapping("/")
public String index(){
Sequence sequence = new Sequence();
sequence.setClassName("class.Test");
sequence.setActual(1);
sequenceRepository.save(sequence);
return "index";
}
}
But if i want to use the SequenceRepository inside the Sequence document like this :
package com.mongo.documents;
import com.mongo.repositories.SequenceRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
#Document
public class Sequence {
#Autowired
private SequenceRepository sequenceRepository;
#Id
private String id;
private String className;
private int actual;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public int getActual() {
return actual;
}
public void setActual(int actual) {
this.actual = actual;
}
public void save(){
this.sequenceRepository.save(this);
}
public void delete(){
this.sequenceRepository.delete(this);
}
}
After that I change the code in the controller to :
package com.controllers;
import com.mongo.documents.Sequence;
import com.mongo.repositories.SequenceRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class IndexController {
#Autowired
private SequenceRepository sequenceRepository;
#RequestMapping("/")
public String index(){
Sequence sequence = new Sequence();
sequence.setClassName("class.Test");
sequence.setActual(1);
sequence.save();
return "index";
}
}
I got a nullPointerExceeption at this point in the save() method.
There is no need to inject your Repository inside your Domain object Sequence as it is really bad design to have a dependency between the domain objects and your repository classes.
To follow some good practices, your Service classes or if you don't need a Service layer, your Controller classes should inject your Repository beans.
In your last code snippet your are already doing it, but the .save() method should be called on your repository SequenceRepository and not on the domain object Sequence.
An example could be the following:
#RestController
public class IndexController {
#Autowired
private SequenceRepository sequenceRepository;
#RequestMapping("/")
public String index(){
Sequence sequence = new Sequence();
sequence.setClassName("class.Test");
sequence.setActual(1);
// now let's save it
sequenceRepository.save(sequence);
return "index";
}
}
You can only autowire Spring-managed components into other Spring-managed components. Your sequence object is not a component (not annotated with #Component, #Service, #Repository or #Controller etc.)
I suggest you follow rieckpil's advice.

SQL not invoked when SELECTing Entity with JPQL

I have a table FAQ ( Frequently asked questions )
Here's the Bean:
package projet.helpdesk.beans;
import javax.persistence.*;
#Entity
#Table(name="faq")
public class FAQ {
#Id
private int id_qr;
private int id_technicien;
private String question;
private String reponse;
public int getId_qr() {
return id_qr;
}
public void setId_qr(int id_qr) {
this.id_qr = id_qr;
}
public int getId_technicien() {
return id_technicien;
}
public void setId_technicien(int id_technicien) {
this.id_technicien = id_technicien;
}
public String getQuestion() {
return question;
}
public void setQuestion(String question) {
this.question = question;
}
public String getReponse() {
return reponse;
}
public void setReponse(String reponse) {
this.reponse = reponse;
}
}
This is the DAO class:
The function public List<FAQ> chargerFAQ() is supposed to return a list of FAQ.
The JPQL query is: private static final String JPQL_SELECT_ALL = "SELECT f FROM FAQ f";
`package projet.helpdesk.dao;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import projet.helpdesk.beans.FAQ;
#Stateless
public class FAQDao {
private static final String JPQL_SELECT_ALL = "SELECT f FROM FAQ f";
private static final String JPQL_SELECT_QR = "SELECT f FROM FAQ f WHERE id_qr=:id_qr";
private static final String PARAMETER = "id_qr";
#PersistenceContext( unitName = "bdd_helpdesk_PU" )
private EntityManager em;
public void creer( FAQ faq ) throws IllegalArgumentException, DAOException {
try {
em.persist(faq);
} catch ( Exception e ) {
throw new DAOException( e );
}
}
public List<FAQ> chargerFAQ() throws DAOException {
List<FAQ> listefaq;
Query query = em.createQuery(JPQL_SELECT_ALL);
try {
listefaq = (List<FAQ>) query.getResultList();
} catch ( NoResultException e ) {
return null;
} catch(Exception e) {
throw new DAOException(e);
}
return listefaq;
}
public FAQ trouverQR(int id_qr) throws DAOException{
FAQ qr;
Query query = em.createQuery(JPQL_SELECT_QR);
query.setParameter(PARAMETER, id_qr);
try {
qr = (FAQ) query.getSingleResult();
} catch ( NoResultException e ) {
return null;
} catch(Exception e) {
throw new DAOException(e);
}
return qr;
}
}
`
Persisting the FAQ entity was successful, but loading the data does'nt return anything, maybe the query instruction is wrong?
Here's the servlet:
`#WebServlet ( urlPatterns = { "/afficherfaq" })
public class AfficherFaq extends HttpServlet {
#EJB
private FAQDao faqDao;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.getServletContext().getRequestDispatcher("/WEB-INF/ChargerFaq.jsp").forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<FAQ> lfaq = faqDao.chargerFAQ();
request.setAttribute("lfaq", lfaq);
this.getServletContext().getRequestDispatcher("/WEB-INF/ChargerFaq.jsp").forward(request, response);
}
}
`
And the Entity's path is included in the persistence.xml file.
EDIT: Added JSP code.
JSP file to show the result:
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link type="text/css" rel="stylesheet" href="inc/style.css" />
<title>Foire aux questions</title>
</head>
<body>
Test
<c:forEach items="${lfaq}" var="faq" varStatus="boucle">
<fieldset>
<p><span class="info">Question:</span></p><br>
<p>${faq.question}</p><br>
<p><span class="info">Reponse:</span></p><br>
<p>${faq.reponse}</p><br>
</fieldset><br><br>
</c:forEach>
</body>
</html>

Web App Project, need assistance

Can someone please help, im in my first year of college and im stuck on my web development project. On my blog web page I have a list of posts which i need to arrange chronolgically (new post first). We just started arraylists in my programming class but we have not yet covered how to sort them
Were using the PLAY framework for the project consisting of models, controllers, views and routes. I have a Post Class in the models folder and a Blog Class in controllers shown below
package models;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import play.db.jpa.Model;
#Entity
public class Post extends Model
{
public String title;
#Lob
public String content;
#OneToMany
public List<Comment> comments = new ArrayList<Comment>();
public String comment;
public Post(String title, String content)
{
this.title = title;
this.content = content;
}
public String toString()
{
return title;
}
}
package controllers;
import java.util.List;
import models.Message;
import models.Post;
import models.User;
import play.Logger;
import play.mvc.Controller;
public class Blog extends Controller
{
public static void index()
{
User user = Accounts.getLoggedInUser();
render(user);
}
public static void newPost(String title, String content)
{
User user = Accounts.getLoggedInUser();
Post post = new Post (title, content);
post.save();
user.posts.add(post);
user.save();
Logger.info ("title:" + title + " content:" + content);
index();
}
public static void deletePost(Long postid)
{
User user = Accounts.getLoggedInUser();
Post post = Post.findById(postid);
user.posts.remove(post);
user.save();
post.delete();
index();
}
}
and this is the html code that displays the published posts
<section class="ui stacked segment">
<h4 class="ui inverted blue block header">Display Posts</h4>
#{list items:user.posts, as:'post'}
<h5 class="ui inverted green block header"></h5>
<i class="external url icon">${post.title}
#{/list}
</section>
Im totally lost in terms of the java part and have crashed the project numerous times trying to make it work, any help would be greatly appreciated