I am new to Resilience4j and circuit breaker pattern.
I write a sample for resilience4j. Details is as below:
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>ir.co.isc</groupId>
<artifactId>circuit-breaker</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>circuit-breaker</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
<spring-cloud.version>Hoxton.SR6</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- resilience4j dependency-->
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot2</artifactId>
<version>1.5.0</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.3.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>2.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
application.yml:
resilience4j:
circuitbreaker:
configs:
default:
registerHealthIndicator: true
slidingWindowSize: 10
minimumNumberOfCalls: 5
permittedNumberOfCallsInHalfOpenState: 3
automaticTransitionFromOpenToHalfOpenEnabled: true
waitDurationInOpenState: 5s
failureRateThreshold: 20
eventConsumerBufferSize: 10
instances:
mainService:
baseConfig: default
Controller class:
package ir.co.isc.circuitbreaker;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class MainServiceController {
#Autowired
private MainService mainService;
#GetMapping("/getSleuthTest")
#ResponseStatus(HttpStatus.OK)
public ResponseEntity<String> getSleuthTest(){
String response = mainService.getResponse();
return new ResponseEntity<>(response, HttpStatus.OK);
}
}
Service class:
package ir.co.isc.circuitbreaker;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
#Service
public class MainService {
private static final String MAIN_SERVICE = "mainService";
#Autowired
private RestTemplate restTemplate;
#Bean
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
#CircuitBreaker(name = MAIN_SERVICE, fallbackMethod="testFallBack")
public String getResponse(){
return restTemplate.getForObject("http://localhost:8081/serviceOne", String.class);
}
private ResponseEntity<String> testFallBack(Exception e){
return new ResponseEntity<>("In fallback method", HttpStatus.INTERNAL_SERVER_ERROR);
}
}
SpringBootApplication class:
package ir.co.isc.circuitbreaker;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class CircuitBreakerApplication {
public static void main(String[] args) {
SpringApplication.run(CircuitBreakerApplication.class, args);
}
}
I use postman runner to call my API. I set runner iterations to 200.
after 10 successful API call I stop third-party in this url :
http://localhost:8081/serviceOne
As I understood, after stopping third party API and record minimum number of successful call, resilience4j start to calculate fault rate and when fault rate is more than failureRateThreshold, fallback method (here testFallBack in service class) called, circuit status change from close to open mode and return my desire answer which describe in testFallBack() method.
But this is never happen (testFallBack() method never called). What is wrong with my application?
Overall after so much Google, i have feeling that fallBack can only be called from Controller. I have tried multiple times, but from Service it didn't work.
Since you are also calling it from Service, that's why you are facing this issue, instead if you call it from controller it should work for you.
Related
I am learning microservices. Therefore to ensure fault tolerance I wanted to use hystrix.
I use springboot with maven for this implementation. I followed a tutorial to make the implementation and have tried adding various dependencies in the pom.xml. However it wasn't successful. The #HystrixCommand is unable to be imported for the usage. I have attached the sample error shown here below. My micro service application code looks like below.
My Pom.XML file looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.7</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>io.javabrains</groupId>
<artifactId>movie-catalog-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>movie-catalog-service</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
<spring-cloud.version>2020.0.3</spring-cloud.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>16</source>
<target>16</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
The main method
package io.javabrains.moviecatalogservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.Bean;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.function.client.WebClient;
#SpringBootApplication
#EnableEurekaClient
#EnableHystrix
public class MovieCatalogServiceApplication {
#Bean
#LoadBalanced
public RestTemplate getRestTemplate() {
HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
clientHttpRequestFactory.setConnectTimeout(3000);
return new RestTemplate(clientHttpRequestFactory);
}
public static void main(String[] args) {
SpringApplication.run(MovieCatalogServiceApplication.class, args);
}
}
The controller/ resource class
package io.javabrains.moviecatalogservice.resources;
import com.netflix.discovery.DiscoveryClient;
import io.javabrains.moviecatalogservice.models.CatalogItem;
import io.javabrains.moviecatalogservice.models.Movie;
import io.javabrains.moviecatalogservice.models.Rating;
import io.javabrains.moviecatalogservice.models.UserRating;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.function.client.WebClient;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
//How to make it REST... Just add the annotation
//So whenever a request is made, it checks the controller for any action to be done
#RestController
//Further to say springboot to treat this as api which is accessible at /catalog/something
#RequestMapping("/catalog")
public class MovieCatalogResource {
#Autowired //I am basically telling spring that somebody has a BEAN somewhere, offsitre restTempltae//GET ME THT THING
private RestTemplate restTemplate;
//
// #Autowired
// private DiscoveryClient client;
//FOR WEB CLIENT
#Autowired
private WebClient.Builder webClientBuilder;
#RequestMapping("/{userId}") //userId is a variable and it will passed
#HystrixCommand(fallbackMethod = "getFallBackCatalog")//teliing hsyutrix that getCatalog shouldnt brak the limit. If it breaks, call getFallBackCatalog
public List<CatalogItem> getCatalog(#PathVariable("userId") String userId){
UserRating ratings = restTemplate.getForObject("http://RATING-DATA-SERVICE/ratingsdata/user/" + userId, UserRating.class);
return ratings.getRatings().stream().map(rating -> {
System.out.println(rating.getMovieId());
Movie movie = restTemplate.getForObject("http://MOVIE-INFO-SERVICE/movies/"+rating.getMovieId(), Movie.class);
return new CatalogItem(movie.getName() , "Test", rating.getRating());
})
.collect(Collectors.toList());
}
public List<CatalogItem> getFallBackCatalog(#PathVariable("userId") String userId){
return Arrays.asList(new CatalogItem("No movie", "", 0));//returning default list
}
}
However, the problem that I get is that I am unable to import the #HystrixCommand as its not getting recognized
Add version in this dependency. Just like this
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
So I'm developing an application with spring boot but I haven't been able to access my h2 console. I'm able to log in fine and get to the /h2 but I when I hit connect I get a 403. I'm not sure why this is happening.
I've seen been people here having trouble accessing the URL location for h2 (in this case it's /h2) but I have no problem accessing the login page for h2. In particular, I get a 403 Whitelabel page, so I'm assuming this has something to do with spring security. If anyone could give some advice I'd really appreciate it.
Here is my web security configure class:
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/h2/**");
}
}
My main application class:
import com.example.demo.AppDevProjectApplication;
import com.example.entities.Director;
import com.example.entities.DirectorDao;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
#ComponentScan({"com.example"})
#EnableJpaRepositories
#SpringBootApplication
public class MainApp implements CommandLineRunner {
#Autowired
static DirectorDao directorDao;
public static void main(String[] args) {
SpringApplication.run(AppDevProjectApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
}
}
And my pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>ie.fiach</groupId>
<artifactId>appdev</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>AppDevProject</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>15</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.1</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.4.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>14</source>
<target>14</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
If only the access to /h2 should be public, try the following security config:
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests(authorize -> authorize.mvcMatchers("/h2/**").permitAll()
.anyRequest().authenticated());
}
}
I'm making a MicroServices based project so I have more the one Spring Boot projects in my workspace. I need to configure restOperations in some of then but I want to configure once for all the project that needs. So I'm trying to add my #Configuration class to a jar and import in each MS projects.
The problem is, when I execute the MS project in my server, I receive this error:
***************************
APPLICATION FAILED TO START
***************************
Description:
Field restOperations in com.epavanellio.base.business.controller.BusinessController required a bean of type 'org.springframework.web.client.RestOperations' 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 'org.springframework.web.client.RestOperations' in your configuration.
Here I have my Rest configuration class:
package com.epavanellio.base.restConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.LaxRedirectStrategy;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestOperations;
import org.springframework.web.client.RestTemplate;
//#Component
#Configuration
public class SimpleRestConfiguration {
final CloseableHttpClient httpClient = HttpClientBuilder.create().setRedirectStrategy(new LaxRedirectStrategy())
.build();
#Bean
public RestOperations createRestTemplate(final ClientHttpRequestFactory clientHttpRequestFactory){
return new RestTemplate(clientHttpRequestFactory);
}
#Bean
public ClientHttpRequestFactory createHttpRequestFactory (#Value("${rest.connect.timeout}") final int connectTimeout,
#Value("${rest.read.timeout}") final int readTimeout) {
HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
clientHttpRequestFactory.setConnectTimeout(connectTimeout);
clientHttpRequestFactory.setReadTimeout(readTimeout);
clientHttpRequestFactory.setHttpClient(httpClient);
return clientHttpRequestFactory;
}
}
I imported the .jar (dpdc-rest) with has the SimpleRestConfiguration class in my MS project POM:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.epavanellio.base</groupId>
<artifactId>ms-manager-business</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>ms-manager-business</name>
<description>Validate business logic. A microservice based project. </description>
<packaging>war</packaging>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.epavanellio.base</groupId>
<artifactId>domain</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.epavanellio.base</groupId>
<artifactId>dpdc-rest</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.epavanellio.base</groupId>
<artifactId>dpdc-custom-exception-handler</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator-annotation-processor</artifactId>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>2.2.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<finalName>ms-manager-business</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
and in my MS application class is like this:
package com.epavanellio.base.business;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
import com.epavanellio.base.restConfig.SimpleRestConfiguration;
//#SpringBootApplication(scanBasePackages={"com.epavanellio.base", "com.epavanellio.base.restConfig"})
//#Import(SimpleRestConfiguration.class)
//#ComponentScan({"com.epavanellio.base", "com.epavanellio.base.restConfig"})
#ComponentScan("com.epavanellio.base")
#EntityScan("com.epavanellio.base.domain")
#EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class,HibernateJpaAutoConfiguration.class})
#SpringBootApplication
public class BusinessApplication extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(BusinessApplication.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(BusinessApplication.class);
}
}
as you can see commented, I already tried to my make my runtime "see" my configuration class in diffrent ways:
First I tried to add (scanBasePackages={"com.epavanellio.base", "com.epavanellio.base.restConfig"}) after my annotation #SpringBootApplication, but the same error occurs. Then I tried to add specifically the SimpleRestConfiguration class package to the #ComponentScan annotation(for this, I uncommented the #Component annotation in SimpleRestConfiguration class), but the same error occurs. At least I tried to use #Import, but in this case I receive the error:
java.io.FileNotFoundException: class path resource [com/epavanellio/base/restConfig/SimpleRestConfiguration.class] cannot be opened because it does not exist
does any one know how can I make my application class to "see" my
#Configuration class?
The problem was Maven, for some reason maven was no recognizing my jar.
so I made a new dependency project, with a new name but same same SimpleRestConfiguration class. I imported the new .Jar to my MS and then works fine.
My application become like this:
#ComponentScan("com.epavanellio.base")
#EntityScan("com.epavanellio.base.domain")
#EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class,HibernateJpaAutoConfiguration.class})
#SpringBootApplication
public class UserApplication extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(UserApplication.class);
}
}
I was working in a projet in intellij using: Spring-boot, maven and thymeleaf. At first I was running it as a Java application and it worked perfectly, but when I wanted to deploy it in a local Tomcat server or embedded Tomcat it can't resolve my html pages. I get the 404 not found message each time.
I tried to maven deploy in the tomcat manager, and them in the embedded tomcat in intellij and always the same problem.
I tried created a thymeleaf configuration file and always the same problem.
This is my pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.EPS</groupId>
<artifactId>EPS</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>EPS</name>
<description>project EPS Spring Boot</description>
<properties>
<start-class>com.programmer.gate.EpsApplication</start-class>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.1-901-1.jdbc4</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>3.3.7</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
And this is my ThymeleafConfiguration.java
package com.EPS.EPS.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
#Configuration
#EnableWebMvc
public class ThymeleafConfiguration {
#Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(thymeleafTemplateResolver());
return templateEngine;
}
#Bean
public SpringResourceTemplateResolver thymeleafTemplateResolver() {
SpringResourceTemplateResolver templateResolver
= new SpringResourceTemplateResolver();
templateResolver.setPrefix("/WEB-INF/classes/templates");
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode("HTML5");
return templateResolver;
}
}
This is my indexController.jave
package com.EPS.EPS.web.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.view.RedirectView;
#Controller
#RequestMapping("/templates")
public class IndexController {
private final Logger logger = LoggerFactory.getLogger(IndexController.class);
/*#PreAuthorize("isAuthenticated()")
#GetMapping(value = "/")
public String index() {
return "ajax";
}*/
//Authentification
#GetMapping(value = "/login")
public String login() {
logger.info("worked!!");
return "login/login.html";
}
#GetMapping(value = "/")
public RedirectView RedirectLogin() {
return new RedirectView("/login");
}
#GetMapping(value = "/login/error")
public String loginerror() {
return "login/errorlogin";
}
//Gestion des utilisateurs et des roles
//utilisateurs
#PreAuthorize("hasAuthority('Gestion_utilisateurs')")
#GetMapping(value = "/gestion_utilisateurs")
public String gestion_utilisateur() {
return "gestion_utilisateurs/gestion_utilisateurs";
}
.....
}
And this is my main Java class EpsApplication.java
package com.EPS.EPS;
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;
#SpringBootApplication
public class EpsApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(EpsApplication.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(EpsApplication.class, args);
}
}
Here is my project tree:
This is what I get
I'm trying to configure Autowired in non-spring managed class under spring boot application.
I run successfully this under web application deployed under tomcat server.
But when i want run this under spring boot nothing works.
I made very simple app to check this functionality:
Console result from web app int tomcat:
...:::TEST CONTROLLER
...:::TEST autowired in cotrnoller: com.mycompany.test_aop.Test#30ea7445
...:::NEW
...:::Check: com.mycompany.test_aop.Test#30ea7445
Console result from spring boot app:
...:::TEST CONTROLLER
...:::TEST autowired in cotrnoller: com.mycompany.test_aop.Test#627ae77d
...:::NEW
...:::Check: null
I read a lot of topics hot to configure spring boot app but nothing works.
I trying set param -javaagent to spring-instrument.jar but no effect.
I struggle with this for three days but no effect
App:
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>pl.com.eurohost</groupId>
<artifactId>aop_test</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<repositories>
<repository>
<id>unknown-jars-temp-repo</id>
<name>A temporary repository created by NetBeans for libraries and jars it could not identify. Please replace the dependencies in this repository with correct ones and delete this repository.</name>
<url>file:${project.basedir}/lib</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>1.3.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>1.3.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>1.3.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>1.3.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>1.3.3.RELEASE</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
<version>1.19</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-servlet</artifactId>
<version>1.19</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.3.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.2.5.RELEASE</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-instrument</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.3.RELEASE</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-agent</artifactId>
<version>2.5.6.SEC03</version>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.3.3.RELEASE</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Main.class:
package com.mycompany.test_aop;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.EnableLoadTimeWeaving;
import org.springframework.context.annotation.aspectj.EnableSpringConfigured;
import org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver;
#SpringBootApplication
#EnableSpringConfigured
#EnableAspectJAutoProxy
#EnableLoadTimeWeaving
#ComponentScan(value = "com.mycompany.test_aop")
public class Main {
public static void main(String args[]) {
SpringApplication.run(Main.class, args);
}
#Bean
public InstrumentationLoadTimeWeaver loadTimeWeaver() throws Throwable {
InstrumentationLoadTimeWeaver loadTimeWeaver = new InstrumentationLoadTimeWeaver();
return loadTimeWeaver;
}
}
Web.java:
package com.mycompany.test_aop;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
#Controller
public class web {
#Autowired
Test t;
#RequestMapping(value = "/")
public #ResponseBody String root(){
System.out.println("...:::TEST CONTROLLER");
System.out.println("...:::TEST autowired in cotrnoller: "+t);
Test2 a = new Test2();
a.check();
return "HI!";
}
}
Test.java:
package com.mycompany.test_aop;
import org.springframework.stereotype.Service;
#Service
public class Test {
public void display() {
System.out.println("...:::TEST CLASS CALL DISPLAY");
}
}
Test2.java
package com.mycompany.test_aop;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
#Configurable
public class Test2 {
#Autowired
private Test t;
public Test2() {
System.out.println("...:::NEW");
}
public void check() {
System.out.println("...:::Check: "+t);
}
}
Webapp has different pom, addittional file app-servlet.xml and no main method:
Main.java
package com.mycompany.test_aop;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableLoadTimeWeaving;
import org.springframework.context.annotation.aspectj.EnableSpringConfigured;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
#EnableSpringConfigured
#EnableLoadTimeWeaving
#ComponentScan(value = "com.mycompany.test_aop")
#Configuration
#EnableWebMvc
public class Main extends WebMvcConfigurerAdapter {
}
app-servlet.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<mvc:default-servlet-handler/>
<context:annotation-config/>
<bean class="com.mycompany.test_aop.Main"/>
<mvc:annotation-driven>
</mvc:annotation-driven>
</beans>
By using Autowire Annotations.
#Autowired
Test2 a;
#RequestMapping(value = "/")
public #ResponseBody String root(){
System.out.println("...:::TEST CONTROLLER");
System.out.println("...:::TEST autowired in cotrnoller: "+t);
Test2 a = new Test2();//instead of this use autowired of test2
a.check();
return "HI!";
If you give thisTest2 a=new Test2();It will initiate with new Object then it will show only NULL