14
respostas

404 ao finalizar ou excluir item do carrinho

Boa tarde pessoal, Fiz todos os ajustes conforme dito em aula, quase tudo funcionando. Porém ao tentar finalizar ou retirar um item do carrinho, recebo 404. Percebi que não estou nem entrando no método do PagamentoController para finalizar ou no do Carrinho Controller para remover item do carrinho.

Form para finalizar pagamento

 <form action="${s:mvcUrl('PC#finalizar').build()}" method="POST" >
 <tr>
    <td colspan="3">
        <input type="submit" class="checkout" name="checkout" 
                             value="Finalizar compra" />
     </td>
     <td class="numeric-cell">${carrinhoCompras.total }</td>
 </tr>
                    </form>

Form para remover item

<form action="${s:mvcUrl('CCC#remover').arg(0,item.produto.id).arg(1,item.tipoPreco).build() }"   method="post">
      <input type="image"src="http:////cdn.shopify.com/s/files/1/0155/7645/t/177/assets/excluir.png?1575580795780530083" 
            alt="Excluir" title="Excluir" />
</form>

Pagamento Controller

package br.com.casadocodigo.loja.controllers;

import java.util.concurrent.Callable;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import br.com.casadocodigo.loja.models.CarrinhoCompras;
import br.com.casadocodigo.loja.models.DadosPagamento;

@RequestMapping("/pagamento")
@Controller
@Scope(value = WebApplicationContext.SCOPE_REQUEST)
public class PagamentoController {

    @Autowired
    private CarrinhoCompras carrinho;

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping(value="/finalizar", method=RequestMethod.POST)
    public Callable<ModelAndView> finalizar(RedirectAttributes model) {
        return () -> {
                try {

                    String uri = "http://book-payment.herokuapp.com/payment";
                    String response = restTemplate.postForObject(uri, new DadosPagamento(carrinho.getTotal()), String.class);
                    model.addFlashAttribute("mensagem", response);
                    System.out.println(response);
                } catch (HttpClientErrorException e) {

                    e.printStackTrace();
                    model.addFlashAttribute("falha","Valor maior que o permitido");
                }

                return new ModelAndView("redirect:/");
            };


    }
}

CarrinhoDeComprasController

package br.com.casadocodigo.loja.controllers;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.ModelAndView;

import br.com.casadocodigo.loja.daos.ProdutoDAO;
import br.com.casadocodigo.loja.models.CarrinhoCompras;
import br.com.casadocodigo.loja.models.CarrinhoItem;
import br.com.casadocodigo.loja.models.Produto;
import br.com.casadocodigo.loja.models.TipoPreco;

@Controller
@RequestMapping("/carrinho")
@Scope(value=WebApplicationContext.SCOPE_REQUEST)
public class CarrinhoComprasController {

    @Autowired
    private ProdutoDAO produtoDAO;

    @Autowired
    private CarrinhoCompras carrinho;

    @RequestMapping("/add")
    public ModelAndView add(Integer produtoId, TipoPreco tipoPreco) {

        ModelAndView modelAndView = new ModelAndView("redirect:/carrinho");
        CarrinhoItem carrinhoItem = criaItem(produtoId, tipoPreco);
        carrinho.add(carrinhoItem);

        return modelAndView;
    }

    private CarrinhoItem criaItem (Integer produtoId,TipoPreco tipoPreco) {
        Produto produto = produtoDAO.find(produtoId);
        CarrinhoItem carrinhoItem = new CarrinhoItem(tipoPreco, produto);
        return carrinhoItem;
    }

    @RequestMapping(method=RequestMethod.GET)
    public ModelAndView itens(){
        return new ModelAndView("/carrinho/itens");
    }

    @RequestMapping("/remover")
    public ModelAndView remover(Integer produtoId, TipoPreco tipoPreco) {
        carrinho.remover(produtoId, tipoPreco);
        return new ModelAndView("redirect:/carrinho");
    }



}

O que pode ser isso?

14 respostas

Fala Thiago, tudo bem ?

