Spring and scheduled/repeated task - spring

I'm using Spring and have created a web application. In my web app I've a rest service. I have one rest method called process which takes in a user's details (from an angular ui) and saves the users details to a database (SQLite)
Basically what I want to do is that when a user initiates a rest call. I want to start a separate thread (of only which one will exist). This thread will poll a database for certain values and emails an administrator if certain values are found. I need the class to be thread safe. See the below. Am I correct in using something like this ?. Do I need an #Async annotation ? Or should i use a TimerTask instead ?
#EnableScheduling
public class DBPoller {
#Scheduled(fixedRate = 5000)
public void checkDatabase() {
//checks the db for certain values
}
}

You must write
#EnableScheduling
in the Main Class of the Application
and the DBPoller class must be an Component of the Spring Framework.
So you must add the Annotation #Component (or #Service) to the Head of the DBPoller Class

It sounds like you do want to use an #Async annotation. #Scheduled won't really achieve the effect you are trying to achieve. #Scheduled would work if you were trying to run this check/email scenario on fixed time intervals, rather than on user request. Luckily the config for both is the same.
<task:annotation-driven scheduler="scheduler"
executor="asyncMethodTaskExecutor" />
<task:scheduler id="scheduler" pool-size="x" />
<bean id="asyncMethodTaskExecutor"
class="org.springframework.scheduling.quartz.SimpleThreadPoolTaskExecutor">
<property name="threadCount" value="y"/>
<property name="threadNamePrefix" value="AsyncMethodWorkerThread"/>
</bean>
If you have the #EnableScheduling annotation, you don't need to define <task:scheduler id="scheduler" pool-size="x" />, but personally I prefer the XML configuration because if you want to change your thread pool size you only have to edit the XML values and restart your application, not recompile and redeploy the whole thing.
Make sure you change x and y to suitable values. This will depend on how many concurrent users you may have on your system.
You also need to make sure that your class is discoverable to the Spring context, and that this method is implementing an interface so that Spring can generate a proxy of it to actually invoke asynchronously like the below example
public interface AsyncService {
public void checkDatabase();
}
#Service
public class AsyncServiceImpl implements AsyncService {
#Override
#Async
public void checkDatabase(){
//Do your database check here.
}
}
You also need to make sure that the package your service is in can be found by Spring, double check your <context:component-scan> value.
Happy asynchronous execution.

Related

Hibernate interceptor or listener with Spring Boot and Spring Data JPA

