Tag Archives: spring

[Solved] thymeleaf.TemplateEngineException processing template “main“: An error happened during template pars

preface

This project uses the thymeleaf template in the springboot project. The main error is that the front-end HTML page uses thymeleaf to obtain the value passed from the background. There is a problem (the value cannot be obtained, or it is empty and null)

Error message

1. error 1: the forwarded is used as redirect:/main

2021-11-18 21:02:01.321 ERROR 9272 — [nio-8082-exec-4] org.thymeleaf.TemplateEngine : [THYMELEAF][http-nio-8082-exec-4] Exception processing template “main”: An error happened during template parsing (template: “class path resource [templates/main.html]”)
*
* org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: “class path resource [templates/main.html]”)
* at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:241) ~[thymeleaf-3.0.12.RELEASE.jar:3.0.12.RELEASE]
* caused by: org.thymeleaf.exceptions.templateprocessingexception: exception evaluating springel expression: "page. Getcurrent()" (template: "main" - line 86, col 17)
* redirection cannot be used here: otherwise, the front-end data cannot be obtained through thymeleaf

2. error 2: null value error

 org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field ‘records’ cannot be found on null

Solution:

1. The first error is that when the data queried in the background is sent to the front-end HTML page, there is no corresponding value, and redirection cannot be used, otherwise the front-end data cannot be obtained through thymeleaf. Remove redirect directly and return “main” directly “;
2. The second error is somewhat similar to the first one. This error can find the corresponding data in the background on the page, but the paging data cannot be obtained without corresponding request. If you enter this page directly from the login interface, it is an error because the data of another requested page paging query is used, and there is no query directly The paging data is null. Therefore, you can only send a request to query the page paging data before it can successfully reach the main page.

Corresponding part code

1. Front end code main.html

<!--Employee data table display-->
<div class="container table-responsive" style="margin-top: 50px">
    <table class="table table-bordered">
        <caption class="caption"><a th:href="@{/showemp}">Display employee information</a> </caption>
        <thead>
            <tr>
                <th>ID</th>
                <th>ID</th>
                <th>Name</th>
                <th>Password</th>
                <th>operate</th>
            </tr>
        </thead>
        <tbody>
            <tr th:each="book,statu:${page.records}">
                <th>[[${statu.count}]]</th>
                <td th:text="${book.id}"></td>
                <td>[[${book.name}]]</td>
                <td>[[${book.password}]]</td>
                <td>
                    <a th:href="@{/delete}" type="button" class="btn btn-danger btn-sm">delete</a>
                    <a th:href="@{/update}" type="button" class="btn btn-info btn-sm">update</a></td>
            </tr>
        </tbody>
    </table>
</div>

2.CrudController.java

@Controller
public class CrudController {
   @Autowired
   BookServiceImpl bookService;

   @GetMapping("/showemp")
   public String selectAll(@RequestParam(value = "pn",defaultValue = "1")Integer pn,
                           Model model){
       Page<Book> page = new Page<>(pn,2);
       Page<Book> bookPage = bookService.page(page, null);
       model.addAttribute("page",bookPage);
       System.out.println(bookPage.getCurrent());
       System.out.println(bookPage.getRecords().size());
       /**
        * 2021-11-18 21:02:01.321 ERROR 9272 --- [nio-8082-exec-4] org.thymeleaf.TemplateEngine             : [THYMELEAF][http-nio-8082-exec-4] Exception processing template "main": An error happened during template parsing (template: "class path resource [templates/main.html]")
        *
        * org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/main.html]")
        * 	at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:241) ~[thymeleaf-3.0.12.RELEASE.jar:3.0.12.RELEASE]
        * Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "page.getCurrent()" (template: "main" - line 86, col 17)
        * Redirection cannot be used here: otherwise the front-end data cannot be obtained through thymeleaf
        */
//        return "redirect:/main";
       return "main";
   }
}

3.LoginController.java

