Declarative (Annotation-based) Caching Solution for Java - java

Besides Spring 3.1 and ehcache-spring-annotations, do we have other alternatives that are other than EhCache and Spring?

Have you looked at Spring-AOP based solutions? You can create an auto-proxy object in your Spring applicationContext using the org.springframework.aop.support.RegexpMethodPointcutAdvisor and then make an object that implements AfterReturningAdvice, ThrowsAdvice and MethodBeforeAdvice.
Use that object to monitor function calls and exits and cache what information you want.
<bean name="cacheHandler" class="org.yourname.CachingInterceptor" />
<bean id="cacheAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice" ref="cacheHandler" />
<property name="pattern" value="org.yourname.regex.of.stuff.you.want.cached.*" />
</bean>
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />

Related

Spring batch - overriding jobrepository in context.xml

Like described in the linked article below, with Java configuration it is possible to override the JobRepository bean by extending DefaultBatchConfigurer and overriding createJobRepository.
How can this be achieved in a context.xml file where the jobrepository bean is defined like this
<bean id="jobRepository_new"
class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
<property name="databaseType" value="Oracle" />
<property name="dataSource" ref="dataSource-batch" />
<property name="transactionManager" ref="transactionManager" />
<property name="tablePrefix" value="BATCH_" />
<property name="lobHandler" ref="oracleLobHandler" />
</bean>
?
Can't serialize access for this transaction when running single job, SERIALIZED isolation level
Unlike with the Java configuration style, there is nothing provided by default (that you can override) when you use the XML configuration style.
So you just need configure the job repository bean as needed like shown in the snippet you shared.

Custom function for Spring ApplicationContext

I'm heavily using Spring to develop an application and I was wondering if there's a way to register custom method which can be used when a bean is defined. Currently I'm using ClassPathXmlApplicationContext to load the bean definitions from a XLM file, then in the XML file I would like to do something like
<bean id="bean1" class="..." scope="prototype"
p:some_property='"hello" + #getCorrelativeNumber()/>
Here some_property should then be evaluated to hello0. I know I can register custom functions using StandardEvaluationContext of SpEL, however I can't figure how to make that work in the context of the ApplicationContext.
Any help is greatly appreciated.
Please refer to this blog, look at the section which shows to create an application context in which expressions are used to inject values
<bean id="engine" class="com.baeldung.spring.spel.Engine">
<property name="capacity" value="3200"/>
<property name="horsePower" value="250"/>
<property name="numberOfCylinders" value="6"/>
</bean>
<bean id="someCar" class="com.baeldung.spring.spel.Car">
<property name="make" value="Some make"/>
<property name="model" value="Some model"/>
<property name="engine" value="#{engine}"/>
<property name="horsePower" value="#{engine.horsePower}"/>
</bean>

Migrating from EJB with Spring to POJO

While migrating from EJB with spring to POJO , I read every where that just changing this configuration will work :
<bean id="sapFeedBean" class="org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean" lazy-init="true">
<property name="jndiName" value="ejb/sapBean" />
<property name="resourceRef" value="false" />
<property name="businessInterface" value="com.aa.inflightsales.sap.SapBusiness" />
<property name="lookupHomeOnStartup" value="false" />
</bean>
but how to do this , I am trying to create bean of the POJO class , but how can I define the business interface , as interface injection is not supported by spring.
Just define the business methods in this interface which should be implemented by the business class and when you need it just use a reference to the interface with the convenient annotation and the framework will inject the implementation.

Setting annotation based SpyMemcached configuration in spring mvc

I am new to spring framework. I want to use spy memcached in my application, but i cant find the proper annotation based configuration to set the bean. Currently i am using Memcached static object in my Controller which looks really bad programming. Please provide a simple way to implement memcache in spring configuration. just on default values of memcached "127.0.0.1:11211". Thank you.
edit.
how to convert this xml cinfiguration into proper annitation based config and what to Autowire in cintroller..
<bean name="defaultMemcachedClient" class="com.google.code.ssm.CacheFactory">
<property name="cacheClientFactory">
<bean name="cacheClientFactory" class="com.google.code.ssm.providers.spymemcached.Mem
</property>
<property name="addressProvider">
<bean class="com.google.code.ssm.config.DefaultAddressProvider">
<property name="address" value="127.0.0.1:11211" />
</bean>
</property>
<property name="configuration">
<bean class="com.google.code.ssm.providers.CacheConfiguration">
<property name="consistentHashing" value="true" />
</bean>
</property>
</bean>
Take a look at Simple Spring Memcached (SSM) library.
It provides integration to memcached (via spymemcached or xmemcached client) using:
Spring Cache annotations (#Cacheable)
custom annotations (like ReadThroughSingleCache).

Using a DAO on a Bean used by a Spring Scheduled Task

I'm developing a web application using Struts2 + Spring, and now I'm trying to add a scheduled task. I'm using Spring's task scheduling to do so. In my applicationContext I have:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
...
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="MYSQL" />
</bean>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
And then I have my DAO that uses this entityManagerFactory:
<bean id="dao" class="data.GenericDAO" />
So this works flawlessly within the web application. But now I have a problem when creating the scheduled task:
<task:scheduled-tasks scheduler="notifier">
<task:scheduled ref="emailService" method="sendMail" fixed-rate="30000" />
</task:scheduled-tasks>
<task:scheduler id="notifier" pool-size="10" />
<bean id="emailService" class="services.emailService" >
<property name="dao" ref="dao" />
</bean>
This executes the method sendMail on my emailService class every 30 seconds. And my emailService has the DAO injected correctly. The thing is that I can fetch objects with my DAO using the findById named queries, but when I try to access any property mapped by Hibernate, such as related collections or entities, I get an "LazyInitializationException: could not initialize proxy - no Session ". I don't know what's wrong, since I believe the scheduled task is being managed by Spring, so it should have no problem using a Spring managed DAO. I must say that I'm using the openSessionInView filter on my struts actions, so maybe I need something similar for this scheduled task.
Any help or suggestion will be appreciated, thanks!
Edit: Finally I found a way to fix this. I changed my regular Dao with one where I can decide when to start and commit the transaction. So before doing anything I start a transaction and then everything works OK. So I still don't know exactly what causes the problem and if someday I'll be able to use my regular DAO, for the moment I'm staying with this solution.
OpenSessionInView won't help you, because you don't have a web context. You need Spring's Declarative Transaction Management.
In most cases, what you need to do is just this XML:
<!-- JPA, not hibernate -->
<bean id="myTxManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven transaction-manager="myTxManager" />
<!-- without backing interfaces you probably also need this: -->
<aop:config proxy-target-class="true">
(Annotate your EmailService class as #Transactional to enable this)

Categories