I'd like to run some checks prior to saving a collection of children of an object (cascade = all).
I am using Spring Boot and Spring Data JPA and was wondering what approach would be the best: a Hibernate listener or an interceptor. What are the pros/cons of each ? Do you happen to have an example for the one you consider the best approach ?
I have used Hibernate listeners before configured in XML like this:
<property name="eventListeners">
<map>
<entry key="post-update">
<list>
<ref bean="myListener" />
</list>
</entry>
</map>
</property>
on the session factory (older project). But now most of my configs are in annotations (cause Spring Boot) and I want to keep the configs as simple and light as possible, so maybe an interceptor would be a better solution.
Thank you.
I did a lot of looking around on this for myself and thought I'd share what I got working (I included the helpful (non-inline) links at the bottom).
Interceptor
To use an interceptor, you extend the org.hibernate.EmptyInterceptor class and override the methods you want to intercept.
You probably want onSave(...) in your case.
package foo.bar;
import org.hibernate.EmptyInterceptor;
import org.hibernate.type.Type;
import java.io.Serializable;
public class MyInterceptor extends EmptyInterceptor {
#Override
public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
// do your checks here
return false;
}
}
You have to register your interceptor with Spring/Hibernate.
You can do this in your application.properties or application.yml.
spring:
jpa:
properties:
hibernate.ejb.interceptor: foo.bar.MyInterceptor
The upsides to an interceptor are that it is (potentially) less code and relatively simple configuration.
The downsides are that you can only have one for your entire application and the API can be confusing to work with.
Event Listener
For events, you implement one of Hibernate's org.hibernate.event.spi.*Listener interfaces.
You probably want the org.hibernate.event.spi.PreInsertEventListener in your case.
You have to register your event in the EventListenerRegistry.
To do this, you can make your class a #Component, #Autowire the EntityManagerFactory into your class, and create a #PostConstruct method to register your class.
package foo.bar;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventType;
import org.hibernate.event.spi.PreInsertEvent;
import org.hibernate.event.spi.PreInsertEventListener;
import org.hibernate.internal.SessionFactoryImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.persistence.EntityManagerFactory;
#Component
public class MyEventListener implements PreInsertEventListener {
#Autowired
private EntityManagerFactory entityManagerFactory;
#PostConstruct
private void init() {
SessionFactoryImpl sessionFactory = entityManagerFactory.unwrap(SessionFactoryImpl.class);
EventListenerRegistry registry = sessionFactory.getServiceRegistry().getService(EventListenerRegistry.class);
registry.getEventListenerGroup(EventType.PRE_INSERT).appendListener(this);
}
#Override
public boolean onPreInsert(PreInsertEvent preInsertEvent) {
// do your checks here
return false;
}
}
The upsides to listeners are that you can have as many as you want, the API is nicer than the interceptor's, and the code and the configuration are all in one place.
The downside is that the configuration is longer and more involved.
https://docs.jboss.org/hibernate/orm/3.5/reference/en-US/html/events.html
How to use Spring managed Hibernate interceptors in Spring Boot?
https://dzone.com/articles/spring-managed-hibernate-event-listeners
Hello,
First of all you can check the: https://www.baeldung.com/database-auditing-jpa where every options is explained in detail.
I would personally recommend Hibernate Interceptor, easy to use and understand. Depending on the complexity of the project, in most cases it will do.
In order to configure this in your application you simply need to add: spring.jpa.properties.hibernate.ejb.interceptor = path.to.interceptor (in application.properties). The interceptor itself should be #Component.
As long as the interceptor doesn't actually use any beans. Otherwise it is a bit more complicated but I would be more than happy to offer the solution.
Don't forget to add in application-test.properties, an EmptyInterceptor to not use the logging system (or whatever you want to use it for) in tests (which wouldn't be very helpful).
Hope this was of use to you.
As a final note: always update your Spring / Hibernate versions (use the latest as possible) and you will see that most code will become redundant as newer versions try to reduce the configurations as much as possible.

Testing methods in #Component class having #PostConstruct anotation

I am testing service methods that are placed in controllers in spring applications. It seems to me that my problem is that one essential service method call is done in class which is anotated #Component and the method call is inside #PostConstruct anotated method.
#Component
public final class Helper
#PostConstruct
public void initialize() {
stuff = service.getNessesaryStuff();
}
The contents of the stuff are coming from a database and they vary in each test. That's why database is populated with needed data before each test. Without the data the other service methods are not working. I have checked that the right data goes to database exactly like intended, but it does not affect right away. I need to run same test couple of times before it gets the right data and passes.
Any fix?
When running the application, Helper class is created itself. When running tests, I need to make a bean of it to avoid NullPointerExceptions.

Migrating from Spring configuration from XML file to Annotation

<prop key="load*">PROPAGATION_REQUIRED, readOnly</prop>
Here the key="load*" uses wildcard "*". It matches every function that starts with load right? My question is that; how am I going to implement this using annotation based configuration without placing it on every function?
#Transactional(readOnly = true, propagation= Propagation.REQUIRED)
Is there anyway I can do this without putting this on top of every function which it's name starts with "load"?
Cheers
You can use aspects for this purpose. I.e. define an aspect which intercepts all methods named as "load*" and ensure transaction is started. However in my opinion, such approach is a bad one since it makes your code hard to unit test, understand and maintain further. In fact #Transactional handling is done using aspects, so why bothering to add another layer of abstraction to this? With this annotation someone will look to your code and immediately know that method is/should be running in transaction. Hiding this will make others life harder.
If you still want to implement it, here is small example. NOTE, that I didn't test this at all, just an idea demonstration.
#Aspect
public class MyInterceptor
{
#Around("execution(* load*(..))")
#Transactional
public Object makeMeTransactional(ProceedingJoinPoint pjp)
{
return pjp.proceed();
}
}

Hibernate 4 + Spring 3.2 + Transaction : One Service, Several Dao , One Method

