I have been trying to find documentation of #enablesns #enablesqs annotations but can't find them.
They seem to be required for the sqs and sns integration to work.
But I'd just like to have a better understanding, and be sure I'm not using them wrong.
Any description would be of great help.
Looking at the source code for those two annotations:
#Import({SnsConfiguration.class, SnsWebConfiguration.class})
public #interface EnableSns
Where #Import does the following:
#interface Import:
Indicates one or more #Configuration classes to import.
Long story short: Those annotations only combine multiple #Configuration classes into one single annotation.
E.g. #EnableSns does the same as adding #SnsConfiguration and #SnsWebConfiguration which provide you with AmazonSNS, RegionProvider and AWSCredentialsProvider beans.
Related
I want to add API versions across all log statements. To achieve that, I have created a custom annotation and its corresponding interceptor.
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
#Around
#Documented
public #interface LogAPIVersion {
String apiVersion() default "";
}
Things are working fine if I place annotation on a method or a class.
But, I want to apply this annotation at a package level (for all classes and their methods). I've created a package-info.java file and decorated my custom annotation onthe package name.
#LogAPIVersion(apiVersion = "v1")
package com.example.controllers.v1;
Unfortunately, my logging interceptor is not getting invoked. How do I make this work?
The simple answer is: Neither native AspectJ nor simpler AOP frameworks such as Spring AOP provide any means to intercept package-level annotations.
What you could do is use native AspectJ's annotation processing support in order to generate annotations for all classes or methods you wish to target during your build and then intercept them using an aspect. Here are some of my old answers showing examples of how to use the feature:
https://stackoverflow.com/a/29877757/1082681
https://stackoverflow.com/a/40449796/1082681
https://stackoverflow.com/a/29437129/1082681
It might need to be annotated with #Inherited.
I have the following autoconfigure class.
#Configuration
#ConditionalOnWebApplication
#EnableConfigurationProperties({LoggerProviderProperties.class})
#Import({LoggerController.class, LogService.class, LogConfig.class})
public class ProviderAutoConfiguration {
}
I need to import all the components, services, configurations using #import annotation, otherwise for example, when I remove LogService.class (LogController autowires LogService) from #Import parameters, it throws the following error
Consider defining a bean of type 'com.log.LogService' in your configuration.
Do I really have to include all of them manuelly as shown above, or is there any other way to automatically detect classes annotated Service, Component or Configuration?
!This is starter library, not a executable app!
The problem with your "library" is that it already needs a lot of moving parts, like Spring Data JPA, properly setup JPA. If that isn't available it will fail, or if you add #EnableJpaRepositories and/or things like #ComponentScan and #EntityScan it will (quite severely) interfere with the (auto)configuration of Spring Boot or the clients. Which is what you want to prevent.
Instead of all those annotations what you need to do is
Conditionally enable #EnableJpaRepositories or just include the dependency and let the auto-configuration kick in (I suggest the latter)
Don't add #ComponentScan, #EntityScan etc. instead use #AutoConfigurationPackage which is designed for starters.
#Configuration
#ConditionalOnWebApplication
#EnableConfigurationProperties({LoggerProviderProperties.class})
#AutoConfigurationPackage
public class ProviderAutoConfiguration {
}
NOTE: This assumes that the ProviderAutoConfiguration is in the same or a higher package then your other classes. If not specify the basePackages in the #AutoConfigurationPackage.
You can use #ComponentScan to specify the packages you want to scan to find configurations and/or components to load.
Assuming you are using Spring Boot, at least so it seems according to your tags, you should take a look at #SpringBootApplication.
#SpringBootApplication encapsulates #Configuration, #EnableAutoConfiguration, and #ComponentScan annotations with their default attributes. The default value for #ComponentScan means that all the sub packages on the package the #ComponentScan is used are scanned. That is why it is usually a good practice to include the main class in the base package of the project.
If your components, services, configurations are under com.log as direct class or in sub-package, you can use #ComponentScan(basePackages="com.log.*")
#Configuration
#ConditionalOnWebApplication
#EnableConfigurationProperties({LoggerProviderProperties.class})
#ComponentScan(basePackages="com.log.*")
public class ProviderAutoConfiguration {
}
My problem references to this issue here on github https://github.com/mapstruct/mapstruct/issues/1427
I got at least two versions of mappers with the same name. I want to use springs getBean/Autowired possibilities but this doesn't work out of the mapstructs box yet. :-)
I followed the second workaround mentioned in the upper link: extend Springs bean naming strategy. Did someone ever get this well ment proposal working?
If i follow the code parts from there the bean naming doesn't take place. For me its's clear why not: there aren't any components to scan and especially to find.
If i add a componenModel = "spring" to the mapper annotation i get a ConflictingBeanDefinitionException. Don't know why. Maybe there's a cat in the tail problem?
As stated from Filip here https://github.com/mapstruct/mapstruct/issues/1427 i followed his approach and with a few modifications it worked. I added a solution comment in the link.
The main changes are:
i added componentModel = "spring" to my mappers and used a filter to exclude all of my mapper classes (the interface all of my mappers are implementing: MapperInterface.class) within the Spring Boot application.
To my Spring Boot application class i added:
#ComponentScan(basePackages = { "com.application.spring_boot_class" }, excludeFilters = { #ComponentScan.Filter(value = { MapperInterface.class }, type = FilterType.ASSIGNABLE_TYPE) })
I had this issue before, and I resolved it using the Spring bean definition in a configuration class, a class annotated with #Configuration, with the Mapstruct mapper call like below:
#Bean
public IMyMapper offerWebMapper() {
return Mappers.getMapper(IMyMapper.class);
}
And then you can inject the mapper using #Autowired or getBean.
I'm trying to understand the transition from using xml annotation to java based annotation in Spring. I have these definitions
<context:annotation-config>: Scanning and activating annotations for already registered beans in spring config xml.
<context:component-scan>: Bean registration + <context:annotation-config>
is #Configuration and is #ComponentScan.
If lets say I declare all my beans with #Component (disregard first the more specific ones like #Repository, #Service etc) annotation and make sure that the packages are getting scanned by the #ComponentScan annotation, what is a particular use case where I will still annotate my class with both #Configuration together with #ComponentScan?
I ask this question because sometimes I see classes annotated with both #Configuration and #ComponentScan at the same time.
First read the following carefully:
Difference between <context:annotation-config> vs <context:component-scan>
Thus <context:component-scan> does the scan job and the same job than <context:annotation-config> does, it means work around with the DI annotations
Then now consider:
<context:component-scan> equivalent to #ComponentScan
<context:annotation-config> no equivalent for annotation.
what is a particular use case where I will still annotate my class
with both #Configuration together with #ComponentScan?
#Configuration is used to define beans about Infastructure such as Database, JMS etc...
Yes, a class can use both, It could be used for example for MVC Infrastructure #Configuration such as:
#EnableWebMvc
#Configuration
#ComponentScan("com.manuel.jordan.controller", "com.manuel.jordan.rest")
public class WebMvcConfig extends WebMvcConfigurerAdapter {
Thus from that class your are configuring MVC and indicating only to scan the MVC classes created by you for the "web side", such as: #Controller, #RestController.
This really depends on your likings and coding style. Documentation states:
Either basePackageClasses() or basePackages() (or its alias value()) may be specified to define specific packages to scan. If specific packages are not defined, scanning will occur from the package of the class that declares this annotation.
So every time you see just #ComponentScan annotation this means that all sub-packages should be scanned. This is a reasonable approach to take with package per feature layout: when you have a #Configuration class for your feature and all #Components related to the feature in sub-packages.
I want to configure CXF to auto-scan for resources, providers, features, and the lot. In my search I came across the SpringComponentScanServer, which sounds like something I need. Unfortunately, documentation about this class is virtually non-existent.
When you have classes annotated with #javax.ws.rs.ext.Provider, they get picked up by CXF as expected. When you have a feature annotated with org.apache.cxf.annotations.Provider, it will also get picked up by CXF.
But what if you have a third-party feature that does not have this annotation?
For example, the CXF LoggingFeature? You cannot, as far as I know, add an annotation to a class if you can't change it's source code.
I came up with the following, hideous, solution, but surely, there must be a better way to do this???
#Configuration
#Import(SpringComponentScanServer.class)
public class CxfConfig {
#Component
#Provider(Provider.Type.Feature)
static class MyLoggingFeature extends LoggingFeature {
}
}
Here, I basically extend the existing LoggingFeature, only to add the #Provider annotation.
I found the following example CXF JAXRS Spring Boot example, which does what I want with the Swagger2Feature. That works, but only starting from CXF 3.1.6, and only for the Swagger2Feature. Not for LoggingFeature.
So my question is: is there a less hideous way to add the LoggingFeature?