Spring Data JPA: Repositories for multiple database / Entitymanger configurations - entitymanager

I have two Entitymanager bean configurations. Each pointing to a separate database with a different schema (one is Oracle, the other one is an in-memory H2)
What could I do to solve the ambiguity of what Entitymanager should be used for each Repository? Right now I'm getting this error:
No unique bean of type [javax.persistence.EntityManagerFactory] is defined:
expected single bean but found 2
I guess I could provide a quick-fix simply by using something like
<jpa:repositories base-package="com.foo.repos.ora"
entity-manager-factory-ref="entityManagerFactoryA">
<jpa:repositories base-package="com.foo.repos.m2"
entity-manager-factory-ref="entityManagerFactoryB">
But hopefully there is a better solution.
EDIT:
I give you an idea of the current scenario:
Spring-Config: there're two EM
<jpa:repositories base-package="com.foo.repos.ora" entity-manager-factory-ref="entityManagerFactory"/>
<jpa:repositories base-package="com.foo.repos.m2" entity-manager-factory-ref="entityManagerFactory2"/>
<context:component-scan base-package="com.foo" /> ....
Everything from here on is in "package com.foo.repos.ora"
Following the pattern of how to make a custom repository I get two interfaces 'ARepository', 'ARepositoryCustom' and its implementation 'ARepositoryImpl' like so
#Repository
public interface ARepository extends ARepositoryCustom, JpaRepository<myEntity, BigDecimal>, QueryDslPredicateExecutor {
}
public interface ARepositoryCustom {
FooBar lookupFooBar()
}
public class ARepositoryImpl extends QueryDslRepositorySupport implements ARepositoryCustom {
ARepositoryImpl(Class<?> domainClass) {
super(domainClass.class)
}
ARepositoryImpl() {
this(myEntity.class)
}
#Override
FooBar lookupFooBar() {
JPQLQuery query = ....
....
return found
}
}
resulting in the following error message:
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'aRepositoryImpl': Injection of
persistence dependencies failed; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
unique bean of type [javax.persistence.EntityManagerFactory] is
defined: expected single bean but found 2
Which is of course correct, there are 2 EM beans, but since I restricted EM #1 aka 'entityManagerFactory' to package 'com.foo.repos.ora' only, I'm still not sure how to reference the exact EM bean.

There is no magic under the hood.
<jpa:repositories base-package="com.foo.repos.ora" entity-manager-factory-ref="entityManagerFactory"/>
doesn't help you at all with your custom interface implementations. Best way I found is to treat your custom implementations as regular beans. So I defined a 'sharedEntitManager' bean in my spring configuration like so
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
...
</bean>
<bean id="sharedEntityManager" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
<property name = "entityManagerFactory" ref="entityManagerFactory"/>
</bean>
After that, I simply injected the EntityManager into my implementation beans
<bean id="aRepositoryImpl" class="comm.foo.repos.ora.ARepositoryImpl">
<property name="entityManager" ref="sharedEntityManager"/>
</bean>
The 'entity-manager-factory-ref' attribute discriminates between different entitymanager factories but only for straight Spring Data Repositories (i.e. only for interfaces). It doesn't however concern itself with any of your implementations.
To sum it up
1) if you simply rely on standard Spring Data repositories with no custom implementation, use the "entity-manager-factory-ref" attribute to differentiate databases.
2a) Additionally, if you use any custom implementation, inject the appropriate EntityManager directly into the implementing class. Wirering is done under control of your spring xml configuration. For some reason I wasn't able to use the #Autowire annotation with a #Qualifier to reference the correct EntityManager. EDIT I just learned about the #Resource annotation
#Resource(name = "sharedEntityManagerA")
EntityManager entityManager
<bean id="sharedEntityManagerA" name="sharedEntityManagerA" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
<property name = "entityManagerFactory" ref="entityManagerFactory"/>
</bean>
With this at hand selecting what EntityMAnger should be used becomes straightforward. No need of plumbing everything togehther in your context xml.
2b) As an alternative to Spring's xml configuration for hooking up your stuff you may also go with
#PersistenceContext( unitName = "nameOfPersistenceUnit" )
to inject the correct EntitymanagerFactory
While 'nameOfPersistenceUnit' referes to your persistence sitting in your standard JPA persistence.xml
However 2b) doesn't go well with 'QueryDslRepositorySupport', since it expects an EntityManager instance. But I found that 'QueryDslRepositorySupport' doesn't offer much support anyway, so I removed it.

Related

Spring data inject repository without explicit type