I'm a beginner in hibernate 4 & Spring 3.2 stuffs.
I have read some tutorials and discussion on stack but i don't find a clear answer to my questions. And i think the best way to understand is to ask and share knowledges !
Here we go!
So you create each time a Pojo, a Dao , a Service class, with methods annotated transactionnal. That's ok. I'm using Sessionfactory to handle my transaction. I'm looking for good practices.
1- If you want to use Delete Method and Save Method from the same Service, how will you do to make it works in a same transaction. When i look at the log, each method are executed in different transactions.
This SampleServiceImpl:
#Transactional
public void save(Sample sample){
sampleDao.save(sample);
}
#Transactional
public void delete(Sample sample){
sampleDao.delete(sample);
}
// A solution could be that , but not very clean...there should be an another way, no?
#Transactional
public void action(Sample sample){
sampleDao.save(sample);
sampleDao.delete(sample);
}
2- If you want to use Delete Method and Save Method from different Services class, how will you do to make it works in a same transaction. Because each method in each service class is handled by a Transactionnal annotation. Do you create a global Service calling all subservice in one method annoted Transactional
SampleServiceImpl:
#Transactional
public void save(Sample sample){
sampleDao.save(sample);
}
ParcicipantServiceImpl
#Transactional
public void save(Participant participant){
participantDao.save(participant);
}
// A solution could be that , but not very clean...there should be an another way, no?
GlobalServiceImpl
#Transactional
public void save(Participant participant,Sample sample){
participantDao.save(participant);
sampleDao.save(sample);
}
3- And the last question but not the least .If you want to use several Methods from severals service in one global transaction. Imagine you want to fill up 5 or more table in one execution of a standalone program. How is it possible because each Service to have his proper transactional method, so each time you called this method, there is a transaction.
a- I have successfully arrive to fill up two tables in a sample transaction using Mkyong tutorial and cascade property in the mapping. So i see how to make it works for one table directly joined to one another or more tables.
b- But if you have a 3 tables Participant -> Samples -> Derived Products. How will you fill up the three tables in a same transaction.
I don't know if i'm clear. But i would appreciated some help or example on that from advanced users.
Thanks a lot for you time.
Your solution is fine, maybe this works if you want to using nested transactional methods(note I saw this solution couple days ago and didn't test it):
< tx:annotation-driven mode="aspectj" / >
< context:load-time-weaver aspectj-weaving="on"/ >
#Transactional
public void action(Sample sample){
save(sample);
delete(sample);
}
Transaction should propagate.
GlobalServiceImpl
#Transactional
public void save(Participant participant,Sample sample){
participantDao.save(participant);
sampleServiceImpl.save(sample);
}
The approch you are following is cleaner approch,
ServiceOpjects are ment to contain business logic. Hence they will always manuplate through data objects.
What we do in practise is create a another layer that uses dataObjects and and other functional call of same layer. Then this all business layer is called via service layer having annotation #transactional.
Can you please mention why you think this approch is dirty??

Apply dynamic properties to a bean at runtime

Assume I have a bean DialogBox, with properties for height and width:
public class DialogBox {
int x;
int y;
...
}
In my applicationContext.xml I would define properties as reasonable defaults:
<bean id="dialogbox" class="DialogBox">
<property name="x" value="100"/>
<property name="y" value="100"/>
</bean>
We have multiple clients that use the dialogBox bean, and each wants a custom value for x and y. One route we have discusses is having multiple properties files, one for each client, and have the client id map to the proper file, for example client 123 would map to dialogbox_123.properties:
dialogbox_123.properties:
x=200
y=400
Then at runtime when the bean is requested, spring would look to see if a custom properties file exists for the client, and use those properties, otherwise use the defaults. I am aware of the PropertyOverrideConfigurer, but AFAIK this only works when the context is started so will not work for our purposes. Is there an existing facility in spring to achieve this, or can someone recommend another way?
Use FactoryBean (as already suggested) to customize instantiation.
set scope="prototype" on the bean, so that each time an instance is required, a new one should be created.
In case you want to inject the prototype bean into a singleton bean, use lookup-method (Search for lookup-method here)
I'm not sure if this would fit your case though. Another suggestion would be:
In #PostConstruct methods of your various "clients" set the properties as desired on the already injected dialog window. Like:
public class MyDialogClient {
#Autowired
private Dialog dialog;
#PostConstruct
public void init() {
dialog.setWidth(150); //or read from properties file
dialog.setHeight(200);
}
...
}
Again, in this case, you can play with the scope atrribute.
Take a look at the Spring OSGi Compendium services, they've got a property manager called "managed-properties", which allows you not only to update the properties at runtime, but while the application is running if you select the "container-managed" update strategy.
If I understood the question, you can use a FactoryBean to customize bean creation logic in Spring.

Resources