What methods the DAO layer should implement? - java

I'm being writing web application right now and got stuck at the stage of designing the DAO layer. Already have surfed through variaty of articles on that subject but still haven't reached the clarity.
And my question is:
What kind of methods are allowed to be declared and implemented in DAO classes?
Are they just limited set of CRUD operations (create, read, update, delete)? Is it considered a good practice to extend this set with some custom methods fitting in your concrete needs in developing a business logic layer?
For example:
I have an entity class named User which fields fully reflect a corresponding database table. Let's suppose I'm about to validate user's login and password while authorization. What approach would be more appropriate in that situation? Should I call generic CRUD method List<User> findAll() to retrieve all users and validate these concrete login and password in method of business logic (something like boolean validateUser(String login, String password, List<User> users)). Or should I add some not CRUD method like boolean checkUser(String login, String password) directly in DAO class?

I'm being writing web application right now and got stuck at the stage of designing the DAO layer.
Are you writing it by hand using plain old servlets or using a web framework (e.g Spring MVC) to ease your pain?
And my question is: What kind of methods are allowed to be declared and implemented in DAO classes? Are they just limited set of CRUD operations (create, read, update, delete)?**
Generally speaking, yes -- the methods should be limited to CRUD operations.
Is it considered a good practice to extend this set with some custom methods fitting in your concrete needs in developing a business logic layer?**
Within reason, yes.
For example: I have an entity class named User which fields are fully reflect a corresponding database table. Let's suppose I'm about to validate user's login and password while authorization. What approach would be more appropriate in that situation? Should I call generic CRUD method List findAll() to retrieve all users and validate these concrete login and password in method of business logic (something like boolean validateUser(String login, String password, List users)). Or should I add some not CRUD method like boolean checkUser(String login, String password) directly in DAO class?
In addition to the standard CRUD methods that your DAO classes are expected to have, you can add a helper method like:
User findUser(String login) whose job is to return a populated User object for the specified login parameter, or null if the login is non-existent.
User findUser(String login) should leverage List<User> findAll() which should already exist with the rest of the CRUD methods in the DAO class. It could be implemented as follows:
public User findUser(String login) {
User user = null;
final SearchCriteria criteria = buildSearchCriteria(login); // construct a search criteria from the login parameter
List<User> users = findAll(criteria);
if (null != users) {
assert (users.size() == 1) : "More than one user was matched - login must be unique.";
user = users.get(0);
}
return user;
}
To summarize, you only need 2 methods to implement the authorization logic:
User findUser(String login) in your DAO layer and;
boolean checkUser(String login, String password) which will be in your frontend layer. If you are not using any web framework, this method will be implemented in your servlet otherwise this method will go inside your controller class (if you are using an MVC framework).

short answer is no: dont add any business logic in dao layer. Just let every tier has its own responsibility, so when someone else (or even you) needs changes they will know where to look.
EDIT:
Other answers:
Q:What kind of methods are allowed to be declared and implemented in DAO classes?
A:Methods that allow you to access database objects or their properties. i.e. public User getOldUsers(), public boolean isUserExist(Long userId)etc...
Q:Are they just limited set of CRUD operations (create, read, update, delete)?
A:Yes additionally you can control persistence or transaction properties
Q:Generic CRUDS?
A:Almost all the projects I work on we use generic CRUDS (AbstractDao classes) and add additional methods

Related

Should duplicate values in aggregate roots be checked in the domain layer or the application layer?