@PostMapping("/login")
    public String LoginValidation(Book book,
                                  RedirectAttributes redirectAttributes){
        String name = book.getName();
        String password = book.getPassword();
        Map<String,Object> map = new HashMap<>();
        map.put("name",name);
        map.put("password",password);
        QueryWrapper<Book> queryWrapper = new QueryWrapper<>();
        queryWrapper.ge("name",name );
        queryWrapper.ge("password",password);
        Book one = bookService.getOne(queryWrapper);
        if (one.toString()!=null){
            /**
             * org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'records' cannot be found on null
             * It is wrong to enter this page directly from the login interface, because the page paging query data requested by showemp is used here, and there is no query when entering directly, and the page paging data is null.
              * So you can only successfully reach the main page by sending a showemp request to query the page paging data.
             */
//            return "redirect:/main";
            return "redirect:/showemp";
        }
        return "login";
    }

[Solved] java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corres

0. Foreword: this error is an error reported by using mybatis in the spring boot project to query a piece of data in the database according to the ID value

1. Error message

2021-11-14 15:37:38.168 ERROR 9936 --- [nio-8086-exec-7] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.jdbc.BadSqlGrammarException: 
### Error querying database.  Cause: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
### The error may exist in file [E:\smallTools\idea\code\spring\springboot-new-2021_11_09\springboot-new-mybatis\target\classes\mybatis\mapper\BookMapper.xml]
### The error may involve com.feng.mybatis.mapper.BookMapper.getBookById-Inline
### The error occurred while setting parameters
### SQL: select * from book where id={#id}
### Cause: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
; bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1] with root cause

java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
	at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120) ~[mysql-connector-java-8.0.27.jar:8.0.27]

2. Mapper.xml file content

<select id="getBookById" parameterType="com.feng.mybatis.bean.Book">
        select * from book where id={#id}
</select>

3. Error reason: the SQL statement is written incorrectly. It should be where id = #{id}

<select id="getBookById" parameterType="com.feng.mybatis.bean.Book">
        select * from book where id=#{id}
</select>

How to Solve Error: Invalid bound statement (not found)

When spring integrates mybatis, such an error is reported because the package name is created incorrectly when the mapper.xml file is created in the resources directory. Because the package cannot be created under resources, only the folder directory can be created. The key point is (the folder cannot be in the form of “.”), so it can’t be lazy and easy. The directory should be created level by level

Error attempting to get column ‘xxxxx’ from result set — after Lombok is annotated with builder, mybatis cannot recognize the correct type of field

Pit stepping record – after Lombok is annotated with builder, mybatis cannot recognize the correct type of field

After adding Lombok to the entity class, sometimes we will use @ builder annotation, so we don’t need to write too many set methods to define the attribute content, which makes our code more elegant. Once the @ builder annotation is added to the entity class, it will cause problems in our mybatis mapping database fields

The questions are as follows

org.springframework.dao.DataIntegrityViolationException: Error attempting to get column 'username' from result set.  Cause: java.sql.SQLDataException: Cannot determine value type from string 'zhangsa'
; Cannot determine value type from string 'zhangsa'; nested exception is java.sql.SQLDataException: Cannot determine value type from string 'zhangsa'

note: when using @ builder annotation, a full parameter structure will be generated, resulting in the disappearance of no parameter structure

terms of settlement

    we can directly remove @ builder annotation, and there will be no problem for mybatis to query the database. We can generate parametric and nonparametric constructs in entity classes (you can add them manually or add annotations @ allargsconstructor , @ noargsconstructor )

    if it is still abnormal, you should check whether your entity class and database type mapping do not correspond

    Hold fireworks to seek life, poetic to seek love

[Solved] java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].StandardContext[]]

Error Messages:

java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].StandardContext[]]
.......
Caused by:
             org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].StandardContext[]]
