Concern about importing class implementation into DAO - java

I have to implement DAOs which use only the interfaces of the objects. Now I'm having trouble figuring out how to use the em.find()of the EntityManagerclass.
My specific question is, if it is ok to import the implementation of a class directly into the DAO like in this example:
import dao.IStreamingServerDAO;
import model.IStreamingServer;
import model.impl.StreamingServer;
import javax.persistence.EntityManager;
public class StreamingServerDAO implements IStreamingServerDAO {
protected EntityManager em;
public StreamingServerDAO(EntityManager em) {
this.em = em;
}
#Override
public IStreamingServer findById(Long id) {
return em.find(StreamingServer.class, id);
}
}
I feel like I'm hurting some privacy principles by simply importing the model.impl.StreamingServer class into the DAO.
Problem is I don't know how else I'm supposed to get the needed class for the em.find()method.
Please not that I can't change the return type of the findByIdmethod as it's defined like this by the interface. (Also this implementation right now works as expected).

Related

Using #Transactional correctly in Spring boot for big queries

I have a method who calls 3 childs-methods before making a transaction with the repository, like this :
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
#Service
public class ObjectService {
#Transactional
public void doSomething() {
objectRepository.findAllObject();
childMethod1();
childMethod2();
childMethod3();
objectRepository.save(int id);
}
public void childMethod1() {
//do something
}
public void childMethod2() {
//do something
}
public void childMethod3() {
//do something
}
}
and the repository has a select and a save method :
#Query("SELECT * FROM object WHERE id is null")
Optional<Obeject> findAllObject();
#Query("SELECT * FROM object WHERE id is null")
Optional<Obeject> save(int id);
In my case, if I'm using this system on a table with 100k entries, the application start with a quicl execution of the queries, but no transaction is realized (no move in the database), because the program seems to wait to do all the job before execute the repository method.
So, in fact, if I use this method on all the table entries, Spring boot become smaller and smaller and finish to be blocked without making one single change in the database.
So, actually, I've created an endpoint to do this with a loop of 1000entries. Just have to ping it with a bash job and it works but it's a dirty method.
I would like to know what is the best practice and if this second way is a good method for you :
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
#Service
public class ObjectService {
#Transactional(propagation = Propagation.REQUIRES_NEW)
public void doSomething() {
objectRepository.findAllObject();
childMethod1();
childMethod2();
childMethod3();
objectRepository.save(int id);
}
public void childMethod1() {
//do something
}
public void childMethod2() {
//do something
}
public void childMethod3() {
//do something
}
}
If I understand correctly, the annotation
#Transactional(propagation = Propagation.REQUIRES_NEW)
will do 1 transaction at the end of execution of the parent method for all objects return by the repository instead of waiting the end of the execution for all of the object, right?
Sorry if these questions seems simple for you, I'm trying to understand the documentation but it's difficult to understand with a bad level of english.
Thanks for your help!
EDIT: add repository methods

Which class should be responsible for starting / ending transaction in JPA?

So I have a sample code like this:
package biz.tugay.books10Aug.dao;
/* User: koray#tugay.biz Date: 10/08/15 Time: 22:54 */
import biz.tugay.books10Aug.model.Book;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
public class BookDaoImpl implements BookDao {
private EntityManager entityManager;
public BookDaoImpl(EntityManager entityManager) {
this.entityManager = entityManager;
}
#Override
public void persist(Book book) {
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
entityManager.persist(book);
transaction.commit();
}
}
and this is how I unit test it:
package biz.tugay.books10Aug.dao;
/* User: koray#tugay.biz Date: 10/08/15 Time: 22:56 */
import biz.tugay.books10Aug.model.Book;
import org.junit.Test;
import javax.persistence.EntityManager;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class BookDaoImplTest {
#Test
public void testPersistNewBook() throws Exception {
PersistenceUtil.initalizeEntityManagerFactory();
EntityManager entityManager = PersistenceUtil.getEntityManager();
BookDao bookDao = new BookDaoImpl(entityManager);
String isbn = new SimpleDateFormat("HHmmss").format(Calendar.getInstance().getTime());
Book book = new Book();
book.setIsbn(isbn);
book.setName("Just Another Book in the DB, Volume: " + isbn);
book.setPrice(10);
book.setPublishDate(Calendar.getInstance().getTime());
book.setPublisher("002");
bookDao.persist(book);
}
}
This all works fine. My question is about OOP.
I decided that BookDaoImpl should not be responsible for getting the EntityManager. It should be the BookService 's responsibility. Why? I a do not know really.
Also, whos responsibility should be to get transaction, begin and commit? Again BookService or BookDao?
JPA Transaction should be managed on a service layer. Here's an counterexample:
consider you have a find method in your DAO layer:
public Book find(long id) {
return entityManager.find(Book.class, id);
}
And your Book class owns a collection of pages:
#OneToMany(mappedBy = "book", fetch = LAZY")
private Set<Page> pages;
public Set<Page> getPages() {
return pages;
}
If the entityManager has a lifecycle within a DAO, the call of getPages() method made from your service layer will result in lazy initialization exception
Of course in each rule there are exceptions, but in general you should manage your transaction on service layer (or repository layer depending on wording).
You can even use MANDATORY transaction demarcation attribute in your DAO layer in order to make it mandatory.
my opinion is it's ok that BookDao knows about EntityManager since it's about way of data persistence.
Regarding transaction - it's responsibility of service layer since it;s responsible for business logic implementation and transaction borders defines in business requirements. However it would be great to implement transaction management independently from persistence technology (now you are using JPA, tomorrow JDBC, later something else). Think Spring's transactions annotations could be a good example of this approach.

