Using JSON returned from jersey method - java

I am currently working with Jersey to support RESTful web service with jsp.
I have a form submitted from client side from jsp that calls upon REST api.
index.jsp
<form action = "../project/rest/user/transfer" method = "POST">
<div class="row">
<div class="col">
<h3>Sender Address</h3>
<input type = "text" name = "sender_address" id="sender_address">
</div>
<div class="col">
<h3>Receiver Address</h3>
<input type = "text" name = "receiver_address" id="receiver_address">
</div>
<div class="col">
<h3>Amount</h3>
<input type = "number" name = "amount" id="transferAmount" />
</div>
</div>
<br>
<input id="submitButton" type = "submit" value = "Transfer"/>
</form>
java class that uses jersey
#POST
#Path("/transfer")
#Produces(MediaType.APPLICATION_JSON)
public ResponseMessage transfer(#FormParam("sender_address") String from, #FormParam("receiver_address") String to, #FormParam("amount") int value){
ResponseMessage msg = new ResponseMessage();
msg.setResponseCode("200");
msg.setResponseMessage("some message");
Transaction trans = new Transaction();
msg.setData(trans);
return msg;
}
When the form is submitted, this calls upon the above java method and display a new page that displays the java method info in JSON format.
However, I would like the page to stay on the same page but be able to retrieve/use the Transaction data returned from that java method(JSON object).
Is there a way to perform something of similar?
Thanks

Related

#ModelAttribute return null thymeleaf

I familiarize myself with Thymeleaf.
I am trying to get data from a POST-mapping in the controller.
But I got null variables when I call employee.getName().
I looked a lot online but can't find a solution.
My controller class
#GetMapping
public String getEmployees(Model model) {
model.addAttribute("newEmployee", new Employee());
return "employees";
}
#PostMapping
public String addEmployee(#ModelAttribute("newEmployee") Employee employee) {
System.out.println(employee); // return object
System.out.println(employee.getFirstName()); // return null
return "employees";
}
HTML form with Thymeleaf
<div class="modal-body">
<form th:action="#{/employees}" th:object="${newEmployee}" method="post">
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label class="col-form-label">First Name <span class="text-danger">*</span></label>
<input th:field="*{firstName}" class="form-control" type="text">
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label class="col-form-label">Last Name</label>
<input th:field="*{lastName}" class="form-control" type="text">
</div>
</div>
See tutorials:
Wim Deblauwe: Form handling with Thymeleaf
Baeldung: Binding a List in Thymeleaf
#GetMapping("/all")
public String showAll(Model model) {
model.addAttribute("employees", employeeService.findAll());
return "employees/all";
}
#GetMapping("/add")
public String createForm(Model model) {
model.addAttribute("newEmployee", new Employee()); // the form-data object as blank employee to be filled
return "employees/form"; // the page containing the form
}
#PostMapping
public String addEmployee(#ModelAttribute("newEmployee") Employee employee) {
System.out.println(employee); // return object
System.out.println(employee.getFirstName()); // return null if either not set in HTML-form or not mapped from HTML-form to POST correctly
// save new employee or add to a repository
employeeService.save(newEmployee);
model.addAttribute("employees", employeeService.findAll());
return "redirect:/employees/all"; // use a redirect
}
Client-Server interaction:
First in your browser you should navigate to the endpoint adding the form-data-object, i.e. GET /employees/add.
Then the form-page should load and you will have a blank object newEmployee to bind all the input-fields to for submitting.
After submitting the form via the submit-click, a POST /employees is sent. The server/controller should receive the form-data as model-attribute in employee parameter and can save it.
The controller-method redirects back to the list-endpoint (same as navigating in browser to) GET /employees/all
<h1>Create employee</h1>
<form th:object="${newEmployee}"
th:action="#{/employees}"
method="post">
<input type="text" name="firstName" id="firstName" th:field="*{firstName}" />
<input type="text" name="lastName" id="lastName" th:field="*{lastName}" />
<button type="submit">Submit new employee</button>
</form>
The th:object attribute refers to the key under which we put our Employee instance in the model (newEmployee in this example). The th:action has the URL for the #PostMapping method. Finally, the method attribute is set to "post" since we want to use the HTTP POST method.
Using th:field=*{…​}, we can setup a two-way binding between the HTML input and the field in our form data object.

