diff --git a/smoke-test/spring-boot-smoke-test-web-thymeleaf/src/main/java/smoketest/web/thymeleaf/InMemoryMessageRepository.java b/smoke-test/spring-boot-smoke-test-web-thymeleaf/src/main/java/smoketest/web/thymeleaf/InMemoryMessageRepository.java index 1e314b2b41b..2a6964978eb 100644 --- a/smoke-test/spring-boot-smoke-test-web-thymeleaf/src/main/java/smoketest/web/thymeleaf/InMemoryMessageRepository.java +++ b/smoke-test/spring-boot-smoke-test-web-thymeleaf/src/main/java/smoketest/web/thymeleaf/InMemoryMessageRepository.java @@ -20,6 +20,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicLong; +import org.jspecify.annotations.Nullable; + public class InMemoryMessageRepository implements MessageRepository { private static final AtomicLong counter = new AtomicLong(); @@ -43,7 +45,7 @@ public class InMemoryMessageRepository implements MessageRepository { } @Override - public Message findMessage(Long id) { + public @Nullable Message findMessage(Long id) { return this.messages.get(id); } diff --git a/smoke-test/spring-boot-smoke-test-web-thymeleaf/src/main/java/smoketest/web/thymeleaf/Message.java b/smoke-test/spring-boot-smoke-test-web-thymeleaf/src/main/java/smoketest/web/thymeleaf/Message.java index 90fb6ca5f8a..6eaa0f71b9d 100644 --- a/smoke-test/spring-boot-smoke-test-web-thymeleaf/src/main/java/smoketest/web/thymeleaf/Message.java +++ b/smoke-test/spring-boot-smoke-test-web-thymeleaf/src/main/java/smoketest/web/thymeleaf/Message.java @@ -18,25 +18,26 @@ package smoketest.web.thymeleaf; import java.util.Calendar; +import jakarta.annotation.Nullable; import jakarta.validation.constraints.NotEmpty; public class Message { - private Long id; + private @Nullable Long id; @NotEmpty(message = "Text is required.") - private String text; + private @Nullable String text; @NotEmpty(message = "Summary is required.") - private String summary; + private @Nullable String summary; private Calendar created = Calendar.getInstance(); - public Long getId() { + public @Nullable Long getId() { return this.id; } - public void setId(Long id) { + public void setId(@Nullable Long id) { this.id = id; } @@ -48,19 +49,19 @@ public class Message { this.created = created; } - public String getText() { + public @Nullable String getText() { return this.text; } - public void setText(String text) { + public void setText(@Nullable String text) { this.text = text; } - public String getSummary() { + public @Nullable String getSummary() { return this.summary; } - public void setSummary(String summary) { + public void setSummary(@Nullable String summary) { this.summary = summary; } diff --git a/smoke-test/spring-boot-smoke-test-web-thymeleaf/src/main/java/smoketest/web/thymeleaf/MessageRepository.java b/smoke-test/spring-boot-smoke-test-web-thymeleaf/src/main/java/smoketest/web/thymeleaf/MessageRepository.java index dfb18a98688..2e29adef139 100644 --- a/smoke-test/spring-boot-smoke-test-web-thymeleaf/src/main/java/smoketest/web/thymeleaf/MessageRepository.java +++ b/smoke-test/spring-boot-smoke-test-web-thymeleaf/src/main/java/smoketest/web/thymeleaf/MessageRepository.java @@ -16,13 +16,15 @@ package smoketest.web.thymeleaf; +import org.jspecify.annotations.Nullable; + public interface MessageRepository { Iterable findAll(); Message save(Message message); - Message findMessage(Long id); + @Nullable Message findMessage(Long id); void deleteMessage(Long id); diff --git a/smoke-test/spring-boot-smoke-test-web-thymeleaf/src/main/java/smoketest/web/thymeleaf/SampleWebUiApplication.java b/smoke-test/spring-boot-smoke-test-web-thymeleaf/src/main/java/smoketest/web/thymeleaf/SampleWebUiApplication.java index d6cc55ec70e..d26183ca997 100644 --- a/smoke-test/spring-boot-smoke-test-web-thymeleaf/src/main/java/smoketest/web/thymeleaf/SampleWebUiApplication.java +++ b/smoke-test/spring-boot-smoke-test-web-thymeleaf/src/main/java/smoketest/web/thymeleaf/SampleWebUiApplication.java @@ -16,6 +16,8 @@ package smoketest.web.thymeleaf; +import org.jspecify.annotations.Nullable; + import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; @@ -33,7 +35,7 @@ public class SampleWebUiApplication { public Converter messageConverter() { return new Converter<>() { @Override - public Message convert(String id) { + public @Nullable Message convert(String id) { return messageRepository().findMessage(Long.valueOf(id)); } }; diff --git a/smoke-test/spring-boot-smoke-test-web-thymeleaf/src/main/java/smoketest/web/thymeleaf/mvc/MessageController.java b/smoke-test/spring-boot-smoke-test-web-thymeleaf/src/main/java/smoketest/web/thymeleaf/mvc/MessageController.java index 215abe4ac73..0a0d0949bde 100644 --- a/smoke-test/spring-boot-smoke-test-web-thymeleaf/src/main/java/smoketest/web/thymeleaf/mvc/MessageController.java +++ b/smoke-test/spring-boot-smoke-test-web-thymeleaf/src/main/java/smoketest/web/thymeleaf/mvc/MessageController.java @@ -21,6 +21,7 @@ import smoketest.web.thymeleaf.Message; import smoketest.web.thymeleaf.MessageRepository; import org.springframework.stereotype.Controller; +import org.springframework.util.Assert; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; @@ -63,7 +64,9 @@ public class MessageController { } message = this.messageRepository.save(message); redirect.addFlashAttribute("globalMessage", "view.success"); - return new ModelAndView("redirect:/{message.id}", "message.id", message.getId()); + Long id = message.getId(); + Assert.state(id != null, "'id' must not be null"); + return new ModelAndView("redirect:/{message.id}", "message.id", id); } @RequestMapping("foo") diff --git a/smoke-test/spring-boot-smoke-test-web-thymeleaf/src/main/java/smoketest/web/thymeleaf/mvc/package-info.java b/smoke-test/spring-boot-smoke-test-web-thymeleaf/src/main/java/smoketest/web/thymeleaf/mvc/package-info.java new file mode 100644 index 00000000000..4875f43d377 --- /dev/null +++ b/smoke-test/spring-boot-smoke-test-web-thymeleaf/src/main/java/smoketest/web/thymeleaf/mvc/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@NullMarked +package smoketest.web.thymeleaf.mvc; + +import org.jspecify.annotations.NullMarked; diff --git a/smoke-test/spring-boot-smoke-test-web-thymeleaf/src/main/java/smoketest/web/thymeleaf/package-info.java b/smoke-test/spring-boot-smoke-test-web-thymeleaf/src/main/java/smoketest/web/thymeleaf/package-info.java new file mode 100644 index 00000000000..f4a3ac0d497 --- /dev/null +++ b/smoke-test/spring-boot-smoke-test-web-thymeleaf/src/main/java/smoketest/web/thymeleaf/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@NullMarked +package smoketest.web.thymeleaf; + +import org.jspecify.annotations.NullMarked;