Olhando o código que você postou não consegui ver direto o problema. Você tem esse projeto em algum repositório aberto, pra que seja possível dar uma olhada ou testar ?

Abraço!

Fala Rafael. Não sei se consegui upar ele certinho no github não. Da uma olhada aqui! https://github.com/thorlan/casadocodigoAluraSpring

Agradeço desde já a atenção

Se eu passar no form assim

<form action="carrinho/remover"   method="post">

Ele acha o metodo + recebo um null pointer. (Por não passar o arg0 e o arg1 que no caso seria

<form action="${s:mvcUrl('CCC#remover').arg(0,item.produto.id).arg(1,item.tipoPreco).build() }"   method="post">

Isso pode ser alguma configuração na classe Security ??? Já tentei dar permissão para todo mundo e até agora nada.

Fala Thiago, tudo bem ?

Clonei seu projeto, fiz pequenos ajustes para o meu ambiente (sem nenhuma alteração no código de negócio) e testei ele por aqui. Vamos lá:

  • Adicionei um produto normalmente. Fui até a página de detalhes do produto, tudo ok. Adicionei um produto ao carrinho e fui redirecionado para a página do carrinho, tudo certo. Cliquei em excluir para tirar o produto do carrinho, e por aqui tudo funcionou também =)

produto no carrinho

Abaixo dá pra ver que o post foi processado e solicita redirect pra página do carrinho que é corretamente atualizada.

exclusão do item

  • Na página de detalhes do produto, cliquei no link pra navegar ao carrinho e lá sim tive um 404.

Percebi que o endereço que estava sendo feito a requisição é http://localhost:8080/cart (sem o contexto do projeto). O que vai resultar em 404 mesmo.

Mudando o trecho da página de detalhes, que originalmente está assim:

<li><a href="/cart" rel="nofollow">Carrinho (${carrinhoCompras.quantidade })</a></li>

..para:

<li><a href="<c:url value='/carrinho' />" rel="nofollow">Carrinho (${carrinhoCompras.quantidade })</a></li>

.. já soluciona o problema.

  • Ao tentar finalizar a compra o problema apresentado foi um 403, reclamando sobre o token csrf necessário ao spring security.

erro ao finalizar

Adicionando o input com o token do crsf ao form que faz o fechamento já resolveu =)

<tfoot>
    <form action="${s:mvcUrl('PC#finalizar').build()}" method="POST" >
        <security:csrfInput/>
        <tr>
            <td colspan="3">
                <input type="submit" class="checkout" name="checkout" value="Finalizar compra" />
            </td>
            <td class="numeric-cell">${carrinhoCompras.total }</td>
        </tr>
    </form>
</tfoot>

pagamento efetuado

Como visto poucos ajustes foram feitos e tudo funcionou perfeitamente, seu código de negócio está perfeito.

Espero ter ajudado. Abraço!

Fala Rafael, Muito obrigado pelo tempo e pela resposta. Ajustei os links que estavam quebrados e agora estão 100%. Adicionei o crfInput no form também, porém o erro continua, tanto no remover produto quanto no finalizar carrinho. Que doidera não?

Tirei um print do remover produto. https://uploaddeimagens.com.br/imagens/removerproduto-png

Fala Thiago ..

Que estranho! Aqui a requisição funcionou .. E é mais estranho porque inicialmente rodando por aqui o problema era um 403, ou seja o recurso foi encontrado, e não 404.

Tente fazer o seguinte: Remova o projeto do servidor momentaneamente. Na pasta do projeto remova o conteúdo da pasta /target e de um Project > Clean no projeto.

Depois dê um clean no servidor; e um Clean Tomcat working directory. Aí adicione novamente o projeto no servidor, clique direito no server > publish. Suba o servidor e tente de novo. Aparentemente deve ter algum problema no último build do projeto instalado no server (porque exatamente o mesmo código rodou aqui).

Tente também criar um arquivo chamado log4j.properties na sua pasta src/main/java com o seguinte conteúdo:

### as mensagens sao impressas pelo logger no console ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### niveis de log disponiveis: 'debug', 'info', 'warn', 'error', 'fatal' 