......
Caused by:
             java.lang.ClassCastException: class org.springframework.web.SpringServletContainerInitializer cannot be cast to class javax.servlet.ServletContainerInitializer (org.springframework.web.SpringServletContainerInitializer is in unnamed module of loader org.apache.catalina.loader.WebappClassLoader @1e0295e0; javax.servlet.ServletContainerInitializer is in unnamed module of loader org.codehaus.plexus.classworlds.realm.ClassRealm @3d88e6b9)
......

 

cause:
I imported the following dependencies in the project’s pom.xml and found that the tomcat7 plugin can’t run
E.g:

<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>javax.servlet-api</artifactId>
  <version>4.0.1</version>
</dependency>
<dependency>
  <groupId>javax.servlet.jsp</groupId>
  <artifactId>javax.servlet.jsp-api</artifactId>
  <version>2.3.3</version>
</dependency>

Check:

1. Check whether the current port is occupied by the process

2. Check whether there is a problem with the servlet mapping URL path in web.xml

3. Check for dependency conflicts

reason:

The servlet dependent version imported in the current Maven configuration file is too high and incompatible with tomcat7

Solution:

The tomcat7 plug-in in pom.xml can be upgraded to tomcat8

reference:

<pluginRepositories>
  <pluginRepository>
    <id>alfresco-public</id>
    <url>https://artifacts.alfresco.com/nexus/content/groups/public</url>
  </pluginRepository>
  <pluginRepository>
    <id>alfresco-public-snapshots</id>
    <url>https://artifacts.alfresco.com/nexus/content/groups/public-snapshots</url>
    <snapshots>
      <enabled>true</enabled>
      <updatePolicy>daily</updatePolicy>
    </snapshots>
  </pluginRepository>
  <pluginRepository>
    <id>beardedgeeks-releases</id>
    <url>http://beardedgeeks.googlecode.com/svn/repository/releases</url>
  </pluginRepository>
</pluginRepositories>
<build>
  <plugins>
    <plugin>
      <groupId>org.apache.tomcat.maven</groupId>
      <artifactId>tomcat8-maven-plugin</artifactId>
      <version>3.0-r1655215</version>
      <configuration>
        <port>80</port>
        <path>/</path>
      </configuration>
    </plugin>
  </plugins>
</build>

last:

Refresh the Maven management tool, recompile the Maven project, and then start it with tomcat8!

[Solved] Failed to configure a DataSource: ‘url‘ attribute is not specified…bug

Question page

Error message in log
no mybatis mapper was found in ‘[com. Ego]’ package. Please check your
configuration. Will not attempt to authenticate using SASL (unknown error)

Console output

Solution 1

Solution 1. I read many blogs, most of which are this solution. But it didn’t solve my problem

Solution 2

1. Because the versions of spring web and spring webmvc in POM are inconsistent, unify the dependent versions
2. If there are no database related things configured, comment out the POM dependencies of mybatis and MySQL first

I cited the problem caused by mapper’s Maven dependency in the consumermodel. Just delete it.

[Solved] Druid register MBean error: ERROR [com.alibaba.druid.stat.DruidDataSourceStatManager]

It is normal to run a Tomcat project. When running two Tomcat projects, an exception will be reported.

ERROR [com.alibaba.druid.stat.DruidDataSourceStatManager] – unregister mbean error javax.management.InstanceNotFoundException: com.alibaba.druid:type=DruidDataSourceStat at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getMBean………

Solution:

Modify catalina.sh under Tomcat: add and set Java at the end_OPTS="Ddruid.registerToSysProperty=true"

This method is effective in personal test. If it is added in other places, it is not guaranteed to be effective

Springboot modifies the reference of the application.yml or. Properties file to report an error after startup

When working, in many cases, we will define the configuration used in production, testing, development and other environments, and then reference the corresponding configuration in application.yml or properties. Occasionally, when I modify the showsql property in the configuration, I start to report an error as soon as I start the project

