I'm learning SpringBoot. My (trivial) problem is I can't get the run() method from the CommandLineRunner Interface to be called by SpringBoot.
I'm using Java 8 , Eclipse Oxygen ,Maven and i'm running my project as a "Spring Boot App".
Code is:
package com.clarivate.dataviewer;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class DvMain implements CommandLineRunner{
static Logger logger = LogManager.getRootLogger();
public static void main(String[] args) {
logger.debug("DS1A in main()");
//SpringApplication.run(DvMain.class, args);
SpringApplication app = new SpringApplication(DvMain.class);
//ConfigurableApplicationContext app = SpringApplication.run(DvMain.class, args);
logger.debug("DS1B in main()");
app.run(args);
}
#Override
public void run(String... args) throws Exception {
// This does not get called
logger.debug("DS4 this line is never printed");
}
}
The overridden run() method does not get called.
I've tried creating a separate class that implements CommandLineRunner but same problem. The console trace is:
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/C:/Users/44/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/C:/Users/44/.m2/repository/org/apache/logging/log4j/log4j-slf4j-impl/2.10.0/log4j-slf4j-impl-2.10.0.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]
12:58:42.225 [main] DEBUG - DS1A in main()
12:58:42.289 [main] DEBUG - DS1B in main()
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.0.2.RELEASE)
2018-06-20 12:58:42.614 INFO 16924 --- [ main] com.clarivate.dataviewer.DvMain : Starting DvMain on 44-TPD-A with PID 16924 (C:\workspace_oxyegen\dataviewer\target\classes started by 44 in C:\workspace_oxyegen\dataviewer)
2018-06-20 12:58:42.615 INFO 16924 --- [ main] com.clarivate.dataviewer.DvMain : No active profile set, falling back to default profiles: default
2018-06-20 12:58:42.655 INFO 16924 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext#6b4a4e18: startup date [Wed Jun 20 12:58:42 BST 2018]; root of context hierarchy
2018-06-20 12:58:43.266 INFO 16924 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2018-06-20 12:58:43.279 INFO 16924 --- [ main] com.clarivate.dataviewer.DvMain : Started DvMain in 0.988 seconds (JVM running for 1.684)
2018-06-20 12:58:43.294 INFO 16924 --- [ Thread-2] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext#6b4a4e18: startup date [Wed Jun 20 12:58:42 BST 2018]; root of context hierarchy
2018-06-20 12:58:43.296 INFO 16924 --- [ Thread-2] o.s.j.e.a.AnnotationMBeanExporter : Unregistering JMX-exposed beans on shutdown
I'm sure i've made a simple mistake but I just can't see it. Any help appreciated.
Add logging.level.root=debug to your application.properties file.
By default Spring boot does not display debug level logging. The first debug messages are shown because they are called before your Spring application has started.
Firstly, the call is coming to your run method. But doesn't log anything because there are couple of issues with your logger. You can use System.out.println(...) to confirm this.
Change your Logger declaration as below.
private static final Logger logger = LoggerFactory.getLogger(DvMain.class);
You are not using correct libraries. Use Logger from slf4j and not log4j
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
That is because your DvMain class is not annotated itself as Spring context #Component, so spring can not find your pojo to execute the run method that you override.
To solve just add #Component to the class, and you will see the traces at log.
Related
I have below project structure
The main project DEMO has a dependency on the Gradle project SERVICE which implements the interface from the PORT project.
Demo build.gradle
dependencies {
implementation project(':port')
runtime project(':service')
}
Service build.gradle
dependencies {
implementation project(':port')
implementation("javax.annotation:javax.annotation-api:1.3.2")
compile "io.micronaut:micronaut-inject:2.4.0"
annotationProcessor "io.micronaut:micronaut-inject-java:2.4.0"
}
Service class implement IStartUpPort
#Singleton
public class StartUpService implements IStartUpPort {
#Override
public void toUpperCase() {
System.out.println("Something happened");
}
}
Port build.gradle
dependencies {
implementation("javax.annotation:javax.annotation-api:1.3.2")
compile "io.micronaut:micronaut-inject:2.4.0"
annotationProcessor "io.micronaut:micronaut-inject-java:2.4.0"
}
Port interface
public interface IStartUpPort {
void toUpperCase();
}
In the main project, I am doing the DI on a service project and facing the exception
#Singleton
public class StartUp implements ApplicationEventListener<StartupEvent> {
private final IStartUpPort iStartUpPort;
public StartUp(IStartUpPort iStartUpPort) {
this.iStartUpPort = iStartUpPort;
}
#Override
public void onApplicationEvent(StartupEvent event) {
iStartUpPort.toUpperCase();
}
}
Exception
Message: No bean of type [fete.bird.IStartUpPort] exists. Make sure the bean is not disabled by bean requirements (enable trace logging for 'io.micronaut.context.condition' to check) and if the bean is enabled then ensure the class is declared a bean and annotation processing is enabled (for Java and Kotlin the 'micronaut-inject-java' dependency should be configured as an annotation processor).
Path Taken: new StartUp([IStartUpPort iStartUpPort])
at io.micronaut.context.AbstractBeanDefinition.getBeanForConstructorArgument(AbstractBeanDefinition.java:1034)
at com.example.$StartUpDefinition.build(Unknown Source)
at io.micronaut.context.DefaultBeanContext.doCreateBean(DefaultBeanContext.java:1943)
at io.micronaut.context.DefaultBeanContext.addCandidateToList(DefaultBeanContext.java:3091)
at io.micronaut.context.DefaultBeanContext.getBeanRegistrations(DefaultBeanContext.java:2968)
at io.micronaut.context.DefaultBeanContext.getBeansOfType(DefaultBeanContext.java:762)
at io.micronaut.context.DefaultBeanContext.publishEvent(DefaultBeanContext.java:1304)
at io.micronaut.context.DefaultBeanContext.start(DefaultBeanContext.java:246)
at io.micronaut.context.DefaultApplicationContext.start(DefaultApplicationContext.java:165)
at io.micronaut.runtime.Micronaut.start(Micronaut.java:71)
at io.micronaut.runtime.Micronaut.run(Micronaut.java:311)
at io.micronaut.runtime.Micronaut.run(Micronaut.java:297)
at com.example.Application.main(Application.java:8)
Caused by: io.micronaut.context.exceptions.NoSuchBeanException: No bean of type [fete.bird.IStartUpPort] exists. Make sure the bean is not disabled by bean requirements (enable trace logging for 'io.micronaut.context.condition' to check) and if the bean is enabled then ensure the class is declared a bean and annotation processing is enabled (for Java and Kotlin the 'micronaut-inject-java' dependency should be configured as an annotation processor).
at io.micronaut.context.DefaultBeanContext.getBeanInternal(DefaultBeanContext.java:2367)
at io.micronaut.context.DefaultBeanContext.getBean(DefaultBeanContext.java:1261)
at io.micronaut.context.AbstractBeanDefinition.getBeanForConstructorArgument(AbstractBeanDefinition.java:1012)
... 12 common frames omitted
This is a Micronuat messenging application repo can be found here https://github.com/anandjaisy/MessengingMultiGradleProject
The code currently in the linked repo is configured such that the error shown in the question will not happen if the app is built and executed properly.
Clone the repository:
$ git clone git#github.com:anandjaisy/MessengingMultiGradleProject.git
Build the service:
$ cd MessengingMultiGradleProject
$ ./gradlew assemble
Run the service:
$ java -jar build/libs/demo-0.1-all.jar
__ __ _ _
| \/ (_) ___ _ __ ___ _ __ __ _ _ _| |_
| |\/| | |/ __| '__/ _ \| '_ \ / _` | | | | __|
| | | | | (__| | | (_) | | | | (_| | |_| | |_
|_| |_|_|\___|_| \___/|_| |_|\__,_|\__,_|\__|
Micronaut (v2.4.0)
Something happened
13:33:55.037 [main] INFO io.micronaut.runtime.Micronaut - Startup completed in 405ms. Server Running: 0 active message listeners.
this is strange but my spring boot api taking much longer that expected when deployed on aws lambda.
in the cloudwatch log, i see spring boot is starting up twice first with default profile and second with a profile i set.
Why should it boot twice.. that is significantly costing time..
Source Code:
lambdahandler.java
public class LambdaHandler implements RequestStreamHandler {
private static SpringBootLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> handler;
static {
try {
handler = SpringBootLambdaContainerHandler.getAwsProxyHandler(Application.class);
handler.activateSpringProfiles("lambda");
} catch (ContainerInitializationException e) {
// Re-throw the exception to force another cold start
e.printStackTrace();
throw new RuntimeException("Could not initialize Spring Boot application", e);
}
}
application.java
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
both these files are in the same package
config.java
#Configuration
#EnableWebMvc
#Profile("lambda")
public class Config {
/**
* Create required HandlerMapping, to avoid several default HandlerMapping instances being created
*/
#Bean
public HandlerMapping handlerMapping() {
return new RequestMappingHandlerMapping();
}
/**
* Create required HandlerAdapter, to avoid several default HandlerAdapter instances being created
*/
#Bean
public HandlerAdapter handlerAdapter() {
return new RequestMappingHandlerAdapter();
}
..
..
}
pom.xml
<dependency>
<groupId>com.amazonaws.serverless</groupId>
<artifactId>aws-serverless-java-container-spring</artifactId>
<version>[0.1,)</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-events</artifactId>
<version>3.1.0</version>
</dependency>
cloudwatch log
07:16:51.546 [main] INFO com.amazonaws.serverless.proxy.internal.LambdaContainerHandler - Starting Lambda Container Handler
:: Spring Boot ::
2020-09-05 07:16:52.724 INFO 1 --- [ main] lambdainternal.LambdaRTEntry : Starting LambdaRTEntry on 169.254.184.173 with PID 1 (/var/runtime/lib/LambdaJavaRTEntry-1.0.jar started by sbx_user1051 in /)
2020-09-05 07:16:52.726 INFO 1 --- [ main] lambdainternal.LambdaRTEntry : No active profile set, falling back to default profiles: default
2020-09-05 07:16:52.906 INFO 1 --- [ main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext#1e81f4dc: startup date [Sat Sep 05 07:16:52 UTC 2020]; root of context hierarchy
..
..
2020-09-05 07:16:57.222 INFO 1 --- [ main] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 40 ms
:: Spring Boot ::
2020-09-05 07:16:57.442 INFO 1 --- [ main] lambdainternal.LambdaRTEntry : Starting LambdaRTEntry on 169.254.184.173 with PID 1 (/var/runtime/lib/LambdaJavaRTEntry-1.0.jar started by sbx_user1051 in /)
2020-09-05 07:16:57.442 INFO 1 --- [ main] lambdainternal.LambdaRTEntry : The following profiles are active: lambda
2020-09-05 07:16:57.445 INFO 1 --- [ main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext#5ef60048: startup date [Sat Sep 05 07:16:57 UTC 2020]; root of context hierarchy
Why should it boot twice ?
I suspect your code change with activateSpringProfiles force reinitialisation.
handler.activateSpringProfiles("lambda");
https://github.com/awslabs/aws-serverless-java-container/blob/master/aws-serverless-java-container-spring/src/main/java/com/amazonaws/serverless/proxy/spring/SpringBootLambdaContainerHandler.java#L149
Try setting active profile with env variable SPRING_PROFILES_ACTIVE as part of lambda configuration file.
Java and serverless
If you use java for serverless application like AWS lambdas I would recommend for looking a framework which supports Ahead-of-Time compilation which will boost a lot your application start.
For instance have a look at Micronaut, Quarkus using with Graalvm.
Spring Boot is not the best option using with directly with AWS lambdas.
I'm currently learning Hibernate and I'm stuck at fetching data from many-to-many relationship in hibernate (spring-jpa). I'm trying to get data by id and it just doesn't work.
I know it's not realistic but one book can be taken from many persons.
The problem is, it does not matter in which class I put fetch type EAGER and in the second I put LAZY fetch type, it's throwing:
LazyInitializationException: failed to lazily initialize a collection of role
But if I put EAGER fetch type in both classes is throwing a StackOverFlowError.
The many-to-many logic goes like this we have a books in library and we have persons and many persons can take many books and book can be taken from many persons.
I have tried to put EAGER fetching in both classes but it gives me StackOverFlowError.
I have to mention that I'm using the JpaRepository interface.
The Person class:
#Entity
#Table(name = "persons")
public class Person { // (in library)
#Id
#Column(name = "id")
#GeneratedValue(strategy= GenerationType.IDENTITY)
private int id;
#Column(name = "name")
private String name;
#Column(name = "number_card")
private int numberCard;
#Column(name = "time_of_account_creating")
#Temporal(TemporalType.DATE)
private Date date;
#ManyToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER)
List<Book> books = new ArrayList<>();
public Person() {
this.date = new Date();
}
public Person(String name, int numberCard) {
this.name = name;
this.numberCard = numberCard;
this.date = new Date();
}
public void addBook(Book book) {
this.books.add(book);
}
// gettters and setters
The Book class:
#Entity
#Table(name = "books")
public class Book { // (in library)
#Id
#Column(name = "id")
#GeneratedValue(strategy= GenerationType.IDENTITY)
private int id;
#Column(name = "release_year")
private int releaseYear;
#Column(name = "name")
private String name;
#ManyToMany(mappedBy = "books", cascade=CascadeType.ALL, fetch = FetchType.LAZY)
private List<Person> persons = new ArrayList<>();
public Book() {
}
public Book(int releaseYear, String name) {
this.releaseYear = releaseYear;
this.name = name;
}
public List<Person> getPersons() {
return persons;
}
public void addPerson(Person person) {
this.persons.add(person);
}
// getters and setters
Main method in the #SpringBootApplication:
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(HibernateDemoApplication.class, args);
PersonRepository personRepository = context.getBean(PersonRepository.class);
System.out.println(personRepository.findById(4));
}
application.property:
spring.datasource.url = jdbc:mysql://localhost:3306/${DB}
spring.datasource.username = ${username}
spring.datasource.password = ${password}
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.hibernate.ddl-auto = update
spring.jpa.show-sql=true
The output console:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.2.5.RELEASE)
2020-03-26 15:59:27.228 INFO 18912 --- [ main] c.e.h.HibernateDemoApplication : Starting HibernateDemoApplication on abu with PID 18912 (/home/yoav/hibernateDemo/target/classes started by yoav in /home/yoav/hibernateDemo)
2020-03-26 15:59:27.232 INFO 18912 --- [ main] c.e.h.HibernateDemoApplication : No active profile set, falling back to default profiles: default
2020-03-26 15:59:28.450 INFO 18912 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2020-03-26 15:59:28.625 INFO 18912 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 131ms. Found 6 JPA repository interfaces.
2020-03-26 15:59:31.886 INFO 18912 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2020-03-26 15:59:31.928 INFO 18912 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2020-03-26 15:59:31.929 INFO 18912 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.31]
2020-03-26 15:59:32.101 INFO 18912 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2020-03-26 15:59:32.101 INFO 18912 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 4687 ms
2020-03-26 15:59:32.636 INFO 18912 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default]
2020-03-26 15:59:33.001 INFO 18912 --- [ main] org.hibernate.Version : HHH000412: Hibernate ORM core version 5.4.12.Final
2020-03-26 15:59:33.631 INFO 18912 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.1.0.Final}
2020-03-26 15:59:35.055 INFO 18912 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2020-03-26 15:59:37.374 INFO 18912 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2020-03-26 15:59:37.689 INFO 18912 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.MySQL5InnoDBDialect
Hibernate: alter table students add constraint FKrpifpqwvgu2pg2lib5c787vs foreign key (laptop_id) references laptops (id)
2020-03-26 15:59:41.092 INFO 18912 --- [ main] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2020-03-26 15:59:41.105 INFO 18912 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2020-03-26 15:59:42.982 WARN 18912 --- [ main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2020-03-26 15:59:43.406 INFO 18912 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2020-03-26 15:59:44.775 INFO 18912 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2020-03-26 15:59:45.009 INFO 18912 --- [ main] c.e.h.HibernateDemoApplication : Started HibernateDemoApplication in 18.339 seconds (JVM running for 18.756)
Hibernate: select person0_.id as id1_5_0_, person0_.time_of_account_creating as time_of_2_5_0_, person0_.name as name3_5_0_, person0_.number_card as number_c4_5_0_, books1_.persons_id as persons_1_6_1_, book2_.id as books_id2_6_1_, book2_.id as id1_0_2_, book2_.name as name2_0_2_, book2_.release_year as release_3_0_2_ from persons person0_ left outer join persons_books books1_ on person0_.id=books1_.persons_id left outer join books book2_ on books1_.books_id=book2_.id where person0_.id=?
Exception in thread "main" org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.hibernateDemo.models.Book.persons, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:606)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:218)
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:585)
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:149)
at org.hibernate.collection.internal.PersistentBag.toString(PersistentBag.java:621)
at java.lang.String.valueOf(String.java:2994)
And I have to say it again, I am getting a StackOverFlowError if I put EAGER fetch type in both classes.
I know this thread is a few months old, but for asker in the future:
Issue:
You hide the Person#toString method. In the method you access the books field. It is fine since the fetchtype is EAGER. The issue is that you access the Book#toString where you access the persons field. This field is LAZY. Since you will not access this field within transaction you will always get the LazyInitializationException.
Solution:
Open a transaction. (google jpa transaction)
Load the entity.
Access the lazy fields. It will work!
Close the transaction: Note, all changes applied to loaded entities within transaction will be save to database automaticallay, there is no need to save them through repository DAO manually!
#Configuration
public class Config {
#Value("${database.name}")
private String dbname;
public String dbname2;
public Config(){
dbname2 = dbname;
System.out.println(" ::::: Got Data from properties file Successfully ::::: " + dbname2);
}
}
#Service
public class MainService {
#Autowired
Config config;
public String getPropertiesData(){
String data = "Properties Data is " + config.dbname2;
return data;
}
}
data in application.properties file:
server.port=8081
database.name=azurecosmosDB
Stack Trace is Below when starting the application:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.2.0.RELEASE)
2019-11-06 13:10:21.106 INFO 13328 --- [ restartedMain] com.example.demo.DemoApplication : Starting DemoApplication on LP-5CD921DY4D with PID 13328 (C:\Users\BalajiChe\Desktop\STOMP\demo\target\classes started by BalajiChe in C:\Users\BalajiChe\Desktop\STOMP\demo)
2019-11-06 13:10:21.113 INFO 13328 --- [ restartedMain] com.example.demo.DemoApplication : No active profile set, falling back to default profiles: default
2019-11-06 13:10:21.247 INFO 13328 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
2019-11-06 13:10:21.247 INFO 13328 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
2019-11-06 13:10:27.732 INFO 13328 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8081 (http)
2019-11-06 13:10:27.763 INFO 13328 --- [ restartedMain] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2019-11-06 13:10:27.763 INFO 13328 --- [ restartedMain] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.27]
2019-11-06 13:10:28.335 INFO 13328 --- [ restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2019-11-06 13:10:28.336 INFO 13328 --- [ restartedMain] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 7089 ms
::::: Got Data from properties file Successfully ::::: null
2019-11-06 13:10:30.395 INFO 13328 --- [ restartedMain] o.s.b.a.e.web.EndpointLinksResolver : Exposing 2 endpoint(s) beneath base path '/actuator'
2019-11-06 13:10:31.212 INFO 13328 --- [ restartedMain] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2019-11-06 13:10:31.382 INFO 13328 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
2019-11-06 13:10:32.063 INFO 13328 --- [ restartedMain] d.s.w.p.DocumentationPluginsBootstrapper : Context refreshed
2019-11-06 13:10:32.128 INFO 13328 --- [ restartedMain] d.s.w.p.DocumentationPluginsBootstrapper : Found 1 custom documentation plugin(s)
2019-11-06 13:10:32.168 INFO 13328 --- [ restartedMain] s.d.s.w.s.ApiListingReferenceScanner : Scanning for api listing references
2019-11-06 13:10:32.523 INFO 13328 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8081 (http) with context path ''
2019-11-06 13:10:32.529 INFO 13328 --- [ restartedMain] com.example.demo.DemoApplication : Started DemoApplication in 12.299 seconds (JVM running for 14.621)
Additionally, Get Data from properties to file Successfully ::::: null ---- is coming in a console. have to get value from properties file while starting the application. Is there any way to get the value?
As #Mustahsan says, you can't access a value injected into a field in the constructor, since the injection takes place after construction.
However, if you want to use a constructor, then instead of field injection you can use constructor injection which is generally considered better practice anyway:
#Configuration
public class Config {
public String dbname2;
public Config(#Value("${database.name}") String dbname){
dbname2 = dbname;
System.out.println(" ::::: Got Data from properties file Successfully ::::: " + dbname2);
}
}
It's because in Spring the fields are initialized after the default constructor call, therefore you should only access it after the constructor is called, try this:
#PostConstruct
public void postConstructorMethod(){
dbname2 = dbname;
System.out.println(" ::::: Got Data from properties file Successfully ::::: " + dbname2);
}
Sidenote first:
Spring boot can read application.properties automatically only if put in
src/main/resources
src/main/resources/config folder
Make sure its there indeed.
Now the real issue:
You're trying to access the property inside the constructor and this is not how spring works:
Spring creates the object first (by calling its constructor) and only after that injects its fields.
So you have two ways:
Option 1:
Use constructor Injection for your beans (I see that you use #Configuration but this advice is more suitable for real beans, just makes more sense there):
#Component
class MyClass {
public MyClass(#Value({"db.name"} String dbName) {
....
}
}
Option 2:
Check not in constructor but in postconstruct or if you're talking about configurations in #Bean annotated methods:
#Configuration
public class MyConfig {
#Value("${db.name}")
private String dbName;
#Bean
public SomeBean someBean() {
// here dbName should be accessible
return new SomeBean (dbName)
}
// alternatively you can inject dbName like this:
#Bean
public SomeOtherBean someOtherBean(#Value("${db.name}") String dbName) {
return new SomeOtherBean(dbName);
}
}
I am trying to call a method asynchronously. But somehow it doesn't work. Could someone please help me resolve this issue?
My main entry point:
#SpringBootApplication
#EnableAsync
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
AsyncService asyncService = new AsyncService();
asyncService.asyncMethod();
asyncService.asyncMethod();
}
}
Async Service:
#Component
public class AsyncService {
#Async
public void asyncMethod(){
log.info("starting...");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("ending...");
}
}
And finally, in log I am expecting:
starting...
starting...
ending...
ending...
but this is what I get:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.2.RELEASE)
2019-02-13 17:52:41.548 INFO 85734 --- [ main] com.example.demo.DemoApplication : Starting DemoApplication on mntbden00122972 with PID 85734 (/Users/h3560/demo/target/classes started by h3560 in /Users/h3560/demo)
2019-02-13 17:52:41.550 INFO 85734 --- [ main] com.example.demo.DemoApplication : No active profile set, falling back to default profiles: default
2019-02-13 17:52:42.084 INFO 85734 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 0.76 seconds (JVM running for 1.329)
2019-02-13 17:52:42.086 INFO 85734 --- [ main] com.example.demo.services.AsyncService : starting...
2019-02-13 17:52:44.088 INFO 85734 --- [ main] com.example.demo.services.AsyncService : ending...
2019-02-13 17:52:44.089 INFO 85734 --- [ main] com.example.demo.services.AsyncService : starting...
2019-02-13 17:52:46.091 INFO 85734 --- [ main] com.example.demo.services.AsyncService : ending...
#Async is spring's annotation that is being applied to public methods on proxies (that's why they need to be public). Self invocation does not work.
In your example, you are not using dependency injection mechanism from spring, so no proxy is being created. To bypass it, you need to make a #Bean out of it (which you have done by annotating it with #Component) and #Autowire it before execution:
#SpringBootApplication
#EnableAsync
public class DemoApplication {
#Autowired
AsyncService asyncService;
public someMethod() {
SpringApplication.run(DemoApplication.class, args);
asyncService.asyncMethod();
asyncService.asyncMethod();
}
}
With this spring AOP can wrap the component into proxy and execute the method asynchronously.
The issue you're having is with instantiating the object manually via the new operator. This does not give the framework the opportunity to wrap the object in proxies. If you want to use the Asynchronous methods you have to use Spring DI by Factory Methos, #Autowired (or #Inject) or using XML configurations.
If you do it like that, you can make System.out.println(obj.getClass()), to see, that under the hood beans injected with DI are not of the class you used there, but of a proxy one.