Post json to struts 2 action - java

I need to post a simple json object to a Struts 2 action, could you tell me what I miss with this:
the Java object to save:
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", unique = true, nullable = false)
private Integer id;
#Column(name = "code")
private String code;
#Column(name = "libelle_fr")
private String libelleFr;
#Column(name = "libelle_nl")
private String libelleNl;
I use alpine.js but it's a detail, the script called to send the request is this one:
<script>
function postForm() {
return {
indicateurDictionnaireForm: {
libelleFr: '',
libelleNl: '',
code: ''
},
message: '',
submitData() {
this.message = ''
fetch('<%= request.getContextPath() %>/mesures.ce.save.action', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
dataType:"json",
body: JSON.stringify(this.indicateurDictionnaireForm)
})
.then(() => {
this.message = 'Form sucessfully submitted!'
})
.catch(() => {
this.message = 'Ooops! Something went wrong!'
})
}
}
}
</script>
the json sent to the action is:
{
"libelleFr":"fr",
"libelleNl":"nl",
"code":"sample"
}
from my action file there is my method called from the front:
private IndicateurDictionnaire indicateurDictionnaireForm;
// Action to save an indicateurDictionnaireto database
#Action(value = "mesures.indicateurs.ce.save", results = {
#Result(name = "success", type = "json", params = {"root", "indicateurDictionnaireForm"}),
#Result(name = "input", type = "tiles", params = {"root", "indicateurDictionnaireForm"}, location = "viewMesureCoutUnitaire")})
public String save(IndicateurDictionnaire indicateurDictionnaire, String libelleFr, String libelleNl, String code) {
dictionnaireIndicateurBo.saveIndicateurDictionnaire(indicateurDictionnaire);
return SUCCESS;
}
According the struts2 json pluggin, the json should be mapped to my object if it's properly formatted but the fields are empty if I look in debug.
Do you know how I can proceed to at least see the json request in my action method?

The methods that are mapped to the actions not use any parameters in the method signature. So you need to remove those parameters and add json interceptor to the action config.
This field is used as root object by the json interceptor and should not be null.
IndicateurDictionnaire indicateurDictionnaire;
// getter and setter should be added
#Action(value = "mesures.indicateurs.ce.save", results = {
#Result(name = "success", type = "json", params = {"root", "indicateurDictionnaire"})
}, interceptorRefs = #InterceptorRef(value = "json", params = {"root", "indicateurDictionnaire"}))
public String save() {
dictionnaireIndicateurBo.saveIndicateurDictionnaire(indicateurDictionnaire);
return SUCCESS;
}

Related

boolean is set to false if it's not present in #RequestBody

I've stumbled upon interesting case and I'm not sure how to resolve it. It's probably related to JSON Post request for boolean field sends false by default but advices from that article didn't help.
Let's say I have this class:
public class ReqBody {
#NotNull
#Pattern(regexp = "^[0-9]{10}$")
private String phone;
//other fields
#NotNull
#JsonProperty(value = "create_anonymous_account")
private Boolean createAnonymousAccount = null;
//constructors, getters and setters
public Boolean getCreateAnonymousAccount() {
return createAnonymousAccount;
}
public void setCreateAnonymousAccount(Boolean createAnonymousAccount) {
this.createAnonymousAccount = createAnonymousAccount;
}
}
I also have endpoint:
#PostMapping(value = "/test", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<MyOutput> test(
#ApiParam(value = "information", required = true) #RequestBody ReqBody input
) {
//do something
}
problem is when I send my request body as:
{
"phone": "0000000006",
"create_anonymous_account": null
}
or just like
{
"phone": "0000000006"
}
it sets createAnonymousAccount to false.
I have checked, and it correctly recognises "create_anonymous_account": true
Is there any way to "force" null value in boolean field?
I really need to know if it was sent or no, and not to have default value.
You can use Jackson annotation to ignore the null fields. If the Caller doesn't send createAnonymousAccount then it will be null.
#JsonInclude(JsonInclude.Include.NON_NULL)
public class ReqBody {
#NotNull
#Pattern(regexp = "^[0-9]{10}$")
private String phone;
//other fields
#JsonProperty(value = "create_anonymous_account")
private Boolean createAnonymousAccount ;
}

How to insert JSON object into database using spring boot and angularjs?