I have a service that needs to use Neo4jRepository (regular repository provider by spring data).
public class SomeServiceBean<T>{
#Autowired
private Neo4jRepository<T,Long> Neo4jRepository;
}
This class will generate en error:
expected single matching bean but found 2: systemUserRepository,systemClaimRepository
The problem is that systemClaimRepository and systemUserRepository is extending Neo4jRepository<T,Long> as a bean without implementation.
Spring see systemClaimRepository and systemUserRepository as Neo4jRepository<T,Long> because they are extending it.
Is there anyway to inject Neo4jRepository<T,Long>?
Thanks
No how should this work?
You have two beans that match the interface and Spring does not know which implementation to inject.

Specifying JPA entity listeners separately being independent of its associated entity

Entity listeners are commonly placed over respective entity classes such as,
#Entity
#EntityListeners(EntityListener.class)
public class Entity implements Serializable {
//...
}
Applications may use one or more class libraries for sharing common functionalities across different projects/modules. In addition to the EE module, class libraries basically also require entities to be present on the compile-time class-path as a dependency i.e entities are present in both the places namely a class library and an EE module in an enterprise application. As such, the class EntityListener in the given example needs to be present on the compile-time class-path of a class library (it cannot only be added to the EE module).
If entity listeners were not to be tightly-coupled with respective entities and be specified separately then, there would be no need to add this dependency (listeners) to a class library i.e. entity listeners would then be present only in the EE project where EJBs are perfectly eligible for injection using #Inject.
Is there any possibility to separate this annotation #EntityListeners(EntityListener.class) from its associated entity so that it can be declared separately in a separate place? There should not be need to tightly couple this annotation with its respective entity.
Using GlassFish 4.1 having EclipseLink 2.6.0 (JPA 2.1).
This is required as there is a problem injecting EJBs into such entity listeners available in class libraries using the CDI specific artifact #Inject. EJBs could otherwise be injected by using #Inject into listeners, if the listeners were present in the EE project (module) only (but not in a class library).
Yes, you can define the default entity listener with xml.
One way to take the annotation #EntityListeners away from an entity is using both XML and annotation approaches together. Mixing and matching the XML descriptor and metadata annotations is perfectly valid and documented.
In order to override that annotation, one will have to register entity listeners in a file called orm.xml[1] as follows.
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm orm_2_1.xsd">
<entity class="com.example.entity.Entity">
<entity-listeners>
<entity-listener class="com.example.entity.listeners.EntityListener"/>
</entity-listeners>
</entity>
<!--Other listeners-->
</entity-mappings>
The corresponding listener class may then be left untouched with annotations as follows.
public class EntityListener {
#PostPersist
#PostUpdate
#PostRemove
public void onChange(Entity entity) {
// Do something with the entity.
}
}
Those callbacks may vary depending upon the functional requirement.
One may, if necessary, also define callbacks as XML elements avoiding callback annotations in the listener class such as,
<entity class="com.example.entity.Entity">
<entity-listeners>
<entity-listener class="com.example.entity.listeners.EntityListener">
<post-persist method-name="onChange"/>
<post-update method-name="onChange"/>
<post-remove method-name="onChange"/>
</entity-listener>
</entity-listeners>
</entity>
Those three annotations namely #PostPersist, #PostUpdate and #PostRemove in the listener class are now not required, since they are registered in the XML descriptor.
[1] IDEs like NetBeans do not seem to have wizard support for generating the orm.xml file. In NetBeans projects, one will need to create an XML file manually under src/conf (or any other custom configured location) so that the application builder can place that file under META-INF/orm.xml while building/deploying the application.

How to access Spring Data configured entity manager (factory) in custom implementation

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.

How to get the Job Instance of Long Running Jobs in Quartz?

