spring-framework icon indicating copy to clipboard operation
spring-framework copied to clipboard

NPE when RestTemplate got HttpHeaders with null "value"

Open bdossantos-incomm opened this issue 1 day ago • 0 comments

I'm migrating my Spring/Springboot application and found a strange behavior:

This code worked on SpringBoot 3.2.5

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("rid", SOME_VALUE_THAT_CAN_BE_NULL));
HttpEntity<Object> entity = new HttpEntity<>(headers);
ResponseEntity<T> response = restTemplate.exchange(host + apiUrl, HttpMethod.GET, entity, clazz);
return response.getBody();

Actual Version: SpringBoot 3.5.8

it raises a NPE. See the stackstrace:

java.lang.NullPointerException: value
	at java.base/java.util.Objects.requireNonNull(Objects.java:246)
	at java.net.http/jdk.internal.net.http.HttpRequestBuilderImpl.checkNameAndValue(HttpRequestBuilderImpl.java:108)
	at java.net.http/jdk.internal.net.http.HttpRequestBuilderImpl.header(HttpRequestBuilderImpl.java:129)
	at java.net.http/jdk.internal.net.http.HttpRequestBuilderImpl.header(HttpRequestBuilderImpl.java:45)
	at org.springframework.http.client.JdkClientHttpRequest.lambda$buildRequest$0(JdkClientHttpRequest.java:158)
	at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:987)
	at org.springframework.util.LinkedCaseInsensitiveMap.forEach(LinkedCaseInsensitiveMap.java:292)
	at org.springframework.util.MultiValueMapAdapter.forEach(MultiValueMapAdapter.java:179)
	at org.springframework.http.HttpHeaders.forEach(HttpHeaders.java:1904)
	at org.springframework.http.client.JdkClientHttpRequest.buildRequest(JdkClientHttpRequest.java:155)
	at org.springframework.http.client.JdkClientHttpRequest.executeInternal(JdkClientHttpRequest.java:103)
	at org.springframework.http.client.AbstractStreamingClientHttpRequest.executeInternal(AbstractStreamingClientHttpRequest.java:88)
	at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:81)
	at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:900)
	at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:801)
	at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:683)

If I put a simple IF around headers.add("rid", SOME_VALUE_THAT_CAN_BE_NULL)); it works.

I couldn't find a doc about this.

What causes the use of jdk.internal.net.http.HttpRequestBuilderImpl.header ? Looks like older version uses SimpleClientHttpRequest and addHeaders method has this line 115 String actualHeaderValue = headerValue != null ? headerValue : "";

Can we add some docs about this? I can write, just need to understand this new behavior first.

Thanks!

bdossantos-incomm avatar Dec 10 '25 21:12 bdossantos-incomm