Our application uses #Bean to define create beans and load them into the Spring context.
We now need to externalize these, so as to enable the application to be configured without touching the java source code.
We wish to replace the #Bean's with Groovy classes.
Is there a way to annotate a Groovy bean so that it will be picked up by Spring?
Note that we cannot simply reference each Groovy bean in the Spring XML, as we need to add and modify beans without touching the Spring code.
Thanks very much.
Use Spring config inheritance.
Move all shared code in a common "base" project that each individual / specific project depends on. Use Maven for this.
Create a common / base Spring config and put that into the "base" project. This config doesn't contain a definition for ProcessDefinition
In the specific project, create one bean which inherits from ProcessDefinition. Create a Spring config which imports the base config and define the single specific bean in it.
Related
My team uses some starter code that's included in every internal Spring project by default. This is included as a dependency (not parent) in the pom.xml file of my project. This starter code contains a default implementation of a configuration interface which Spring does not allow duplicates of (AsyncConfigurer), but I need to create my own custom implementation. I am not sure how to resolve this. Is there a way for me to exclude this configuration class but keep the rest of the dependency? Or can I somehow keep the given config class, but modify its properties?
The specific exception I get is: java.lang.IllegalStateException: Only one AsyncConfigurer may exist
//Thank you
You can define the AsyncConfigurer on parameter excludes from #SpringBootApplication. Example:
#SpringBootApplication(exclude=AsyncConfigurer.class)
Notice that this will excludes the entire #Configuration .
Another solution is to use bean override, to define only the beans you need to replace.
Add this to your application.properties (or yaml):
spring.main.allow-bean-definition-overriding=true
And you will be able to override it.
I have a Spring Boot application with different submodules which also contains spring components.
And in the main web modules I use 70% of the beans from the submodules. It depends on the application.yml properties, if the property group (which points to a bean) is enabled or not.
First I wanted to create Aspect-s, so when a method of a bean (which is not enabled by it's property) is called, then throw an exception. This solution could work, but then I would need to create Aspect classes, method annotations, import more and more dependencies.
So I am just wondering, would be there any other easier solution to disable a bean, or do not load at all to the spring boot container?
I would imagine something like #DependsOn, but for this you need to give a name of a bean name, but you cannot use this annotation to work with yml property.
Other easy solution is to #Bean or #Import every bean I want to managed by spring container, instead of #Import everything once from submodules, but then it is a static setting, cannot be overwrite by a single property from yml.
Spring introduced the concept of conditionals quite some time ago. Spring Boot uses this to a great extend to conditionally enable features. It even created a lot of conditional rules which you can use.
One of those rules is the conditional on a property rule. To use this rule add an #ConditionalOnProperty annotation to your bean. Now it will only be included if said property is enabled or has the specific value.
#ConditionalOnProperty(name="your.property.name")
Say I have 3 Spring/Maven projects:
api-spec: Contains interface MyService.
api-impl: Contains class MyServiceImpl which implements MyService. Also contains class MyServiceConfiguration which is a Spring #Configuration, that defines a bean of type MyServiceImpl.
main: Contains a Spring application setup with Spring JavaConfig (e.g. a #SpringBootApplication). It has a bean with an #Autowired MyService myService field, which works as its configuration class is annotated with #Import(MyServiceConfiguration.class).
I would like the main-project to have api-spec as a Maven compile dependency and to have api-impl as a runtime dependency (to prevent us from making "hard" dependencies from the main project to the api-impl project by mistake). This is not possible, because #Import takes an array of Classes - e.g.: #Import(MyServiceConfiguration.class). I would like something like #Import("my.package.MyServiceConfiguration") instead.
Using class path scanning is not an option (we have seen too many beans getting picked up by accident), and I would prefer not having to use XML files. We could use SpringApplicationBuilder.source(..) as it accepts a class name as a String - but I can't find a way to use that in my tests...
Compile time check is one of the advantages of java config, so I don't think that it's possible to do such thinks with Java. As for me you should use XML to handle this. It doesn't mean that you should do all your configuration in XML, most of the beans of your api-impl module can be in Java and just imported to XML where will be only beans that you are going to change in runtime.
If you don't want to use XML maybe you should consider to use Groovy config instead:
https://spring.io/blog/2014/03/03/groovy-bean-configuration-in-spring-framework-4
I use Play Framework + Spring Data JPA from this example:
https://github.com/typesafehub/play-spring-data-jpa
I have models, repositories and now I want to initialize my DB on start up. I inject repositories to my Global.java file using #Autowired, but they equals to null on run time. It's because Spring don't try to inject dependencies to Global.java, because Global.java don't have even package name, so I can't tell Spring to scan his package!
With controllers Spring DI works well, but how to use it in Global.java? How to initialize database using repositories?
You can change package of Global.java in application.conf by setting property application.global.
Other way can be to fetch dependency explicitly calling
context.getBean(YourBeanClass)
in Global.java instead of autowiring it, as you have context available in Global.
You may explicitly create a bean by defining it in your context xml
<bean id="global" class="Global"></bean>
Also, having classes in default packages is not a good idea.
In my unit tests I want to configure Spring in code (API, Annotations) so they will not depend on bean configuration files.
Can this be done?
For example:
Class Dependency {}
Class A
{
#AutoWired
Dependency d;
}
When testing A, I want to be able to create an instance of it with the Dependency member resolved, without having to use configuration files.
Thank you!
In short, yes, you can start a spring application context with any of the implementations of org.springframework.context.support.AbstractApplicationContext. Namely, if you don't want to load the definitions from an XML file, you can use the org.springframework.context.support.StaticApplicationContext or org.springframework.context.support.GenericApplicationContext to start the context.
With the context instantiated, you can start creating beans with the BeanFactory, either the oen default to the selected context or a custom one, that suits your needs.
In practice, it's lot more work than that. It's easier if you just use plain XML configuration, but it can be done.
You can use the Java configuration instead of the XML configuration.
You can use the AnnotationConfigApplicationContext to create application context programatically without bean configuration files.