Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] mvc-annotation-commons NoSuchMethodError ServerHttpRequest.getMethodValue() #11652

Closed
3 tasks done
CzyerChen opened this issue Dec 13, 2023 · 6 comments · Fixed by apache/skywalking-java#658
Closed
3 tasks done
Assignees
Labels
bug Something isn't working and you are sure it's a bug! java Java agent related plugin Plugin for agent or collector. Be used to extend the capabilities of default implementor.
Milestone

Comments

@CzyerChen
Copy link
Contributor

Search before asking

  • I had searched in the issues and found no similar issues.

Apache SkyWalking Component

Java Agent (apache/skywalking-java)

What happened

Run a project with

  • SpringBoot 3.2.0(released at 2023.11.03)
  • apm-springmvc-annotation-commons-9.1.0.jar
  • apm-springmvc-annotation-6.x-plugin-9.1.0.jar

can not trace SpringMVC node because of the error from java-agent logs

java.lang.NoSuchMethodError: 'java.lang.String org.springframework.http.server.reactive.ServerHttpRequest.getMethodValue()'
	at org.apache.skywalking.apm.plugin.spring.mvc.commons.interceptor.AbstractMethodInterceptor.beforeMethod(AbstractMethodInterceptor.java:171)
	at org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstMethodsInter.intercept(InstMethodsInter.java:76)

but works fine with SpringBoot previous version, like 3.1.0.

With the error and the source code, see that:

public interface HttpRequest extends HttpMessage {
......
	@Deprecated(since = "6.0", forRemoval = true)
	default String getMethodValue() {
		return getMethod().name();
	}
......
}

the method getMethodValue removed from SpringBoot 3.2.0

What you expected to happen

SpringMVC node can be traced with SpringBoot 3.1.0, and can not traced with SpringBoot 3.2.0.
We should fix the bug.

How to reproduce

Run a normal SpingBoot project with

  • SpringBoot 3.2.0(released at 2023.11.03)
  • apm-springmvc-annotation-commons-9.1.0.jar
  • apm-springmvc-annotation-6.x-plugin-9.1.0.jar

Anything else

No response

Are you willing to submit a pull request to fix on your own?

  • Yes I am willing to submit a pull request on my own!

Code of Conduct

@CzyerChen CzyerChen added the bug Something isn't working and you are sure it's a bug! label Dec 13, 2023
@wu-sheng
Copy link
Member

Are you proposing a new interceptor for newer version?

@wu-sheng wu-sheng added plugin Plugin for agent or collector. Be used to extend the capabilities of default implementor. java Java agent related labels Dec 13, 2023
@CzyerChen
Copy link
Contributor Author

Are you proposing a new interceptor for newer version?

add the witnessmethod and add a new interceptor.

@wu-sheng
Copy link
Member

That works. And please make sure you add the new unsupported version into the test matrix.

@CzyerChen
Copy link
Contributor Author

That works. And please make sure you add the new unsupported version into the test matrix.

Got it.

@CzyerChen
Copy link
Contributor Author

I have checked gettMethod && getMethodValue method called by org.springframework.http.server.reactive.ServerHttpRequest in all spring-web versions(3.0.x/3.1.x/3.2.x/4.0.x/4.1.x/4.2.x/4.3.x/5.0.x/5.1.x/5.2.x/5.3.x/6.0.x/6.1.x),getMethod exists all the time, but getMethodValue only in version 5.x & 6.0.x
Whether we can just change the method from getMethodValue to getMehtod without a new interceptor?

3.0.x

/**
 * Represents a server-side HTTP request.
 *
 * @author Arjen Poutsma
 * @since 3.0
 */
public interface ServerHttpRequest extends HttpInputMessage {

	/**
	 * Return the HTTP method of the request.
	 * @return the HTTP method as an HttpMethod enum value
	 */
	HttpMethod getMethod();

	/**
	 * Return the URI of the request.
	 * @return the URI of the request
	 */
	URI getURI();
}

3.1.x/3.2.x

