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.
Related
In ASP.NET the default lifecycle of objects created in IoC container is per web request. While learning SpringBoot + Webflux, I found that the default lifecycle (Bean, Repository, Service, etc) created by the IoC container is singleton. I know I can change the default scope like this:
#Scope("prototype")
but I have not yet found an example where it would be used. So if IoC creates all object as singletons, how come there are no problems with concurrency. Can someone please explain this to me.
It's a good question. Generally speaking where concurrency is an issue, for example a transaction context in the database layer, springbook uses a thread based locking mechanism. See for example 1.2. Understanding the Spring Framework Transaction Abstraction. Otherwise, yes, anything injected with CDI is a singleton unless specifically annotated otherwise. That means that you should not keep state variables in your #Component or #Service classes. As long as the methods use only parameters passed in or variable local to the method concurrency isn't an issue because ever variable is created on the stack which is unique for each call. I have seen an application work great up until the day two people log in at once.
If you have to have a class with state variables you need to do a new of that class.
Each spring-context is created with a unique thread, so where objects are created or injected that are not stateless then state information is attached to the spring-context which runs in its own thread.
See also How does Spring bean Handle concurrency
How to run a method in Spring Boot when the value of concrete database field changed or it reached a certain level (programmatically)? The user wants to choose which field the method will respond to. Is there any common solution or best practice in Spring Boot?
I think what you are looking is reload a bean when the properties which are loading from db is changed. you can use something similar here in this stackoverflow post with ApplicationContextAware in prototype scope.
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.
I migrated a simple CRUD application developed in Java using OSGi to Grails using Spring. I converted all the REST resources to controllers and HTML pages to GSP views, keeping the rest of the Java code as such.
I have a DBService service, which helps connect to the DB and run queries on it, and a ProcessorService, which uses DBService to perform business operations.
I created beans for these services as follows:
beans = {
dbServiceBean(DBService, "test_db")
processorServiceBean(ProcessorService,ref("dbServiceBean"))
}
Everything is working fine with the above config.
Now, I want the application to be able to process multiple DBs (multi-tenant). I won’t know the name of the DB beforehand, however, so I can’t have a list of dbServiceBeans predefined.
Is it possible to rebuild/reload a bean with dynamically obtained values and reload the dependent beans as well when the application is running?
Grails already have the option to use multiple datasources.
You can change your DBService to get a connection from the datasources configured. If you just change it to a Groovy class and put it in grails-app/service you will get transactions and dependency injection by attribute name for free.
I have some legacy code that I am now trying to re-use under Spring. This code is deeply nested in other code so it's not practical to redesign and is called in many situations, only some of which are through Spring. What I'd like to do is to use the Spring transaction if one has been started; otherwise, continue to use the existing (legacy) db connection mechanism. Our first thought was to make our legacy class a bean and use an injected TransactionPlatformManager, but that does not seem to have any methods germane to our situation. Some research showed that Spring has a class called TransactionSynchronizationManager which has a static method isActualTransactionActive(). My testing indicates this method is a reliable way of detecting if a Spring transaction is active:
When called via Spring service without the #Transactional annotation, it returns false
When called via Spring service with #Transactional, it returns true
In my legacy method called the existing way, it returns false
My question: Is there a better way of detecting if a transaction is active?
No better way than the TransactionSynchronizationManager.isActualTransactionActive(). It is the utility method used by spring to handle the transactions. Although it is not advisable to use it within your code, for some specific cases you should - that's why it's public.
Another way might be to use the entity manager / session / connection and check there if there's an existing transaction, but I'd prefer the synchronization manager.