Java MVC Understanding - java

I have a hard time understanding on how to user MVC pattern in my java based web application.
I have multiple tables (postgreSQL 9.4) and the data stored there is going to be visible to multiple users.
As far as my understanding goes I need a Model (which holds all data from the DB tables)
and any user who wants to view any of this data uses a view to do so.
Right now I have a class that is full of getter methods. Each of those asks the database to provide the stored data from a specific sql table. That data is then retured as a json String into my .jsp page and there I fill this data into a html table (.jsp just hols the table construct)
This is sort of a model, except the fact that data is just pulled from the db and given to the jsp to display.
From there on, how can I assure that all users always have the same view on the data and data is always up to date even when user A makes changes to the data that other users are also looking at??
As I have multiple db tables do I need a model for each table?
EDIT:
The way I would approach this issue would be the following.
I have a class (model) for each database table.
On Application startup I pull the data from the SQL table and store it inside the specific class
If any user wants to view data I have a getter Method in each model class to send this data to the .jsp page for display
If any user does changes to the database (setter method) the data is (after the set method is executed) pulled again so the model is up to date
Then I somehow need the data that is viewed by any user is updated on the .jsp page
Is this going in the same direction as MVC pattern?
EDIT1:
An example
One of my SQL tables looks like this
CREATE TABLE users
(
id serial NOT NULL,
user character varying(50) NOT NULL,
CONSTRAINT users_pkey PRIMARY KEY (id)
)
My Model class looks like this:
public class Users extends HttpServlet implements Servlet{
private List<List<String>> users = new ArrayList<List<String>>();
private void load_userData(){
// Code to pull data from database
/**/
List<List<String>> users = new ArrayList<List<String>>(2);
// instantiate array list
users.add(new ArrayList<String>());
users.add(new ArrayList<String>());
try {
m_ResultSet = database_connection.execute_querry_on_db(query);
while (m_ResultSet.next()) {
users.get(0).add(m_ResultSet.getString("id"));
users.get(1).add(m_ResultSet.getString("user"));
}
} catch (SQLException ex) {
Logger.getLogger(Login.class.getName()).log(Level.SEVERE, null, ex);
}
// store pulled data into model
this.users = users ;
}
private List<List<String>> get_userData(){
// Code to pull data from Model
return users;
}
private void set_userData(){
// make changes to SQL table with an update/insert query
// Update Model with new data since it has been altered
get_userData();
}
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
String requested_values = request.getParameter("type");
if("get_users".equals(requested_values)){
String json_users = new Gson().toJson(get_userData());
// write JSON string to response
response.getWriter().write(json_users);
}
}
}
This way the model is always up to date with the actual data from the database.
Since there is model & controller in the same class a possible controller would look like the one below??
Because using a controller like this I have to some "initialisation" in a main area of my code I guess, but that is not clear to me..
public class User_Controller extends HttpServlet implements Servlet{
private User_data model;
public OE_Controller(User_data model){
this.model = model;
}
private List<List<String>> get_userData(){
return model.users;
}
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
String requested_values = request.getParameter("type");
if("get_users".equals(requested_values)){
String json_users = new Gson().toJson(get_userData());
// write JSON string to response
response.getWriter().write(json_users);
}
}
}
####### Solution to MVC-"Problem" #######
What do you think about this solution? (as the controller will hand out data directly, instead of calling a method from "main")
Users.java (Model)
public class Users{
private List<List<String>> users = new ArrayList<List<String>>();
public List<List<String>> get_users(){
return users;
}
// Fill model with data from database
public void pull_UserData(){
/**/
List<List<String>> users = new ArrayList<List<String>>(2);
// instantiate array list
users.add(new ArrayList<String>());
users.add(new ArrayList<String>());
try {
m_ResultSet = database_connection.execute_querry_on_db(query);
while (m_ResultSet.next()) {
users.get(0).add(m_ResultSet.getString("id"));
users.get(1).add(m_ResultSet.getString("user"));
}
} catch (SQLException ex) {
Logger.getLogger(Login.class.getName()).log(Level.SEVERE, null, ex);
}
/**/
this.users = users;
}
}
User_Controller.java (Controller)
public class User_Controller extends HttpServlet implements Servlet{
private Users model;
public User_Controller(Users model){
this.model = model;
}
public List<List<String>> get_users(){
return model.get_users();
}
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
String requested_values = request.getParameter("type");
if("get_users".equals(requested_values)){
String json_users = new Gson().toJson(get_users());
// write JSON string to response
response.getWriter().write(json_users);
}
}
}
"MAIN"
// create Model
Users model = pull_UserData();
// create Controller
User_Controller controller = new User_Controller(model);
// get Model data
controller.get_oes();
// Even though I will never access Model data from here since
// my Controller will hand out the data via the do_Get() method
// "Main" is just to load the model data once on application startup
// and the model data reload is done after a setter method is executed
public static Users fill_model_Users_data(){
Users users = new Users();
users.pull_UserData();
return users;
}
What is left is to have the data always updated on all session in the frontend.
So each user of my application needs to see the same data. Here I would need a listener that refreshes the .jsp page when another user does changes to the database. How would I do this??
EDIT:
I found some solutions working with a time interval to check for new data but that still leaves me with the problem that there is a data mismatch based on how long the timer interval is & setting the interval to 1ms for example cannot be the optimal solution I guess (there has to be a "smoother" way to do that)
I'd rather have the application to update the .jsp page with new data as soon as there is new data available & even then I'm left with the Race-Condition which user is faster in clicking a button to lets say delete a user (one will succeed & one will fail)