Missing parameter error when submitting a form with two request params

Below is code from a controller that I'm aiming to make sure it's receiving two input parameters (name and code) from a front-end interface.
It's a page that takes two parameters within a submit form, "name" and "code".
#RequestMapping(method = RequestMethod.POST)
public String transfer(#RequestParam(name = "name") String name,
#RequestParam(name = "code") String code,
Errors errors, RedirectAttributes redirectAttributes) {
try {
User userToBeTransferred = usersRepository.findByName(name);
userToBeTransferred.setTransferred(true);
Region regionOfTransference = regionsRepository.findByCode(code);
regionOfTransference.setPopulationNumber(regionOfTransference.getPopulationNumber() + 1);
userToBeTransferred.setRegion(regionOfTransference);
usersRepository.save(userToBeTransferred);
regionsRepository.save(regionOfTransference);
return "redirect:/section/users/new";
} catch (IllegalArgumentException e) {
return "htmlPageOne";
}
}
The front-page form :
<form class="form-horizontal" method="POST" action="/section/users/new" th:object="${user}">
<input type="hidden" th:field="*{id}"/>
<div class="form-group row">
<label for="name" class="col-form-label">User name</label>
<input type="text" class="form-control" id="name" th:field="*{name}" name="name"/></div>
<div class="form-group row">
<label for="code" class="col-form-label">Code</label>
<input type="text" class="form-control" id="code" th:field="*{region.code}" name="code"/></div>
<button type="submit" class="btn btn-primary col-sm-6 ">Save</button>
</form>
For some reason, I'm getting the following error after I click to submit the form :
There was an unexpected error (type=Bad Request, status=400).
Required String parameter 'code' is not present
org.springframework.web.bind.MissingServletRequestParameterException: Required String parameter 'code' is not present
I'm not sure if I'm using the requestparams correctly, so maybe it's got something to do with this? I don't know, I've been stuck on this for a few hours now, so would appreciate if someone could help me.
The problem is that th:field="*{region.code}" overrides your name attribute into name="region.code". You can tell by inspecting the rendered <input> element using dev tools of your browser.
You can change following
th:field="*{region.code}"
...into:
th:value="${user.region.code}"

Propagate object in thymeleaf form

I have a page with two forms, and want to add object from first form when submitting second one. Basically it looks like this:
First form:
<form action="#" method="POST" enctype="multipart/form-data" th:action="#{/foo}" th:object="${prop1}" id="form1">
<input type="file" name="file" class="form-control"/>
<input type="text" th:value="${prop1.taskSheetName}" name="taskSheetName"/>
<input type="number" th:value="${prop1.descriptionColumnPosition}" name="descriptionColumnPosition"/>
</form>
Second form:
<form th:if="${resourceId}" action="#" method=" th:object="${prop2}" id="prop2" th:action="#{/foo/{id}(id=${resourceId})}">
<input type="url" th:value="${prop2.url}" name="url"/>
<input type="text" th:value="${prop2.username}" name="username"/>
<input type="password" th:value="${prop2.password}" name="password"/>
</form>
And controller methods:
#RequestMapping(value = "/foo", method = POST)
public String uploadFile(#RequestParam("file") MultipartFile file, final ExcelProperties properties, final Model model) {
//some logic here
}
#RequestMapping(value = "/process/{id}", method = POST)
public String processResource(#PathVariable("id") String id, final Prop2 prop2, final Prop1 prop1, final Model model) {
}
And I need to pass the values from first form values to second method with second form values, but it passes empty form object. I tried to add
<div th:with="p1=${prop1}">
since I know that this data is present in page, but it didn't help.
If this even possible or should I just give up and write custom submit handler in javascript?
According to MDN, it's impossible to attach 1 input into 2 forms,
You need to do some work with JavaScript.

`null` result from request in servlets