Caused by: java.nio.charset.MalformedInputException: Input length = 1
	at java.nio.charset.CoderResult.throwException(CoderResult.java:281) ~[?:1.8.0_291]
	at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:339) ~[?:1.8.0_291]
	at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178) ~[?:1.8.0_291]
	at java.io.InputStreamReader.read(InputStreamReader.java:184) ~[?:1.8.0_291]
	at org.yaml.snakeyaml.reader.UnicodeReader.read(UnicodeReader.java:125) ~[snakeyaml-1.23.jar:?]
	at org.yaml.snakeyaml.reader.StreamReader.update(StreamReader.java:183) ~[snakeyaml-1.23.jar:?]
	at org.yaml.snakeyaml.reader.StreamReader.ensureEnoughData(StreamReader.java:176) ~[snakeyaml-1.23.jar:?]
	at org.yaml.snakeyaml.reader.StreamReader.peek(StreamReader.java:136) ~[snakeyaml-1.23.jar:?]
	at org.yaml.snakeyaml.scanner.ScannerImpl.scanPlain(ScannerImpl.java:1999) ~[snakeyaml-1.23.jar:?]
	at org.yaml.snakeyaml.scanner.ScannerImpl.fetchPlain(ScannerImpl.java:1044) ~[snakeyaml-1.23.jar:?]
	at org.yaml.snakeyaml.scanner.ScannerImpl.fetchMoreTokens(ScannerImpl.java:399) ~[snakeyaml-1.23.jar:?]
	at org.yaml.snakeyaml.scanner.ScannerImpl.checkToken(ScannerImpl.java:227) ~[snakeyaml-1.23.jar:?]
	at org.yaml.snakeyaml.parser.ParserImpl$ParseBlockMappingKey.produce(ParserImpl.java:558) ~[snakeyaml-1.23.jar:?]
	at org.yaml.snakeyaml.parser.ParserImpl.peekEvent(ParserImpl.java:158) ~[snakeyaml-1.23.jar:?]
	at org.yaml.snakeyaml.parser.ParserImpl.checkEvent(ParserImpl.java:148) ~[snakeyaml-1.23.jar:?]
	at org.yaml.snakeyaml.composer.Composer.composeMappingNode(Composer.java:214) ~[snakeyaml-1.23.jar:?]
	at org.yaml.snakeyaml.composer.Composer.composeNode(Composer.java:144) ~[snakeyaml-1.23.jar:?]
	at org.yaml.snakeyaml.composer.Composer.composeValueNode(Composer.java:236) ~[snakeyaml-1.23.jar:?]
	at org.yaml.snakeyaml.composer.Composer.composeMappingChildren(Composer.java:227) ~[snakeyaml-1.23.jar:?]
	at org.yaml.snakeyaml.composer.Composer.composeMappingNode(Composer.java:215) ~[snakeyaml-1.23.jar:?]
	at org.yaml.snakeyaml.composer.Composer.composeNode(Composer.java:144) ~[snakeyaml-1.23.jar:?]
	at org.yaml.snakeyaml.composer.Composer.composeValueNode(Composer.java:236) ~[snakeyaml-1.23.jar:?]
	at org.yaml.snakeyaml.composer.Composer.composeMappingChildren(Composer.java:227) ~[snakeyaml-1.23.jar:?]
	at org.yaml.snakeyaml.composer.Composer.composeMappingNode(Composer.java:215) ~[snakeyaml-1.23.jar:?]
	at org.yaml.snakeyaml.composer.Composer.composeNode(Composer.java:144) ~[snakeyaml-1.23.jar:?]
	at org.yaml.snakeyaml.composer.Composer.composeValueNode(Composer.java:236) ~[snakeyaml-1.23.jar:?]
	at org.yaml.snakeyaml.composer.Composer.composeMappingChildren(Composer.java:227) ~[snakeyaml-1.23.jar:?]
	at org.yaml.snakeyaml.composer.Composer.composeMappingNode(Composer.java:215) ~[snakeyaml-1.23.jar:?]
	at org.yaml.snakeyaml.composer.Composer.composeNode(Composer.java:144) ~[snakeyaml-1.23.jar:?]
	at org.yaml.snakeyaml.composer.Composer.getNode(Composer.java:85) ~[snakeyaml-1.23.jar:?]
	at org.yaml.snakeyaml.constructor.BaseConstructor.getData(BaseConstructor.java:123) ~[snakeyaml-1.23.jar:?]
	at org.yaml.snakeyaml.Yaml$1.next(Yaml.java:547) ~[snakeyaml-1.23.jar:?]
	at org.springframework.beans.factory.config.YamlProcessor.process(YamlProcessor.java:200) ~[spring-beans-5.1.19.RELEASE.jar:5.1.19.RELEASE]
	at org.springframework.beans.factory.config.YamlProcessor.process(YamlProcessor.java:164) ~[spring-beans-5.1.19.RELEASE.jar:5.1.19.RELEASE]
	at org.springframework.boot.env.OriginTrackedYamlLoader.load(OriginTrackedYamlLoader.java:76) ~[spring-boot-2.1.18.RELEASE.jar:2.1.18.RELEASE]
	at org.springframework.boot.env.YamlPropertySourceLoader.load(YamlPropertySourceLoader.java:50) ~[spring-boot-2.1.18.RELEASE.jar:2.1.18.RELEASE]
	at org.springframework.boot.context.config.ConfigFileApplicationListener$Loader.loadDocuments(ConfigFileApplicationListener.java:544) ~[spring-boot-2.1.18.RELEASE.jar:2.1.18.RELEASE]
	at org.springframework.boot.context.config.ConfigFileApplicationListener$Loader.load(ConfigFileApplicationListener.java:499) ~[spring-boot-2.1.18.RELEASE.jar:2.1.18.RELEASE]
	... 28 more