public interface ServerHttpRequest extends HttpRequest, HttpInputMessage {

}

/**
 * Represents an HTTP request message, consisting of {@linkplain #getMethod() method}
 * and {@linkplain #getURI() uri}.
 *
 * @author Arjen Poutsma
 * @since 3.1
 */
public interface HttpRequest extends HttpMessage {

	/**
	 * Return the HTTP method of the request.
	 * @return the HTTP method as an HttpMethod enum value
	 */
	HttpMethod getMethod();

	/**
	 * Return the URI of the request.
	 * @return the URI of the request
	 */
	URI getURI();

}

4.0.x/4.1.x/4.2.x/4.3.x

/**
 * Represents a server-side HTTP request.
 *
 * @author Arjen Poutsma
 * @author Rossen Stoyanchev
 * @since 3.0
 */
public interface ServerHttpRequest extends HttpRequest, HttpInputMessage {

	/**
	 * Return a {@link java.security.Principal} instance containing the name of the
	 * authenticated user. If the user has not been authenticated, the method returns
	 * <code>null</code>.
	 */
	Principal getPrincipal();

	/**
	 * Return the address on which the request was received.
	 */
	InetSocketAddress getLocalAddress();

	/**
	 * Return the address of the remote client.
	 */
	InetSocketAddress getRemoteAddress();

	/**
	 * Return a control that allows putting the request in asynchronous mode so the
	 * response remains open until closed explicitly from the current or another thread.
	 */
	ServerHttpAsyncRequestControl getAsyncRequestControl(ServerHttpResponse response);

}

/**
 * Represents an HTTP request message, consisting of {@linkplain #getMethod() method}
 * and {@linkplain #getURI() uri}.
 *
 * @author Arjen Poutsma
 * @since 3.1
 */
public interface HttpRequest extends HttpMessage {

	/**
	 * Return the HTTP method of the request.
	 * @return the HTTP method as an HttpMethod enum value
	 */
	HttpMethod getMethod();

	/**
	 * Return the URI of the request.
	 * @return the URI of the request
	 */
	URI getURI();

}

5.0.x/5.1.x/5.2.x/5.3.x

/**
 * Represents a server-side HTTP request.
 *
 * @author Arjen Poutsma
 * @author Rossen Stoyanchev
 * @since 3.0
 */
public interface ServerHttpRequest extends HttpRequest, HttpInputMessage {

	/**
	 * Return a {@link java.security.Principal} instance containing the name of the
	 * authenticated user.
	 * <p>If the user has not been authenticated, the method returns <code>null</code>.
	 */
	@Nullable
	Principal getPrincipal();

	/**
	 * Return the address on which the request was received.
	 */
	InetSocketAddress getLocalAddress();

	/**
	 * Return the address of the remote client.
	 */
	InetSocketAddress getRemoteAddress();

	/**
	 * Return a control that allows putting the request in asynchronous mode so the
	 * response remains open until closed explicitly from the current or another thread.
	 */
	ServerHttpAsyncRequestControl getAsyncRequestControl(ServerHttpResponse response);

}
/**
 * Represents an HTTP request message, consisting of
 * {@linkplain #getMethod() method} and {@linkplain #getURI() uri}.
 *
 * @author Arjen Poutsma
 * @since 3.1
 */
public interface HttpRequest extends HttpMessage {

	/**
	 * Return the HTTP method of the request.
	 * @return the HTTP method as an HttpMethod enum value, or {@code null}
	 * if not resolvable (e.g. in case of a non-standard HTTP method)
	 * @see #getMethodValue()
	 * @see HttpMethod#resolve(String)
	 */
	@Nullable
	default HttpMethod getMethod() {
		return HttpMethod.resolve(getMethodValue());
	}

	/**
	 * Return the HTTP method of the request as a String value.
	 * @return the HTTP method as a plain String
	 * @since 5.0
	 * @see #getMethod()
	 */
	String getMethodValue();

	/**
	 * Return the URI of the request (including a query string if any,
	 * but only if it is well-formed for a URI representation).
	 * @return the URI of the request (never {@code null})
	 */
	URI getURI();

}

