[JAVA] Une histoire qui m'a fait regretter quand une "NotReadablePropertyException" s'est produite pendant le développement de l'application Spring Boot.

Comme le titre l'indique, je suis resté coincé dans une erreur et il semblait que je regardais le code plusieurs fois. J'ai réussi à le résoudre par essais et erreurs, mais je n'ai pas pu m'en empêcher, mais je pensais que ça pourrait être quelqu'un d'autre, alors je vais le laisser comme un mémorandum.

contenu de l'erreur

console



2019-12-27 09:13:27.304 ERROR 21044 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/mainPage.html]")] with root cause

org.springframework.beans.NotReadablePropertyException: Invalid property 'foodsName' of bean class [com.PFCbalancer.model.FormFoodsData]: Bean property 'foodsName' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
	at org.springframework.beans.AbstractNestablePropertyAccessor.getPropertyValue(AbstractNestablePropertyAccessor.java:622) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.beans.AbstractNestablePropertyAccessor.getPropertyValue(AbstractNestablePropertyAccessor.java:612) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.validation.AbstractPropertyBindingResult.getActualFieldValue(AbstractPropertyBindingResult.java:104) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.validation.AbstractBindingResult.getFieldValue(AbstractBindingResult.java:228) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:129) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.web.servlet.support.RequestContext.getBindStatus(RequestContext.java:903) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.thymeleaf.spring5.context.webmvc.SpringWebMvcThymeleafRequestContext.getBindStatus(SpringWebMvcThymeleafRequestContext.java:227) ~[thymeleaf-spring5-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.spring5.util.FieldUtils.getBindStatusFromParsedExpression(FieldUtils.java:306) ~[thymeleaf-spring5-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.spring5.util.FieldUtils.getBindStatus(FieldUtils.java:253) ~[thymeleaf-spring5-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.spring5.util.FieldUtils.getBindStatus(FieldUtils.java:227) ~[thymeleaf-spring5-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.spring5.processor.AbstractSpringFieldTagProcessor.doProcess(AbstractSpringFieldTagProcessor.java:174) ~[thymeleaf-spring5-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.processor.element.AbstractAttributeTagProcessor.doProcess(AbstractAttributeTagProcessor.java:74) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.processor.element.AbstractElementTagProcessor.process(AbstractElementTagProcessor.java:95) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.util.ProcessorConfigurationUtils$ElementTagProcessorWrapper.process(ProcessorConfigurationUtils.java:633) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.engine.ProcessorTemplateHandler.handleStandaloneElement(ProcessorTemplateHandler.java:918) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.engine.TemplateHandlerAdapterMarkupHandler.handleStandaloneElementEnd(TemplateHandlerAdapterMarkupHandler.java:260) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.templateparser.markup.InlinedOutputExpressionMarkupHandler$InlineMarkupAdapterPreProcessorHandler.handleStandaloneElementEnd(InlinedOutputExpressionMarkupHandler.java:256) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.standard.inline.OutputExpressionInlinePreProcessorHandler.handleStandaloneElementEnd(OutputExpressionInlinePreProcessorHandler.java:169) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.templateparser.markup.InlinedOutputExpressionMarkupHandler.handleStandaloneElementEnd(InlinedOutputExpressionMarkupHandler.java:104) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.attoparser.HtmlVoidElement.handleOpenElementEnd(HtmlVoidElement.java:92) ~[attoparser-2.0.5.RELEASE.jar:2.0.5.RELEASE]
	at org.attoparser.HtmlMarkupHandler.handleOpenElementEnd(HtmlMarkupHandler.java:297) ~[attoparser-2.0.5.RELEASE.jar:2.0.5.RELEASE]
	at org.attoparser.MarkupEventProcessorHandler.handleOpenElementEnd(MarkupEventProcessorHandler.java:402) ~[attoparser-2.0.5.RELEASE.jar:2.0.5.RELEASE]
	at org.attoparser.ParsingElementMarkupUtil.parseOpenElement(ParsingElementMarkupUtil.java:159) ~[attoparser-2.0.5.RELEASE.jar:2.0.5.RELEASE]
	at org.attoparser.MarkupParser.parseBuffer(MarkupParser.java:710) ~[attoparser-2.0.5.RELEASE.jar:2.0.5.RELEASE]
	at org.attoparser.MarkupParser.parseDocument(MarkupParser.java:301) ~[attoparser-2.0.5.RELEASE.jar:2.0.5.RELEASE]
	at org.attoparser.MarkupParser.parse(MarkupParser.java:257) ~[attoparser-2.0.5.RELEASE.jar:2.0.5.RELEASE]
	at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:230) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parseStandalone(AbstractMarkupTemplateParser.java:100) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.engine.TemplateManager.parseAndProcess(TemplateManager.java:666) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1098) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1072) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.spring5.view.ThymeleafView.renderFragment(ThymeleafView.java:362) ~[thymeleaf-spring5-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.thymeleaf.spring5.view.ThymeleafView.render(ThymeleafView.java:189) ~[thymeleaf-spring5-3.0.11.RELEASE.jar:3.0.11.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1373) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1118) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1057) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:634) ~[tomcat-embed-core-9.0.29.jar:9.0.29]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) ~[tomcat-embed-core-9.0.29.jar:9.0.29]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.29.jar:9.0.29]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.29.jar:9.0.29]
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.29.jar:9.0.29]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.29.jar:9.0.29]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.29.jar:9.0.29]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.29.jar:9.0.29]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.29.jar:9.0.29]
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.29.jar:9.0.29]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.29.jar:9.0.29]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.29.jar:9.0.29]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.29.jar:9.0.29]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.29.jar:9.0.29]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-9.0.29.jar:9.0.29]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:526) [tomcat-embed-core-9.0.29.jar:9.0.29]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) [tomcat-embed-core-9.0.29.jar:9.0.29]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.29.jar:9.0.29]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) [tomcat-embed-core-9.0.29.jar:9.0.29]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) [tomcat-embed-core-9.0.29.jar:9.0.29]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:367) [tomcat-embed-core-9.0.29.jar:9.0.29]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.29.jar:9.0.29]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860) [tomcat-embed-core-9.0.29.jar:9.0.29]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1591) [tomcat-embed-core-9.0.29.jar:9.0.29]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.29.jar:9.0.29]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_162]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_162]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.29.jar:9.0.29]
	at java.lang.Thread.run(Thread.java:748) [na:1.8.0_162]