I am new to DDD, and I have ran into a problem with unique constraints. I have a problem where one of the fields (a value object) on my aggregate root cannot be a duplicate value. For example, a user has a unique username.
My domain layer contains:
public class User {
private UUID id;
private Username username;
private User(UUID id, Username username) {
this.id = id;
this.username = username;
}
public void rename(Username username) {
if (!username.equals(username)) {
this.username = username;
EventBus.raise(new UserRenamedEvent(username));
}
}
public UUID getId() {
return id;
}
public Username getUsername() {
return username;
}
public static User create(UUID id, Username username) {
User user = new User(id, username);
EventBus.raise(new UserCreatedEvent(user));
return user;
}
}
Username:
public record Username(String name) {
// Validation on username
}
As well as a simple CRUD repository interface, implemented in the infrastructure layer.
My application layer contains:
UserSerivce:
public interface UserService {
UUID createUser(Username username);
// Get, update and delete functions...
}
And UserServiceImpl:
public class UserServiceImpl implements UserService {
public UUID createUser(Username username) {
// Repository returns an Optional<User>
if (userRepository.findByName(username).isPresent()) {
throw new DuplicateUsernameException();
}
User user = User.create(UUID.randomUUID(), username);
repsitory.save(user);
return user.getId();
}
}
This solution doesn't feel right, as preventing duplicate usernames is domain logic, and should not be in the application layer. I have also tried creating a domain service to check for duplicate usernames, but this also feels wrong as the application service has access to the repository and can do this by itself.
If the user was part of an aggregate I would do the validation at the aggregate root level, but as user is the aggregate this isn't possible. I would really like to know the best place to validate the unique constraint.
EDIT: I decided to take VoiceOfUnreasons advice and not worry about it too much. I put the logic to check for duplicates in the application service, as it makes for readable code and works as expected.
This solution doesn't feel right, as preventing duplicate usernames is domain logic, and should not be in the application layer.
There are at least two common answers.
One is to accept that "domain layer" vs "application layer" is a somewhat artificial distinction, and to not get too hung up on where the branching logic happens. We're trying to ship code that meets a business need; we don't get bonus points for style.
Another approach is to separate the act of retrieving some information from the act of deciding what to do with it.
Consider:
public UUID createUser(Username username) {
return createUser(
UUID.randomUUID(),
username,
userRepository.findByName(username).isPresent()
);
}
UUID createUser(UUID userId, Username username, boolean isPresent) {
if (isPresent) {
throw new DuplicateUsernameException();
}
User user = User.create(userId, username);
repository.save(user);
return user.getId();
}
What I'm hoping to make clear here is that we actually have two different kinds of problems to address. The first is that we'd like to separate the I/O side effects from the logic. The second is that our logic has two different outcomes, and those outcomes are mapped to different side effects.
// warning: pseudo code ahead
select User.create(userId, username, isPresent)
case User(u):
repository.save(u)
return u.getId()
case Duplicate:
throw new DuplicateUsernameException()
In effect, User::create isn't returning User, but rather some sort of Result that is an abstraction of all of the different possible outcomes of the create operation. We want the semantics of a process, rather than a factory.
So we probably wouldn't use the spelling User::create, but instead something like CreateUser::run or CreateUser::result.
There are lots of ways you might actually perform the implementation; you could return a discriminated union from the domain code, and then have some flavor of switch statement in the application code, or you could return an interface, with different implementations depending on the result of the domain logic, or....
It largely depends on how important it is that the domain layer is "pure", how much additional complexity you are willing to take on to get it, including how you feel about testing the designs, which idioms your development team is comfortable with, and so on.
It should be noted that one can reasonably argue that the definition of "unique" itself belongs in the domain, rather than in the application.
In that case, the design is mostly the same, except that instead of passing "the answer" to the domain code, we pass the capability of asking the question.
select User.create(
userId,
username,
SomeServiceWrapperAround(
userRepository::findByName
))
Or we define a protocol, where the domain code returns representations of questions, and the application code does the I/O and passes representations of the answers back to the domain model.
(and, in my experience, begin questioning whether all this ceremony is actually making the design "better")
This solution doesn't feel right, as preventing duplicate usernames is
domain logic, and should not be in the application layer.
Correct.
I have also tried creating a domain service to check for duplicate
usernames, but this also feels wrong as the application service has
access to the repository and can do this by itself.
Yes, the application service could do the work by itself, but you have taken a conscious decision to create a dedicated layer for those 'tricky' bits where the domain aggregate cannot do the work on its own and you do not want to leak domain knowledge into the application service.
There's nothing wrong with this. Just don't let 'Domain Service' become a your default approach whenever something looks a bit tricky. You'll end up with an anaemic domain model and all the logic sitting in Domain Services. But, sometimes, a Domain Service is the only pragmatic solution and feel free to use them when all else fails.
The other alternative is to search up "Domain Events". They keep a better separation in my view but demands more effort and plumbing.
Here's a C# introduction, but just as applicable to the world of java.
https://learn.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/domain-events-design-implementation

Spring And Hibernate - generic entity updates