Then, if I restart the project after rebuilding, there will still be an error. At this time, we just need to reinstall in Maven to run successfully

Self test error when springboot accesses es and starts

1、 Background

Recently, I was working on a project to connect two es clusters, so I initialized two resthighlevelclient instances esclient and esclient1

package com.xxx.common.config;

import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class EsConfig {

    @Value("${es.url}")
    private String url;

    @Value("${es.port}")
    private Integer port;

    @Value("${es.username}")
    private String username;

    @Value("${es.password}")
    private String password;

    @Value("${es.connection.timeout:30000}")
    private int connctionTimeout;

    @Value("${es.socket.timeout:60000}")
    private int socketTimeout;

    @Bean
    public RestHighLevelClient esClient() {
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));

        RestClientBuilder builder = RestClient.builder(new HttpHost(url, port))
                .setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
                    @Override
                    public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
                        return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
                    }
                }).setRequestConfigCallback(requestConfigBuilder -> requestConfigBuilder.setConnectTimeout(connctionTimeout)
                        .setSocketTimeout(socketTimeout));
        RestHighLevelClient client = new RestHighLevelClient(builder);
        return client;
    }
}

As a result, an error was reported during startup, as follows:

java.net.ConnectException: Connection refused
 at org.elasticsearch.client.RestClient.extractAndWrapCause(RestClient.java:823)
 at org.elasticsearch.client.RestClient.performRequest(RestClient.java:248)
 at org.elasticsearch.client.RestClient.performRequest(RestClient.java:235)
 at org.springframework.boot.actuate.elasticsearch.ElasticsearchRestHealthIndicator.doHealthCheck(ElasticsearchRestHealthIndicator.java:60)
 at org.springframework.boot.actuate.health.AbstractHealthIndicator.health(AbstractHealthIndicator.java:82)
 at org.springframework.boot.actuate.health.HealthIndicator.getHealth(HealthIndicator.java:37)
 at org.springframework.boot.actuate.health.HealthEndpoint.getHealth(HealthEndpoint.java:71)
 at org.springframework.boot.actuate.health.HealthEndpoint.getHealth(HealthEndpoint.java:39)
 at org.springframework.boot.actuate.health.HealthEndpointSupport.getContribution(HealthEndpointSupport.java:99)
 at org.springframework.boot.actuate.health.HealthEndpointSupport.getAggregateHealth(HealthEndpointSupport.java:110)
 at org.springframework.boot.actuate.health.HealthEndpointSupport.getContribution(HealthEndpointSupport.java:96)
 at org.springframework.boot.actuate.health.HealthEndpointSupport.getHealth(HealthEndpointSupport.java:74)
 at org.springframework.boot.actuate.health.HealthEndpointSupport.getHealth(HealthEndpointSupport.java:61)
 at org.springframework.boot.actuate.health.HealthEndpoint.health(HealthEndpoint.java:65)
 at org.springframework.boot.actuate.health.HealthEndpoint.health(HealthEndpoint.java:55)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:498)
 at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:282)
 at org.springframework.boot.actuate.endpoint.invoke.reflect.ReflectiveOperationInvoker.invoke(ReflectiveOperationInvoker.java:77)
 at org.springframework.boot.actuate.endpoint.annotation.AbstractDiscoveredOperation.invoke(AbstractDiscoveredOperation.java:60)
 at org.springframework.boot.actuate.endpoint.jmx.EndpointMBean.invoke(EndpointMBean.java:121)
 at org.springframework.boot.actuate.endpoint.jmx.EndpointMBean.invoke(EndpointMBean.java:96)
 at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
 at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
 at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1468)
 at javax.management.remote.rmi.RMIConnectionImpl.access$300(RMIConnectionImpl.java:76)
 at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1309)
 at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1401)
 at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:829)
 at sun.reflect.GeneratedMethodAccessor87.invoke(Unknown Source)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:498)
 at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:357)
 at sun.rmi.transport.Transport$1.run(Transport.java:200)
 at sun.rmi.transport.Transport$1.run(Transport.java:197)
 at java.security.AccessController.doPrivileged(Native Method)
 at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
 at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:573)
 at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:834)
 at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:688)
 at java.security.AccessController.doPrivileged(Native Method)
 at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:687)
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
 at java.lang.Thread.run(Thread.java:748)
 Caused by: java.net.ConnectException: Connection refused
 at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
 at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:715)
 at org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor.processEvent(DefaultConnectingIOReactor.java:174)
 at org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor.processEvents(DefaultConnectingIOReactor.java:148)
 at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor.execute(AbstractMultiworkerIOReactor.java:351)
 at org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager.execute(PoolingNHttpClientConnectionManager.java:221)
 at org.apache.http.impl.nio.client.CloseableHttpAsyncClientBase$1.run(CloseableHttpAsyncClientBase.java:64)
 ... 1 common frames omitted

  2、 Analyze the cause