You do not use a controller for communication between model and view as far as I see that. So it's not really MVC.
It is not necessary to have a model for each table, but it is recommended.
The idea itself seems to be solid.
To be more specific:
I have often seen and used the following structures: controller, services and models. The models save the data whereas the services are responsible for pulling it once the user sends a request. The request is handled via the controller, which informs the corresponding service to pull the data and provides the necessary models to the view.
A short example I found (Hibernate/Spring MVC)
UserController (manages all incoming requests and communicates with UserService):
#RequestMapping(value = "user/{id}", method = RequestMethod.GET)
#ResponseBody
public User get(#PathVariable Long id, Locale locale, Model model) throws NotFoundException {
User u = userService.find(id);
if (u != null)
return u;
else
throw new NotFoundException("user not found");
}
#RequestMapping(value = "user", method = RequestMethod.GET)
#ResponseBody
public List<User> list(Locale locale, Model model) {
List<User> l = userService.list();
return l;
}
UserService (takes care of providing the right data for the controller):
public User find(Long key) {
// access on database
return (User) sessionFactory.getCurrentSession().get(User.class, key);
}
public List<User> list() {
// again query the database for a list but not for a single user
// the DAO is just something hibernate specific
return userDAO.list();
}
And then at last there is a class User which is used for communication to the interface (and contains all necessary attributes) - in this example it was used to pass via REST/JSON.

To ensure that the JSP page always shows the latest data, page has to be refreshed using javascript or ajax.

Related

Update Specific Fields with Spring Data Rest and MongoDB

