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
}
Related
I'm developing a Web Application with Spring Framework(Spring Boot) and JDBC (no JPA or ORM) so I'm using Dependency Injection to use Beans through layers. The structure is composed by three main layers: DB (DAOs), Service and Controller. DAOs are injected in other DAOs or in Service layer and Services in other Services and in Controller Layer.
My Database layer is composed by one DAO for each the tables of the database. Each DAOhas the general CRUDand some specific operations according to its needs. In total I have more than 10 tables (nearly 15 maybe).
Example of DAO
public class Dao1 implements Crud<Entity, Integer>{
public Entity findById(Integer id){
//Impl Jdbc
}
public void insert(Entity entity){
//JDbc impl
}
//Other CRUD operations -> Update, delete,...
}
In the Service layer I map Entities (Database objects) to DTos(Data access object).
Problem
I have a #Service class with It is needed to inject too much dependencies (10 dependencies) of data access object.
Why? I've got a complex DTO class which is needed to fill getting some data of each entity (using DAOs) and doing some operations also (Update, insert, delete.....
Example of Service
public class ServiceO{
#Autowired
private Dao1 dao1;
#Autowired
private Dao2 dao2;
//assume there are 10 daos....
public ObjectComplexDTO findObject(int id){
ObjectComplexDTO dto = mapToObjectComplexDTO(dao1.findById(id));
dto.setOtherObjects(mapToOtherObjectDto(dao2.findByCompleDto(id)));
// and so on....
return dto;
}
}
When I reviewed my #Service I saw clearly it`s needed to refactor this class but I'm not sure how.
I have considered the following options:
Create a Class which groups by functionality: but extract data remain too much, 7 dependencies...
Group DAOs (no just one DAO for Entity) and Make more complex SQL and extract more data giving more functionality to the Database Engine in the Entities of this data that only DTOs has and then filled in DAOs layer: the problem is moved to the layer DAO...
Keep the class knowing that it has too many dependencies.
Do you have any idea's to improve this issue?
Just off the top of my head, I would suggest refactoring your DAOs. It sounds like you have one DAO per table. Instead, try to align your DAOs with business requirements in a more Domain-Driven style of design. Your service layer is required to "know" too much about the data layer and is therefore likely to be unnecessarily coupled to it.
Some days ago I heard about spring-boot.
So I started to setup my project from zero, include jpa and dont use older setups from existing projects. But now there is an understanding problem between what I've learned and what I've read about the "easy setup" with spring boot and jpa.
Usually my projects have this structur.
Model (for excample Car)
ModelDao (CarDao with the following code-example)
#Component
public class CarDao {
/** The Hibernate session factory. */
#Autowired
private SessionFactory sessionFactory;
#Transactional
public void save(Car car) {
sessionFactory.getCurrentSession().saveOrUpdate(car);
}
CarServiceImpl thats works with DAO´s (includes methods like findAll(), getCarById() or saveCar(Car car))
But now I only read about #Entity and JPA-repositorys.
Is it right to say that I dont need models and dao's because I have the #Entity-Annotation? And my ServiceImples and JPA-repositorys have the same functionality? What happend with the SessionFactory? Is all managed automatically?
You dont need DAO if you are going to use JPA-Repositories.
As well Session-Factory also not required.
Just you need one Class as model and one interface as repository and you all done.
example:
#Entity
#Table(name="COUNTRY")
public class Country {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="COUNTRY_ID", nullable = false)
private Integer country_id;
#Column(name="COUNTRY_CODE")
private String country_code;
//Add getter and setter
}
interface
public interface CountryRepository extends PagingAndSortingRepository<Country, Integer> {
}
Yes you need to configure in spring.xml about where your above repository is located
<jpa:repositories base-package="com.repository" />
create transactionManager in spring.xml
and access it by using below code
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"spring.xml");
countryRepository = (CountryRepository) ctx.getBean("countryRepository");
Country country = countryRepository.findOne(1);
Is it right to say that I dont need models and dao's because I have the #Entity-Annotation?
#Entity annotation is used on models your POJOs. #Entity maps the POJO i;e class properties to the db table. How would you write your business logic if you get rid of models.
Service layer, DAO layer are all components of application design. They have their specific role. ServiceImpl proverbially manages the transactions whereas DAO/Repository layer manages the communication with the db.
Here your CarDao class should be annotated with #Repository annotation. It is a DAOImpl class.
And all your transactional methods should move to the Service layer.
And my ServiceImples and JPA-repositorys have the same functionality?
No, as I've already stated they have specific respective functionality. They are not same.
What happend with the SessionFactory? Is all managed automatically?
SessionFactory is always injected into the DAO layer. You can either manage the sessions yourself or let hibernate manage the sessions.
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:";
}
}
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.
I have a moderate sized Java EE 6 project that uses several EJBs, including one which sole purpose is managing database calls through JPA. My question is what is the best way to add a new class that does some random bit of functionality and then calls the database access EJB to persist the data from this class.
Does this new class have to be an EJB if it needs access to annotations and injections? Does it have to be an EJB if it has to be deployed with the rest of the project?
I was told that if you want to add a new logic class to the project it either has to be an EJB or you can remotely integrate it using JNDI to access EJB elements and create some kind of client interface. Right now my new class is just a POJO but it's not able to access the EJB functionality.
What should I do in general?
EDIT: Please note my question IS NOT about database access. That's just an example I'm using. My guestion is more broad. I want to know how to access EJB methods from other classes I create. From one EJB to another you can simply inject the other EJB since they're both container managed. But say I create another class in the same package as the EJBs how might How can I access those methods? Is it possbile? What is the best practices here.
Right now I have a class that is taking twitter feed data from a URL it then parses the JSON and returns a string of the top 10 entries. I want to call my EJB that manages database access and pass that string to its corresponding method but I cannot do that because my class is not also an EJB.
EJBs are generally used to implement services of any kind. They integrate really well with JPA so are often used for DB access, but that's not their only usage.
What EJBs are typically not suited for is modeling data. I.e. they should be the verbs in your application, not the nouns. The following is thus wrong:
#Stateless
#Entity
public class CreditCard { // silly, don't do this!
#Id
Long id; + getters/setters
Data expiration date; + getters/setters
}
The following is better, it's a service that when your application starts up fetches some quote data from somewhere:
#Singleton
#Startup
public class QuoteFetcher {
private List<Quote> quotes; // + getter
#PostConstruct
public fetchQuote()
quotes = SomeUrlBuilder.someUrl().getQuotes();
}
}
The following is the obligatory DAO example:
#Stateless
public class JPAInvoiceDAO implements InvoiceDAO {
#PersistenceContext
private EntityManager entityManager;
public Invoice getById(Long invoiceId) {
return entityManager.find(invoiceId, Invoice.class);
}
// More DAO methods
}
The following shows how declarative security is used, and how a bean looks up something that has been externally mapped into its private context (ENC):
#Stateless
public class TokenFetcher
#Resource
private SessionContext sessionContext;
#RolesAllowed("SYSTEM")
public Token getToken() {
return (Token) sessionContext.lookup("token");
}
}
The second part of the question seems to be how to use these beans in your code. There are basically four methods:
Injection in managed beans
Bootstrapping via JNDI
Automatically called at startup
Automatically via a timer
Injection is the easiest way, but only managed beans are injection candidates (basically meaning the Java EE framework creates the bean, and you don't use new() to instantiate it).
E.g. Injection:
#ManagedBean
public class InvoiceBacking {
private Long invoiceId; // + getter/setter
private Invoice invoice; // + getter
#EJB
private InvoiceDAO invoiceDAO;
#PostConstruct
public void init() {
invoice = invoiceDAO.getById(invoiceId);
}
}
(also see Communication in JSF 2.0#Processing GET request parameters)
Bootstrapping via JNDI:
public class SomeQuartzJob implements Job {
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
InvoiceDAO invoiceDAO = (InvoiceDAO) new InitialContext().lookup("java:global/myApp/myEJB/InvoiceDAO");
List<Invoice> openInvoices = invoiceDAO.getAllByOpenStatus();
// verbose exception handling and closing JNDI context omitted for brevity
}
}
The #Singleton bean showed earlier was an example of how the Java EE framework calls your code itself at startup. For the automatic timer you would use the #Schedule annotation on a bean's method.