I have a Struts 2 textfield tag where I just need to get a user enter value and send to the action.
<s:textfield name="user.firstAnswer" size="110" cssClass="FormObjectCompulsary" autocomplete="off" />
Even when this page loads user object contains value for first answer, I don't want to display it in the text field instead I want the text field to be blank.
But with out specify the value attribute still the value in user object shows in this field.
If you are adding a new object user, then you should create this object with new operator before you show it in the JSP. It will contain null references that are not displayed. If the value attribute is not specified, then name is used to show the value.
Make your user object null after inside the execute(). So again it will not show value inside text box.
eg. user = null;
I am showing you piece of code, may be it will help you.
See the execute().
package online.solution;
import com.opensymphony.xwork2.Action;
public class MyAction implements Action {
UserBean user = new UserBean();
public UserBean getUser() {
return user;
}
public void setUser(UserBean user) {
this.user = user;
}
#SuppressWarnings("finally")
#Override
public String execute() throws Exception {
String result = "";
try {
user.setGuest("Bye bye");
System.out.println(user.getUsername() + " " + user.getPassword());
if (user.getUsername().equals(user.getPassword())) {
result = SUCCESS;
}
else {
result = ERROR;
}
user = null; //Make it null when all task completed.
}
catch (Exception exception) {
System.out.println("Exception -> " + exception);
}
finally {
return result;
}
}
#Override
protected void finalize() throws Throwable {
super.finalize();
}
}
By looking at name="user.firstAnswer" I am thinking that you are implementing ModelDriven<> to your action class. What might be happening is that when you return success in your action class and come to the jsp page, and if in action your user model had some values on it.. model driven will set those fields for your on your JSP page.
I have used this approach for update form functionality while learning struts2. Just make sure that user object contains nothing before you return...
Related
alright so this is a bit tricky to explain well but I will do my best and hopefully someone has an idea.
So this project in built using the Spring Framework. I did not write this code but a previous dev who is no longer here.
here is a snippet from the controller.
#RequestMapping(value = "/affidavit/{id}/{userid}", method = RequestMethod.GET)
public String getProgramAffidavit(#PathVariable("id")
Program program, #PathVariable("userid")Attendee attendee, Model model) {
model.addAttribute("affidavitDetailDtoTest",affidavitDetailDto);
return "affidavit/program_affidavit";
}
I won't bother with the code that constructs the affidavitDetailDto object for now as I don't think it is relevant.
so you will see that this adds an attribute called affidavitDetailDTO to the model.
then over on my view page which is a jsp page I have a form with a model attribute of "affidavitDetailDTO" and my related information.
so now is the part I don't understand. I click the 'submit' button and my page and the form posts and calls the following controller method.
#RequestMapping(value = "/affidavit", method = RequestMethod.POST)
public String post(AffidavitDetailDto affidavitDetail, HttpServletRequest request, HttpServletResponse response, Model model) {
String out;
if(request.getParameter("programID")!= null)
out = request.getParameter("programID");
else
return "redirect: " + request.getContextPath()+ "/home";
//Session Information Section
//gets a list of program sessions and assigns it to affidavitProgramSessions dto list
List<AffidavitProgramSessionDto> affidavitProgramSessions = affidavitDetail.getAffProgramSessionList();
//Iterates through list of session in affidavitProgramSessions
for (Iterator<AffidavitProgramSessionDto> iter = affidavitProgramSessions.listIterator(); iter.hasNext(); ){
//create AffidavitProgramSession DTO object and fill it with value from list
AffidavitProgramSessionDto session = iter.next();
//get the programs session ID and assign it to a string
String programSessionDetailId = session.getProgramSessionDetailId();
logger.debug("programSessionDetailId:: " + programSessionDetailId);
//if there was no program session id then remove the item from list
if(StringUtil.isBlank(programSessionDetailId)) {
iter.remove();
}else{
// set the program session detail from value in the program session detail repo found by program session ID
session.setProgramSessionDetail(psdRepo.findOne(UUID.fromString(programSessionDetailId)));
}
}
//End oF Session Information Section
out = "affidavit/summary";
return out;
}
now on the summary jsp page there is the following loop to spit out the results.
c:forEach items="${affidavitDetailDto.affProgramSessionList}" var="session">
so here is my issues.. how the hell is it working. where is that affidavitDetailDto object coming from?
it isn't the GET method in the controller adding it because I can rename the attribute and the summary page still works.
any ideas?
EDIT
Showing how affidavitDetailDto is created in controller.
in the class this is done
#Controller
public class AffidavitController extends BaseController {
private AffidavitDetailDto affidavitDetailDto;
then in the GET Request.
#RequestMapping(value = "/affidavit/{id}/{userid}", method = RequestMethod.GET)
public String getProgramAffidavit(#PathVariable("id") Program program, #PathVariable("userid")Attendee attendee, Model model) {
affidavitDetailDto = new AffidavitDetailDto();
List<AffidavitProgramSessionDto> affProgramSessionList = affidavitDetailDto.getAffProgramSessionList();
Set<ProgramSessionDetail> programSessionDetails = ps.getProgramSessionDetail();
if(programSessionDetails != null) {
for (ProgramSessionDetail programSessionDetail : programSessionDetails) {
AffidavitProgramSessionDto affidavitProgramSessionDto = new AffidavitProgramSessionDto();
AffidavitAttendeeTypeDetailDto affidavitAttendeeTypeDetailDto = new AffidavitAttendeeTypeDetailDto();
affidavitProgramSessionDto.setAffidavitAttendeeTypeDetailDto(affidavitAttendeeTypeDetailDto);
affProgramSessionList.add(affidavitProgramSessionDto);
}
}
model.addAttribute("affidavitDetailDto",affidavitDetailDto);
Also on the model attribute level.
#ModelAttribute
private void addAttributes(Model model) {
logger.debug("call addAttributes.....");
if(affidavitDetailDto != null && affidavitDetailDto.getAffProgramSessionList().size() != 0) {
logger.debug("add affidavitDetailDto to model......");
model.addAttribute("affidavitDetailDto", affidavitDetailDto);
}
If I change the line
model.addAttribute("affidavitDetailDto", affidavitDetailDto);
to be something like
model.addAttribute("testing1234", affidavitDetailDto);
then the affidavitDetailDto objects STILL work on the summary post page.
Edit 2
This is the form tag that the for each loop runs in.
<form:form acceptCharset="utf-8" method="POST" enctype="multipart/form-data" action="${CTX_PATH}/approvedProgram" modelAttribute="affidavitDetailDto" id="jpFormInput">
however.. I can change the modelAtttrbute to equal "Madeupnothing123" and the jsp page still functions as normal.. this is why I am so confused.
I have a form whose purpose is to allow a user to create a new entry in a database table. The form is very large, ~50 fields in total. I'm needing a way get all of these values to my controller, though I don't see an easy way. Every solution I've seen is to have a #RequestParam('field'), but with around 50 fields that is a little crazy. Maybe if using a #RequestParam Map<T, T> is possible?
What I tried at first was to create an AJAX POST call to
baseapplication.com/add?field1=value1&field2=value2&...&field50=value50
but then the servlet complained about not finding the add.jsp file. This is sort of reasonable because that file does not exist, but I created a controller mapping #RequestMapping(value="/add") so I shouldn't actually need that file. I have another method which creates an AJAX GET call to /search with some url parameters, and that works fine. There is also no search.jsp file.
This problem is hard to explain, I hope I did a halfway decent job. Let's look at some code now, with omissions because dealing with ~50 form fields is very lengthy.
Starting with the JavaScript, which initiates this whole process:
ctx = "baseapplication.com"
$('#addNewRecordBtn').on('click', function(){
var m_insId = document.getElementById('m_insId');
//This repeats for every field
var url = ctx + '/add?insuredId=' + m_insId /** + all other fields **/;
addCase(url);
});
function addCase(url) {
$.ajax({
url: url,
type: 'POST'
}).success(function(data){
alert("Successfully added row");
}).fail(function(jzXHR, textStatus, errorThrown){
alert(jzXHR);
alert(textStatus);
alert(errorThrown);
});
}
So the flow of this is as follows: The user clicks on the addNewRecordBtn button, which fires the first function. This function grabs the value of every field in the form, then builds a URL with parameters for each of these values. The addCase() function is then called, which creates an AJAX POST (not sure what to call this?) to the URL that was just built. This function does not succeed, the error alerts provide zero information, but the server console claims Failed to find resource /WEB-INF/views/add.jsp
Now we move into the controller.
#Controller
public class ApplicationController {
#Autowired
SpecialClaimsCaseManager caseManager;
#RequestMapping(value="/add")
public void addRow(#RequestParam Map<String, String> requestParams) {
SpecialClaimsCase newCase = new SpecialClaimsCase();
newCase.setInsuredId(requestParams.get("insuredId"));
//Repeat this for all parameters
caseManager.addNewSpecialClaimsCase(newCase);
}
The caseManager.addNewSpecialClaimsCase(newCase) call just creates a DTO object out of this model object, and then adds that new object to the database via some Hibernate magic. I don't know much about that side, other than it works.
So, I'm not sure if I'm going about this the right way. I hear there's a way to map a model object to a JSP form using Spring's tag library, but that would require a ton of rewriting as the form is huge. I'm also using Bootstrap to build the interface, and I'm not sure if Bootstrap and Spring's tag library mix well. I can't imagine why not.
I'm not sure if I need to be using AJAX here or not. I went with it because I don't want the page to have to reload or anything. I'm not usually a web developer, so I am sure I am lacking some fundamental knowledge here.
My main question is: given my sitatuation, what is the best way to get this massive form of information into my controller?
Thanks in advance for reading this wall of text and code and for any assistance you can offer!
Create a domain class that has all of these needed fields and generate getters and setters and also a constructor. Once you get all these fields/some of these fields POST as json to your controller. The appropriate controller will then call the required service and then the DAO will handle the persistence part.
In short, send the data you need as a JSON object. The json will be made as java object and the operation on the same will be performed.
Here is the controller
#Controller
#RequestMapping(value = "/students/association")
public class StudentDepartmentController {
#Autowired
private StudentService studentService;
#Autowired
private StudentDepartmentService studentDepartmentService;
#RequestMapping(value = "/add-department", method = RequestMethod.POST)
public ResponseEntity<StudentDepartment> createStudentDepartmentAssociation(
#RequestBody final StudentDepartment studentDepartment) {
StudentDepartment newStudentDepartment;
// check if the student exists
Student student = studentService.getStudentByUuid(studentDepartment
.getStudentUuid().getUuid());
if (null == student) {
throw new IllegalArgumentException("No students found!");
}
// check the status of student
if (student.getStatus() == Liveliness.INACTIVE) {
throw new IllegalArgumentException(
"cannot create an association with an inactive student! activate student first");
}
// check for valid department
if (null == studentDepartment.getDepartment().getName()) {
throw new IllegalArgumentException("No such Department");
}
// check if the association already exists
if (null != findOneAssociationAgainstStudent(student)) {
throw new IllegalArgumentException(
"cannot create student department association, as "
+ student.getUsn()
+ " already present in another association ( "
+ studentDepartment.getDepartment().getName()
+ " )");
}
try {
newStudentDepartment = studentDepartmentService
.createNewAssociation(studentDepartment);
} catch (DataIntegrityViolationException ex) {
throw new AutomationTransactionException(
"cannot create student department association, as "
+ student.getUsn()
+ " already present in another association ( "
+ studentDepartment.getDepartment().getName()
+ " )", ex);
}
return new ResponseEntity<StudentDepartment>(newStudentDepartment,
HttpStatus.CREATED);
}
private StudentDepartment findOneAssociationAgainstStudent(Student student) {
return studentDepartmentService.findOneAssociation(student);
}
private StudentDepartment findOne(Uuid uuid) {
String studentDepartmentUuid = uuid.getUuid();
return findOne(studentDepartmentUuid);
}
private StudentDepartment findOne(String uuid) {
return studentDepartmentService.findOne(uuid);
}
#RequestMapping(value = "/delete-association", method = RequestMethod.DELETE)
public ResponseEntity<String> deleteStudentDepartmentAssociationByUuid(
#RequestBody final StudentDepartment studentDepartment) {
// check if association exists
StudentDepartment association = findOne(studentDepartment.getUuid());
if (null == association) {
throw new IllegalArgumentException("No such association found!");
}
studentDepartmentService.deleteAssociation(association);
return new ResponseEntity<String>("success", HttpStatus.OK);
}
}`
the #RequestBody annotation helps you to make the json object into java object.
with this, you can take the payload as json, and get the java object and send the json back to the UI with ResponseEntity<Class> annotation
I am attempting to create a registration handler for my Play Framework application but I am running into some trouble. The goal of this code is to grab the data that was submitted and then check if the username or email is in use. This is done using methods built into my User class, which is a model.
The register method:
public static F.Promise<Result> register() {
// Get the POST data and turn it into something we can read from
DynamicForm form = Form.form().bindFromRequest();
// Get the email, username, and password
String email = form.get("email");
String username = form.get("username");
String password = form.get("password");
return User.findByUsername(username).map(user -> {
// For .map to run we must not have encountered an error, this means
// a user already has this username (otherwise the doc would not exist)
return redirect("/register");
}).recover(userCheckError -> {
// For .recover to run there must have been an error. This will happen
// if a doc was not found with the username (therefore it is not in use)
return User.findByEmail(email).map(option -> { // ERROR START
// We now have an F.Option object. If the email is already taken,
// then the Option is defined (has a value within it), if the email
// is free, the Option will be undefined (no value within it)
if (option.isDefined()) {
return redirect("/register");
} else {
return redirect("/register");
}
}); // ERROR END
});
}
The findByUsername and findByEmail methods (in the User class):
public static F.Promise<User> findByUsername(String username) {
return bucket.get(username.toLowerCase(), User.class);
}
public static F.Promise<F.Option<User>> findByEmail(String email) {
return bucket.find("users", "by_email", QueryHelper.findOne(email), User.class).map(result ->{
if (result.isEmpty()) {
return F.Option.None();
} else {
User user = result.iterator().next();
return F.Option.Some(user);
}
});
}
Edit: I have added comments to the register method and removed some unneeded code. I have also labeled where the error starts and ends (the lines that IntelliJ is highlighting. The exact error is "bad return type in lambda expression". The register method needs to return a Promise<Result> but that block of code is returning a Promise<B> (generic?).
Javadocs:
http://www.playframework.com/documentation/2.3.x/api/java/play/libs/F.Promise.html
http://www.playframework.com/documentation/2.3.x/api/java/play/libs/F.Option.html
class SampleAction extends ActionSupport {
private Map<String,String> circleIdNameMap;
public String preprocess(){
--logic for populating value of MAP
}
--getters and setters
}
Now my problem is on page load I call preprocess function and populate the value of Map. After page submit another method is called and during that after some DB interaction it redirects to JSP, but this time the value of Map is empty. I am using this Map for drop-down tag in Struts2.
My preprocess is associated in the link like:
href="/gma/preprocessConfigureTspThreshold?operatorId=5102&sessionId=12332"`
So only first time when the link is clicked preprocess is called, after that when I redirect to my JSP so its not called then, so second time the value of Map is empty.
Shall I put the map in a session so that it is retained? Or can do something else?
I read that don't use preprocess function, use Preparable interface. But as per docs:
The prepare method will always be called by the Struts 2 framework's prepare interceptor
whenever any method is called for the Action class.
So, it will be called for every method. I want preprocess to be called only when page loads.
The prepare method of the Preparable action class is called on every action execution, that's right. That might be the reason why you prepare the map for a drop-down in the preprocess method.
public class SampleAction extends ActionSupport {
private Map<String,String> circleIdNameMap;
private String circleId;
//getters and setters here
protected boolean reload = false;
private void preprocess(){
// Get the Map by calling a stateless Session bean
circleIdNameMap = remoteInterface.getMap();
}
public String action1(){
preprocess();
Map session = ActionContext.getContext().getSession();
session.put("circleIdNameMap ", circleIdNameMap );
return SUCCESS;
}
public String action2(){
Map session = ActionContext.getContext().getSession();
circleIdNameMap = (Map<String,String>)session.get("circleIdNameMap");
if (circleIdNameMap == null){
if (reload) {
preprocess();
Map session = ActionContext.getContext().getSession();
session.put("circleIdNameMap ", circleIdNameMap );
} else {
addActionError("circleIdNameMap is null");
return ERROR;
}
}
return SUCCESS;
}
...//other actions
}
the JSP for drop-down
<s:select name="circleId" list="circleIdNameMap" listKey="key" listValue="value"/>
The meaning of this code is: you should not return result SUCCESS or INPUT if fields in JSP aren't initialized.
I have a spring controller that I want a method to handle a certain request and then redirect to another one with keeping some value attached, so I will use RedirectAttributes on the first one and #ModalAttribute on the second, but the thing is I will not always have this modal attribute existing so I want to add it only if it exists.
#RequestMapping("/main")
public String getMain(Model model,HttpSession session,#ModalAttribute List<Loans> loansList){
if(session.getAttribute("user") != null){
if(session.getAttribute("current_start")!=null){
model.addAttribute("loans",loanDao.findAll((Integer) session.getAttribute("current_start")));
} else {
model.addAttribute("loans",loanDao.findAll(0));
session.setAttribute("current_start",0);
}
model.addAttribute("loan",new Loan());
model.addAttribute("countries",countryDao.findAll());
model.addAttribute("types",typeDao.findAll());
session.setAttribute("total_loans_number", loanDao.findCount());
return "main";
} else {
return "redirect:index";
}
}
and the redirecting one one is
#RequestMapping(value = "/search")
public String searchLoans(Model model,RedirectAttributes redirectAttributes,
#RequestParam String keyword){
redirectAttributes.addAttribute("loansList",loanDao.findAll(keyword));
return "redirect:/main";
}
but here the #ModalAttribute fails because it sometimes does not exist,sometimes I request main with out the loansList, how to make a condition to add it only if it exists ? or how to do this correctly ?
you can let spring populate your model attributes using #ModalAttribute annotation on methods:
#ModalAttribute("results")
public List<Loans> populateLoans() {
return new ArrayList<Loans>();
}
#RequestMapping("/main")
public String getMain(Model model,HttpSession session,#ModalAttribute("results") List<Loans> loansList){
if (CollectionUtils.isNotEmpty(loanList)) {
// do something if the loan list is not empty.
}
}