Can a service-layer object "service" a DAO-layer object? Or is does this violate the integrity of a properly layered architecture?
e.g.,
class MyService {
}
class MyDao {
private MyService myService;
}
I wouldn't do it. DAOs ought to deal with databases; services manage other services and DAOs to fulfill their use cases. It'd be better to have the service call the DAO and any other services that are required.
You risk a circular dependency with this arrangement.
The standard way of constructing services with DAO objects is to let the service encapsulate the DAO.
public class Service {
private DAO dao;
}
public class DAO {}
This is useful e.g., to let a service encapsulate multiple DAO objects, or to provide additional logic such as transaction demarcation in the service.
Related
Suppose I want to use a service in a POJO class, like an implementation of some sort, can I just pass this service as a parameter to this POJO? Or would that be bad practice?
#Service
public class MyService {
// Inject AnotherService in this service
public MyService(AnotherService anotherService) {
// Now pass that service in a POJO
SomeImplementation impl = new SomeImplementation(anotherService);
}
}
public class SomeImplementation {
public SomeImplementation(AnotherService anotherService) {
// start using the AnotherService here...
}
}
For this example I used Java and Spring, but this question applies to all languages with dependency injection.
I would say that it's just not making use of the framework you're operating within. That's exactly what DI is for: letting the container handle the components and their relations (eg. if you inject sth multiple times, DI helps you avoid multiple instantiations).
Now, in your case, you can use the #Configurable annotation, which adds a POJO component to the Spring context, and so lets you inject stuff into it.
I have an controller that call three services :
public class ProductController() {
#Autowired
private AccountService accountService;
#Autowired
private ProcessService processService;
#Autowired
private releaseService releaseService;
#RequestMapping("/process")
public Product process(#RequestParam(value="name", defaultValue="docs") ProductProcessed process) {
accountService.notify();
releaseService.sendRelease(process);
return processService.process(process);
}
}
What is the best approach to encapsulate this service calls??
What you are looking for is possibly some design patterns. I approach could be to create a coarse-grained facade over the fine-grained services (Account, Process and Release). (see also Coarse-grained vs fine-grained)
The Facade will basically have these 3 services injected in them and encapsulate the behavior you are making your controller perform currently. This way you will minimize the business logic to invoking the coarse grained service in your controller thus further encapsulating the guts of the system.
You already have them marked as private, so they cannot be called outside of this class. This is encapsulated.
A common practice is to autowire them so the implementation of the service can be modified.
I'm trying to figure out how to setup a Service/Dao layer in my application. I've found a few dozen resources all with different ways on how to do it and decided to follow the model found here: How should EntityManager be used in a nicely decoupled service layer and data access layer?
I can't figure out what I'm missing that's causing this NPE.
Usage:
#Path("/helloworld")
public class MyController {
#GET
#Produces(MediaType.TEXT_PLAIN)
public String TestRequest() {
Workflow workflow = new Workflow();
workflow.setName("test");
WorkflowService workflowService = new WorkflowService();
workflowService.save(workflow);
return "Workflow ID:";
}
}
My Dao:
#Stateless
public class WorkflowDao {
#PersistenceContext(unitName = "unit")
private EntityManager entityManager;
public int save(Workflow workflow) {
entityManager.persist(workflow);
return workflow.getId();
}
}
My Service:
#Stateless
public class WorkflowService {
#EJB
WorkflowDao workflowDao;
public int save(Workflow workflow) {
int id = workflowDao.save(workflow); //throws NullPointerException because workflowDao is null
return id;
}
}
This is my first time setting up a Java project (only have worked on 1 before and it used Spring) so please keep that in mind if this looks horribly wrong.
WorkflowDao is not an EJB, it's a POJO with a#Stateless annotation. So naturally, injecting it with #EJB fails, creating a null workflowDao attribute and eventually producing a NullPointerException.
To make WorkflowDao into a full-fledged EJB, besides having a #Stateless or #Stateful annotation it needs to implement a local, remote or both interfaces, and those interfaces must be annotated respectively with #Local and #Remote. Please refer to the tutorial for details.
Also, quite possibly (this can be application server-dependent) you'll have to register the EJB in the application's xml descriptor files - for instance, in web.xml's <ejb-local-ref> element.
As a side note - it's not a good idea to use an EJB as a DAO, an EJB is typically used for implementing business logic (true, persist/merge operations can be called from here) but the actual persistence layer nowadays is implemented using JPA. In other words, WorkflowService should be the EJB service, there's no need to inject an EJB into it, and there's no need for a separate DAO layer - JPA entities fulfill this role.
If you instantiate your WorkflowService manually, the container wont perform any injection, since your WorkflowService is not managed by the Container.
I suggest you:
Annotate your Jax-RS Resource #Stateless
Inject your WorkfloService via #EJB as a member
Implementing a Local or Remote Interface is not necessary anymore
#Path("workflows")
#Stateless
public class WorkFlowResource{
#EJB
WorkflowService workflowService;
#GET
#Produces(MediaType.TEXT_PLAIN)
public String TestRequest() {
Workflow workflow = new Workflow();
workflow.setName("test");
workflowService.save(workflow);
return "Workflow ID:";
}
}
im programming a project and im trying to apply multitier architecture.
Right now ive got 2 EJB, business and persistence and a shared jar. Due a funcional requirment, persistence must be replaceable. I made an Interface called IPersistence.
Then I crated a remote session bean called "persistence" inside the persistence EJB and put the remote interface in the shared library. Now, i need to call an IPersitence using injection from the business. How can i do that? Maybe the whole idea is wrong. I need some advice.
Thanks!
Here is a simple example where you have a car repository/DAO that abstracts the persistence from the business logic by not exposing if it is stored in a database, file, XML etc. The business class then injects an instance to be able to - in this case - save to an database. However you could have made other classes that implemented the CarRepository and provide other means for saving data in your application without touching other parts of your code.
Persistence layer
Interface for the repository/DAO
#Local
public interface CarRepository {
List<Car> findAllCars();
// Many other methods
}
Repository (Domain driven design) or Data Access Object
#Stateless
public class CarSqlRepository implements CarRepository {
#PersistenceContext(unitName = "MyUnit")
private EntityManager entityManager;
public List<Car> findAllCars() {
}
// Many other methods
}
Service/business layer
#Stateless
public class CarService {
#Inject
private CarRepository carRepository;
public List<Car> findAllCars() {
return carRepository.findAllCars();
}
// Many other methods
}
Am I right in understanding the principles of DAO & Service layer interconnection?
DAO performs extractions of base objects, say by id from a db.
Service layer USES a DAO object and may invoke MORE THAN ONE METHOD of DAO in one function.
So, Service layer has to:
instantiate a DAO implementation object
invoke as many methods of the DAO as needed
If a Dao implements an interface, then does a DAO interface has to have a method setSessionFactory()?
How to declaratively mark in Spring:
DAO object
Service layer methods, and class as a whole
so that it would give what is needed?
I'm surprised no one else has specifically mentioned this, but an implementation-specific detail such as setSessionFactory() should not be in your DAO interface. By adding a Hibernate-specific class to your DAO interface, you are tying your DAO's directly to Hibernate.
The purpose of using interfaces and dependency injection is to allow you to change an implementation detail (such as, what ORM solution you use, or if your data comes from a web service vs a database) of a layer (your DAO) without affecting other layers.
If you add setSessionFactory to your DAO interface, then all other layers that use this DAO become aware and tied to the fact that the data access is done through Hibernate. This is the direct opposite of what you are trying to achieve by using interfaces and dependency injection.
For my projects I write a base class which has a setSessionFactory() method that all my DAOs extend. Then I wire up my DAOs with Spring so that it injects the SessionFactory into each DAO.
Hibernate has a SessionFactory.getCurrentSession() so if you inject the SessionFactory into your DAOs and use that method, then the scope of the Session will be defined according to your transaction management mechanism.
What this means is if you have a method as such:
#Transactional
public void doSomething(){
dao1.makeCall();
dao2.makeOtherCall();
}
The SessionFactory you inject into each DAO when constructed will be using the same Session. But only for the scope of that transaction.
Leave transaction and session management to spring (via the built-in transaction managers).
In your DAOs use sessionFactory.getCurrentSession() tp access the session
have the SessionFactory injected in the DAO.
have DAO in scope singleton
use declarative transactions (either with <aop or with #Transactional)
the DAO is injected into the service objects via a regular dependency-injection. The same way the service classes are injected where they are needed.