I'm creating a web app using JEE7. My question is about the architecture of my application. Basically, I have several entity classes (business class) that represent what will be stored in my database. For example I've got an entity class Book and an entity class Comic.
To access the database I want to create an EJB (kindda like the DAO design pattern). And here is my problem, I couldn't find a precise answer online.
Should I create one #remote interface and one #stateless class with all the methods to add/delete/get/update for both the Book class and the comic class ?
Or should I create 2 #remote interfaces and 2 #stateless classes (2 EJB), one for each entity class ?
Because lets imagine I create a bigger web app. If I have 100 entity classes, with the first method I'll have one huge EJB but with the second I'll have 100 EJB with their interfaces. I think the second is better but I'm not sure. What do you think ?
Why not just use one stateless bean and one remote interface?
A very nice feature of remote beans is, that they can be generic, so basically at minimum you only need one interface and one remote bean at all (see SimpleEntity and its remote bean).
I use a mix of a very generic remote bean DAO to read simple entities and some specific beans for entities which need more logic on CUD operations. Following i just extracted the minimum interfaces to reproduce it.
If i create a new table and entity it can immediately be used at the remote client.
Entities
/*
* Complex entity with enhanced CRUD logic
*/
public class Foo implements Entity { }
/*
* Simple entity without complex CRUD logic
*/
public class Bar implements SimpleEntity { }
Interface
public interface Entity { }
public interface SimpleEntity extends Entity { }
/*
* Generic entity DAO interface, for remote beans and other datasources
*/
public interface IEntityDAO<T extends Entity>
{
public T get(Class<T> type, long id);
public T update(T t);
}
/*
* Generic remote bean interface for a JNDI service locator lookup
*/
public interface EntityDAOBeanRemote<T extends Entity> extends IEntityDAO<T> { }
Stateless remote Beans
/*
* 'abstract' base class for stateless DAO beans
*/
public class AEntityDAOBean<T extends Entity> implements EntityDAOBeanRemote<T>
{
public T get(Class<T> type, long id)
{
Session session = // obtain current hibernate session
return id == (T) session.createCriteria(type).add(Restrictions.idEq(id)).uniqueResult();
}
public T update(T t, long id)
{
Session session = // obtain current hibernate session
session.update(t);
return t; // return updated instance
}
}
/*
* Generic stateless remote DAO bean implementation
*/
#Stateless(mappedName = "SimpleEntityDAOBean")
#Remote(EntityDAOBeanRemote.class)
public class SimpleEntityDAOBean extends AEntityDAOBean<SimpleEntity> implements EntityDAOBeanRemote<SimpleEntity>
{
// empty since all methods are from parent class
}
/*
* Foo specific remote DAO bean
*/
#Stateless(mappedName = "FooDAOBean")
#Remote(EntityDAOBeanRemote.class)
public class FooDAOBean extends AEntityDAOBean<SimpleEntity> implements EntityDAOBeanRemote<Foo>
{
#Override
public Foo update(Foo foo)
{
// make specific foo things and update
return foo;
}
}
Client
Using JNDI at your client you can call the bean using a JNDI service locator pattern like:
EntityDAOBeanRemote<Foo> fooDAOBeanRemote = jndiServiceLocator
.getEntityDAOBeanRemote(Foo.class);
EntityDAOBeanRemote<Bar> barDAOBeanRemote = jndiServiceLocator
.getEntityDAOBeanRemote(Bar.class);
Client JSF
With generic JSF converters and a generic extension of a DAO for a GUI framework (such as PrimeFaces LazyDataModel) it saves a lot of time making new entities quickly accessible in JSF beans and editable in the GUI.
Java EE application architecture is obviously a massive topic, but a common approach would be to create a Session EJB to expose general API calls to your client and then use a coarse grain Entity EJB to handle your persistent data. These Entity EJBs can manage a number of finer grained Java objects and classes that map onto your database structure.
This might be a good place to start:
https://docs.oracle.com/cd/A87860_01/doc/java.817/a83725/entity1.htm
Related
I'm trying to get used to how JSF works with regards to accessing data (coming from a spring background)
I'm creating a simple example that maintains a list of users, I have something like
<h:dataTable value="#{userListController.userList}" var="u">
<h:column>#{u.userId}</h:column>
<h:column>#{u.userName}</h:column>
</h:dataTable>
Then the "controller" has something like
#Named(value = "userListController")
#SessionScoped
public class UserListController {
#EJB
private UserListService userListService;
private List<User> userList;
public List<User> getUserList() {
userList = userListService.getUsers();
return userList;
}
}
And the "service" (although it seems more like a DAO) has
public class UserListService {
#PersistenceContext
private EntityManager em;
public List<User> getUsers() {
Query query = em.createQuery("SELECT u from User as u");
return query.getResultList();
}
}
Is this the correct way of doing things? Is my terminology right? The "service" feels more like a DAO? And the controller feels like it's doing some of the job of the service.
Is this the correct way of doing things?
Apart from performing business logic the inefficient way in a managed bean getter method, and using a too broad managed bean scope, it looks okay. If you move the service call from the getter method to a #PostConstruct method and use either #RequestScoped or #ViewScoped instead of #SessionScoped, it will look better.
See also:
Why JSF calls getters multiple times
How to choose the right bean scope?
Is my terminology right?
It's okay. As long as you're consistent with it and the code is readable in a sensible way. Only your way of naming classes and variables is somewhat awkward (illogical and/or duplication). For instance, I personally would use users instead of userList, and use var="user" instead of var="u", and use id and name instead of userId and userName. Also, a "UserListService" sounds like it can only deal with lists of users instead of users in general. I'd rather use "UserService" so you can also use it for creating, updating and deleting users.
See also:
JSF managed bean naming conventions
The "service" feels more like a DAO?
It isn't exactly a DAO. Basically, JPA is the real DAO here. Previously, when JPA didn't exist, everyone homegrew DAO interfaces so that the service methods can keep using them even when the underlying implementation ("plain old" JDBC, or "good old" Hibernate, etc) changes. The real task of a service method is transparently managing transactions. This isn't the responsibility of the DAO.
See also:
I found JPA, or alike, don't encourage DAO pattern
DAO and JDBC relation?
When is it necessary or convenient to use Spring or EJB3 or all of them together?
And the controller feels like it's doing some of the job of the service.
I can imagine that it does that in this relatively simple setup. However, the controller is in fact part of the frontend not the backend. The service is part of the backend which should be designed in such way that it's reusable across all different frontends, such as JSF, JAX-RS, "plain" JSP+Servlet, even Swing, etc. Moreover, the frontend-specific controller (also called "backing bean" or "presenter") allows you to deal in a frontend-specific way with success and/or exceptional outcomes, such as in JSF's case displaying a faces message in case of an exception thrown from a service.
See also:
JSF Service Layer
What components are MVC in JSF MVC framework?
All in all, the correct approach would be like below:
<h:dataTable value="#{userBacking.users}" var="user">
<h:column>#{user.id}</h:column>
<h:column>#{user.name}</h:column>
</h:dataTable>
#Named
#RequestScoped // Use #ViewScoped once you bring in ajax (e.g. CRUD)
public class UserBacking {
private List<User> users;
#EJB
private UserService userService;
#PostConstruct
public void init() {
users = userService.listAll();
}
public List<User> getUsers() {
return users;
}
}
#Stateless
public class UserService {
#PersistenceContext
private EntityManager em;
public List<User> listAll() {
return em.createQuery("SELECT u FROM User u", User.class).getResultList();
}
}
You can find here a real world kickoff project here utilizing the canonical Java EE / JSF / CDI / EJB / JPA practices: Java EE kickoff app.
See also:
Creating master-detail pages for entities, how to link them and which bean scope to choose
Passing a JSF2 managed pojo bean into EJB or putting what is required into a transfer object
Filter do not initialize EntityManager
javax.persistence.TransactionRequiredException in small facelet application
It is a DAO, well actually a repository but don't worry about that difference too much, as it is accessing the database using the persistence context.
You should create a Service class, that wraps that method and is where the transactions are invoked.
Sometimes the service classes feel unnecessary, but when you have a service method that calls many DAO methods, their use is more warranted.
I normally end up just creating the service, even if it does feel unnecessary, to ensure the patterns stay the same and the DAO is never injected directly.
This adds an extra layer of abstraction making future refactoring more flexible.
How can I add a specific code in the implementations of methods that are listed in jparepository of spring data jpa without creating a new method in an interface that extending jparepository.
I want to edit the body of some methods listed in jparepository.
for example in save method body:
add[system.out.println("before persisting");] just before calling persist method
and [system.out.println("after persisting");] just after a persist calling
Thanks
You can introduce some aspect. It will provide you implement whatever you want.
You can see similar example here
Spring AOP + JPARepository
Something similar to this
#Aspect
#Component
#Configurable
public class AuditLogAspect {
#Pointcut("execution(* org.springframework.data.repository.CrudRepository+.save(*))")
public void whenSaveOrUpdate() {};
#Before("whenSaveOrUpdate() && args(entity)")
public void beforeSaveOrUpdate(JoinPoint joinPoint, BaseEntity entity) {...}
}
I'm writing a custom implementation for a Spring Data JPA repository. So I have:
MyEntityRepositoryCustom => interface with the custom methods
MyEntityRepositoryUmpl => implementation of the above interface
MyEntityRepository => standard interface which extends JpaRepository and MyEntityRepositoryCustom
My problem is this: within the implementation of MyEntityRepositoryUmpl I need to access the entity manager that was injected into Spring Data. How to get it?
I can use #PersistenceContext to get it autowired, but the problem is that this repository must work in an application that sets up more than one persistence units. So, to tell Spring which one I need, I would have to use #PersistenceContext(unitName="myUnit"). However, since my repositories are defined in a reusable service layer, I can't know at that point what will be the name of the persistence unit that the higher-level application layer will configure to be injected into my repositories.
In other words, what I would need to do is to access the entity manager that Spring Data itself is using, but after a (not so quick) look at Spring Data JPA documentation I couldn't find anything for this.
Honestly, the fact that the Impl classes are totally unaware of Spring Data, although described as a strength in Spring Data manual, is actually a complication whenever you need to access something that is usually provided by Spring Data itself in your custom implementation (almost always, I would say...).
Since version Spring Data JPA 1.9.2 you have access to EntityManager through JpaContext, see: http://docs.spring.io/spring-data/jpa/docs/1.9.2.RELEASE/reference/html/#jpa.misc.jpa-context.
Example:
#Component
public class RepositoryUtil
{
#Autowired
private JpaContext jpaContext;
public void deatach(T entity)
{
jpaContext.getEntityManagerByManagedType(entity.getClass()).detach(entity);
}
}
P.S.
This approach will not work if you have more than one EntityManager candidate for some Class, see implementation of JpaContext#getEntityManagerByManagedType -> DefaultJpaContext#getEntityManagerByManagedType.
The best I could find is to set up a "convention": my repositories declare that they expect a persistence unit named myConventionalPU to be made available. The application layer then assigns that alias to the entity manager factory that it sets up and injects into Spring Data, so my custom implementations can receive the correct EMF with autowiring by using that alias. Here's an excerpt of my application context:
<bean id="myEntityManagerFactory" name="myConventionalPU"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
[...]
</bean>
<jpa:repositories base-package="com.example"
entity-manager-factory-ref="myEntityManagerFactory"
transaction-manager-ref="transactionManager" />
And within my custom implementation:
#PersistenceContext(unitName = "myConventionalPU")
private EntityManager em;
I opened DATAJPA-669 with this requirement.
Spring Data JPA uses Auto configuration classes to auto generate entityManagerFactory, dataSource and transactionManager.
If you want get access to entityManager and control the instantiation and settings, you need to define your own PersistenceConfiguration. Below is the sample code using Java Config
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(basePackages = { "com.test.repositories.*" })
public class PersistenceJpaConfig {
#Autowired
JpaVendorAdapter jpaVendorAdapter;
#Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setName("testdb")
.setType(EmbeddedDatabaseType.HSQL)
.build();
}
#Bean
public EntityManager entityManager() {
return entityManagerFactory().createEntityManager();
}
#Bean
public EntityManagerFactory entityManagerFactory() {
LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
lef.setDataSource(dataSource());
lef.setJpaVendorAdapter(jpaVendorAdapter);
lef.setPackagesToScan("com.test.domain.*");
lef.afterPropertiesSet();
return lef.getObject();
}
#Bean
public PlatformTransactionManager transactionManager() {
return new JpaTransactionManager(entityManagerFactory());
}
}
If you have multiple data sources, follow this article.
1) What is a JaxB provider, and is it the same as a ContextResolver?
2) What is a jaxb handler?
I'm very lost in these terminologies. Please reply in simple to understand words.
Here it is from the book:
JAXB JAX-RS Handlers
The JAX-RS specification requires implementations to automatically support the marshalling and unmarshalling of classes that are annotated with #XmlRootElement or #XmlType as well as objects wrapped inside javax.xml.bind.JAXBElement instances. Here’s an example that interacts using the Customer class defined earlier:
#Path("/customers")
public class CustomerResource {
#GET
#Path("{id}")
#Produces("application/xml")
public Customer getCustomer(#PathParam("id") int id) {
Customer cust = findCustomer(id);
return cust;
}
#POST
#Consumes("application/xml")
public void createCustomer(Customer cust) {
...
}
}
As you can see, once you’ve applied JAXB annotations to your Java classes, it is very easy to exchange XML documents between your client and web services. The built-in JAXB handlers will handle any JAXB-annotated class for the application/xml, text/xml, or application/*+xml media types. By default, they will also manage the creation and initialization of JAXBContext instances. Because the creation of JAXBContext instances can be expensive, JAX-RS implementations usually cache them after they are first initialized.
Managing your own JAXBContexts with ContextResolvers
If you are already familiar with JAXB, you’ll know that many times you need to configure your JAXBContext instances a certain way to get the output you desire. The JAX-RS built-in JAXB provider allows you to plug in your own JAXBContext instances. The way it works is that you have to implement a factory-like interface called javax.ws.rs.ext.ContextResolver to override the default JAXBContext creation:
public interface ContextResolver<T> {
T getContext(Class<?> type);
}
ContextResolvers are pluggable factories that create objects of a specific type, for a certain Java type, and for a specific media type. To plug in your own JAXBContext, you will have to implement this interface. Here’s an example of creating a specific JAXBContext for our Customer class:
#Provider
#Produces("application/xml")
public class CustomerResolver
implements ContextResolver<JAXBContext> {
private JAXBContext ctx;
public CustomerResolver() {
this.ctx = ...; // initialize it the way you want
}
public JAXBContext getContext(Class<?> type) {
if (type.equals(Customer.class)) {
return ctx;
} else {
return null;
}
}
}
JAXB Provider
A JAXB provider is an implementation of the Java Architecture for XML Binding (JSR-222) specification. This specification was created through the Java Community Process. It was originally lead by Sun Microsystems, but is now lead by Oracle. The expert group had members from several object-to-XML technologies (XMLBeans, EMF, TopLink OX, etc) as well as several individuals. A JAXB implementation is required to pass the Test Compatibility Kit (TCK). Below are links to a couple of JAXB providers:
https://jaxb.java.net/
http://www.eclipse.org/eclipselink/moxy.php
ContextResolver
JAXB is the default object-to-XML provider in JAX-RS. By default it will create a JAXBContext based on the parameter/return type of the JAX-RS annotated method (i.e. annotated with #GET). Then it will pull in all referenced classes to produce metadata as well. Sometimes this doesn't produce all the required metadata and you need to provide the JAXBContext yourself. This can be done with a ContextResolver.
JAXB Handler
I'm not familiar with this term.
JAXB is the acronym for "Java Architecture for XML Binding", a specification defining ways to convert between XML documents and Java object trees, originally created by Sun Microsystems. The valid spec, version 2.0, was completed in 2006.
An implementation according to the JAXB specification is a JAXB provider.
The specification contains some hints, what a plausible implementation might contain. For instance: "The JAXBContext class is the entry point for a Java application into the
JAXB framework." It maintains information about the classes to expect during (un)marshalling. It is created either from one or more packages or from a list of classes. (The process of context resolution may follow hints in the annotation.)
The term "JAXB handler" (as it is used in the quoted text) refers to the code associated with a JAXBContext class that investigates a Java class, introspecting fields and methods and annotations, thus creating a database of all information contained within the Java code.
I am using a class separate from my DAO to handle access requests, but I don't know how to implement InstanceRequest methods:
public class Service
{
public static DAO findDAO(Long id);
}
#Service(Service.class)
public interface DAORequestContext extends RequestContext
{
Request<ProxyForDAO> findDAO(Long id);
InstanceRequest<ProxyForDAO, Long> persist();
}
I define public Long persist() in my DAO implementation, because the gwt docs say, "On the server, instance methods must be implemented as non-static methods in the entity type," but request factory can't seem to find it:
SEVERE: Could not find any methods named persist in com.activegrade.server.data.Service
Feb 23, 2011 10:03:02 PM com.google.gwt.requestfactory.server.ServiceLayerDecorator die
How do I implement an instance method in Service? I don't know how to transform the InstanceRequest. Do I need to connect the DAO class to the Service some way, so that the code generator knows to look in Service for most methods but to skip over to the DAO for InstanceRequest calls?
ASAIK it's not possible because the InstanceRequest methods are bound to the class specified in the #Service annotation. With Request methods it is possible to have a method for multiple data classes one service class, using locators. But from what I understand of request factory this is not possible with the InstanceRequest methods. See also this project, which uses Locators, with methods in one place: http://code.google.com/p/listwidget/
Edit: I've rewritten the answer based after the update/and comment below.