Quartz service is not working using Spring Feign Client - java

I create a real time notification functionality using spring quartz library. I create two services as bellow :
1) quartz-service : Which is used to set schedule a for real time notification.
2) task-service : Which is used to create a task and remind through quartz-service.
When task-service call quartz-service through feign client I'm not get any response. But If I call through Rest Template it's working find.
Actually we are used spring boot microservice architecture, In using Rest Template we need to specify URL Hard coded, So we can't achieved Ribbon concept in this case that's why we not interest to use Rest Template.
So please help me if any once face this problem.
quartz-service :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Rest Controller :
#RestController
#RequestMapping(value = "/quartz/taks", produces = "application/hal+json")
public class QuartzTaskController
{
#Autowired
private QuartzTaskServices quartzTaskServices;
#PostMapping("/reminder")
public ResponseEntity<Object> saveTaskReminder(#RequestBody Task task)
{
quartzTaskServices.saveTaskReminderScheduler(task);
return ResponseEntity.ok().build();
}
}
task-service
Dependency :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
Feign Client :
#RibbonClient(name="quartz-services")
#FeignClient(name="quartz-services")
public interface QuartzProxy
{
#PostMapping("/quartz/taks/reminder")
public ResponseEntity<Object> saveTaskReminder(#RequestBody Task task);
}
Call Feign Client :
#Autowired
private QuartzProxy quartzProxy;
...
.....
......
quartzProxy.saveTaskReminder(task);

Related

Creating keycloak users through spring boot

I am trying to create a keycloak object to register new user with keycloak with the following code:
public Keycloak getInstance() {
if (keycloak == null) {
return KeycloakBuilder.builder()
.realm(realm)
.serverUrl(serverURL)
.clientId(clientID)
.clientSecret(clientSecret)
.grantType(OAuth2Constants.CLIENT_CREDENTIALS)
.build();
}
return keycloak;
}
But i keep getting the following error:
java.lang.ClassCastException: class org.jboss.resteasy.client.jaxrs.internal.ResteasyClientBuilderImpl cannot be cast to class javax.ws.rs.client.ClientBuilder (org.jboss.resteasy.client.jaxrs.internal.ResteasyClientBuilderImpl and javax.ws.rs.client.ClientBuilder are in unnamed module of loader 'app')
at org.keycloak.admin.client.ClientBuilderWrapper.create(ClientBuilderWrapper.java:29) ~[keycloak-admin-client-17.0.1.jar:17.0.1]
at org.keycloak.admin.client.spi.ResteasyClientClassicProvider.newRestEasyClient(ResteasyClientClassicProvider.java:35) ~[keycloak-admin-client-17.0.1.jar:17.0.1]
at org.keycloak.admin.client.Keycloak.newRestEasyClient(Keycloak.java:98) ~[keycloak-admin-client-17.0.1.jar:17.0.1]
at org.keycloak.admin.client.Keycloak.<init>(Keycloak.java:89) ~[keycloak-admin-client-17.0.1.jar:17.0.1]
at org.keycloak.admin.client.KeycloakBuilder.build(KeycloakBuilder.java:146) ~[keycloak-admin-client-17.0.1.jar:17.0.1]
at com.microfinanceBank.Customer.Config.KeycloakProvider.getInstance(KeycloakProvider.java:41) ~[classes/:na]
at com.microfinanceBank.Customer.service.KeycloakAdminClientServices.wow(KeycloakAdminClientServices.java:31) ~[classes/:na]
at com.microfinanceBank.Customer.controller.CustomerController.getCustomer(CustomerController.java:68) ~[classes/:na]
at com.microfinanceBank.Customer.controller.CustomerController$$FastClassBySpringCGLIB$$8c9f9beb.invoke(<generated>) ~[classes/:na]
Below are my keycloak dependencies:
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-admin-client</artifactId>
<version>17.0.1</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<version>6.1.0.Alpha1</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson2-provider</artifactId>
<version>6.1.0.Alpha1</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-multipart-provider</artifactId>
<version>6.1.0.Alpha1</version>
</dependency>
<dependency>
<groupId>com.guicedee.services</groupId>
<artifactId>jakarta.ws.rs-api</artifactId>
<version>1.2.2.1</version>
</dependency>
What am i doing wrong?
I have tried adding some dependencies yet keep getting error.
Please what should i do.Thanks in advance
You can use keycloak's SDK for your springboot application. Include these two dependencies in the pom.xml
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-boot-starter</artifactId>
<version>18.0.2</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-admin-client</artifactId>
<version>18.0.2</version>
</dependency>
After that create a keycloak's instance in your springboot application.
public Keycloak getAdminKeycloakUser() {
return KeycloakBuilder.builder().serverUrl("keycloak-auth-url")
.grantType("password").realm("realm-name")
.clientId("client-id")
.username("admin-user")
.password("admin-password")
.resteasyClient(new ResteasyClientBuilder().connectionPoolSize(10).build()).build();
}
The above method will get you the admin user which is needed in order to create users into Keycloak.
The next step would be to get the realm as realm manages users.
public RealmResource getRealm() {
return getAdminKeycloakUser().realm(realm);
}
Finally now you can create user by using org.keycloak.representations.idm.UserRepresentation.
public void createUser() {
UserRepresentation userRepresentation = new UserRepresentation();
userRepresentation.setUsername("username");
userRepresentation.setFirstName("first-name");
userRepresentation.setLastName("last-name");
userRepresentation.setEmail("test#email.com");
Response response = getRealm().realmResource.users().create(userRepresentation);
//If user is created successfully 200 is returned for response status.
//Set password flow
CredentialRepresentation passwordCred = new CredentialRepresentation();
String userId = CreatedResponseUtil.getCreatedId(response);
passwordCred.setTemporary(false);
passwordCred.setType("password");
passwordCred.setValue("some-password");
UserResource userResource = realmResource.users().get(userId);
userResource.resetPassword(passwordCred);
}
keycloak-spring-boot-starter is deprecated, don't use it. You might find alternatives here
I wouldn't use keycloak-admin-client neither. Admin API is quite well documented. Just use your favorite REST client (with spring-boot features to configure OAuth2 REST client if you like) and POST a request to your Keycloak server.
UserRepresentation userRepresentation = new UserRepresentation();
userRepresentation.setUsername("username");
userRepresentation.setFirstName("first-name");
userRepresentation.setLastName("last-name");
userRepresentation.setEmail("test#email.com");
// set other required values
javax.ws.rs.core.Response response = KeycloakBuilder.builder().build().realm("your-realm-nam").users().create(userRepresentation);
if (response != null && response.getStatusInfo().getFamily() == Family.SUCCESSFUL)
{
return org.keycloak.admin.client.CreatedResponseUtil.getCreatedId(response); // returns String (Id of created User)
}

Webflux and Resilience4j retry issue

wanted to ask a basic question about webflux and resilience4j's retry.
We are running Java SpringBoot with Webflux and Resilience4J (not Spring Cloud Circuit Breaker).
While running the application its giving error (Somehow full stack trace is not coming for me) :
due to exception [reactor.core.publisher.Mono.retryWhen(Ljava/util/function/Function;)Lreactor/core/publisher/Mono;]
Code to build the Retry bean is as follows (we are not using YAML based configuration):
#Bean
public Retry retryConfig(ResilienceCCMConfig resilienceCCMConfig) {
RetryConfig config = RetryConfig.custom().maxAttempts(5)
.waitDuration(Duration.of(1, SECONDS))
.retryExceptions(ServerException.class)
.ignoreExceptions(ClientException.class)
.build();
return RetryRegistry.of(config).retry("retry-config", config);
}
Now we are calling our web client's POST method as below with bean injected from above :
#Autowired
private Retry retryConfig;
return webClient.post().uri(url)
.headers(httpHeaders -> getItemHeaders(httpHeaders, tenantId, bannerId, correlationId))
.body(itemServiceRequestMono, ItemServiceRequest.class)
.retrieve()
.onStatus(HttpStatus::isError, clientResponse -> {
LOGGER.error("Error");
if (clientResponse.statusCode().is5xxClientError()) {
throw new Exception("Something went wrong ");
}
return Mono.empty();
})
.bodyToMono(MyResponse.class)
.transform(RetryOperator.of(retryConfig))
.onErrorResume(ex -> myFallbackMethod(ex));
POM dependency :
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
<version>3.4.3</version>
</dependency>
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-reactor</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId> io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot2</artifactId>
<version>1.6.1</version>
</dependency>
Please help .

Send Apache Camel Actuator Metrics to Prometheus

I am trying to forward/add the Actuator Camel metrics from /actuator/camelroutes (route metrics like number of exchanges/transactions) to the Prometheus Actuator endpoint. Is there a way for me to configure Camel to add those metrics to the PrometheusMeterRegistry?
I have tried adding:
camel.component.metrics.metric-registry=io.micrometer.prometheus.PrometheusMeterRegistry
in my application.properties according to the documentation here: https://camel.apache.org/components/latest/metrics-component.html
But still nothing relating to Apache Camel is displayed in actuator/prometheus
Here are the dependencies I am using with Spring Boot 2.1.9 and Apache Camel 2.24.2:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-metrics-starter</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
Got the Camel Routes metrics working in the /actuator/prometheus endpoint.
Use the camel-micrometer-starter dependency as stated by #claus-ibsen 's comment.
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-metrics-starter</artifactId>
</dependency>
Set the following in your properties file:
camel.component.metrics.metric-registry=prometheusMeterRegistry
Then add set the Camel Context to use the MicrometerRouterPolicyFactory and MicrometerMessageHistoryFactory. Code seen below is places in a Configuration class:
#Configuration
public class AppConfig {
#Bean
public CamelContextConfiguration camelContextConfiguration() {
return new CamelContextConfiguration() {
#Override
public void beforeApplicationStart(CamelContext camelContext) {
camelContext.addRoutePolicyFactory(new MicrometerRoutePolicyFactory());
camelContext.setMessageHistoryFactory(new MicrometerMessageHistoryFactory());
}
#Override
public void afterApplicationStart(CamelContext camelContext) {
}
};
}
}
You need to trigger an exchange in a route for the metrics to appear in /actuator/prometheus.
Here are the metrics made available to Prometheus:
CamelMessageHistory_seconds_count
CamelMessageHistory_seconds_max
CamelRoutePolicy_seconds_max
CamelRoutePolicy_seconds_count
CamelRoutePolicy_seconds_sum
You can use the JMX Exporter jar for Prometheus to get the more detailed metrics from the JMX of Camel. I wanted to avoid this approach as it would mean that for each Camel Spring Boot App I have would use 2 ports; 1 for the JMX Metrics and 1 for the Actuator Metrics.
There is a camel-micrometer-starter dependency you should use instead that integrates with micrometer. And then you can use the micrometer route policy from that dependency to let it monitor all your routes. See the docs at: https://camel.apache.org/components/2.x/micrometer-component.html
I can see the metrics by keeping these dependencies intact
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-management</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-metrics</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-micrometer-starter</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
Why dont I see the actual process and bean names rather than like process3, bean1 etc ??
CamelMessageHistory_seconds_sum{camelContext="AppName",nodeId="process3",routeId="AppNameRoute",serviceName="MicrometerMessageHistoryService",} 0.041466
CamelMessageHistory_seconds_count{camelContext="AppName",nodeId="bean1",routeId="AppNameRoute",serviceName="MicrometerMessageHistoryService",} 100.0
CamelMessageHistory_seconds_sum{camelContext="AppName",nodeId="bean1",routeId="AppNameRoute",serviceName="MicrometerMessageHistoryService",} 4.8417576

Spring Boot WebSocket

In summary, Intellij tells me that no MessageMapping and SendTo annotations could be found!?
I included the sprint-boot-starter-websocket like that:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
After i implemented a websocket controller intellij tells me that there are no MessageMapping and SendTo annotations found.
#Controller
public class WebSocketController
{
#MessageMapping("/chat/{topic}")
#SendTo("/topic/messages")
public String send( #DestinationVariable("topic") String topic, Message message){
return "test";
}
}
I also tried to include:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>
but that did not work too.
What do i wrong?
EDIT:
In project structure>modules>dependencies a error message say
Library 'Maven: org.springframework:spring-messaging:5.0.7:RELEASE' has broken path.
What does that mean?

Netflix Feign Exception

Dependencies
org.springframework.cloud:spring-cloud-starter-feign:jar:1.2.2.RELEASE:compile
com.netflix.feign:feign-core:jar:8.16.2:compile
com.netflix.feign:feign-slf4j:jar:8.16.2:compile
com.netflix.feign:feign-jackson:jar:8.15.1:compile
Enabling Feign on SpringBootAppilication
#EnableFeignClients(basePackages = "com.vett.services.bucket.restclient")
Feign interface Client
#FeignClient(name = "myClient", configuration = ClientConfigs.class, url = "https://my-endpoint");
public interface MyClient {
Results in this error
org.springframework.core.annotation.AnnotationConfigurationException: Attribute 'value' in annotation [org.springframework.cloud.netflix.feign.FeignClient] must be declared as an #AliasFor [serviceId], not [name]
So far I have
As its unclear to me what the issue is i have used the value instead of name, my searching has not been successful i have see a few issues with feign annotation but not appear to be similar to this at all
I was getting the same issue, Once I added the below dependency , it started working :
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:Brixton.SR7"}
}
I am using Spring boot 1.4 but Spring 4.3.6. Also Spring feign 1.2.5.RELEASE
This error may occur when using multiple feign clients or bad package architecture. Sometimes this error occurs due to version incompatibilities, but in some projects we may not be able to change the versions. Therefore, you can solve the problem with the following codes. This codes worked for me.
Use this annotation in ApplicationStarter class:
#EnableFeignClients
Feign Client Interface:
import org.springframework.cloud.netflix.feign.FeignClient;
#FeignClient(value = "account-service", url = "${feign.client.account-service}", path = "/account/api/v1")
public interface AccountServiceClient {
#RequestLine("POST /customer/{email}/?name={accountName}")
Long registerCustomer(#Param("email") String email, #Param("accountName") String accountName);
}
Define bean for multiple feign usage:
#Bean
#Qualifier("account-feign-client")
public AccountServiceClient accountServiceClient() {
return Feign.builder().target( AccountServiceClient.class,"${feign.client.account-service}");
}
#Bean
#Qualifier("mail-feign-client")
public MailServiceClient mailServiceClient() {
return Feign.builder().target( MailServiceClient.class,"${feign.client.mail-service}");
}
Autowire in service:
#Autowired
#Qualifier("account-feign-client")
private AccountServiceClient accountServiceClient;
pom.xml:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Brixton.SR7</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
...
</dependencies>

Categories