I am new to Spring boot so the question may sound silly. I want to insert a json object into database. But it is giving me an error like:
"Failed to evaluate Jackson deserialization for type".
On console, I am getting an error like:
Http 415 Unsupported Media type error with JSON
Here is my POJO class:
#Entity
#Table(name = "academics")
public class Academics {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private int id;
#Column(name = "adhaarcard")
private String adhaarCard;
#Column(name = "grade")
private List grades;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAdhaarCard() {
return adhaarCard;
}
public void setAdhaarCard(String adhaarCard) {
this.adhaarCard = adhaarCard;
}
public List getGrades() {
return grades;
}
public void setGrades(List grades) {
this.grades = grades;
}
}
My controller function:
#RequestMapping(value="saveacademics",method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Object> saveAvademics(#RequestBody Academics academics) {
academicsService.save(academics);
URI location = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}")
.buildAndExpand(academics.getId()).toUri();
return ResponseEntity.created(location).build();
}
Angularjs Code:
$scope.saveAcademics = function() {
var adhaar = sessionStorage.getItem("emp-key");
var _data = {
"adhaarCard":adhaar,
"grades": {
"graduation":
{ "ssc": "SSC", "hsc": "HSC", "quOne": $scope.qone
},
"specialization":
{ 'ssc': "N.A", 'hsc': $scope.hscSpl, 'qoneSpl': $scope.qoneSpl},
"grade":
{ 'ssc': $scope.sscGrade, 'hsc': $scope.hscGrade, 'qoneGrade': $scope.qoneGrade},
"university":
{ 'ssc': $scope.sscUni, 'hsc': $scope.hscUni, 'qoneUni': $scope.qoneUni},
"year":
{ 'ssc': $scope.sscYear, 'hsc': $scope.hscYear, 'qoneYear': $scope.qoneYear}
}
};
console.log(_data);
$http({
url: 'saveacademics',
method: "POST",
data: JSON.stringify(_data)
})
.then(function(response) {
alert("Success");
},
function(response) { // optional
alert("Error Occoured.");
});
}
Try MediaType.APPLICATION_JSON instead on MediaType.APPLICATION_JSON_VALUE
#RequestMapping(value="saveacademics",method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON)
MediaType.APPLICATION_JSON is a "public constant media type for application/json", whereas MediaType.APPLICATION_JSON_VALUE is a "String equivalent of MediaType.APPLICATION_JSON".
Json that you generate from angular js and your Java pojo are not matching.
Better you can reformat json as below
{ adhaarCard: "12", grades : [
{ university: "univ name", specialization: "sadd", grade: 83, graduation:"SSC", year: 2007 },
{ university: "univ name", specialization: "sadd", grade: 67, graduation:"HSC", year: 2009 }
]
}
And mapping PoJo class as
#Column(name = "adhaarcard")
private String adhaarCard;
#Column(name = "grade")
private List<Grades> grades ;
Grades.java
private String university;
private String specialization;
private int grade;
private Sting graduation;
private int year;
Add Column mapping and getter, setters.
Tip:
Instead of #RequestMapping you can use #PostMapping which is a shorthand. So you wont get confused with media type, it take application/json as default type.
#RequestMapping(value="saveacademics",method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
replace with
#PostMapping("saveacademics")

How to pass javascript array to spring data rest