Why only one client will not report an error?If two clients report an error through self-test, and the URL in the client is【 http://localhost:9200 】, with such questions, I read the source code of ES self-test once

ElasticsearchRestHealthIndicator

The main method is this

public ElasticsearchRestHealthIndicator(RestClient client) {
    super("Elasticsearch health check failed");
    this.client = client;
    this.jsonParser = JsonParserFactory.getJsonParser();
}

protected void doHealthCheck(Builder builder) throws Exception {
    Response response = this.client.performRequest(new Request("GET", "/_cluster/health/"));
    StatusLine statusLine = response.getStatusLine();
    if (statusLine.getStatusCode() != 200) {
        builder.down();
        builder.withDetail("statusCode", statusLine.getStatusCode());
        builder.withDetail("reasonPhrase", statusLine.getReasonPhrase());
    } else {
        InputStream inputStream = response.getEntity().getContent();
        Throwable var5 = null;

        try {
            this.doHealthCheck(builder, StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8));
        } catch (Throwable var14) {
            var5 = var14;
            throw var14;
        } finally {
            if (inputStream != null) {
                if (var5 != null) {
                    try {
                        inputStream.close();
                    } catch (Throwable var13) {
                        var5.addSuppressed(var13);
                    }
                } else {
                    inputStream.close();
                }
            }

        }

    }
}

