000
I encountered a problem recently and recorded the solution process.
Fault cause
The colleague's application went online and Tomcat could not be started normally. This exception is thrown:
Org. springframework. beans. propertyBatchUpdateException; nested PropertyAccessExceptions (1) are: | PropertyAccessException 1: org. springframework. beans. methodInvocationException: Property 'brokerurl' threw exception; nested exception is java. lang. illegalArgumentException: Invalid broker URI: nio :/// 10.0.0.0: 91616 at org. springframework. beans. abstractPropertyAccessor. setPropertyValues (AbstractPropertyAccessor. java: 121) at org. springframework. beans. abstractPropertyAccessor. setPropertyValues (AbstractPropertyAccessor. java: 75) at org. springframework. beans. factory. support. abstractAutowireCapableBeanFactory. applyPropertyValues (AbstractAutowireCapableBeanFactory. java: 1504) at org. springframework. beans. factory. support. abstractAutowireCapableBeanFactory. populateBean (AbstractAutowireCapableBeanFactory. java: 1216) at org. springframework. beans. factory. support. abstractAutowireCapableBeanFactory. doCreateBean (AbstractAutowireCapableBeanFactory. java: 538) at org. springframework. beans. factory. support. abstractAutowireCapableBeanFactory. createBean (AbstractAutowireCapableBeanFactory. java: 476) at org. springframework. beans. factory. support. abstractBeanFactory $1. getObject (AbstractBeanFactory. java: 302) at org. springframework. beans. factory. support. defaultSingletonBeanRegistry. getSingleton (DefaultSingletonBeanRegistry. java: 229) at org. springframework. beans. factory. support. abstractBeanFactory. doGetBean (AbstractBeanFactory. java: 298) at org. springframework. beans. factory. support. abstractBeanFactory. getBean (AbstractBeanFactory. java: 193)
According to colleagues, the online environment can run normally, and an error occurs in the online environment, which is very strange.
The program has an env. properties configuration file:
Broker. producer = failover: // (nio: // 10.0.0.3: 91615? ConnectionTimeout = 3000, nio: // 10.0.0.4: 91615? ConnectionTimeout = 3000)
Different env. properties are loaded online and offline.
The following configuration is available in the Spring xml configuration file:
<! -- ActiveMQ connection factory --> <amq: connectionFactory id = "jmsConnectionFactory" brokerURL = "$ {broker. producer}"/>
When Spring is running, the value in the $ {} expression is automatically replaced.
First, check the network connectivity:
Run
Telnet 10.0.0.3 91616
You can connect to ActiveMQ and check the Connection on the Web Console. It is found that there is no Connection to this IP address.
Check whether the configuration is normal:
The brokerURI configured online is the following:
Failover: // (nio: // 10.0.0.3: 91616? ConnectionTimeout = 3000, nio: // 10.0.0.4: 91616? ConnectionTimeout = 3000)
Directly change to the simplest one. In vim, yy copies a row and deletes the redundant row. The remaining one is:
Nio: /// 10.0.0.3: 91616
An exception is reported.
Use ssh for port forwarding and perform local testing
Run a simple program locally and use the XShell port to forward the local request to the online machine. The message can be sent normally. So I asked my colleagues to go back and check for other problems in the code.
Put the test program on an online machine for running
However, my colleague did not find the error. Therefore, he typed the simple program into a fat jar package and put it on the online machine to run it. He found that ActiveMQ messages could be sent normally.
The one jar plug-in of maven is used for program packaging. For details, refer:
Http://www.mkyong.com/maven/maven-create-a-fat-jar-file-one-jar-example/
Integrate the test program into the code of a colleague and run it.
Put the test program in the code of the War package of a colleague and put it on an online machine. The test program can send messages normally.
However, the ActiveMQ configured by the colleague still cannot send messages, or the error "Invalid broker URI" is reported.
Add variables, perform repeated tests, and compare configurations
No way, set the environment variable $ {broker. producer} of the colleague to the test code, and find that the test code throws an exception.
So it is confirmed that the variable $ {broker. producer} has a problem.
However, the configuration in the env. properties file looks correct. It is suspected that the configuration file format is incorrect.
Back up the old file and create a new configuration file.
Broker. producer = nio: // 10.0.0.3: 91615
I found that it was normal.
Then we compared the two configuration files and found that there was an additional space on the old configuration file .. A space is added after 91615.
ActiveMQ cannot identify a space after processing configuration values. The exception thrown by Spring does not contain this information.
Search for the keyword "Invalid broker URI", view the ActiveMQ code, and find the original exception.
When debugging starts, the original exception information cannot be found, and there are too many levels of Spring function calls. Therefore, code search is used.
Search for "Invalid broker URI" in the https://searchcode.com and finally find that the original exception information is thrown out by the following code:
URI org. apache. activemq. activeMQConnectionFactory. createURI (String brokerURL) private static URI createURI (String brokerURL) {try {return new URI (brokerURL);} catch (URISyntaxException e) {throw (IllegalArgumentException) new IllegalArgumentException ("Invalid broker URI:" + brokerURL ). initCause (e );}}It is strange that the URISyntaxException is correctly set to cause in the IllegalArgumentException exception, but the following Spring does not print this information ..
Working Principle of Spring printing exceptions
Why can't Spring print all the preceding exception information, but the original exception information? For example, a Spring exception message is as follows:
Caused by: org. springframework. beans. PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
Srping uses Caused by and nested exception is. Such a character concatenates all exceptions. How does this work?
Search "nested exception is" again"
Find the Spring-related code.
All Spring exception classes are inherited from NestedRuntimeException, while NestedRuntimeException overwrites the getMessage () function. In the getMessage () function, all exception information is serialized.
The IllegalArgumentException inherits from the Throwable class. The getMessage () function of the Throwable class simply prints the message and does not output the cause.
Org. springframework. core. nestedRuntimeException/*** Return the detail message, including the message from the nested exception * if there is one. * // @ Overridepublic String getMessage () {return NestedExceptionUtils. buildMessage (super. getMessage (), getCause ();} org. springframework. core. nestedExceptionUtils/*** Build a message for the given base message and root cause. * @ param message the base messa Ge * @ param cause the root cause * @ return the full exception message */public static String buildMessage (String message, Throwable cause) {if (cause! = Null) {StringBuilder sb = new StringBuilder (); if (message! = Null) {sb. append (message ). append (";");} sb. append ("nested exception is "). append (cause); return sb. toString () ;}else {return message ;}}
Other things:
The NestedExceptionUtils class is abstract. This prevents the user from getting an instance, so that the user cannot use an error. This is also a common util class technique.
Public abstract class NestedExceptionUtils {
Summary:
This code search site is better: https://searchcode.com
Many popular websites have data, which is more comprehensive than github.
Later, I searched for "Invalid broker URI" on the Internet, with more than 0.1 million results .. It is estimated that many of them are caused by spaces ..
ActiveMQ developers only need to add a little trim () judgment to process the code, which can reduce the suffering of many people.
Therefore, it is necessary to implement defensive programming. Sometimes it is not really intended for users, but for errors that come from unimagined places.
URI org. apache. activemq. ActiveMQConnectionFactory. createURI (String brokerURL) private static URI createURI (String brokerURL) {try {if (brokerURL! = Null) brokerURL = brokerURL. trim (); return new URI (brokerURL);} catch (URISyntaxException e) {throw (IllegalArgumentException) new IllegalArgumentException ("Invalid broker URI:" + brokerURL ). initCause (e );}}
Process for resolving ActiveMQ's "Invalid broker URI" exception