How to send array to spring rest? I tried the following but didn't work
javascript:
function postTopic(){
self.data.blogTopicsArr.push({
options: {
"title": self.title.value,
"details": self.topicDetails.value,
"username": "Guest user",
"userImage": "assets/img/spiritual-icon4.png",
"day_posted": new Date().toLocaleString()
}
});
$.ajax({
url: "/new_topic",
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
data: JSON.stringify(self.data.blogTopicsArr),
success: function (res) {
},
error: function (err) {
}
});
}
Topic Bean class:
#Entity
#Table(name = "topics")
public class TopicBean implements Serializable {
#Id
#Column(name = "ID")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "title")
private String title;
#Column(name = "details")
private String details;
#Column(name = "username")
private String username;
#Column(name = "userImage")
private String userImage;
#Column(name = "day_posted")
private Date day_posted;
//Getters and Setters
}
Spring rest:
#RequestMapping(path = "/new_topic", method = RequestMethod.POST)
public ResponseEntity new_topic(#RequestBody List[] topics) throws Exception {
HttpHeaders headers = new HttpHeaders();
headers.add("success", "topic added");
return new ResponseEntity(headers, HttpStatus.OK);
}
I get error: {"statusCode":400,"body":{"timestamp":1484506636823,"status":400,"error":"Bad Request","exception":"org.springframework.http.converter.HttpMessageNotReadableException","message":"Required request body is missing: public org.springframework.http.ResponseEntity seconds47.restAPI.Topics.new_topic(java.util.List[]) throws java.lang.Exception","path":"/new_topic"}}}
How do I solve this?
Update: added topic bean class above with fields I am using in that class
Try using
#RequestMapping(path = "/new_topic", method = RequestMethod.POST)
public ResponseEntity new_topic(#RequestBody List<HashMap<String, Object>> topics) throws Exception
And print out any input from topics. If you do get any values, you need to replace it with
#RequestMapping(path = "/new_topic", method = RequestMethod.POST)
public ResponseEntity new_topic(#RequestBody List<Topic> topics) throws Exception
with the relevant structure of the Topic class.
public class Topic{
OptionsBean options;
...
//getters and setters
...
}
public class OptionsBean{
String title;
String details;
String username;
String userImage;
String day_posted;
...
//getters and setters
...
}
function postTopic(){
var topic = {
"title": self.title.value,
"details": self.topicDetails.value,
"username": "Guest user",
"userImage": "assets/img/spiritual-icon4.png",
"day_posted": new Date().toLocaleString()
};
$.ajax({
url: "/new_topic",
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
data: topic,
success: function (res) {
},
error: function (err) {
}
});
}
#RequestMapping(path = "/new_topic", method = RequestMethod.POST)
public ResponseEntity new_topic(#RequestBody TopicBean topic) throws Exception {
//... do whatever with the new topic
HttpHeaders headers = new HttpHeaders();
headers.add("success", "topic added");
return new ResponseEntity(headers, HttpStatus.OK);
}
topic and TopicBean must have the same members and must be of same type.

How to send a JSON object with an array of objects in it to the spring controller?

I have two domain models mapped using Hibernate #OneToMany. I am trying to create a JSON object in the frontend and send it to the spring mvc controller to set the model data on its own.
Following are my model classes:
ConceptModelDetails.java
#Entity
#Table(name="conceptModelDetails")
#SequenceGenerator(name="CONCEPT_SEQ",sequenceName="concept_sequence", initialValue=1, allocationSize=1)
public class ConceptModelDetails implements java.io.Serializable{
private static final long serialVersionUID = 1L;
#Id #GeneratedValue(strategy = GenerationType.SEQUENCE, generator="CONCEPT_SEQ")
private int instructionsId;
private String operationType;
private String conceptModelID;
private String requestor;
private String status;
private Timestamp requestDateTime;
private Timestamp lastExecutedDateTime;
private Timestamp completedDateTime;
#OneToMany(fetch = FetchType.EAGER, cascade=CascadeType.ALL, mappedBy="conceptModelDetails")
#JsonManagedReference // nested exception is org.springframework.http.converter.HttpMessageNotWritableException:
//Could not write JSON: Infinite recursion
//The fix is to get Jackson to be able to handle bi-directional references
private List<Instructions> instructions = new ArrayList<Instructions>();
public ConceptModelDetails() {
// TODO Auto-generated constructor stub
}
//setter & getter methods
}
and Instructions.java:
#Entity
#Table(name="instructions")
#SequenceGenerator(name="INSTRUCTIONS_SEQ", sequenceName="instructions_sequence",initialValue=1, allocationSize=1)
public class Instructions implements java.io.Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator="INSTRUCTIONS_SEQ")
private int Sno;
private String instruction;
#ManyToOne
#JoinColumn(name="instructionsId")
#JsonBackReference
private ConceptModelDetails conceptModelDetails;
//setter & getter methods
}
This is my send method at frontend to create and send the JSON object:
$scope.send = function() {
console.log("test");
var dataObj = {
"operationType" : $scope.operationType,
"conceptModelID" : $scope.conceptID,
"requestor" : $scope.requestor,
"status" : "new",
"requestDateTime" : null,
"lastExecutedDateTime" : null,
"completedDateTime" : null,
"instructions" : null
};
console.log(dataObj);
dataObj.instructions = [];
console.log($scope.operations_publish);
var ins = getSelected();
for ( var i in ins) {
var temp = {
instruction : null,
conceptModelDetails : null
}
temp.instruction = ins[i];
dataObj.instructions.push(temp);
}
var response = $http.post(
'PostService', dataObj);
response.success(function(data, status, headers, config) {
$scope.responseData = data;
});
response.error(function(data, status, headers, config) {
alert("Exception details: " + JSON.stringify({
data : data
}));
});
}
Following is my controller:
#RequestMapping(value = "/PostService", method = RequestMethod.POST)
public #ResponseBody String Test(#RequestBody ConceptModelDetails conceptModelDetails){
ApplicationContext context = new ClassPathXmlApplicationContext(
"applicationContext.xml");
ConceptModelDAO obj = (ConceptModelDAO) context.getBean("objDAO");
System.out.println("concept id: "+conceptModelDetails.getConceptModelID()+" "+ conceptModelDetails.getInstructionsId());
System.out.println("instructions id: "+conceptModelDetails.getInstructions());
// ConceptModelDAOImpl objDAO = new ConceptModelDAOImpl();
obj.add(conceptModelDetails);
Instructions instructions = new Instructions();
System.out.println("dimba: " + instructions.getInstruction());
ArrayList<Instructions> operations = (ArrayList<Instructions>) conceptModelDetails.getInstructions();
for (int i = 0; i< operations.size(); i++ ) {
instructions.setInstruction(operations.get(i).getInstruction());
instructions.setConceptModelDetails(conceptModelDetails);
obj.addInstructions(instructions);
}
return null;
}
I am getting the eror: 400 (Bad Request) because of List<Instructions> instructions. Please suggest how do I deal with this.
I have found the problem in this code. As explained by Bozho here,
ArrayList<Instructions> operations = (ArrayList<Instructions>) conceptModelDetails.getInstructions();
should be
List<Instructions> operations = conceptModelDetails.getInstructions();
in the spring controller.

