I am following this tutorial to build a basic application with Spring. It is working flawlessly as long as I follow this sub-directory structure:
└── src
└── main
└── java
└── hello
If I move my Application.java and ScheduledTasks.java classes out of the hello package I get the following error:
** WARNING ** : Your ApplicationContext is unlikely to start due to a `#ComponentScan` of the default package.
And a few seconds later, indeed...
java.lang.IllegalStateException: ApplicationEventMulticaster not initialized - call 'refresh' before multicasting events via the context: org.springframework.context.annotation.AnnotationConfigApplicationContext#71fa8894: startup date [Wed Jan 18 22:19:12 CET 2017]; root of context hierarchy
My question is, why do I need to put my classes into a package? What use does it have? How can I avoid this error? Do I really need to use packages if it is a really simple application?
Put your java files again to hello package.
When a class doesn’t include a package declaration it is considered to be in the “default package”. The use of the “default package” is generally discouraged, and should be avoided.
It can cause particular problems for Spring Boot applications that use #ComponentScan, #EntityScan or #SpringBootApplication annotations, since every class from every jar, will be read.
Read more here.
I moved the class annotated with #SpringBootApplication from the default package to a specific package and it worked.
I had created a blank Maven folder where Java folder was the last one. I added class MainApplication.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
Further, I had to create a package within Java folder such as com.test and then I moved my MainApplication class into it. Note "package com.test;" Now this default package Spring boot is looking for.
package com.test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
Then it worked fine.
Related
I created a spring boot application(3.0.1). Then I connected the Postgres database and executed it. The application is up on server 8080 smoothly. then I added below-mentioned annotations.
#EnableAutoConfiguration
#ComponentScan
whole file,
package com.example.SpringRecap;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
#SpringBootApplication
#EnableAutoConfiguration
#ComponentScan
public class SpringRecapApplication {
public static void main(String[] args) {
SpringApplication.run(SpringRecapApplication.class, args);
}
#GetMapping("/")
public void Employee() {
}
}
Now, below mentioned error are appeared,
Redundant declaration: #SpringBootApplication already applies #EnableAutoConfiguration
Redundant declaration: #SpringBootApplication already applies given #ComponentScan
Image of InteliJ:
If anyone knows the reason, please help me. If further information is needed to solve the problem please put a comment here.
Thank You.
below mentioned error are appeared: This means that you can remove #ComponentScan and #EnableAutoConfiguration.
As the documentation on spring mentioned, it is included in #SpringBootApplication:
Many Spring Boot developers like their apps to use auto-configuration, component scan and be able to define extra configuration on their "application class". A single #SpringBootApplication annotation can be used to enable those three features, that is:
#EnableAutoConfiguration: enable Spring Boot’s auto-configuration mechanism
#ComponentScan: enable #Component scan on the package where the application is located (see the best practices)
#Configuration: allow to register extra beans in the context or import additional configuration classes
It is a check in the plugin of Intellij. Also see https://youtrack.jetbrains.com/issue/IDEA-177632
I have a multi-module build using Gradle. There are 2 INDEPENDENT (not using packages from project 1 to project 2) but related spring projects in it. 1 of the projects is working as expected but 2nd project is not scanning any beans either in the same package or in sub packages.
Below are the things that I have tried (including the comments). None of the things worked except ImportAutoConfiguration and mentioning the classes which I wanted to import.
#SpringBootApplication(scanBasePackages = {"io.comany.logs.functionality"})
//#ImportAutoConfiguration( classes = {Test.class, DecorationManager.class, Consumer.class})
//#ComponentScan(basePackages = {"io.comany.logs.functionality"})
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
I have verified that my package names are correct. The main class is present in the package io.comany.logs.functionality and the classes I want to scan are in the pacakge io.comany.logs.functionality.kafka
Edit : Copied the same project and created another standalone project, it still doesn't work. So the problem should ideally not be with gradle config.
I've written an interceptor to generate service logs for a SpringBoot Java Rest API. I have the code below to define the custom WebMvcConfigurer:
package com.gem.common.interceptors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
#Configuration
public class InterceptorConfig implements WebMvcConfigurer {
#Autowired
LoggerInterceptor logInterceptor;
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(logInterceptor);
}
}
I'd like to use this InterceptorConfig across different modules. Can I package it and use it or do I need to define it in each module?
I suppose with "other modules" you are asking if you could make that code available to other spring boot applications too?
If that's the case - then: yes you can package it in a jar and add it as a dependency to all your other modules. I'll post the way to do this just below, however - just to warn you - if it's just for that simple class, the solution is not going to be worth it.
In short, what you'd need to do is to create your own external artifact (this usually is done via maven or gradle. You create a new maven project for your shared code. It will need to depend on some base libraries so that you have your #Configuration annotation available. Put your class as described in that project, and create a file src/main/resources/META-INF/spring.factories file. There you'll need to point to that class.
Then you build that project and upload the resulting jar to a package repository. Once that's done, you can add it as a dependency to your project. At startup, Spring boot will find the spring.factories file and automatically include the classes that are mentioned there in its initialization.
Please also note, that this is just a high level explanation and you will need more details. Spring has good documentation on this use case and they also have a demo project to show this extension mechanism.
I have a myapp parent pom type maven project with myapp-core and myapp-web modules. myapp-core module is added as dependency to myapp-web.
All the classes in myapp-core module reside in root package com.myapp.core and all classes in myapp-web module reside in root package com.myapp.web
The main Application.java is also in com.myapp.web package. As my core module root package is different I am including common base package "com.myapp" for ComponentScan as follows:
#Configuration
#ComponentScan(basePackages="com.myapp")
#EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Now the surprising thing is if I run this app using Run As -> Spring Boot App it is working fine. But if I run it as Run As -> Java Application it is failing with error saying it can't found beans defined in myapp-core module.
If I move my Application.java to com.myapp package it is working fine.
It should work even if i run it as Java Application also, right?
After enabling debug log level for spring and going through extensive logs I found that scanning for various components like JPA Repositories, JPA Entities etc are depending on the Application.java's package name.
If the JPA Repositories or Entities are not in sub packages of Application.java's package then we need to specify them explicitly as follows:
#Configuration
#ComponentScan(basePackages="com.sivalabs.jcart")
#EnableAutoConfiguration
#EnableJpaRepositories(basePackages="com.sivalabs.jcart")
#EntityScan(basePackages="com.sivalabs.jcart")
public class Application{
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
With the above additional #EnableJpaRepositories, #EntityScan I am able to run it using Run As -> Java Application.
But still not sure how it is working fine when Run As -> Spring Boot App!!
Anyway I think it is better to move my Application.java to com.myapp package rather than fighting with SpringBoot!
I have the same problem. Only adding the #EnableJpaRepositories annotation can solve the issue. I tried to define basePackages in #SpringBootApplication, to no avail.
I think the package of the Application class is fed to the scanning process of JpaRepositories, but other packages defined in #SpringBootApplication are ignored.
It looks like a bug/improvement of Spring Boot.
I had a similar issue with Redis repositories that was fixed in a similar way:
#Configuration
#EnableConfigurationProperties({RedisProperties.class})
#RequiredArgsConstructor
#EnableRedisRepositories(basePackages = {"com.example.another"})
public class RedisConfig {
private final RedisConnectionFactory redisConnectionFactory;
#Bean
public RedisTemplate<?, ?> redisTemplate() {
RedisTemplate<byte[], byte[]> template = new RedisTemplate<byte[], byte[]>();
template.setConnectionFactory(redisConnectionFactory);
template.afterPropertiesSet();
return template;
}
}
I'm trying to use a spring getting started project, and I have a problem I cannot figure out: when I move the restController from the default "hello" package to another one (say com.mydomain.controllers) I get a 404 error page. Any ideas how to solve this?
PS: I'm using intellij + gradle
In this case, this controller is located in a package that's not scanned by Spring. In the Application class:
package hello;
#SpringBootApplication
public class Application {
//...
}
The #SpringApplication annotation is a convenience annotation - see the full explanation in the guide itself.
If you want to scan other locations and customize more your configuration, you can change your application class to this:
package hello;
#Configuration
#EnableAutoConfiguration
#ComponentScan({"hello", "com.mydomain.controllers"})
public class Application {
//...
}