I have a very simple task,
I have a "User" Entity.
This user has tons of fields, for example :
firstName
age
country
.....
My goal is to expose a simple controller for update:
#RequestMapping(value = "/mywebapp/updateUser")
public void updateUser(data)
I would like clients to call my controller with updates that might include one or more fields to be updated.
What are the best practices to implement such method?
One naive solution will be to send from the client the whole entity, and in the server just override all fields, but that seems very inefficient.
another naive and bad solution might be the following:
#Transactional
#RequestMapping(value = "/mywebapp/updateUser")
public void updateUser(int userId, String[] fieldNames, String[] values) {
User user = this.userDao.findById(userId);
for (int i=0 ; i < fieldsNames.length ; i++) {
String fieldName = fieldsName[i];
switch(fieldName) {
case fieldName.equals("age") {
user.setAge(values[i]);
}
case fieldName.equals("firstName") {
user.setFirstName(values[i]);
}
....
}
}
}
Obviously these solutions aren't serious, there must be a more robust\generic way of doing that (reflection maybe).
Any ideas?
I once did this genetically using Jackson. It has a very convenient ObjectMapper.readerForUpdating(Object) method that can read values from a JsonNode/Tree onto an existing object.
The controller/service
#PATCH
#Transactional
public DomainObject partialUpdate (Long id, JsonNode data) {
DomainObject o = repository.get(id);
return objectMapper.readerForUpdating(o).readValue(data);
}
That was it. We used Jersey to expose the services as REST Web services, hence the #PATCH annotation.
As to whether this is a controller or a service: it handles raw transfer data (the JsonNode), but to work efficiently it needs to be transactional (Changes made by the reader are flushed to the database when the transaction commits. Reading the object in the same transaction allows hibernate to dynamically update only the changed fields).
If your User entity doesn't contains any security fields like login or password, you can simply use it as model attribute. In this case all fields will be updated automatically from the form inputs, those fields that are not supose to be updated, like id should be hidden fields on the form.
If you don't want to expose all your entity propeties to the presentation layer you can use pojo aka command to mapp all needed fields from user entity
BWT It is really bad practice to make your controller methods transactional. You should separate your application layers. You need to have service. This is the layer where #Transactional annotation belongs to. You do all the logic there before crud operations.

Difference between Repository and Service layer

