Scheduler not running in Spring Boot - java

I have created a Spring Boot application. I have configured my class that contains the scheduler method startService().
Below is my code :
Service Class :
package com.mk.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import com.mk.envers.model.BossExtChange;
import com.mk.envers.model.BossExtChangeRepository;
#Component
public class EnverseDemoService {
#Autowired
BossExtChangeRepository bossExtChangeRepository;
#Scheduled(fixedRate = 30000)
public void startService() {
System.out.println("Calling startService()");
BossExtChange bossExtChange = bossExtChangeRepository.findById(5256868L);
System.out.println("bossExtChange.getDescription()--->"+bossExtChange.getDescription());
System.out.println("Ending startService()");
}
}
Main Class :
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.PropertySource;
import org.springframework.scheduling.annotation.EnableScheduling;
#SpringBootApplication
#EnableScheduling
#PropertySource("classpath:application.properties")
public class EnverseDemoApplication {
public static void main(String[] args) {
SpringApplication.run(EnverseDemoApplication.class, args);
}
}
I have annotated the class as #Component and also method as #Scheduled(fixedRate = 30000) that will running as a scheduler. But while running the application as Spring Boot the scheduler does not trigger. The console show the below message:
2016-02-03 10:56:47.708 INFO 10136 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2016-02-03 10:56:47.721 INFO 10136 --- [ main] com.mk.envers.EnverseDemoApplication : Started EnverseDemoApplication in 3.231 seconds (JVM running for 3.623)
2016-02-03 10:56:47.721 INFO 10136 --- [ Thread-2] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext#49e202ad: startup date [Wed Feb 03 10:56:44 IST 2016]; root of context hierarchy
2016-02-03 10:56:47.721 INFO 10136 --- [ Thread-2] o.s.j.e.a.AnnotationMBeanExporter : Unregistering JMX-exposed beans on shutdown
2016-02-03 10:56:47.736 INFO 10136 --- [ Thread-2] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
Can anyone please help me out.

May be you can solve this problem by adding the #ComponentScan annotation in the configuration file
#SpringBootApplication
#EnableScheduling
#ComponentScan(basePackages = "com.mk.service")
#PropertySource("classpath:application.properties")
public class EnverseDemoApplication {
public static void main(String[] args) {
SpringApplication.run(EnverseDemoApplication.class, args);
}
}

I was able to solve the issue, I forgot to provide #service level annotation,
I have created the check List for #Scheduler, kindly go through every point one by one, It will help you to solve the issue.
Check for the #EnableScheduling on SpringBoot Main class.
Scheduled method should be annotated with #Scheduled, Follow the #Scheduled Method rules. a method should have the void return type, a method should not accept any parameters.
Make sure the class should be annotated with #Service or #Component Annotation so SpringBoot can make the object of that class.
The package of the scheduler jobs should be under the main Application class's package. e.g com.company is your main application class package then scheduler class package should be com.company.scheduler,
If you are using Cron expression confirm the same e.g #Scheduled( cron = "0 0/2 * * * ?"), This Cron expression will schedule the task for every 2 min.
Feel free to add more points in the comment so it will help to solve the issue.

It must be that you forgot to add #EnableScheduling annotation in your app class.
public static void main(String[] args) {
context = SpringApplication.run(YouApplication.class, args);
}

I was finally able to solve the above issue, I changed the package of my service class EnverseDemoService from package com.mk.service; to com.mk.envers.service;. This is because if the main configuration class EnverseDemoApplication is present in the package com.mk.envers. All the other classes in the boot application should be in the qualifying package. Eg: com.mk.envers.*;

In my case, was the lazy-initialization with value true which was preventing my #Component to be loaded by Spring at startup and #Scheduled method was never running.
Make sure the Spring Boot lazy initialization is disabled.

Please check if in application.properties you have
"spring.main.lazy-initialization=true"
Remove this from application.properties.
Even if you have all the configuration correct, this simple line will enable lazy loading due to which your #Component will initalize during application start.

As Swapnil already mentioned all the check-points to make sure while using cron. One additional thing you should do:
Always verify your cron expression whether it's in right format or not, using below reference site - http://www.freeformatter.com/cron-expression-generator-quartz.html#

Related

Can't access API endpoint

