Difference between #Bean and #Component when registering a filter? - spring

I am using a custom filter in my Spring Boot application and it seems there are 2 ways of getting the filter registered.
--> Register the filter using the #Bean
#Bean
public Filter AuthenticationFilter() {
return new AuthenticationFilter();
}
--> Anotate the Filter using #Component
#Component
public class AuthenticationFilter implements Filter {}
I am puzzled on what the difference is and why i should use one over the other?

It's largely down to personal preference.
Using #Component requires component scanning to be enabled. Some people prefer not to use component scanning as they find that it makes it hard to determine where your beans are coming from. Declaring everything using #Bean methods avoids this but at the cost of writing (slightly) more Java configuration.
Another reason to use #Bean is that you may not have any control over the Filter's source, i.e. you can't annotate it with #Component so declaring it using an #Bean method is your only option.

Related

Ordering Spring proxies without AspectJ

#Service
#Transactional
public CarService {
#Autowired private CarRepository carRepository;
#Cachable("cars")
public List<Car> getCars() {
return carRepository.getAll();
}
}
Suppose I have a code like this, where both #Transactional and #Cachable are presented. How can I guarantee that proxy chain spring will go through will be proxyForCache-proxyForTransaction? I.e. transaction won't be created, if my application already has cached result. I've seen a lot of examples, where people offer to implement Ordered interfaface on a class-level, namely, on #Aspect level. But problem is we don't use AspectJ in our project. Is there any way to order spring proxies without creating additional classes or at least using of AspectJ?

Java Configuration vs Component Scan Annotations

Java configuration allows us to manage bean creation within a configuration file. Annotated #Component, #Service classes used with component scanning does the same. However, I'm concerned about using these two mechanisms at the same time.
Should Java configuration and annotated component scans be avoided in the same project? I ask because the result is unclear in the following scenario:
#Configuration
public class MyConfig {
#Bean
public Foo foo() {
return new Foo(500);
}
}
...
#Component
public class Foo {
private int value;
public Foo() {
}
public Foo(int value) {
this.value = value;
}
}
...
public class Consumer {
#Autowired
Foo foo;
...
}
So, in the above situation, will the Consumer get a Foo instance with a 500 value or 0 value? I've tested locally and it appears that the Java configured Foo (with value 500) is created consistently. However, I'm concerned that my testing isn't thorough enough to be conclusive.
What is the real answer? Using both Java config and component scanning on #Component beans of the same type seems like a bad thing.
I think your concern is more like raised by the following use case:
You have a custom spring-starter-library that have its own #Configuration classes and #Bean definitions, BUT if you have #Component/#Service in this library, you will need to explicitly #ComponentScan these packages from your service, since the default #ComponentScan (see #SpringBootApplication) will perform component scanning from the main class, to all sub-packages of your app, BUT not the packages inside the external library. For that purpose, you only need to have #Bean definitions in your external library, and to inject these external configurations via #EnableSomething annotation used on your app's main class (using #Import(YourConfigurationAnnotatedClass.class) OR via using spring.factories in case you always need the external configuration to be used/injected.
Of course, you CAN have #Components in this library, but the explicit usage of #ComponentScan annotation may lead to unintended behaviour in some cases, so I would recommend to avoid that.
So, to answer your question -> You can have both approaches of defining beans, only if they're inside your app, but bean definitions outside your app (e.g. library) should be explicitly defined with #Bean inside a #Configuration class.
It is perfectly valid to have Java configuration and annotated component scans in the same project because they server different purposes.
#Component (#Service,#Repository etc) are used to auto-detect and auto-configure beans.
#Bean annotation is used to explicitly declare a single bean, instead of letting Spring do it automatically.
You can do the following with #Bean. But, this is not possible with #Component
#Bean
public MyService myService(boolean someCondition) {
if(someCondition) {
return new MyServiceImpl1();
}else{
return new MyServiceImpl2();
}
}
Haven't really faced a situation where both Java config and component scanning on the bean of the same type were required.
As per the spring documentation,
To declare a bean, simply annotate a method with the #Bean annotation.
When JavaConfig encounters such a method, it will execute that method
and register the return value as a bean within a BeanFactory. By
default, the bean name will be the same as the method name
So, As per this, it is returning the correct Foo (with value 500).
In general, there is nothing wrong with component scanning and explicit bean definitions in the same application context. I tend to use component scanning where possible, and create the few beans that need more setup with #Bean methods.
There is no upside to include classes in the component scan when you create beans of their type explicitly. Component scanning can easily be targeted at certain classes and packages. If you design your packages accordingly, you can component scan only the packages without "special" bean classes (or else use more advanced filters on scanning).
In a quick look I didn't find any clear information about bean definition precedence in such a case. Typically there is a deterministic and fairly stable order in which these are processed, but if it is not documented it maybe could change in some future Spring version.