I looked through some related questions but still I don't see much difference between the a repository and a service layer. So given the example I suppose it should look like this , if not please tell me why?
public interface ProductRepository extends CrudRepository<Product, Long>{
public List<Product> findByName(String name);
public List<Product> findByPrice(Double price);
}
public interface ProductService {
public List<Product> findAll();
public Product findById(Long id);
public Product save(Product product);
public void delete(Product product);
public List<Product> findByName(String name);
public List<Product> findByPrice(Double price);
}
and the implementation of the ProductService would use the ProductRepository to implement the methods. As I understand from http://docs.spring.io/spring-data/jpa/docs/1.3.0.RELEASE/reference/html/jpa.repositories.html the queries for methods from the repository are auto generated. In my example the methods are repeated in the repository and Service, so please explain what/why needs to be changed?
All your business logic should be in the Service Layer.
Any access to the Database (any storage) should go to the Repository Layer.
Lets take an Example. You have to save an entity(Person). But before saving the Person you want to make sure that the Person's FirstName does not exist already.
So the validation part should go to the business layer.
In the service Layer
PersonRepository repository;
public Person save(Person p){
Person p = findByName(p.getName();
if (p != null){
return some customException();
}
return repository.save(p);
}
public Person findByName(String name){
return repository.findByName(name);
}
And in your Repository Layer just concentrate on DB Operation.
You could have done this in Repository Layer it self. Assume you have implemented this in your Repository then your save method always check before saving (some time you may not required to do).
Repository Layer gives you additional level of abstraction over data access. Repository layer exposes basic CRUD operations.
Service layer exposes business logic, which uses repository.
You can read a more detailed answer here:
https://stackoverflow.com/a/5049454/1446006
A Repository is a data access pattern in which data transfer objects are passed into a repository object that manages CRUD operations. This pattern is useful in situations where the mechanism of your data access may change significantly -- e.g. you expect to have varying data stores like Oracle in one implementation and SQL Server or even HADOOP in another.
A Service Layer is a business logic pattern that is commonly used in SaaS architectures. Using a service layer allows one or more presentation implementations to access your business logic through a common interface. For example if you wanted your website to have an API you would use a service layer to implement common back-end functionality that both the site and the API would consume.
The former should be concerned mostly with data access and the latter with business logic. Neither are mandatory nor must one accompany the other. In simple applications both patterns may be implemented by the same class.
As far as I know, the Repository is meant for directly accessing the database. This is where direct calls to the stored procedures or whatever your data storage mechanism is will be.
The service layer is the API to your data. There is usually some logic level that you would do hear, or in another layer of abstraction between the service and the repository.
For example, a website would call a method in your service. Your service would call your repository for getting that data, then your service would transform it somehow (build objects, generate dynamic information based on business rules, etc.) then pass that back up to the website.
It seems that you are using Spring Data in this case where repositories act as DAOs (they define the available database operations and the implementation of these methods is generated by the framework). The service layer should be on top of the repositories, i.e. it accesses data through repositories.
Other answers have not pointed out that you might not need a Service layer: if your implementation is as simple as it seems (only passing entities to the controller without any processing) then a Service layer may be an unnecessary level of abstraction in your application. You should only create a Service layer when it has some purpose.
Simply ,I will give a practical example ..
like if you have 2 sources of the data , one from local db and the other from a web api for instance.
So , the repository should manage that for you , asking for the lacal data ( are you exist ? tes get it from its service, and if Not service please get data from the api …
So we will have 2 services ( water streams ) that get the data to the pool ( repository) .

Better approach for DTOs?

I am developing a simple forum web application using SpringMVC, JPA2.
I have created JPA entities like User, Forum, Post etc which reflects the DB table structure.
But while displaying the data on UI I need DTOs as I can't always hold the data to be displayed on UI using Entities.
For ex: Change Password screen. Here I need to hold Old Pwd, New Password and Confirm New Pwd. But User entity won't have Old/New/Confirm Pwd fields, it just has Password. So I need to create DTOs which are just data carriers between Web and service layers.
My question is while creating DTO objects, should I put all the properties in DTO itself or wrap the Entity in DTO and add additional properties needed?
Ex: For Edit User Screen,
public class UserDTO
{
private User user; // User is a JPA entity
// setters & getters
}
With this I can pass the underlying User entity to my service layer. But while binding UI properties to DTO I need to associate PropertyEditors.
(or)
public class UserDTO
{
private String userId;
private String userName;
private String password;
// setters & getters
}
With this approach, I need to convert & copy the DTO properties into JPA entities and pass to Service layer.
Which approach is better? Or is there any other approach without DTOs altogether?
Your first approach still carries the Entity object itself to the presentation layer. If you have additional parameters that are not coming from the database, and your persistence context is still available, then this approach is sufficient.
The second approach requires duplication of code, which is not ideal.
If the persistence context is not available, I would suggest detaching the Entity from the persistence context using EntityManager.detach(), rather than creating a parallel hierarchy of beans.
On the other hand, if data is coming in from the presentation layer, you will need to load the Entity from the database (using find() or something similar) and update it, or merge() it into the persistence context.

Submitting / binding partial objects with spring mvc

The Spring MVC binding mechanism is powerful, but I'm now confronted with a trivial issue that I wonder how to resolve:
User JPA entity, that is used for the binding and validation as well (i.e. throughout all layers)
"Edit profile" page, that is not supposed to change the password or some other entity properties
Two ways that I can think of:
Using the same object
use #InitBinder to configure a list of disallowed properties
obtain the target user (by id)
then use a reflection utility (BeanUtils) to copy the submitted object to the target object, but ignore null values - i.e. fields that are not submitted
Introduce a new object that has the needed subset of fields, and use BeanUtils.copyProperties(..) to merge it to the entity.
Alternatives?
I've found that as soon as your web model starts to diverge from your business layer in function, it's best to use a view layer object (a model object) to collect, or display the data
the entity:
public class com.myapp.domain.UserEntity {
}
the model object:
public class com.myapp.somesite.web.SomeSiteUserModel {
public static SomeSiteUserModel from(UserEntity userEntity) {
... initialize model ...
}
public UserEntity getModelObject() {
... get entity back ...
}
}
now all view based operations can hand off processing to the internal model object if that makes sense, otherwise it can customize them itself. Of course the problem with this is you have to re-write all the getters and setters you want for the entity (an issue that I've had to deal with, that is annoying) unfortunately that is a bit of a Java language issue
I just checked up with two of the last Spring projects I have worked on and in both places the following approach is taken:
In the JSP page for the form the change password field has a name that does not match the name of the password field in the User bean, so that it doesn't get mapped to the bean. Then in the onSubmit method there is a separate check whether a new password has been submitted, and if it has been, the change is reflected explicitly.
Поздрави,
Vassil
You can read the object from the database first and bind then the request. You can find an example at FuWeSta-Sample.
It uses a helper-bean which must be initialized by Spring.

Categories