I am new in servlets-
I am filling text in form but value in request is null-
In login page-
<body>
<form action="">
<input type="text" name="uname">
<input type="text" name="pwd">
link
</form>
</body>
In DisplayPage-
<body>
Display:
<%
String uname=(String)request.getParameter("uname");
String upass=(String)request.getParameter("pwd");
out.println(uname+" - "+upass);
Enumeration<String> enumeration = request.getParameterNames();
boolean b=enumeration.hasMoreElements();
out.println(b);
while (enumeration.hasMoreElements()) {
String name = (String) enumeration.nextElement();
String data=(String)request.getParameter(name);
out.println(name+" - "+data);
}
%>
</body>
Now in my result value of uname and upass is null and hence boolean b is false.Weird!
My Question Is- If request object is created when we use anchor tag since there is no NPE on calling getParameter() on request object,so what kind of data attached with this request object.why this is provided to us?
Because you are not submitting your form to server or not passing any value in url, instead you are clicking on link, which will redirect it to your link.
<body>
<form action="display.jsp"> // added action
<input type="text" name="uname">
<input type="text" name="pwd">
<button type="submit">Link</button> // added submit button
</form>
</body>
For Updated Question
On server side every request is handled as HttpServletRequest object. So when we submit the form, every input field is submitted and then it is retrieved from the request object on server side.

JQuery to update a <c:forEach> in Spring MVC

I сreated a jsp page with the table. I would like to refresh table after click the button using Jquery.
But in result i see two views at the same time. How to avoid this problem ?
My Controller
#Controller
#RequestMapping("/")
public class HelloController {
private final Logger log = LoggerFactory.getLogger(getClass());
#Autowired
private UserServiceDao userServiceDao;
#RequestMapping(method = RequestMethod.GET)
public String printWelcome(ModelMap model) {
model.addAttribute("Message","first");
model.addAttribute("list",userServiceDao.findAll());
log.trace("NUMBER:::::::::::::::::::::"+userServiceDao.findAll().size());
return "main";
}
#RequestMapping("/table")
public ModelAndView renderTable(HttpServletRequest request) {
String name = request.getParameter("nameSearch");
log.trace("1: "+name);
List<User> people = userServiceDao.find(name);
log.trace("2: "+people.size());
return new ModelAndView("main", "list", people);
}
}
MY view with the Jquery script
<body>
<div class="sear">
<input class=" int datasearch" type="search" value="an" id="dataSearch">
<input class="int search" type="button" value="Search" id="search">
<input class="int create" type="button" id="err" value="Create user">
</div>
<h1>List of users: </h1>
<div class="table" >
<c:forEach var="item" items="${list}">
<div class="row" >
<div id="tabl" class="cell" style="width:300px;"><c:out value="${item.name}"/>></div>
<div class="cell" style="width:100px;" ><input class="delete" type="button" value="Delete user"></div>
<div class="cell"><input class="edit" type="button" value="Edit user"></div>
</div>
</c:forEach>
</div>
<script type="text/javascript">
$('#err').click(function(){
window.location.href='/registration';
})
$('#search').click(function(){
$(function() {
var myTableContainer = $("#tabl");
var renderTable = function(container) {
var data = $('#dataSearch').val();
var postReqData = {}; // Create an empty object
postReqData['nameSearch'] = data;
$.get("/table",postReqData, function(data) {
container.empty().html(data);
})
};
/* This is called on document ready */
renderTable(myTableContainer);
/* Use the same renderTable function when the refresh button is clicked */
$("#search").click(function() {
renderTable(myTableContainer);
});
})
})
Ok, this might be a bit too long for comments.
Your main problem is that both #RequestMapping(method = RequestMethod.GET) and #RequestMapping("/table") render the same view.
That is: the view containing all your search inputs, <c:forEach> table and javascript.
So when you do the search and when the ajax call returns, you replace contents of div#tabl with all those search inputs, <c:forEach> and javascript.
You end up with two pieces of everything nested in the wrong way.
My advice would be to do one RequestMapping that renders the basic jsp, and the other one that renders only the search results (or even returns json and render it as html in javascript).

Categories