If a MethodReplacer replaces a method with a primitive return type, and if the replacer returns null, CGLIB silently converts the null to a zero-value primitive (false or 0), instead of throwing an exception (see CodeEmitter::zero_or_null in CGLIB).

This does not align with the rest of the Spring Framework. For example, the AOP module checks for a null in advices for methods with primitive return types before it reaches the CGLIB proxy (CglibAopProxy::processReturnType) and throws an AopInvocationException. Similarly, the AOP module maintains functional parity between the JDK Proxy and CGLIB proxies by wrapping an undeclared checked exception in an UndeclaredThrowableException. Moreover, silently converting a null to a non-null value can lead to hard-to-find bugs.

MvcUriComponentsBuilder.ControllerMethodInvocationInterceptor also has this quirk, but the return values of the proxies it returns aren't meant to be used, so I didn't touch that one.

This PR follows the pattern used by CglibAopProxy and throws an exception if null is returned in the advice for a method with a primitive return type.

Comment From: pivotal-cla

@LeMikaelF Please sign the Contributor License Agreement!

Click here to manually synchronize the status of this Pull Request.

See the FAQ for frequently asked questions.

Comment From: pivotal-cla

@LeMikaelF Thank you for signing the Contributor License Agreement!

Comment From: sbrannen

Hi @LeMikaelF,

Congratulations on submitting your first PR for the Spring Framework! 👍

This has been merged into main in 3e48031601a59d648a6fbd2b376f2e7c318230a1 and revised in 04e69bdb260d9e74f392e9cbf01ee87f6feb798b.

Thanks