Can spring statemachine support multi configuration?

In my project, i have a problem; i have many scenes in which i need to support multi status configuration, for example, i need to define create order status machine and i also need to define create item status; so can any one tell me how can i do with spring statemachine?
i already use #EnableStateMachineFactory and define
#Configuration
#EnableStateMachineFactory
#SuppressWarnings("all")
public class OrderHoldConfiguration extends EnumStateMachineConfigurerAdapter<HoldState, HoldEvent> {
...
}
#Configuration
#EnableStateMachineFactory
public class JsdConfiguration extends EnumStateMachineConfigurerAdapter<BizState, BizEvent> {
...
}
but it don't work, which way should i use?
Looks like docs are a bit unclear on this but both #EnableStateMachine and #EnableStateMachineFactory work in a same way where resulting beans are named stateMachine and stateMachineFactory respectively. In your case other factory simple gets overridden.
#EnableStateMachineFactory(name = "factory1"){}
#EnableStateMachineFactory(name = "factory2"){}
Then you can autowire or get bean from spring app context just like any other bean by name. There is existing ticket gh-306 to allow autowiring by generic types so until that gets fixed you need to wire by name (i.e using #Qualifier).

spring/tomcat-jdbc pool - new connection listener

I am using tomcat-jdbc pool in default spring-boot setup. I would like to run some custom Java code each time new JDBC connection is established in the pool and before it is used for the first time. How to do it, and if there are several possibilities which one is the best?
To extend already accepted answer, you can use Spring AOP without full AspectJ if you use pointcut as this one:
#AfterReturning(pointcut = "execution(* org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection())")
public void afterConnectionEstablished() {
...
}
Well, I can think of two options:
Create your own wrapper class - either by extending Tomcat's DataSource class or by implementing Java's DataSource interface and delegating to the wrapped DataSource - and then add the logic you want to the desired methods and register a bean in a #Configuration class by manually instantiating your tomcat-jdbc DataSource (for examples on how to do so, refer to DataSourceConfiguration.Tomcat class) and wrapping it with your class.
Create an aspect and use Spring's AOP support to intercept calls to getConnection. Since DataSourceclass is in the javax package, I think you'll have to use AspectJ, and for some examples refer to this link
My suggestion would be to go with the first option, it should give you fewer headaches, here's a small example how you'd define your wrapper bean:
#Bean
public DataSource dataSource(DataSourceProperties properties) {
return new MyDataSourceWrapper(tomcatDataSourceFrom(properties));
}
private org.apache.tomcat.jdbc.pool.DataSource tomcatDataSourceFrom(
DataSourceProperties properties) {
// manual instantiation like in DataSourceConfiguration.Tomcat class
}

How to make Spring #autowired annotation to pick a certain type without using #Qualifier?

Is there a way to specify the default type for Spring #autowired annotation? For example, I have bean ValidatorA and bean ValidatorB that extends ValidatorA.
The ValidatorA is used in some other places and is injected using #autowired.
Is there a way to force Spring to inject ValidatorB instead of ValidatorA without changing the existing code?
The only solution I found at How to override the behavior of Spring #Autowired suggests to exclude ValidatorA from the context.
Is there any other way?
For example, with Guice I would just bind the ValidatorA.class to ValidatorB.class and that will do exactly what I need.
I have no problem to add #Qualifier to ValidatorB but ValidatorA should stay unchanged.
Guice provides ability to define "Providers", is there something similar in Spring? Maybe with #Configuration annotation?
I think you could use primary indicator there. If your bean is defined through annotation, add #Primary to ValidatorB definition. If you are using xml config add primary="true" to <bean> definition.
Is there a way to force Spring to inject ValidatorB instead of ValidatorA without changing the existing code?
Without changing the code, I doubt it very much. You could change the app context or alter the code something like this :
#Component
#Qualifier("B")
public class ValidatorB extends ValidatorA {
}
and then inject like so (there are other syntactic options as well)
#Resource
#Qualifier("B")
private ValidatorA validatorB;

Resources