Olá Adriana, tudo bem ?
Não deve ser a chamada para spring:mvcUrl
a causa do problema. Tenho um teste com o mesmo projeto do curso na minha máquina. Originalmente estava usando a propriedade servletRelativeAction
(taglib de forms do spring) que tem o mesmo propósito. Mas fiz o teste local alterando para usar action="${spring:mvcUrl('PC#save').build()}"
que infere pro método de adição de novos produtos.
Veja:
Perceba que a função é resolvida normalmente para o endereço apropriado quando o html correspondente ao jsp é criado.
Veja o endereço da action: http://localhost:8080/casadocodigo/products; e o método: post
Agora depois de enviado:
Tudo deu certo
Tente ver se o html gerado a partir do jsp está dentro do que você espera e quais dados a aplicação está enviando (é possível ver justamente na aba Network, inspecionando a requisição que foi feita)
Tente buscar por Request Payload ao buscar as informações sobre a requisição.
No meu caso localmente ele enviou esse payload, por exemplo:
------WebKitFormBoundaryjmZTBptptzG5Ou8F
Content-Disposition: form-data; name="product.title"
Teste Alura
------WebKitFormBoundaryjmZTBptptzG5Ou8F
Content-Disposition: form-data; name="product.description"
Teste Alura
------WebKitFormBoundaryjmZTBptptzG5Ou8F
Content-Disposition: form-data; name="product.numberOfPages"
123
------WebKitFormBoundaryjmZTBptptzG5Ou8F
Content-Disposition: form-data; name="product.prices[0].value"
19
------WebKitFormBoundaryjmZTBptptzG5Ou8F
Content-Disposition: form-data; name="product.prices[0].bookType"
EBOOK
------WebKitFormBoundaryjmZTBptptzG5Ou8F
Content-Disposition: form-data; name="product.prices[1].value"
29
------WebKitFormBoundaryjmZTBptptzG5Ou8F
Content-Disposition: form-data; name="product.prices[1].bookType"
PRINTED
------WebKitFormBoundaryjmZTBptptzG5Ou8F
Content-Disposition: form-data; name="product.prices[2].value"
39
------WebKitFormBoundaryjmZTBptptzG5Ou8F
Content-Disposition: form-data; name="product.prices[2].bookType"
COMBO
------WebKitFormBoundaryjmZTBptptzG5Ou8F
Content-Disposition: form-data; name="product.releaseDate"
2018-02-23
------WebKitFormBoundaryjmZTBptptzG5Ou8F
Content-Disposition: form-data; name="summary"; filename="nota-fiscal-moto-z.pdf"
Content-Type: application/pdf
------WebKitFormBoundaryjmZTBptptzG5Ou8F
Content-Disposition: form-data; name="_csrf"
110be46f-eecd-4556-a01e-80c24bb7965b
------WebKitFormBoundaryjmZTBptptzG5Ou8F--
OBS: Caso esteja se perguntando porque a diferença nos names, é porque minha implementação interna é diferente do curso base, ao invés de receber um Produto direto no construtor, recebo um objeto específico do form que possui um produto e mais coisas. Mas a ideia é a mesma.
Caso não consiga encontrar o problema poste os códigos aqui pra gente poder analisar.
Esperto ter ajudado. Abraço!