I have created my own job class by extending the default class added couple of member variables and member methods. I saw the job gets triggered and is running for a very long time.
I just wanted to get the Job Instance not the JobDetail and wanted to invoke any member methods which has been defined by me or wanted to access the member variables.
Could you please let me know how we can achieve this?
Thanks,
Kathir
There is not such way, probably because quartz is meant to be compatible with a remote scheduling mode (i.e. cluster).
But if you are using it in a single server / application context, you could probably implement your own JobFactory (http://quartz-scheduler.org/api/2.1.5/org/quartz/simpl/SimpleJobFactory.html) that will just delegate to the super class the creation of the instance, and then register the instance somehow in a map or something else. Then you'll have to loop over the map keys to find the instance you are looking at.
Be careful of memory leaks with such a solution
Quick example:
In your spring configuration file:
<!-- quartz scheduler -->
<bean id="orchestration-api-quartz-factory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="configLocation" value="classpath:spring/quartz.properties"/>
<property name="jobFactory">
<bean class="service.scheduler.SpringServiceJobFactory"/>
</property>
</bean>
And the basic implementation of your Factory:
/**
* This job factory tries to locate the spring bean corresponding to the JobClass.
*
* #author Mathieu POUSSE
*/
public class SpringServiceJobFactory extends SpringBeanJobFactory implements JobFactory {
#Autowired
private ApplicationContext context;
/**
* {#inheritDoc}
*/
#Override
protected Object createJobInstance(final TriggerFiredBundle bundle)
throws Exception {
// create or get the bean instance
Object bean = this.context.getBean(bundle.getJobDetail().getJobClass());
// do what you want with the bean
// but remeber what you did, otherwise if you forget to forget
// you will have memory leaks !!!
// myConcurrentMap.put("job.key", bean);
return bean ;
}
}
HIH

JTA UserTransaction rollback does not work

I try to describe my environment shortly. Technologies: EJB 3.1, JSF, JBoss 7.1.1
There are Servise-classes (#SessionScoped #Stateful). Servise-classes call Dao classes (#Stateless)
I want :
use EntityManager only into #StateLess beans (Dao)
have short transaction in most cases (like persist, merge)
have one long transaction for some multistep-methods (methods are in Dao also)
have actual (up to date, without first-level cache) data
I have:
Pesistense.xml
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:jboss/datasources/MydataSource</jta-data-source>
<properties>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name="hibernate.dialect"value="org.hibernate.dialect.PostgreSQLDialect"/>
<property name="hibernate.transaction.manager_lookup_class"
value="org.hibernate.transaction.JBossTransactionManagerLookup"/>
<property name="hibernate.connection.autocommit" value="true"/>
<property name="hibernate.connection.characterEncoding" value="utf8"/>
<property name="hibernate.c3p0.min_size" value="5"/>
<property name="hibernate.c3p0.max_size" value="20"/>
<property name="hibernate.c3p0.timeout" value="1800"/>
<property name="hibernate.c3p0.max_statements" value="50"/>
</properties>
</persistence-unit>
Dao
#Stateless
#TransactionManagement(TransactionManagementType.BEAN)
public class UserDaoBean implements UserDAO, Serializable {
#PersistenceContext(name = "MyEntityManager")
private EntityManager em;
#Override
#Transactional
public void update(User user) throws Exception {
User tmpUser = getUser(user.getUser());
//some code, should be rollback, if it is an exception
em.persist(tmpUser);
}
Transaction interceptor
#Transactional
#Interceptor
public class TransactionInterceptor implements Serializable {
#Resource
private UserTransaction userTransaction;
#AroundInvoke
public Object verifyAccess(InvocationContext context) throws
Exception {
Object result = null;
try {
userTransaction.begin();
result = context.proceed();
userTransaction.commit();
} catch (Exception e) {
userTransaction.rollback();
throw new CustomRuntimeException(e.getMessage());
}
return result;
}
}
Problem:
If it is throw an Exception into Dao method, part data will save in DB instead of total rollback.
I think, is need Join Transaction to EM. Or disconnect persists each item to the DB right away (using cache).
I've try different ways, but didn't have success.
Thanks for in advance!
This like looks particularly problematic:
<property name="hibernate.connection.autocommit" value="true"/>
You shouldn't be doing any connection management at all in your persistence.xml file. The <jta-data-source> element and the notion of putting connection information in <properties> are mutually exclusive.
Either the JPA provider creates and manages connections (using properties) or it gets the connections from the container (using jta-data-source). Putting both in there will give you unpredictable results. If the JPA provider chooses to honor the connection properties you can quite easily shut off transaction management, connection pooling and more.
What you want is to configure all those things in the container and do not do any of that in the persistence unit declaration.
UPDATE
The combination of TransactionManagementType.BEAN (BMT) and UserTransaction should be fine. Note that you'll want to catch Throwable rather than Exception. As well the rollback() call can also throw exceptions which should be handled. Overall, though, this should produce the results you want.
Note carefully that while this looks to be nearly identical to what you get from TransactionManagementType.CONTAINER (CMT) and no interceptor, they do differ in one critical way:
Two CMT beans can share the same transaction
Two BMT beans can not share the same transaction.
This is because the container is required to suspend any transaction that might be in progress before invoking any bean using BMT. In that regard the term Bean-Managed Transaction is actually a bit of a misnomer as the container will always take action on any transactions in progress before invoking the BMT bean.
As such BMT and CMT are not on equal footing and it is actually impossible to implement some of the basic CMT features such as SUPPORTS or REQUIRED using BMT.