Skip to content

Commit bd5befa

Browse files
fix: NPE when web push subscription is expired (#24310) (CP: 25.0) (#24317)
This PR cherry-picks changes from the original PR #24310 to branch 25.0. --- #### Original PR description > When the push service reports a subscription as expired, `WebPush.sendNotification` threw `NullPointerException` instead of the intended `WebPushException`. > > Remove a leftover reference to an unassigned `HttpResponse` local variable that was no longer populated after the migration to `com.interaso.webpush`. > > Fixes #24306 > --------- Co-authored-by: Marco Collovati <marco@vaadin.com>
1 parent 4492d01 commit bd5befa

3 files changed

Lines changed: 84 additions & 5 deletions

File tree

flow-webpush/pom.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
<name>Flow WebPush</name>
1313
<description>${project.name}</description>
1414

15-
<properties/>
15+
<properties>
16+
<testListener/>
17+
</properties>
1618

1719
<dependencies>
1820
<!-- Project dependencies -->

flow-webpush/src/main/java/com/vaadin/flow/server/webpush/WebPush.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import java.io.IOException;
1919
import java.io.InputStream;
2020
import java.io.Serializable;
21-
import java.net.http.HttpResponse;
2221
import java.security.spec.InvalidKeySpecException;
2322

2423
import com.interaso.webpush.VapidKeys;
@@ -108,8 +107,7 @@ public WebPush(String publicKey, String privateKey, String subject) {
108107
*/
109108
public void sendNotification(WebPushSubscription subscription,
110109
WebPushMessage message) throws WebPushException {
111-
SubscriptionState status = null;
112-
HttpResponse<String> response = null;
110+
SubscriptionState status;
113111
try {
114112
status = pushService.send(message.toJson(), subscription.endpoint(),
115113
subscription.keys().p256dh(), subscription.keys().auth(),
@@ -122,7 +120,6 @@ public void sendNotification(WebPushSubscription subscription,
122120
if (!SubscriptionState.ACTIVE.equals(status)) {
123121
getLogger().error(
124122
"Failed to send web push notification, received status code: 404 or 410");
125-
getLogger().error(String.join("\n", response.body()));
126123
throw new WebPushException(
127124
"Sending of web push notification failed with status code 404 or 410");
128125
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* Copyright 2000-2026 Vaadin Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
package com.vaadin.flow.server.webpush;
17+
18+
import java.lang.reflect.Field;
19+
20+
import com.interaso.webpush.WebPush.SubscriptionState;
21+
import com.interaso.webpush.WebPushService;
22+
import org.junit.Before;
23+
import org.junit.Test;
24+
25+
import static org.junit.Assert.assertEquals;
26+
import static org.junit.Assert.assertThrows;
27+
import static org.mockito.ArgumentMatchers.any;
28+
import static org.mockito.Mockito.mock;
29+
import static org.mockito.Mockito.when;
30+
31+
public class WebPushTest {
32+
33+
private static final String PUBLIC_KEY = "BPXZkCj3rxN6a1v21aCyMQHmTaAn1QZyWRDeBfwQ4qperQNszSD9JhnZv9b45vHLQLxnK3zsCvCl1r8EDpPDjoM";
34+
private static final String PRIVATE_KEY = "W-J0f4QwsjrEwDnJJTky5waIX9xNaM87-Dfd42_SEDM";
35+
36+
private WebPush webPush;
37+
private WebPushService pushServiceMock;
38+
39+
@Before
40+
public void setUp() throws Exception {
41+
webPush = new WebPush(PUBLIC_KEY, PRIVATE_KEY,
42+
"mailto:test@example.com");
43+
pushServiceMock = mock(WebPushService.class);
44+
Field field = WebPush.class.getDeclaredField("pushService");
45+
field.setAccessible(true);
46+
field.set(webPush, pushServiceMock);
47+
}
48+
49+
@Test
50+
public void sendNotification_subscriptionExpired_throwsWebPushException() {
51+
when(pushServiceMock.send(any(String.class), any(String.class),
52+
any(String.class), any(String.class), any(), any(), any()))
53+
.thenReturn(SubscriptionState.EXPIRED);
54+
55+
WebPushSubscription subscription = new WebPushSubscription(
56+
"https://push.example/endpoint",
57+
new WebPushKeys("p256dhKey", "authKey"));
58+
WebPushMessage message = new WebPushMessage("title", "body");
59+
60+
WebPushException ex = assertThrows(WebPushException.class,
61+
() -> webPush.sendNotification(subscription, message));
62+
assertEquals(
63+
"Sending of web push notification failed with status code 404 or 410",
64+
ex.getMessage());
65+
}
66+
67+
@Test
68+
public void sendNotification_subscriptionActive_doesNotThrow() {
69+
when(pushServiceMock.send(any(String.class), any(String.class),
70+
any(String.class), any(String.class), any(), any(), any()))
71+
.thenReturn(SubscriptionState.ACTIVE);
72+
73+
WebPushSubscription subscription = new WebPushSubscription(
74+
"https://push.example/endpoint",
75+
new WebPushKeys("p256dhKey", "authKey"));
76+
WebPushMessage message = new WebPushMessage("title", "body");
77+
78+
webPush.sendNotification(subscription, message);
79+
}
80+
}

0 commit comments

Comments
 (0)