spring-in-action-5-samples
spring-in-action-5-samples copied to clipboard
chapter 3: NullPointerException when saving Taco design without ingredients
Steps to reproduce:
- go to ch03/tacos-jdbc
-
mvn spring-boot:run
- localhost:8080
- click on the link "Design a taco"
- set taco name: "test-taco-name"
- click on the button: "Submit your taco"
Expected result: An error appears with the text: "You must choose at least 1 ingredient"
Actual result: Whitelabel Error Page Logs:
java.lang.NullPointerException: null at tacos.data.JdbcTacoRepository.save(JdbcTacoRepository.java:31) ~[classes/:na] at tacos.data.JdbcTacoRepository$$FastClassBySpringCGLIB$$59d8a28e.invoke(
) ~[classes/:na] at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-5.0.8.RELEASE.jar:5.0.8.RELEASE] ...
Root cause: Taco.java
...
@Size(min=1, message="You must choose at least 1 ingredient")
private List<Ingredient> ingredients;
...
ingredients
field has @Size
validation. But according to documentation for @Size
validation null is considered valid. If you choose no ingredients then ingredients
field will be null and it is a valid value.
I had got a similar NullPointerException with ingredients. But I think it throws such exception because jdbc.update() in method saveTacoInfo() didn't update the KeyHolder.
private long saveTacoInfo(Taco taco) {
taco.setCreatedAt(new Date());
PreparedStatementCreator psc = new PreparedStatementCreatorFactory(
"insert into Taco (name, createdAt) values (?, ?)",
Types.VARCHAR, Types.TIMESTAMP
).newPreparedStatementCreator(Arrays.asList(taco.getName(), new Timestamp(taco.getCreatedAt().getTime())));
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbc.update(psc, keyHolder);
return keyHolder.getKey().longValue(); //TODO this line of code throws NullPointerException because jdbc update didn't update KeyHolder
}
Try this:
private long saveTacoInfo(Taco taco) { taco.setCreatedAt(new Date()); PreparedStatementCreator psc = new PreparedStatementCreatorFactory( "insert into Taco (name, createdAt) values (?, ?)", Types.VARCHAR, Types.TIMESTAMP ).newPreparedStatementCreator(Arrays.asList(taco.getName(), new Timestamp(taco.getCreatedAt().getTime())));
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbc.update(psc, keyHolder);
*System.out.println(keyHolder.getKey()); //I guess here it will
print null.*
return 1L; //TODO this line of code throws NullPointerException
because jdbc update doesn't generated key }
On Fri, Jan 10, 2020 at 4:50 AM Benjamin L. [email protected] wrote:
I had got a similar NullPointerException with ingredients. But I think it throws such exception because jdbc.update() in method saveTacoInfo() didn't update the generated key.
private long saveTacoInfo(Taco taco) { taco.setCreatedAt(new Date()); PreparedStatementCreator psc = new PreparedStatementCreatorFactory( "insert into Taco (name, createdAt) values (?, ?)", Types.VARCHAR, Types.TIMESTAMP ).newPreparedStatementCreator(Arrays.asList(taco.getName(), new Timestamp(taco.getCreatedAt().getTime())));
KeyHolder keyHolder = new GeneratedKeyHolder(); jdbc.update(psc, keyHolder); return keyHolder.getKey().longValue(); //TODO this line of code throws NullPointerException because jdbc update doesn't generated key
}
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/habuma/spring-in-action-5-samples/issues/40?email_source=notifications&email_token=AEUCCLNNXPRQLDJM2T6P6BTQ5BAF5A5CNFSM4GUA373KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEITJ4QA#issuecomment-572956224, or unsubscribe https://github.com/notifications/unsubscribe-auth/AEUCCLPLS2WELZIZ4F33W4TQ5BAF5ANCNFSM4GUA373A .
@ghbenl Hi,
I met the same issue as you post. I guess it's a bug in Spring. Try to use SimpleJdbcInsert
as we coded in JdbcOrderRepository.java
instead, in my case, it works~
you must set this:
preparedStatementCreatorFactory.setReturnGeneratedKeys(true);
private long saveTacoInfo(Taco taco) {
taco.setCreatedAt(new Date());
PreparedStatementCreatorFactory pscf = new PreparedStatementCreatorFactory(
"Insert into Taco(name, createdAt) values(?,?)", Types.VARCHAR, Types.TIMESTAMP);
pscf.setReturnGeneratedKeys(Boolean.TRUE);
PreparedStatementCreator psc = pscf.newPreparedStatementCreator(
Arrays.asList(taco.getName(), new Timestamp(taco.getCreatedAt().getTime())));
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbc.update(psc, keyHolder);
return keyHolder.getKey().longValue();
}
Steps to reproduce:
- go to ch03/tacos-jdbc
mvn spring-boot:run
- localhost:8080
- click on the link "Design a taco"
- set taco name: "test-taco-name"
- click on the button: "Submit your taco"
Expected result: An error appears with the text: "You must choose at least 1 ingredient"
Actual result: Whitelabel Error Page Logs:
java.lang.NullPointerException: null at tacos.data.JdbcTacoRepository.save(JdbcTacoRepository.java:31) ~[classes/:na] at tacos.data.JdbcTacoRepository$$FastClassBySpringCGLIB$$59d8a28e.invoke() ~[classes/:na] at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-5.0.8.RELEASE.jar:5.0.8.RELEASE] ...
Root cause: Taco.java
... @Size(min=1, message="You must choose at least 1 ingredient") private List<Ingredient> ingredients; ...
ingredients
field has@Size
validation. But according to documentation for@Size
validation null is considered valid. If you choose no ingredients theningredients
field will be null and it is a valid value.
Anybody knows how to solve this problem?