Falha ao localizar recurso por JAX-RS

Estou começando a utilizar JAX-RS nas minhas aplicações, e gostaria de uma ajuda de vocês. Após tentar implementar rest em um CRUD de produtos estou recebendo o seguinte log pelo console:

[org.jboss.resteasy.core.ExceptionHandler] (default task-7) failed to execute: javax.ws.rs.NotFoundException: Could not find resource for full path:http://localhost:8080/myStore/store/products.xhtml

Já tentei fazer o request por: http://localhost:8080/myStore/store/products e também por http://localhost:8080/myStore/products porém ambas não carregam o xml propriamente e também deixou de carregar a página jsf.

A minha classe de configuração está da seguinte forma:

package org.myStore.services;

public class ApplicationService extends Application{
	@Override
	public Map<String, Object> getProperties(){
		Map<String, Object> properties = new HashMap<>();
		properties.put("jersey.config.server.provider.packages", "org.myStore.managedbeans");
		return properties;
	}
}

e a classe qual estou chamando o meu serviço está assim:

package org.myStore.managedbean;

@Path("store/products")
@Consumes({MediaType.APPLICATION_XML})
@Produces({MediaType.APPLICATION_XML})
@Model
public class ProductsBean {
	
	@Inject
	private ProductDao productdao;
	
	private List<Product> products = new ArrayList<Product>();
	@GET
	@PostConstruct
	private void loadProducts(){
		this.products = productdao.listProduct();
	}
	
	public List<Product> getProducts(){
		return products;
	}

}

e caso precisem ver como configurei o web.xml, eu o deixei desta forma:

 <servlet>
 	<servlet-name>org.myStore.services.ApplicationService</servlet-name>
 	<load-on-startup>1</load-on-startup>
 </servlet>
 
 <servlet-mapping>
 	<servlet-name>org.myStore.services.ApplicationService</servlet-name>
 	<url-pattern>/*</url-pattern>
 </servlet-mapping>

Desde já agradeço quem puder ajudar.

Apenas para atualizar.

Notei que havia feito o mapeamento com uma letra errada.
Após a correção não houve mais warnings no log do console, e minha aplicação voltou a carregar o xhtml, porém ainda não consigo trabalhar com o rest.
Quando tento acessar pela url localhost:8080/myStore/store/products como configurado a página apenas retorna 404 not found.

Alguém sugere algo ou encontrou algum detalhe que deixei passar?

Vou ler o seu post e comentar os problemas ou potenciais problemas que eu encontrar durante a leitura.

  1. Você está utilizando o RESTEasy como implementação mas está especificando propriedades do Jersey. Isso não vai funcionar. As duas são implementações completamente independentes;

  2. Você não deve colocar extensões em requisições para serviços RESTful. Você não está consumindo um arquivo estático ou um script, mas uma entidade. O certo seria: https://host/api/caminho/ate/a/entidade, sem o .xhtml ou qualquer outra extensão. Você especifica o tipo de dado que quer receber utilizando o header accept do HTTP;

  3. Você está misturando GET com PostConstruct, e os dois não tem nada a ver um com o outro. O GET declara que esse método deve ser utilizando quando alguém fizer uma requisição HTTP com o verbo GET para o endpoint (ou path) store/products. O PostConstruct é um método de lifecycle e é chamado para que você possa tomar alguma ação quando esse recurso é construído pelo container, como carregar algum tipo de dependência;

  4. Recursos RESTful devem ser STATELESS, ou seja, você não deve guardar NENHUM estado dentro deles que tem a ver com as requisições. Dentre outras razões, especificamente no JAX-RS, você deve seguir essa regra a risca porque você não sabe em qual instância dessa classe as requisições vão ser executadas. No Jersey, por exemplo, o padrão de escopo de um recurso JAX-RS é @RequestScoped. Ou seja, cada vez que você faz uma requisição para o endpoint específico, o container pode trata-la com instâncias diferentes do recurso;

  5. Você está inicializando a variável List<Product> products duas vezes. Uma na hora que faz new ArrayList<Product>() e dentro do @PostConstruct. A primeira é desnecessária. Na verdade, essa variável é completamente desnecessária;

  6. Como você está usando um container com RESTEasy, vou colocar aqui como deveria ficar o web.xml baseado na documentação:

     <web-app>
         <servlet>
             <servlet-name>MinhaAPI</servlet-name>
             <servlet-class>
                 org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
             </servlet-class>
             <init-param>
                 <param-name>javax.ws.rs.Application</param-name>
                 <param-value>org.myStore.services.ApplicationService</param-value>
             </init-param>
         </servlet>
    
         <servlet-mapping>
             <servlet-name>MinhaAPI</servlet-name>
             <url-pattern>/*</url-pattern>
         </servlet-mapping>
     </web-app>
    

    Isso se você realmente quiser fazer o mapeamento no web.xml, que hoje é completamente desnecessário. Você pode simplesmente anotar a tua classe ApplicationService com @ApplicationPath("pathParaApi") e o container vai fazer o mapeamento automaticamente;

  7. Um recurso JAX-RS tem mais ou menos essa cara aqui:

     @Path("notes")
     public class NoteResource {
         @Inject
         NoteService noteService;
    
         @GET
         public Response getAllNotes(@QueryParam("offset") Long offset, @QueryParam("size") Long size) {
             List<Note> result;
             try {
                 result = noteService.fetchNotes(offset, size);
                 return Response.ok(result).build();
             } catch (AlgumaException ex) {
                 return Response.status(/*400, 500, etc*/).build();
             }
         }
     }
    

    Esse método vai ser encontrado quando alguém fizer uma requisição HTTP com GET para host/pathParaApi/notes?offset=5&size=3. Os parâmetros de query são opcionais, mas caso informados, são injetados nos parâmetros do metodo getAllNotes.

Vou tentar seguir por esse caminho, mas criando um novo package que servirá apenas de interação com os “serviços”.
Já que antes eu estava seguindo um caminho onde colocava as tags de serviço no meu managed bean… acredito que isso possa ter criado algum conflito, já que algumas tags estavam uma sobre a outra, como você citou em relação ao GET e ao PostConstruct.

Solução em: CRUD JAX-RS ou CRUD via managed beans com persistencia em DAO?

1 curtida