POST request returns 415 error - java

I'm trying to call a POST request (using Jersey APi for REST) from an HTML form using AngularJS v 1.5.8.
I have an HTML form with a submit button that calls a REST serivce:
<body ng-app="myApp" ng-controller="loginController">
......
<form name="myForm" nonvalidate ng-submit="login()">
......
<div
class="col-md-4 col-md-offset-4 col-sm-4 col-sm-offset-3 col-xs-6 col-xs-offset-3">
<button type="submit" class="btn btn-default" ng-submit="login()">Submit</button>
</div>
</form>
This is my loginController script:
var app = angular.module ("myApp", []);
app.controller("loginController", function($scope, $http){
$scope.username = "";
$scope.password = "";
$scope.login = function() {
var transform = function(data) {
return $.param(data);
}
$http(
{
url : 'http://localhost:8080/RestServices/services/user/add',
method : 'POST',
headers : {
'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8'
},
transformRequest : function(data) {
return $.param(data);
},
data: { name: $scope.username,
password: $scope.password }
}).success(function(response, status) {
$scope.data = response; //Assign data received to $scope.data
}
)
}
}
)
And here is my simple REST post service:
#Path("user")
public class UserResource {
private TreeMap<Integer, User> userMap = new TreeMap<Integer, User>();
#POST
#Path("add")
#Consumes({MediaType.APPLICATION_JSON})
public Response addUser(User user) {
int id = userMap.size();
user.setId(id);
userMap.put(id, user);
ObjectMapper mapper = new ObjectMapper();
String jsonString = "";
try {
jsonString = mapper.writeValueAsString(user);
} catch (JsonProcessingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
jsonString = null;
}
return Response.ok().entity(jsonString).build();
}
}
The POST request is called but returns a 415 error: the server refused this request because the request entity is in a format not supported by the requested resource for the requested method.

The problem is with the format that the REST API is expecting i.e. JSON.
So try with application/json and specifying charset won't be required:
headers: {
'Content-Type' : 'application/json'
}

