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()}" />
Related
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.
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("").
Today i have a big discussion with one of our team member about validation of RESTful API input in Controller and Service layer and i feel it is a bad day for making bigger argument. So we have a spring boot microservice application with layered architecture
Controller --> Service --> Repository
The argument is having the validation at each layer or just having the validation at Controller layer, for example we have Controller with POST request and using JSR-380 validation for input request body
Controller :
#PostMapping(value = "/", consumes = {"application/json"}, produces = {"application/json"})
public ResponseEntity<Detail> createConfig(
#NotNull(message = "{error.message.config_detail}")
#RequestBody #Validated Config config) {
return new ResponseEntity<>(configService.create(config.getConfigId(), config.getTaskId()), HttpStatus.CREATED);
}
Config : Request Body
public class Config {
#ApiModelProperty(name = "config_id", example = "1", required = true)
#NotNull(message = "{error.message.config_id}")
private Long configId;
#ApiModelProperty(name = "task_id", example = "11", required = true)
#NotNull(message = "{error.message.task_id}")
#Min(value = 0, message = "{error.message.task_id}")
#Max(value = 9999, message = "{error.message.task_id}")
private Integer taskId;
// bunch of addition fields with validations
}
If the validation success then calling the Service method with some properties from Config
Service :
public Detail create(#Valid #NotNull Long configId, #NotNull Integer taskId) {
// some business logic to convert to entity and saving to database
return repository.save(entity));
}
So if we see the above code, same validation is done at Controller and Service, So i argued that there is no need of validating in Service layer, perform the validation at controller layer and if input is wrong then throw 400 or 500 to user. But another person in team also suggest having validation in each block for whatever is used in the block, so that individual piece of code is safe (focusing on the unit instead of the integration path).
I know i might be wrong in this case, but still not able to understand the validation at each layer,(null check i agree) so it is recommended approach having validation at each level
Controller --> validation call service
Service ---> validation and call business
Business ---> validation and call repository
Repository --> save
But what is the prefered way of validation ? according to me if Controller input is valid call Service and perform business logic and call Repository. correct me if i'm wrong so that i can follow the recommended pattern
You are right : the validation should be placed in controller, if possible. And it's make no sense in my opinion to validate the data more then 1 time.
See also DRY principle https://en.wikipedia.org/wiki/Don%27t_repeat_yourself
It is situational. Some validation needs to be performed in the service layer. Say, you will need to change a state of an object, but only if certain conditions are met etc.
A part from that, as a rule of thumb i follow these guidelines:
If your services are publicly exposed to other services via RMI, then service layer validation is mandatory, if not go with controller level validation.
Unless you are using the services and / or repositories as libraries in other projects, too, it does not make sense to do the validation multiple times.
If the controllers are the only classes accessing the additional layers there is no need for additional validation as you and your controller are the only one to access the Spring beans. You and the controller are in control of accessing the services with valid parameters.
Doing several validations has the disadvantage of writing more complex services - including unit tests.
It is slower.
Changing the validation will take longer as multiple layers have to be changed - including unit tests.
The validations on several layers can and will differ in a matter of time.
The preferred way is to do the validation once in (or even before) the controller and writing integration tests to ensure its functionality.
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!
This is the short description of my situation...
I have spring bean BookingServiceImpl which implements BookingService
BookingService has method: RoomDescription getRoomDescriptionById(String roomId);
I also have JSP page with javascript on it
I want to do something like this in javascript
var roomDescription = bookingService.getRoomDescriptionById(222);
/// ... use roomDescription
The question is: is there any existent framework which does things like that (magically allows to cal spring beans from javascript without additional boiler-plate code, assuming all parameters and method results are JSON-friendly)?
Spring provides mechanisms to expose RESTful endpoints via the Web MVC framework
The documentation is very good. A Controller definition for your specific example could look like this:
#Controller
#RequestMapping(value = "/rooms/{roomId}", method = RequestMethod.GET, produces="application/json")
#ResponseBody
public Room getRoom(#PathVariable String roomId, ModelMap modelMap) {
return bookingService.getRoomById(roomId);
}
On the javascript side, you could use jQuery to make an ajax call to retrieve the data. Here is an example of what that could look like:
$.getJSON('http://yourserver.com/rooms/222',
function(room) {
// Do something with room.description
});
This is a basic example (without proper error handling, security, etc). It's the closest thing to an existent framework that I'm aware of for Spring RESTful calls from javascript. If you need to access the Room data on the client side javascript then you'll need to expose it via some Spring construct (e.g. a Controller)
Take a look at DWR. This is as close as you will get to creating js clients.
http://directwebremoting.org/dwr/documentation/server/integration/spring.html