I am using Resilience4j Circuit breaker version: '1.4.0 with Spring boot version 2.0.6 and my problem is - fallback method is not working. the call is not going to the fallback method.
Below is my code :
#Override
#CircuitBreaker(name="mainService",fallbackMethod = "callFallback")
public JSONObject callService(JSONObject rawRequest) throws TimeoutException {
...
throw new TimeoutException("Time occured while calling
service");
...
}
-- and fallback method :
private JSONObject callFallback(JSONObject rawRequest,Throwable t){
System.out.println("Inside fallback method callNsFallback,
cause"+t.toString());
logger.info("Inside fallback method callFallback,
cause - {}",t.toString());
return rawRequest;
}
--Configurations in application.yml
resilience4j:
circuitbreaker:
configs:
default:
registerHealthIndicator: true
ringBufferSizeInClosedState: 5
ringBufferSizeInHalfOpenState: 3
slidingWindowSize: 10
minimumNumberOfCalls: 5
permittedNumberOfCallsInHalfOpenState: 3
automaticTransitionFromOpenToHalfOpenEnabled: true
waitDurationInOpenState: 1s
failureRateThreshold: 50
eventConsumerBufferSize: 10
recordExceptions:
- java.util.concurrent.TimeoutException
instances:
mainService:
baseConfig: default
The possible reasons could be you are missing some required dependencies. Here I am sharing the dependencies and the yaml configuration which were working for me.
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot2</artifactId>
<version>1.7.1</version>
</dependency>
</dependencies>
application.yml
resilience4j:
circuitbreaker:
instances:
menu-service:
registerHealthIndicator: true
eventConsumerBufferSize: 10
automaticTransitionFromOpenToHalfOpenEnabled: true
failureRateThreshold: 50
minimumNumberOfCalls: 5
permittedNumberOfCallsInHalfOpenState: 1
slidingWindowSize: 10
waitDurationInOpenState: 2s
slidingWindowType: COUNT_BASED
management:
health:
circuitbreakers:
enabled: true
endpoints:
web:
exposure:
include: health
endpoint:
health:
show-details: always
I have been missing below dependency. It worked after adding and fallback method was called!
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
Related
I am trying to consume a kafka topic from spring boot application. I am using Spring cloud stream with below mentioned version
Spring-boot-starter-parent: 2.5.7
Spring cloud version: 2020.0.4
Below are the code and configuration
application.yml
spring:
zipkin:
sender:
type: kafka
kafka:
bootstrap-servers:
- localhost:19091
cloud:
stream:
bindings:
audit-in-0:
destination: com.tonitingaurav.kafka.log
group: kafka-log-group
consumer:
concurrency: 10
max-attempts: 3
default-binder: kafka
kafka:
binder:
brokers:
- localhost:19091
Message Consumer Class
#Configuration
public class LogConsumer {
#Bean
Consumer<Log> audit(){
return log -> {
System.out.println(log.getMessage());
};
}
}
Below message publisher is publishing the messages properly. Publisher is written in different micro service.
#Component
public class LogEventPublisher {
#Autowired
#Qualifier(LogProducerKafkaConfig.KAFKA_LOG_PUBLISHER)
MessageChannel messageChannel;
public void logMessage(Log log) {
Message<Log> message = MessageBuilder.withPayload(log).build();
messageChannel.send(message);
}
}
pom.xml
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-kafka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-kafka-streams</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-test-support</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka-test</artifactId>
<scope>test</scope>
</dependency>
You already posted a very similar question here and the response with two different solutions was provided.
Also, here are the samples you can use as starting point -
https://github.com/spring-cloud/spring-cloud-stream-samples
I have a scenario with spring boot, zuul as the gateway, and Eureka as Service discovery. I need to implement the retry mechanism before doing the fallback in the gateway. But the retry code is not working.Applcation.yml is given below
server:
port: 8080
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8083/eureka
spring:
application:
name: gateway-service
zuul:
retryable: true
prefix: /api
routes:
test-service:
sensitive-headers: Cookie,Set-Cookie
service-id: test-service
path: /testservice/**
strip-prefix: true
retryable: true
test-service:
ribbon:
MaxAutoRetries: 5
retryableStatusCodes: 503
OkToRetryOnAllOperations: true
authorization:
token:
name: Authorization
prefix: Bearer
secret: qqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
hystrix:
command:
test-service:
execution:
isolation:
strategy: THREAD
thread:
timeoutInMilliseconds: 60000000
timeout:
enable: false
app:
auth:
allowPermissionPaths:
- /
- /error
- /favicon.ico
- /**/*.png
- /**/*.gif
- /**/*.svg
- /**/*.jpg
- /**/*.html
- /**/*.css
- /**/*.sass
- /**/*.js
- /api/testservice/**
the pom.xml adding below
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-ribbon -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
I am expecting help to implement the retry with zuul gateway.
spring-cloud.version:Greenwich.SR2, spring boot 2.1.7
mvn spring-boot:run makes the endpoint /graphql accessible but not mvn clean verify
I included graphql-java-servlet, javax.servlet-api, graphql-spring-boot-starter-test and graphql-spring-boot-starter, but it stills does not work
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
<!-- graphql -->
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java</artifactId>
<version>13.0</version>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java-extended-scalars</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>java-dataloader</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>5.10.0</version>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-spring-boot-starter-test</artifactId>
<scope>test</scope>
<version>5.0.2</version>
</dependency>
<!-- Apache CXF -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-client</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>spring-mock-mvc</artifactId>
<version>3.3.0</version>
<scope>test</scope>
</dependency>
Here is my simple test which returns 404:
#Test
public void persons() throws Exception {
Map<String, Object> variables = new HashMap<String, Object>();
GraphQLRequest request = new GraphQLRequest(
"query persons{persons"
+ "{"
+ " id"
+ "}}",
variables,
null);
// SUT
given()
.contentType(ContentType.JSON)
.body(request)
.get(GRAPHQL_PATH)
.then()
.log().body()
.statusCode(200);
}
The test class is annotated with :
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
#TestPropertySource(locations = "classpath:bootstrap-test.yml")
Here is my bootstrap.yml:
spring:
application:
name: crm-service
cloud:
config:
uri: http://localhost:8081
fail-fast: false
password: configPassword
username: user
main:
allow-bean-definition-overriding: true #i dont remember why but i think there is a bug with spring cloud and OAuth2ClientContext
acls-management:
permissions-config-path: permissions-config.json
acl-rules-path: acl-rules.json
eureka:
client:
register-with-eureka: false
fetch-registry: false
graphql:
servlet:
mapping: /graphql
enabled: true
I have an application on EC2 instance that connect to RDS (MySQL), after 8 hours the DB connection gets closed from MySQL and when the application tries to read/write data I get the below Exception
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed;
nested exception is org.springframework.dao.DataAccessResourceFailureException: could not extract ResultSet;
nested exception is org.hibernate.exception.JDBCConnectionException: could not extract ResultSet] with root cause
java.io.EOFException: Can not read response from server. Expected to read 4 bytes, read 0 bytes before connection was unexpectedly lost.
also this Exception:
Request processing failed; nested exception is
org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction;
nested exception is javax.persistence.PersistenceException: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionEx
ception: No operations allowed after connection closed.] with root cause
java.net.SocketException: Connection timed out (Write failed)
this happens after 8 hours when the application is running.
my config file (YAML):
management:
security:
enabled: false
spring:
profiles: prod
datasource:
tomcat:
max-active: 20
max-idle: 10
min-idle: 5
initial-size: 5
test-while-idle: true
test-on-borrow: true
test-on-return: true
validation-query: select 2 from dual
validation-interval: 3600
time-between-eviction-runs-millis: 5000
jpa:
database: MYSQL
generate-ddl: false
show-sql: true
properties:
globally_quoted_identifiers: true
hibernate:
ddl-auto: none
cloud:
aws:
stack:
auto: false
region:
static: *****
credentials:
instanceProfile: true
rds:
dev-db:
databaseName: dev-db
username: ******
password: ******
I'm using:
Java 1.8
Spring boot 1.5.4.RELEASE (JAR deployment)
Spring Cloud AWS JDBC and AWS autoconfigure, 1.1.3.RELEASE
My POM is:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</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.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-aws-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-aws-autoconfigure</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Camden.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<repositories>
<repository>
<id>io.spring.repo.maven.release</id>
<url>http://repo.spring.io/release/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
My Question is:
How can I configure Data source pool in Spring Boot for AWS (Amazon)? I Logged the DataSource configuration once the App is deployed on EC2, and it not configured to with test-while-idle and other configurations, here is the logs from EC2:
Data source Class Impl: class org.apache.tomcat.jdbc.pool.DataSource
TimeBetweenEvictionRunsMillis: 5000
ValidationInterval: 3000
isTestOnBorrow: false
isTestOnBorrow: false
isTestOnBorrow: false
I checked this Page but cannot find a way to configure the pool from properties file (yaml in my case)...
I found below workaround, but it would be better to support it through same spring AWS-JDBC auto-config properties.. I added the below (from spring cloud aws)
#Configuration
#EnableRdsInstance(dbInstanceIdentifier = "test",password = "secret")
public class ApplicationConfiguration {
#Bean
public RdsInstanceConfigurer instanceConfigurer() {
return new RdsInstanceConfigurer() {
#Override
public DataSourceFactory getDataSourceFactory() {
TomcatJdbcDataSourceFactory dataSourceFactory = new TomcatJdbcDataSourceFactory();
dataSourceFactory.setInitialSize(10);
dataSourceFactory.setValidationQuery("SELECT 1 FROM DUAL");
dataSourceFactory.setValidationInterval(10000);
dataSourceFactory.setTimeBetweenEvictionRunsMillis(20000);
return dataSourceFactory;
}
};
}
}
I'm trying to create a Spring cloud microservice application using Zuul and Consul.
I have 2 components in my project:
api-gateway microservice using Zuul
Hello world microservice (a simple hello world Rest Webservice)
Here is the code of The api-gateway:
#SpringBootApplication
#EnableZuulProxy
#EnableDiscoveryClient
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
The pom.xml
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-parent</artifactId>
<version>Brixton.M3</version>
</parent>
<properties>
<java.version>1.8</java.version>
<spring.cloud.consul.version>1.0.0.M4</spring.cloud.consul.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
</dependency>
<dependency>
<!-- Setup Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<!-- Setup Spring MVC & REST, use Embedded Tomcat -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<!-- Spring Cloud starter -->
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-all</artifactId>
<version>${spring.cloud.consul.version}</version>
</dependency>
</dependencies>
application.yml
zuul:
routes:
hello1:
path: /hello1/**
serviceId: microservice-example
logging:
level:
org.springframework: INFO
com.netflix: DEBUG
bootstrap.yml
spring:
application:
name: edge-server
cloud:
consul:
config:
enabled: true
host: localhost
port: 8500
Here is the code of hello microservice:
#SpringBootApplication
#EnableConfigServer
#EnableDiscoveryClient
#RestController
public class Application {
#RequestMapping(value="/hello1",method = RequestMethod.GET)
public String hello() {
System.out.print("hello1");
return "Hello1";
}
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).web(true).run(args);
}
}
bootstrap.yml:
spring:
application:
name: microservice-example
profiles:
active: native
cloud:
consul:
config:
enabled: true
host: localhost
port: 8500
But, when I start the api-gateway I got the following exception:
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.cloud.netflix.zuul.filters.RouteLocator]: Factory method 'routeLocator' threw exception; nested exception is java.lang.IllegalStateException: Unable to locate service in consul agent: edge-server
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE]
... 69 common frames omitted
Caused by: java.lang.IllegalStateException: Unable to locate service in consul agent: edge-server
at org.springframework.cloud.consul.discovery.ConsulDiscoveryClient.getLocalServiceInstance(ConsulDiscoveryClient.java:66) ~[spring-cloud-consul-discovery-1.0.0.M4.jar:1.0.0.M4]
This issue is fixed in Brixton.M3 (1.0.0.M5). As mentioned above this was an issue with spring-cloud-consul. The new version is working fine