Yesterday I got very strange spring boot behaviour
For example: i'm trying to start server using ./gradlew bootRun:
...
:findMainClass
:bootRun
:: Spring Boot :: (v1.3.1.RELEASE)
2016-01-19 16:37:15.315 INFO 6118 --- [ main] c.e.server.Application$Companion : Starting Application.Companion on fake with PID 6118 (/home/user/code/xproject/server/build/classes/main started by user in /home/user/code/xproject/server)
2016-01-19 16:37:15.320 INFO 6118 --- [ main] c.e.server.Application$Companion : No active profile set, falling back to default profiles: default
2016-01-19 16:37:15.400 INFO 6118 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext#a3ec6b: startup date [Tue Jan 19 16:37:15 GMT 2016]; root of context hierarchy
2016-01-19 16:37:17.908 INFO 6118 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2016-01-19 16:37:17.923 INFO 6118 --- [ main] c.e.server.Application$Companion : Started Application.Companion in 3.048 seconds (JVM running for 3.421)
2016-01-19 16:37:17.924 INFO 6118 --- [ Thread-2] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext#a3ec6b: startup date [Tue Jan 19 16:37:15 GMT 2016]; root of context hierarchy
2016-01-19 16:37:17.930 INFO 6118 --- [ Thread-2] o.s.j.e.a.AnnotationMBeanExporter : Unregistering JMX-exposed beans on shutdown
BUILD SUCCESSFUL
Total time: 23.756 secs
So it doesn't wait for requests as it always did. I thought there are some problems with classpath, so I put few annotated methods as #PostConstruct in Controllers and Services and can confirm that they are called and all dependencies are injected at that point.
Here is my gradle.build:
buildscript {
ext.kotlin_version = '1.0.0-beta-4584'
repositories {
mavenCentral()
jcenter()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.1.RELEASE")
}
}
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'spring-boot'
apply plugin: 'kotlin'
jar {
baseName = 'xproject'
version = '0.1.0'
}
repositories {
mavenCentral()
jcenter()
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.springframework.boot:spring-boot-starter-tomcat")
compile("org.springframework.boot:spring-boot-devtools")
compile 'org.springframework.data:spring-data-mongodb:1.8.2.RELEASE'
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
compile "com.restfb:restfb:1.18.1"
testCompile("junit:junit")
testCompile("org.springframework.boot:spring-boot-starter-test")
}
sourceSets {
main {
java.srcDirs += ['java', 'kotlin']
}
test {
java.srcDirs += 'test'
}
}
UPD#1
Here is Application class(I haven't touch it from the beginning).
#SpringBootApplication
open class Application {
companion object {
#JvmStatic fun main(args: Array<String>) {
SpringApplication.run(Application::class.java, *args)
}
}
}
UPD#2
Small self-contained code
#RestController
#SpringBootApplication
#ComponentScan
public class GreetingController {
public static void main(String[] a) {
SpringApplication.run(GreetingController.class, a);
}
#PostConstruct
public void postConstruct() {
System.out.println("!! Post construct called");
}
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
#RequestMapping("/greeting")
public Greeting greeting(#RequestParam(value="name", defaultValue="World") String name) {
return new Greeting(counter.incrementAndGet(),
String.format(template, name));
}
}
Gives me almost the same result
:: Spring Boot :: (v1.3.1.RELEASE)
2016-01-19 17:18:19.790 INFO 8230 --- [ restartedMain] hello.GreetingController : Starting GreetingController on fake with PID 8230 (/home/user/code/xproject/server/build/classes/main started by user in /home/user/code/xproject/server)
2016-01-19 17:18:19.814 INFO 8230 --- [ restartedMain] hello.GreetingController : No active profile set, falling back to default profiles: default
2016-01-19 17:18:19.918 INFO 8230 --- [ restartedMain] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext#71ceb8: startup date [Tue Jan 19 17:18:19 GMT 2016]; root of context hierarchy
!! Post construct called
2016-01-19 17:18:22.860 INFO 8230 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
2016-01-19 17:18:22.905 INFO 8230 --- [ restartedMain] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2016-01-19 17:18:22.922 INFO 8230 --- [ restartedMain] hello.GreetingController : Started GreetingController in 4.022 seconds (JVM running for 4.949)
2016-01-19 17:18:22.924 INFO 8230 --- [ Thread-8] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext#71ceb8: startup date [Tue Jan 19 17:18:19 GMT 2016]; root of context hierarchy
2016-01-19 17:18:22.930 INFO 8230 --- [ Thread-8] o.s.j.e.a.AnnotationMBeanExporter : Unregistering JMX-exposed beans on shutdown
Process finished with exit code 1
I was having exactly the same issue you just described and in my case, I had forgotten to add spring-boot-starter-web as dependency. I had copy/pasted the dependencies from a basic example just having spring-boot-starter and I misread it.
Once I added it, the container was started normally and I got a regular web app listening at the 8080 port.
It is my first very basic test so it just has spring-boot-starter-web, kotlin-stdlib and kotlin-reflect as dependencies and class that looks like this:
#SpringBootApplication
class Application {
private val log = LoggerFactory.getLogger(Application::class.java)
}
fun main(args: Array<String>) {
SpringApplication.run(Application::class.java, *args)
}
From what I see in your code, the only thing I can think of is that you might require kotlin-reflect as well. I got the idea of including it from this blog post and this sample project also uses it so...
Good luck!
Related
I am new to Spring and Spring Boot and I played around with different ways how to resolve Beans. In my example I've got a Bean that should always be a singleton. What surprises me is that there seems to be a way where this bean is resolved as, I assume, "prototype".
Could anyone explain to me why it's not a singleton when it is resolved in the signature of the method showSingletonBeans?
#SpringBootApplication
class DemoApplication
fun main(args: Array<String>) {
runApplication<DemoApplication>(*args)
}
#Service("stackSingletonBean")
// #Scope("singleton")
class MySingletonBean {
init {
println("Created MySingletonBean " + this.hashCode())
}
}
#RestController
class MyController {
#Autowired
// #Qualifier("singletonBean")
lateinit var memberSingletonBean: MySingletonBean
#Autowired
lateinit var singeltonFactory: ObjectFactory<MySingletonBean>
fun buildSingleton() : MySingletonBean {
return singeltonFactory.`object`
}
#Lookup
fun getSingletonInstance() : MySingletonBean? {
return null
}
#GetMapping("/")
fun showSingletonBeans(#Autowired stackSingletonBean: MySingletonBean) {
println("member " + memberSingletonBean.hashCode() )
println("stack " + stackSingletonBean.hashCode())
println("lookup:" + getSingletonInstance().hashCode())
println("factory: " + buildSingleton().hashCode())
}
}
The log looks like that:
2020-08-13 18:44:32.604 INFO 172175 --- [ main] com.example.demo.DemoApplicationKt : No active profile set, falling back to default profiles: default
2020-08-13 18:44:33.118 INFO 172175 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2020-08-13 18:44:33.124 INFO 172175 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2020-08-13 18:44:33.124 INFO 172175 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.37]
2020-08-13 18:44:33.164 INFO 172175 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2020-08-13 18:44:33.164 INFO 172175 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 528 ms
Created MySingletonBean 1747702724
2020-08-13 18:44:33.286 INFO 172175 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2020-08-13 18:44:33.372 INFO 172175 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2020-08-13 18:44:33.379 INFO 172175 --- [ main] com.example.demo.DemoApplicationKt : Started DemoApplicationKt in 1.011 seconds (JVM running for 1.24)
2020-08-13 18:44:37.341 INFO 172175 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2020-08-13 18:44:37.341 INFO 172175 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2020-08-13 18:44:37.344 INFO 172175 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 3 ms
Created MySingletonBean 562566586
member 1747702724
stack 562566586
lookup:1747702724
factory: 1747702724
Created MySingletonBean 389331797
member 1747702724
stack 389331797
lookup:1747702724
factory: 1747702724
Resolving controller method parameters is actually quite different mechanism. It has nothing to do with dependency injection and the #Autowired annotation: the annotation can be removed and it won't change the behavior.
Although #Autowired can technically be declared on individual method or constructor parameters since Spring Framework 5.0, most parts of the framework ignore such declarations. The only part of the core Spring Framework that actively supports autowired parameters is the JUnit Jupiter support in the spring-test module (see the TestContext framework reference documentation for details).
https://docs.spring.io/
In your case, the stackSingletonBean is instantiated by the ModelAttributeMethodArgumentResolver. It's not aware of the #Service annotation nor of its scope: it simply uses the default constructor on each request.
Model attributes are sourced from the model, or created using a default constructor and then added to the model.
Note that use of #ModelAttribute is optional — for example, to set its attributes. By default, any argument that is not a simple value type( as determined by BeanUtils#isSimpleProperty) and is not resolved by any other argument resolver is treated as if it were annotated with #ModelAttribute. Web on Reactive Stack
I am trying to create a simple Spring Boot project which uses spring data jpa for DB interactions.
Application Class:
package org.railway.fms.documentmgmt;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
#SpringBootApplication
#EnableJpaRepositories(basePackages = {"org.railway.fms.documentmgmt.repository"})
#EntityScan(basePackages= {"org.railway.fms.documentmgmt.entities"})
public class FMSApplication {
public static void main(String[] args) {
SpringApplication.run(FMSApplication.class, args);
}
}
Controller Class:
package org.railway.fms.documentmgmt;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class NatureOfDocumentRestService {
#GetMapping("/document/nature")
public String getNatureOfDocuments() {
return "test";
}
}
build.gradle file :
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:2.1.4.RELEASE")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
bootJar {
baseName = 'document-mgmt'
version = '0.1.0'
}
repositories {
mavenCentral()
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
compile ("org.springframework.boot:spring-boot-starter-web")
implementation ("org.springframework.boot:spring-boot-starter-data-jpa")
implementation ("org.postgresql:postgresql")
testCompile("junit:junit")
}
application.properties
# Database
spring.datasource.url=jdbc:postgresql://localhost:5444/db?currentSchema=fms
spring.datasource.username=username
spring.datasource.password=password
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto = update
spring.jpa.show-sql=true
The problem I am facing is when not using org.springframework.boot:spring-boot-starter-data-jpa dependency in my build.gradle file, I am able to successfully hit my controller from the browser.
But when I am using the org.springframework.boot:spring-boot-starter-data-jpa then the controller is not loaded in spring context and I am unable to hit the controller from my browser.
How do I use spring-data-jpa in my spring boot project containing exposed web sevices, please help !
Note : there is no error in logs, application starts successfully.
logs:
2019-06-10 09:52:11.348 INFO 15540 --- [ main] o.r.fms.documentmgmt.FMSApplication : Starting FMSApplication on abcd with PID 15540 (C:\Users\furquan.ahmed\Workspaces\fmsWorkspace\document-mgmt\bin\main started by furquan.ahmed in C:\Users\furquan.ahmed\Workspaces\fmsWorkspace\document-mgmt)
2019-06-10 09:52:11.354 INFO 15540 --- [ main] o.r.fms.documentmgmt.FMSApplication : No active profile set, falling back to default profiles: default
2019-06-10 09:52:12.200 INFO 15540 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data repositories in DEFAULT mode.
2019-06-10 09:52:12.228 INFO 15540 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 13ms. Found 0 repository interfaces.
2019-06-10 09:52:13.083 INFO 15540 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$5149c32d] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-06-10 09:52:14.106 INFO 15540 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2019-06-10 09:52:14.161 INFO 15540 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2019-06-10 09:52:14.162 INFO 15540 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.17]
2019-06-10 09:52:14.402 INFO 15540 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2019-06-10 09:52:14.402 INFO 15540 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 2968 ms
2019-06-10 09:52:14.714 INFO 15540 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2019-06-10 09:52:18.002 INFO 15540 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2019-06-10 09:52:18.099 INFO 15540 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [
name: default
...]
2019-06-10 09:52:18.267 INFO 15540 --- [ main] org.hibernate.Version : HHH000412: Hibernate Core {5.3.9.Final}
2019-06-10 09:52:18.268 INFO 15540 --- [ main] org.hibernate.cfg.Environment : HHH000206: hibernate.properties not found
2019-06-10 09:52:18.494 INFO 15540 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.0.4.Final}
2019-06-10 09:52:19.060 INFO 15540 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect
If there's no direct need to explicitly state the basePackages for #EnableJpaRepositories and #EntityScan, I would suggest letting Spring find out the locations by means of auto-configuration, as all your classes are located in org.railway.fms.documentmgmt:
#SpringBootApplication
#EnableJpaRepositories
public class FMSApplication { ... }
Otherwise, try adding a #ComponentScan to state the location of Spring components:
#SpringBootApplication
#EnableJpaRepositories(basePackages = "org.railway.fms.documentmgmt.repository")
#EntityScan(basePackages= "org.railway.fms.documentmgmt.entities")
#ComponentScan(basePackages= "org.railway.fms.documentmgmt")
public class FMSApplication { ... }
Furthermore, if you do need to state the base package location, there's also the option to use basePackageClasses instead of basePackages, which is a type-safe alternative.
As you mentioned
The problem I am facing is when not using org.springframework.boot:spring-boot-starter-data-jpa dependency in my build.gradle file, I am able to successfully hit my controller from the browser.
But when I am using the org.springframework.boot:spring-boot-starter-data-jpa then the controller is not loaded in spring context and I am unable to hit the controller from my browser.
I think when you are adding org.springframework.boot:spring-boot-starter-data-jpa you may be forgetting to add db config in in application.properties
If I'm correct then add below properties in application.properties file and replace the values with specific to you db
spring.jpa.hibernate.ddl-auto=create
spring.datasource.url=jdbc:mysql://localhost:3306/db_example
spring.datasource.username=springuser
spring.datasource.password=ThePassword
in case you have already added these properties. Could you please provide logs and stack trace to see what errors are you getting.
Try to define below properties in your application.properties file.
server.servlet.context-path
spring.data.rest.base-path
Now access your controller mappings using the context-path and the rest repository mappings using rest.base-path.
I'm running a spring boot application with a scheduled task. It is divided into two maven projects, lets call them 'lib' and 'app'.
The class whose method is annotated with #Scheduled is located in 'lib' project. It does not contain any classes annotated with #SpringBootApplication, or any classes that start a spring application. Here's what Scheduled bean looks like:
#Component
public class Refresher {
#Scheduled(fixedRate = 30000)
public void refresh() {
...
}
The 'lib' project also has a simple SchedulingConfigurer implementation that tells Spring to use ThreadPoolTaskScheduler with its Scheduled tasks.
The 'app' project, on the other hand, has a dependency on 'lib' and has a class annotated with #SpringBootApplication, and starts it as usual:
#SpringBootApplication(scanBasePackages = {"x.y", "x.y.z"})
#EnableScheduling
public class ExampleService {
public static void main(String[] args) {
SpringApplication.run(ExampleService.class, args);
}
}
Both maven projects have this:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
<relativePath/>
</parent>
So, when ExampleService starts I see it finds Refresher and executes its refresh method once every 30 sec alright, but something strange appears in the logs. When Example service starts, it prints:
2019-01-11 18:18:27.647 INFO 6428 --- [ main] x.y.z.ExampleService : Started ExampleService in 32.613 seconds (JVM running for 40.37)
This is great, it tells me that main application has started. But then I get the following lines every 30 seconds, every time Refresher gets executed:
2019-01-11 18:18:58.596 INFO 6428 --- [nio-8080-exec-3] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext#66e31414: startup date [Fri Jan 11 18:18:58 MSK 2019]; root of context hierarchy
2019-01-11 18:18:58.637 INFO 6428 --- [nio-8080-exec-3] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$7c355e31] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
... some logging from the refresh() method
2019-01-11 18:19:01.020 INFO 6428 --- [nio-8080-exec-3] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext#1262db58: startup date [Fri Jan 11 18:19:01 MSK 2019]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext#66e31414
2019-01-11 18:19:01.035 INFO 6428 --- [nio-8080-exec-3] o.s.boot.SpringApplication : Started application in 3.585 seconds (JVM running for 73.771)
2019-01-11 18:19:01.035 INFO 6428 --- [nio-8080-exec-3] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext#1262db58: startup date [Fri Jan 11 18:19:01 MSK 2019]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext#66e31414
2019-01-11 18:19:01.035 INFO 6428 --- [nio-8080-exec-3] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext#66e31414: startup date [Fri Jan 11 18:18:58 MSK 2019]; root of context hierarchy
Notice 'Started application in 3.585 seconds (JVM running for 73.771)'. This happens every 30 seconds. It looks like in order to run the Scheduled bean Spring runs a new separate Spring application every time. Why would it do that, and can this be avoided? Can Scheduled bean run as part of currently started Spring Boot app?
The CamelContextStartedEvent is called twice for the same camel context (camel-1). The issue might be the way I register the EventNotifier. You can reproduce the issue with Spring Initializr with Spring Boot 1.5.14, Spring Boot Camel Starter 2.21.1 and Spring Boot Web Starter.
See the logs:
2018-07-06 11:04:41.104 INFO 19092 --- [ main] o.a.camel.spring.SpringCamelContext : Apache Camel 2.21.1 (CamelContext: camel-1) is starting
2018-07-06 11:04:41.106 INFO 19092 --- [ main] o.a.c.m.ManagedManagementStrategy : JMX is enabled
2018-07-06 11:04:41.191 INFO 19092 --- [ main] o.a.camel.spring.SpringCamelContext : StreamCaching is not in use. If using streams then its recommended to enable stream caching. See more details at http://camel.apache.org/stream-caching.html
2018-07-06 11:04:41.193 INFO 19092 --- [ main] o.a.camel.spring.boot.RoutesCollector : Starting CamelMainRunController to ensure the main thread keeps running
2018-07-06 11:04:41.193 INFO 19092 --- [ main] o.a.camel.spring.SpringCamelContext : Total 0 routes, of which 0 are started
2018-07-06 11:04:41.194 INFO 19092 --- [ main] o.a.camel.spring.SpringCamelContext : Apache Camel 2.21.1 (CamelContext: camel-1) started in 0.090 seconds
2018-07-06 11:04:41.195 INFO 19092 --- [ main] c.e.bug.service.StartupEventNotifier : CamelContextStartedEvent for SpringCamelContext(camel-1) with spring id application:11223
2018-07-06 11:04:41.195 INFO 19092 --- [ main] c.e.bug.service.StartupEventNotifier : CamelContextStartedEvent for SpringCamelContext(camel-1) with spring id application:11223
2018-07-06 11:04:41.216 INFO 19092 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 11223 (http)
2018-07-06 11:04:41.221 INFO 19092 --- [ main] com.example.bug.BugApplication : Started BugApplication in 4.684 seconds (JVM running for 6.773)
The service that initializes the EventNotifier:
#Service
public class SchedulerService {
private final CamelContext camelContext;
private final StartupEventNotifier startupEventNotifier;
public SchedulerService(CamelContext camelContext, StartupEventNotifier startupEventNotifier) {
this.camelContext = camelContext;
this.startupEventNotifier = startupEventNotifier;
}
#PostConstruct
public void init() {
camelContext.getManagementStrategy().addEventNotifier(startupEventNotifier);
}
}
The EventNotifier:
#Component
public class StartupEventNotifier extends EventNotifierSupport {
private static final Logger logger = LoggerFactory.getLogger(StartupEventNotifier.class);
#Override
public void notify(EventObject event) throws Exception {
if (event instanceof CamelContextStartedEvent) {
logger.info("CamelContextStartedEvent for {}", event.getSource());
}
}
#Override
public boolean isEnabled(EventObject event) {
if (event instanceof CamelContextStartedEvent) {
return true;
}
return false;
}
}
application.yml:
camel:
springboot:
main-run-controller: true
server:
port: 11223
It is called twice, because it is registered twice. Once by you and once by Apache Camel. EventNotifier is registered automatically, if is found in Registry. Since your StartupEventNotifier is annotated as Component, it is part of Registry and Apache Camel registered it during CamelContext startup (You can see it in CamelAutoConfiguration line 424).
You have four options:
Remove your custom registration from SchedulerService.
Remove #Component annotation from StartupEventNotifier and register it with with camelContext.getManagementStrategy().addEventNotifier(new StartupEventNotifier())
Add duplicity check to your SchedulerService. Something like:
if (!context.getManagementStrategy().getEventNotifiers().contains(startupEventNotifier)){
context.getManagementStrategy().addEventNotifier(startupEventNotifier);
}
Register EventNotifier in #PostConstruct of RouteBuilder. It will be registered before automatic discovery is started and then it will be skipped in CamelAutoConfiguration (See line 422)
I've created a spring boot project and added
compile('net.sf.dozer:dozer:5.5.1')
to dependencies. But the class, org.dozer.Mapper, is not recognized by my app.
I run gradle clean, gradle buildDependents and gradle build.
But things did not changed.
What should I do ?
my build.gradle
buildscript {
ext {
springBootVersion = '2.0.0.RC1'
}
repositories {
mavenCentral()
maven { url "https://repo.spring.io/snapshot" }
maven { url "https://repo.spring.io/milestone" }
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'com.everglowtrading'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
maven { url "https://repo.spring.io/snapshot" }
maven { url "https://repo.spring.io/milestone" }
maven { url "https://repository.jboss.org/nexus/content/repositories/releases" }
}
dependencies {
compile('org.springframework.boot:spring-boot-starter-aop')
compile('org.flywaydb:flyway-core')
compile('org.springframework.boot:spring-boot-starter-hateoas')
compile('org.mybatis.spring.boot:mybatis-spring-boot-starter:1.3.1')
compile('org.springframework.boot:spring-boot-starter-thymeleaf')
compile('org.springframework.boot:spring-boot-starter-web')
compile('org.springframework.boot:spring-boot-starter-webflux')
compile('org.springframework.data:spring-data-commons')
compile('com.h2database:h2')
compile('net.sf.dozer:dozer:5.5.1')
runtime('org.springframework.boot:spring-boot-devtools')
runtime('com.h2database:h2')
compileOnly('org.projectlombok:lombok')
testCompile('org.springframework.boot:spring-boot-starter-test')
testCompile('io.projectreactor:reactor-test')
}
The controller
package com.myproject.stock.controllers;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import javax.servlet.http.HttpServletResponse;
import org.dozer.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import com.myproject.stock.domain.model.Stock;
import com.myproject.stock.domain.repository.StockCriteria;
import com.myproject.stock.form.StockListForm;
import com.myproject.stock.service.StockService;
#RestController
public class StockController {
private static final int DEFAULT_PAGEABLE_SIZE = 5;
#Autowired
Mapper beanMapper;
#Autowired
StockService<Integer> stockService;
#Autowired
MessageSource msg;
#RequestMapping("/")
void index(HttpServletResponse response) throws IOException {
response.sendRedirect("/stock");
}
#RequestMapping("/stock")
public ModelAndView stock(ModelAndView mav) {
Stock stock = stockService.getItems(11);
List<Stock> stockList = stockService.getAllItems();
String message = msg.getMessage("stock.label", null, Locale.JAPAN);
mav.addObject("stock_id", stock.getId());
mav.addObject("stockList", stockList);
mav.addObject("message", message);
mav.addObject("stockBuildingName", stock.getBuilding_name());
mav.setViewName("stock/search/index");
return mav;
}
#RequestMapping("/stock/search")
public String index(#Validated StockListForm stockListForm
, BindingResult bindingResult
, Pageable pageable
, Model model) {
StockCriteria criteria = beanMapper.map(stockListForm, StockCriteria.class);
Page<Stock> page = stockService.findPageByCriteria(criteria, pageable);
model.addAttribute("page", page);
return "stock/search/index";
}
}
the error message
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.0.0.RC1)
2018-02-19 22:15:35.648 INFO 7950 --- [ restartedMain] c.e.wms.stock.WmsApplication : Starting WmsApplication on YatabeMBP.local with PID 7950 (/Users/ayatabe/dev/wms-stock/build/classes/java/main started by ayatabe in /Users/ayatabe/dev/wms-stock)
2018-02-19 22:15:35.648 INFO 7950 --- [ restartedMain] c.e.wms.stock.WmsApplication : No active profile set, falling back to default profiles: default
2018-02-19 22:15:35.695 INFO 7950 --- [ restartedMain] ConfigServletWebServerApplicationContext : Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext#82f0a7d: startup date [Mon Feb 19 22:15:35 JST 2018]; root of context hierarchy
2018-02-19 22:15:36.772 INFO 7950 --- [ restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$d86c709b] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2018-02-19 22:15:37.104 INFO 7950 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 9090 (http)
2018-02-19 22:15:37.114 INFO 7950 --- [ restartedMain] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2018-02-19 22:15:37.114 INFO 7950 --- [ restartedMain] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.27
2018-02-19 22:15:37.127 INFO 7950 --- [ost-startStop-1] o.a.catalina.core.AprLifecycleListener : The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: [/Users/ayatabe/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.]
2018-02-19 22:15:37.209 INFO 7950 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2018-02-19 22:15:37.209 INFO 7950 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1517 ms
2018-02-19 22:15:37.369 INFO 7950 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Servlet dispatcherServlet mapped to [/]
2018-02-19 22:15:37.371 INFO 7950 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Servlet webServlet mapped to [/h2console/*]
2018-02-19 22:15:37.374 INFO 7950 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*]
2018-02-19 22:15:37.374 INFO 7950 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2018-02-19 22:15:37.374 INFO 7950 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2018-02-19 22:15:37.374 INFO 7950 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*]
2018-02-19 22:15:37.415 WARN 7950 --- [ restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'stockController': Unsatisfied dependency expressed through field 'beanMapper'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.dozer.Mapper' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
2018-02-19 22:15:37.417 INFO 7950 --- [ restartedMain] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
2018-02-19 22:15:37.434 INFO 7950 --- [ restartedMain] ConditionEvaluationReportLoggingListener :
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2018-02-19 22:15:37.550 ERROR 7950 --- [ restartedMain] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Field beanMapper in com.myproject.stock.controllers.StockController required a bean of type 'org.dozer.Mapper' that could not be found.
Action:
Consider defining a bean of type 'org.dozer.Mapper' in your configuration.
You haven't define a bean for org.dozer.Mapper type so Spring can't inject a proper instance to your controller class.
The simplest way to define this bean is to add following method to your main Spring application class:
#Bean
public Mapper mapper() {
return new DozerBeanMapper();
}
Alternatively you can put it in any #Configuration annotated class.
For those who might run into the same problem as me:
Add #MapperScan("yourMapperPath") at your spring boot main launch class. If the notation shows as red, reimport your mybatis-spring-boot-starter dependency:
Go to your project pom.xml > right click on the artifactId > Maven > Reimport
I thought I have imported the dependency days ago, but the project didn't.