how to properly use Models on Spring 4? - java

I am new using Spring's MVC (but Ive been using it for some years at other php frameworks).
I have many doubts, I read the spring info and seems to be right and all.. then Ichecked this tutorial http://javahash.com/spring-4-mvc-hello-world-tutorial-full-example/ and it works and all, but on the controller part, there is a code I dont understand, and Id like to know how to properly use the Models on Spring.
As far as I know, the models should call make the calls to the db, so, what about the services (interfaces and implementations) and the DTOs?
At the example they make something like this:
#Controller
public class HelloWorldController {
#RequestMapping("/hello")
public String hello(#RequestParam(value="name", required=false, defaultValue="World") String name, Model model) {
model.addAttribute("name", name);
return "helloworld";
}
}
It receives a model as parameter... I bet if there is any, Spring would use a default one, what if I want to add more interaction and lets say, specifiy a model to call the db? Any idea how I could do that?
And if I want to add a service... I am a little bit clueless about it, if someone could help me to understand...
Thanks in advance

Model is a map representing the data that the view needs. It can contain one or more entities, or simple objects, or strings, or whatever you want.
MVC doesn't require the use of a database. The model does not "call the db". You can inject a repository into your controller to load data from a db into your model.
#Controller
#RequestMapping("/foo")
public class FooController {
#Autowired
private FooRepository fooRepository;
#RequestMapping
String getFoos(Model model) {
List<Foo> foos = fooRepository.findAll();
model.addAttribute("foos", foos);
model.addAttribute("someOtherDataYourViewNeeds", "bar");
return "foo/list";
}
}

This Model Object is injected by spring, and his content will be sent to the view.
You can see the documentation for Model interface here http://docs.spring.io/spring-framework/docs/current/javadoc-api/.
If you wanna access some object on your view, you can you use
model.addAttribute(object).
I think you could read The IoC Container documentation to understand how spring works.

Related

Is there a way to provide an attribute to all models in Spring?

Thymeleaf dropped template expressions like #session, #httpServletRequest etc. in Version 3.1 (https://www.thymeleaf.org/doc/articles/thymeleaf31whatsnew.html).
We used those a lot in relatively large applications. I wrote an interceptor to populate those attributes at every request since I don't want to add them in every Controller needed (like described in the migration guide).
Does anybody know a better way of achieving this?
This is already the best method to populate attributes at each request, compared to the earlier methods defined in the Spring framework documentations.
I learned that #ControllerAdvice can be used in this case (see https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc).
Classes annotated with #ControllerAdvice, can have methods annotated with #ModelAttribute to populate attributes over multiple Controllers (all of them if not specified otherwise).
In my case:
#ControllerAdvice
public class CommonDataAdvice {
#Autowired
private HttpServletRequest request;
#ModelAttribute("request")
public HttpServletRequest populateRequest(){
return request;
}
}

How to structure controllers that communicate with databases

