I asked a question yesterday ( Using Spring in standalone apps ) on how you would use Spring in a standalone application. From that I learned that you only create the application context object once. So now the question is (even though it was partially answered in a comment) what happens when you create the application context?
Does Spring create the beans and wire them together when you say
new ClassPathXmlApplicationContext("some.xml") ?
I am not sure if I understand the boot strapping, and why it is like that.
The idea behind the ApplicationContext in Spring is that in order to properly inject objects where they are needed, some thing needs to be aware of the configuration the user specifies and inject dependencies based on this configuration.
The ApplicationContext is the thing that understands the user's wishes in terms of where and what should be injected (as well as other things such as AOP pointcuts and such) based on the configuration a user provides, either through an xml file or annotations.
Yes it will parse the bean definition file , it will create the beans , give them the dependencies,
The easiest way to debug is to go with the output print statements,
Put the statements in constructor & setter methods and try different possibilities to track the flow
Related
I'm trying to make a Spring Boot app where plugins are loaded dynamically from JARs at runtime. I also want the plugins to have access to all the Spring Boot features, most prominently Spring Data JPA. I've already figured out how to load classes from JARs, and now my problem is how to "hook up" the loaded classes (that might be Beans, JpaRepositories etc.) to "work with" my main Spring Boot application.
I also might in the future want to have my own annotation system for doing different things with the main app from the plugins, (that I know how to do using reflection) and I would want to still be able to do it after I manage to sort the Spring stuff out.
I imagine I have to tell Spring somehow to additionally look for #Components and other meaningful classes from those JARs, when it's scanning for annotations. I tried with #ComponentScan's basePackageClasses attribute but that needs to be constant, and hard-coding this is not an option for what I wanna do.
So is what I want to achieve even possible? And if it is, then can I do it through Java code, or is it maybe achievable by writing some XML configs?
When you start an spring app, beans are loaded and hooked in its contexts, so if you want to add more to it manually you might need to reload the whole context which may not be a good idea for an spring boot app.
Instead, I would suggest to use spring profiles, so you can define different configurations and based on what you want you can simple enable the one you need.
Find out more at:
https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-profiles
Hope this helps!
I have a Spring Boot REST application with JPA entities and Repository classes (and related services) that works very well. Now I would like to reuse these classes for other purposes, like weekly CRON jobs and similar one-time processes which will be run from the command line.
What would be the best way to do this? The challenge is that the persistence context properties are set in application.properties, and the persistence context isn't initialized unless the Application class is initialized.
I can break out all of these classes into a separate project, and use a different way to define the persistence context there, but this becomes more of a maintenance headache if anything changes with the entities or DAO methods.
What I would really like is to have a way, from the command line, to tell Spring Boot to run another class instead of the main Application (and have the persistence context properly initialized). Any way to do this?
(Note I asked a similar question which got no response: Possible to use Spring Boot repositories from another main class?)
[Edit] is it possible to do this by creating a #component that implements the CommandLineRunner? I just want it to run a simple one-time process and not the full REST application.
There are a number of ways you could do this.
You can have multiple Main classes, and then select which application yuo want to start select main class, however if you don't know how ComponetScan works you will end up loading both applications if you are not careful.
Another way is to use Profiles, you can set the profile when you start your spring app, and then have your web profile that will start Tomcat, and a command line profile that will not .
In the project I'm working on we have choosen to have the data-layer as a completly separate module (same gradle project), which has it's own Spring Context. The data-layer spring context is then used as the parent context for other applications, as a reusable component. It is a somewhat cleaner separations of concerns, were the shared code is clearly marked, instead of having multiple applications inside the same code mudule.
I am starting to learn Spring and came across a feature of Spring - overriding spring bean declared in one xml config in another config.
I do not understand where this feature can be useful. It seems illogical because same container will be configured using two different xmls and even when there are two beans with same ID, instead of reporting the ambiguity it is defaulting to the last one.
Is there a practical scenario where this can actually be useful? Is this good practice?
There are reasons why this could be useful for instance
Testing
Developing Component Libraries
Testing
When testing you can choose to override 1 or more beans. For instance a DataSource you probably don't want to test against the production instance of your database. But maybe an in memory one or one specially for testing. For this you can then just override the DataSource bean.
Developing Component Libraries
You can provide a starting configuration for your libraries and let users override certain components or let them implement interfaces. A sample of this is how the different Spring portfolio projects work (Spring Security, Spring Batch) with their default configuration.
Also when overriding beans spring will log this at startup of your application.
I have an ApplicationContextProvider class, which can used to access Spring ApplicationContext from beans not managed by Spring. Something like mentioned here
For the spring managed beans however I can make them ApplicationContextAware, so they can get access to ApplicationContext.
My question is, is it a good idea to use the common ApplicationContextProvider to get spring application context from the spring-managed beans as well or should I continue to use ApplicationContextAware?
Using a singleton with static reference to application context is asking for trouble. It is almost never a good idea to use such utility class in any case. When dealing with legacy web application use WebApplicationContextUtils instead.
I once reinvented this solution in a project during migration from EJB 2.1 to Spring - but after migration we get rid of it and could sleep again.
Back to your question - using such utility for Spring managed beans has no sense at all. To be honest, I rarely need ApplicationContextAware interface as well. Spring is suppose to inject dependencies, you shouldn't ask Spring for them all the time!
Can you show us some use case when you need quoted utility class (both for managed- and umanaged beans)? Looks like you are refusing to accept support Spring gives you.
I'm working on a web application that uses Spring MVC 2.5 and Hibernate.
One of the requirements of the application is that it must be able to export some objects to an external database. I figure I might as well use my existing data layer and just save the objects to the external source.
I'm new to Spring and Hibernate, and I guess I'm just wondering how I should approach this. Right now everything is automatically wired up through annotations. I'm guessing I'll have to create a new dataSource bean, and a new sessionFactory, and a transactionManager...maybe...but...
I only want the connection to the external data source to be available when the user is specifically "exporting".
Is autowiring going to get in my way? How can I tell Spring to inject the appropriate sessionFactory when I instantiate a DAO for my export process? (I'm autowiring through constructors) Should I programatically create my session factory (etc) and then manually instantiate my DAO? If so, will this "override" the autowire annotation?
I guess I don't need answers to the above questions specifically if someone can just step me through the basic process of getting something like this to work. Thanks!
Spring fortunately already has a solution for this: AbstractRoutingDataSource. It basically acts as a Facade for multiple DataSources and allows you to subclass it and implement whatever logic you need to decide which DataSource should be used. Some details are here:
http://blog.springsource.com/2007/01/23/dynamic-datasource-routing/
This allows your DataSource lookup logic to be handled in exactly one place. Your DAO layer and SessionFactory do not need to be adjusted, except that you need to inject your subclass of AbstractRoutingDataSource into the Hibernate SessionFactory.
Configuring multiple data sources and session factories in your spring context will not itself be a problem, but it does make autowiring less attractive.
You could use the #Qualifier annotation to tell the autowiring which one to choose, but I'd suggest not using autowiring, and instead explicitly injecting the correct data source and session factory using <property> or <constructor-arg>.
The transaction manager could potentially be shared between both data sources, if both data sources are managed by your app server, but it sounds like having transactional integrity across both data sources is not a requirement for you, and that having separate transactions for each data source would be enough.