Toutes les déclarations d'erreur ci-dessus. L'erreur principale dans ceci est ** 2e ligne **.

Does the return type of the getter match the parameter type of the setter?

En passant, une fois traduit, il dit: "La valeur de retour du getter ne correspond pas au type du setter."

Maintenant que je comprends, je me demande si je vais jeter un œil au code.

Code correspondant

view(Extrait)



<form method="post" th:action="@{/main/calcNowPFC}" th:object="${formFoodsData}">
	<div class="bottomForm__inputArea">
		<div>
			<label class="bottomForm__inputArea--label">Nom du produit:</label>
			<input class="bottomForm__inputArea--textbox" type="text" th:field="*{foodsName}">
			<label class="bottomForm__inputArea--label">P:</label>
			<input class="bottomForm__inputArea--numberbox" type="number" th:field="*{foodsProtein}">
			<label class="bottomForm__inputArea--label">F:</label>
			<input class="bottomForm__inputArea--numberbox" type="number" th:field="*{foodsFat}">
			<label class="bottomForm__inputArea--label">C:</label>
			<input class="bottomForm__inputArea--numberbox" type="number" th:field="*{foodsCarb}">
		</div>
		<div class="bottomForm__inputArea--btn">
			<button type="submit" class="bottomForm__inputArea--btnSubmit">add</button>
		</div>
	</div>
</form>


Cette fois ** j'ai eu une erreur dès que j'ai mis ce qui précède. ** ** J'ai également vérifié les contrôleurs suivants tels que la méthode, l'action et la méthode de spécification de liaison (th: object, th: field) du formulaire.

controller(Extrait)



@PostMapping("/main/calcNowPFC")
	public String postMainNowPFC(@ModelAttribute FormBodyData formBodyData, FormFoodsData formFoodsData, BindingResult bindingResult, Model model) {

	foodsList.add(formFoodsData);
	model.addAttribute("foodsList",foodsList);

	model.addAttribute("label",label);
    model.addAttribute("protein",protein);
    model.addAttribute("fat",fat);
    model.addAttribute("carb",carb);
    model.addAttribute("kal",kal);

    model.addAttribute("foodsProtein",foodsProtein);
    model.addAttribute("foodsFat",foodsFat);
    model.addAttribute("foodsCarb",foodsCarb);

		return "mainPage";
}

Ceci est la description du côté contrôleur

Après l'annotation @ModelAttribute, ** FormFoodsData formFoodsData spécifie la classe de liaison ** et il est estimé que le modèle Model a ** Attribute comme argument. ** **

BindingResult Vérifiez si vous pouvez recevoir le résultat de ** bind avec bindingResult. ** **

À ce stade, le côté contrôleur semblait aller bien.

model(Pour la reliure)



package com.PFCbalancer.model;

import lombok.Data;

@Data
public class FormFoodsData {
	private String foodsName;
	private int foodsProtein;
	private int foodsFat;
	private int foodsCarb;
}

