nodeBuilder() is removed by Elasticsearch, but still spring-data-elasticsearch documentation contains configuration which uses nodeBuilder() - spring-boot

I was following the Spring-Data-Elasticseach documentaion and was following the configuration as mentioned in the above link.
#Configuration
#EnableElasticsearchRepositories(basePackages = "org/springframework/data/elasticsearch/repositories")
static class Config {
#Bean
public ElasticsearchOperations elasticsearchTemplate() {
return new ElasticsearchTemplate(nodeBuilder().local(true).node().client());
}
}
Since import for nodeBuilder() is not mentioned in the documentation I assumed it from org.elasticsearch.node.NodeBuilder.* as mentioned in elasticsearch Java API.
But in the later releases, the API got changed and NodeBuilder no longer exists. So why/how the spring documentation still using the NodeBuilder?
If that's an issue with the documentation, what's the right configuration?
The dependencies I am using
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
with the boot version 2.1.1.RELEASE

This looks like a documentation issue. I've raise DATAES-574 to have that fixed.
With Spring Boot 2.1, the usual way to create a Client bean is to set a spring.data.elasticsearch.cluster-nodes property. Behind the scenes this will create the Client as a org.elasticsearch.client.transport.TransportClient instance.
You can also define that bean yourself if you so wish.
In the future, TransportClient is also going to been deprecated by Elasticsearch. At that point you'll need to use the higher level REST API. See https://jira.spring.io/browse/DATAES-407 for the details.

Related

awspring SQS Configuration not working in Spring Boot Project

We are attempting to move away from spring cloud aws to the new io.awspring.cloud project. The documentation states:
The AmazonSQSAsync client is automatically created and passed to the template’s constructor based on the provided credentials.
I am attempting to run this locally. In my pom.xml I have added the dependency:
<dependency>
<groupId>io.awspring.cloud</groupId>
<artifactId>spring-cloud-aws-messaging</artifactId>
<version>${spring.cloud.aws}</version>
</dependency>
And I removed the code to create an AmazonSQSAsync client. As per the documentation, I still define a QueueMessagingTemplate
import io.awspring.cloud.messaging.core.QueueMessagingTemplate;
import com.amazonaws.services.sqs.AmazonSQSAsync;
#Bean
#Qualifier
public QueueMessagingTemplate queueMessagingTemplateFifoSupport(AmazonSQSAsync amazonSQSAsync,
ObjectMapper objectMapper) {
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.setSerializedPayloadClass(String.class);
converter.setObjectMapper(objectMapper);
QueueMessagingTemplate messagingTemplate = new QueueMessagingTemplate(amazonSQSAsync);
messagingTemplate.setMessageConverter(converter);
return messagingTemplate;
}
The package namespace was updated to use io.awspring. When running the app I get the error:
No qualifying bean of type 'com.amazonaws.services.sqs.AmazonSQSAsync' available
My belief is that Spring should supply this client automatically. Am I missing something?
In my application properties I have defined:
cloud.aws.credentials.access-key
cloud.aws.credentials.secret-key
cloud.aws.region.static
I was missing a dependency:
<dependency>
<groupId>io.awspring.cloud</groupId>
<artifactId>spring-cloud-aws-autoconfigure</artifactId>
<version>${spring.cloud.aws}</version>
</dependency>
which is necessary for automatic creation of default clients.
On a side note- best to avoid using this for now as you will be locked in to v1 of the Java AWS SDK until you can upgrade io.awspring to a version compatible with both a newer version of spring boot and aws

I am not able to connect to Google Cloud Memory Store from Spring Boot

