Tag Archives: spring

Spring Boot Druid Error: discard long time none received connection

Spring boot integration Druid exception

In the spring boot integrated Druid project, the following error messages are frequently found in the error log:

discard long time none received connection. , jdbcUrl : jdbc:mysql://******?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8, version : 1.2.3, lastPacketReceivedIdleMillis : 172675

After troubleshooting, it was found that the exception was caused by Druid version, which did not appear in version 1.2.2 or earlier. In the above versions, there is this problem, the following is to analyze the causes of the exception and solutions.

Anomaly analysis

First of all, the above exception does not affect the normal operation of the program, but as a programmer to see the program constantly abnormal or intolerable. So we still need to get to the bottom of it.

Trace the stack information and find that the corresponding exception is thrown from the com.alibaba.druid.pool.druidabstractdatasource # testconnectioninternal method. The corresponding code is as follows:

if (valid && isMySql) { // unexcepted branch
    long lastPacketReceivedTimeMs = MySqlUtils.getLastPacketReceivedTimeMs(conn);
    if (lastPacketReceivedTimeMs > 0) {
        long mysqlIdleMillis = currentTimeMillis - lastPacketReceivedTimeMs;
        if (lastPacketReceivedTimeMs > 0 //
                && mysqlIdleMillis >= timeBetweenEvictionRunsMillis) {
            discardConnection(holder);
            String errorMsg = "discard long time none received connection. "
                    + ", jdbcUrl : " + jdbcUrl
                    + ", jdbcUrl : " + jdbcUrl
                    + ", lastPacketReceivedIdleMillis : " + mysqlIdleMillis;
            LOG.error(errorMsg);
            return false;
        }
    }
}

In the above code, mysqlutils.getlastpacketreceivedtimems (conn) is to get the last used time, mysqlidle millis is to calculate the idle time, and timebetweenevecitionrunsmillis is a constant of 60 seconds. If the connection is idle for more than 60 seconds, the discard connection (holder) discards the old connection and prints a log. Warn (errormsg) along with it.

Principle tracing

In the above code, we can see that there is a prerequisite for entering the business logic, that is, the variables valid and ismysql are true at the same time. It is necessary for ismysql to be true. What we use is the MySQL database. Can I make valid false?In this way, it will not enter the business processing?

Let’s take a look at the source of the valid method

boolean valid = validConnectionChecker.isValidConnection(conn, validationQuery, validationQueryTimeout);

We find the MySQL implementation subclass of validconnectionchecker, MySQL validconnectionchecker. The implementation of isvalidconnection in this class is as follows:

public boolean isValidConnection(Connection conn, String validateQuery, int validationQueryTimeout) throws Exception {
    if (conn.isClosed()) {
        return false;
    }

    if (usePingMethod) {
        if (conn instanceof DruidPooledConnection) {
            conn = ((DruidPooledConnection) conn).getConnection();
        }

        if (conn instanceof ConnectionProxy) {
            conn = ((ConnectionProxy) conn).getRawObject();
        }

        if (clazz.isAssignableFrom(conn.getClass())) {
            if (validationQueryTimeout <= 0) {
                validationQueryTimeout = DEFAULT_VALIDATION_QUERY_TIMEOUT;
            }

            try {
                ping.invoke(conn, true, validationQueryTimeout * 1000);
            } catch (InvocationTargetException e) {
                Throwable cause = e.getCause();
                if (cause instanceof SQLException) {
                    throw (SQLException) cause;
                }
                throw e;
            }
            return true;
        }
    }

    String query = validateQuery;
    if (validateQuery == null || validateQuery.isEmpty()) {
        query = DEFAULT_VALIDATION_QUERY;
    }

    Statement stmt = null;
    ResultSet rs = null;
    try {
        stmt = conn.createStatement();
        if (validationQueryTimeout > 0) {
            stmt.setQueryTimeout(validationQueryTimeout);
        }
        rs = stmt.executeQuery(query);
        return true;
    } finally {
        JdbcUtils.close(rs);
        JdbcUtils.close(stmt);
    }

}

