Spel Expressions | #CacheEvict | applicationContext - spring

I am using caching annotations of Spring. I want to pass name of Cache [#CacheEvict(name="vendorCache")] from applicationContextfile or it can be configured in any other way.
Now i have scenario in which i have two classes VendorDAo and NetworkDao.
public VenderDAO
{
#CacheEvict(name="vendorCache")
public String insert():void
{
//code to add the record into the table using ibatis
}
}
public NetworkDao
{
#CacheEvict(name="netWorkCache")
public String insert():void
{
//code to add the record into the table using ibatis
}
}
Now i have few more methods but the only difference is that #CacheEvict.
Is there any way such that i can declare cache name in the configuration file and pass to bean as property.
<bean id="venderDAO" class="VenderDAO">
<property name="cachename" value="vendorCache"/>
</bean>
<bean id="netWorkDAO" class="VenderDAO">
<property name="cachename" value="netWorkCache"/>
</bean>
[Note: both the beans have the same class name]
and can use this in java file Or there is any other way.
Any pointers will be highly appreciated.
Regards
Raj

Spring cache abstraction is only available through annotations (#Cacheable and #CacheEvict) on methods you need to cache. You cannot use XML declaration. 27. Cache Abstraction

Related

Convert XML bean definition with parent to Java with annotations

I have an application using a framework that provides certain Spring beans via XML files in the framework. The configuration of my application is currently done partly in XML but mostly with Spring annotations.
Some of the XML bean definitions have parents referring to beans supplied by the framework, e.g.
<bean id="MyBean" parent="FrameworkBean">
<property name="context">
<map merge="true">
<entry key="SomeKey" value-ref="SomeValue" />
</map>
</property>
</bean>
FramwworkBean is defined in an XML file in the framework. There is a chain of bean inheritance. At each step some entries are added to the context:
<bean id="FrameworkBean" parent="AbstractBean">
<map merge="true">...
<bean id="AbstractBean" abstract="true" class="ClassWithContext"/>
I understand the result of all this is construction of a ClassWithContext
instance with a map containing all the entries up the chain.
Is it possible to write Java code to do the same, without duplicating code from the framework XML files?
#Bean("MyBean") ClassWithContext myBean() {
return ??? // code that uses "FrameworkBean" somehow
}
The XML bean definition has no dependency on the type of AbstractBean.
If MyBean can be created by Java code, can that code be written to be equally type-agnostic? Or should I just leave this in XML?
If your "FrameworkBean" is not abstract bean you can try the following:
#Bean
public SomeType myBean(#Qualifier("FrameworkBean") FrameworkBeanType frameworkBean) {
SomeType type = getSomeType();
type.setFrameworkBean(frameworkBean);
return type;
}

How JpaPagingItemReader works?

I'm trying to implement a reader java class: UserReader extends JpaPagingItemReader
this reader should execute a query String: "query_string" and return the result to the processor.
I've searched in the net and I couldn't understand how JpaPagingItemReader works?
normally I shoud find something like this:
package com.UserReader;
public class UserReader extends JpaPagingItemReader<User> {
#Override
public User read()
{
read();
}
}
<bean id="userReader"
class="com.userReader">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="queryString"
value="myQuery" />
</bean>
...step declaration reader="userReader"
But actually, I found the same java class, but with a non understable xml config (no reference to com.UserReader in spring beans but a bean with class : org.spring...jpaPagingItemReader and id: userReader), how spring batch knows that jpaPagingItemReader refers to the com.userReader class (we suppose that we can have many readers)? is it by the id of the bean?

Spring transaction propogation on non spring managed beans

I am working on a migration project which involves upgrading the platform to Spring 4 with MyBatis. In the legacy code, transactions are handled at a central locations wherein call to start/end transactions are spread across various classes like service class, helper class and DAO class.
I managed to convert all service classes to spring managed component and DAO classes to support MyBatis-spring API. Problem is my service class use several other classes to perform a function and those classes are all instantiated manually and used. Now if i start a transaction on service class methods and perform database transactions inside other helper or DAO classes which are not spring managed, my transaction handling doesn't work correctly. I have illustrated this problem in the below code. Could you tell what are the ways to acheive transaction handling without modifying the code?
Example :
package com.service;
#Service
class MyService {
#Transactional( propagation=Propagation.REQUIRED)
public void processRequest () {
HelperClass helper = new HelperClass();
helper.performOperation();
}
}
package com.helper;
// this class is not spring bean
class HelperClass {
// MyBatis mapper class
private EmployeeMapper mapper;
public HelperClass () {
mapper = // retrieve mapper class bean from spring context
}
public performOperation () {
// call to mapper class insert operation
// call to mapper class update operation
}
}
package com.dao;
#Component
interface EmployeeMapper {
// method definition to perform database operation
}
Spring configuration details:
<context:component-scan base-package="com" />
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
....
....
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" mode="aspectj" />
<mybatis:scan base-package="com.dao" />
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mapperLocations"
value="classpath*:mybatis/*.xml" />
</bean>
In the above code HelperClass.performOperation() method is doing 2 database operations (insert,update). Say if insert succeeds and update fails, my database transaction doesn't get rollback. Since I already started the transaction at MyService.processRequest() should this not rollback the operations that are carried inside that method call? Correct me if my understanding is wrong.

how to load spring properties without injection or inject a bundle or something?

I currently load my properties file like so in spring
<context:property-placeholder location="test-esb-project-config.properties"/>
<context:property-placeholder location="esb-project-config.properties"/>
This seems to work great for properties use inside the xml files. How do I load a property from inside my java code now though? OR how do I inject some kind of Bundle or Config object so I don't have to inject 10 properties in one bean?
thanks,
Dean
using annotations #Value(${property}) worked much better and it injected the property into my bean without all the work of xml typing and adding a setter...way too much work going that route.
You can either have setters for each property and wire them with the property reference.
public class MyBean{
public void setFoo(String foo){ /* etc */}
public void setBar(String bar){ /* etc */}
}
<bean class="foo.bar.MyBean">
<property name="foo" value="${my.properties.foo}" />
<property name="bar" value="${my.properties.bar}" />
</bean>
Or you can inject a Properties Object into your Spring Bean.
public class MyBean{
public void setProperties(Properties properties){
// init your properties here
}
}
<bean class="foo.bar.MyBean">
<property name="properties" value="classpath:/path.to.properties" />
</bean>
Both of these would also work without XML when using the #Value annotation.
(see Expression Language > Annotation-based Configuration)

Ability to switch Persistence Unit dynamically within the application (JPA)

My application data access layer is built using Spring and EclipseLink and I am currently trying to implement the following feature - Ability to switch the current/active persistence unit dynamically for a user. I tried various options and finally ended up doing the following.
In the persistence.xml, declare multiple PUs. Create a class with as many EntityManagerFactory attributes as there are PUs defined. This will act as a factory and return the appropriate EntityManager based on my logic
public class MyEntityManagerFactory {
#PersistenceUnit(unitName="PU_1")
private EntityManagerFactory emf1;
#PersistenceUnit(unitName="PU_2")
private EntityManagerFactory emf2;
public EntityManager getEntityManager(int releaseId) {
// Logic goes here to return the appropriate entityManeger
}
}
My spring-beans xml looks like this..
<!-- First persistence unit -->
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="emFactory1">
<property name="persistenceUnitName" value="PU_1" />
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager1">
<property name="entityManagerFactory" ref="emFactory1"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager1"/>
The above section is repeated for the second PU (with names like emFactory2, transactionManager2 etc).
I am a JPA newbie and I know that this is not the best solution. I appreciate any assistance in implementing this requirement in a better/elegant way!
Thanks!
First of all thanks to user332768 and bert. I tried using AbstractRoutingDataSource as mentioned in the link provided by bert, but got lost trying to hook up my jpa layer (eclipselink). I reverted to my older approach with some modifications. The solution looks cleaner (IMHO) and is working fine. (switching database at runtime and also writing to multiple databases in the same transaction)
public class MyEntityManagerFactoryImpl implements MyEntityManagerFactory, ApplicationContextAware {
private HashMap<String, EntityManagerFactory> emFactoryMap;
public EntityManager getEntityManager(String releaseId) {
return SharedEntityManagerCreator.createSharedEntityManager(emFactoryMap.get(releaseName));
}
#Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
Map<String, LocalContainerEntityManagerFactoryBean> emMap = applicationContext.getBeansOfType(LocalContainerEntityManagerFactoryBean.class);
Set<String> keys = emMap.keySet();
EntityManagerFactory entityManagerFactory = null;
String releaseId = null;
emFactoryMap = new HashMap<String, EntityManagerFactory>();
for (String key:keys) {
releaseId = key.split("_")[1];
entityManagerFactory = emMap.get(key).getObject();
emFactoryMap.put(releaseId, entityManagerFactory);
}
}
}
I now inject my DAO's with an instance (singleton) of MyEntityManagerFactoryImpl. The dao will then simply call createSharedEntityManager with the required release and will get the correct EntityManager for that database. (Note that i am now using application managed EntityManager and hence i have to explicitly close them in my dao)
I also moved to jta transaction manager (to manage transaction across multiple databases)
This is how my spring xml looks like now.
...
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="em_Rel1">
<property name="persistenceUnitName" value="PU1" />
</bean>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="em_Rel2">
<property name="persistenceUnitName" value="PU2" />
</bean>
<bean class="org.springframework.transaction.jta.JtaTransactionManager" id="jtaTransactionManager">
</bean>
<tx:annotation-driven transaction-manager="jtaTransactionManager"/>
....
Cheers! (comments are welcome)
I am not sure if this is a clean method. Instead of declaring the enitiymanagerfactory multiple times, we can use the spring application context to get the entitymanagerfactory declared in the spring application.xml.
hm = applicationContext.getBeansOfType(org.springframework.orm.jpa.LocalEntityManagerFactoryBean.class);
EntityManagerFactory emf = ((org.springframework.orm.jpa.LocalEntityManagerFactoryBean) hm.get("&emf1")).getNativeEntityManagerFactory();
EntityManagerFactory emf2 = ((org.springframework.orm.jpa.LocalEntityManagerFactoryBean) hm.get("&emf2")).getNativeEntityManagerFactory();
This is something i need to do in the future too, for this i have bookmarked Spring DynamicDatasourceRouting
http://blog.springsource.com/2007/01/23/dynamic-datasource-routing/
As far as i understand, this is using one PU, which gets assigned different DataSources. Perhaps it is helpful.

Resources