Spring - JPA - observe events - spring

I would like to observe when an entity is saved or deleted so that I may perform additional activities pertaining to that entity. I thought I did this in the past WITHOUT using the #EntityListeners annotation on the entity class itself because my entity listeners would be implemented in the service layer and NOT in the model / data layer.
The only other way I can think of to do it is inside the persistence.xml and specify my listeners there.
Are there any alternate approaches?

I did this a long time ago in a galaxy far, far away, and the answer was in my question.
The solution (that I wanted, but disliked because of using XML) was to:
write a generic entity listener using annotations, and get a programmatic instance of the bean manager (CDI), or equivalent in spring, then fire an event which I can process either via CDI or spring
where I want that listener to work, place a persistence.xml file and manually specify the entity-listeners there
if I want to do anything special, I simply observe the event that I'm interested in and I get the information that I want.

Related

Sending rabbitMQ events after transaction commit

I have big task in transaction (#Transactional method). In this task the id-s are collected and then after transaction commit they must be sent to RabbitMQ (with convertAndSend-method). The RabbitMQ-listener in the other side takes the ids and updates the statuses in DB (it's important to update statuses after transaction changes because only after them the updated data is actual)
I have next questions:
What is the best way to use like the hook in the end (commit) of transaction? I need make the one "afterCommit" method for several service classes (many transactional-methods);
What need I use as the storage of ids? I have thought about smth like ThreadLocal variable but this is not a variant - if there is the parallelStream, the new Thread is created;
May be some other solution?
I have read about the delay RabbitMQ plugin but it is not the variant 4 my task - their time is very different.
Looking at the tags in your question I suppose you are using the spring framework.
So you could use Spring Events and its ApplicationEventPublisher to publish your specific ApplicationEvent together with all the necessary data (the ids in your case).
Spring allows you to bind an event listener to a phase of the current transaction. Just use the #TransactionalEventListener annotation on a method that sends the data to RabbitMQ finally. Binding is possible to different transaction phases. With the default binding (AFTER_COMMIT) the event will only be fired if the transaction has completed successfully.
This Baeldung article on Spring Events is a nice place to find more detailed information.

SDN4 - Entity lifecycle event handlers compatible with GraphRepository

I am using Spring Data Neo4j 4.0.0.RELEASE and would like to take advantage of the built-in data manipulation events to insert some audit information on the fly (e.g. timestamps). The documentation seems to suggest that this is only available to me if I am directly using Neo4jTemplate.
Are there any similar hooks available for the GraphRepository abstraction? That is, is there an out of box way for me to hook into graph repository operations (a la Spring DataJPA?) I've written some tests and can confirm that the documented events don't fire when I'm just using the GraphRepository.
AbstractGraphRepository is from the 3.x codebase, so is not directly relevant here.
As noted, SDN 4 does not yet provide automatic support for Spring's RepositoryEventListener interfaces. Implementing event listeners correctly in SDN 4.0 is complicated because of the nature of the underlying save mechanism, which persists an entire tree of "dirty" objects rather than just a single top-level entity. If the object you want to intercept is not the top-level entity being saved, the event listener for it won't fire.
The SDN development team is currently considering the best way to enable event handlers to fire for objects that may be persisted at any depth in the save tree.
In the meantime, the solution suggested by simonl should work.

spring-boot-jpa Initial Entity Persistence

I'm trying to figure out how, in the lifecycle of a Spring Boot application, to conditionally persist a single entity when the application starts up. The normal method of loading initial data via 'import.sql' or similar methods is no good in this use case, because the insert is conditional. On start up, I'd like for my application to check and see if an admin account and the associated admin role exists. If neither exists, I'd like the application to create them. If they do exist, I'd like the application to do nothing and leave the existing entities alone. If I use the import.sql method, I'll either wind up with a duplicate key (username=admin) or I'll overwrite the existing admin account, which may have had it's password changed away from the default password by a previous installation of the application.
I've tried using ApplicationListeners for all the default Spring and Spring Boot events, and I get null pointer exceptions for every one of those listeners because the JPA repositories are not yet initialized. I thought that listeners invoked for the ContextRefreshedEvent were supposed to be called after all beans and such are initialized, but I guess I'm wrong about that. I've also tried to create a bean which has a #PostConstruct annotated method which does this entity creation, however I had the same result with the JPA CrudRepositories not being initialized.
So my base question is; "What is the preferred entry point for doing initialization work with JPA CrudRepositories during Spring Boot application start up?"
ContextRefreshedEvent would normally work (so you may have an initialization ordering problem with your listener). You can also use SmartInitializingSingleton or a SmartLifecycle with autostart=true. In a Spring Boot app you also have CommandLineRunner.

Dynamically creating generic services around Data Repositories in Spring 3.1

I've gotten the basics of Spring more or less down (I think) and I'm trying out new things. Currently, I'm trying to figure out a way not to have explicitly write a service class for each entity/repository if that service is just going to be extending a generic service class.
What I'd like to be able to do is, after the Entity and Repository beans are loaded, loop through them, check to see if a bean named [Model Name]Service exists and, if it does not, create a new instance of my generic service class, pass in the Repository object, and then register this service in the applicationContext.
Is this possible and if so, what is the best way to do it? I've been trying to figure out the PostProcessors, but the one that I think would actual work (BeanPostProcessor) doesn't seem like the appropriate place to do this.
Thanks for your time

spring + struts2, inject DAO into external thread

I have a web application that uses Struts2 + Spring for the resource injection, basically my DAO. Now I would like to create a thread that periodically polls the database and, if needed, send email notifications to users.
I would like to know how I can implement this in a way that this thread can use my DAO. I haven't been able to manage Spring to inject it the way I've done it. So I would like to hear suggestions and see if someone can point me to the right way.
Right now I have a thread started by a ServletContextListener, that just creates a timer and schedules an action every 5 minutes. But I can't get this action to use my DAO. I don't have any need to use this structure, I'm open to using whichever solution works.
Thanks for your help!
Edit: As axtavt suggested, I used Spring task Execution Scheduling and it works perfectly, the thing is that my task gets injected with the DAO but then I get LazyInitializationException every time I try to access a property of my fetched objects, any suggestion on how to solve that??
Perhaps the best option is to use Spring's own scheduling support, see 25. Task Execution and Scheduling (if necessary - with Quartz, see 25.6 Using the OpenSymphony Quartz Scheduler). This apporach allows you to configure your scheduled action as Spring beans, so you can wire them with other beans such as DAO.
Alternatively, you can use the following to obtain any Spring bean in web application (for example, to obtain DAO from your thread):
WebApplicationContextUtils.getWebApplicationContext(servletContext).getBean(...)

Resources