function loginController($scope, $http) {
$scope.username = "";
$scope.password = "";
$scope.login = function () {
$http({
method: 'POST',
url: 'user/add',
data: {
username: $scope.username,
password: $scope.password
}
}).success(function (data, status, headers, config) {
$scope.result =data.username;
alert($scope.result);
}).error(function (data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
}
}

Related

Although I wrote 'enctype="multipart/form-data', ERROR 'Current request is not a multipart request' happen

I am implementing the file upload function.
When I upload a file, it shows what I uploaded, puts in the contents, and posts.
By the way, there was a problem below while uploading the files.
While trying to find a solution, many people asked me to add enctype="multipart/form-data but I added that one earlier.
And yet I don't understand that kind of error.
error
2021-07-30 23:08:21.239 ERROR 20744 --- [nio-8080-exec-9] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.multipart.MultipartException: Current request is not a multipart request] with root cause
front
<template>
<div class="scale">
<button><b-icon-arrow-left></b-icon-arrow-left></button><span>게시글 생성하기</span>
<form enctype="multipart/form-data" method="post" >
<div class="d-flex flex-row">
<button style="display:inline-block; margin-right:5%; margin-left:2%" #click.prevent="clickInputTag()" id='addimage'><b-icon-plus class="h1"></b-icon-plus></button>
<input hidden ref="plus" name="file" id="file" type="file" accept="image/*" #change.prevent="uploadImage($event)" multiple>
<div id="image_container"></div>
</div>
<div>
<b-textarea v-model="content" placeholder="Tall textarea" rows="8"></b-textarea>
<b-button #click="articleCreate()" >전송</b-button>
</div>
</form>
</div>
</template>
import axios from 'axios'
export default {
name:'ArticleCreate',
data(){
return{
content:"",
files: new FormData(),
}
},
methods:{
clickInputTag() {
this.$refs['plus'].click()
},
uploadImage(event) {
console.log(event.target.files)
const photoFile = document.getElementById("file")
this.files.append("file", photoFile.files[0]);
for (var image of event.target.files) {
var reader = new FileReader();
reader.onload = function(event)
{
var img = document.createElement("img");
img.setAttribute("src", event.target.result);
img.setAttribute("width","25%");
document.querySelector("div#image_container").appendChild(img);
};
reader.readAsDataURL(image);
}
console.log(this.files, typeof this.files)
},
articleCreate(){
axios({
url:'http://127.0.0.1:8080/article',
method:'post',
headers: {
'x-access-token': `${localStorage.getItem('token')}`,
},
params: {
content: this.content,
files: this.files,
}
})
.then(res=>{
this.$router.push({ name:'article'})
console.log(res.data)
console.log(this.files)
})
.catch(err=>{
console.log(`${localStorage.getItem('token')}`)
console.log(this.files)
console.log(this.content)
console.log(err)
})
},
}
}
back
#PostMapping("/article")
#ApiOperation(value = "게시글 작성")
public Object postArticle(#RequestParam String content, #RequestParam(required = true) List<MultipartFile> files) throws IOException {
Authentication user = SecurityContextHolder.getContext().getAuthentication();
ResponseEntity response = null;
if(user.getPrincipal() == "anonymousUser"){
response = new ResponseEntity<>("Fail", HttpStatus.UNAUTHORIZED);
return response;
}else {
UserDetails user2 = (UserDetails) user.getPrincipal();
Optional<User> userOpt = userDao.findByEmail(user2.getUsername());
Long articleId = articleDao.save(Article.builder()
.articleid(null)
.id(userOpt.get().getUid())
.createdtime(null)
.updatedtime(null)
.review(content)
.build()
).getArticleid();
List<String> pathName = saveFiles(files);
System.out.println(pathName.get(0));
for(int i = 0; i < files.size(); ++i) {
imageDao.save(Image.builder()
.imageid(null)
.articleid(articleId)
.imgURL(pathName.get(i))
.build()
);
}
response = new ResponseEntity<>("게시글 작성 완료", HttpStatus.OK);
return response;
}
}
Try adding content-type: multipart/form-data in header of your axios call.
headers: {
'x-access-token': `${localStorage.getItem('token')}`,
'content-type': 'multipart/form-data'
}
Also your axios post data should be in FormData type
var dataBody = new FormData();
dataBody .append('content', this.content);
dataBody .append('files', this.files);
change params to data and set it to dataBody
axios({
url:'http://127.0.0.1:8080/article',
method:'post',
headers: {
'x-access-token': `${localStorage.getItem('token')}`,
'content-type': 'multipart/form-data'
},
data: dataBody
}
Finally, at your backend:
Add consumes = { MediaType.MULTIPART_FORM_DATA_VALUE } in #PostMapping.
Replace #RequestParams with #RequestPart.
#PostMapping("/article", consumes = { MediaType.MULTIPART_FORM_DATA_VALUE })
#ApiOperation(value = "게시글 작성")
public Object postArticle(#RequestPart String content, #RequestPart(required = true) List<MultipartFile> files)

java spring rest parameter not work

I created code where pass data to spring rest but don't work correctly see my code below:
#PutMapping("/notification/save/{id}")
public #ResponseBody String update(#PathVariable("id") long id, #RequestBody AccountNotification accountNotification){
String result="ok";
ServiceAccount serviceAccount = new ServiceAccount();
serviceAccount.setId(id);
//accountNotification.setServiceAccount( serviceAccount );
//result =notificationsService.update(id,accountNotification);
JSONObject jObject = new JSONObject();
try
{
JSONArray jArray = new JSONArray();
JSONObject accountNotificationJSON = new JSONObject();
if(result.equals("ok")) {
accountNotificationJSON.put("success", "true");
accountNotificationJSON.put("messages", "Successfully Saved");
}
else {
accountNotificationJSON.put("success", "false");
accountNotificationJSON.put("messages", "NOT Successfully Saved");
}
jArray.put(accountNotificationJSON);
jObject.put("data", jArray);
} catch (JSONException jse) {
logger.error( jse.getMessage());
}
return jObject.toString();
}
my javascrit has:
$("#saveChanges").on('click',function(){
var params1={
proxy:$(proxy).val() ,
port:$(port).val(),
uri:$(uri).val(),
actived:$(actived).val()=="on"?true:false
};
$.ajax({
url: 'notification/save/'+id,
params: params1,
type: 'post',
success:function(response) {
if(response.data[0].success == "true") {
$(".removeMessages").html('<div class="alert alert-success alert-dismissible" role="alert">'+
'<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>'+
'<strong> <span class="glyphicon glyphicon-ok-sign"></span> </strong>'+response.data[0].messages+
'</div>');
// close the modal
$("#editMember").modal('hide');
} else {
$(".removeMessages").html('<div class="alert alert-warning alert-dismissible" role="alert">'+
'<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>'+
'<strong> <span class="glyphicon glyphicon-exclamation-sign"></span> </strong>'+response.data[0].messages+
'</div>');
}
},
error: function(x, e) {
alert(x);
}
});
in this situation ajax code return 400. Any body knows why? thanks if withdraw #RequestBody annotation the rest has been called but the parameter accountNotifications is initialized but without valeus passed.
there is a put mapping #PutMapping("/notification/save/{id}") in your Rest code, but in your js called by post method type: 'post', so it returns 400 Bad Request, you should use type: put which is equals to your Rest method.
#PutMapping("/notification/save/{id}")
public #ResponseBody String update(#PathVariable("id") long id,
#RequestParam AccountNotification accountNotification){
.....
}
$.ajax({
url: 'notification/save/'+id,
params: params1,
type: 'put',
success:function(){
}})
I resolved this mode:
#RequestMapping(value={"/notification/save/{id}"}, method = {RequestMethod.GET, RequestMethod.POST},
produces = "application/json"
)
public #ResponseBody String update(#PathVariable("id") long id, AccountNotification accountNotification){
String result="ok";
JavaScript:
$("#saveChanges").on('click',function(){
var params1={
proxy:$(proxy).val() ,
port:$(port).val(),
uri:$(uri).val(),
actived:$(actived).is(':checked')
};
$.ajax({
url: 'notification/save/'+id,
data: params1,
type: 'post',
success:function(response) {
I replaced into js param with data

How to pass JSON array from AngularJS Controller to the Spring Controller?

I am making SPA using AngularJS in Spring 4 with Hibernate 5.
I'm getting an error while passing JSON array from the AngularJS controller to the Spring Controller.
All fields value successfully coming in angular JSON array, but not passing in Spring controller.
Error: Could not read JSON: ; nested exception is
com.google.gson.JsonSyntaxException:
My project structure is like below.
Spring_Hibernate_MVC
=src
-com->karmesh->mvcApp->controller->register->RegisterController.java
=WebContent
-js->app->RegisterController.js
-Views->Register.html
Register,html
<div id="DivRegisterMain" ng-controller="RegisterController">
<form name="myForm" novalidate>
:::://Form fields here.
<input type="submit" value="SubmitTest" ng-click="submit()" ><br>
</form>
</div>
app.js
var routeApp=angular.module("RouteApp",['ngRoute']);
RegisterController.js
routeApp.controller("RegisterController", function($scope, $http) {
$scope.regJson = {
"is" : 1,
"fname" : "",
"lname" : "",
"gender" : "",
"dob" : "",
"email" : "",
"contact" : "",
"yop" : "",
"degree" : "",
"branch" : "",
"perc" : "",
"state" : "",
"city" : ""
};
$scope.studentList = [];
$scope.submit = function() {
var req = {
method: 'POST',
url: 'http://localhost:8050/Spring_Hibernate_MVC/registerStudent.do',
data: $scope.studentList,
};
$http(req).
then(function(response){
console.log(response); // prints true or false
if (response)
console.log("in success");
else
console.log("in fail");
$scope.studentList=[];
}, function(response){
console.log(response.status);
console.log("in error");
});
};
RegisterController.java
#EnableWebMvc
#RestController
#RequestMapping("/")
public class RegisterController {
#Autowired
private RegisterService registerService;
public RegisterController() {
System.out.println(this.getClass().getSimpleName() + "created..");
}
#ResponseBody
#RequestMapping(value="/registerStudent.do", method = RequestMethod.POST)
public boolean registerStudent(#RequestBody List<RegisterDTO> stdList) {
System.out.println("inside controller..");
if (stdList != null) {
System.out.println("success...");
}
return registerService.isStudentExist(stdList);
}
}
use JSON Serialization/Deserialization
your request should be
var req = {
method: 'POST', url:'http://localhost:8050/Spring_Hibernate_MVC/registerStudent.do',
data: JSON.stringify($scope.studentList),
};
your spring controller
#ResponseBody
#RequestMapping(value="/registerStudent.do", method = RequestMethod.POST)
public boolean registerStudent(#RequestBody string data) {
List<RegisterDTO> stdList = JsonConvert.DeserializeObject<RegisterDTO>(data); // find java jsondeserializer
System.out.println("inside controller..");
if (stdList != null) {
System.out.println("success...");
}
return registerService.isStudentExist(stdList);
}
You are missing contentType: 'application/json' in your request!
RegisterController.js
$scope.submit = function() {
var req = {
method: 'POST',
url: 'http://localhost:8050/Spring_Hibernate_MVC/registerStudent.do',
data: angular.toJson($scope.studentList),// note this
};
};
download gson jar file.
RegisterController.js
#ResponseBody
#RequestMapping(value = "/registerStudent.do", method = RequestMethod.POST)
public boolean registerStudent(#RequestBody String data) {
Gson googleJson = new Gson();
ArrayList stdList = googleJson.fromJson(data, ArrayList.class);
if (stdList != null) {
// store your stdList
}
return registerService.isStudentExist(stdList);
}

Spring Rest Controller POST request doesn't work

I have a rest controller:
#RestController
#RequestMapping("/query")
public class QueryController {
#Autowired
private QueryService queryService;
#RequestMapping(value = "/select", method = RequestMethod.POST)
public #ResponseBody QueryResultDTO executeQuery(#RequestBody QueryDTO queryDTO) {
try {
QueryResultDTO queryResultDTO = queryService.executeQuery("select * from employees");
queryResultDTO.setSuccessful(true);
return queryResultDTO;
} catch (SQLException e) {
QueryResultDTO queryResultDTO = new QueryResultDTO();
queryResultDTO.setSuccessful(false);
queryResultDTO.setErrorMessage(e.getMessage());
return queryResultDTO;
}
}
}
and I try to send POST request from AngularJS controller:
app.controller("AppCtrl",function($scope,$http) {
var app = this;
$scope.execute= function () {
$http({
url: '../query/select',
method: "POST",
data: { 'message' : $scope.queryText }
})
.then(function(response) {
$scope.queryResult = response.data;
console.log($scope.queryResult);
console.log($scope.queryText)
},
function(response) {
console.log(response);
});
}
});
but It doesn't work. My executeQuery function in Spring Controller isn't even called.
But when I change RequestMethod to GET it works correctly.
#RestController
#RequestMapping("/query")
public class QueryController {
#Autowired
private QueryService queryService;
#RequestMapping(value = "/select", method = RequestMethod.GET)
public #ResponseBody QueryResultDTO executeQuery() {
try {
QueryResultDTO queryResultDTO = queryService.executeQuery("INSERT INTO employee VALUES (7,'dupa')");
queryResultDTO.setSuccessful(true);
return queryResultDTO;
} catch (SQLException e) {
QueryResultDTO queryResultDTO = new QueryResultDTO();
queryResultDTO.setSuccessful(false);
queryResultDTO.setErrorMessage(e.getMessage());
return queryResultDTO;
}
}
}
and in Angular controller:
app.controller("AppCtrl",function($scope,$http) {
var app = this;
$scope.execute= function () {
$http({
url: '../query/select',
method: "GET",
data: { 'message' : $scope.queryText }
})
.then(function(response) {
$scope.queryResult = response.data;
console.log($scope.queryResult);
console.log($scope.queryText)
},
function(response) {
console.log(response);
});
}
});
My main problem is that I'd like to send some data to my Spring controller and then send JSON in response to my Angular controller. Whith GET method response works perfectly, but when I use POST the controller method isn't even called.
Edit:
My QueryDTO class is simple:
public class QueryDTO {
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
And some logs with DEBUG level:
2016-06-06 09:28:23.697 DEBUG 7504 --- [nio-8090-exec-2] o.s.web.servlet.DispatcherServlet : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
2016-06-06 09:28:23.698 DEBUG 7504 --- [nio-8090-exec-2] o.s.web.servlet.DispatcherServlet : Successfully completed request
Try adding the consumes=MediaType.APPLICATION_JSON_VALUE in your method.
#Transactional
#RequestMapping(value = "/userlogincheck", method = RequestMethod.POST, consumes=MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody void userLoginCheck(#RequestBody UserImpl user, HttpServletRequest request, HttpServletResponse response) throws JSONException, IOException {
JSONObject json = new JSONObject();
try {
String email=user.getEmail();
Long userId=user.getId();
User loginData = accountService.userLoginCheck(email,userId);
if(loginData==null)
{
json.put("status", "FAILURE");
json.put("message", "user does not exist");
json.put("nextPage", "signIn");
}
else
{
json.put("status", "SUCCESS");
json.put("nextPage", updateState);
}
}
catch(Exception e) {
logger.info(e.getMessage());
}
response.setContentType("application/json;charset=UTF-8");
logger.info("response======" + json.toString());
PrintWriter out = response.getWriter();
out.write(json.toString());
}
I had the same issue and was able to fix it by adding CSRF token to my request (this is only an issue if you are using the WebSecurity). https://docs.spring.io/spring-security/site/docs/current/reference/html/csrf.html
This link describe the following steps:
1) Add the token to your header, with thymeleaf you do as follows (I think you can fetch the token from cookie as well):
<head>
<meta name="_csrf" th:content="${_csrf.token}"/>
.....
</head>
2) Change your request to include the CSRF token as follows (I am not familiar with angular but I guess you can set the header the same way as I did with Jquery):
var token = $("meta[name='_csrf']").attr("content");
$.ajax({
type: 'POST',
url: url,
data: JSON.stringify(newTodo),
headers: {
'X-CSRF-TOKEN': token
},
contentType: 'application/json',
dataType: 'json',
success: function(){
alert('callback ');
}
});

how to call spring controller in jquery ajax success method

I have created a spring controller and a jsp page. In jsp page I am using jquery ajax call to hit the controller. Now, this controller returns a json response as string. Now on based of json response in success method, I want to call a next controller call which will return a ModelAndView jsp page. How can I do this. Below is my code:
JSP Jquery ajax call:
$(document).ready(function(){
$("#submitButton").click(function(e){
var formData = getFormData();
if(formData!=false){
$.ajax({
type: 'POST',
'url': 'http://localhost:8080/Test_ReportingUI/fieldMappingNext.htm',
data: {jsonData: JSON.stringify(formData)},
dataType: 'json',
success: function(response){
try{
var strResponse=jQuery.parseJSON(response);
}catch(err){}
if(response.status=='ok')
{
alert ("okokokokokokokokok");
//I am successfully reaching till here.
//But in case of this alert box I want to call a
//controller which will return ModelAndView and
//should open a corresponding ModelAndView jsp page.
//something like:
/*
$.ajax({
type: 'GET',
'url': 'http://localhost:8080/Test_ReportingUI/abcxyz.htm',
)};
*/
}
else
{
alert("ERROR!!");
}
},
timeout: 10000,
error: function(xhr, status, err){
if(response.status=='timeout')
{
alert('Request time has been out','');
}
console.log(status,err);
}
}); }
});
});
Controller class methods:
#RequestMapping (value="fieldMappingNext.htm", method=RequestMethod.POST)
#ResponseBody String addFieldMappingNext(#RequestParam String jsonData)
{
String customerID =null;
String objectID = null;
String syncFieldName = null;
String optMapping = null;
JSONObject jsonResponse = new JSONObject();
try{
JSONObject requestedJSONObject = new JSONObject(jsonData);
customerID = requestedJSONObject.getString("customerID");
objectID = requestedJSONObject.getString("objectID");
syncFieldName = requestedJSONObject.getString("syncFieldName");
optMapping = requestedJSONObject.getString("optMapping");
}catch(Exception exex){
exex.printStackTrace();
}
if(optMapping.equalsIgnoreCase("direct")){
long metadataID=rwCustomerService.getMetaDataID(customerID,objectID);
List<RWFieldDetail> list=rwCustomerService.getFieldDetailNames(metadataID);
request.setAttribute("customerID", customerID);
request.setAttribute("objectID", objectID);
request.setAttribute("optMapping", optMapping);
request.setAttribute("syncFieldName", syncFieldName);
request.setAttribute("fieldNames", list);
try {
jsonResponse.put("status", "ok");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return jsonResponse.toString();
}
Second Controller method that I want to call from jquery success method:
#RequestMapping (value="abcxyz.htm", method=RequestMethod.GET)
ModelAndView fieldMapping(){
ModelAndView modelAndView=new ModelAndView("FieldMappingMainScreenNext");
return modelAndView;
}
How do I do this.
Since the second handler method returns ModelAndView, you should redirect from the success callback:
...
success: function(response) {
window.location.replace(response.url);
}
...
In your Java code you can use something like:
Map<String, String> map = new HashMap<String, String>();
if(condition1){
map.put("url","url1.html");
}
if(condition2){
map.put("url","url2.html");
}
Convert it to a JSON string and revert it back. Afterwards, in the jquery portion you'll get the response:
success:function(jsonStr){
var obj = JSON.parse(jsonStr);
var url = obj.url;
}
That is how you can get the url. If you want to load an other page or create an ajax call then you can do it.

Categories

Resources