I am developing a bunch of Java/Sprint Boot webservices that will all have several identical (ideally, reusable) Spring-based resources:
many annotation-based Spring Security configurations
several #Services and #Components
many annotation-based event handlers
annotation-based exception handler
#ControllerAdvice that extends ResponseEntityExceptionHandler
annotation-based configuration files (#Configuration)
Ideally I could place these in a library (shared JAR file) and reuse them across the different webservice projects. However I don't believe Spring Boot will scan the entire dependency graph of libraries and load them based on their annotations.
Does anybody know of a way to encourage Spring Boot to do this? For example if I package the following class into a reusable/shareable library JAR:
#ControllerAdvice
#Slf4j
public class ApiExceptionHandler extends ResponseEntityExceptionHandler implements ApiContractConstants {
// ... common exception handling code to be used by
// all services
}
And then pull that in to a Spring Boot webservice (via Maven/Gradle) as a runtime dependency, how do I get Spring Boot to scan, find and load that exception handler for me?
The description makes me think of #SpringBootApplication. The property scanBasePackages of #SpringBootApplication defines base packages to scan for annotated components.
#SpringBootApplication(scanBasePackages = {"org.example"})
Related
I have an annotation named #UserHasAccess which is used to check user's access based on some service call. In the advice, I have some dependency to call the service. This is the advice class:
public class UserHasAccessAdvice{
#Autowired
ServiceClient client;
//Other methods
}
Now I am planning to move this annotation to a common project so that I can use it in all the projects. When I tried, I am getting compilation error as ServiceClient is not present in the common project. How can I reuse this annotation by moving it to a common package? How to inject the service class based on the target project?
I am using Spring Boot 2.x
We are externalizing configuration of our microservices (spring boot based) using spring cloud.
As per my understanding on Spring Cloud, to enable the beans loading refreshed/updated values from Config server we need to do 2 things in Spring Cloud Client:
add #RefreshScope on the beans reading values from property files
using #Value
add spring actuator to provide /refresh endpoint to
refresh the context.
Scenario:
We have 100s of classes reading values from property file using #Value.
I have to mark all these beans refresh enabled using #RefreshScope annotation.
How can I avoid putting #RefreshScope annotation on all these classes.
Is there any shortcut or spring cloud feature to get around this situation.
You may want to look into Spring Boot feature called #ConfigurationProperties. It is designed to better organize several external configuration options.
According this Github issue, it should work for spring-cloud without #RefreshScope usage.
EDIT (reaction on comment): Maybe you are missing point of #ConfigurationProperties. With this annotation, you wouldn't use it in other configuration classes. You would have dedicated class (or few classes) only for reading and providing properties. Other configuration classes would inject this configuration holder bean.
You could encapsulate your #Values into one (or several) ConfigurationService bean which is #RefreshScoped and autowire this service into your classes instead. That way you only have a small amount of request scoped beans and your services can stay singletons.
I am new to Spring Boot and I was just wondering if I need all annotations on my main method that I currently have
Here they are
#Import(ServiceConfiguration.class)
#SpringBootApplication(scanBasePackages = {"com.myproject.rest",})
#EnableJpaRepositories({"com.myproject.dao.jpa"})
#EntityScan(basePackages = "com.myproject.domain.jpa")
The class ServiceConfiguration.class has the following annotations
#Configuration
#EnableConfigurationProperties({SlackServiceProperties.class})
My database objects have the #Entity annotation, my rest classes have the #RestController annotation and my service classes have the #Component annotation
Just wondering are they all needed or can I exclude any of these annotations?
Thanks
If your main method is located in a top-level package, then all you need is:
#SpringBootApplication
It will automatically scan your sources recursively and pick up any #Bean's, #Component's or #Configuration's
Spring Data JPA will also automatically be configured if you're using this starter:
spring-boot-starter-data-jpa
If you structure your code like so:
com.myproject
- Application.java
com.myproject.configuration
- ServiceConfiguration.java
- OtherConfiguration.java
com.myproject.dao.jpa
- .. your repositories..
com.myproject.domain.jpa
- .. your #Entity classes...
You ONLY need to annotate your Application class with #SpringBootApplication.
All your #Configuration, repositories, other #Component and #Service classes will be auto scanned and configured by Spring Boot. That means you DON'T need to manually #Import configurations, you don't need #EnableJpaRepositories or #EntityScan.
All you need for Spring Boot to configure JPA is to include the JPA starter:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
You can follow this tutorial: https://spring.io/guides/gs/accessing-data-jpa/
You will see that it requires minimal annotations.
I assume it may depend on what you need, as I have not used a few of those in your example. I am not too familiar with all of Spring's "magic" when it comes to behind-the-scenes work it does with annotations. I have a perfectly functioning Spring Boot app with only
#SpringBootApplication
#Configuration
#ComponentScan
In order,
#SpringBootApplication is Spring's way of identifying that this application is from Spring Boot (one consequence, for example, is that there is no web.xml file).
#Configuration tells Spring to look for .properties files on your src path. Here, for example, you can define an "application.properties" file to define your datasource (database information for Spring to use).
#Component tells Spring to look for "Components" when it starts up the application. Pretty much #Controllers, #Service, etc. that may be found throughout your application.
For more accurate and in-depth explanations for many of Spring's annotations, may I direct you to:
http://www.techferry.com/articles/spring-annotations.html
and
https://dzone.com/refcardz/spring-annotations
These both have excellent descriptions and examples for the annotations.
Edit: #Configuration and #ComponentScan are included in #SpringBootApplication, as Strelok has pointed out in the comments.
Hope that helps.
I am creating a few spring components and it would be a part of a library - jar.
I want the components to get loaded automatically by the applications that have the jar in the classpath.
#Component
public class AComponent {
}
I tried creating a configuration class and doing a component scan, but, the configuration is not loading.
#Configuration
#ComponentScan(BasePackages="")
public class ComponentConfig {
}
Can you please suggest a solution? It's a non-spring-boot application.
As you are writing a library, that uses Spring, I do not believe it is possible for the client applications to make zero changes. Your library has a collection of Spring beans that must be loaded into an ApplicationContext. At the very least, the clients will need to include your #Configuration/#Component classes (via scanning).
Good luck.
I'm actually studying spring application, more particularly the ComponentScan annotation that scans java packages to find some classes annotated with #Component.
I was wondering if the Spring ComponentScan annotation stores the related components found in other packages inside of the meta-datas of the Main Class (where I have the static void main method?)
Is this the only place where the framework stores these informations?
<context:component-scan base-package="com.mycompany.package" />
tells spring that it should look on com.mycompany.package and find classes annotated with the following (not only #Component ):
#Controller
#Repository
#Service
#Component
Then Spring will register these classes with the bean factory.
the Spring IoC container consumes a form of configuration metadata; this configuration metadata represents how you as an application developer tell the Spring container to instantiate, configure, and assemble the objects in your application.
Configuration metada are either an xml Configuration or java classes annotated with #Configuration that's where spring stores config informations.