6.0.x

/**
 * Represents a server-side HTTP request.
 *
 * @author Arjen Poutsma
 * @author Rossen Stoyanchev
 * @since 3.0
 */
public interface ServerHttpRequest extends HttpRequest, HttpInputMessage {

	/**
	 * Return a {@link java.security.Principal} instance containing the name of the
	 * authenticated user.
	 * <p>If the user has not been authenticated, the method returns <code>null</code>.
	 */
	@Nullable
	Principal getPrincipal();

	/**
	 * Return the address on which the request was received.
	 */
	InetSocketAddress getLocalAddress();

	/**
	 * Return the address of the remote client.
	 */
	InetSocketAddress getRemoteAddress();

	/**
	 * Return a control that allows putting the request in asynchronous mode so the
	 * response remains open until closed explicitly from the current or another thread.
	 */
	ServerHttpAsyncRequestControl getAsyncRequestControl(ServerHttpResponse response);

}

/**
 * Represents an HTTP request message, consisting of a
 * {@linkplain #getMethod() method} and a {@linkplain #getURI() URI}.
 *
 * @author Arjen Poutsma
 * @since 3.1
 */
public interface HttpRequest extends HttpMessage {

	/**
	 * Return the HTTP method of the request.
	 * @return the HTTP method as an HttpMethod value
	 * @see HttpMethod#valueOf(String)
	 */
	HttpMethod getMethod();

	/**
	 * Return the HTTP method of the request as a String value.
	 * @return the HTTP method as a plain String
	 * @since 5.0
	 * @see #getMethod()
	 * @deprecated as of Spring Framework 6.0 in favor of {@link #getMethod()} and
	 * {@link HttpMethod#name()}
	 */
	@Deprecated(since = "6.0", forRemoval = true)
	default String getMethodValue() {
		return getMethod().name();
	}

	/**
	 * Return the URI of the request (including a query string if any,
	 * but only if it is well-formed for a URI representation).
	 * @return the URI of the request (never {@code null})
	 */
	URI getURI();

} 

6.1.x

/**
 * Represents a server-side HTTP request.
 *
 * @author Arjen Poutsma
 * @author Rossen Stoyanchev
 * @since 3.0
 */
public interface ServerHttpRequest extends HttpRequest, HttpInputMessage {

	/**
	 * Return a {@link java.security.Principal} instance containing the name of the
	 * authenticated user.
	 * <p>If the user has not been authenticated, the method returns <code>null</code>.
	 */
	@Nullable
	Principal getPrincipal();

	/**
	 * Return the address on which the request was received.
	 */
	InetSocketAddress getLocalAddress();

	/**
	 * Return the address of the remote client.
	 */
	InetSocketAddress getRemoteAddress();

	/**
	 * Return a control that allows putting the request in asynchronous mode so the
	 * response remains open until closed explicitly from the current or another thread.
	 */
	ServerHttpAsyncRequestControl getAsyncRequestControl(ServerHttpResponse response);

}

/**
 * Represents an HTTP request message, consisting of a
 * {@linkplain #getMethod() method} and a {@linkplain #getURI() URI}.
 *
 * @author Arjen Poutsma
 * @since 3.1
 */
public interface HttpRequest extends HttpMessage {

	/**
	 * Return the HTTP method of the request.
	 * @return the HTTP method as an HttpMethod value
	 * @see HttpMethod#valueOf(String)
	 */
	HttpMethod getMethod();

	/**
	 * Return the URI of the request (including a query string if any,
	 * but only if it is well-formed for a URI representation).
	 * @return the URI of the request (never {@code null})
	 */
	URI getURI();

}

@wu-sheng
Copy link
Member

In the Spring 6, getMethodValue is deprecated but because Deprecated as of Spring Framework 6.0 in favor of getMethod() and HttpMethod.name().

You could try whether your solution works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working and you are sure it's a bug! java Java agent related plugin Plugin for agent or collector. Be used to extend the capabilities of default implementor.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants