I have a web application using jdbc for database calls.
I have a service, dto and dao layer.
I have a request xml which is huge. Can I pass the request object to dao method or should I transfer the request to a dto model and then pass the dto object as a paramter to my dao method?
Which is the right approach??
public TestServiceClass addSurveySubmitDetails(TestRequestXML testRequestXML){
//call to dao method
TestDao = testdao = new TestDao(testRequestXML);
}
OR
public TestServiceClass addSurveySubmitDetails(TestRequestXML testRequestXML){
//create dto object
TestDTO testDTO = new TestDTO();
testDTO .setId(testRequestXML);
//call to dao method
TestDao = testdao = new TestDao(testDTO );
}
Which is the right approach??
I don't think there is a right or wrong answer. It's pretty subjective in my opinion.
But I personally like to have a thin layer between the controllers and the services (assuming you're using the MVC pattern), that its only task is to convert requests (XML, Json, etc) to domain objects.
It is quite useful when you have complex domain objects or aggregates of which you need to show information in a view.
It depends on your architecture, but as DTO is Data Transfer Object there's no reason to use them between service and dao layers.
You can have one for service layer I suppose like in code sample below, but anyway it depends on your application's architecture.
public TestServiceClass addSurveySubmitDetails(TestDTO testDTO){
TestRequestXML testRequestXML = testDTO.getId();
TestDao = testdao = new TestDao(testRequestXML);
}
More on DTO's
Data Transfer Object
LocalDTO
YAGNI is good idea, keep it simple design, where possible
DTOs are really intended for remote calls. If you're sending data over the network to a different virtual machine, use a DTO. If you're sending data to another local class on the same virtual machine, don't bother with a DTO. A DTO is just an efficient way to transfer data remotely. It doesn't really have any advantages anywhere else.
Related
Good day, I have a Spring Boot based backend , we are using own library to convert JPA entities to Dto's (library works based on reflection).
The problem is , we inject service layer directly to some mappers. Let's say I have a UserEntity and UserDto.
UserDto has a field called avatar and avatars are stored in S3.
So in order to build a UserDto we are using the code like this.
#Component
class UserMapper {
#Inject
S3Service s3Service;
public UserDto toDto(UserEntity entity){
UserDto dto = new UserDto();
BeanUtils.copy(entity,dto);
dto.setAvatar(s3Service.getAvatarByUser(entity));
}
}
I don't like this approach because Mapper mustn't know anything about Service layer . However this mapper is used by other mappers as well. In case I want to return an OrderDto, it has a nested UserDto so OrderDto calls UserMapper internally.
Are there any best practices for Mappers to be service free ?
So far I tried the following.
Store avatar in ThreadLocal cache. When controller calls a service to get a user, service will store user's avatar in the ThreadLocal, and then Mapper will get it from ThreadLocal cache. Disadvantage - it's hard to test it and requires me to make Mocks
Create a separate POJO called UserWithAvatar that stores UserEntity entity;String avatar and create a mapper for UserWithAvatar instead of UserEntity. Disadvantage - as I said this mapper will be used by OrderMapper and order mapper takes OrderEntity with nested UserEntity instead of UserWithAvatar
I think mapper should be inside of service but I will try working with ur requirements
u have 2 choices:
You inject both service and mapper to controller, get entity back to the controller and map it using mapper before returning response
Use event publishing to publish an event which mapper then catches and produces the mapping. After that you could either directly return the dto to controller or produce another event. (event publishing is by default synchroneous so you dont have to worry about concurrency issues)
Event publishing is done via spring and results in very uncoupled code where publisher doesnt know anything about event subscribers and hence these 2 can be in 2 seperate layers that wont know anything about each other
Easy to follow guide: https://www.baeldung.com/spring-events
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I have my own service calling a third party rest service that is returning a text based response.This text based response is not a proper service response and needs to be parsed for content as well as errors. For purposes of discussion, assume the 3rd party rest service cannot be changed.
Given these circumstance I am wondering whether I should wire that parsing into the dao layer or the service layer of my application.I know that the service layer should contain all of your business logic, but I feel like if I don't do the parsing in my Dao layer I am leaking. Is it ok to have logic in the dao for purposes of parsing/transformation in this case or should it be done in the service layer?
Any advice is appreciated.
public void MyDao {
private RestTemplate restTemplate;
private ResponseParser responseParser;
public myDao(RestTemplate restTemplate, ResponseParser responsePaser){
this.restTemplate = restTemplate;
this.responseParser = responseParser;
}
public MyResponse sendRequest(MyRequest myRequest){
ResponseEntity<String> responeEntity = restTemplate.exchange(...);
String body = responseEntity.getBody();
return responseParser.parse(body);
}
}
OR
public void MyDao {
private RestTemplate restTemplate;
public myDao(RestTemplate restTemplate, ResponseParser responsePaser){
this.restTemplate = restTemplate;
}
public String sendRequest(MyRequest myRequest){
ResponseEntity<String> responeEntity = restTemplate.exchange(...);
return responseEntity.getBody();
}
}
public void MyService {
private MyDao myDao;
private ResponseParser responseParser;
public myDao(MyDao myDao, ResponseParser responsePaser){
this.myDao = myDao;
this.responseParser = responseParser;
}
public MyObject process(MyRequest myRequest){
String response = myDao.sendRequest(myRequest)
return responseParser.parse(response);
}
}
Here are my take and opinion of the design.
DAO is a pattern to abstract the persistence operations and should be kept solely to work with persistence operations.
The DAO patterns help to abstract away persistence mechanism/operations or data access operations from a data-source from the client and the design follows SRP, making the transition to a new persistence type easy. And the change - change of your persistence mechanism/ data source, stays in the DAO layer not boiling up to service layers.
The service layer is responsible to handle and compute business operations on your data. It uses a DAO/Repository/Client to fetch the data it needs to operate on.
Taking into consideration the above points, here is what I think of the existing design and how I would do it.
DAO, as chrylis mentioned above, is a data access object and should not matter if the data is fetched from the DB or over HTTP.
The article from Oracle about J2EE pattern reads:
Use a Data Access Object (DAO) to abstract and encapsulate all access to the data source. The DAO manages the connection with the data source to obtain and store data.
It further reads: The data source could be a persistent store like an RDBMS, an external service like a B2B exchange, a repository like an LDAP database, or a business service accessed via CORBA Internet Inter-ORB Protocol (IIOP) or low-level sockets.
Taking these into consideration, I would make the call from DAO, parse the response and send over a business object to the Service.
Taking SRP into consideration, the Service should not be aware of the call made over HTTP/ db call made/ reading from a flat-file. All it should know is, once I make a query for the data, I get back an object with the required data from the DAO.
If Service is taking care of the parsing, what if the data source changes tomorrow and you have the data in-situ. So now you DAO changes because now it talks to the DB instead of making an HTTP request. You cannot return back a String representation anymore. You need a Data Mapper and will send some sort of Object representation back, which means your Service class changes too. So one change of data source, not only changes your code in DAO but boils to the business layer, which breaks the SRP.
Saying this, not developing for long and not from a software engineering background(I had the understanding that data access object can only be from datastore, but thanks to chrylis' comment made me read more and think about the difference between data-source and datastore), I always prefer naming it Client -> RestClient and make the call and keep my DB operations to DAO/Repo. The reason being, it is simply easy to read tomorrow. One look at the classname and it is easy to understand what it is doing or what sort of operation the class is possibly handling.
So, yes the call and parsing should happen in the DAO/Client.
Strictly speaking, Dao layer is used to manage information included in a persistence mechanism like: database, LDAP, etc So when you deal with an external endpoint, "include" that functionality in a service is an approach more widely used.
Answering your question, the first option is a better one.
You are including the required business logic into the class that knows the returned format/information by the external endpoint.
External classes that use the above one will manage a well know object (instead of a raw string value)
Some types of upgrades in the external endpoint (changes in the response format, for example) can be better managed in your Dao class, without affecting to the other classes that use it.
My opinion is put it in DAO layer. Because parsing isn’t a business feature. Also DAO layer is meant for accessing data from DBs or other third party entities. So having the data in right POJO format while returning from DAO layer makes good sense in my opinion.
I'm pretty new to the concept of patterns. I am practising my dependency injection skills as well as using DAO principles. The code I have written works but I feel that it can be written in a more elegant fashion. I've tried restructuring it a pattern I saw but that complicated things so not sure if I implemented it correctly. As a general rule when a web application communicates with a database and throws out result, how should one structure their project?
I've heard of the MVC principle but that doesn't necessarily add database to the mix.
This is what I have so far:
A class containing a controller in a Controller package:
#RestController
public class ResponseController {
#Autowired
MongoBase dbConnection;
#RequestMapping(value = "/jsonresult", method = RequestMethod.GET)
#ResponseBody
public String jsonresult(#RequestParam(value = "id", required = true) String id){
return dbConnection.documentToJSON(id, Constants.database,Constants.collection);
}
#RequestMapping(value = "/alljsonresult", method = RequestMethod.GET)
#ResponseBody
public String alljsonresult(){
return dbConnection.allDocumentToJSON(Constants.database,Constants.collection);
}}
A class containing CRUD methods to the database in a Database package:
#Component
public class MongoBase {
#Autowired
MongoClient mongoClient;
public MongoBase() {
try {
mongoClient = new MongoClient("localhost", 27017);
} catch (Exception e) {
e.printStackTrace();
}
}
public void printAllCollection(String databaseName, String collectionName) {
...
}
So is there a better way/more efficient way of writing thi? Also I feel I haven't fully implemented DI in the Monogbase class since it contains the new keyword..
If you are using springboot, then you don't need this old style
also don't need to create mongoClient bean your self, spring boot help you in it
You just need to add following properties in application.properties file
#mongodb
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=app1
Also declares a spring-boot-starter-data-mongodb in your pom or gradle
it's a cool and super awesome dependency for accessing Data with MongoDB
you can read about it from here[https://spring.io/guides/gs/accessing-data-mongodb/]
suppose you have a domain
#Document(collection = "domain")
public class User {
#Id
private long id;
#Indexed(unique = true)
private String domain;
private boolean displayAds;
//getters and setters
}
Now if we need to perform curd operation on this domain, extends MongoRepository, you have CRUD function automatically. Spring data come with many magic findBy queries, review the official Spring data MongoDB – Query methods for detail.
public interface UserRepository extends MongoRepository<User, Long> {
Domain findFirstByDomain(String domain);
Domain findByDomainAndDisplayAds(String domain, boolean displayAds);
//Supports native JSON query string
#Query("{domain:'?0'}")
Domain findCustomByDomain(String domain);
#Query("{domain: { $regex: ?0 } })")
List<Domain> findCustomByRegExDomain(String domain);
}
UserRepository extends the MongoRepository interface and plugs in the type of values and id it works with: User and Long. Out-of-the-box, this interface comes with many operations, including standard CRUD operations (create-read-update-delete).
now you can easly use it in your controller
#RestController
public class ResponseController {
#Autowired
UserRepository userRepository;
#RequestMapping(method = RequestMethod.POST)
#ResponseStatus(HttpStatus.CREATED)
User create(#RequestBody #Valid User user) {
return userRepository.create(user);
}
}
also you can do with it lot of things. you just need to go throw with it doc.
Also you you can use mongoTemplate for execute the query
#Autowired
MongoTemplate mongoTemplate;
When I build web applications I typically define the full chain as follows:
Client Side:
View - This is the V in MVC where you control visuals & user action derived workflow.
Controller - This is the C in MVC where workflow is managed. Most Client processing will go here and multiple Client calls can be made to get/send data or perform lookups.
Client - This is where you make a call to a REST web service and parse/deserialize the results/handle exceptions.
Server Side:
RestController (Sometimes Called Resource) - This is your REST API endpoint. Here you extract & validate a request.
Service - This is where most of your server logic will go. Sometimes you might have to make multiple data access calls or call other service functions.
DataAccessObject (Sometimes Called Provider) - This is your database interaction to pull data from your database into a model. CRUD operations (Create Read Update Delete)
Example Scenario:
Lets say we want to submit data & permissions for a given user
UserView.jsp - User types in user & permission data and hits submit.
UserController.java - validates User & permission data, does any necessary lookups, then calls UserClient.
UserClient.java - Builds the REST request and calls the /user/create REST endpoint.
UserRestController.java - Unpackages/Validates the request, then calls UserManagementService
UserManagementService.java - Server Logic happens here! Lets say I have two tables in my database. A User table and a Permissions table. I want to store the user information in the User table and the permission information in the permission table so I will call the UserDAO for the user data and the PermissionDAO for the permission data.
UserDAO & PermissionDAO - Saves The passed models to their respective tables.
Return to Service, Return to RestController, Return to Client (Parse Response), Return to Controller (Move the Workflow forward with a redirect or a success message).
Conclusion:
This may seem like a lot of in-between steps but this design provides a ton of flexibility, especially if your building large, complex web services. Each component has a specific purpose, follows an easy naming convention, and splits complex logic into smaller, simpler steps.
I'd like to recommend some improvements to your solution:
You're using Spring. You should not create any injected beans using new. Let Spring instantiate and manage those beans for you.
Use the #Repository annotation to mark your persistence class.
Make your repository class interface based.
Don't embed "Mongo" into the class name. You happen to be using Mongo as your persistence provider now, but you may change your mind later. Don't reveal implementation information in your class names - hide it.
The Controller is part of the UI. It uses repositories and/or services to fulfill use cases. It's perfectly correct to use Spring to inject the repository into the Controller.
I'd recommend that you use Spring Boot, an opinionated version of Spring. Have a look at their guides to learn how to use it properly.
I'm trying to refactor the existing code base of one of my project following Repository pattern, so that i can make the project more re-usable and testable.
I've written services, repositories, when I try to set Authentication, Authorization and Transactional annotation on service layer, I am facing issues.
These annotations works only on controller level, but not on service layer, so I want a way for annotate service methods.
Is it possible to do so?
It would be helpful, if someone points me samples using repository pattern on Play framework or better way to proceed further.
Authentication and authorization only make sense on a request, so sticking them on anything but a controller method is not going to work either way.
Transactional is just a helper annotation to wrap the entire request in a JPA transaction. It is usually advisable to do the wrapping yourself anyway, so you don't really need that. Example taken from the documentation:
#Inject
private JPAApi jpaApi;
public void updateSomething() {
// do something with the entity manager, per instance
// save, update or query model objects.
jpaApi.withTransaction(() -> {
EntityManager em = jpaApi.em();
Query query = em.createNativeQuery("update people set active = 1 where age > 18");
query.executeUpdate();
});
}
Lets assume a simple Spring MVC Controller that receives the ID of a domain object. The Controller should call a service that should do something with that domain object.
Where do you "convert" the ID of the domain object into the domain object by loading it from the database? This should not be done by the Controller. So the service method interface has to use accept the ID of the domain object instead of the domain object itself. But the interface of the service would be nicer if it takes the domain object as a parameter.
What are your thoughts about this common use case? How do you solve this?
The controller should pass the id down into the service layer and then get back whatever is needed to render the rest of the HTTP response.
So -
Map<String,Object> doGet (#RequestParam("id") int id) {
return serviceLayer.getStuffByDomainObjectId(id);
}
Anything else is just going to be polluting the web layer, which shouldn't care at all about persistence. The entire purpose of the service layer is to get domain objects and tell them to perform their business logic. So, a database call should reside in the service layer as such -
public Map<String,Object> getStuffByDomainObjectId(int id) {
DomainObject domainObject = dao.getDomainObjectById(id);
domainObject.businessLogicMethod();
return domainObject.map();
}
in a project of mine I used the service layer:
class ProductService {
void removeById(long id);
}
I think this would depend on whether the service is remote or local. As a rule I try to pass IDs where possible to remote services but prefer objects for local ones.
The reasoning behind this is that it reduces network traffic by only sending what is absolutely necessary to remote services and prevents multiple calls to DAOs for local services (although with Hibernate caching this might be a mute point for local services).