I'm attempting to utilize a REST API which is created using Spring by using AngularJS controllers. All I want to do, is send the credentials from the form using AngularJS to the Spring controllers in the back end; however, they don't seem to be communicating at all. Whenever I push the login button, the page simply refreshes. I placed loggers in the Spring controller I'm attempting to call, but they never print anything out which means the controller is never being called.
AngularJS controller:
angular.module('landing', [ 'ngRoute' ])
.controller('authentication',
function($rootScope, $scope, $http, $location) {
$scope.credentials = {};
$scope.login = function() {
$http.post('http://localhost:8090/login', $.param($scope.credentials), {
headers : {
"content-type" : "application/json"
}
}
};
});
The Spring controller I'm attempting to utilize:
#RequestMapping(value = "/login", method = RequestMethod.POST)
public ResponseEntity<BusinessUser> login(#RequestBody BusinessUser inputUser) {
logger.info(inputUser.getUsername());
logger.info(inputUser.getPassword());
BusinessUser requestedUser = businessUserService.findByUsername(inputUser.getUsername());
if(requestedUser != null)
if(BCrypt.checkpw(inputUser.getPassword(), requestedUser.getPassword()))
return new ResponseEntity<>(requestedUser, HttpStatus.OK);
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
Lastly, here's the form:
<body data-spy="scroll" data-target=".navbar" ng-app="landing">
<div id="home" class="border-shadow">
<div class="container-fluid container-background-color">
<div class="row border-shadow">
<div class="col-lg-7">
<h2 class="heading-margin main-color"><img class="imagesize" src="images/icon.png"/><b>Test Company</b></h2>
</div>
<div class="col-lg-5" ng-controller="authentication">
<form role="form" ng-submit="login()">
<div class="form-group row row-margin">
<div class="col-lg-5">
<input type="text" class="form-control" ng-model="credentials.username" placeholder="Username" required>
</div>
<div class="col-lg-5">
<input type="password" class="form-control" ng-model="credentials.password" placeholder="Password" required>
Forgot Your Password
</div>
<div class="col-lg-2">
<button type="submit" class="btn btn-success">Log in</button>
</div>
</div>
</form>
</div>
</div>
</div>
I can send requests using a Chrome add on called "Postman" and the results come back perfectly, so it's an AngularJS problem. Any idea what's wrong?
EDIT This is a Spring Boot project by the way.
Related
I'm trying to develop an application in spring boot + thymeleaf, and I'm able to retrieve the logged in user details in the profile tab from the MySQL database, but when I try to change one or two field details (update) and hit the update button it is showing me an error message - Fri Sep 04 20:39:47 IST 2020
There was an unexpected error (type=Method Not Allowed, status=405).
Request method 'POST' not supported
see my controller code (I'm using #RestController annotated on top of the class)-
#RequestMapping(value = "/profile", method = RequestMethod.PUT)
public ModelAndView updateProfile(#ModelAttribute Customer customer, HttpSession session) {
ModelAndView model = new ModelAndView();
Customer exist = cRepo.findByCustEmail(customer.getCustEmail());
if(exist != null) {
if(exist.getCustEmail().equals(session.getAttribute("emailsession"))) {
cRepo.save(customer);
model.addObject("msg", "User Details has been successfully updated!!");
model.setViewName("profile");
}
}else {
model.addObject("exist", "Please enter correct email address!");
String email = (String) session.getAttribute("emailsession");
Customer cust = cRepo.findByCustEmail(email);
model.addObject("customer", cust);
model.setViewName("profile");
}
return model;
}
Thymleaf code (html) -
<div align="center" class="alert alert-success" th:if="${msg}" th:utext="${msg}"></div>
<div align="center" class="alert alert-danger" th:if="${exist}" th:utext="${exist}"></div>
<!-- Modal HTML -->
<div id="myModal">
<div class="modal-dialog modal-login">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Profile Details</h4>
</div>
<div class="modal-body">
<form name="myForm" th:action="#{/profile}" th:object="${customer}" method="post">
<div class="form-group">
<i class="fa fa-id-card"></i>
<input name="id" type="text" class="form-control" placeholder="Enter Id" th:field="${customer.custId}" disabled="true" required="required" />
</div>
<div class="form-group">
<i class="fa fa-user"></i>
<input name="name" type="text" class="form-control" placeholder="Enter Name" th:field="${customer.custName}" required="required" />
</div>
<div class="form-group">
<i class="fa fa-envelope"></i>
<input name="email" type="email" class="form-control" placeholder="Enter Email" th:field="${customer.custEmail}" required="required" />
</div>
<div class="form-group">
<i class="fa fa-lock"></i>
<input name="password" type="text" class="form-control" placeholder="Enter Password" th:field="${customer.custPassword}" required="required" />
</div>
<div class="form-group">
<input type="submit" class="btn btn-primary btn-block btn-lg" value="Update" />
</div>
</form>
</div>
</div>
</div>
</div>
I want when user login and visit he/she should be able to check his/her profile(which I'm able to do working code) and when the user wants to update few fields(1-2 based on choice) and hit update he/she should be able to update the details (not create new user or record) because when I use #Controller on top of class then this code work and create new user instead update.
Your controller is annotated with #RequestMapping(value = "/profile", method = RequestMethod.PUT) which makes it a PUT endpoint. However, your request is clearly a POST. If we look at your html form it contains method="post". HTML forms only support GET and POST as valid methods so you need to update your endpoint to be a POST endpoint.
tldr;
RequestMapping(value = "/profile", method = RequestMethod.PUT)
to
RequestMapping(value = "/profile", method = RequestMethod.POST)
You request mapping in is POST but Controller has set to accept request as PUT.
<form name="myForm" th:action="#{/profile}" th:object="${customer}" **method="post"**>
#RequestMapping(value = "/profile", method = **RequestMethod.PUT**)
Just keep these in similar way both should be same.
Please check what I find and resolve this.
#RequestMapping(value = "/profile" ,method = RequestMethod.POST)
public ModelAndView updateProfile(#ModelAttribute Customer customer, HttpSession session) {
ModelAndView model = new ModelAndView();
Customer exist = cRepo.findByCustEmail(customer.getCustEmail());
if(exist != null) {
if(exist.getCustEmail().equals(session.getAttribute("emailsession"))) {
**exist.setCustId(exist.getCustId());
exist.setCustName(customer.getCustName());
exist.setCustEmail(customer.getCustEmail());
exist.setCustPassword(customer.getCustPassword());**
cRepo.save(exist);
model.addObject("msg", "User Details has been successfully updated!!");
model.addObject("customer", exist);
model.setViewName("profile");
}
}else {
model.addObject("exist", "Please enter correct email address!");
String email = (String) session.getAttribute("emailsession");
Customer cust = cRepo.findByCustEmail(email);
model.addObject("customer", cust);
model.setViewName("profile");
}
return model;
}
I have a spring boot project. In that I want to search details by using employee ID .
I got result in postman when I get empData by using id.
But I didn't work in angular. I kept search bar to get details but it not get the employee details when I enter id in searchbar.
Can anyone please solve this solution.I will give the basic code
This is my spring boot controller class of employee code
#GetMapping("/findemp/{id}")
public EmployeeEntity findEmployee(#PathVariable int id){
return empRepository.findByid(id);
}
serarchComponent.ts
export class SearchDeleteComponent implements OnInit {
emps:Observable<Emp[]>;
emps1:any;
id:number;
constructor(public empService: EmpRegistrationService) { }
ngOnInit() {
this.empService.getEmployees().subscribe(data => {
this.emps = data;
});
}
delteUser(id:number){
this.empService.deleteEmp(id).subscribe(
data => {
console.log(data);
this.ngOnInit();
},
error => console.log(error));
}
public findEmpById(id: number){
// let resp = this.empService.getEmpById(this.id);
// resp.subscribe((data)=>this.emps=data);
}
}
search component.html
<div class="container">
<br/>
<div class="row justify-content-center">
<div class="col-12 col-md-10 col-lg-8">
<form class="card card-sm">
<div class="card-body row no-gutters align-items-center">
<div class="col-auto">
<i class="fas fa-search h4 text-body"></i>
</div>
<!--end of col-->
<div class="col">
<input class="form-control form-control-lg form-control-borderless" type="search"
placeholder="Search topics or keywords">
</div>
<!--end of col-->
<div class="col-auto">
<button class="btn btn-lg btn-success" type="submit" (click)="findEmpById(id)">Search</button>
</div>
<!--end of col-->
</div>
</form>
</div>
<!--end of col-->
</div>
</div>
In "emp-registration-service.ts" I wrote url of springboot
public getEmpById(id: number): Observable<any>{
return this.http.get("http://localhost:8080/findemp/"+id)
}
I want get data when I search by id
Try this in your controller of Searching function
#GetMapping("/findemp/{id}")
public EmployeeEntity findEmployee(#PathVariable int id){
return empRepository.findById(id);
}
add this annotation #CrossOrigin(origins = "*") , Your method should now be something like
#GetMapping("/findemp/{id}")
#CrossOrigin(origins = "*")
public EmployeeEntity findEmployee(#PathVariable int id){
return empRepository.findById(id);
}
The reason is that your angular app is running on a different domain.For security reasons, browsers prohibit AJAX calls to resources residing outside the current origin. That's why it works on postman and not on browser
I have a side bar for my user profile page which has two items for 1) Updating the information and 2) showing the reviews that the user has already written.
The first item works perfectly (as it includes a form and has a submit button). But for the second one, I have no idea. The goal is that when I click on My Reviews, a method from the controller class is called, the reviews of the user are extracted from the database and the results are shown on the right side of the page.
As I don't have a submit button or a form for the second item, I don't know how I can implement it.
Here is my code:
<div class="module-inner">
<div class="side-bar">
<nav class="side-menu">
<div class="col-xs-3">
<ul class="nav nav-pills nav-stacked">
<li class="active"><a data-toggle="pill" href="#profile">Profile</li>
<li class="active"><a data-toggle="pill" href="#review">My
Reviews</a></li>
</ul>
</div>
</nav>
</div>
<div class="content-panel">
<div class="col-xs-9">
<div class="tab-content">
<div id="profile" class="tab-pane fade">
<form class="form-horizontal" th:action="#{/edit_profile}"> <fieldset class="fieldset">
<h3 class="fieldset-title">Personal Info</h3>
<div class="form-group">
<label class="col-md-2 col-sm-3 col-xs-12 control-label">User
Name</label>
<div class="col-md-10 col-sm-9 col-xs-12">
<input type="text" class="form-control"
th:disabled="${currentUser.email}"
th:value="${currentUser.email}">
</div>
</div>
<div class="form-group">
<label class="col-md-2 col-sm-3 col-xs-12 control-label">First
Name</label>
<div class="col-md-10 col-sm-9 col-xs-12">
<input name="firstname" type="text" class="form-control"
th:value="${currentUser.firstname}">
</div>
</div>
<div class="form-group">
<label class="col-md-2 col-sm-3 col-xs-12 control-label">Last
Name</label>
<div class="col-md-10 col-sm-9 col-xs-12">
<input name="lastname" type="text" class="form-control"
th:value="${currentUser.lastname}">
</div>
</div>
</fieldset>
<hr>
<div class="form-group">
<div
class="col-md-10 col-sm-9 col-xs-12 col-md-push-2 col-sm-push-3 col-xs-push-0">
<input class="btn btn-primary" type="submit"
value="Update Profile">
</div>
</div>
</form>
</div>
<div id="review" class="tab-pane fade">
<h3>Menu 2</h3>
<p>You have no reviews yet.</p>
</div>
</div>
</div>
</div>
</div>
Here is my controller:
#RequestMapping(value = "/findUserReviews", method = RequestMethod.GET)
public ModelAndView findUserReviews() {
ModelAndView modelAndView = new ModelAndView();
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
User user = userService.findUserByEmail(auth.getName());
..
modelAndView.addObject("reviews", reviewRepository.findUserRevies());
modelAndView.setViewName("profile");
return modelAndView;
}
I use the following technologies: Spring boot, Hibernate and Thymeleaf.
Any help would be appreciated.
Final update: The provided code in the accepted answer works, provided that I don't return a ModelAndView but a List<Review>.
With Ajax calls you can call the controller endpoints using javascript. One ajax call looks like this :
function getReviews() {
$.ajax({
type: "GET",
url: "/users/findUserReviews", //example
dataType: "JSON",
success: function (data) {
//do something with this JSON
fillReviews(data);
}
});
}
Now you can use this function as an on-click event for your button. And the fillReviews() is a function that gets the element with id="review" from the jsp page and create the list tree with the fetched data.
function fillReviews(data) {
var reviewDiv= document.getElementById('review');
var reviewList = document.createElement('ul');
for ( var i=0 ; i < data.length; i++)
{
var reviewListItem = createListItem(data[i]);
reviewList.appendChild(reviewListItem);
}
reviewDiv.appendChild(reviewList);
}
And createListItem(data[i]) could look like this:
function createListItem(data)
{
var listItem = document.createElement('li');
listItem.innerHTML = data["reviewName"]; // for example ..
return listItem;
}
And now all you have to do is to call getReviews() here :
<button onclick="getReviews()"/>
EDIT : The "data" from the ajax call is a JSON. So the "/users/findUserReviews" should return a List<Review> for example. And there is no need to change your original "/findUserReviews" endpoint. This was only an example, you can create a new endpoint in your controller which returns a list.
I have form action with textarea and submit button
<form method="post" action="/analyze">
<div class="form-group">
<label for="text">Input text:</label>
<textarea class="w-100" name="text" id="text" cols="30" rows="10"></textarea>
</div>
<div class="form-group d-flex justify-content-center">
<input type="submit" class="btn__submit btn btn-dark my-auto" value="Обработать">
</div>
</form>
<div class="row">
<div class="col">
<p th:text="#{nertext}"></p>
</div>
</div>
When I click submit button, i want to get processed text from server in Spring Boot and paste in tag p in div col.
Java Controller
#RequestMapping(value = "/analyze", method = RequestMethod.POST)
public String analyzeText(#RequestParam String text, Model model) {
System.out.print(classifier.classifyToString(text, "tsv", false));
String asd = classifier.classifyToString(text, "tsv", false);
model.addAttribute("nertext", asd);
return "/analyze";
}
How can i do submit without reload page
Use the Fetch API (https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) and the onsubmit event listener (https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onsubmit) to submit the form with JavaScript without reloading the page:
let form = document.getElementById("the-form");
form.onsubmit = function (e) {
e.preventDefault();
fetch(form.action, {
method: "post",
body: new FormData(form)
}).then(response => {
// do something with the response...
});
}
The e.preventDefault() makes sure that the page is not reloaded when you click the submit button. This assumes your form has the id the-form, like this:
<form id="the-form" method="post" action="/analyze"> ... </form>
On my view, I generate input "username", select with attribute multiple=multiple, which has name "rolesss".
My issue is, that if I send such form via post, my controller should convert roles to list, but i get only list containing single element.
For example:
I send post, with values:
username:MyUser
_csrf:aef50238-92cf-48df-86a4-cb6e2b8f62c9
rolesss:USER
rolesss:ADMIN
In debug mode in my controller I see values:
roless: "USER"
username: "MyUser"
"ADMIN" did just disappear.
My controller looks like:
#Controller
#RequestMapping("/user-management")
public class UserManagementController {
#RequestMapping("")
public ModelAndView home() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("pages/user-management");
return modelAndView;
}
#RequestMapping(value = "", method = RequestMethod.POST)
public ModelAndView changeRoles(#ModelAttribute("username") String username,#ModelAttribute("rolesss") List<String> rolesss) {
return null;
}
}
My view I merged 2 thymeleaf fragments into 1, in my code #user-roles-form is in separate fragment, but I think that it should not change anything:
<th:block layout:fragment="main-content">
<section>
<h2 class="section-title no-margin-top">Role Management</h2>
<div class="form-group">
<div class="panel panel-primary">
<div class="panel-heading">Změna rolí uživatele</div>
<div class="panel-body">
<form class="form-horizontal" role="form" action="/user-management" method="post">
<div class="form-group">
<label for="user-name" class="col-sm-2 control-label">Uživatel</label>
<div class="col-sm-10">
<input id="user-name" class="autocomplete form-control" type="text"
placeholder="Jméno uživatele" name="username"/>
</div>
<input type="hidden"
th:name="${_csrf.parameterName}"
th:value="${_csrf.token}"/>
</div>
<div id="user-roles-form" th:fragment="roles(roles)" xmlns:th="http://www.thymeleaf.org">
<div class="form-group">
<label for="user-roles" class="col-sm-2 control-label">Uživatelovy role</label>
<div class="col-sm-10">
<select multiple="multiple" class="form-control" id="user-roles" name="rolesss">
<th:block th:each="role : ${roles}">
<option th:value="${role.userRole.role}" th:text="${role.userRole.role}" th:selected="${role.selected}"></option>
</th:block>
</select>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-ar btn-primary">Uložit</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</section>
</th:block>
try using like below in your controller
in your HTML or JSP
<form modelAttribute="your_model_name"></form>
if you are using model attribute then use #ModelAttribute
otherwise, use #RequestParam("username")
In your case
#RequestMapping(value = "", method = RequestMethod.POST)
public ModelAndView changeRoles(#RequestParam("username") String username,#RequestParam("rolesss") List<String> rolesss) {
..........
.........
return null;
}