I saw some NullPointerExceptions in the log. All the exceptions are from two users. The spring controller is supposed to received the form object that the user uploaded. However it is null.
This is the jsp code of the form:
<form method="POST" action="/events/${id}/tickets/checkout" id="checkout-info-form">
<label> Recipient Name <input id="recipient" type="text" name="recipient"></label>
<label class="address-row checkout-hidable"> Address Line 1 <input id="address1" type="text" name="addressLine1"> </label>
<label class="checkout-hidable"> Address Line 2 (optional) <input id="address2" type="text" name="addressLine2"> </label>
<label class="city-row checkout-hidable"> City <input type="text" id="city" name="city" placeholder="e.g. New York"> </label>
<label class="state-row checkout-hidable"> State <input type="text" id="state" name="state" placeholder="e.g. NY"> </label>
<label class="zip-row checkout-hidable"> Zip Code <input type="text" id="zip" name="zip" placeholder="e.g. 12345"> </label>
<label class="shipping-row">Shipping Method:</label>
<label class="shipping-method">
<input type="radio" name="shipping" value="usps_5days" id="shipping1">
<span>USPS 3-5 days shipping</span> $5.99
</label>
<label class="shipping-method">
<input type="radio" name="shipping" value="usps_1days" id="shipping2">
<span>USPS overnight shipping</span> $19.99
</label>
<c:set var="index" value="${0}"/>
<c:forEach items="${tickets}" var="ticket">
<input type="hidden" name="tickets[${index}]" value="${ticket.id}">
<c:set var="index" value="${index + 1}"/>
</c:forEach>
<c:remove var="index"/>
<input id="checkout-info-form-submit-button" class="btn-blue-large" type="submit" name="submitbutton" value="Next step">
</form>
This is the model object that I use to receive the form:
public class CheckoutInfo implements Serializable {
private static final long serialVersionUID = 2585075011792338943L;
private String recipient;
private String addressLine1;
private String addressLine2;
private String city;
private String state;
private String zip;
private String shipping;
private String[] tickets;
public CheckoutInfo() {
}
}
The controller:
#RequestMapping(value="/events/{eventId}/tickets/checkout", method=RequestMethod.POST)
public ModelAndView purchaseTickets(
#PathVariable("eventId") long id,
CheckoutInfo checkoutInfo,
RedirectAttributes redir,
#AuthenticationPrincipal User user) {
......
}
The null pointer exception occurs because checkoutInfo is null. I don't know why this could happen. I never seen this happen. And this only come from a few of our users. I am using spring boot v1.2.3.RELEASE
I appreciate it if anyone could help.
Related
I'm a bit at a loss here.
I have a thymeleaf page and a spring-boot backend that takes in a user object, getting the object to the page is fine, my problem comes in when I'm trying to get it to the back end to do stuff with it.
I keep getting the following
2021-09-15 09:21:07.834 WARN 3624 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported]
and on the browser
Failed to load resource: the server responded with a status of 405 ()
for my controller I have the following
#Controller("/user")
public class UserController {
#Autowired
private UserService userService;
#Autowired
private ModelMapper modelMapper;
#RequestMapping(value = "/add")
public String addUser(#ModelAttribute("user") final UserDto userDto) {
//do stuff
//userService.save(modelMapper.map(userDto, User.class));
return "/user";
}
}
as for my thymeleaf page
<form th:action="#{/user/add}" th:object="${user}" method="post">
<label for="fullName">Full Name</label>
<input id="fullName" class="form-control form-group" type="text" th:field="*{fullName}">
<label for="email">Email</label>
<input id="email" class="form-control form-group" type="email" th:field="*{email}">
<label for="password">Password</label>
<input id="password" class="form-control form-group" type="password" th:field="*{password}">
<p>
<button class="form-group form-control btn btn-primary" type="submit" value="Submit">Submit</button>
</p>
</form>
What am I missing here?
I did try to mess around the #GetMapping, #PostMapping, #RequestMapping(method = GET), #RequestMapping(method = POST), #RequestMapping(method = {GET, POST})
I also tried <form ... th:method="post"> and <form ... th:method="get">
But none of these seems to work.
You add global /user in #Controller. this annotation is used to implement Web Application not for path and it is better to give global path in application.properties like below code. Inside addUser() method you want to return with page name like return "user" if go to the url then put return "redirect:/user"
Here down is modified code:
application.properties
server.servlet.contextPath=/user/
Controller
#Controller
public class UserController {
#Autowired
private UserService userService;
#Autowired
private ModelMapper modelMapper;
#RequestMapping(value = "/add", method = RequestMethod.POST)
public String addUser(#ModelAttribute("user") final UserDto userDto) {
//do stuff
//userService.save(modelMapper.map(userDto, User.class));
return "pagename"; // enter page name where you wanna go not url
}
}
Template
<form th:action="#{/add}" th:object="${user}" method="post">
<label for="fullName">Full Name</label>
<input id="fullName" class="form-control form-group" type="text" th:field="*{fullName}">
<label for="email">Email</label>
<input id="email" class="form-control form-group" type="email" th:field="*{email}">
<label for="password">Password</label>
<input id="password" class="form-control form-group" type="password" th:field="*{password}">
<p>
<button class="form-group form-control btn btn-primary" type="submit" value="Submit">Submit</button>
</p>
</form>
I trying persist this entity:
#Entity
public class Cliente extends Model {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
#OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private Usuario usuario;
#OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private org.loja.model.cesta.Cesta cesta;
#OneToMany(fetch = FetchType.EAGER, cascade=CascadeType.ALL)
#OrderColumn
private List<org.loja.model.pedido.Pedido> pedidos;
public Cliente() {
this.usuario = new Usuario();
this.cesta = null;
this.pedidos = null;
}
}
with this form:
<form class="form-signin" id="form" method="post" th:action="#{/register}">
<label for="username" class="sr-only">Username</label>
<input type="text" name="usuario.username" id="username" class="form-control" placeholder="Username" required autofocus>
<label for="password" class="sr-only">Password</label>
<input type="password" name="usuario.password" id="password" class="form-control" placeholder="Password" required>
<label for="firstName" class="sr-only">Nome</label>
<input type="text" name="usuario.firstName" id="firstName" class="form-control" placeholder="Nome" required>
<label for="lastName" class="sr-only">Sobrenome</label>
<input type="text" name="usuario.lastName" id="lastName" class="form-control" placeholder="Sobrenome" required>
<label for="email" class="sr-only">E-mail</label>
<input type="email" name="usuario.email" id="email" class="form-control" placeholder="E-mail" required>
</form>
I also tried this:
<form class="form-signin" id="form" method="post" th:object="${command}" th:action="#{/register}">
<label for="username" class="sr-only">Username</label>
<input type="text" th:field="*{usuario.username}" id="username" class="form-control" placeholder="Username" required autofocus>
<label for="password" class="sr-only">Password</label>
<input type="password" th:field="*{usuario.password}" id="password" class="form-control" placeholder="Password" required>
<label for="firstName" class="sr-only">Nome</label>
<input type="text" th:field="*{usuario.firstName}" id="firstName" class="form-control" placeholder="Nome" required>
<label for="lastName" class="sr-only">Sobrenome</label>
<input type="text" th:field="*{usuario.lastName}" id="lastName" class="form-control" placeholder="Sobrenome" required>
<label for="email" class="sr-only">E-mail</label>
<input type="email" th:field="*{usuario.email}" id="email" class="form-control" placeholder="E-mail" required>
</form>
But I keep getting the error:
java.lang.IllegalArgumentException: attempt to create event with null entity
when I try submit the data.
my controller:
#RequestMapping(value = "/register", method=RequestMethod.GET)
public String formRegister(Model model) {
model.addAttribute("command", new Cliente());
return "register";
}
#RequestMapping(value = "/register", method=RequestMethod.POST)
#ResponseBody
public void doRegister(#ModelAttribute("cliente") Cliente object) throws Exception {
home.register(object);
}
Anyone can give a hint of what's wrong here?
adding in form is trivial when I have only one object like here:
<form th:action="|#{group/save}/${id}|" th:object="${groupForm}" method="post" class="col m8 s8 offset-m2">
<div class="row">
<div class="input-field">
<input th:field="${groupForm.name}" id="name" type="text" required="required"/>
<label for="name">Nazwa:</label>
</div>
</div>
<div class="row">
<button class="btn-success" type="submit" name="save">Wyślij<i class="mdi-content-send right"></i></button>
</div>
</form>
but let's assume that groupForm have list of customer
public class Customer{
private long id;
private String firstName;
private String lastName;
private String nick;
}
How can I add 5 Customers into list in class Group? I want to achive in one request.
Assuming that your Group class looks something like this:
public class Group {
private List<Customer> customers;
}
Try this:
<input th:field="*{customers[0].name}" type="text" required="required"/>
<input th:field="*{customers[1].name}" type="text" required="required"/>
<input th:field="*{customers[2].name}" type="text" required="required"/>
<input th:field="*{customers[3].name}" type="text" required="required"/>
<input th:field="*{customers[4].name}" type="text" required="required"/>
Hello I want to update User entity, so in the form edit.html i'm using thymeleaf:
<form action="#" th:action="#{/{id}/edit(id=${user.id})}"
th:object="${user}" method="post">
<div class="md-form">
<input type="text" th:field="*{firstName}"
th:value="${user.firstName}" name="firstName" id="firstName"
class="form-control" /> <label class="active" for="firstName">Prénom</label>
</div>
<div class="md-form">
<input type="text" th:field="*{lastName}"
th:value="${user.lastName}" name="lastName" id="lastName"
class="form-control" /> <label class="active" for="lastName">Nom</label>
</div>
<div class="md-form">
<input type="text" th:field="*{email}" th:value="${user.email}"
name="email" id="email" class="form-control" /> <label
class="active" for="email">email</label>
</div>
<div class="md-form">
<input type="text" th:field="*{password}"
th:value="${user.password}" name="password" id="password"
class="form-control" /> <label class="active" for="password">mot
de passe</label>
</div>
<div class="md-form">
<input type="text" th:field="*{occupation}"
th:value="${user.occupation}" name="occupation" id="occupation"
class="form-control" /> <label class="active" for="occupation">profession</label>
</div>
<div class="md-form">
<input type="text" th:field="*{ville}" th:value="${user.ville}"
name="ville" id="ville" class="form-control" /> <label
class="active" for="ville">ville</label>
</div>
<div>
<input class="btn btn-sm btn-primary waves-effect btn-rounded"
type="submit" value="modifier" />
</div>
</form>
User.java:
#Entity
#Table(name = "users")
public class User {
#Id
#GeneratedValue
private Long id;
private String firstName;
private String lastName;
private String userName;
private int age;
private String ville;
private String email;
private String password;
private String phone;
private String company;
private String occupation;
private String img_profil;
#ManyToMany(mappedBy = "users", cascade = { CascadeType.ALL })
private Set<Discussion> discussion;
UserController.java
#GetMapping("/{userName}/edit")
public String editUser(#PathVariable String userName, Model model) {
User user = ur.findByUserName(userName).get(0);
model.addAttribute(user);
return "edit";
}
#PostMapping("/{id}/edit")
public String updateUser(#ModelAttribute("user") User user, #PathVariable("id") Long id) {
user = ur.findOne(id);
ur.save(user);
return "redirect:/find/" + user.getUserName();
}
UserRepository.java
#Repository
public interface UserRepository extends CrudRepository<User, Long> {
List<User> findByUserName(String userName);
}
PROBLEM is in the console I do not see update request (generated by Hibernate), nothing is changed on the database.
Make the following change in UserController.java:
#PostMapping("/{id}/edit")
public String updateUser(
#ModelAttribute("user") User user,
#PathVariable("id") Long id)
{
//user = ur.findOne(id);
user.setId(id);
ur.save(user);
return "redirect:/find/" + user.getUserName();
}
I'm making a registration page for a website. I understand that in order for a new User to be created, an id is required, so we have the field:
<input type="hidden" th:field="{*id} />
However, when I go to the page, I get the error I mentioned in this post's title.
Here is the form in question:
<form th:action="#{/users/register}" th:object="${user}" class="form-signin" method="POST">
<h2 class="form-signin-heading">Register</h2>
<input type="hidden" th:field="*{id}" />
<label for="inputUsername" class="sr-only">Username*</label>
<input type="text" th:field="*{username}" name="username" id="inputUsername" class="form-control" placeholder="Username" required="required" autofocus="autofocus" />
<label for="inputEmail" class="sr-only">Email Address*</label>
<input type="text" th:field="*{email}" name="email" id="inputEmail" class="form-control" placeholder="Email address" required="required" autofocus="autofocus" />
<label for="inputPassword" class="sr-only">Password</label>
<input type="password" th:field="*{password}" name="password" id="inputPassword" class="form-control" placeholder="Password" required="required" />
<label for="inputConfirmPassword" class="sr-only">Confirm Password</label>
<input type="password" th:field="${confirmPassword}" name="confirmPassword" id="inputConfirmPassword" class="form-control" placeholder="Confirm password" required="required" />
<button class="btn btn-lg btn-primary btn-block" type="submit">Register</button>
</form>
Here is my UserController:
#RequestMapping("/register")
public String registerAction(Model model) {
model.addAttribute("user", new User());
model.addAttribute("confirmPassword", "");
return "views/users/register";
}
#RequestMapping(value="/register", method = RequestMethod.POST)
public String doRegister(User user) {
User savedUser = userService.save(user);
return "redirect:/"; //redirect to homepage
}
And the first part of the User entity:
#Entity
#Table(name = "users")
public class User {
// Default constructor require by JPA
public User() {}
#Column(name = "id")
#Id #GeneratedValue
private Long id;
public void setId(long id) {
this.id = id;
}
public long getId() {
return id;
}
From what I can see, there's nothing wrong here so I'm stuck.
I'm following this example: https://github.com/cfaddict/spring-boot-intro
Any ideas?
The problem is the way you have declared your id property. The field uses a reference type Long which is null. The getter uses a primitive long. When Spring accesses the id field it tries to unbox a null value causing an error. Change your domain class to be
#Entity
#Table(name = "users")
public class User {
// Default constructor required by JPA
public User() {}
#Id
#Column(name = "id")
#GeneratedValue
private Long id;
public void setId(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
}
I don't know if you have a class like this
#Controller
#RequestMapping("/users")
public class MyController{
#RequestMapping("/register")
public String registerAction(Model model) {
model.addAttribute("user", new User());
model.addAttribute("confirmPassword", "");
return "views/users/register";
}
#RequestMapping(value="/register", method = RequestMethod.POST)
public String doRegister(User user) {
User savedUser = userService.save(user);
return "redirect:/"; //redirect to homepage
}
}
becouse if you don't have the #RequestMapping("/users") this is a problem becous if you dont have this annotation in you class the correct actione in the thymeleaf templace should be "#{/register}" other wise yon don't have the endpoint pubblished in other words with the methods that you posted you should have a template like this:
<form th:action="#{/register}" th:object="${user}" class="form-signin" method="POST">
<h2 class="form-signin-heading">Register</h2>
<input type="hidden" th:field="*{id}" />
.... should be as you written
<input type="password" th:field="*{confirmPassword}" id="inputConfirmPassword" class="form-control" placeholder="Confirm password" required="required" />
<button class="btn btn-lg btn-primary btn-block" type="submit">Register</button>
</form>
reading beter the your html you probably should have th:field="*{confirmPassword}" and not th:field="${confirmPassword}".
another think that in my opinion don't works is that you repeate name attribute. The my advice is don't repeate and let to thymeleaf the work of build the correct attribute for databinding.