I am trying make hello world using ajax and spring, but it not workit, I dont know why.
My servlet is:
import javax.servlet.http.HttpServlet;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
#Controller
public class SomeController {
#RequestMapping(value = "/profile", method = RequestMethod.GET)
public #ResponseBody
String processAJAXRequest(
#RequestParam("firstname") String firstname,
#RequestParam("lastname") String lastname) {
String response = "HELLO: " + firstname + " " + lastname;
return response;
}
}
And my page with ajax is:
<html>
<head>
<title>TODO supply a title</title>
<meta charset="windows-1250">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
</head>
<body>
<form id="sampleForm" method="post" action="/profile">
<div>
<input type="text" name="firstname" id="firstname">
</div>
<div>
<input type="text" name="lastname" id="lastname">
</div>
<div>
<button type="submit" name="submit">Submit</button>
</div>
</form>
<script>
$(document).ready(function () {
$('#sampleForm').submit(
function (event) {
var firstname = $('#firstname').val();
var lastname = $('#lastname').val();
var data = 'firstname='
+ encodeURIComponent(firstname)
+ '&lastname='
+ encodeURIComponent(lastname);
$.ajax({
url: $("#sampleForm").attr("action"),
data: data,
type: "GET",
success: function (response) {
alert(response);
},
error: function (xhr, status, error) {
alert(xhr.responseText);
}
});
return false;
});
});
</script>
</body>
</html>
When I try to send form, I am getting error 404. Can you help me? Where is a problem?
Normal servlet extends from HttpServlet working fine.
Related
Hey I've got a problem with updating my object. I've got a table of movies where can i delete it or go to details. In details i wanted to have my "update" option. Im giving whole object to movieDetailPage, it shows object details in input fields but i cant update it. My "updateMovie" method doesnt see what i typed in input. For example im changing name from "Movie1" to "Movie2" and method still see "Movie1"
Here's my movieDetailsPage.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form th:object="${movieToUpdate}" method=post >
<p>Movie name: <input type="text" th:field="*{name}"></p>
<p>Movie description: <input type="text" th:field="*{description}"></p>
<img th:src="${movieToUpdate.getImageUrl()}" th:width="300" th:height="300"><br>
<p>Nowy image url: <input type="text" th:field="*{imageUrl}" class="cloudinary-fileupload"></p>
<a th:href="${'/movie/update/'+movieToUpdate.getId()}">Update</a><br>
</form>
</body>
</html>
and my controller class
package pl.fsaaa.filmapp.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import pl.fsaaa.filmapp.model.Movie;
import pl.fsaaa.filmapp.service.CloudinaryImageUploader;
import pl.fsaaa.filmapp.service.MovieService;
import java.io.IOException;
import java.util.List;
#Controller
public class MovieController {
private CloudinaryImageUploader cloudinaryImageUploader;
private MovieService movieService;
#Autowired
public MovieController(MovieService movieService, CloudinaryImageUploader cloudinaryImageUploader) {
this.movieService = movieService;
this.cloudinaryImageUploader = cloudinaryImageUploader;
}
#GetMapping("/addmovie")
public String getNewMovie(Model model) {
model.addAttribute("newMovie",new Movie());
// model.addAttribute("newImage",new File(""));
return "addMoviePage";
}
#PostMapping("/add-movie")
public String addMovie(#ModelAttribute Movie movie) throws IOException {
cloudinaryImageUploader.saveImageToCloudinary(movie.getImageUrl());
movie.setImageUrl(cloudinaryImageUploader.getCloudinaryImageUrl());
movieService.addMovie(movie);
return "redirect:/addmovie";
}
#GetMapping("/movies")
public String getAllMovies(Model model) {
List<Movie> movieList = movieService.getAllMovies();
model.addAttribute("allMovies",movieList);
return "moviesPage";
}
#GetMapping("/movie/{id}")
public String getMovieDetail(Model model, #PathVariable Long id) {
Movie movieToUpdate = movieService.getMovieById(id);
System.out.println(movieToUpdate);
model.addAttribute("movieToUpdate", movieToUpdate);
return "movieDetailsPage";
}
#RequestMapping(value = "/movie/update/{id}", method = {RequestMethod.GET,RequestMethod.PUT})
// #PutMapping("movie/update/{id}")
public String updateMovie(#PathVariable Long id, #ModelAttribute Movie movieToUpdate){
// movieToUpdate = movieService.getMovieById(id);
// System.out.println(movieToUpdate);
movieService.addMovie(movieToUpdate);
return "redirect:/movies";
}
#RequestMapping(value = "/movie/delete/{id}", method = {RequestMethod.DELETE,RequestMethod.GET})
public String deleteMovie(#PathVariable Long id){
movieService.deleteMovie(id);
return "redirect:/movies";
}
}
Problem solved.
I've added submit button to details page instead of link:
<form th:action="'/movies/update/'+*{id}" th:object="${movieToUpdate}" method=put >
<p>Movie name: <input type="text" th:field="*{name}"></p>
<p>Movie description: <input type="text" th:field="*{description}"></p>
<img th:src="${movieToUpdate.getImageUrl()}" th:width="300" th:height="300"><br>
<p>New image url: <input type="text" th:field="*{imageUrl}" class="cloudinary-fileupload"></p>
<p><input type="submit" value="Update"></p>
</form>
and changed update edited "movie" method a little bit, because previous one wasn't uploading changed image to cloudinary.
#RequestMapping(value = "/update/{id}", method = {RequestMethod.GET,RequestMethod.PUT})
public String updateMovie(#PathVariable Long id, #ModelAttribute Movie movieToUpdate) throws IOException {
movieToUpdate.setId(id);
cloudinaryImageUploader.saveImageToCloudinary(movieToUpdate.getImageUrl());
movieToUpdate.setImageUrl(cloudinaryImageUploader.getCloudinaryImageUrl());
movieService.addMovie(movieToUpdate);
return "redirect:/movies/all";
}
I was following this getting started guide and following error:
org.thymeleaf.exceptions.TemplateProcessingException: Error during execution of processor 'org.thymeleaf.spring5.processor.SpringInputGeneralFieldTagProcessor' (template: "index" - line 10, col 31)"
The code is exactly same as shown in the guide. I understand this is something to do with Thymeleaf form tag, so I also checked the Thymeleaf documentation but couldn't figure out what is wrong with my code.
Here's the code:
index.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Getting Started: Handling Form Submission</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h1>Form</h1>
<form action="#" th:action="#{/greeting}" th:object="${greeting}" method="post">
<p>Id: <input type="text" th:field="*{id}" /></p>
<p>Message: <input type="text" th:field="*{content}" /></p>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>
</body>
</html>
GreetingController.java
package com.example;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
#Controller
public class GreetingController {
#GetMapping("/greeting")
public String greetingForm(Model model) {
model.addAttribute("greeting", new Greeting());
return "greeting";
}
#PostMapping("/greeting")
public String greetingSubmit(#ModelAttribute Greeting greeting) {
return "result";
}
}
Greeting.java
package com.example;
public class Greeting {
private long id;
private String content;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
I would appreciate any advice.
So tutorial says you to create 2 files, result.html and greeting.html. And you created index.html. The thing is that you didn't bind your template page to Spring controller, it's bound to greeting.html as in tuturial.
So solution is just to change return from greeting to index in greetingForm() method:
#GetMapping("/greeting")
public String greetingForm(Model model) {
model.addAttribute("greeting", new Greeting());
return "index"; // <- changed line
}
Hope this would help you.
I'm Trying to Save small record using JSP ajax in technology. The project working procedure is like this.
01. index.jsp : Send data to SaveStudent servlet
02. SaveStudent : Get request form jsp and send it to validation java class
03. Validation : Validate data and Send to DaoImpl java class
04. DaoImpl : Override the method in StudentDAO, Do the save SQL query.
05. StudentDAO : A interface has all the database related methods.
Here is the image of the project.
Given below is index.jsp files source code.
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
</head>
<body>
<form action="SaveStudent" method="post">
<label>Enter Name:</label>
<input type="text" name="name" id="txtName"/>
<br/>
<label>Enter City:</label>
<input type="text" name="city" id="txtCity"/>
<br/>
<input type="submit" value="Send" id="btnSave"/>
<div id="response"></div>
</form>
<script type="text/javascript">
$(document).ready(function() {
$('#btnSave').click(function() {
var $name = $("#txtName").val();
var $city = $("#txtCity").val();
$.post('SaveStudent', {
name: $name,
city: $city
}, function(responseText) {
if (responseText !== null) {
$('#response').text(responseText);
} else {
alert("Invalid Name");
}
});
});
});
</script>
</body>
Here is SaveStudent java class's source code.
package Control;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import Model.Validation;
public class SaveStudent extends HttpServlet {
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
String record = "";
try {
Validation val = new Validation();
record = val.validateSave(request, response);
response.setContentType("text/plain");
response.setCharacterEncoding("UTF-8");
if (record != null) {
out.write(record);
} else {
out.print("Error Occured..!");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
out.close();
}
}
}
Save record is working fine. Database is also updating. But the problem is The "Save Successful" message is appears in servlet page. Not under the jsp page.
Please help me on this. Thank you.
I figure out a way. I put replace "submit" type to "button". Now working perfectly. Thank you for your Time.
I am trying to register user (take some information from form input at frontend and send it to backend via AngularJS) but I am experiencing some problems.
Here is my index.html file:
<!DOCTYPE html>
<html data-ng-app="collectionsApp">
<head>
<meta charset="UTF-8">
<title>Collections</title>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div data-ng-view></div>
</body>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.10.0/ui-bootstrap-tpls.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.20/angular-route.js"></script>
<script src="/scripts/app.js"></script>
<script src="/scripts/service/userService.js"></script>
<script src="/scripts/controller/indexController.js"></script>
<script src="/scripts/controller/registerController.js"></script>
</html>
As you ca see, I have included Bootstrap UI, AngularJS, Bootstarp CSS and my project files: userService.js, indexController.js and registerController.js. I have created atributes data-ng-app="collectionsApp" (created in app.js) and data-ng-view (routing works just fine).
Here is my app.js file:
var collectionsApp = angular.module('collectionsApp', [ 'ngRoute' ]);
collectionsApp.config(function($routeProvider) {
$routeProvider.when('/login', {
templateUrl : '/view/login.html',
controller : 'loginController'
})
.when('/register', {
templateUrl : '/view/register.html',
controller : 'registerController'
}).
otherwise({
redirectTo : '/login'
});
});
As you can see I have included my registerControll and loginControll in app.js so i do not have to do it in register.html and login.html.
Here is my register.html file:
<div class="container">
<form class="form-signin" role="form">
<h1 class="form-signin-heading">Please register</h1>
<input type="text" class="form-control" placeholder="Email address" required data-ng-model='user.email'>
<input type="text" class="form-control" placeholder="Password" required data-ng-model='user.password'>
<input type="text" class="form-control" placeholder="Firts name" required data-ng-model='user.firstName'>
<input type="text" class="form-control" placeholder="Last name" required data-ng-model='user.LastName'>
<button class="btn btn-lg btn-primary btn-block" type="submit" data-ng-click="register(user)">Register</button>
<div>
Login
</div>
</form>
</div>
On data-ng-click register(user) function is called from userControl.js file.
Here is my userController.js file:
collectionsApp.controller('registerController', function($scope, userService) {
userService.register($scope.user).then(function(data){
});
});
From this file, function from userService.js file is called.
Here is my userService.js file:
collectionsApp.service('userService', function($scope, $http) {
return {
login : function(user) {
$http.post('/user/login', user).then(function(data) {
return data;
});
},
register : function(user) {
$http.post('/user/add', user).then(function(data) {
return data;
});
}
};
});
From here register function targets /user/add in userController.java in backend. Here is that file:
package x.y.collections.controller;
import java.util.HashMap;
import javax.annotation.Resource;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import x.y.collections.dao.UserDAO;
import x.y.collections.model.User;
import x.y.collections.utility.Response;
#RestController
#RequestMapping("/user")
public class UserController {
#Resource
UserDAO userDao;
#RequestMapping("/find/{id}")
public User FindUser(#PathVariable Long id) {
return userDao.findOne(id);
}
#RequestMapping(value = "/add", method = RequestMethod.POST)
public HashMap<String, String> AddUser(#RequestBody User user) {
final User requestedUserBody = userDao.findByEmail(user.getEmail());
if (requestedUserBody.getEmail().equals(user.getEmail())) {
return Response.setError("User allready in databse!");
} else {
userDao.save(user);
return Response.setSuccess("Registration succsessful!");
}
}
#RequestMapping(value = { "/login" }, method = RequestMethod.POST)
public HashMap<String, String> LoginUser(#RequestBody User user) {
final User requestedUserBody = userDao.findByEmail(user.getEmail());
if (requestedUserBody.getPassword().equals(user.getPassword())) {
return Response.setError("Username and password do not match!");
} else {
return Response.setSuccess("Login succsessful!");
}
}
}
When I start server and go to my frontend via Chrome and localhost:port in adressbar I can see that routing is working, but when I fill in the form, and press button that is supposed to trigger data-ng-click="register(user)" noting happens. When I go right click > inspect element > console : I see this error:
Error: [$injector:unpr] http://errors.angularjs.org/1.2.19/$injector/unpr?p0=<div data-ng-view="" class="ng-scope">copeProvider%20%3C-%20%24scope%20%3C-%20userService
at Error (native)
at http://ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular.min.js:6:450
at http://ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular.min.js:36:202
at Object.c [as get] (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular.min.js:34:305)
at http://ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular.min.js:36:270
at c (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular.min.js:34:305)
at d (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular.min.js:35:6)
at Object.instantiate (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular.min.js:35:165)
at Object.<anonymous> (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular.min.js:35:435)
at Object.d [as invoke] (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular.min.js:35:36)
Can someone explain to me what I am doing wrong?
Than you in advance...
Papi
In your registerController
collectionsApp.controller('registerController', function($scope, userService) {
$scope.user = {};
.....
$scope.register = function(){
userService.register($scope.user).then(function(data){
});
};
});
to consume a single object in jersey I have my method like this
#POST
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
#Produces(MediaType.APPLICATION_JSON)
public Response postPerson(MultivaluedMap<String, String> personParams){
ResponseBuilder response = Response.ok();
return response.build();
}
its working well.
my doubt is how can i consume list of objects in jersey
some thing like this
#POST
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
#Produces(MediaType.APPLICATION_JSON)
public Response postPerson(List<Person> person){
ResponseBuilder response = Response.ok();
return response.build();
}
I did some googling but didn't found any working example.
It seems you want to pass the form data as list:
#POST
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
#Produces(MediaType.APPLICATION_JSON)
public Response postPerson(#FormParam("person") List<String> person){
ResponseBuilder response = Response.ok();
return response.build();
}
<html><body>
<form action="http://localhost:9998/myresource" method="POST">
<input type="checkbox" name="person" value="a">A</input>
<input type="checkbox" name="person" value="b">B</input>
<input type="checkbox" name="person" value="c">C</input>
<input type="submit">OK</input>
</form>
</body></html>
similarly for Person object, you have to map the diffrent property so that it can post the list of person
Source:JERSEY RESTful - How to work with multiselect checkboxes? this has worked for me.
I am using jersy as the RESTful webservice and angularJS to post all the todo objects at the same time use your person object to update data at the same time
//Define an angular module for our app
var sampleApp = angular.module('sampleApp', ['ngRoute','ngResource']);
sampleApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/AddNewOrder', {
templateUrl: 'add_order.jsp',
controller: 'AddOrderController'
}).
when('/TestArray', {
templateUrl: 'list.html',
controller: 'TestArrayController'
}).
}).
otherwise({
redirectTo: '/AddNewOrder'
});
}]);
sampleApp.controller( 'TestArrayController', function ( $scope, $location,$http,$resource) {
var array=new Array();
var postObject1 = new Object();
postObject1.description = "testDesc1";
postObject1.summary = "testSummary1";
array.push(postObject1);
var postObject2 = new Object();
postObject2.description = "testDesc2";
postObject2.summary = "testSummary2";
array.push(postObject2);
$http.post("/AngularJS/JerseyWebService/todo/arrayTest", array).success(function(data){
//Callback function here.
//"data" is the response from the server.
$scope.updateMessage=data;
});
HTML page
<html lang="en">
<head>
<title>AngularJS Routing example</title>
<script src="jquery.min.js" type="text/javascript" language="javascript"></script>
<script src="xml2json.js" type="text/javascript" language="javascript"></script>
<script src="angular.js"></script>
<script src="angularjs/angular-route.js"></script>
<script src="angularjs/angular-resource.js"></script>
<script src="app1.js"></script>
<script type="text/javascript">
var jquery = $.noConflict();
</script>
</head>
<body ng-app="sampleApp">
<div class="container">
<div class="row">
<div class="col-md-3">
<ul class="nav">
<!--<li> Add New Order </li>
<li> Show Orders</li>-->
<li>Test Array Update</li>
</ul>
<div>{{updateMessage}}</div>
</div>
<div class="col-md-9">
<div ng-view></div>
</div>
</div>
</div>
</body>
</html>
Jersy WebService
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
#Path("/todo")
public class TodoResource {
#POST
#Path("/arrayTest")
#Consumes({ MediaType.APPLICATION_JSON })
#Produces({ MediaType.APPLICATION_JSON })
public String wantsJSONArray(List<Todo> array)
{
System.out.println("---------------------------------------------------"+array);
// here's your array
return "success";
}
}
Todo.java
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
// JAX-RS supports an automatic mapping from JAXB annotated class to XML and JSON
// Isn't that cool?
public class Todo {
private String summary;
private String description;
public String getSummary() {
return summary;
}
public void setSummary(String summary) {
this.summary = summary;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String toString(){
return "{summary:"+summary+"description:"+description+"}";
}
}
web.xml entry
<servlet>
<servlet-name>JerseyWebService</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JerseyWebService</servlet-name>
<url-pattern>/JerseyWebService/*</url-pattern>
</servlet-mapping>