habuma / spring-in-action-5-samples

Home for example code from Spring in Action 5.
Apache License 2.0
1.21k stars 1.04k forks source link

chapter 3: NullPointerException when saving Taco design without ingredients #40

Open grolegor opened 5 years ago

grolegor commented 5 years ago

Steps to reproduce:

  1. go to ch03/tacos-jdbc
  2. mvn spring-boot:run
  3. localhost:8080
  4. click on the link "Design a taco"
  5. set taco name: "test-taco-name"
  6. 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.

bensgith commented 4 years ago

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
}
Sammygracezhu commented 4 years ago

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. notifications@github.com 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 .

LiUzHiAn commented 4 years ago

@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~

knastnt commented 4 years ago

you must set this: preparedStatementCreatorFactory.setReturnGeneratedKeys(true);

mananmehta11 commented 4 years ago
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();
    }
CharlesUESTC commented 1 year ago

Steps to reproduce:

  1. go to ch03/tacos-jdbc
  2. mvn spring-boot:run
  3. localhost:8080
  4. click on the link "Design a taco"
  5. set taco name: "test-taco-name"
  6. 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.

Anybody knows how to solve this problem?