EclipseLink JTA Persistence issue (Null Pointer Exception)

I have two entities working in Mater Detail pattern like i describe in:
Stackoverflow Post: jpa-eclipselink-onetomany-derived-ids-fail
The pattern works as expected with LOCAL RESOURCE, but when i try to move the example to a web environment GlassFish4.1 (JSF) with JTA, i get the following error:
Advertencia: DTX5014: Caught exception in beforeCompletion() callback:
java.lang.NullPointerException at entidades.OrderItemPK._persistence_set(OrderItemPK.java)
The source code for persistence class:
import java.util.List;
import javax.persistence.Query;
import javax.persistence.EntityManager;
import java.util.List;
import javax.persistence.Query;
import javax.persistence.EntityManager;
public abstract class AbstractFacade<T> {
private Class<T> entityClass;
protected abstract EntityManager getEntityManager();
public AbstractFacade(Class<T> entityClass) {
this.entityClass = entityClass;
}
public void create(T entity) {
getEntityManager().persist(entity);
}
public T edit(T entity) {
return getEntityManager().merge(entity);
}
public void remove(T entity) {
getEntityManager().remove(getEntityManager().merge(entity));
}
I tried with both methods create and edit. Any idea what I'm doing wrong, suggestions are welcome.
Your entity is using the basic 'long' types which do not allow null, so check that your database values are not null. If they are, a quick fix is to change the to the wrapper type "Long": http://edwin.baculsoft.com/2012/02/nullpointerexception-when-using-jpa/
If that is the case, you will need to track down how the database is being populated with null values for fields associated to the primary key.
The problem was in the PK class, change the data type int to Integer and then the error appeared on the method hashCode()

Using Spring Security ACL

I am trying to implement Spring Security ACL in my application. I have many classes that I want to use an ACL on.
I read in the documentation that AOP have been used with success before. Does this mean that all the services should have a common interface for doing CRUD against the objects for maximum reuse of the advise?
Or is it normal to manually insert, delete, ... in the save, update, delete methods of the service?
I can't manage to find many examples of how people use the framework.
---- Listener for Entity removal (includes cascading deletes) -----
package com.acme.model.aspects;
import javax.annotation.PostConstruct;
import javax.persistence.PreRemove;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.data.domain.Persistable;
import com.acme.PermissionService;
#Component
public class ObjectIdentityListener {
private static final Logger LOG = LoggerFactory.getLogger(ObjectIdentityListener.class);
static private PermissionService permissionService;
#Autowired(required = true)
#Qualifier("permissionService")
public void setSearchService(PermissionService _permissionService)
{
permissionService = _permissionService;
}
#PreRemove
public void preRemove(Object object) {
if(object instanceof Persistable) {
LOG.info("Deleting object identity for class {} id {} ", persistable.getClass(), persistable.getId());
permissionService.deleteObjectIdentity((Persistable) object);
}
}
#PostConstruct
public void init() {
Assert.notNull(permissionService, "'permissionService' is required");
}
}
---- Delete method for permissionService ----
public void deleteObjectIdentity(Persistable persistable) {
try{
MutableAcl acl = (MutableAcl) mutableAclService.readAclById(identity(persistable));
mutableAclService.deleteAcl(acl.getObjectIdentity(), true);
} catch (NotFoundException e){
LOG.info("Could not find ACL for target {}", persistable);
}
}
It all depends on your app. Having a centralized hierarchy of services would certainly make it simpler to implement single security checks for create/retrieve/update/delete methods. But you have an existing app with different services that don't necessarily have a common parent implementation, then you'd have to add ALC security annotation on each service method.
Another option is to put ACL security on your DAO layer, it works fine, but for some reason just doesn't feel right. IMHO DAO's shouldn't deal with things like security. I've spent a LOT of time dealing with Spring Security ACL, got a pretty good handle on it by now, ping me if you need any concrete examples.

Bad practice in this spring tutorial?

I'm following the spring tutorial.
In section "3.2. Add some classes for business logic" an interface ProductManager is created:
package springapp.service;
import java.io.Serializable;
import java.util.List;
import springapp.domain.Product;
public interface ProductManager extends Serializable{
public void increasePrice(int percentage);
public List<Product> getProducts();
}
Then a SimpleProductManager implementation class is created:
package springapp.service;
import java.util.List;
import springapp.domain.Product;
public class SimpleProductManager implements ProductManager {
public List<Product> getProducts() {
throw new UnsupportedOperationException();
}
public void increasePrice(int percentage) {
throw new UnsupportedOperationException();
}
public void setProducts(List<Product> products) {
throw new UnsupportedOperationException();
}
}
The implementation class adds an extra method setProducts(). Should the interface ProductManager not also have a setProducts method to allow classes which use setProducts to instantiate SimpleProductManager polymorphically. Currently this is not possible -
ProductManager p = new SimpleProductManager();
p.setProducts();
The interface does not include setProducts because the clients of that interface (probably an MVC controller) are not supposed to call it. The interface defines only those operations that clients are supposed to use, rather than defining all of the methods that the implementation may have.
The setProducts method will be accessible to the beans configuration (e.g. using <property name="products">), which allows the products to be statically configured at start up. After that, client code refers to the bean via its restricted interface.
Your p.setProducts() example should never be called in this example, since the products are only configured in the beans config, not by business logic.

Categories

Resources