I am developing a module with spring boot in my backend where i need to use Redis through GCP Memory Store. I have been searching in forum and even the "oficial documentation" about memory store but i cannot understand how to connect to memory store with my spring boot app.
I found a google code lab but they use a Compute Engine VM to install spring boot and then save and retrieve information from memory store. So i tried to do it like that in my local spring boot but it didnt work because throws an error saying:
Unable to connect to Redis; nested exception is io.lettuce.core.RedisConnectionException: Unable to connect to 10.1.3.4
the codelab i mentioned earlier says that you only have to add this line to your application.properties:
spring.redis.host=10.1.3.4
as well as the annotation #EnableCaching in the main class and #Cachable annotation in the controller method where you try to do something with redis.
the method looks like this:
#RequestMapping("/hello/{name}")
#Cacheable("hello")
public String hello(#PathVariable String name) throws InterruptedException {
Thread.sleep(5000);
return "Hello " + name;
}
i dont know what else to do. Notice that i am new on this topic of redis and memory store.
Anyone can give me some guidance on this please?
thanks in advance
codelab url: https://codelabs.developers.google.com/codelabs/cloud-spring-cache-memorystore#0
See this documentation on how to setup Memorystore Redis instance.
Included in the documentation is how you can connect and test your Memorystore instance from different computing environments.
There's also a step by step guide on how SpringBoot can use Redis to cache with annonations.
Add the Spring Data Redis starter in your pom.xml if you're using Maven for your project setup.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
Add this configuration in your application.properties file:
spring.redis.host=<MEMORYSTORE_REDIS_IP>
# Configure default TTL, e.g., 10 minutes
spring.cache.redis.time-to-live=600000
Turn on caching capability explicitly with the #EnableCaching annotation:
#SpringBootApplication
#EnableCaching
class DemoApplication {
...
}
Once you configured the Spring Boot with Redis and enabled caching, you can use the #Cacheable annotation to cache return values.
#Service
class OrderService {
private final OrderRepository orderRepository;
public OrderService(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
#Cacheable("order")
public Order getOrder(Long id) {
orderRepository.findById(id);
}
}

Use Micrometer with OpenFeign in spring-boot application

The OpenApi documentation says that it supports micrometer. How does the integration works? I could not find anything except this little documentation.
I have a FeignClient in a spring boot application
#FeignClient(name = "SomeService", url = "xxx", configuration = FeignConfiguration.class)
public interface SomeService {
#GET
#Path("/something")
Something getSomething();
}
with the configuration
public class FeignConfiguration {
#Bean
public Capability capability() {
return new MicrometerCapability();
}
}
and the micrometer integration as a dependency
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-micrometer</artifactId>
<version>10.12</version>
</dependency>
The code makes a call but I could not find any new metrics via the actuator overview, expecting some general information about my HTTP requests. What part is missing?
Update
I added the support for this to spring-cloud-openfeign. After the next release (2020.0.2), if micrometer is set-up, the only thing you need to do is putting feign-micrometer onto your classpath.
Old answer
I'm not sure if you do but I recommend to use spring-cloud-openfeign which autoconfigures Feign components for you. Unfortunately, it seems it does not autoconfigure Capability (that's one reason why your solution does not work) so you need to do it manually, please see the docs how to do it.
I was able to make this work combining the examples in the OpenFeign and Spring Cloud OpenFeign docs:
#Import(FeignClientsConfiguration.class)
class FooController {
private final FooClient fooClient;
public FooController(Decoder decoder, Encoder encoder, Contract contract, MeterRegistry meterRegistry) {
this.fooClient = Feign.builder()
.encoder(encoder)
.decoder(decoder)
.contract(contract)
.addCapability(new MicrometerCapability(meterRegistry))
.target(FooClient.class, "https://PROD-SVC");
}
}
What I did:
Used spring-cloud-openfeign
Added feign-micrometer (see feign-bom)
Created the client in the way you can see above
Importing FeignClientsConfiguration and passing MeterRegistry to MicrometerCapability are vital
After these, and calling the client, I had new metrics:
feign.Client
feign.Feign
feign.codec.Decoder
feign.codec.Decoder.response_size

How to use OpenApi annotations in spring-webflux RouterFunction endpoints?