We can see that there are three return places in the above methods: the first connection is closed; The second uses Ping to check; Third, use select 1 to check. When Ping is used, it will return true no matter whether the exception is thrown or not. Here we can disable this mode.

The business logic of Ping mainly depends on the variable usepingmethod. Tracing code will find the settings here:

public void configFromProperties(Properties properties) {
    String property = properties.getProperty("druid.mysql.usePingMethod");
    if ("true".equals(property)) {
        setUsePingMethod(true);
    } else if ("false".equals(property)) {
        setUsePingMethod(false);
    }
}

In other words, when we set the system property Druid. Mysql. Usepingmethod to false, we can disable this function.

Disable ping method

After finding the root of the problem, the rest is how to disable it. There are usually three forms.

First, when starting the program, add: – Druid. Mysql. Usepingmethod = false in the running parameters.

Second, in the spring boot project, you can add the following static code to the startup class:

static {
    System.setProperty("druid.mysql.usePingMethod","false");
}

Third, class file configuration. In the druidconfig class of the project, add:

/*
* Resolving druid log errors: discard long time none received connection:xxx
* */
@PostConstruct
public void setProperties(){
    System.setProperty("druid.mysql.usePingMethod","false");
}

So far, the function has been successfully turned off, and the exception information will never appear again.

Why clear connections that are idle for more than 60 seconds

It is speculated that the idle waiting time of the database set by Alibaba is 60 seconds. When the MySQL database reaches the idle waiting time, the idle connection will be closed to improve the processing capacity of the database server.

The default idle waiting time of MySQL is 8 hours, which is “wait”_ “Timeout”. If the database actively closes the idle connection, but the connection pool does not know that it is still using the connection, an exception will be generated.

Can’t Dubbo’s @ service be injected into the spring container?

Solution: rebuild the module and test again
when testing the Dubbo provider, adding @ service under the Dubbo path to the business implementation code will report that a test class is not injected
org.springframework.beans.factory.unsatisfied dependencyexception: error creating bean with name ‘com.tanhua.dubbo.server.api.testrecommenduserapi XXXXXX,
No qualifying bean of type ‘com. Tanhua. Dubbo. Server. API. Recommenduserapi’ available: (I think the interface recommenduserapi was not injected), so I replaced it with spring’s @ service line; But shouldn’t Dubbo’s @ service have spring’s @ service function?Baidu for a long time did not belong to their correct answer; After carefully checking the scan package, the annotation @ runwith (springrunner. Class) @ springboottest
on the test class has been added, and the @ service under Dubbo still reports an error
at last, the module was simply rebuilt by copying and pasting, and the final test was successful!! But what’s wrong?I don’t know. Maybe it’s related to building a module! Hope it works…