C'est un plug-in pratique qui génère automatiquement un getter et un setter appelés lombok dans model, et le getter et le setter en question ne sont pas décrits.

Pour le moment, vérifiez si le nom de classe spécifié pour th: objet du côté vue est correct. Il s'agit de th: object = "$ {formFoodsData}" et il semble que la ** première majuscule du nom de la variable soit automatiquement convertie **, donc ** vérifiez la correspondance avec le nom de la classe **, donc il n'y a pas de problème.

Vérifiez également th: field = "* {foodsName}" et 3 autres champs. Ce n'est pas un problème car le nom d'argument du modèle est ** exactement correspondant. ** **

À la suite de la lecture du code ...

Jugé qu'il n'y a pas de problème en termes de code. Alors quoi? Qu'est-ce que cela signifie que "les types getter et setter ne correspondent pas" en premier lieu? lombok ...!

Pendant que j'enquêtais, j'ai pensé que j'aimerais réinsérer Lombok et mettre à jour le projet. プロジェクト再起動.png

Résultat ... Lancement de l'application: sob :: sob :: sob:

Résumé

Cette fois, il n'y avait rien de mal avec le code. Mais j'ai lavé le code et l'ai vérifié ** Il a été écrasé pendant une demi-journée. **: déçu_relieved: En conséquence, le code a pu échapper à la difficulté en ** réinstallant le plug-in et en mettant à jour le projet ** sans aucun problème. : détendu: Cependant, j'ai personnellement réalisé que c'était un développement très inquiétant, ou qu'un tel développement pouvait se produire tant que j'étais ingénieur. ** **

Ce que je veux transmettre dans ce cas, et ce que j'ai en tête, n'est pas lié par les choses en face de moi. ** Si vous observez les choses dans une perspective plus large, ces solutions seront plus rapides. Qu'il sera? J'ai pensé ** </ font>. Cela fait longtemps, mais j'aimerais en faire le dernier mot.

: sunny: Bonne vie d'ingénieur! : ensoleillé:

Recommended Posts

Une histoire qui m'a fait regretter quand une "NotReadablePropertyException" s'est produite pendant le développement de l'application Spring Boot.
Une histoire remplie des bases de Spring Boot (résolu)
L'histoire de la montée de la série Spring Boot 1.5 à la série 2.1
Lors de l'introduction de JOOQ dans Spring Boot, une histoire qui a été traitée parce qu'une erreur s'est produite autour de Liquidbase
[Spring Boot] L'histoire selon laquelle le bean de la classe avec l'annotation ConfigurationProperties n'a pas été trouvé
L'histoire de la montée de Spring Boot de la série 1.5 à la série 2.1 part2
Obtenez une instance proxy du composant lui-même dans Spring Boot
Un mémo qui conteneurise l'application de chat simple de Node.js + socket.io
Une histoire qui a eu du mal avec l'introduction de Web Apple Pay
Développement d'applications Spring Boot dans Eclipse
Mémorandum lorsque Spring Boot 1.5.10 → Spring Boot 2.0.0
Un mémo qui a touché Spring Boot
Cas où les utilisateurs sont déconnectés lors de la modification d'une application (rails)
Créez un projet de développement d'application Spring Boot avec la commande cURL + tar
Une histoire sur un projet Spring Boot écrit en Java qui prend en charge Kotlin
L'histoire de la rencontre avec l'annotation personnalisée Spring
L'histoire de la transition de Spring Boot 1.5 à 2.1
Démarrez le développement d'applications Web avec Spring Boot
L'histoire de la création d'une application Android capable d'ajuster la fréquence d'échantillonnage du capteur d'accélération
Connectez-vous aux applications Web Spring Boot sur la plate-forme Microsoft ID
Obtenez le chemin défini dans la classe Controller de Spring Boot sous forme de liste
Une histoire confirmant l'implémentation de la bibliothèque Java SendGrid lorsque la livraison du courrier échoue
Paramètres du gestionnaire de ressources lors de la livraison du SPA avec la fonction de ressource statique de Spring Boot
J'ai essayé de cloner une application Web pleine de bugs avec Spring Boot
Comment définir des variables d'environnement dans le fichier de propriétés de l'application Spring Boot
Signaler un exemple de dégradation des performances survenue lorsque l'argument Comparator of Arrays.sort a été donné sous forme d'expression lambda
[Incontournable pour les ingénieurs débutants] Une histoire que le monde s'est étendue lorsque j'ai exploité un service Web que j'ai créé moi-même
Une histoire que les personnes qui ont fait iOS solidement peuvent être accro à la mise en œuvre de Listener lors du passage à Android