I need to create a simple project that uses the Model-View-Controller principle and a MySQL database. And I want to use Spring Boot with Spring MVC and Spring Data JPA.
And I want to make GET, POST, PUT and DELETE requests that call the database and send a JSON to the client.
#GetMapping(value = "/users")
public Users getUsers() {
// call the service -> call the database
}
And the response will be:
{
"name": "John",
"age": 45,
...
}
Does this project use the MVC principle? Or do I need to use a .jsp for the view to have a complete MVC principle?
So the Controller is the REST Controller and the Model is the Users POJO. And if this project use the MVC principle can somebody explain where is the view?
And if the service calls the repository and fetch the data from the MySQL database I want to know if the MVC is modified by adding the DAO, or the DAO is a part of the Model?
MVC is an architectural design pattern for the layers of your application. It is exactly about inner work of your application.
REST is how does your application interact with other applications.
You can combine them together at one application.
In general they are different patterns for different problems:
MVC you are receiving request -> process it (fetching the data from DB or with some ways) -> render it to the view -> and view with requested data return to the caller.
REST (Representational State Transfer) flow is quite similar. However, instead of return view with the data -> your app sends just representation of the data. The content type of response should be specified by the caller at request.
Now go one by other parts of your questions. (Maybe, it is even too many questions just for one question to answer them properly)
Does this project use the MVC principle? Or do I need to use a .jsp file for the view to have a complete MVC principle?
From the snipped which you have already shared - you used REST - and your method return JSON representation of resource.
For now looks like it is the desired goal which you want to achieve:
And I want to make GET, POST, PUT and DELETE requests that call the database and send a JSON to the client.
If you want to use MVC you have to return a rendered view with fetched data instead. Keep in the mind that you have to return HTML page to the caller at that case:
#Controller
#RequiredArgsConstructor
public class ControllerDemo {
private final UserService userService;
#GetMapping(value = "/users")
public String getAllUsers(Model model) {
// add fetched data to model as attribute
model.addAtribute("users", userService.findAll());
// view resolver should be configured to render response to `response-page.ftl` for example
return "response-page";
}
It doesn't matter if you use JSP or Freemarker or Mustache, etc - the main idea is that you create template and data from DB will be represented according to this template on HTML page.
So the Controller is the REST Controller and the Model is the Users pojo. And if this project use the MVC principle can somebody explain where is the view? - with REST approach is no view, the response at this case is representation of resource.
And if the service calls the repository and fetch the data from the MySQL database I want to know if the MVC is modified by adding the DAO, or the DAO is a part of the Model?
DAO stands for Data Access Layer. You a have a model - User class which describes your entity. And you store some user entities at DB. And you want to receive the all users which have already been stored (in real life you need to have pagination but we omit it for simplicity).
Thus for doing it you have to go row by row for your users table and convert the row from DB to the User entity. And you take this retrieving to separate data layer - DAO.
DAO is not part of the Model it is separate layer between Model and DB.
You could not do it at your service layer (UserService) because it will brake the Simple Responsibility Principle (SOLID Principles) for the service layer - do one job and do it well.
At the same time you support high cohesion for parts of your app (GRASP Principles)
MVC is the pattern to implement UI. So if you are just developing a REST API, no UI is involved and hence you do not need to concerned whether it is implemented as MVC or not.
Instead if you are developing a web application , the view is the technology to render HTML codes to the browser . Usually they are just a template engine such as JSP , FreeMarker or Thymeleaf which allows you to use their expression language to access the data in some Java object (i.e. Model) to define the HTML code that you want to generate as a template.
In Spring MVC , you need to use #RestController for developing a REST API while #Controller for the web application. The main difference is that #RestController includes #ResponseBody which will by-pass the view resolution process as there are no view in the REST API.
In short, as you are developing a REST API now , there are no UI and no view. Hence MVC is not applicable in here and you do not need to worry whether it is implemented based on MVC or not.
And if the service calls the repository and fetch the data from the
MySQL database I want to know if the MVC is modified by adding the
DAO, or the DAO is a part of the Model?
DAO is an object that is responsible for getting and managing the data from DB. It is nothing to do with Model.
Related
I'm starting to play around with Spring Boot to learn how it functions for a MVC web application.
At a high-level the goal is to have a controller that will handle GET requests by issuing a request to an external gRPC server which will return a Order protobuf message. The Order data will be added to the Model and served via a template with Thymeleaf.
I am new to the Spring framework as a whole so the approach is likely incorrect but what I was doing is:
#Controller
public class OrderController {
#GetMapping("/order")
public String getOrder(#RequestParam(name = "order_number") String orderNumber, Model model) {
// Code for getting Order proto message from external server here
model.addAttribute("name", Order.getDate());
model.addAttribute("total", Order.getTotal());
model.addAttribute("number", Order.getNumber());
....
return "order";
}
}
However, this seems pretty tedious (especially for larger messages). Is there something I am missing that would allow me to add these fields en-masse?
Sorry, I cannot comment on question (SO restriction), hence asking here - cannot you just put your order object in model (rather than individual fields) and access it's fields/methods in view (Thymeleaf)?
In controller
model.addAttribute("order", order);
in view, I am not sure as I have not used Thymeleaf but should be simillar to
<span th:text="${order.getName()}" />
I'm new to Spring Framework and currently trying develop an simple application were restaurant owners can add a dish to a main database through logging in and imputing the dish data into a Html form (with Thymeleaf). (dish name, price, gluten free = true etc.)
App users should then be able to search the main database based on their location and dietary requirements etc.
I'm trying to learn through Youtube tutorials however, all of them seem to use #RestController and #Requestbody and use Postman to send JSON requests. I'm having difficulty adapting this to my Html form.
I have used the #controller annotation for simple 'save' methods but when I research 'how to include a foreign key in the data added to the data base' (i.e. include 'restaurant id' as foreign key in the 'dish' class), all of the tutorials use #RequestController and JSON requests in Postman.
As I'm trying to build a usable application sending requests in Postman doesn't seem like a good solution.
I think the problem I'm according to other posts is the following:
"If you use template engine like Thymeleaf it will not work with #RestController because of #ResponseBody which included in this annotation" – Sonique
"#ResponseBody makes the returned objects to something that could be in the body, e.g. JSON or XML" – Martin Thoma
I've tried removing #RequestBody and changing it to #RequestParam but I get errors.
Are there any work-arounds to my issue? E.g. using a different file format for the 'add new dish' form or not using Thymeleaf?
Any help/advice would be very much appreciated!
If you want to use HTML with Thymeleaf and the class should annotate by #Controller and the method parameter that handle the object from the FORM you want to control should be #ModelAttribute("").
I am new to Restful web services in Java and trying to discover it by using MVC design pattern.
I have a simple HTML form with one button and one input text box. When the user types something into the text box, I want to store this data in DB.
This is part of my HTML code:
<input type="button" onclick="doneButton()" value="Done" />
When the button is clicked, I call "doneButton()" function as
<script>
function doneButton() {
var param = document.getElementById("text").value;
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
document.getElementById("text").innerHTML = xhttp.responseText;
}
};
xhttp.open("GET","MYURL"+param);
xhttp.send();
}
</script>
I am able to call my RestFul web service by the AJAX code above.
In my web service, I call my model class and establish DB connection there. After that, I call my DAO class from my model class and store the required data in DB table.
As far as I know MVC design pattern:
I should not call a web service directly from view. I should first call
A controller from the view
This controller should call the Restful web service.
The web service should call the model class.
The model class should class DAO and DB operation.
Is this corrent in terms of MVC design pattern?
Can I call a Restful Web service directly from view in MVC design pattern?
I use jersey in web.xml:
RESTful Service
com.sun.jersey.spi.container.servlet.ServletContainer
1
RESTful Service
/webservices/*
Can you please help me to understand how I should build my application using MVC design pattern?
Thank you for your help.
Best Regards
Let me clarify this for you:
View makes a RESTful call to the controller. In other words, your controller is one API in your RESTful web service.
Controller calls the DAO layer, which in turn returns data from the underlying database.
Controller uses the returned data, also called the model, to return response to the view.
This is just an example, hope this helps
$(document).ready(function() {
$('#response_button').on('click', function() {
// console.log($('#request_textarea').val()); //get your values you need to send to the controller
$.ajax({
type : "GET",
url : "url", //call to your controller here.
data : "xmlRequest=" + $('#request_textarea').val() + "&functionType=submit_request", //append your data here
success : function(msg) {
$("#response_textarea").text(msg); //response from the controller will be processed here.
}
});
});
});
Call your DAO layer via the service layer and return the data back to the UI. To answer one of your questions, You can call the controller from the view.
Well thanks for your question.
First I want to tell you that your basic idea is right.
You should not call a web service directly from a view.
Also true is the fact that the controller is your entry point for displaying a view of your application.
But I think there is a little misunderstanding of the term 'view'.
For most MVC Frameworks a view is some sort of a template that is composed of HTML and several placeholders for the data.
A controller might call a REST service. It might also get it's data by querying a database directly. How the data is retrieved is pretty much dependent on the actual implementation of the controller.
Yet, client-side MVC Frameworks like Angular.js are usually designed to work with REST services.
So using REST services for the data operations is a good idea in case you want to use a Javascript MVC Framework.
Now what does a controller do?
A controller listens to a specific resource (a URL) and responds to it.
It does that by binding a (view) model to the requested view (usually an HTML template).
It basically replaces the placeholders from the view-definition with actual data and displays the completed HTML to the client.
If form data gets posted to the controller it parses the data and updates the view model accordingly.
So what is a (view) model and how is it populated with data?
Well, a (view) model is the M in MVC. It is the actual model that is bound to the view. In some cases the view model might be coincident with the domain model. That is usually the case when you are working with javascript based MVC frameworks. So your view model is not just a simple data model that contains the data bound to the placeholders of a specific view template. It terms of js MVC frameworks it might also contain the business logic that is called by the controller...in javascript...on the client. -> That's the downside.
In your case all the DB operations are handled by the REST service. So you have a server side component that has it's own data model which is independent of the MVC structured presentation layer. The REST service is therefore not part of the MVC approach! So you can still implement server side validation in the REST service operations if you want to. But remember that your client side controller has to translate between the client side (view and domain model) and the server side (domain and/or persistence model²).
² nicer word for an anemic domain model.
Roadmap:
Find an answer to the question: Do I build my own MVC framework (hint: bad idea!) or do I use an existent MVC framework to take advantage of the MVC approach?
Select an MVC framework that fits your needs and download it.
Create model, views and controllers.
But before you're actually thinking of building an MVC structured presentation layer you might want to understand what a REST service is and how it is structured and created.
I hope that helps.
Happy coding!
It seems like I can do everything that the Controller class do inside Spring Web-Flow, for example decision making and switching from page to page. To my understanding, its the C inside the MVC model. Am I correct about this?
So my question is, is there any advantage to still include a Controller class when using Spring Web-Flow?
If you need access to the request and response, an appropriate design might still include a controller while also having a flow.xml. For example, if you had this code:
HttpServletRequest request = (HttpServletRequest)context.getExternalContext().getNativeRequest();
HttpServletResponse response = (HttpServletResponse)context.getExternalContext().getNativeResponse();
It's more intelligible to put that in a controller rather than a service.
Also, if you want to register a custom editor, it might make sense to have the controller have this logic in the initBinder() method.
Spring Web Flow uses the Spring MVC framework. The DispatcherServlet handles the request. A FlowHandlerMapping is used to map the request to a particular Web Flow.
Web Flow is to solve the problem involved with controller logic that spans multiple-page navigation (a pageflow, or wizard).
Web Flow can eliminate the need for specialized controller classes to accomplish following a path of page transitions/form updates along a predefined workflow. If you don't need to do this, you can save yourself a lot of configuration/complexity just by using MVC.
I have a problem with populating a model content in Spring MVC application, based on user role managed by Spring Security.
In my application (simplified example) I've got two roles defined: ROLE_USER and ROLE_ADMIN. Also I've got a page that displays a two separate lists of objects: readers (only available for ADMIN) and books (for both, ADMIN and USER).
There is no problem in conditional displaying lists in JSP Page, but I need to prepare model first and I don't want to load readers list if current user isn't an ADMIN.
I've thought about using Spring EL in Java code to determine if user has specified role (hasRole('ROLE_ADMIN')), but I can't find a way to manually evaluate that code.
Is there some way to call Spring EL handler in controller source code, or maybe there is a better solution (on architectural or design pattern level) for conditionally populating model, than checking roles directly in java code.
The issue was tackled by #Chepech and #Boris Kirzner in Prevent Method call without Exception using #PreAuthorize Annotation. That way you can return null (or empty list in your case) when a AccessDeniedException occurs.
One approach would be to just return everything when you're generating your model then rely on #PostFilter to filter that result based on roles. If you don't want to go that route, you could have your controller call out to another bean to build up specific parts of your model, and that other bean could have the role annotations attached. That would effectively limit you from ever creating objects if they won't be used.
If conditionally displaying of page parts is controlled by JSP page, then a conditional populating of model should be done by a controller (because JSP page and Controller are tightly coupled in view layer).
If we use annotations in service layer it will put the responsibility in wrong layer of an application (in service layer instead of view layer).
My final solution is based on remembering a Set of user Roles as user session attribute:
/* This is executed once, after user successful login. */
Set<String> roles = new HashSet<String>();
for (GrantedAuthority authority : authentication.getAuthorities()) {
roles.add(authority.getAuthority());
}
session.setAttribute("userRoles", roles);
Then if I want to conditionally populate a model I only need to check if required Role is contained by that Set.
Set<String> roles = (Set<String>) session.getAttribute("userRoles");
if(roles.contains("ROLE_ADMIN")) {
putReadersInModel(model);
}
I think that solution is clean and keeps the responsibility of proper populating of model in Controller.