I have been searching for a while, but I can't found any information on how to achieve in Java EE to define custom annotations (interceptor bindings) to be able to be used in multiple maven modules without declaring it in every package where I would like to use it. It's basic interceptor where implementation only prints something into console.
An example is like javax.ws.rs.Path where this annotation can be used on multiple locations and everything what it needs to do is to import correct dependency. I cannot achieve same affect with my annotation.
I have created new maven module with the interceptor and binding annotation. I also have beans.xml file in META-INF folder to enable CDI. Then I add dependency of this module to other project, where I want to use this annotation. Problem is, that when I want to use this annotations, the implementation of annotation does not execute method which is annotated with #AroundInvoke annotation.
I don't know what I'm doing wrong, because weld should start initializing bean implementation because CDI is enabled, but he don't, unless I put extra configuration for <interceptor> in beans.xml file where I want to use annotation.
Assuming by package you mean module;
You need to declare your annotation in its own maven module (possibly with other shared logic). Then pull in that maven module as a dependency in your other modules. That way you can use the annotation wherever you want.
Related
Why do we need META-INF/spring.factories when create starters for Spring Boot applications? What if omit it at all or leave empty?
Doesn't the target application's #SpringBootApplication which is
a combination of three annotations #Configuration (used for Java-based
configuration), #ComponentScan (used for component scanning), and
#EnableAutoConfiguration
scan everything and find all beans from all the starters with no help of META-INF/spring.factories?
Component Scanning would scan the packages that you give it. You could technically tell it to scan all the packages of your dependencies, too, and it would start loading up any beans defined in them. If you don’t specify any packages to scan, then Spring will use the base package where the annotation is applied, which would very likely not include beans defined in any dependency libs.
There’s another layer to this- a lot of the libraries you use may be using annotations like “#AutoConfigureBefore” to give spring instructions on the order of bean creation. Component Scanning will not respect that, which could result in some weird behaviors if some dependency tries to override a bean from another which is annotated with #ConditionalOnMissingBean (I.e. create this bean only if it doesn’t exist.) You could easily end up with name collision issues where that bean actually gets created first, and then the override bean is created, too.
So the answer seems to be no. You need spring.factories.
Doesn't the target application's #SpringBootApplication scan everything...
No, it doesn't scan everything because if it was it could take a lot of time and resources. Think about it in a way that in order to understand whether the file with an extension *.class contains a bean (something annotated with #Component for example) it needs at least to read a class and analyze the byte code or even load it into memory to check the annotation by reflection.
So if your application's root package is in com.sample.app (the package with the class annotated with #SpringBootApplication), then spring boot by convention scans only the beans in this package and the packages beneath it. This means that it won't scan any thirdparties (assuming they won't be placed in com.sample.app anyway).
Now Its true that you can change the rules of component scanning, but again, you don't want to scan everything for performance reasons at least.
So Autoconfiguration modules (technically implemented with META-INF/spring.factories can specify an additional place (classes annotated with #Configuration) that spring boot will load despite the fact that they are not placed under the packages of your application
or, in other words, they do not obey the default component scanning rules.
In addition, spring.factories file allows to specify much more than auto configuration rules, you can specify environment post processors there for example, and other stuff that can be useful for your application, probably mostly beneficial at the level of application infrastructure, but still.
I have several projects that depend on a common framework, built on top of Spring Boot. This framework autoconfigures lots of the things that applications use via BeanPostProcessor and similar Spring mechanisms.
It also adds support for optional libraries that the applications can use, using #Conditional beans and optional Maven dependencies.
The problem I'm facing is that one of those optional libraries is Resilience4J and I'd like to add a dependency on resilience4j-micrometer if Resilience4j is added, so I can expose out-of-the-box all Resilience4J metrics via Micrometer.
Is there any mechanism in Maven that allows to add a conditional dependency given some condition, so I ensure that every application using Resilience4J exposes its metrics?
PS: I tried to just create a module to wrap the dependencies, but there are different Resilience4J dependencies the applications use (some apps are web and others Webflux, some use the Spring Cloud abstraction and others don't...).
You can try to manage dependencies via maven profile but it not really the best way. Your framework should integrate all libraries and your app manage dependencies with exclusions in order that Spring Boot can autoconfigure only included dependencies.
I'm not sure I'm following your question, I assume that you have a library "common".
So you have an application A (spring boot driven), and in its pom.xml you add a dependency on "common". You would like to create Beans in the application context of A if A has a dependency on Resilience4J. These beans are supposed to add expose some micrometer related stuff.
In this case you could probably use ConditionalOnClass:
In "common"'s code you could have something like this:
#Configuration
#ConditionalOnClass(Resilience4j.class) // or whatever class that can indicate that resilience4j is in the classpath, I took this for the sake of example, I don't know whether this class really exists
public class CommonConfiguration {
#Bean
public YourMicrometerIntegrationBean yourMicrometerIntegrationBean() {
return new YourMicrometerIntegrationBean();
}
.. other beans ..
}
This solution assumes that you have a dependency (optional ?) at the level of maven in "commons" to resilience4j. If you don't want this for some reason, you could create your custom condition (I believe you know how to do that based on the details that you've supplied in the question you have a pretty advanced setup, let me know if you need more details on that), and this custom condition will evaluate to "true" if Class.forName(<FULLY_QUALIFIED_NAME_OF_RESILIENCE_4_J>) won't throw an exception so that you'll see that its available in runtime.
I am using a dependency JAR in my project which has a custom annotation "#monitor"
This annotation is being used at a lot of places in the code.
Going forward, I would like to perform a quick test if there are any performance improvements if we ignore this annotation(As there are reflection api calls due to this).
I do not want to remove annotation classes from the dependency JAR as other projects might be using this. I also do not want to go to every method in my code or inside JAR to remove the "#monitor" annotation from methods.
Is there a way in SpringBoot2 to ignore a particular annotation from a spring configuration class?
Is there a way in SpringBoot2 to ignore a particular annotation.
We have a maven multi-module project with the following modules:
prj-srv
prj-client
The srv project contains EJBs. In prj-srv/src/test, we have #Alternative implementations of the EJBs, specified in the alternatives section of beans.xml. This works.
The project prj-client has prj-srv as a dependency. In addition, it has a dependency on prj-srv of type test-jar, scope test, so that it can use the alternative EJB implementations for tests. This works, too.
Now then: in prj-client/src/main/java, we have local implementations of the EJB interfaces (so that we can cache the data) annotated with our qualifier #Cacheable. What I would like to do, is setup the tests in prj-client/src/test/java so that they use my test implementations from prj-srv (the ones that aren't cacheable, but who cares since it's for testing).
I have tried:
Creating a class with producer methods (#Produces #Alternative #Cacheable) in prj-client/src/test/java, but I don't know how to configure beans.xml to set this up as the alternative
Creating classes in prj-srv/src/test/java that extend the test EJBs, annotated #Alternative #Cacheable, and put them in src/test/resources/META-INF/beans.xml in the alternatives section, but weld still injects the "real" #Cacheable beans from src/main/java.
Is there some problem mixing #Alternative with qualifiers? How can I get my tests to use alternate implementations of a qualified class?
Just found it: I had forgotten to mark the constructors of the #Cacheable implementations with #Inject. Apparently, even though it was marked as an alternative in beans.xml, since Weld didn't know how to initialize it, instead of throwing an error, it just silently decided to ignore the alternative...
My spring mvc application is broken into modules.
My services are in their own module.
Previously I used to put a #Service annotation on my services, but since they are in a seperate module, that doesn't have spring, how can I wire them up automatically like before in my web application?
If you split application into modules you have split its dependencies too.
For example:
Your ui depends on spring-mvc.
Your services depend on spring-core and hibernate-annotation.
Your services-impl depend on hibernate-core.
And then if your modeles have appropriate dependence. You can use #Service as you used.
Please bear in mind that when you create WAR with your application, all required modules will be placed in WEB-INF/lib along with Spring dependencies (required by MVC module).
So module in which your services are placed may have dependency to spring-context (containing annotations) since the MVC module requires this dependency itself so it will be placed in the final package anyway. If you use maven, it will handle everything under the hood automatically.
However, if you don't want to have dependencies to spring, because, for example, your 'services module' is deployed as a separate, spring-free bundle, you can use JSR330 #Inject, #Resource and #Qualifier Java annotations - these works interchangeable to Spring equivalents. However I don't know Java equivalents of #Service, #Component or #Repository, so in these cases you can rely on XML Spring context configuration in your MVC module.