I am currently working on a project where I use spring functional web programming. I usually use annotations of swagger 2 in restController but with functional web programming I can not find where ! The place to tell the app to do a search for endpoints (like basepackage in Docket) and load swagger in an html page.
Here is my code:
#Configuration
public class RouterClient{
#Bean
public RouterFunction<ServerResponse> routes(ClientHandler client){
return route(GET("/api/client"), client::findAll)
.andRoute(POST("/api/client"),client::add);
}
}
Config Class:
#Configuration
public class OpenApiConfiguration{
#Bean
public GroupedOpenApi groupOpenApi() {
String paths[] = {"/api/**"};
String packagesToscan[] = {"com.demo.client"};
return GroupedOpenApi.builder().setGroup("groups").pathsToMatch(paths).packagesToScan(packagesToscan)
.build();
}
}
The dependencies:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-webflux-core</artifactId>
<version>1.2.32</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-webflux-ui</artifactId>
<version>1.2.32</version>
</dependency>
The result :
Functional endpoints are supported since 1.3.8 (early May). See releases on GitHub.
Have a look at this: https://springdoc.org/#spring-webfluxwebmvc-fn-with-functional-endpoints
The easiest way to see your endpoints on the Swagger UI is to add the #RouterOperation annotation to your RouterFunction methods (containing a single route), and specify the beanClass and beanMethod used in it. However, in your case, there are multiple routes on a single method, so you must also use the #RouterOperations annotation. These cases are well documented in the link above.
It seems like the current implementation of springdoc-openapi only allows to manually add the documentation.
set
springdoc.api-docs.enabled=false
This will skip classpath scanning (springfox) for the API annotations. (OAS3 replaced these in v3) and replace them with reading in the spec file (json/yaml).
Put the documentation in the Spec files, as one can generate any number of clients from these. Easiest way to start with legacy code is to copy the /api-docs/ files generated by springfox.
You can go to editor.swagger.io, load in the version 2 yaml and convert it to version 3 if springfox still doesn't do that. Then work with yaml files. (it's a contract UP-Front specification for a reason)
https://springdoc.org/
You need springdoc-openapi-webflux-ui and #RouterOperation.
spring-webflux with Functional Endpoints, will be available in the future release

How to configure Spring Boot with elasticsearch 5.2.1?

I am trying to connect my Spring Boot application to local elasticsearch 5.2.1 instance. When i use "org.springframework.boot:spring-boot-starter-data-elasticsearch" dependency, i face with "Received message from unsupported version: [2.0.0] minimal compatible version is: [5.0.0]". I think this is due to elasticsearch version is 2.4.4 in starter dependency. So to solve this error, i edit pom.xml properties by adding elasticsearch.version>5.2.1/elasticsearch.version> line. But this time i get
"java.lang.NoSuchMethodError: org.elasticsearch.client.transport.TransportClient.builder()"
To overcome this issue, i create custom config class like below:
#Configuration
public class ElasticsearchConfiguration {
#Bean
public Client client() throws UnknownHostException {
TransportClient client = new PreBuiltTransportClient(Settings.EMPTY)
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"), 9300));
return client;
}
#Bean
public ElasticsearchTemplate elasticsearchTemplate() throws UnknownHostException {
return new ElasticsearchTemplate(client());
}
}
This time i get apache.logging.log4j exceptions (check here) so i add necessary dependencies.
Finally i get below error and stucked there. Could anyone help me out with this?
nested exception is java.lang.NoClassDefFoundError:org/elasticsearch/action/count/CountRequestBuilder
The github page of spring-data-elasticsearch shows that it currently supports elasticsearch only up to version 2.4.0.
For now you have 3 options:
Wait and hope
checkout the pull request
checkout the dev branch 5.0.x-prep
You need to use Spring Boot 2. Check out my spring-boot-elasticsearch-5.x example.
You can use elasticsearch java api to create transport client instead of using spring-data-elasticsearch.
I tried the same and getting that error too for CountRequestBuilder, reason is that CountRequestBuilder class is deprecated and removed now from 5.x elastic search versions, that class is replaced by SearchRequestBuilder but unfortunately spring-data-elasticsearch don't provide this even in the latest release of its jar and that CountRequestBuilder is used in ElasticSearchTemplate.
I am also looking out for some solution. I will post if able to resolve.

Resources