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.
Related
What is the difference between Spring Boot's auto-configuration and auto-wiring?
Is it that, autowiring is injection of a Bean into another class, and auto-configuration is the term used for complete auto-wired application?
Auto-configuration in Spring refers to what Spring does for you to configure your application based on the dependencies that you have added. Instead of having bean definitions and having to configure your own stuff in Spring MVC (Do you remember the amount of xml configs you had to do?), Spring Boot essentially "listens" for things on your class path, and if it's something that it's able to auto-configure for you, it'll do so.
The #SpringBootApplication annotation automatically opts you into having Spring automatically configure various beans for you.
You are correct in the sense that auto-wiring relates to Dependency Injection. Having the annotation #Autowired inside one of your classes, means that you bring an instance of the class that's being annotated, into the class that the annotation exists in.
● #SpringBootApplication
If you don’t want to use #SpringBootApplication, the #EnableAutoConfiguration and #ComponentScan annotations that it imports defines that behaviour so you can also use that instead.
#SpringBootApplication actually defines #EnableAutoConfiguration and #ComponentScan
● #EnableAutoConfiguration
Spring Boot auto-configuration attempts to automatically configure your Spring application based on the jar dependencies that you have added
● #ComponentScan
All of your application components (#Component, #Service, #Repository, #Controller etc.) are automatically registered as Spring Beans.
● #Autowired is used for dependency injection
I'm trying to create project structure that would allow me to add/remove modules by simply having them on classpath. With #ComponentScan("com.companyname") annotation in my Spring Application it detects and creates annotated components from modules. But I get errors when trying to autowire my CrudRepository anywhere:
Field repo in com.companyname.somemodule.services.SomeService required a bean of type 'com.companyname.somemodule.repos.SomeRepo' that could not be found.
So I thought that maybe it somehow can't create repos if they are defined in one of modules, so I wen't ahead and added test repo to my base SpringApplication and to my surprise I got:
Field repo in com.companyname.modularapp.TestService required a bean of type 'com.companyname.modularapp.TestRepo' that could not be found.
Then I just removed my #ComponentScan annotation and suddenly TestRepo worked as I intended, I was able to persist and read Test entities normally. So apparently ComponentScan somehow either screw up creation of CrudRepository, or it's later detection.
I define my repos like this:
#Entity
public class Test {
#Id
private long id;
}
public interface TestRepo extends CrudRepository<Test, Long>{}
I'm trying out Spring Boot 2.0.0.M7 with this project but I doubt that's the cause.
Did I miss something?
Also you can define package for Repositories scan by :
#EnableJpaRepositories("com.companyname")
or in XML config
<jpa:repositories base-package="com.companyname"/>
If you are using spring-boot you might as well drop the #ComponentScan annotation, as there is one already defined in the #SpringBootApplication annotation. Maybe there's a conflict of some sort between them, it's hard to tell without looking at the code.
If you customizing package scans in your project, then probably you need to manually configure bean which requires path to scan, e.g. for JPA you can create your own bean of LocalContainerEntityManagerFactoryBean (you can find auto-configuration example here -
org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration#entityManagerFactory - class link from spring-boot 1.5.*).
But, if you do not require package scan customization, just put class annotated with #SpringBootApplication in project root, and pass it to spring::run method.
I am working on a Spring boot application that uses Spring JPA with PostgreSQL. I am using #SpringBootTest(classes = <my package>.Application.class) to initialize my unit test for a controller class.
The problem is that this is causing the entityManagerFactory bean (and many other objects related to jpa, datasource, jdbc, etc.) to be created which is not needed for unit tests. Is there a way to prevent Spring from automatically creating these objects till they are actually used the first time?
I spent a lot of time trying to load up only the beans I need for my unit test but ran into many errors. I am relatively new to Spring and I am hoping someone else has run into this before...and can help. I can post code snippets if needed.
Update: I am not sure if I should edit or answer my own question...choosing to edit since I ended up changing my approach to unit tests. I added this to my test config class.
#Configuration
#ComponentScan(basePackages = {"api.controller", "api.config", "api.utils"})
public class TestControllerConfig {
}
and I mocked out the service and repository classes.
You can disable auto configuration in spring-boot using exclude attribute of #EnableAutoConfiguration, as follows:
#Configuration
#EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
public class TestConfig {
}
From #EnableAutoConfiguration documentation:
If the class is not on the classpath, you can use the excludeName attribute of the annotation and specify the fully qualified name instead. Finally, you can also control the list of auto-configuration classes to exclude via the spring.autoconfigure.exclude property.
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.
I need a mechanism to descide which components should be included into the application context. Currently, I use #Import for it. Whether it works, #Import is for #Configuration only. Is there an alternative?
EDIT:
I use #ComponentScan to register spring beans and components. I have a directory with controllers annotated with #Controller. For testing purpose I do not want to register all controllers, but only specific. Can I use something like
Currently I use
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = TestConfiguration.class)
#Transactional
#TransactionConfiguration(defaultRollback = true){/*testings*/}
#Configuration
#EnableAutoConfiguration
#ComponentScan(basePackageClasses = {AccountsRepository.class, LogoutService.class})
#Import({AccountCommandsController.class})
public class TestConfiguration {}
#Import works for me, but its for Configurations only, not for registering controller components. Is there an equaliant for controllers or components?
If are using Spring 3.1 you should really be using Spring Profiles for situations where you conditionally need to include beans in the application context. It makes setting up tests very easy
If you are using Spring 4 and your needs are not covered by profiles, you can look into Spring's #Conditional support
If you use that way, there is no need to use #Include. Just have regular #Configuration classes where either the whole class is annotated with #Profile or specific #Bean methods (only supported in Spring 4)
You can then activate whatever profiles the specific test requires by using #ActiveProfiles