I tried create BaseDao and inject EntityManager to it. In Spring I was make this:
public abstract class BaseJpaDao<E> implements BaseDao<E>{
protected Class<?> entityClass;
#PersistenceContext(unitName = "access")
protected EntityManager entityManager;
public BaseJpaDao(Class<?> entityClass) {
this.entityClass = entityClass;
}
#Override
public E persist(E e) {
entityManager.persist(e);
return e;
}
but now I tried make this in OSGI and I not understand how do it. I treid write in blueprint.xml
<bean id="baseJpaDao" class="domain.access.impl.BaseJpaDao" >
<jpa:context unitname="access" property="entityManager"/>
<tx:transaction method="*" value="RequiresNew"/>
</bean>
and after this
public abstract class BaseJpaDao<E> implements BaseDao<E>{
protected Class<?> entityClass;
private EntityManager entityManager;
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
public BaseJpaDao(Class<?> entityClass) {
this.entityClass = entityClass;
}
#Override
public E persist(E e) {
entityManager.persist(e);
return e;
}
I treid like this link
but not help.
I tried this
EntityManagerFactory emf = Persistence.createEntityManagerFactory("access", System.getProperties());
em = emf.createEntityManager();
but not help.
In Aries JPA 1.x that does not work.
In Aries JPA 2.x you can use exactly the same code as in spring. See TaskServiceImpl.java. You just need to add the jpa:enable and jta:enable elements to you blueprint context to activate the functionality.
Alternatively you can use the blueprint-maven-plugin to generate the whole blueprint.xml from annotations. Btw version 1.3.0 should be fine. You do not need the snapshot.
Thanks for the configuration snippets. The problem is that you use the wrong namespace for jpa. Try these:
xmlns:jpa="http://aries.apache.org/xmlns/jpa/v2.0.0"
xmlns:tx="http://aries.apache.org/xmlns/transactions/v1.2.0"
Related
I use karaf 4.0.5 and hibernate 4.2.15 And I want get EntityManager in my BaseDao class.
If I tried get EntityManager in my service
<bean id="subscriberService" class="domain.payment.impl.subscriber.SubscriberServiceImpl" scope="singleton"
init-method="init">
<tx:transaction method="*" />
</bean>
and in class
#PersistenceContext(unitName="payment")
private EntityManager entityManager;
I get EntityManager normaly.
But if I tried it in another class
public class BaseJpaDao<E> implements BaseDao<E>{
protected Class<?> entityClass;
#PersistenceContext(unitName="payment")
private EntityManager entityManager;
public BaseJpaDao(Class<?> entityClass) {
this.entityClass = entityClass;
}
#Override
public E persist(E e) {
entityManager.persist(e);
return e;
}
My entityManager is NULL;
I tried
<bean id="baseDao" class="domain.payment.impl.base.BaseJpaDao" scope="singleton"
init-method="init">
<tx:transaction method="*" />
</bean>
But it not help.
In Spring project it work fine, but in OSGi I have many problems.
really only from the services I can get entityManager?
Have you checked the log ? The BaseJpaDao does not seems to have a public empty constructor, so there should be an error in karaf.log saying the the baseDaobean cannot be created...
I'm using Spring Boot (1.3.3) with annotation-based/JavaConfig configuration on an application.
I have the following repository interface:
#RepositoryRestResource(collectionResourceRel = "something", path = "something")
public interface SomethingRepository
extends CrudRepository<SomethingRepository, Long> {
}
What I would like to do is override the behavior of some methods in the generated repository proxy. The only way I found of doing this is based on what the documentation suggests for adding new custom methods (see: Adding custom behavior to single repositories), so I define the following interface:
public interface SomethingRepositoryCustom {
Something findOne(Long id);
}
...and I add the corresponding implementation:
public SomethingRepositoryImpl extends SimpleJpaRepository<Something, Long>
implements SomethingRepositoryCustom {
public SomethingRepositoryImpl(<Something> domainClass, EntityManager em) {
super(domainClass, em);
this.entityManager = em;
}
#Override
public Something findOne(Long id) {
System.out.println("custom find one");
// do whatever I want and then fetch the object
return null;
}
}
Now, if I start the application, I get the following error:
... org.springframework.beans.BeanInstantiationException: Failed to
instantiate [com.dummy.repositories.SomethingRepositoryImpl]: No
default constructor found; nested exception is
java.lang.NoSuchMethodException:
com.dummy.repositories.SomethingRepositoryImpl.() ...
Question:
How can I solve the BeanInstantiationException? I'm assuming I need to declare a repository factory bean but I'm not sure how to do so overriding the Spring Boot configuration.
Indeed you have to declare a new FactoryBean in your #EnableJpaRepositories annotation:
#Configuration
#EnableJpaRepositories(value = "your_package",
repositoryFactoryBeanClass = CustomFactoryBean.class)
public class ConfigurationClass{}
CustomFactoryBean.java:
public class CustomFactoryBean<R extends JpaRepository<T, I>, T, I extends Serializable> extends JpaRepositoryFactoryBean<R, T, I>{
#Override
protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
return new SimpleJpaExecutorFactory(entityManager);
}
/**
* Simple jpa executor factory
* #param <T>
* #param <I>
*/
private static class SimpleJpaExecutorFactory<T, I extends Serializable> extends JpaRepositoryFactory{
private EntityManager entityManager;
/**
* Simple jpa executor factory constructor
* #param entityManager entity manager
*/
public SimpleJpaExecutorFactory(EntityManager entityManager) {
super(entityManager);
this.entityManager = entityManager;
}
#Override
protected Object getTargetRepository(RepositoryMetadata metadata) {
JpaEntityInformation entityInformation =
getEntityInformation(metadata.getDomainType());
return new SomethingRepositoryImpl<T,I>(entityInformation, entityManager);
}
#Override
protected Class getRepositoryBaseClass(RepositoryMetadata metadata) {
return SomethingRepositoryImpl.class;
}
}
}
Then it will be your SimpleJpaRepository instance: SimpleJpaRepositoryImpl that will be used
From version 1.9, you no longer need to create a new FactoryBean class, instead you can just set the base repository directly. From Baeldung:
#Configuration
#EnableJpaRepositories(basePackages = "org.baeldung.persistence.dao",
repositoryBaseClass = ExtendedRepositoryImpl.class)
public class StudentJPAH2Config {
// additional JPA Configuration
}
public class ExtendedRepositoryImpl<T, ID extends Serializable>
extends SimpleJpaRepository<T, ID> implements ExtendedRepository<T, ID> {
private EntityManager entityManager;
public ExtendedRepositoryImpl(JpaEntityInformation<T, ?>
entityInformation, EntityManager entityManager) {
super(entityInformation, entityManager);
this.entityManager = entityManager;
}
// ...
}
I have a JPA/hibernate setup with multiple entity managers. What I am trying to do is dynamically injecting the entity manager in an abstract class used by multiple schemas with the same entity definition -- the tables are exactly the same across different databases in a single MySQL server. I am trying not to write unnecessary duplicate code, but I can't seem to find a way to inject the persistence context dynamically without duplicating a lot of code. Is there any way to do this?
Well, do you need to change the EntityManager that exists in a DAO instance? If yes, I'd say just switch your connection pool instead.
If instead you want to select to which instance to connect, set up the necessary keys in one or more profiles, then use that to get the necessary connection properties for your connection pool.
If you want to have multiple instance of the same DAO, use qualified beans and constructor injection to get the proper entity managers to them (abstract away everything else like factory / pool creation into methods).
I ended up creating an abstract DAO with all the basic list, update, delete methods and extending by another abstract DAO in which I set the entity manager for that particular set. Any DAOs that extend the last one will have the correct annotated entity manager associated with them. From that point on I am able to reuse my models, and all I have to do is extend the right DAO on my service layer.
The magic happens by calling setEntityManager(EntityManager em) using the #PerisstenceContext with the persistence unitName. I am not entirely sure why this works, but seems to do the trick.
Here's what I did:
AbstractJpaDao:
#MappedSuperclass
public class AbstractJpaDao <T>{
private Class<T> clazz;
protected EntityManager entityManager;
public final void setClazz(final Class<T> clazzToSet) {
this.clazz = clazzToSet;
}
#Transactional
public T getById(final long id) {
return entityManager.find(clazz, id);
}
//... all the others ...
}
InheritedDao1:
#MappedSuperclass
public class InheritedDao <T> extends AbstractJpaDao <T>{
//This is what allows me to inject the entityManager by its annotation
#PersistenceContext(unitName = "myPU")
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
}
InheritedDao2:
#MappedSuperclass
public class OtherInheritedDao <T> extends AbstractJpaDao <T>{
//This is what allows me to inject the entityManager by its annotation
#PersistenceContext(unitName = "otherPU")
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
}
Service1:
#Service
#Transactional(readOnly = true)
public class MyService extends InheritedDao<MyModel> {
public MyService() {
setClazz(MyModel.class);
}
}
Service2:
#Service
#Transactional(readOnly = true)
public class OtherService extends OtherInheritedDao<MyModel> {
public OtherService() {
//same model as used in MyService
setClazz(MyModel.class);
}
}
I’d like a controller that is able to seamlessy access the persistence layer and EJB is a nice technology for this purpose. I can do something like this:
#PersistenceContext
EntityManager em;
...
Cat timmy = em.findById(Cat.class, "Timmy");
timmy.color = "red";
And it feels like timmy is in-memory. The sad part is that this has to be done at business level because beans are only at business level. However transactions should be defined at client level in the MVP.
That’s why I would like to have a Presenter that is a #Stateful bean. This way I can start and end transactions at client level. Anyways I have this strange feeling that #Stateful bean are evil and I’d rather not use them.
is that:
#PersistenceContext
EntityManager em;
...
Cat timmy = em.findById(Cat.class, "Timmy");
timmy.setColor("red");
em.merge(timmy);
working?
in term of architecture I use #Stateless Dao
#Stateless
public class CatDao extends Dao<Cat> {
public CatDao () {
super(Cat.class);
}
}
public class Dao<E> {
#PersistenceContext(unitName = "myappPU")
private EntityManager em;
private final Class<E> entityClass;
protected Dao(Class<E> entityClass) {
this.entityClass = entityClass;
}
public E find(Object id) {
return em.find(entityClass, id);
}
public List<E> findAll() {
CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
Query q = entityManager.createQuery(cq) ;
return q.getResultList();
}
public void create(E entity) {
em.persist(entity);
}
public void edit(E entity) {
em.merge(entity);
}
public void remove(E entity) {
em.remove(entityManager.merge(entity));
}
}
so in the controller I do
#Inject
private CatDao dao;
//...
Cat cat = dao.find("Timmy");
cat.setColor("red");
dao.edit(cat);
see... statless
Netbeans generate this Dao automatically but called them Facade (new>Other>Entreprise JavaBeans>session beans for entity classes)
Finally I did it!
The solution was hidden in CDI specs:
#Inject CatRepository catRepository;
#Transactional
void changeColorToCat(String color, String catName) {
Cat timmy = catRepository.findByName("Timmy");
timmy.color = "red";
}
And it’s done! It’s like databases don’t exist at all!
I'm trying to get CDI (with Open Web Beans) working from within a unit test using Delta Spike (#RunWith(CdiTestRunner.class)). Dependency injection is working fine but my EntityManagerFactory is always null:
public class EntityManagerProducer {
#PersistenceContext(unitName = "sbPersistenceUnit")
private EntityManagerFactory emf; //Always null
#Produces
public EntityManager create() {
return emf.createEntityManager();
}
public void close(#Disposes EntityManager em) {
if (em.isOpen()) {
em.close();
}
}
}
I know that my persistence.xml is okay because I can create the Session Factory manually:
EntityManagerFactory test = Persistence.createEntityManagerFactory("sbPersistenceUnit");
and all other injections are working fine. Does anybody know what might be missing?
In an unit-test you aren't in a managed environment.
OpenWebBeans would support it via the openwebbeans-resource module + #PersistenceUnit, but that isn't portable.
So you need to use e.g.:
#Specializes
public class TestEntityManagerProducer extends EntityManagerProducer {
private EntityManagerFactory emf = Persistence.createEntityManagerFactory("...");
#Produces
//...
#Override
protected EntityManager create() {
return emf.createEntityManager();
}
#Override
protected void close(#Disposes EntityManager em) {
if (em.isOpen()) {
em.close();
}
}
}
in the test-classpath
If you ask such questions on their mailing-list, you get answers petty quickly.
You will need to use #PersistenceUnit to inject EntityManagerFactory. #PersistentContext is used for EntityManager injection.
Do you define your entitymanagerFactory as a bean?
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>