# nivel padrao: 'warn' 
log4j.rootLogger=warn, stdout

# nivel para o package org.springframework: 'info'
log4j.logger.org.springframework=info

Assim você vai ter logs de inicialização mais completos. Vai poder ver por exemplo todos os endereços mapeados pelo controllers spring no load da app.

Veja se funciona. Caso não, poste aqui os logs de inicialização com os detalhes e contando o que ocorreu.

Abraço!

Eu de novo! Fiz tudo e não funcionou. Deletei e clonei do git e mesmo assim não funcionou. Adicionei o arquivo, o log veio assim

INFORMAÇÕES: Initializing Spring root WebApplicationContext
00:51:33,267  INFO ContextLoader:285 - Root WebApplicationContext: initialization started
00:51:33,274  INFO AnnotationConfigWebApplicationContext:510 - Refreshing Root WebApplicationContext: startup date [Thu Dec 21 00:51:33 BRST 2017]; root of context hierarchy
00:51:33,353  INFO AnnotationConfigWebApplicationContext:208 - Registering annotated classes: [class br.com.casadocodigo.loja.config.SecurityConfiguration,class br.com.casadocodigo.loja.config.AppWebConfiguration,class br.com.casadocodigo.loja.config.JPAConfiguration]
00:51:33,614  INFO DefaultListableBeanFactory:793 - Overriding bean definition for bean 'mvcConversionService': replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration; factoryMethodName=mvcConversionService; initMethodName=null; destroyMethodName=(inferred); defined in class org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=appWebConfiguration; factoryMethodName=mvcConversionService; initMethodName=null; destroyMethodName=(inferred); defined in class br.com.casadocodigo.loja.config.AppWebConfiguration]
00:51:34,085  INFO DriverManagerDataSource:133 - Loaded JDBC driver: com.mysql.jdbc.Driver
00:51:34,103  INFO LocalContainerEntityManagerFactoryBean:337 - Building JPA container EntityManagerFactory for persistence unit 'default'
00:51:36,116  INFO DefaultSecurityFilterChain:28 - Creating filter chain: org.springframework.security.web.util.matcher.AnyRequestMatcher@1, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@3cb0a4fd, org.springframework.security.web.context.SecurityContextPersistenceFilter@3e1e44a5, org.springframework.security.web.header.HeaderWriterFilter@59ecbff6, org.springframework.security.web.csrf.CsrfFilter@75038f62, org.springframework.security.web.authentication.logout.LogoutFilter@7c26b384, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@32702e11, org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@655377bf, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@6e045665, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@6281472, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@1d7639b2, org.springframework.security.web.session.SessionManagementFilter@383878c5, org.springframework.security.web.access.ExceptionTranslationFilter@4b81e8ae, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@17317345]
00:51:36,494  INFO RequestMappingHandlerAdapter:523 - Looking for @ControllerAdvice: Root WebApplicationContext: startup date [Thu Dec 21 00:51:33 BRST 2017]; root of context hierarchy
00:51:36,555  INFO SimpleUrlHandlerMapping:315 - Mapped URL path [/resources/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
00:51:36,590  INFO RequestMappingHandlerMapping:220 - Mapped "{[/carrinho/add],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.web.servlet.ModelAndView br.com.casadocodigo.loja.controllers.CarrinhoComprasController.add(java.lang.Integer,br.com.casadocodigo.loja.models.TipoPreco)
00:51:36,591  INFO RequestMappingHandlerMapping:220 - Mapped "{[/carrinho/remover],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.web.servlet.ModelAndView br.com.casadocodigo.loja.controllers.CarrinhoComprasController.remover(java.lang.Integer,br.com.casadocodigo.loja.models.TipoPreco)
00:51:36,591  INFO RequestMappingHandlerMapping:220 - Mapped "{[/carrinho],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.web.servlet.ModelAndView br.com.casadocodigo.loja.controllers.CarrinhoComprasController.itens()
00:51:36,591  INFO RequestMappingHandlerMapping:220 - Mapped "{[/],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.web.servlet.ModelAndView br.com.casadocodigo.loja.controllers.HomeController.index()
00:51:36,594  INFO RequestMappingHandlerMapping:220 - Mapped "{[/pagamento/finalizar],methods=[POST],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.util.concurrent.Callable<org.springframework.web.servlet.ModelAndView> br.com.casadocodigo.loja.controllers.PagamentoController.finalizar(org.springframework.web.servlet.mvc.support.RedirectAttributes)
00:51:36,594  INFO RequestMappingHandlerMapping:220 - Mapped "{[/produtos/form],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.web.servlet.ModelAndView br.com.casadocodigo.loja.controllers.ProdutoController.form(br.com.casadocodigo.loja.models.Produto)
00:51:36,595  INFO RequestMappingHandlerMapping:220 - Mapped "{[/produtos],methods=[POST],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.web.servlet.ModelAndView br.com.casadocodigo.loja.controllers.ProdutoController.grava(org.springframework.web.multipart.MultipartFile,br.com.casadocodigo.loja.models.Produto,org.springframework.validation.BindingResult,org.springframework.web.servlet.mvc.support.RedirectAttributes)
00:51:36,595  INFO RequestMappingHandlerMapping:220 - Mapped "{[/produtos/detalhe/{id}],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.web.servlet.ModelAndView br.com.casadocodigo.loja.controllers.ProdutoController.detalhe(java.lang.Integer)
00:51:36,596  INFO RequestMappingHandlerMapping:220 - Mapped "{[/produtos],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.web.servlet.ModelAndView br.com.casadocodigo.loja.controllers.ProdutoController.listar()
00:51:36,699  INFO ContextLoader:325 - Root WebApplicationContext: initialization completed in 3430 ms
dez 21, 2017 12:51:36 AM org.apache.catalina.core.ApplicationContext log
INFORMAÇÕES: Initializing Spring FrameworkServlet 'dispatcher'
00:51:36,704  INFO DispatcherServlet:479 - FrameworkServlet 'dispatcher': initialization started
00:51:36,707  INFO AnnotationConfigWebApplicationContext:510 - Refreshing WebApplicationContext for namespace 'dispatcher-servlet': startup date [Thu Dec 21 00:51:36 BRST 2017]; parent: Root WebApplicationContext
00:51:36,743  INFO DispatcherServlet:498 - FrameworkServlet 'dispatcher': initialization completed in 39 ms
dez 21, 2017 12:51:36 AM org.apache.coyote.AbstractProtocol start
INFORMAÇÕES: Starting ProtocolHandler ["http-nio-8080"]
dez 21, 2017 12:51:36 AM org.apache.coyote.AbstractProtocol start
INFORMAÇÕES: Starting ProtocolHandler ["ajp-nio-8009"]
dez 21, 2017 12:51:36 AM org.apache.catalina.startup.Catalina start
INFORMAÇÕES: Server startup in 9660 ms

Qualquer link que eu tente fazer usando o s:mvc... da erro

<security:authorize access="hasRole('ROLE_ADMIN')">
    <li><a href="${s:mvcUrl('PC#listar').build() }" rel="nofollow">Listagem de Produtos</a></li>
       <li><a href="${s:mvcUrl('PC#form').build() }" rel="nofollow">Cadastro de Produtos</a></li>
  </security:authorize>

Adicionei esses dois links ná página e pronto, 404 também. Só nessa jsp que tenho esse erro.

Criei uma nova jsp, só coloquei as informações necessárias e mesmo assim nada. :( https://uploaddeimagens.com.br/imagens/compilar-jpg

Apaguei o pagamentoController e o carrinhoController, colei o código dentro de novo e FOI kkkkkkkkkk. Vai entender isso Muito obrigado pelo tempo, ajuda e atenção Rafael. Abraços

Fala Thiago ...

Que bom que conseguiu resolver. As vezes o arquivo compilado estava com uma versão defasada do seu código, causado talvez por algum bug no plugin do eclipse para o maven, ou algo assim. As vezes acontecem essas bruxarias rs.

Abraço!

Então kkkk! Valeu meu camarada! Abraços!

Abraço!