Scheduling using Camel - Quartz2 and Spring boot - spring-boot

I am trying to setup a scheduler using Camel and Quartz2 and my goal is to read messages from queue only in a specific time period.I am getting the following error on start of the server.
org.apache.camel.spring.boot.CamelSpringBootInitializationException:
org.apache.camel.FailedToCreateRouteException: Failed to create route
route1:
Route(route1)[[From[quartz2://simpleTimer?cron=0/1+0+13-15+?...
because of Failed to resolve endpoint:
quartz2://simpleTimer?cron=0%2F1+0+13-15+%3F+*+MON-FRI due to: No
component found with scheme: quartz2
This is the pom entry
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-quartz2</artifactId>
<version>2.19.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring-boot-dependencies</artifactId>
<version>2.19.2</version>
</dependency>
code snippet in routes
from("quartz2://simpleTimer?cron=0/1+0+13-14+?+*+MON-FRI")
.log("Reading msgs")
.from("some queue")
.bean("myBean")
Also tried with this
from("quartz2://testGroup/someName?cron=0/1+0+13-14+?+*+MON-FRI").
I made multiple attempts in fixing the issue but failed, can anyone help me in fixing this?
Can I use simpleTimer along with Cron settings or Is there any other approach?
any suggestions/help in this regards would be highly appreciated.

The error indicates you have not added the dependency in maven to camel-quartz2 component.
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-quartz2</artifactId>
<version>x.x.x</version>
<!-- use the same version as your Camel core version -->
</dependency>

The problem is that you put 2 from in the same route. Each route has only one from.
When you read from a queue, for example with jms component, you get directly the messages as soon as they arrive. So quarz component is not needed.
Which component are you using for reading from a queue? Probably this component has more options that they can help you!

This got resolved when I created a Bean instance of QuartzComponent in routes file.Also, we can have multiple "from" in the routes definition.

Related

Stop sending Spring boot metrics to Prometheus with Micrometer

I have a Spring boot application where I am sending custom metrics generated within the service to Prometheus via Pushgateway.
I am using Prometheus Pushgateway with Micrometer, mainly based on this tutorial: https://luramarchanjo.tech/2020/01/05/spring-boot-2.2-and-prometheus-pushgateway-with-micrometer.html
I have following dependencies in my pom.xml
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient_pushgateway</artifactId>
<version>0.16.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
And sending custom metrics with:
Counter counter = Counter.builder("sb_console_test_counter").register(meterRegistry);
counter.increment();
It is working fine and I can view the custom metrics generated by the application however in addition to this I am seeing application specific metrics generated by Spring boot e.g.
tomcat_sessions_active_current_sessions
tomcat_sessions_active_max_sessions
etc.
I only want to capture the custom metrics generated by my code and not any other generic metrics, how can I stop sending this?
When you add the dependency spring-boot-starter-actuator you will get a lot of metrics out of the box from various configurations such as JvmMetricsAutoConfiguration and TomcatMetricsAutoConfiguration.
To filter those out, you could add a deny filter in your Micrometer config, and only allow your custom metric meters to be registered.
Example using a deny filter:
#Bean
public MeterRegistryCustomizer<MeterRegistry> metricsRegistryConfig() {
return registry -> registry.config()
.meterFilter(MeterFilter.deny(id -> !id.getName().startsWith("sb_console")));
}
The above will deny any metrics not starting with sb_console.
See this link for more info about the meter filters
I believe you can just add this:
management.metrics.export.defaults.enabled=false
to your application.properties. I see this in some of my code. I'm not set up to try it right now, but that's why we have it there.
If you want to add back some of the built in metrics, you can then add lines like this:
management.metrics.export.<groupname>.enabled=true

How to configure Swagger with Openapi

I just started using springdoc-openapi. I want to be able to customize the Swagger for things like background color, logo, etc. Is there a way to do that? I see that springdoc-openapi-ui includes webjars/swagger-ui, but I'd hate to just run a customize version. Would prefer to do it as an update so it doesn't interfere with future upgrades
Just to experiment, I've tried copying the entire swagger-ui distribution to my resources directory: resources/swagger-ui. I've also tried resources/webjars/swagger-ui.
In my pom, I have
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.6.6</version>
<exclusions>
<exclusion>
<groupId>org.webjars</groupId>
<artifactId>swagger-ui</artifactId>
</exclusion>
</exclusions>
</dependency>
So it should only use my local version. But I get a 404
GET "/swagger-ui/index.html", parameters={}
Mapped to ResourceHttpRequestHandler [classpath [META-INF/resources/webjars/]]
Resource not found
Completed 404 NOT_FOUND
Not sure why it's not finding it at swagger-ui/index.html
It looks like you need to set some of the variables in the .properties file:
try
springdoc.swagger-ui.path=/swagger <- sets the url path so you can see localhost:8080/swagger/index.html
springdoc.swagger-ui.enabled=true <- sets the swagger-ui to enabled
springdoc.api-docs.enabled=true <- sets the springdoc openapi enpoint to enabled
I would look here for other property setting you might need - such as turning off swagger in production, etc...
https://springdoc.org/#properties
As for customization, you will have to create your own .html page and disable the use of the default one.
springdoc.swagger-ui.path=MyNewHtmlFile.html
I think is the property name for setting your own .html file.

WebClient create java.lang.ExceptionInInitializerError: null ExchangeStrategies.withDefaults

I'm trying to play around Spring WebFlux Webclient.
Tried to create a simple webclient in a quartz cron job
this.webClient = WebClient.create(this.queryUrl);
I made sure the queryUrl is valid.
However, I've got an error as following:
java.lang.ExceptionInInitializerError: null
at org.springframework.web.reactive.function.client.ExchangeStrategies.withDefaults(ExchangeStrategies.java:67)
at org.springframework.web.reactive.function.client.DefaultWebClientBuilder.initExchangeStrategies(DefaultWebClientBuilder.java:302)
at org.springframework.web.reactive.function.client.DefaultWebClientBuilder.build(DefaultWebClientBuilder.java:269)
at org.springframework.web.reactive.function.client.WebClient.create(WebClient.java:154)
Tracing into the code, I've found that
DefaultExchangeStrategiesBuilder is null.
Does anyone have any idea what is missing?
It's a simple web client.
Thanks.
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.13.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.13.0</version>
</dependency>
Adding these dependencies and making sure the versions are the same.
I only had jackson-core before.
I tried to move the job out of quartz and ran it directly in main.
it still threw an exception, but it's different and I then looked it up
and some one has asked the issue and the solution to make sure both jackson packages need to be included and versions must be same.
I then added them to the pom file. try to run the job and it worked.
Putting the job back to quartz to run and it also worked.

How to block Cassandra from trying to connect automatically

I have this project where I'm trying to connect to different DB types based on configuration.
I have it working for Mongo and MySQL and switch by loading Beans by using #ConditionalOnProperty(name = "settings.data.source", havingValue = "mongodb")
Now I want to add Cassandra, but once I added the following dependency to my pom, it starts trying to connect to Cassandra nodes on localhost.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-cassandra</artifactId>
</dependency>
I want to have more control over when the Cassandra resources are loaded.
It doesn't try to connect automatically when I added Mongo dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
Anyone familiar with this behavior? How can I control this? I don't always need a Cassandra connection...
You may disable Cassandra auto configuration,
#SpringBootApplication
#EnableAutoConfiguration(exclude={CassandraDataAutoConfiguration.class})
Yep, That's it, thanks!
#EnableAutoConfiguration(exclude={
CassandraDataAutoConfiguration.class,
MongoDataAutoConfiguration.class,
MongoRepositoriesAutoConfiguration.class,
MongoAutoConfiguration.class})
For both my #SpringBootApplication and #Configuration classes.

Injecting spring dependencies into Domain objects best practices?

I've scraped all over many resources, and have made this work and it's kinda complex, which turns me into asking for review and other ideas on how to properly inject spring dependencies into DomainObjects ..
My solution so far includes ..
Defining the dependencies needed for loadweaving
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-instrument</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
And then .. configure it in the spring context file :
<context:spring-configured />
<context:load-time-weaver/>
Using #Configurable for my domain classes :
#Configurable
public class MyDomainClass {
....
}
And of course, using these VM arguments :
-XX:-UseSplitVerifier -javaagent:C:/Users/albert/.m2/repository/org/springframework/spring-instrument/3.0.6.RELEASE/spring-instrument-3.0.6.RELEASE.jar
For this current solution, i have the feeling that this seems too much, like the lots of dependencies needed, and also the VM args, which i would dislike when deploying in production server where i have to use specific options, which i fear could be not supported in the future or perhaps have different behaviours between version.
Im thinking of doing domainObjects with prototype scope, but i fear the dependencies issues when fetching the domain objects from the database (not from applicationContext).
Please share your experiences, thank you !
1: When you start injection stuff dynamically into domain objects, they're really not domain objects any more in the sense that the domain should reflect your information model, independent of any business rules and functional logic.
2: Remember KISS (keep it simple...). At some point, someone else might have to take ownership and maintain your code so have some mercy on that person :)
I would call this an anti-pattern, which in my opinion should be avoided.
If you use compile time waving, then you will not need the VM argument.

Resources