So I've started learning Spring recently by following a small course where we created a market api, when we started we created a simple hello world endpoint to test things out. Recently we just created an endpoint for accessing a list of products, but it seems all requests return a 404 error, since this error seems to be related with the controller I don't think posting all my code is needed.
This is my controller ProductController.java, I've only added the mapping for the first two methods (since I'm trying to fix this error still)
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
#RequestMapping("/products")
public class ProductController {
#Autowired
private ProductService productService;
#GetMapping("/all")
public List<Product> getAll() {
return productService.getAll();
}
#GetMapping("/{productId}")
public Optional<Product> getProduct(#PathVariable("productId") int productId) {
return productService.getProduct(productId);
}
public Optional<List<Product>> getByCategory(int categoryId) {
return productService.getByCategory(categoryId);
}
public Product save(Product product) {
return productService.save(product);
}
public Boolean delete(int productId) {
return productService.delete(productId);
}
}
I also had to deal with a bean not being found which translated domain objects into dto's (and vise versa) by using MapStruct with the following error:
I made sure to annotate my interface with #Mapper(componentModel="spring")
***************************
APPLICATION FAILED TO START
***************************
Description:
Field mapper in com.platzi.market.persistance.ProductoRepository required a bean of type 'com.platzi.market.persistance.mapper.ProductMapper' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.platzi.market.persistance.mapper.ProductMapper' in your configuration.
I managed to fix this with this (source from another student's comment)
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication(scanBasePackages = { "com.platzi.market.persistance.mapper.ProductMapper", })
public class PlatziMarketApplication {
public static void main(String[] args) {
SpringApplication.run(PlatziMarketApplication.class, args);
}
}
But I'm not sure if this could be causing some interference with the controller class.
Are you accessing the correct endpoint?
This is my application.properties:
spring.profiles.active=dev
server.servlet.context-path=/platzi-market/api
And this is the active dev profile (application-dev.properties)
server.port=8080
# Database, values are altered
spring.datasource.url=jdbc:mysql://localhost:3306/platzi-market
spring.datasource.username=foo
spring.datasource.password=bar
So the endpoint for accesing all product in my controller should be: localhost:8080/platzi-market/api/products/all which is returning a 404
I also checked if maybe I am using https so I made sure to use http:// in Postman, which also returned a 404
I double-checked the output in the terminal just to make sure the right port and context-path are being used:
2021-02-23 17:20:07.583 INFO 51334 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '/platzi-market/api'
2021-02-23 17:20:07.594 INFO 51334 --- [ main] c.platzi.market.PlatziMarketApplication : Started PlatziMarketApplication in 3.881 seconds (JVM running for 4.296)
If you would like to check the rest of the code here's a link to the repo: https://github.com/Je12emy/spring-market-api, hope this makes since since I'm going crazy with error XD
I could reproduce your problem... (with Eclipse STS 4.9.0).
When running as "Spring boot run configuration" (in eclipse) the context comes up, but with a decent warning. I can reproduce the 404 error pages (due to missing /error mapping!).
I removed the (useless)scanBasePackages, and found the context not starting. (with the described problems).
To build.gradle, I added:
plugins {
...
id "com.diffplug.eclipse.apt" version "3.26.0" // Only for Eclipse
}
..as described by https://mapstruct.org/documentation/stable/reference/html/#_gradle
Then I (recognized, that no mapperImpls were generated,) tried to run via gradle :bootRun and found following generation/"compilation" errors in your mappers:
In CategoryMapper it must be "description" not "descripcion".
Missing Getter/Setter for productos in Categoria.
Missing Getter/Setter for categoria in Producto.
Applying these fixes, (& running (at least initially/every time, when mapper/dto changes) with gradle), should* bring up the application and give access to loclahost:8080/platzi-market/api/products/all.
*: I "tested" on an empty (different/h2/in-memory) database. (It means, there can be runtime bugs.)
A warm welcome to a spring!
Reviewing your repo, I can recommend you:
(next) to create some tests (for mappers, repos, controllers ... code-coverage)
probably Spring Boot - Loading Initial Data.
and of course don't: expose (real) prod-credentials in public repos. ;)
...

How to fix "Field ... required a bean of type ... that could not be found" exception Spring Boot

I am working with spring boot tutorial from javabrains and everything was clear until putting CrudRepository inside project. Below you can find my main class:
package pl.springBootStarter.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class CourseApiDataApplication
{
public static void main(String args[])
{
SpringApplication.run(CourseApiDataApplication.class,args);
}
}
Service class:
package pl.springBootStarter.app.topic;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
#Service
public class TopicService
{
#Autowired
private TopicRepository topicRepository;
private List<Topic> topics = new ArrayList<>(Arrays.asList(
new Topic("spring","spring framework", "spring framework dectription"),
new Topic("sprin","spring framework", "spring framework dectription"),
new Topic("spri","spring framework", "spring framework dectription")));
public List<Topic> getAllTopics()
{
// return topics;
List<Topic> t = new ArrayList<Topic>();
topicRepository.findAll().forEach(t::add);
return t;
}
public Topic getTopic (String id)
{
return topics.stream().filter( t -> t.getId().equals(id)).findFirst().get();
}
public void addTopic(Topic topic) {
topicRepository.save(topic);
}
public void updateTopic(Topic topic, String id)
{
topics.set(topics.indexOf(topics.stream().filter(t-> t.getId().equals(id)).findFirst().get()), topic);
}
public void deleteTopic(String id)
{
topics.remove(topics.stream().filter(t -> t.getId().equals(id)).findFirst().get());
}
}
And Repository interface:
package pl.springBootStarter.app.topic;
import org.springframework.data.repository.CrudRepository;
public interface TopicRepository extends CrudRepository<Topic,String>
{
}
When I run the app there is a problem with injection of TopicRepository into topicRepository field in TopicService class. I get following error:
Error starting ApplicationContext. To display the conditions report re- run your application with 'debug' enabled.
2019-05-01 10:33:52.206 ERROR 6972 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Field topicRepository in pl.springBootStarter.app.topic.TopicService required a bean of type 'pl.springBootStarter.app.topic.TopicRepository' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
What could be the reason that Spring cannot do the autowiring?
Be sure the class is scanned by spring!
(this may help if that's the problem:
Intellij Springboot problems on startup).
Optionally you may want to annotate TopicRepository as a #Repository.
#Repository
public interface TopicRepository extends CrudRepository<Topic,String>
{
}
See a demo code here: https://github.com/lealceldeiro/repository-demo
Spring cannot inject bean because it has not been created.
You have to instruct Spring to generate implementation of declared repository interfaces by using #EnableJpaRepositories(basePackages={"pl.springBootStarter.app"}) annotation on any of your configuration classes or class annotated with #SpringBootApplication. That should fix your problem.
I got a similar message and I was missing the #Service annotation in the Service class. Simple mistake, posting in case it helps anyone else.
For anybody who was brought here by googling the generic bean error message, but who is actually trying to add a feign client to their Spring Boot application via the #FeignClient annotation on your client interface, none of the above solutions will work for you.
To fix the problem, you need to add the #EnableFeignClients annotation to your Application class, like so:
#SpringBootApplication
// ... (other pre-existing annotations) ...
#EnableFeignClients // <------- THE IMPORTANT ONE
public class Application {
I got a similar message.
the thing was my main package was com.example
and the package for other classes was com.xyz
so when I Changed the name of the package of other class to com.example.topic
i.e.
finally
The main package was com.example
and the package for the other class was com.example.topic
A simple mistake, posting in case it helps anyone else.
In my cases, the necessary configuration from org.springframework.boot.autoconfigure.jdbc. has been excluded at SpringBootApplication, causing relevant bean not added properly. Check your main application java file and see if you can find following configuration in the exclusion list
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
#SpringBootApplication(
exclude = {
DataSourceAutoConfiguration.class, // REMOVE THIS
DataSourceTransactionManagerAutoConfiguration.class, // REMOVE THIS
}
)
and remove them from exclusion list.
in service class
do:
#Autowired(required=false)

How to implement ApplicationRunner before springboot application starts?

By reading Spring-boot docs I have understood that I can create a class implementing ApplicationRunner or CommandLineRunner in order to execute code before application starts.
From docs:
An ApplicationReadyEvent is sent after any application and command-line runners have been called. It indicates that the application is ready to service requests.
However, I have following class:
#Component
public class MyClass implements ApplicationRunner {
#Override
public void run(ApplicationArguments args) throws Exception {
Thread.sleep(10000);
}
}
And instead of waiting those 10 seconds to start, it says application started in 3seconds:
2018-11-19 08:51:21.906 INFO 24872 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2018-11-19 08:51:21.909 INFO 24872 --- [ main] com.mycompany.Application : Started Application in 3.565 seconds (JVM running for 4.016)
I assume my class is running in another thread. But I have the feeling that this does not guarantee that my code has finished executing before any possible incoming request.
Is this the correct approach? Am I missing something?

SpringBoot can't scan Controller and get the URL mapping

I just wrote a Springboot application as a testing Webserver which origins from spring.io.
It packaged initially in "jar", changed it to "war" file.
And get the application class code as below:
package com.ronzhong;
import org.springframework.boot.Banner.Mode;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.web.context.WebApplicationContext;
#SpringBootApplication(scanBasePackages={"com.ronzhong.libraryManagement"})
public class LibraryManagementApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
application.application().setBannerMode(Mode.OFF);
return application.sources(SpringApplicationBuilder.class);
}
protected WebApplicationContext run(SpringApplication application) {
return (WebApplicationContext) application.run();
}
// public static void main(String[] args) {
// SpringApplication.run(LibraryManagementApplication.class, args);
//}
}
and the controller is :
package com.ronzhong.libraryManagement;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.*;
//#CrossOrigin(origins = "http://localhost:4200", maxAge = 3600)
#RestController
#RequestMapping("/api")
public class CounterController {
#Autowired
private BookService bookService;
#PostMapping
public boolean add(#RequestBody Book book){
return bookService.add(book);
}
#RequestMapping(value = "/books", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public Book[] get(){
return bookService.getBooks();
}
#RequestMapping(value = "{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public Book findOne(#PathVariable("id") int id){
return bookService.findById(id);
}
}
And I also checked the
"Dynamic Web Module" in the project facets.
Finally, I got these logs when launch tomcat server with this war file generated.
INFO: 2 Spring WebApplicationInitializers detected on classpath
2018-11-28 10:43:31.925 INFO 14888 --- [ main] c.ronzhong.LibraryManagementApplication : Starting LibraryManagementApplication on ronzhongmachine with PID 14888 (C:\Users\ronzhong\workspace_testserver\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\library-Management\WEB-INF\classes started by ronzhong in C:\tools_installers\eclipse-jee-2018-09-win32-x86_64\eclipse)
2018-11-28 10:43:32.002 INFO 14888 --- [ main] c.ronzhong.LibraryManagementApplication : No active profile set, falling back to default profiles: default
2018-11-28 10:43:33.910 INFO 14888 --- [ main] o.a.c.c.C.[.[.[/library-Management] : Initializing Spring embedded WebApplicationContext
2018-11-28 10:43:33.911 INFO 14888 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1604 ms
2018-11-28 10:43:34.362 INFO 14888 --- [ main] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'errorPageFilter' to: [/*]
2018-11-28 10:43:34.704 INFO 14888 --- [ main] c.ronzhong.LibraryManagementApplication : Started LibraryManagementApplication in 5.958 seconds (JVM running for 36.407)
2018-11-28 10:43:34.955 INFO 14888 --- [ main] org.apache.coyote.ajp.AjpNioProtocol : Starting ProtocolHandler ["ajp-nio-8009"]
2018-11-28 10:43:34.968 INFO 14888 --- [ main] org.apache.catalina.startup.Catalina : Server startup in 28177 ms
There're no mappings info in the logs.
And if I request with http://localhost:8080/api/books, it will get 404 error.
But the logs hasn't change even a little.
So I googled the potential causes, and excluded those causes temporarily:
springboot application does not scan the package which controller locates?
I moved springboot application class to the uplevel package, and also specified what kind of package it should scan.
While you see, it doesn't work.
the annotation issue?
Some people say we should use #RestController annotation instead of #Controller, better add the #ResponseBody, while I did.
it does't work, either.
the deployment issue?
don't know, I did changed the build path of this project, which generated jar file and war file normally, but webapp folder is empty, since I don't have any static resource, I think it's fine, right?
Anyone can help me? very appreciate for your answer, thanks in advance.
From the logs, I can see that your war file name is library-Management, whichh means its deloyed under this folder, as logs states. So you should check http://localhost:8080/library-Management/api/books instead.
You get 404 from Tomcat, it doesnt hit your app at all, this is ehy you dont see any logs.

Switch off DispatcherServlet on Spring Boot

How can I disable the DispatcherServlet on SpringBoot, even trying to disable it via servlet registration the uri mapping appears on the log:
#Bean
public ServletRegistrationBean servletRegistrationBean(final DispatcherServlet dispatcherServlet) {
final ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(dispatcherServlet);
servletRegistrationBean.setEnabled(false);
return servletRegistrationBean;
}
LOG
2015-06-10 10:39:57.552 INFO 7032 --- [ main] o.s.b.c.e.ServletRegistrationBean : Servlet dispatcherServlet was not registered (disabled)
2015-06-10 10:39:57.553 INFO 7032 --- [ main] o.s.b.c.e.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/]
Thanks any help!
I added below code into my main class, and the servlet was removed from log.
#SpringBootApplication(exclude = { DispatcherServletAutoConfiguration.class })
From Spring boot docs here
Spring Boot wants to serve all content from the root of your application / down. If you would rather map your own servlet to that URL you can do it, but of course you may lose some of the other Boot MVC features. To add your own servlet and map it to the root resource just declare a #Bean of type Servlet and give it the special bean name dispatcherServlet (You can also create a bean of a different type with that name if you want to switch it off and not replace it).
If you exclude DispatcherServletAutoConfiguration.class,
then you need to exclude ErrorMvcAutoConfiguration.class as well, or at least I did.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
#SpringBootApplication(exclude = { DispatcherServletAutoConfiguration.class, ErrorMvcAutoConfiguration.class})
#EnableAspectJAutoProxy
public class CoreApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(CoreApplication.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(CoreApplication.class);
}
}

Categories

Resources