I use Elasticsearch version 6.8.5 with 9201 is HTTP port and 9301 is port of cluster node.
On my project, I use spring boot (spring-boot-starter-data-elasticsearch). On application.properties file, I set port of cluster node:
spring.data.elasticsearch.cluster-nodes=localhost:9301
But I don't know how to set HTTP port. So when I start my project, I get an error:
NoNodeAvailableException[None of the configured nodes are available: [{#transport#-1}{de81Kcj-QUqTRdA9HskFWg}{localhost}{localhost:9301}]];
I tried to use High Level REST Client setting (https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#elasticsearch.clients.rest), but it still not work:
#Configuration
public class ElasticsearchConfig {
#Bean(destroyMethod = "close")
public RestHighLevelClient restClient1() {
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
RestClientBuilder builder = RestClient.builder(new HttpHost("localhost", 9201));
RestHighLevelClient client = new RestHighLevelClient(builder);
return client;
}
}
How can I config HTTP port (not default port)?
You should use the following code:
#Bean
public RestHighLevelClient elasticsearchClient() {
final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
.connectedTo("localhost:9201")
// if you need basic authentication:
.withBasicAuth("user", "password")
.build();
return RestClients.create(clientConfiguration).rest();
}
Edit:
Check the complete configuration from the docs, when using a custom configuration like this, I'd recommend to not let Spring Boot try to configure Spring Data Elasticsearch. You can do this by changing the annotation on your application class to
#SpringBootApplication(exclude = ElasticsearchDataAutoConfiguration.class)
Related
#Bean
public RestHighLevelClient elasticsearchClient() {
ClientConfiguration clientConfiguration
= ClientConfiguration.builder()
.connectedTo("localhost:9200")
.build();
return RestClients.create(clientConfiguration).rest();
}
#Bean
public Client client() throws Exception {
Settings settings = Settings.builder().put("cluster.name", esClusterName).build();
TransportClient client = new TransportClient(settings);
client.addTransportAddress(new TransportAddress(InetAddress.getByName(esHost), esPort));
return client;
}
I have been trying to connect to elasticsearch from spring boot using following techniques:
RestHighLevelClient & TransportClient
Custom binary port : 9300
as these techniques are deprecated.
Please help me with best recommended solution to this.
Thanks,
Dilip
You can probably allow the auto-configuration to create the client for you, so it isn't necessary to create the bean. Set the configuration properties if needed:
spring.elasticsearch.rest.uris=http://localhost:9300
All properties can be found here.
I am running a springboot application which requires to trust the certificate which i added in my local truststore.
For now i am setting it under run configurations options in intellij and it works.
ex->::-Djavax.net.ssl.trustStore=location\cacerts;-Djavax.net.ssl.trustStorePassword=changeit
I was wondering is there any way to set it from application.properties file in springboot in the way we set spring properties?
If you want to make REST calls, You can configure the RestTemplate Bean like :
#Configuration
public class SslConfiguration {
#Value("${http.client.ssl.trust-store}")
private Resource keyStore;
#Value("${http.client.ssl.trust-store-password}")
private String keyStorePassword;
#Bean
RestTemplate restTemplate() throws Exception {
SSLContext sslContext = new SSLContextBuilder()
.loadTrustMaterial(
keyStore.getURL(),
keyStorePassword.toCharArray()
).build();
SSLConnectionSocketFactory socketFactory =
new SSLConnectionSocketFactory(sslContext);
HttpClient httpClient = HttpClients.custom()
.setSSLSocketFactory(socketFactory).build();
HttpComponentsClientHttpRequestFactory factory =
new HttpComponentsClientHttpRequestFactory(httpClient);
return new RestTemplate(factory);
}
}
Check this : Example
I am going through a code that configures dedicated restTemplate for a rest operation. I see the following properties
httpProperties.connection-request-timeout=6100
httpProperties.connect-timeout=6100
httpProperties.read-timeout=6100
My Config class looks like below
#Bean
#ConfigurationProperties(prefix = "httpProperties")
public HttpComponentsClientHttpRequestFactory webSystemHttpRequestFactory() {
SSLContext sslContext;
try {
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext);
HttpClient httpClient = HttpClients.custom().setMaxConnTotal(maxTotalConnection)
.setMaxConnPerRoute(maxConnectionPerRoute).setSSLSocketFactory(socketFactory).build();
return new HttpComponentsClientHttpRequestFactory(httpClient);
}
catch(Exception e) {
}
return new HttpComponentsClientHttpRequestFactory();
}
#Bean(name = "webSystemRestTemplate")
public RestTemplate webSystemRestTemplate() {
RestTemplate restTemplate = new RestTemplate(webSystemHttpRequestFactory());
return restTemplate;
}
I can see the logs
o.a.h.i.c.DefaultManagedHttpClientConnection.setSocketTimeout - http-outgoing-1: set socket timeout to 6100
Here is what i want to understand:
How is this value set and to which property by the #CnfigurationProperties annotation?
Is it applicable at the spring boot application level or at each request level?
Please help me understand the concept underlying.
Note: Apache http client version used is 4.5.2
In the source code for HttpComponentsClientHttpRequestFactory.class there is an object called RequestConfig.class.
In it's source code you can see that there are three parameters.
private final Timeout connectionRequestTimeout;
private final Timeout connectTimeout;
private final Timeout responseTimeout;
These are the ones that the parameters map to using
#ConfigurationProperties(prefix = "httpProperties")
That is not the most common way to set these parameters. But there are multiple ways to set these as pointed out here.
RestTemplate timeout examples
The properties are setting the attributes connectionRequestTimeOut, connectTimeOut and readTimeOut of the HttpComponentsClientHttpRequestFactory class. The mapping is done using the ConfigurationProperties annotation that maps the kebab case property names to the bean attributes.
HttpComponentsClientHttpRequestFactory documentation :
HttpComponentsClientHttpRequestFactory
Elastic Search configs are as follows:
import java.net.InetAddress;
#Configuration
#EnableElasticsearchRepositories
public class ElasticSearchConfig {
#Value("localhost")
private String host;
#Value("9300")
private int port;
#Value("elasticsearch")
private String clusterName;
#Bean
public Client client() throws Exception {
Settings esSettings = Settings.builder()
.put("cluster.name", clusterName)
.put("node.name", "node-1")
.put("node.attr.rack","r1")
.put("client.transport.sniff", true)
.build();
TransportClient transportClient = new PreBuiltTransportClient(esSettings);
transportClient.addTransportAddress(new TransportAddress(InetAddress.getByName(host),port));
return transportClient;
}
/* #Bean
public ElasticsearchOperations elasticsearchTemplate() throws Exception {
return new ElasticsearchTemplate(client());
}*/
}
I am getting following exception like:
NoNodeAvailableException[None of the configured nodes are available: [{#transport#-1}{6cirTCG_SJW0yPPONMB-HQ}{localhost}{127.0.0.1:9300}]]
at org.elasticsearch.client.transport.TransportClientNodesService.ensureNodesAreAvailable(TransportClientNodesService.java:349)
at org.elasticsearch.client.transport.TransportClientNodesService.execute(TransportClientNodesService.java:247)
at org.elasticsearch.client.transport.TransportProxyClient.execute(TransportProxyClient.java:60)
at
Please suggest
I tried by enabling all the different properties like client.transport.sniffing, node.attr.rack etc. I have enabled all these properties in elasticsearch.yml
Try to change the port from 9300 to 9200. And also package you are using will be deprecated in future as per the documentation. Please try to use High Level REST Client which is feature-rich and well supported. For more details refer this link
Port 9300 is for ES nodes to communicate with each other when you have multi-node(single master-multi data) setup for elasticsearch cluster. We should be using 9200 to interact with Elasticsearch.
How I can easily configure the embedded tomcat server to redirect all http traffic to https? I have Spring Boot running on an ec2 instance that is behind an elastic load balancer. I have configured the ELB to handle ssl for me (which is awesome) and it sets the X-FORWARDED-PROTO header to "https". I want to detect when that isn't set, and redirect the user to force them to use https if they aren't already.
So far, I have tried adding the following to my application.properties file with no luck:
server.tomcat.protocol-header=x-forwarded-proto
security.require-ssl=true
My answer is a little late but I just recently had this problem and want to post a solution which worked for me.
Originally, I thought that setting tomcat up to use the X-Forwarded headers would suffice but the RemoteIPValve from Tomcat, which should normally handle this case, didnt work for me.
My solution was to add an EmbeddedServletContainerCustomizer and add a ConnectorCustomizer:
(note that I am using Tomcat 8 here)
#Component
public class TomcatContainerCustomizer implements EmbeddedServletContainerCustomizer {
private static final Logger LOGGER = LoggerFactory.getLogger(TomcatContainerCustomizer.class);
#Override
public void customize(final ConfigurableEmbeddedServletContainer container) {
if (container instanceof TomcatEmbeddedServletContainerFactory) {
final TomcatEmbeddedServletContainerFactory tomcat = (TomcatEmbeddedServletContainerFactory) container;
tomcat.addConnectorCustomizers(connector -> {
connector.setScheme("https");
connector.setProxyPort(443);
});
LOGGER.info("Enabled secure scheme (https).");
} else {
LOGGER.warn("Could not change protocol scheme because Tomcat is not used as servlet container.");
}
}
}
The important thing is that you not only set the Scheme to https but also the ProxyPort without which all internal redirects from Spring Boot were routed to port 80.
The configuration property security.require-ssl doesn't work when basic authentication is disabled (at least on old versions of Spring Boot). So you probably need to secure all the requests manually with code similar to this one:
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Inject private SecurityProperties securityProperties;
#Override
protected void configure(HttpSecurity http) throws Exception {
if (securityProperties.isRequireSsl()) http.requiresChannel().anyRequest().requiresSecure();
}
}
You can check my full answer here: Spring Boot redirect HTTP to HTTPS
You will need a keystore file and few config classes.
The below link explains it in detail.
Https on embedded tomcat
Spring Boot 2.0 redirection of http to https:
Add the following to the #Configuration
#Bean
public ServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
#Override
protected void postProcessContext(Context context) {
SecurityConstraint securityConstraint = new SecurityConstraint();
securityConstraint.setUserConstraint("CONFIDENTIAL");
SecurityCollection collection = new SecurityCollection();
collection.addPattern("/*");
securityConstraint.addCollection(collection);
context.addConstraint(securityConstraint);
}
};
tomcat.addAdditionalTomcatConnectors(redirectConnector());
return tomcat;
}
private Connector redirectConnector() {
Connector connector = new Connector(
TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
connector.setScheme("http");
connector.setPort(8080);
connector.setSecure(false);
connector.setRedirectPort(8443);
return connector;
}