I'm pretty new to the concept of patterns. I am practising my dependency injection skills as well as using DAO principles. The code I have written works but I feel that it can be written in a more elegant fashion. I've tried restructuring it a pattern I saw but that complicated things so not sure if I implemented it correctly. As a general rule when a web application communicates with a database and throws out result, how should one structure their project?
I've heard of the MVC principle but that doesn't necessarily add database to the mix.
This is what I have so far:
A class containing a controller in a Controller package:
#RestController
public class ResponseController {
#Autowired
MongoBase dbConnection;
#RequestMapping(value = "/jsonresult", method = RequestMethod.GET)
#ResponseBody
public String jsonresult(#RequestParam(value = "id", required = true) String id){
return dbConnection.documentToJSON(id, Constants.database,Constants.collection);
}
#RequestMapping(value = "/alljsonresult", method = RequestMethod.GET)
#ResponseBody
public String alljsonresult(){
return dbConnection.allDocumentToJSON(Constants.database,Constants.collection);
}}
A class containing CRUD methods to the database in a Database package:
#Component
public class MongoBase {
#Autowired
MongoClient mongoClient;
public MongoBase() {
try {
mongoClient = new MongoClient("localhost", 27017);
} catch (Exception e) {
e.printStackTrace();
}
}
public void printAllCollection(String databaseName, String collectionName) {
...
}
So is there a better way/more efficient way of writing thi? Also I feel I haven't fully implemented DI in the Monogbase class since it contains the new keyword..
If you are using springboot, then you don't need this old style
also don't need to create mongoClient bean your self, spring boot help you in it
You just need to add following properties in application.properties file
#mongodb
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=app1
Also declares a spring-boot-starter-data-mongodb in your pom or gradle
it's a cool and super awesome dependency for accessing Data with MongoDB
you can read about it from here[https://spring.io/guides/gs/accessing-data-mongodb/]
suppose you have a domain
#Document(collection = "domain")
public class User {
#Id
private long id;
#Indexed(unique = true)
private String domain;
private boolean displayAds;
//getters and setters
}
Now if we need to perform curd operation on this domain, extends MongoRepository, you have CRUD function automatically. Spring data come with many magic findBy queries, review the official Spring data MongoDB – Query methods for detail.
public interface UserRepository extends MongoRepository<User, Long> {
Domain findFirstByDomain(String domain);
Domain findByDomainAndDisplayAds(String domain, boolean displayAds);
//Supports native JSON query string
#Query("{domain:'?0'}")
Domain findCustomByDomain(String domain);
#Query("{domain: { $regex: ?0 } })")
List<Domain> findCustomByRegExDomain(String domain);
}
UserRepository extends the MongoRepository interface and plugs in the type of values and id it works with: User and Long. Out-of-the-box, this interface comes with many operations, including standard CRUD operations (create-read-update-delete).
now you can easly use it in your controller
#RestController
public class ResponseController {
#Autowired
UserRepository userRepository;
#RequestMapping(method = RequestMethod.POST)
#ResponseStatus(HttpStatus.CREATED)
User create(#RequestBody #Valid User user) {
return userRepository.create(user);
}
}
also you can do with it lot of things. you just need to go throw with it doc.
Also you you can use mongoTemplate for execute the query
#Autowired
MongoTemplate mongoTemplate;
When I build web applications I typically define the full chain as follows:
Client Side:
View - This is the V in MVC where you control visuals & user action derived workflow.
Controller - This is the C in MVC where workflow is managed. Most Client processing will go here and multiple Client calls can be made to get/send data or perform lookups.
Client - This is where you make a call to a REST web service and parse/deserialize the results/handle exceptions.
Server Side:
RestController (Sometimes Called Resource) - This is your REST API endpoint. Here you extract & validate a request.
Service - This is where most of your server logic will go. Sometimes you might have to make multiple data access calls or call other service functions.
DataAccessObject (Sometimes Called Provider) - This is your database interaction to pull data from your database into a model. CRUD operations (Create Read Update Delete)
Example Scenario:
Lets say we want to submit data & permissions for a given user
UserView.jsp - User types in user & permission data and hits submit.
UserController.java - validates User & permission data, does any necessary lookups, then calls UserClient.
UserClient.java - Builds the REST request and calls the /user/create REST endpoint.
UserRestController.java - Unpackages/Validates the request, then calls UserManagementService
UserManagementService.java - Server Logic happens here! Lets say I have two tables in my database. A User table and a Permissions table. I want to store the user information in the User table and the permission information in the permission table so I will call the UserDAO for the user data and the PermissionDAO for the permission data.
UserDAO & PermissionDAO - Saves The passed models to their respective tables.
Return to Service, Return to RestController, Return to Client (Parse Response), Return to Controller (Move the Workflow forward with a redirect or a success message).
Conclusion:
This may seem like a lot of in-between steps but this design provides a ton of flexibility, especially if your building large, complex web services. Each component has a specific purpose, follows an easy naming convention, and splits complex logic into smaller, simpler steps.
I'd like to recommend some improvements to your solution:
You're using Spring. You should not create any injected beans using new. Let Spring instantiate and manage those beans for you.
Use the #Repository annotation to mark your persistence class.
Make your repository class interface based.
Don't embed "Mongo" into the class name. You happen to be using Mongo as your persistence provider now, but you may change your mind later. Don't reveal implementation information in your class names - hide it.
The Controller is part of the UI. It uses repositories and/or services to fulfill use cases. It's perfectly correct to use Spring to inject the repository into the Controller.
I'd recommend that you use Spring Boot, an opinionated version of Spring. Have a look at their guides to learn how to use it properly.

Java Spring REST + MongoDB (custom URI? using MongoDB Template instead of respository class? what about the xml config files?)

I currently have been reading and trying out MongoDB with Spring REST framework.
I have the following code for the controller:
#RestController
#RequestMapping("/users")
public class UserController {
#Autowired
private UserRepository userRepo;
#RequestMapping(value = "/info2", method = RequestMethod.GET)
public List<User> getAllUser(){
List<User> users = userRepo.findByEmail("test#test.com");
return users;
}
#RequestMapping(value = "/save", method=RequestMethod.POST)
public User createUser(#RequestBody User user){
return userRepo.save(user);
}
}
However, when I call
localhost:8080/users, it returns back
{
_links: {
self: {
href: "http://localhost:8080/users{?page,size,sort}"
templated: true
}-
search: {
href: "http://localhost:8080/users/search"
}-
}-
page: {
size: 20
totalElements: 0
totalPages: 0
number: 0
}-
}
I want the URI /users/info2 to return back the list of users by that particular email. How do I do that?
Also, here are the outstanding questions I have:
Can I just use MongoDBTemplate instead of the MongoRepository? I want more customized queries, and I couldn't find any in depth examples on the web.
How does Spring framework map the xml config file, for example, in cases like when I setup multiple MongoDB connections?
So without your configs, but looking at your existing code and service response, one can make some general assumptions. Your Repository is annotated with #RepositoryRestController which not only provides Spring Data access but also exposes a common ReST endpoint for your repository.
This can be determined from two aspects of your post. First you don't appear to be using HATEOAS in your Controller class, yet your service exposes JSON + HAL. Furthermore your response exposes the paging and sorting feature of Mongo Repository as well as the search behavior of Spring Data Repositories when annotated with #RepositoryRestController.
If you don't want this behavior, change the annotation on your Repository to #Repository instead.
Also to answer your other questions:
1. you can annotate methods if you want with queries on Spring Data Repositories, you can also use any class in the stack managed by spring you want, but why?
I suggest reading about the bean lifecycle to understand the dependency management within spring, there are plenty of presentations (including one in my github repo). If you have multiple connections, you can define your repository beans to utilize anything you wire it. There is a lot more manual operations at that point, and it will take some understanding and through to make it work. There is no way to give you a simple "do xyz" type answer without a lot more information.

Does Spring MVC create a new object defined as a ModelAttribute on every call?

I am working on a wizard-like set of pages, where the user has to enter bits of data in several views for a final submission, allowing them to go back-and-forth prior to the final Submit is done. I was trying to use the same Bean, defined as a ModelAttribute, for all the views, basically just passing this one Bean around like a token in which each view adds its little bit of data.
The problem is that Spring MVC seems to create a new Bean on ever call. My admittedly fuzzy understanding about the Model was that it was basically like putting something into session, and that object would be around until the session was done. This does not seem to be the case.
So, I guess the first question is...where do Model Attributes "live", and for how long? Is there a better pattern out there for implementing a wizard-like interface using just Spring MVC (I am limited and can't use Web Flow...its not an approved tool where I work)?
It is NOT a good practise to use Model Attribute as a bean. It is good for manimulating form data before they are persisted into database.
#ModelAttribute("formAttribute") is created when you have specified it in your method as parameter:
public void getForm(#ModelAttribute("formAttribute") Form form) {
}
It is created before every method call by calling its contruct:
#ModelAttribute("formAttribute")
public Form getForm() {
return new Form();
}
When it is not specified in method parameter it doesn't exist.
There is possible to add your #ModelAttribute into session by defining #SessionAttributes on your controller:
#Controller
#SessionAttributes("formAttribute")
public HelloController
Then it is initialized once, when you firstly use it, and destroyed when you destroy it by calling:
public void finalStep(SessionStatus status) {
status.setComplete();
}
I think with combination of #SessionAttributes it is possible in relatively easy way create the wizard-like flow.
If Web-flow is not an option, you can try doing this:
Store your model attribute as a session attribute, this is accomplished by adding a #SessionAttribute annotation to your controller:
#Controller
#SessionAttribute("myconversationModel")
public class MyFlowController{
#RequestMapping
public String myMethod(#ModelAttribute("myconversationModel") ConversationModel myConversationModel){
....
}
}
Then where you think you are done with the flow, just accept an additional parameter SessionStatus and call sessionStatus.complete, this will wipe the attribute from session
#RequestMapping
public String myFinalMethod(#ModelAttribute("myconversationModel") ConversationModel myConversationModel, SessionStatus sessionStatus){
sessionStatus.complete();
....
}

Trying to understand the workflow for basic form validation using Spring

New to Spring here, and after reading the reference docs the workflow to validate a simple web form isn't popping out at me.
Could someone give me a beginners overview of how we go about form validation in Spring 3.0.3 (I'm using a mix of annotations and xml config in a webapp that I'm migrating now). Starting from the Controller, what happens?
For example: so far I think I understand that I should "bind" the form data to an object of my creation (say MyPerson for example), then create a Validation object that accepts MyPerson and uses ValidationUtils to perform the validation.
But that's all very fuzzy in my head (especially the "binding" concept) and a step by step review of the workflow from someone who's been through it before would help me be confident that I'm not missing or mis-interpreting any steps.
The method you are mentioning for validating forms is one of a few options you have available.
As well as the method you have suggested you may also want to investigate using JSR-303 annotations with an appropriate implementation (for example Hibernate Validator). There are a lot of example of how to accomplish this.
For the spring validation method your basic steps are:
Create an class to act as a binding object, pass an instance of this to the view in your controller
Bind the object to the fields in your view using the form taglib
In the controller method which handles the form submission, use the #ModelAttribute annotation to bind the form data to your binding object
Use your custom validator object (probably #Autowired to your controller) to perform validation
Heres a simple example controller:
#Controller
public class PersonController {
#Autowired
private PersonValidator personValidator;
#RequestMapping(value="person/form", method = RequestMethod.GET)
public ModelAndView form() {
// Instance of binding object
Person person = new Person();
// Create ModelAndView which displays personForm view
ModelAndView mav = new ModelAndView("person/form");
// Put our binding object in the model
mav.getModel().put("person", person);
return mav;
}
#RequestMapping(value="person/form", method = RequestMethod.POST)
public String save(#ModelAttribute Person person, BindingResult errors, Model model) {
// Call our custom validator and put errors into BindingResult
personValidator.validate(person, errors);
// If we have validation errors
if (errors.hasErrors()) {
// Show form with errors
return "person/form";
}
// Otherwise show some success page
return "person/success";
}
}

Categories

Resources