I'm building a web application that primarily constitutes of CRUD operations of data from back end/database. There are instances where in I have to write business logic(I'm sure we will have more business logic built as we go deeper in to development). Currently for each UI screen I'm creating I create a model class,Service class, DAO class, a controller(it's servlet essentially) and bunch of jsp pages. In most cases the service class just calls the methods from DAO to pass in model objects. Essentially we use model classes to map data from UI screens. Hence the controller will have the model objects populated when a form is submitted. I have started using service classes to keep a separation layer from web layer to DAO layer. But at times I feel that the service class is just adding unnecessary level of API calls, I would think that I could just inject the DAO in to Controller and complete the task faster. I want to use the service class only when there is additional business logic to be performed. If you have to design an application what factors do you consider using controller->DAO vs controller->Service->DAO control flow?
DAOs are more granular and deal with one specific entity. Services provide macro level functionalities and can end up using more than one DAO. Typically, Services are used for defining transaction boundaries to gain atomicity. In other words, if you end up updating multiple tables using multiple DAOs, defining transaction boundary at service will help in either committing or rollbacking all the changes done to DB.
In your design, since you are primarily doing CRUD for various entities, it may seem that services are not adding much value. However, think of web-based front end as one way of updating data. Usage of services will allow you to expose same capabilities as a web-service later to other forms of client like third party integrators, etc.
So, in summary, your design seems to be in line with conventional practices. If you feel that you can combine multiple services into one based on some common theme such that it can reduce the overhead of code, then, you should go ahead and do it. At the end of day, ultimate goal is to create maintainable code which no one is afraid to change when need arises.
In Pro-Spring-3 book they mentioned below line, for controller with JPA2
Once the EntityManagerFactory had been properly configured, injecting it into your service layer
classes is very simple.
and they are using the same class as service and repository as in below:
package com.apress.prospring3.ch10.service.jpa;
// Import statements omitted
#Service("jpaContactService")
#Repository
#Transactional
public class ContactServiceImpl implements ContactService {
private Log log = LogFactory.getLog(ContactServiceImpl.class);
#PersistenceContext
private EntityManager em;
// Other code omitted
}
but in case you are going to use spring-data CRUDRepository or JPARepository then your DAO will be Interface and you have to make service layer to handle your code
I'd reference my answer here
The long and short of it is the advantage of using a Service layer is it gives you room to move in the future if you want to do anything with Spring Security and roles etc. It allows you to handle transactions more atomically and Spring itself has really nice annotations for this.
Use a service class when dealing with more than one aggregate root.
Inject repositories (aka a dao that returns a collection) or dao's directly into controller, no need for an extra layer/class to do a basic get.
Only use service classes where necessary, otherwise you have twice as much code as required.
You can make repository generic, and annoatoate with #Transactional(propagation = Propagation.REQUIRED) which enforces a transaction is present, but won't create a new one if already present. So if you later use multple repositoes in one service class method, you will only have the one transaction.
Related
I'm new to Spring and I'm creating a REST-Service.
I wonder what the Service-Layer is for (#Service).
Currently I encapsulate my DAOs with that Layer.
So for example my PersonController receives a PUT, calls the PersonService which calls the DAO which finally saves the person in my database.
I also saw some examples in the www. (https://howtodoinjava.com/spring/spring-core/how-to-use-spring-component-repository-service-and-controller-annotations/)
I also have read this question here: Is this a good Spring Architecture (include testing)
Do I even need the Services, if it only calls the DAO like:
public void save(Person p) {
personDAO.save(p);
}
?
I don't really see what the advantage of this is. I create classes which actually do nothing... Or is it just a architecture standard because additional business logic will be in this layer too?
Also... when I have several services like personService, familyService, animalService, etc. and they all have some method signatures that are the same and some which aren't... is it useful to use Interfaces here?
When I create Interfaces like: Saveable, Loadable, Deleteable (does this even make sense?) - how do I use them correctly? Do I create a new Interface for every service that extends the Interfaces I desire? Like a PersonServiceInterface that extends Loadable and Deleteable and I implement it in my PersonService?
Thanks in advance!
If you do not feel the need for a service layer, then chances are high your controllers are performing way more business logic than they should.
adding a service layer in between allows for dedicated tests of pure frontend (controller handle request and response wiring only / services handle the business logic/ repositories persist and query the data).
so rule of thumb - it is much easier to have many services handle fractions of your logic than to stuff everything into your controllers
i am not sure what you are trying to solve with the interfaces you introduce - i do not think it makes sense to re-invent the Repository interface on top of your services. If your services only forward to repositories directly then there is no use in having them anyway.
Let's say we have some layer above service layer, with web controllers for example. Service layer is in turn above DAO/Repo layer. In the upper layer the service calls are used alongside repo calls. It breaks the layering of the application to some extent, but should we really bother about wrapping repo methods like findAll() into service methods. I don't think so. Are there any drawbacks that might cause a lot of pain because of such design? Transactional issues?
I would turn your question around and say - why not have a service layer for such a method? Is it such a pain to wrap a DAO method like:
public class PersonService {
...
private PersonDao personDao;
...
public List<Person> findAll() {
return personDao.findAll();
}
...
}
Client data
What if you don't want to send back the data entity that represents a Person to your controller? You could map the data in the service layer to an Object that only clients are dependent on.
Coupling
You are also coupling your layers. The controller layer should only depend on the service layer and the service layer should only depend on the DAO layer.
Transactions
All transactions should be handled at the service layer (as a service method may call multiple DAO methods).
Business Logic
All business logic should be in your service layer. Therefore, you should never bypass such logic by calling a DAO directly.
I know, for a method like findAll, it seems pointless but I think the point about layer coupling defeats that argument.
Yes it can be a pain if some developer used to call DAO layer code directly from other layers i.e. other than Service layer or whatever architecture you are following for this as a solution:
Use maven dependencies create 4-5 different modules for your project and mention the dependencies in pom.xml so that no calls will be made from any other incorrect layer.
For making it more clear:-
If you want to access layer 3 only from layer 4 just add one dependency entry in layer 3 for 4 and as no other modules have access to layer 3 they can't call code from it.
You definitely get hundred of example for doing this.
I have design issue when implement 1 simple web application.
I use struts2 web controller, spring’s IOC and Hibernate as persist layer.
Because this web application is very simple at begging. So I only have 2 layers:
1 DAO layer which used to access database. Almost every table have related DAO.
2 Action layer. User struts2.
I am satisfy with this architecture because can quickly implement my web application.
As project become bigger, I found the action layer become big and complex, and very hard to re-use.
I try to create service layer, to solve complex business logic is good, but my application still have a lot of simply logic. E.g: Load 1 object, save 1 object, and get collection by some condition and display it to webpage. If give each simple DB access method have corresponding service method. Still cost a lot of effort. How can solve this issue?
And I think, if service layer existing, direct call DAO layer still not good design for my application.
Is any good solution for this kind of small web application?
When planing the different layers in a web application it is good practice to explicitly protect attributes and associations in your model from being manipulated without providing an identity context.
This is something that should neither be done in the DAO layer nor in the Controller. You should wrap your DAO layer in a service layer and have the controller only talk to the services not the DAO directly.
Protecting your model against unwanted manipulation means that you for instance adapt the amount of information passed in a data structure between Controller and Service to the actual operation that you want to perform.
For instance: adding or removing an element from a collection is an explicit operation in the service, it does not happen implicitly by manipulating a collection as a member of a DAO object and passing that DAO back into the service.
Instead your service may look like this:
+ getAllCompanies(): CompanyType[*]
+ getAllEmployeesOfCompany(c: CompanyType) : EmployeeType[*]
+ addEmployeeToCompany(e: EmployeeType, c: CompanyType)
+ removeEmployeeFromCompany(e: EmployeeType, c: CompanyType)
The additional benefit of such an architecture is that the service layer serves as boundary for your transactions. Using the methods of your controller as boundary for your transactions is in fact a very bad habbit. You could even call it an anti-pattern. Why? Because for instance it would mean that when your client hangs up it would roll back your transaction. That is clearly unwanted in 99% of the cases.
As #mwhs commented, Apache Isis provides plenty of guidance on layering your app. To figure out whether it fits your requirements, you could run through this tutorial I presented at a recent conference.
How should be separated Repository and Service? IMHO clients (e.g. Controller) should primaly use Service layer instead of Repository as it should be separated from persistance implementation. Single Repository should provide methods of access of only one entity, while methods of Service are able to provide more complex actions, including usage of multiple repositories.
But what to do with rich repositories, that provides not only CRUD methods but much more, like JPARepository from Spring Data? In such implementations there are so many possible methods of fetching objects that duplicating them in Service isn't cool.
So what is the solution for that problem?
A. Duplicate methods in service layer like this
#Service
class XService{
#Autowired
private XRepository repository;
public List<X> findAll(){
return repository.findAll();
}
}
B. Simply using repository in controllers (autowired or access method in service)
C. Any other good approach?
Services should implement (business) logic and possibly modify entities according to that logic. If your service layer is only a thin wrapper around repositories, i.e. only fetching entities as your description suggests, something is wrong with your design.
Often logic is spread throughout the controllers. Identify that logic, extract and encapsulate it in services and restrict Controllers to manage the application's flow, by orchestrating the appropriate services.
I need some advice on designing an "Integration Tier" of an N-Tiered system in Java. This tier is responsible for persisting and retrieving data for the "Business Tier" (located on a separate server). I'm new to J2EE and I've read a few books and blogs. The alphabet soup of technology acronyms is confusing me so I have a handful of questions.
First, what I have so far: I'm using JPA (via Hibernate) for persisting and retrieving data to a database. I made my data access objects EJBs and plan on deploying to an application server (JBoss) which makes transactions easier (they're at the function level of my DAOs) and I don't have to worry about getting a handle to an EntityManager (dependency injection). Here's an example of what things look like:
#Entity
class A{
#Id
Long id;
#OneToMany
List<B> setOfBs = new ArrayList<B>;
}
#Entity
class B{
#Id
Long id;
}
#Remote
public interface ADAO{
public A getAById(Long id);
}
#Stateless
class ADAOImpl implements ADAO{
#PersistenceContext
EntityManager em;
public A getAById(Long id){ ... }
}
My question: How should the Business Tier exchange data with the Integration Tier. I've read up on RESTful services, and they seem simple enough. My concern is performance when the frequency of gets and sets increases (HTTP communication doesn't seem particularly fast). Another option is RMI. My DAOs are already EJBs. Could I just have the Business Tier access them directly (via JNDI)? If so, what happens if the #OneToMany link in the example above are lazily loaded?
For example if the Business Tier does something like the following:
Context context = new InitialContext(propertiesForIntegrationTierLookup);
ADAOImpl aDao = (ADAOImpl) context.lookup("something");
A myA = aDao.getAById(0);
int numberOfBs = myA.setOfBs.size();
If the setOfBs list is loaded lazily, when the Business Tier (on a separate server) accesses the list, is the size correct? Does the list somehow get loaded correctly through the magic of EJBs? If not (which I expect), what's the solution?
Sorry for the long post. Like I said I'm new to J2EE and I've read enough to get the general idea, but I need help on fitting the pieces together.
When you call size() on lazy collection, it gets initialized, so you'll always get correct size no matter which interface you're using - Remote or Local.
Another situation is when you're trying to use JPA classes as data transfer objects (DTO) and request them via Remote interface. I don't remember any lazy initialization issues here, cause prior to transmission all objects have to be serialized (with lazy collections initialized) on server side. As a result, the whole object graph is passed over network, which might cause serious cpu and network overheads. In addition, for deserialization to be possible, you will have to share JPA classes with remote app. And that's where and how 'EJB magic' ends :)
So, once remote calls are possible, I'd suggest to start thinking of data transfer strategy and non-JPA data transfer objects as additional data layer. In my case, I've annotated DTO classes for XML binding (JAXB) and reused them in web-services.
Short answer: If you are using an "Integration Layer" approach, the things you should be integrating should be loosely coupled services, following SOA principles.
This means you should not be allowing remote calls to methods on entities that could be making calls to the framework under the lid on another server. If you do this, you are really building a tightly coupled distributed application and you will have to worry about the lazy loading problems and the scope of the persistence context. If you want that, you might like to consider extended persistence contexts http://docs.jboss.org/ejb3/docs/tutorial/extended_pc/extended.html.
You have talked about a "business tier", but JPA does not provide a business tier. It provides entities and allows CRUD operations, but these are typically not business operations. a "RegisterUser" operation is not simply a question of persisting a "User" entity. Your DAO layer may offer a higher level of operation, but DAOs are typically used to put a thin layer over the database, but it is still very data centric.
A better approach is to define business service type operations and make those the services that you expose. You might want another layer on top of your DAO or you might want to have one layer (convert your DAO layer).
You business layer should call flush and handle any JPA exceptions and hide all of that from the caller.
The issue of how to transfer your data remains. In many cases the parameters of your business service requests will be similar to your JPA entities, but I think you will notice that often there are sufficient differences that you want to define new DTOs. For example, a "RegisterUser" business operation might update both the "User" and "EmailAddresses" table. The User table might include a "createdDate" property which is not part of the "RegisterUser" operation, but is set to the current date.
For creating DTOs, you might like to look at Project Lombok.
To copy the DTO to the Entity, you can use Apache Commons BeanUtils (e.g., PropertyUtils.copyProperties) to do a lot of the leg work, which works if the property names are the same.
Personally, I don't see the point in XML in this case, unless you want to totally decouple your implementations.