I have two entities : User and Post (relation one-to-many). Post fields: id, creationDate, title, content, user.
Data is stored in the database and accessed via Hibernate.
I have a controller to pass Post object as a JSON to JavaScript. Then it is shown on the web page. But it is not always necessary to pass all the Post fields. For ex., I need to show to the user only title and creation date, and if the user presses the button Show content, only then I need to show post content (which I want to request from server only when it is need to show).
So here is a problem: How can I implement lazy initialization of the content field in Post object? Should I write two methods in my controller: one for generating JSON with list of Posts and setting content field to null or empty String, and another to pass only content string?
Make post content an object and a single table in db.
It looks like the following in java:
public class Post {
...
PostContent postContent;
}
First you may try to initialize the lazy collection at the DAO via Hibernate.initialize(lazyCollection). If it didn't work then either use FetchType.EAGER or keep the session open during request and the collection should be fetched when needed.
Related
I've a simple RESTful API based on Spring MVC using a JPA connected MySQL database. Until now this API supports complete updates of an entity only. This means all fields must be provided inside of the request body.
#ResponseBody
#PutMapping(value = "{id}")
public ResponseEntity<?> update(#Valid #RequestBody Article newArticle, #PathVariable("id") long id) {
return service.updateById(id, newArticle);
}
The real problem here is the validation, how could I validate only provided fields while still require all fields during creation?
#Entity
public class Article {
#NotEmpty #Size(max = 100) String title;
#NotEmpty #Size(max = 500) String content;
// Getters and Setters
}
Example for a partial update request body {"content": "Just a test"} instead of {"title": "Title", "content": "Just a test"}.
The actual partial update is done by checking if the given field is not null:
if(newArticle.getTitle() != null) article.setTitle(newArticle.getTitle());
But the validation of course wont work! I've to deactivate the validation for the update method to run the RESTful service. I've essentially two questions:
How can I validate only a "existing" subset of properties in the
update method while still require all fields during creation?
Is there a more elegant way for update partially then checking for
null?
The complexity of partial updates and Spring JPA is that you may send half of the fields populated, and even that you will need to pull the entire entity from the data base, then just "merge" both entity and the pojo, because otherwise you will risk your data by sending null values to the database.
But merging itself is kind of tricky, because you need to operate over each field and take the decision of either send the new value to the data base or just keep the current one. And as you add fields, the validation needs to be updated, and tests get more complex. In one single statement: it doesn't scale. The idea is to always write code which is open for extension and closed for modifications. If you add more fields, then the validation block ideally doesn't need to change.
The way you deal with this in a REST model, is by operating over the entire entity each time you need. Let's say you have users, then you first pull a user:
GET /user/100
Then you have in your web page the entire fields of user id=100. Then you change its last name. You propagate the change calling the same resource URL with PUT verb:
PUT /user/100
And you send all the fields, or rather the "same entity" back with a new lastname. And you forget about validation, the validation will just work as a black box. If you add more fields, you add more #NotNull or whatever validation you need. Of course there may be situations where you need to actually write blocks of code for validation. Even in this case the validation doesn't get affected, as you will have a main for-loop for your validation, and each field will have its own validator. If you add fields, you add validators, but the main validation block remains untouchable.
I am going to implement following function:
As front-end tool, HtmlBox is used to edit text data and then transmit these data to back-end controller to save in database.
My question is:
How could the back-end controller receive the data edit and submit by HtmlBox?
According to the common coding way of Spring MVC I used, One class called Data is created with a private member variable named "articleContent", the same as the textarea id in the web page the HtmlBox embeded in. In my opinion, when the object of Data class is passed into the Controller as a parameter and the form, contain a HtmlBox with text data in it, is submitted, the data should be got by the controller easily as a String variable? But the fact isn't like this, the data object's articleContent is null?
How should controller get the data?
I have obtained the answwer of this question by myself!
In the front end Jsp view, the textarea enhanced by HtmlBox must use the "name" property or both "name" and "id" properties instead of "id" property alone! For instance:
<textarea id="theHtmlBoxName" name="theHtmlBoxName"></textarea>
In the back end controller, code as one of following:
public String saveTheHtmlBoxContent(#RequestParam String theHtmlBoxName){...};
or
public String saveTheHtmlBoxContent(HttpServletRequest request){
String data = request.getParameter("theHtmlBoxName");...};
Kenneth
In my project i dynamically generate the text box in table like below
project Name Date1 Date2 Date3 Date4 Date5 Activity
java Development Addnew
C++ Development Addnew
i display tables for one week.if user clicks addnew i generate the dynamic text box below the row where user clicked addnew button.
My problem is how to get all the textbox value in my spring controller as bean class.Because i am not sure abut how many text boxes are come in page load and submit.
Any Idea will be greatly appreciated!!!
There aren't enough specifics in your question for a specific answer. However the general approach I would recommend.
If you have a framework like Backbone or Angular, investigate use of its collection facilities.
Write JavaScript that builds JSON array from all your textfields
Define a POJO in Java that mirrors each entry in your array.
Ensure you're using Jackson - this maps JSON to Java objects for you before your controller is called
Define an method in your controller that takes a list of POJO, e.g. create(List values) with a URL like /times/{ employeeId} using PUT
For reading out of the database, add method in your controller that returns a list of POJO, e.g. List values get(long employeeId) with a URL like /times/{ employeeId} using GET
Alternatively if you need the form to be 'live', i.e. 'Add new' causes row in database instantly use a REST interface with a create, update and DELETE using POST, PUT and DELETE respectively
I assume you'll need to update the list later, so I'd recommend a structure with an ID which can be used for CREATE and UPDATE operations, not just a plain list of Strings, this will also allow more fields later.
public void Foo {
private String project;
private String name;
private long id;
// getters + setters
}
JSON for a create
[{"project":"java","name":"Development",id:0}, {"project":"C++","name":"Development",id:0}]
JSON for a later update, i.e. with IDs round-tripped
[{"project":"java","name":"Development",id:100}, {"project":"C++","name":"Development",id:101}]
Go with the traditional getParameter() method. I assume your text box will have unique names while generated using jquery.
In the controller,
List<String> requestParameterNames = Collections.list((Enumeration<String>) request.getParameterNames());
for (String parameterName : requestParameterNames) {
String attributeName = parameterName;
String attributeValue = request.getParameter(parameterName);
// will have the text box values
}
we have created a jBPM workflow where we are passing custom object to create a workitem, we are passing this custom object as Map params.
Now using REST API "List getTasksAssignedAsPotentialOwnerByStatus" we can retrieve the TaskSummary for assigned userId, here TaskSummary object is predefined with fields, can anybody please guide me if i want to customize my response (i.e. if i want to retrieve additional parameters in the TaskSummary) then how can i do it using REST API?
The task summary should link a content id (in task data), containing the parameters you passed. Use this content id to get the content.
Hi all question I'm having problems finding an answer for...
Use Case:
Reading in an Excel spreadsheet in a controller. A 4 row sheet was processed and row 2 and 3 had some errors in it, so I skip them and move on with the rest of the processing. But I want to retain these rows to display to the user after the processing is complete. I'd like to retain all the values in the row to display back to the user just to provide enough information.
So what I tried to do was this:
#RequestMapping(value = "/bulk-create", method = RequestMethod.POST)
public String bulkCreate(Model model, SpreadSheetFile spreadSheetFile){
...some code...
List<Row> errorRows = new LinkedList<Row>();
...some code to process rows...
//Error Found
errorRows.add(row);
...more code to wrap up processing (possibly more errors)...
model.addAttribute("erroRows", errorRows);
return "redirect:/bulk-review"
}
#RequestMapping(value = "/bulk-review", method = RequestMethod.GET)
public String bulkReview(Model model,
#ModelAttribute("errorRows")
LinkedList<Row> errorRows){
model.addAttribute("errorRows", errorRows);
return "bulk-review";
}
So basically I'm trying to pass a LinkedList from one MVC method to another without actually hitting a page first (unless I'm misunderstanding how "redirect:" works... it calls the controller method first correct?)
When I but a break point into the bulkReview method, errorRows is empty... So how do I retain this value between the two methods?
Thanks for the help! Let me know if I need to clarify anything! :)
Kris
I don't think the redirect mechanism works the way you think it does. The first controller sends back a URL to the user's browser which the browser then follows. And by default, Spring places any data in the model at the time of a redirect in the redirect URL, so that the page-being-redirected to can "see" the model data. However, this doesn't work well when you have complex data in the model.
So, you need to think about how the data will be passed in the redirect URL that the browser sends back to the user. How does a List get serialized to the URL? probably not very well.
Another option would be to put the data in session from one controller and access it in the second.