Required String parameter is not present error in Spring MVC

I try to make an AJAX query to my controller in Spring MVC.
My action code is:
#RequestMapping(value = "events/add", method = RequestMethod.POST)
public void addEvent(#RequestParam(value = "start_date") String start_date, #RequestParam(value = "end_date") String end_date, #RequestParam(value = "text") String text, #RequestParam(value = "userId") String userId){
//some code
}
My Ajax query is:
$.ajax({
type: "POST",
url:url,
contentType: "application/json",
data: {
start_date: scheduler.getEvent(id).start_date,
end_date: scheduler.getEvent(id).end_date,
text: scheduler.getEvent(id).text,
userId: userId
},
success:function(result){
//here some code
}
});
But I got an error:
Required String parameter ''start_date is not present
Why?
As I know I presented it like (#RequestParam(value = "start_date") String start_date
UDP
Now I give 404
My class to take data
public class EventData {
public String end_date;
public String start_date;
public String text;
public String userId;
//Getters and setters
}
My js AJAX call is:
$.ajax({
type: "POST",
url:url,
contentType: "application/json",
// data: eventData,
processData: false,
data: JSON.stringify({
"start_date": scheduler.getEventStartDate(id),
"end_date": scheduler.getEventEndDate(id),
"text": scheduler.getEventText(id),
"userId": "1"
}),
And controller action:
#RequestMapping(value = "events/add", method = RequestMethod.POST)
public void addEvent(#RequestBody EventData eventData){
}
And JSON data is:
end_date: "2013-10-03T20:05:00.000Z"
start_date: "2013-10-03T20:00:00.000Z"
text: "gfsgsdgs"
userId: "1"
On the server side you expect your request parameters as query strings but on client side you send a json object. To bind a json you will need to create a single class holding all your parameters and use the #RequestBody annotation instead of #RequestParam.
#RequestMapping(value = "events/add", method = RequestMethod.POST)
public void addEvent(#RequestBody CommandBean commandBean){
//some code
}
Here is a more detailed explanation.
I had the same issue.. I solved it by specifying the config params in the post request:
var config = {
transformRequest : angular.identity,
headers: { "Content-Type": undefined }
}
$http.post('/getAllData', inputData, *config*).success(function(data,status) {
$scope.loader.loading = false;
})
config was the parameter I included and it started working..
Hope it helps :)
Spring Boot Code
#RequestMapping(value = "events/add", method = RequestMethod.POST)
public void addEvent(#RequestParam(value = "start_date") String start_date, #RequestParam(value = "end_date") String end_date, #RequestParam(value = "text") String text, #RequestParam(value = "userId") String userId){
//some code
}
Postman Request Link to be send: Add the parameters and value using Parmas in postman and see the below request link.
http://localhost:8080/events/add?start_date=*someValue*&end_date=*someValue*&text=*someValue*&userId=*someValue*

Categories

Resources