Cannot resolve reference to bean ‘sqlSessionFactory‘ while setting bean property ‘sqlSessionFactory‘

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘collectionService’: Unsatisfied dependency expressed through field ‘collectionDao’; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘collectionDao’ defined in file [E:\IdeaProjects\myMusic\target\track-stacking\WEB-INF\classes\com\hechenbo\trackstacking\dao\CollectionDao.class]: Cannot resolve reference to bean ‘sqlSessionFactory’ while setting bean property ‘sqlSessionFactory’; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘sqlSessionFactory’ defined in class path resource [bean.xml]: Initialization of bean failed; nested exception is org.springframework.beans.TypeMismatchException: Failed to convert property value of type ‘java.lang.String’ to required type ‘org.springframework.core.io.Resource[]’ for property ‘mapperLocations’; nested exception is java.lang.IllegalArgumentException: Could not resolve resource location pattern [classpath:com/hechenbo/trackstacking/dao/impl/*.xml]: class path resource [com/hechenbo/trackstacking/dao/impl/] cannot be resolved to URL because it does not exist

Error creating bean with name ‘collectionDao’ defined in file [E:\IdeaProjects\myMusic\target\track-stacking\WEB-INF\classes\com\hechenbo\trackstacking\dao\CollectionDao.class]
maven will compile and package the file will miss the xml file, when starting tomcat can not find the xml file, in all configuration files are no problem, the target folder does not contain the mapping xml file.
The xml file is not packaged by maven under the target. Add it to the <build> tag in pom.xml:

<resources>
          <resource>
              <directory>src/main/java</directory>
              <includes>
                  <include>**/*.xml</include>
              </includes>
              <filtering>true</filtering>
          </resource>
      </resources>

Then clean in Maven and restart Tomcat to display the mapping XML file in the class directory

Cause: java.sql.BatchUpdateException: Unknown column ‘xxx‘ in ‘field list‘

Error 12164 – [xnio-1 TASK-2] p.p.c.s.c.globalexception handler resolver: Global exception information ex = com.xxx.cd.mapper.cdinvoiceinfomapper.insert (batch index # 1) failed———— Error information

Cause: java.sql.batchupdateexception: unknown column ‘xxx’ in ‘field list’ — prompt reason

Finding problems

First of all, the error prompt means that the field cannot be found in the database and the input is invalid

resolvent

    first check the database to see if there is this field in the table. If not, add it. Then add this field to the corresponding mapper.xml and entity class. If the above problems do not exist or cannot be solved, it is recommended to check on the web side to see if there is this missing data in your input data. If not, check the service layer, Open the configuration in Nacos, maintain the table directory in this field, and find that there is this table, but this table does not need this field. Remove this table from it, and then you can do it

Summary

Don’t be afraid when you make mistakes. It’s best to read the error information and the reason patiently, and understand the meaning roughly. If you don’t understand, ask your colleagues first.

Error assembling WAR: Problem creating war: Execution exception (and the archive is probably corrup

Using idea development, Maven build error:

 Error assembling WAR: Problem creating war: Execution exception (and the archive is probably corrupt but I could not delete it)

The cause of the error is that the memory of the JVM is not enough, so it’s better to configure it. The steps are as follows:

So we modify Maven’s JVM parameters directly in idea,

file-> setting-> Build,Execution,Deployment-> Maven-> Runner

Set the JVM parameter in VM option column, – xmx1g – XX: maxmetaspacesize = 128M

After setting, click Install on the right side to start the compilation, the parameter takes effect, and the maximum heap memory becomes 1g
0  

Get connection timeout retry: 1 MySQL errorcode 0, state 08s01 docker container accessing MySQL container is very slow and sometimes interrupted

Today, I encountered a problem: starting the Tomcat container and then accessing the MySQL container, the query speed is very slow, and sometimes it is the same as disconnecting
solution: when starting the Tomcat container, do not add the host name and MAC address, it is likely that there is a conflict

When SSM + Maven project is running, it is prompted that org.springframework.web.servlet.dispatcherserservlet cannot be found

When SSM + Maven project is running, it is prompted that org.springframework.web.servlet.dispatcherserservlet cannot be found

When running SSM project today, an error is reported:
HTTP status 500 – error identifying servlet class org. Springframework. Web. Servlet. Dispatcherservlet
java. Lang. classnotfoundexception: org. Springframework. Web. Servlet. Dispatcherservlet

You can confirm that org. Springframework. Web. Servlet. Dispatcherservlet exists and Maven is imported normally

Problem solving method:
select item – & gt; Right click Properties – & gt; Select deployment asset – & gt; Select Add – & gt; Select Java build path entries – & gt; Next-> Select Maven dependencies – & gt; Finish-> Apply-> OK

It can solve the problem

————————————————
Link to the original text: https://blog.csdn.net/cd19930508/article/details/80256595

Aspecj cannot intercept method annotations on an interface

Aspecj cannot intercept method annotations on an interface

Aspecj can’t intercept the method annotation on the interface, it can only act on the method of the implementation class. At this time, it needs to use methodinterceptor to implement.

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface AopTest {
}

Interface

public interface TestAOPI {
    @AopTest
    public String test();

}

Implementation class 1

@Service
public class TestAOPService implements TestAOPI{
    @Override
    public String test() {
        return "service";
    }
}

Implementation class 2

@Service
public class TestAOPService2 implements TestAOPI{
	@AopTest
    @Override
    public String test() {
        return "service";
    }
}

Aspecj (partially valid)

If and only if the @ aoptest annotation is added to the method of the implementation class, it will take effect (implementation class 2), but implementation class 1 will not

@Aspect
@Configuration
public class AopTestAspect {
  /**
     * Identifies the method annotated with OperationLog
     */
    @Pointcut("@annotation(com.example.demo1.config.AopTest)")
    public void methodHasAopTestAnnotation() {
    }
    
    @Around("methodHasAopTestAnnotation()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("aop!!!");
        return joinPoint.proceed();
    }
}

Solution

It needs to be changed to the following way by manual

@Configuration
public class AopTestConfiguration {
	@Bean
    public Advisor methodPointcutAdvisor() {
        AopTestMethodPointcutAdvisor advisor = new AopTestMethodPointcutAdvisor();
        advisor.setAdvice(new AopTestInterceptor());
        return advisor;
    }

    class AopTestInterceptor implements MethodInterceptor {
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            String name = invocation.getMethod().getName();
            System.out.println("==============" + name + " before ================");
            Object result = invocation.proceed();
            System.out.println("==============" + name + " after ================");
            return result;
        }
    }
    public class AopTestMethodPointcutAdvisor extends StaticMethodMatcherPointcutAdvisor {
        @Override
        public boolean matches(Method method, Class<?> targetClass) {
        	// Implementing a class method with a target annotation on it
            if(method.isAnnotationPresent(AopTest.class)){
                return true;
            }
            // The method has a corresponding interface method and the interface method is annotated
            Class<?>[] interfaces = method.getDeclaringClass().getInterfaces();
            for (int i = 0; i < interfaces.length; i++) {
                Method[] methods = interfaces[i].getMethods();
                for (int j = 0; j < methods.length; j++) {
                    if(methods[j].getName().equals(method.getName())){
                        return methods[j].isAnnotationPresent(AopTest.class);
                    }
                }
            }
            return false;
        }
    }
}

How to Solve Spring Cloud Error context has been closed already

Context has been closed already solution

Error code

With such a piece of code, the context has been closed already error may occur during running, and once it occurs, it will make an error every time it runs in the future.

@Component
public class SpringContextUtil implements ApplicationContextAware {

    private static ApplicationContext context = null;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ApplicationContextExt.context = applicationContext;
    }

	/**
	 * This static method allows you to retrieve the desired bean from the Spring context.
	 */
	public static <T> T getBean(Class<T> cls) {
        if (context == null)
            throw new IllegalStateException("no application context aviliable.");
        try {
            return (T) context.getBean(cls); // Wrong!
        } catch (BeansException e) {
			throw new RuntimeException(e);
        }
        return (T) null;
    }
}    

Cause analysis

However, when spring cloud context. Jar is included in the classpath, because the contextrefresher class will close the old context when the context is refreshed, so that the context in the static class has been closed, so this error will occur.

Trigger exploration

Find out the direct reason. Find out that a jar that you depend on listens to a notification from MQ. When you hear the message to be refreshed, you will refresh the context, which leads to this phenomenon.

Springboot time zone problem

1. Add the

@PostConstruct

void   setDefaultTimezone()  {
  TimeZone.setDefault(TimeZone.getTimeZone(“Asia/Shanghai”));
}  
2. Add the

 ##  json   setting
spring.jackson.date-format=yyyy-MM-dd   HH:mm:ss
spring.jackson.time-zone=Asia/Shanghai  
 
3. Add the

public static void main(String[] args) {

    TimeZone.setDefault(TimeZone.getTimeZone(“Asia/Shanghai”));

  SpringApplication.run(BaseMicroServiceApplication.class, args);

}

 
// Otherwise, there will be 8-hour time difference on the server

Or in the database:

After logging in as root, set global time_ zone=’+8:00′;

 
 
Mysql database has time zone setting, and the system time zone is used by default

You can query the current time zone through the following statement

show variables like ‘%time_ zone%’;

Why interview requires reading the source code

Some people always think that when interviewing to build an aircraft carrier, you need to screw up your work. In the junior interview, you often ask, what is the life cycle of spring and what has been done since it was started, but it doesn’t matter at work. It’s useless and meaningless. Is that really the case?

Here is a small problem that can only be solved by understanding the initial sequence of spring.

Problem description

In the old version, obtaining a certain data XXX depends on a table tb in the database_ XXX, the new version requires to obtain these data by calling service_ B service interface. It’s reasonable to change bservice’s implementation class to interface mode, but after the change, we find that the application can’t be started! Error: DH handshake failed! I didn’t modify other logic, but I couldn’t start it, and the interface I called doesn’t need any encryption verification. As a fresh undergraduate who has been employed for less than two months, how can I solve this situation?

Background

Application introduction
our Java Web application service_ A is dynamic, the page is dynamic, the fields of the entity class are dynamic, the functions of an entity class and the services to be accessed are dynamic. You need to read the XML configuration file at startup to determine what the application looks like and what capabilities it has. The technology stack is SSM. In order to facilitate the natural loading of XML in @ postcut, That is, these XML configuration files are loaded after bean creation.

Requirements and changes
in the new version of the technology stack, we need to switch to spring boot, with some functional changes. Parsing these model configuration files actually depends on a table tb in the database_ XXX, the new version requires to obtain these data by calling service_ B service interface.

Introduction to service invocation
before calling other services remotely, you need to call addressing service first_ X address to obtain the protocol, IP, port and domain information of the target service, and then get the same address as the domain of its own service, and then get a callable instance of the target service according to the specified load balancing algorithm to call. The sensitive interface needs DH handshake and data encryption and decryption.


Problem orientation

I just changed a service method from database to interface, and the error was DH handshake failure. There was no change, which means that there must be something wrong with the interface call. Debugging found that the DH error occurred in the service addressing report, that is, the error occurred before entering the code I wrote, and the service addressing code was provided by the internal framework, Other people are also using the frame. Why didn’t other people respond?

Make a breakpoint in the addressing part of the framework code of idea decompilation, and debug step by step to find that the addressing service is being called_ The IP port of the target host can’t be found in X, but the framework code takes it directly from the cache. If it doesn’t, NPE will be thrown, and it will be thrown as a DH error by the upper layer. It is reasonable to say that there should be IP port information of addressing service in cache. Debug check shows that the cache is empty, size = 0, indicating that it has not been put in. Ctrl Alt F7 looks for a wave to see where the key pair will be put into the cache. It is found that the framework injects a bean: serviceinfolistener, which is executed after listening to the applicationcontextinitializedevent.

At this point, students who have read the spring source code or know what spring did when it started will immediately know what the problem is, because XML parsing is too early, and the dependent service addressing is not initialized at this time, so it cannot be called.


solve

Temporary scheme:
the parsing of XML will be delayed until the listener of the framework is finished.

The following scheme:
discuss with the framework group, the framework will rely on the addressing service_ The configuration time of X’s secret key pair is advanced to the after properties set of initializing bean, that is, the application developed with the framework is allowed to be called remotely at startup.

With root cause solution

Phenomenon: 1. There is no exception when the project starts, when the page is loaded into the spring:message In the background, the null pointer is abnormal, and the console will display the prompt with root cause;

2. Note out spring:message After related tags, there is no exception, but where the specific content should be displayed, the code value in the tag is displayed;

3. The same project can be used on other people’s computers, but not on my computer;

4. Available on eclipse, not on MyEclipse;

Reason: there is a space in the Tomcat installation path;

Solution: put the Tomcat of the deployment project in a path without spaces, such as the root directory.

The above are the phenomena and solutions I encountered. If there are any other phenomena and solutions, please add.