i face a problem when i using spring cloud gateway
is if any dependency call spring-boot-starter-tomcat directly or recursively
it will not work because it will start the embedded tomcat server not the netty server that spring cloud gateway use
i started to solve this problem by excluding this dependency
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
the spring cloud gateway worked successfully
but sometimes i want to use spring-cloud-starter-oauth2 to use #EnableOAuth2Sso
i start to use
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
at that time i face the big issue that throw exception saying
Caused by: java.lang.IllegalStateException: Failed to introspect annotated methods on class org.springframework.security.oauth2.config.annotation.web.configuration.OAuth2ClientConfiguration
......
Caused by: java.lang.NoClassDefFoundError: javax/servlet/Filter
As you've seen, the Spring cloud gateway uses the reactive model and is based on netty rather than tomcat. The reactive change is a major shift and currently isn't supported by Spring Security but work is in progress on it and you can track it at https://github.com/spring-cloud/spring-cloud-gateway/issues/179
Use the following dependencies (I copied from my build.gradle)
dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
implementation 'org.springframework.cloud:spring-cloud-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
}
Code your gateway app minimally as follows
#SpringBootApplication
public class App {
#Bean
public ForwardedHeaderTransformer forwardedHeaderTransformer() {
return new ForwardedHeaderTransformer();
}
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
Configure in application.yml
spring:
security:
oauth2:
client:
registration:
google:
client-id: XXX
client-secret: YYY
I am actively building my stack that uses OAuth2 with Docker Swarm Discovery https://github.com/trajano/spring-cloud-demo.git so you can see how it would work in action.
spring boot 2.1 with spring security 5 have resolve this problem
see this example
Related
I have a simple app that uses Netflix Zuul as an API gateway
I added the Zuul dependency in the pom.xml file as follows:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
<version>2.2.10.RELEASE</version>
</dependency>
and #EnableZuulProxy for the main class of the app
The problem is that whenever I try to run the API, It fails to start and shows in the console:
Consider defining a bean of type
'org.springframework.cloud.client.loadbalancer.reactive.DeferringLoadBalancerExchangeFilterFunction'
in your configuration.
I couldn't solve the issue, what's the problem?
The issue was solved when I added the following dependency in pom.xml:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
and as a result, spring also asked me to add this to my app configuration:
spring.main.web-application-type=reactive
Then my API ran successfully without failing or throwing any exception
I'm facing issue with Swagger Integration in Spring Boot. Have a look at the code and error snippet.
------------------POM--------------------
<properties>
<java.version>1.8</java.version>
<swagger.version>2.9.2</swagger.version>
</properties>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-bean-validators</artifactId>
<version>${swagger.version}</version>
</dependency>
-----------------App class--------------
#SpringBootApplication
#EnableSwagger2
public class ProducerApplication {
public static void main(String[] args) {
SpringApplication.run(ServletPocProducerApplication.class, args);
}
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
}
}
Stack Trace
org.springframework.context.ApplicationContextException: Failed to start bean
'documentationPluginsBootstrapper'; nested exception is
java.lang.NullPointerException: Cannot invoke
"org.springframework.web.servlet.mvc.condition.PatternsRequestCondition.toString()"
because the return value of
"springfox.documentation.spi.service.contexts.Orderings.patternsCondition(springfox.docume
ntation.RequestHandler)" is null
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:181) ~[spring-context-5.3.13.jar:5.3.13]
How do I fix this??
I solved it by adding "spring.mvc.pathmatch.matching-strategy=ant-path-matcher" in application.properties.
For a long time I have tried to solve this problem and solution for this is:
a) adding this to application.properties:
spring.mvc.pathmatch.matching-strategy=ant-path-matcher
b) adding this to application.yaml(or application.yml):
spring:
mvc:
pathmatch:
matching-strategy: ant_path_matcher
I know this does not solve your problem directly, but consider moving to springdoc. Springfox is so buggy at this point that is a pain to use. I've moved to springdoc 2 years ago because of its Spring WebFlux support and I am very happy about it. Additionally, it also supports Kotlin Coroutines, which I am not sure Springfox does.
If you decide to migrate, springdoc even has a migration guide.
For the integration between spring-boot and swagger-ui, add the library to the list of your project dependencies (No additional configuration is needed):
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.5.12</version>
</dependency>
The Swagger UI page will then be available at
http://server:port/context-path/swagger-ui.html and the OpenAPI
description will be available at the following url for json format:
http://server:port/context-path/v3/api-docs
server: The server name or IP
port: The server port
context-path: The context path of the application
Adding this "spring.mvc.pathmatch.matching-strategy=ant-path-matcher" to your application.properties file solves the problem.
It's what i used and i saved me alot of trouble.
My suggestion is when you are using spring-boot then it is better to use spring boot dependency for swagger. So, spring-boot will take care of your default settings.
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>...</version>
</dependency>
I'm trying to configure OAuth2 for a Spring project. I used jdbc authentification and my authorization server and resource server are two separate API. My issue is now with the microservices. I'm trying to use this shared authorization server to authenticate the microservices. I can get access_token from the token endpoint.
I can check the access_token from the check_token endpoint.
My resource server configuration:
#SpringBootApplication
#EnableCircuitBreaker
#EnableDiscoveryClient
#EnableResourceServer
public class ProductApiServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ProductApiServiceApplication.class, args);
}
}
And application.yml:
security:
oauth2:
client:
client-id: saba-product-api-service
client-secret: secret123
resource:
id: saba-product-api-service
token-info-uri: http://localhost:9999/uaa/oauth/check_token
And REST controller:
#GetMapping("/user/me")
public Principal user(Principal principal) {
return principal;
}
When I call the /user/me endpoint I get invalid_token.
My Resource Server log:
And my Authorization Server log:
What is wrong with my code?
Update
The problem is because of this code:
I had the same issue. In my case, I was using spring cloud oauth2, Hoxton.SR4 release and it was working. So, I change to Hoxton.SR6 and the issue was throwed. My Authoriation Server also was a Eureka's client, and the issue was origined cause this dependency. There was one dependĂȘncia inside Eureka Client, named jackson-dataformat-xml, and because it the return of check_token endpoint was converted in xml instead json. When RemoteTokenServices called check_token, and the resulta was a xml, it culdn't decerialized in map<String,Object> the right way. If you had more than one aud, scope or authorities, it picked the last one. And the active propertie was trated as string. In my case I solved the issue excluding in Authorization Server the dependency mentioned from Eureka Client, like this:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</exclusion>
</exclusions>
</dependency>
Finally, I replaced
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.3.4.RELEASE</version>
</dependency>
with
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.5.0.RELEASE</version>
</dependency>
// gh-838
if (map.containsKey("active") && !"true".equals(String.valueOf(map.get("active")))) {
logger.debug("check_token returned active attribute: " + map.get("active"));
throw new InvalidTokenException(accessToken);
}
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
I'm using Spring Boot and ActiveMQ. In application.properties I set the url for activemq like this:
spring.activemq.broker-url=vm://localhost?broker.persistent=false
As you can see I'm using an embedded broker (dependency added in pom).
This is my application class:
#SpringBootApplication
#EntityScan(
basePackageClasses = {ServiceApplication.class, Jsr310JpaConverters.class}
)
#EnableAutoConfiguration
#ServletComponentScan
public class ServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceApplication.class, args);
}
}
These are the activemq related dependencies in the pom:
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-camel</artifactId>
<version>5.14.5</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-pool</artifactId>
<version>5.14.5</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-broker</artifactId>
<version>5.14.5</version>
</dependency>
I have a single application.properties, I don't have different profiles.
But when I run the app, I get this log:
[ActiveMQ Task-1] o.a.a.t.failover.FailoverTransport : Failed to connect to [tcp://localhost:61616] after: 10 attempt(s) continuing to retry.
It's trying to connect to tcp://localhost:61616 even though that's not the url I defined.
I tried removing #EnableAutoConfiguration but still the same issue.
How can I solve this?
Your ActiveMQ client is not aware of spring.activemq.broker-url since this property is used to configure spring-boot-starter-activemq.If you do not have this starter - you configure nothing with this property.
I would suggest you to go through the following resources to have a better understanding of how to set up spring-boot-starter-activemq in your project:
https://spring.io/guides/gs/messaging-jms/
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-messaging.html
Hope it helps!