I'm developing a set of microservices for a web application with Spring Boot, and I'm unsure if the pattern design I'm using is correct, or makes sense, or has any advantages.
What I'm using is a controller-facade-service design, which in my mind should work in this way:
The controller delegates everything to the facade, passing the input DTO to it
The facade implements all the business logic and uses one or more services to create an output DTO to send back to the controller
Services implement core and atomic functionalities, mostly CRUDs, without any or minimal business logic so that different facades with different business logic can use them, and return a JPA entity to the facade
Is this a good design pattern? Is the facade unnecessary?
More specifically, should the business logic be in the facade or in the service? I believe services should be logic agnostic so that they can be shared across multiple facades, which may implement different logic depending on the endpoint.
Also, in the case of a CRUD operation, should the service return an entity to the facade? Or should it be up to the service to create an output DTO for the facade?
Related
It feels comparatively easy to implement a bunch of classes that will eventually be part of a UI and need to be persisted without dealing with things like Hibernate or Spring and then, once tested and working in unit and integration tests, add in Hibernate and Spring later. In fact, I think maybe that is the correct approach. But is it realistic? If you know from the outset that a class would have to be persisted and indeed multiple classes which have complex relationships have to be saved to a database, would that not in practice affect the design? Or can you actually just get all the logic working, ignoring the eventual persistence and UI and add it in later?
You mentioned developing without UI and persistence layer. Then the only layer of prominence which remains is Service layer.
If you are going ahead with implementing only the service layer its NOT a bad idea. Reason, now-a-days there are many RESTful services. They do not have a UI. But on the other hand they do have persistence. However, the process of exposing them as RESTful services,determining their input/output format(JSON schema mostly) and testing their integration with any other system can still be done without a persistence layer.
This is not to say that your service layer will also be exposed as RESTful service. Even if it is not - while implementing your services you need to -
design your service granularity(fine or course)
design your DTOs(Data Transfer Objects) which will be responsible for carrying data from UI layer to service layer where they will be converted to domain objects(but this conversion to domain classes can wait till you implement persistence)
unit test your service classes and make sure business logic is implemented correctly
Considering there are a lot of things that can be done without a UI & persistence layer - I would say go ahead - design and even start implementing.
But keep in mind only one caveat - keep some buffer integration time when you integrate your service layer with UI & persistence layers.
I don't know where to put the business logic in spring mvc because I'm new to it. I have a clue on what to do but because of lack in knowledge in spring mvc, I don't know where to start. I would also like to ask if somebody knows where I can get a good tutorial on this or a complete sample of a spring mvc web application that has a business logic on it? Anyways, the business logic that I was talking about is all about database handling :)
#Controller classes serve as C from MVC. Note that the real controller in Spring MVC is DispatcherServlet that will use the specific #Controller class to handle the URL request.
#Service classes should serve for your service layer. Here you should put your business logic.
#Repository classes should serve for your data access layer. Here you should put CRUD logic: insert, update, delete, select.
#Service, #Repository and your entity classes will be M from MVC. JSP and other view technologies(e.g. JSP, Thymeleaf etc.) will conform V from MVC.
#Controller classes should only have access to #Service classes through interfaces. Similar, #Service classes should only have access to other #Service classes and for a specific set of #Repository classes through interfaces.
Many people would recommend to add the business logic to the service layer. I personally find out that's not a great idea, specially when you start testing: you may have to deal either with the persistence and business logic at the same time, or mocking everything around, and then things can get very messy.
I do recommend reading this article before taking any conclusions:
The Biggest Flaw of Spring Web Applications
Resuming, the idea would be to move the business logic to the model layer and simplify your services methods.
Generally, your business logic goes in the service layer. Though you can put basic validation rules in your pojos with JSR annotations.
For a Spring MVC app you have controllers, which handle http requests, and a domain layer, which are pojos representing your business models. You often have a persistence layer, or DAO. You might have a service layer as well, for helping with non-trivial logic.
Your comment about database handling doesn't make sense. Business rules are orthogonal to storing data. Your database handling should go in your persistence layer.
I have a design/architectural problem:
I've started developing a java web application. I thought of using 3 layers: a persistence layer (with jpa and hibernate), a business layer and a presentation layer. My problem now is:
the jpa entities would make the model but can or may I use the entities as business objects?
Is this a practice? My common sense says I shouldn't, but then, I need to duplicate these entities as business objects?
Finally, I'd like the presentation layer to be really decoupled from the other layers. While using spring mvc with jsp at first, I'd like. if it's suitable, at some moment to switch to javascript-based application that communicates with the backend through rest requests.
Yes, you can. Outside the persistence context, the JPA Entities are like simple POJOs. It is legal to use them in business code (actually, as hinted by JB Nizet, you usually ALWAYS use them in your business layer without DAO). If it is tightly related to the Entity, you can even add business logic into your JPA beans. Nevertheless, it will be harder to read and understand what the code does. But if you have a reason to do that - there is nothing illegal. It all comes down to software design practices and what you need most.
When you want to change your app into the REST-powered service, it is not difficult. You will have to change the Servlet you are currently running your app with for a JAX-RS or other framework Servlet which will handle HTTP requests in a REST manner for you. It is done in web.xml. Then, you will place your html-pages in any place, where it is accesible for the remote hosts, and connect them to your REST-service with the Javascript AJAX or sth. You should take care of CORS then.
I've participated in several projects of Spring-based web-application - and have written a quantity myself. Usually we have (roughly speaking) following folders to divide our classes by categories like dao, models, web (for controllers if we use Spring MVC or backing beans for JSF for example) and also service - here we keep what we think is business-logic (even when sometimes classes here simply forward methods to dao).
Now I am faced with development of EJB application - I've learnt that I will have some web and model classes anyway. Also I may use dedicated dao layer or may put data access into facades (I prefer dedicated folder though it increases verbosity).
But I do not understand clearly whether facades are exactly the place to put business-logic in it, or I should add services folder for it and use facades more like dao (eliminating dao itself).
I also would be glad for short and comprehensive compilation of hints on EJB application architecture.
I would go with a similar setup with EJB as you have done with Spring. You have your web package (MVC stuff), then your service layer which contains most business logic and then DAO layer which contains basic CRUD operations and some database queries.
In this scenario you can test the possibly complex business logic in the session beans with fast unit tests that don't need database and you can mock the DAO access here. Then you can have relatively simple tests for your DAO layer, so the number of tests requiring database (ie. that are consirably slower) is smaller.
Normally I would call facade a set of session beans that offer simple methods for operating the system via for example Web services. These beans would use the normal service layer beans. With just a web layer and no integration layers I don't see a reason to create an extra facade layer.
Can anyone point me in the direction of documentation for exposing a DAO as an external web service? Currently, in my application we follow a DAO -> Service -> UI layered architecture. Everything is internal to the app, our DAOs access the DB through Spring JDBC and the services are visible only to the web application.
We now have a need for downstream systems within my company to access the DAOs we've created. I need to know what the effort would be to expose our DAOs and what, if any, other technologies I would need to perform this task.
Also, would I expose the DAOs themselves or the services?
I guess I don't fully understand the problem. You'll have to create service operations that do CRUD operations for you DAOs, along with operations for any special data processing your DAOs perform. You already expose the DAOs via service to your current UI. Can you not simply use that service as a template for your externally facing service?
If I were you, I'll just wrap the DAOs in a webservice. So, first define the wsdl, then generate the java code that goes with that wsdl. Then, in the webservice implementation, just hand-copy the entity beans into this webservice beans. Guess you could use bean copy utils if that is too tedious.
Not sure if you can use the entity beans directly in java2wsdl style webservice development, but that seems like a bad idea because you don't have an abstraction layer between entity beans and webservice interface in that case.