I'm using Spring Data MongoDB and Spring Data Rest to create a REST API which allows GET, POST, PUT and DELETE operations on my MongoDB database and it's all working fine except for the update operations (PUT). It only works if I send the full object in the request body.
For example I have the following entity:
#Document
public class User {
#Id
private String id;
private String email;
private String lastName;
private String firstName;
private String password;
...
}
To update the lastName field, I have to send all of the user object, including the password ! which is obviously very wrong.
If I only send the field to update, all the others are set to null in my database. I even tried to add a #NotNull constraints on those fields and now the update won't even happens unless I send all of the user object's fields.
I tried searching for a solution here but I only found the following post but with no solution: How to update particular field in mongo db by using MongoRepository Interface?
Is there a way to implement this ?
Spring Data Rest uses Spring Data repositories to automatically retrieve and manipulate persistent data using Rest calls (check out https://docs.spring.io/spring-data/rest/docs/current/reference/html/#reference).
When using Spring Data MongoDB, you have the MongoOperations interface which is used as a repository for your Rest endpoints.
However MongoOperations currently does not supports specific fields updates !
PS: It will be awesome if they add this feature like #DynamicUpdate in Spring Data JPA
But this doesn't mean it can be done, here's the workaround I did when I had this issue.
Firstly let me explain what we're going to do:
We will create a controller which will override all the PUT operations so that we can implement our own update method.
Inside that update method, we will use MongoTemplate which do have the ability to update specific fields.
N.B. We don't want to re-do these steps for each model in our application, so we will retrieve which model to update dynamically. In order to do that we will create a utility class. [This is optional]
Let's start by adding the org.reflections api to our project dependency which allows us to get all the classes which have a specific annotation (#Document in our case):
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.12</version>
</dependency>
Then create a new class, called UpdateUtility and add the following methods and also replace the MODEL_PACKAGE attribute with your own package containing your entities:
public class UpdateUtility {
private static final String MODEL_PACKAGE = "com.mycompany.myproject.models";
private static boolean initialized = false;
private static HashMap<String, Class> classContext = new HashMap<>();
private static void init() {
if(!initialized) {
Reflections reflections = new Reflections(MODEL_PACKAGE);
Set<Class<?>> classes = reflections.getTypesAnnotatedWith(Document.class); // Get all the classes annotated with #Document in the specified package
for(Class<?> model : classes) {
classContext.put(model.getSimpleName().toLowerCase(), model);
}
initialized = true;
}
}
public static Class getClassFromType(String type) throws Exception{
init();
if(classContext.containsKey(type)) {
return classContext.get(type);
}
else {
throw new Exception("Type " + type + " does not exists !");
}
}
}
Using this utility class we can retreive the model class to update from it's type.
E.g: UpdateUtility.getClassFromType() will returns User.class
Now let's create our controller:
public class UpdateController {
#Autowired
private MongoTemplate mongoTemplate;
#PutMapping("/{type}/{id}")
public Object update(#RequestBody HashMap<String, Object> fields,
#PathVariable(name = "type") String type,
#PathVariable(name = "id") String id) {
try {
Class classType = UpdatorUtility.getClassFromType(type); // Get the domain class from the type in the request
Query query = new Query(Criteria.where("id").is(id)); // Update the document with the given ID
Update update = new Update();
// Iterate over the send fields and add them to the update object
Iterator iterator = fields.entrySet().iterator();
while(iterator.hasNext()) {
HashMap.Entry entry = (HashMap.Entry) iterator.next();
String key = (String) entry.getKey();
Object value = entry.getValue();
update.set(key, value);
}
mongoTemplate.updateFirst(query, update, classType); // Do the update
return mongoTemplate.findById(id, classType); // Return the updated document
} catch (Exception e) {
// Handle your exception
}
}
}
Now we're able to update the specified fields without changing the calls.
So in your case, the call would be:
PUT http://MY-DOMAIN/user/MY-USER-ID { lastName: "My new last name" }
PS: You can improve it by adding the possibility to update specific field in a nested objects...

Object exists and can be used on JSP page but I don't know WHY it works

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.

Getting large form to Spring controller

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

Session Synchronization in Spring MVC

Good day everybody.
Please help me.
I have application and simple Controller which search data from database and when data founded in database it render them in browser also when data appears on page there is also Render in EXCEL button appears if user wants render it in Excel file. Here is controller:
#Scope("session")
#Controller
public class SearchController {
//Apache log4j logger for this controller to bring info to console of executing inside of this controller
#SuppressWarnings("unused")
private static final Logger logger = LoggerFactory.getLogger(SearchController.class);
#Autowired
private EducationWebServiceInterface educationWebService;
List<FormDate> listForm = null;
#ModelAttribute("listOfDates")
public List<Date> prepareModelDate() {
List<Date> listOfDates = educationWebService.fetchAllDatesService();
return listOfDates;
}
#ModelAttribute("listOfNames")
public List<String> prepareModelNames() {
List<String> listOfNames = educationWebService.fetchAllInstitutionNamesService();
return listOfNames;
}
#ModelAttribute("listOfTypes")
public List<String> prepareModelTypes() {
List<String> listOfTypes = educationWebService.fetchAllInstitutionTypesService();
return listOfTypes;
}
#RequestMapping(value="/search", method=RequestMethod.GET)
public String search(FormBackingObjectSearch fbos, Model model) {
model.addAttribute("fbosAttributes", fbos);
return "search";
}
#RequestMapping(value="/result", method=RequestMethod.GET)
public String resultHTML(#RequestParam String particularDate,
#RequestParam String nameOfInstitution,
#RequestParam String typeOfInstitution,
#ModelAttribute("fbosAttributes") #Validated FormBackingObjectSearch fbos,
BindingResult bindingResult,
Model model) throws Exception {
ValidatorSearch validatorSearch = new ValidatorSearch();
validatorSearch.validate(fbos, bindingResult);
if(bindingResult.hasErrors()) {
return "search";
}
listForm = new ArrayList<FormDate>();
//Case 1:
if(!fbos.getParticularDate().equals("") && !fbos.getNameOfInstitution().equals("") && fbos.getTypeOfInstitution().equals("")) {
listForm = educationWebService.fetchByDateAndNameService(DateChangerUtils.dateConvertation(fbos.getParticularDate()), fbos.getNameOfInstitution());
model.addAttribute("findAttributes", listForm);
//Case 2:
} else if(!fbos.getParticularDate().equals("") && fbos.getNameOfInstitution().equals("") && !fbos.getTypeOfInstitution().equals("")) {
listForm = educationWebService.fetchByDateAndTypeService(DateChangerUtils.dateConvertation(fbos.getParticularDate()), fbos.getTypeOfInstitution());
model.addAttribute("findAttributes", listForm);
//Case 3:
} else if(!fbos.getParticularDate().equals("") && fbos.getNameOfInstitution().equals("") && fbos.getTypeOfInstitution().equals("")) {
listForm = educationWebService.fetchByDateService(DateChangerUtils.dateConvertation(fbos.getParticularDate()));
model.addAttribute("findAttributes", listForm);
//Case 4:
} else {
throw new Exception("Exception occurs because it's not correspond to any case in controller");
}
return "search";
}
#RequestMapping(value="/result.xls", method=RequestMethod.GET)
public String resultXLS(Model model) throws NullPointerException {
if(listForm == null || listForm.isEmpty() == true) {
throw new NullPointerException("Can not create Excel file because no data to create from");
} else {
model.addAttribute("findAttributesXls", listForm);
}
return "xlspage";
} //End of the resultXLS(..) method
} //End of the class
Now let's play with tabs in browser:
My problem is that when I save rendered data in browser tab one as Excel file once and open new tab in browser tab two, find and render some different data in tab two again and after come back to tab one in my browser and again trying to save same data from table one as Excel file I get data from table two(latest I render), but I want to get my old data from tab one
I learn before Servlets and really interested of session synchronization. It my works in my case In servlets it just can be reached by: HttpSession session = request.getSession();
How can I do this in Spring MVC??? And does it will solve my problem??
Please give me advice.
Thank you people.
With all the best.
You can access the session in your controller method by adding a parameter HttpSession session
#RequestMapping(value="/result.xls", method=RequestMethod.GET)
public String resultXLS(HttpSession session, Model model) throws NullPointerException {
Object myObj = session.getAttribute("myAttr");
....
}
Another alternative is to have a parameter of type HttpServletRequest in the controller method
#RequestMapping(value="/result.xls", method=RequestMethod.GET)
public String resultXLS(HttpServletRequest request, Model model) throws NullPointerException {
Object myObj = request.getSession(false).getAttribute("myAttr");
....
}
But, Synchronizing the session will not solve your problem. Session synchronization is best suited for the situations where a lot of parallel requests keep coming and modifying the shared data which is stored in session. This is not the case you are talking about.
What you want is something like tab based states which is something you would not get any ready made solution, neither it's a good practice to go for. It will make your session very heavier and your web-application will not scale.

spring form tags to have default values

in My jsp I am using spring form tags to bind and update data.
my scenario is to show default values when user enters the page. these default values should come from database depending on some conditions.
But when user edits the data and submit, I want to save them in databse without updating the default values.
Any suggestion is greatly appreciated!
Standard approach to a form page is to have a controller with two methods, one for GET and one for POST. You'll also need an object to bind to the form.
The method that handles the GET sets up the bind object and puts it in the model, then returns the view for the form page. The bind object here can be created with default values which you can get from anywhere. Your bind object will probably have some key, like an ID. The default one can have a zero/default key.
The method that handles the POST takes the bind object as a parameter. It probably validates the values then inserts into the database. Its likely the database will generate the key/id.
Here's an example;
#Controller
public class PersonController {
#RequestMapping(value="/person.do", method=RequestMethod.GET)
public ModelAndView setup() {
ModelAndView response = new ModelAndView("person");
//Create default bind object, can get values
//from database if you like. Here they're just
//hard coded.
Person person = new Person();
person.setName("Joe Bloggs");
response.addObject("person", person);
return response;
}
#RequestMapping(value="/person.do", method=RequestMethod.POST)
public ModelAndView post(#ModelAttribute("person") Person person,
BindingResult result) {
Validator.validate(person, result);
if (result.hasErrors()) {
ModelAndView response = new ModelAndView("person");
response.addObject("person", person);
return response;
} else {
personDao.store(person);
}
return new ModelAndView("redirect:nextPage.do");
}
}
The form will be populated with any values you supply in the backing object. I don't understand the second part of your question.

Categories