The reason for the error is that the URL in the client configuration is not pointed to correctly【 http://localhost:9200 】So curiosity showed me the ES auto configuration source code

ElasticsearchRestClientAutoConfiguration

ElasticsearchRestClientConfigurations

ElasticsearchRestClientProperties

RestClientBuilderCustomizer

I found something fishy in elasticsearchrestclientconfigurations, as shown in the following code

    @Bean
    @ConditionalOnMissingBean
    RestClient elasticsearchRestClient(RestClientBuilder builder, ObjectProvider<RestHighLevelClient> restHighLevelClient) {
        RestHighLevelClient client = (RestHighLevelClient)restHighLevelClient.getIfUnique();
        return client != null ?client.getLowLevelClient() : builder.build();
    }

This code indicates that if there are multiple resthighlevelclient instances in the current application, restclientbuilder will be selected. If there is only one instance, the default one will be selected. This also explains the default configuration of elasticsearchrestclientproperties if there are multiple clients without an error

private List<String> uris = new ArrayList(Collections.singletonList("http://localhost:9200"));
private String username;
private String password;
private Duration connectionTimeout = Duration.ofSeconds(1L);
private Duration readTimeout = Duration.ofSeconds(30L);

3、 Solution

1. If there are multiple es, remove the self-test (not recommended)

management.health.elasticsearch.enabled=false

2. Configure the default restclientbuilder to self check the default es

The first method: keep the name the same as the default resthighlevelclient

@Bean(name = "restHighLevelClient")
public RestHighLevelClient restHighLevelClient() {
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));

        RestClientBuilder builder = RestClient.builder(new HttpHost(url, port))
                .setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
                    @Override
                    public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
                        return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
                    }
                }).setRequestConfigCallback(requestConfigBuilder -> requestConfigBuilder.setConnectTimeout(connctionTimeout)
                        .setSocketTimeout(socketTimeout));

        RestHighLevelClient restHighLevelClient = new RestHighLevelClient(builder);
        return restHighLevelClient;
}

The second method: set @ primary as the default

@Bean
@Primary
public RestHighLevelClient esClient() {
    final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
    credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));

    RestClientBuilder builder = RestClient.builder(new HttpHost(url, port))
            .setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
                @Override
                public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
                    return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
                }
            }).setRequestConfigCallback(requestConfigBuilder -> requestConfigBuilder.setConnectTimeout(connctionTimeout)
                    .setSocketTimeout(socketTimeout));
    RestHighLevelClient client = new RestHighLevelClient(builder);
    return client;
}

3. Repeat the ES self-test procedure (allow multiple es clusters to perform self-test)

What I’m interested in is to expand and enable the two clusters to implement health check

The typereference reported an error classnotfoundexception:

Error message

java.lang.ClassNotFoundException: com.alibaba.fastjson.TypeReference

First, I went to the mvnrepository to find the fastjson package
introduced into the common service dependency
but still reported an error

Later, in project structure, I found that the dependencies of search service are also divided into complie, runtime, test, etc. my fastjson scope is test. After I modify it to complie, it can be used normally

Common errors reported by Eureka in spring cloud

1.Consider the following:
     If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
     If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).

The reason for this is that the service provider starts earlier than Eureka, or Eureka service may not start, and then start the service provider after Eureka starts.

2.No instances found of configserver (config-server)

The annotation @ enablediscoveryclient may be missing from the startup class

  3.Cannot execute request on any known server

This error is due to the missing annotation @ enableeurekaserver in the Eureka startup class