I have a Java server application with a ton of different entities. So far, each entity top level entity has its own CRUD service. By top level, I mean the root of a tree of entities that can stand alone.
Now I am getting into the heart of my Flex client and find I am needing/writing many different queries. But where best to put these queries?
Say for example, I have a query to find all "foos" based on their associate with a certain "bar". Currently that query is on the "foo" service (findAllByBar), but I am finding that it would be very convenient to have it (also?) in the "bar" service (findFoos). On the other hand, I could also create a query service and lump all the queries in there.
Whats a good practice to do here?
Try to layer your application in these perspectives:
Domain: design your class as entities like "Customer", value objects like "Address" or "Color", and aggregate roots (like "Order" which includes a list of "LineItem")
Repositories: these are the data access for the entities, create a repository for each aggregat root (CustomerRepository, OrderRepository, ...)
Services: create a coarse grained services spitted by logical business abstractions or bounded context not by entities, it is not logical to create a service for order and a service for items and a service for customers when all these entities are representing one atomic business value of order processing, then your service will use all required repositories to handle the data access.
example:
public class OrderRepository {
public Foo getById(int id) {
//
}
public Foo getByCustomer(Customer customer) {
//
}
}
public class CustomerRepository {
public Foo getById(int id) {
//
}
public Foo getByUserName(string userName) {
//
}
}
public class TradingService {
private OrderRepository _orderRepository;
private CustomerRepository _customerRepository;
public TradingService(OrderRepositoryInterface orderRep, CustomerRepositoryInterface cusRep) {
_orderRepository = orderRep;
_customerRepository = custRep;
}
public void placeOrder(string customerUserName, Order order) {
Customer customer = _customerRepository.getByUserName(customerUserName);
order.setCustomer(customer);
_orderRepository.add(order);
// ....
}
}
I would put queries in their respective classes instead of creating one (bloatable)query service
Related
In which layer should DTO/Entity conversion take place.
Having following structure in a Spring Mvc application:
Controller
Service
Repository
The approach I'm using now, where service layer is #Transactional.
#RestController
public class ExampleController {
#Autowired
private ExampleService exampleService;
#Autowired
private ExampleMapper exampleMapper;
#GetMapping("/examples")
public ResponseEntity<List<ExamleDto>> getAll() {
var examples = exampleService.getAll();
return ResponseEntity.ok(exampleMapper.examplesToExampleDtos(examples));
}
#PostMapping("/examples")
public ResponseEntity<Void> create(#RequestBody #Valid ExampleCreateDto createDto) {
var example = exampleService.create(createDto)
return ResponseEntity.created(URI.create("examples/" + example.getId()).build();
}
// PUT, DELETE, ...
}
#Service
#Transactional
public class ExampleService {
#Autowired
private ExampleRepository exampleRepository;
#Autowired
private ExampleMapper exampleMapper;
public List<Examle> getAll() {
var examples = exampleRepository.findAll();
return examples;
}
public void create(ExampleDto exampleDto) {
var example = exampleMapper.asExample(exampleDto);
return exampleRepository.save(example);
}
}
public interface ExampleRepository extends JpaRepository<Example, Long> {
Why I choose this aproach:
The service layer is transactional, so whenever we get back to the controller, all changes will be flushed (version field for example) will all be set.
It makes you think about your entitygraph, lets say you have a Person entity which has a list of Deparments. Lets say the PersonDto contains also the list of DeparmentDtos, it forces you to fetch all deparments before hand or you will run into a LazyInitializationException in the controller layer.
Which in my opinion is a good thing, because if you would perform the mapping in the service you would be doing N + 1 queries (N being the number of deparments) without realizing it.
Services who need each other to perform there business tasks, work on the entity model instead of the DTO model, which might have some validation (#NotNull, #Size, ...) which only supposed to be valided when it comes from the outside, but internally not all validations should be applied.
Business rules will still be checked in the service layer as part of the service method.
The only thing here is that for update/creates service still communicate by passing dtos iso of entities.
I googled this topic a lot, but couldn't find a definitive answer.
Below I present flow of data from a use form to persistence layer. But have doubts about which objects should be available in which layer of MVC and how data should be transfered between different layers of MVC. I am working with Spring so the code posted below is that of Spring framework.
Here we go, I have a DTO(Data transfer object) PatientForm, which holds form data entered by user.
public class Patient {
private int id;
private String name;
private String medicineOne;
private String medicineTwo;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMedicineOne() {
return medicineOne;
}
public void setMedicineOne(String medicineOne) {
this.medicineOne = medicineOne;
}
public String getMedicineTwo() {
return medicineTwo;
}
public void setMedicineTwo(String medicineTwo) {
this.medicineTwo = medicineTwo;
}
}
PatientForm is passed on to a controller PatientController, does not transfer data but passes the form to the service layer PatientService.
#PostMapping("/patient/addpatient")
public ModelAndView addPatient(#ModelAttribute("patientform") PatientForm patient){
patientService.addPatient(patient);
return new ModelAndView("redirect:/");
}
In service layer PatientService actual transfer of data from DTO to Pesistent Entity Patient takes place.
public void addPatient(com.hp.view.form.PatientForm patientForm){
String medicineOneName = patientForm.getMedicineOne();
Medicine medicineOne = medicineService.findByName(medicineOneName);
if(medicineOne == null){
medicineService.save(new Medicine(medicineOneName));
medicineOne = medicineService.findByName(medicineOneName);
}
String medicineTwoName = patientForm.getMedicineTwo();
Medicine medicineTwo = medicineService.findByName(medicineTwoName);
if(medicineTwo == null){
medicineService.save(new Medicine(medicineTwoName));
medicineTwo = medicineService.findByName(medicineTwoName);
}
List<Medicine> medicines = new ArrayList<>();
medicines.add(medicineOne);
medicines.add(medicineTwo);
Patient patient = new Patient();
patient.setName(patientForm.getName());
patient.setMedicine(medicines);
patientRepository.save(patient);
}
Here are my questions as per the flow above:
Should Controller layer or Service layer transfer data from DTO to Persistent Entity?
If data transfer is done in controller means model entity will be declared in controller layer. And if data transfer is done in service layer means DTO will be declared in service layer. Which of the two is prefered?
In my service layer I have instantiated instance of my entity object Patient. Will this create problem and I should let Spring contianer manage my entity beans?
Patient patient = new Patient();
(1) Should Controller layer or Service layer transfer data from DTO to
Persistent Entity?
FormBeans are client/channel/endpoint specific, so the Controller layer should do the client specific validations (like min length, max length, etc..) and then convert FormBean's data to Entity Bean which will be passed it to the Service layer.
In the 3 tier architecture, Service layer should be reusable (explained below) which should NOT be aware of FormBeans, therefore receives entity object and should be responsible for processing the business logic (performing business validations and core logic plus interacting with DAO/Repository classes).
(2) If data transfer is done in controller means model entity will be
declared in controller layer. And if data transfer is done in service
layer means DTO will be declared in service layer. Which of the two is
prefered?
A single service can be reused/exposed to connect with multiple end points like a Controller or a different web service and each end point might require different formbeans, so Controller (end point) layer is preferred to handle end point specific validations and then create/pass the correct entity object to the service.
(3) In my service layer I have instantiated instance of my entity
object Patient. Will this create problem and I should let Spring
container manage my entity beans?
No problem. As entity objects are NOT singletons, you can create them inside your service like how you did. But if you are allowing Spring to manage them, you need to ensure that they are created one instance per each input request. This is because Spring bean's default scope is singleton, which needs to be changed to request scope.
Actually, I would go with totally different approach. DTO's could be potentially bound for specific web application framework. That would decrease reusability of services. Instead, you can create something like "DTO to entity converter". A simple interface that could look like this:
public interface DtoToEntityConverter<T, R> {
R getEntity(T t);
}
And then you could define concrete class like (or even use lambdas in simpler cases):
#Component
public class PatientFormConverter implements DtoToEntityConverter<PatientForm, Patient> {
public Patient getEntity(PatientForm form) {
// Conversion rules and stuff...
}
}
Then, just inject that component to controller and invoke getEntity upon adding of patient:
addPatient(patientFormConverter.getEntity(patientForm));
In spring you let application context to manage your beans (i e. You don't initialize your class) and then you can autowire (include them in other classes) without explicitly initializing them.
1) Service layers are used as an intermediary between your controller and model. That is, you autowire your service into your rest controller.
2 and 3rd answer is explained above.
P.S.: here autowire means dependency injection - .http://www.javatpoint.com/dependency-injection-in-spring
I'm trying to create a good OOP design especially conforming to SRP for interfacing with a database to insert and delete Customers. My focus is on design rather than getting bogged down by details of SQL and JDBC or datasources. So I've left simple implementations using printlines. But I'm wondering if this is how springs jdbctemplate is designed..
This effort came about while I was learning about the SRP OOP design principle. A poorly designed Customer class violated SRP since it contained database insert/delete responsibility. I pulled out code from Customer class and put it into a class that inherits from an RdbmsManager base class who's responsibility is to establish connections and interact with the database. I'm not sure about weather this is a good design, and I'm also not sure if some database API object similar to jdbcTemplate or something needs to be provided to child classes to interact with the database.
Customer class
public class Customer {
private int id;
private String fullName;
private boolean active;
public Customer(int id, String name, boolean active){
this.id = id;
this.fullName = name;
this.active = active;
}
#Override
public String toString() {
return "Customer [id=" + id + ", name=" + name + ", active=" + active
+ "]";
}
}
The parent database access class:
public class RdbmsManager{
public RdbmsManager(){
connectToDatabase();
}
private void connectToDatabase(){
// read from properties files to get DB URL, PORT number etc.
// Create Datasource object and establish connection to database
System.out.println("Established Database Connection...");
}
// Below method returns the database object children can use to issue commands
protected DatabaseAPI getDatabaseObject(){
DatabaseAPI databaseObject = new DatabaseAPI ();
return databaseObject;
}
}
CustomerDataManager child class:
public class CustomerDataManager extends RdbmsManager{
public CustomerDataManager() {
super(); // call to super will establish database connection from parent class
}
public void saveCustomerToDatabase(Customer Customer) {
getDatabaseAPI().insert(Customer);
}
public void deleteCustomerFromDatabase(Customer Customer) {
getDatabaseAPI().delete(Customer);
}
}
Simple implementation for the database interaction object to focus on design:
public class DatabaseAPI{
protected void insert(Object object){
System.out.println("inserted the into the database: "+ object.toString());
}
protected void delete(Object object){
System.out.println("Deleted object from database" + object.toString());
}
}
Well, you're pretty close to what is one of the standard designs to working with databases.
The main difference is in the name of the classes (e.g. DAO instead of Manager), and that you are extending the DB connection pool manager in order to create the DAOs.
Let me elaborate a little bit:
The database should be separated by abstraction from your application. In order to achieve this, you usually create what's known as a data abstraction layer on top of the database. This is a little bit similar to your RdbmsManager class, and its point is to abstract away the actual DB used. In order to achieve this, you normally have a database access interface of some kind which will be implemented by some class controlling all connections to the DB (try to avoid names containing 'Manager' since it doesn't really help clarify what those classes do). If later on you decide to change the DB you're using, all you need to do is create a new implementation to the interface that supports the new DB, and you're pretty much done !
Access to the actual data in the database should also be abstracted by another layer, usually called data access layer. This layer contains interfaces that encapsulate all access to specific type of data (per table usually), and enable CRUD operations to be performed on them. Those interfaces are generally named SomethingDAO where 'Something' stands for the type of object being accessed (the 'DAO' part stands for: 'Data Access Object'). Again, the implementations of those interfaces should be DB specific and be changed when you replace the DB you use with another.
The data should be transferred to the client code (usually the business/application layer) using some other method, usually DTOs (stands for 'Data Transfer Object'). These are (again) interfaces which expose some functionality required from the objects being represented in the DB, which should be implemented by DB specific (or generic, it depends) classes.
This is the theory in short. There are many data sources online (not to mention books) that will allow you to read much more about it.
On a different note, this is just one way to implement DB connectivity. There are numerous others, since there are a lot of design patterns that refer to enterprise applications in general, and to inter-tier communications in particular. Let me refer you to what I consider the best source for those design patterns: Patterns of Enterprise Application Architecture
Edit 1:
Here's a really simplistic code example (untested of course - treat as pseudo code):
public interface Customer { ... }
public interface CustomerDTO implements Iterable<Customer> { ... }
public class CustomerDTOSQLImpl {
public CustomerDTOSQLImpl(ResultSet resultSet) { ... }
#Override
public Iterator<Customer> iterator() { ... }
...
}
public interface CustomerDAO {
public CustomerDTO findById(int id);
...
}
public class CustomerDAOSQLImpl {
#Inject
private Connection connection;
#Override
public CustomerDTO findById(int id) {
PreparedStatement statement = connection.prepareStatement("SELECT * FROM CUSTOMER WHERE ID = ?");
statement.setInt(1, id);
return new CustomerDTOSQLImpl(statement.executeQuery());
}
...
}
I am currently developing a web application using Struts2 with Spring plugin and hibernate and while I was looking at online examples I saw the use of Service and DAO layers now it came to me what are the real use of Service and data access object layers? If The Service layer is just calling the methods of DAO layers to perform CRUD operations. wouldn't be sensible to just call the DAO layers methods directly?
Let's say this example of Dao and Service Layer
PeopleService
#Transactional
public class PeopleService {
private PeopleDao pDao;
public PeopleDao getPDao() { return pDao; }
public void setPDao(PeopleDao peopleDao) { this.pDao = peopleDao; }
public void createPerson(String name){
pDao.createPerson(name);
}
public List<Person> getPeople(){
return pDao.getPeople();
}
}
PeopleDao
public class PeopleDao {
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public Session sess() {
return sessionFactory.getCurrentSession();
}
public Person getPersonById(long id) {
return (Person) sess().load(Person.class, id);
}
public void deletePersonById(long id) {
sess().delete(getPersonById(id));
}
public void createPerson(String name) {
Person p = new Person();
p.setName(name);
sess().save(p);
}
#SuppressWarnings("unchecked")
public List<Person> getPeople() {
return sess().createQuery("from Person").list();
}
}
My question is what is the real use of Service layers if they are only being injected by their representative DAO and then calling its method?
It is a good idea to have those two layers when your business logic is more complex than your data logic. The service layer implements the business logic. In most cases, this layer has to perform more operations than just calling a method from a DAO object. And if you're thinking of making your application bigger, this is probably the best solution.
Imagine you want to include a City entity and create a relationship between People and City. Here is an example:
#Transactional
public class PeopleService {
....
private PeopleDAO pDAO;
private CityDAO cDAO;
...
public void createPerson(String name, String city)
throws PeopleServiceException {
Person p = new Person();
p.setName(name);
City c = cDAO.getCityByName(city);
if (c == null) throw new ServiceException(city + " doesn't exist!");
if (c.isFull()) throw new ServiceException(city + " is full!");
c.addPeople(p);
sess().save(p);
sess().save(c);
}
...
}
In this example, you can implement more complex validations, like checking the consistency of the data. And PersonDAO has not been modified.
Another example:
DAO and Service layers with Spring
Definition of Service layer pattern
If your application will grow with new and changing requirements you are very well served with having distinct layers for those TWO DISTINCT ASPECTS (persistence->DAO, business use case -> services) of your software.
One aspect is your persistence model with its relations, validations, transactions and many access patterns.
The services are driven by the business use cases which have a very different granularity. In the beginning you may have very simple services which don't do much more than calling DAOs to hand over data they received from, let's say, a web page. But this is likely to change over time and services will grow into small networks of collaborating objects that do a lot more to serve the business use case. If you don't use DAOs then
your services will contain code that deals with querying objects, transaction handling, validation, all of which has nothing to do with real business requirements
service code will look messy and it will be difficult to find out what parts of the code are actually business related
if you then change the persistence model you might end up changing many services
Also you can not easily unit test your persistence model but write tests only on the service layer. Do not forget that decoupling and encapsulation are important techniques to minimize the impact of change.
When done right, having a DAO layer will not introduce much implementation overhead so there is not much extra cost in having it. It will soon pay off and you will be very glad to have this dedicated layer.
Check out this article: http://codeblock.engio.net/?p=180. It also comes with a full implementation hosted on github
Can any one say to me that can I return Hibernate Entities as return value in JAXWS web service methods!?
Indeed I have some Entities like these:
#Entity
public class Parent {
...
private Childone childoneByChildoneid;
#ManyToOne
public
#javax.persistence.JoinColumn(name="ChildOneId",referencedColumnName="Id")
Childone getChildoneByChildoneid() {
return childoneByChildoneid;
}
public void setChildoneByChildoneid(Childone childoneByChildoneid) {
this.childoneByChildoneid = childoneByChildoneid;
}
...
}
#Entity
public class Childone {
...
private Collection<Parent> parentsById;
#OneToMany(mappedBy = "childoneByChildoneid")
public Collection<Parent> getParentsById() {
return parentsById;
}
public void setParentsById(Collection<Parent> parentsById) {
this.parentsById = parentsById;
}
...
}
And have a service like this:
#Stateless
#WebService()
public class MasterDataService {
#EJB
private MasterDataManager manager;
#WebMethod
public Parent getParent(int parentId) {
return manager.getParent(parentId);
}
}
#Stateless
public class MasterDataManager {
#PersistenceContext
EntityManager em;
public Parent getParent(int parentId) {
Parent parent = (Parent) em.createQuery(
"select p from Parent p where p.id=:parentId")
.setParameter("parentId", parentId).getSingleResult();
return parent;
}
}
When I call this web method from client I get LazyInitializationException exception :(
I test Serializable and Cloneable interfaces and override clone method but unfortunately it doesn't work, I use em.detach(parent) in manager but it doesn't work still.
Can any one help me?
tnax
It is debatable. Generally, you have two options:
return the entities, but make sure they are initialized. Either mark the #*ToMany with fetch=FetchType.EAGER or use Hibernate.initialize(..). The reason for the exception is that by default all collections in entities are not fetched from the database until requested. But when you request them from the jax-ws serializer, the hibernate session is already closed. Technically, you can have some OpenSessionInViewIntercepetor but I don't think there's something ready-to-use with JAX-WS, and it might be a problem to write one. If you don't want to transfer these collections, you can annotate them with #XmlTransient (or #JsonIgnore, depending on the serialization technique). It makes the entity somewhat of a mess, but I still prefer it to code duplication.
Use DTOs (data transfer objects) - transfer all data from the entity to a new object with a similar structure, that will be exposed by the web service. Again you'd have to make sure you are populating the DTO when the hibernate session is active
I prefer the first option, because it requires less biolerplate code, but I agree one should be very careful with entity state management when using it.