Spring: Apply Annotation based on properties - spring

Say i am using #Scheduled annotation on a function. But i want that annotation to take effect only if some property is defined in properties file. How do we configure that scenario?
Use case: Same app deployed on multiple servers but #Scheduled should be active only on one server.

My Idea:
Use an extra bean (MyScheduler), that contains nothing more than a method annotated with #Schedule. This Method "forward" the invocation to your real Service.
Then annotate the MyScheduler class with #Component and #Profile
The use your properties file to enable or disable this profile
Sketch:
#Component
#Profile("onTHEserver")
public class MyScheduler{
#Autowire
private RealService realService;
#Schedule(cron="1****") {
realService.doSomething();
}
}
#See: Spring 3.1 M1: Introducing #Profile
#See: #Profile Java Doc

Related

Sping-boot configuration-properties and service layer injection

I'm new to spring dependency-injection and am reaching out to learn about best practices. I would like to know if its a good design philosophy to inject classes annotated with #ConfigurationProperties into service layer classes (annotated with #Service). Im trying to map properties in my application.yml to a config-class as follows -
#ConstructorBinding
#ConfigurationProperties(prefix = "application")
class ApplicationConfig(
val kafka: someDeeplyNestedType = SomeDeeplyNestedObj()
) {
// helper functions
}
I'm then injecting above config class in service layer as follows -
#Service
#EnableConfigurationProperties(ApplicationConfig::class)
class RestService(val config: ApplicationConfig) {
init {
// Reference config object
// Reference application.yml properties via config object.
}
}
I'm curious to know if I can improve upon my current implementation - not sure if its agreeable to pass configuration classes to service-layer classes. I'm also curious to know if theres any better approach to wiring ApplicationConfig without needing to use EnableConfigurationProperties annotation.
It is agreeable, documented, and probably "unrivaled" (only bounded by: "limitations" (no SpEL -> helper functions!?;)).
To work with #ConfigurationProperties beans, you can inject them in the same way as any other bean, as shown in the following example:
#Service
public class MyService {
private final SomeProperties properties;
...
The only problems can arise from the "deeply", not "owning" the (config) structure ...and possibliy from "helper functions".
But
The prefix = "application" "sounds" suspicious!
Note:
[Most - almost All] (official) spring* boot properties, are already "typesafe", and have their object/class representation in spring-boot-autoconfigure packages.
Please study that "typesafe chapter", but also gazing at PropertySource Abstraction.
There is no hard rule for this as in Spring Boot we can add #EnableConfigurationProperties at a class level with stereotype annotations.
As a part of good practices EnableConfigurationProperties or any configuration thing should be part of Configuration class of or main spring boot class so any developer can easily figure out those configuration instead of going any specific service class and then check.
In your case, yo can use #EnableConfigurationProperties annotation in conjunction with #SpringBootApplication annotation.

How SpringBoot dependency injection works with different type of annotations

I recently started exploring Spring Boot. I see that there are 2 ways to define Beans in Spring Boot.
Define #Bean in the class annotated with #SprinBootApplication
Define #Bean in a class annotated with #Configuration
I am also confused about stereo-type annotation #Repository #Service #Controller etc.
Can someone please explain how dependency-injection works with these annotations?
Yes it is possible.
Either you use #Bean in any of your #Configuration or #SpringBootApplication class or mark the bean classes explicitly with annotations like #Service, #Component #Repository etc.
#Service or #Component
When you mark a class with #Service or #Compoenent and if spring's annotation scanning scope allows it to reach to the package, spring will register the instances of those classes as spring beans.
You can provide the packages to be included/excluded during scan with #ComponentScan
#Bean
#Beans are marked on factory methods which can create an instance of a particular class.
#Bean
public Account getAccount(){
return new DailyAccount();
}
Now in you application you can simply #Autowire Account and spring will internally call its factory method getAccount, which in turn returns an instance of DailyAccount.
There is a simple difference of using #Bean vs #Service or #Compoenent.
The first one makes your beans loosely coupled to each other.
In the #Bean, you have flexibility to change the account implementation without even changing any of the account classes.
Consider if your classes instantiation is a multi-step operation like read properties values etc then you can easily do it in your #Bean method.
#Bean also helps if you don't have source code access to the class you are trying to instantiate.
Spring Boot auto-configuration attempts to automatically configure your Spring application based on the jar dependencies that you have added.
You need to opt-in to auto-configuration by adding the #EnableAutoConfiguration or #SpringBootApplication annotations to one of your #Configuration classes.
You are free to use any of the standard Spring Framework techniques to define your beans and their injected dependencies. For simplicity, we often find that using #ComponentScan (to find your beans) and using #Autowired (to do constructor injection) works well.
One way is to define #Bean in the class annotated with
#SprinBootApplication
If you see #SprinBootApplication it is combination of many annotation, and one of them is #Configuration. So when you define #Bean in the Main class, it means it's inside #Configuration class.
According to Configuration docs :
Indicates that a class declares one or more #Bean methods and may be
processed by the Spring container to generate bean definitions and
service requests for those beans at runtime.
class annotated with #Configuration
When you define #Bean is a class annotated with #Configuration class, it means it is the part of spring configuration all the Beans define in it all available for Dependency-Injection.
I have also seen some code where neither of the 2 above approaches
have been used and yet dependency injection works fine. I have tried
to research a lot on this but could not find any concrete answer to
this. Is this possible?
I am assuming you are talking about Sterio-type annotation. Every sterio type annotation has #Component, according to docs :
Indicates that an annotated class is a "component". Such classes are
considered as candidates for auto-detection when using
annotation-based configuration and classpath scanning.

Possible to autowire imported utility classes in Spring?

I want to use data mappers, logger, transfromers, etc. in my Spring web projects. Is it possible to autowire an imported (jar) utility dependency, without wrapping it in some #Component or #Service class? Do we even want to do it that way, or should we just use a static reference?
If your utils, are based on not static methods, then this is simple:
If you use java based configuration, then just declare that util in an #Bean annotated method.
#Configuration
public class YourConfig {
#Bean
public YourUtil util(){
return new YourUtil ();
}
}
in xml it could been as simple as:
<bean id="util" class="org.example.YourUtil" />
The following is true, but it is not what was asked for:
There are at least two other ways to inject beans in instances that are not created (managed) by Spring:
(1) add #Configurable annotation to this class - this requires real AspectJ (compile-time or load-time -weaving)
#see Spring Reference Chapter 7.8.1 Using AspectJ to dependency inject domain objects with Spring
#see this answer of mine https://stackoverflow.com/a/7007572/280244 for a quick "guide" to enable the #Configurable support
(2) invoke SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
#see this question and its (two highes voted answers) for some ideas how to use
You can only #Autowire a bean managed by Spring. So you have to declare your instance through some configuration : a bean in an xml file, or a #Bean method in a java configuration.
#Component are just automatically discovered and registered in the spring context.

How does SimpleCORSFilter work?

How does SimpleCORSFilter work in this example?
Enabling Cross Origin Requests for a RESTful Web Service.
I only see a declaration of SimpleCORSFilter class but no instance. I tried ctrl+f to search the example page but can't find anywhere this class be instantiated.
How does it work?
I am new to Spring and Java.
So more detail more helpful. Thx.
A main point of Spring is a mechanism called dependency injection. Spring allows you to mark your classes, instance variables and so on with special annotations. Spring will look for those annotations and configure your application according to them.
In your example you annotate your filter with #Component:
#Component
public class SimpleCORSFilter implements Filter
And you annotate your Application class with #SpringBootApplication:
#SpringBootApplication
public class Application
The second annotation (#SpringBootApplication) tells Spring to search through your project for #Component annotations. As you annotated your filter with this, Spring will find your filter and instantiate it automatically. That's how your filter will be created and put to the right place.

Using proxy-target-class="true" with Spring beans

Im using Jersey Rest and want a Jersey filter to have access to some spring beans.
however as I've discovered from other threads, Jersey does not obtain Spring beans if they are Java proxies as opposed to generated java proxies. I want to add the proxy-target-class="true"
What are the impacts of doing so and also can this just be set on a single bean or does it need to be set on all referenced beans?
By setting proxy-target-class="true" you will be using CGLIB2 for your proxies, instead of jdk proxys.
The implications are the following, as described in the documentation:
final methods cannot be advised, as they cannot be overriden.
You will need the CGLIB 2 binaries on your classpath, whereas dynamic proxies are available with the JDK. Spring will automatically
warn you when it needs CGLIB and the CGLIB library classes are not
found on the classpath.
The constructor of your proxied object will be called twice. This is a natural consequence of the CGLIB proxy model whereby a subclass
is generated for each proxied object. For each proxied instance, two
objects are created: the actual proxied object and an instance of the
subclass that implements the advice. This behavior is not exhibited
when using JDK proxies. Usually, calling the constructor of the
proxied type twice, is not an issue, as there are usually only
assignments taking place and no real logic is implemented in the
constructor.
Also, you should be able to make a "target-proxy" for a specific component by using
proxyMode=ScopedProxyMode.TARGET_CLASS
Forcing a CGLib-Proxy although the controller formally implements an interface (SpringBoot 1.2.3.RELEASE with Spring 4.1.6.RELEASE):
#Controller
#Scope( proxyMode = ScopedProxyMode.TARGET_CLASS )
public class ServiceImpl implements ServiceIntf
{ .... }
This enables valid and working #RequestMapping and #Transactional annotations
Use the following annotation in Java Spring Config class:
#EnableAspectJAutoProxy(proxyTargetClass = true)
This is the way I made my test working:
MyTarget target = new MyTarget();
AspectJProxyFactory factory = new AspectJProxyFactory(target);
factory.setProxyTargetClass(true);

Resources