Ressource not found error in postman with spring - java

i'm a beginner and i'm testing springboot, creating a simple api.
When testing my post request via postman, it gives me a 404 error.
postman
package com.ecommerce.microcommerce;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
#SpringBootApplication
#ComponentScan("com.ecommerce.microcommerce.repository")
public class MicrocommerceApplication {
public static void main(String[] args) {
SpringApplication.run(MicrocommerceApplication.class, args);
}
}
UserRepository :
package com.ecommerce.micocommerce.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.ecommerce.microcommerce.model.User;
public interface UserRepository extends JpaRepository<User, Long> {
}
UserService :
package com.ecommerce.microcommerce.service;
import java.util.List;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ecommerce.micocommerce.repository.UserRepository;
import com.ecommerce.microcommerce.model.User;
#Service
#Transactional
public class UserService {
#Autowired
private UserRepository userRepository;
public void saveUser(User user) {
userRepository.save(user);
}
UserController :
package com.ecommerce.microcommerce.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.ecommerce.microcommerce.model.User;
import com.ecommerce.microcommerce.service.UserService;
#RestController
public class UserController {
#Autowired
private UserService userService;
#PostMapping("/Users")
public void addUser(#RequestBody User user) {
System.out.println(user);
userService.saveUser(user);
}
}
application.properties :
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:8889/microcommerce?createDatabaseIfNotExist=true
spring.datasource.username=root
spring.datasource.password=root
#Hibernate
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
I noticed that since I added the #ComponentScan annotation, postman returns me a 404.
But I have to use this one because otherwise #Autowired does not work.
Thanks for your help.

Your #ComponentScan is not scanning your Controller neither your Service.
In fact, having it is not needed at all when using #SpringBootApplication. This should scan all packages that it's part of, in your case, com.ecommerce.microcommerce.
Perhaps your Repository has not been scanned/autowired because of a type on your package name?
micocommerce vs microcommerce.
tip: use constructor injection instead of autowiring
#RestController
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
// methods
}

Edit #ComponentScan("com.ecommerce.microcommerce.repository") to #ComponentScan("com.ecommerce.microcommerce) so that it scans Controller, Services and Repositories in your base package. Please check link how Springboot uses #SpringBootApplication annotation(as it already enables #ComponentScan feature):
Please do check the package name(micocommerce) you have provided for the UserRepository class.

Related

Consider defining a bean of type 'com.fsse2207.project_backend.service.ProductService' in your configuration

Basically, I have created all of the pojo and layers(including the repository layer) necessary for Spring Boot to automatically implement MySql commands. When I trying to run the programme, I get the following command:
Description:
Parameter 0 of constructor in com.fsse2207.project_backend.api.ProductApi required a bean of type 'com.fsse2207.project_backend.service.ProductService' that could not be found.
Action:
Consider defining a bean of type 'com.fsse2207.project_backend.service.ProductService' in your configuration.
It turns out there's sth wrong about the bean in my ProductApi. It says "
Could not autowire. No beans of 'ProductService' type found." How do I fix it?
The following is the interface under the service layer:
package com.fsse2207.project_backend.service;
import com.fsse2207.project_backend.data.ProductCreateData;
import com.fsse2207.project_backend.data.ProductDetailData;
import com.fsse2207.project_backend.exception.ProductFoundByIdException;
import org.springframework.stereotype.Service;
public interface ProductService {
ProductDetailData createProductData (ProductCreateData productCreateData) throws ProductFoundByIdException;
}
The following is the service class:
package com.fsse2207.project_backend.service.impl;
import com.fsse2207.project_backend.data.ProductCreateData;
import com.fsse2207.project_backend.data.ProductDetailData;
import com.fsse2207.project_backend.data.entity.ProductEntity;
import com.fsse2207.project_backend.exception.ProductFoundByIdException;
import com.fsse2207.project_backend.repository.ProductRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class ProductServiceImpl {
private ProductRepository productRepository;
#Autowired
public ProductServiceImpl(ProductRepository productRepository){
this.productRepository=productRepository;
}
public ProductDetailData createProductData (ProductCreateData productCreateData) throws ProductFoundByIdException {
ProductEntity productEntity=new ProductEntity(productCreateData);
if(productRepository.existsById(productEntity.getpId())){
throw new ProductFoundByIdException();
}
return new ProductDetailData(productRepository.save(productEntity));
}
}
The following is the Api:
package com.fsse2207.project_backend.api;
import com.fsse2207.project_backend.data.ProductCreateData;
import com.fsse2207.project_backend.data.ProductDetailData;
import com.fsse2207.project_backend.data.dto.CreateRequestDto;
import com.fsse2207.project_backend.data.dto.CreateResponseDto;
import com.fsse2207.project_backend.exception.ProductFoundByIdException;
import com.fsse2207.project_backend.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class ProductApi {
private ProductService productService;
#Autowired
public ProductApi(ProductService productService){
this.productService=productService;
}
#PostMapping
public CreateResponseDto createResponseDto(#RequestBody CreateRequestDto createRequestDto) throws ProductFoundByIdException {
ProductCreateData productCreateData=new ProductCreateData(createRequestDto);
ProductDetailData productDetailData =productService.createProductData(productCreateData);
return new CreateResponseDto(productDetailData);
}
}
I found the problem:
I didn't add the implements keyword in the class definition of ProductServiceImpl so it was not connected to the bean, aka the interface, aka the service layer.
First of all you should not add annotation #Service for ProductService interface.
Moreover this can happen when you have your Class Application in "another package".
You can solve the problem using annotation #ComponentScan (basePackages = {"your.company.domain.package"})

Spring doesn't scan packages

I have a repository, annotated with #Repository
package com.jeppa.interfaces;
import com.jeppa.entities.User;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface UserRepository extends CrudRepository<User, String> {
User findByUserEmailIgnoreCase(String useremail);
}
Part of my controller:
package com.jeppa.controllers;
import com.jeppa.entities.ConfirmationToken;
import com.jeppa.entities.User;
import com.jeppa.interfaces.TokenRepository;
import com.jeppa.interfaces.UserRepository;
import com.jeppa.mail.EmailSenderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
#Controller
public class UserAccountController {
#Autowired
private UserRepository userRepository;
#Autowired
private TokenRepository tokenRepository;
#Autowired
private EmailSenderService emailSenderService;
#RequestMapping(value = "/register", method = RequestMethod.GET)
public ModelAndView displayRegistration(ModelAndView modelAndView, User user){
modelAndView.addObject("user", user);
modelAndView.setViewName("register");
return modelAndView;
}
//////////////
And, finnaly, my #SpringBootApplication:
package com.jeppa;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class RunApplication {
public static void main(String[] args) {
SpringApplication.run(RunApplication.class, args);
}
}
and i keep getting this error
*************************** APPLICATION FAILED TO START
Description:
Field userRepository in com.jeppa.controllers.UserAccountController
required a bean of type 'com.jeppa.interfaces.UserRepository' that
could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.jeppa.interfaces.UserRepository'
in your configuration.
what am i doing wrong? here's my project structure:
structure
With Spring Boot, you should generally rely on Spring Boot starters to autoconfigure your dependencies. In case of Spring Data add:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
into your pom file to autoconfigure Spring Data instead of directly relying on Spring Data (spring-data-jpa), which requires further manual configuration.
Also don't forget to add and configure an actual implementation as well (h2, jdbc, etc.)

Wrong Pageable data displayed in my browser

I am trying to display data from MySQL database using spring data with Pageable class. I am new in Spring Data and unfortunately I get all rows shown in my browser, instead of some.
Find below my code
pom.xml
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.5.0.RELEASE</version>
</dependency>
ProductDaoImpl
package com.dao;
import java.util.List;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import com.model.Product;
#Repository
public class ProductDaoImpl implements ProductDao {
#Autowired
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
#SuppressWarnings("unchecked")
public Page<Product> getPageProduct(#Param("libelleProduct")String libelleProduct, Pageable pageable) {
List<Product> listProduct = sessionFactory.getCurrentSession().createQuery("From Product p where p.libelleProduct like :libelleProduct").setParameter("libelleProduct", libelleProduct).list();
Page<Product> pageProduct = new PageImpl<Product>(listProduct, pageable, listProduct.size());
return pageProduct;
}
}
ProductService
package com.service;
import java.util.List;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import com.dao.ProductDao;
import com.model.Product;
#Service
#Transactional
public class ProductServiceImpl implements ProductService {
#Autowired
private ProductDao productDao;
public ProductDao getProductDao() {
return productDao;
}
public Page<Product> getPageProduct(String libelleProduct, int page, int size) {
return productDao.getPageProduct(libelleProduct, new PageRequest(page, size));
}
}
ProductController
package com.controller;
import org.jboss.logging.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.model.Product;
import com.service.ProductService;
#RestController
public class ProductController {
public Logger logger = Logger.getLogger(ProductController.class);
public ProductController(){
System.out.println("ProductController()");
}
#Autowired
private ProductService service;
#RequestMapping(value="/listedesproduit", method=RequestMethod.GET, headers="Accept=application/json")
#ResponseBody
public Page<Product> getPageProduct(){
Page<Product> pageProduct = service.getPageProduct("%e%",0, 1);
pageProduct.forEach(p->System.out.println(p.getLibelleProduct()));
return pageProduct;
}
}
Find below the result I get in my browser, I get four rows shown instead of one on each page.
{"content":[{"idProduct":2,"libelleProduct":"sprite","qteProduct":5},{"idProduct":3,"libelleProduct":"eku","qteProduct":5},{"idProduct":4,"libelleProduct":"33 export","qteProduct":5},{"idProduct":6,"libelleProduct":"guiness","qteProduct":5}],"size":1,"number":0,"numberOfElements":4,"sort":null,"totalPages":4,"totalElements":4,"firstPage":true,"lastPage":false}
Can you please help me to find what I do wrong?
You are using it wrong here:
List<Product> listProduct = sessionFactory.getCurrentSession()
.createQuery("From Product p where p.libelleProduct like :libelleProduct")
.setParameter("libelleProduct", libelleProduct).list();
Page<Product> pageProduct = new PageImpl<Product>(listProduct, pageable, listProduct.size());
You are basically loading all the query results and then returning it in a PageImpl, which is just a wrapper of the data.
You should create a PagingAndSortingRepository and call query methods passing the Pageable, which is the page request to be executed by the repository.
If this doesn't make sense to you, look for tutorials about "spring data paging" like this one and take a look at the documentation.

How to properly #Autowire a component in a Spring Boot App

I'm putting together a simple Spring Boot app, and having an issue with an #Autowired field not "showing up".
My main app class:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class SpringElasticCatalogApi {
public static void main(String[] args) {
SpringApplication.run(SpringElasticCatalogApi.class, args);
}
}
My Repository class:
import com.discover.harmony.elastic.model.Customer;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Component;
import java.util.List;
#Component
public interface CustomerRepository extends ElasticsearchRepository<Customer, String> {
public Customer findByFirstName(String firstName);
public List<Customer> findByLastName(String lastName);
}
This class ("Loaders") requires an #Autowired repository field, which is NULL:
import com.discover.harmony.elastic.model.BusinessMetadata;
import com.discover.harmony.elastic.model.Customer;
//import com.discover.harmony.elastic.repository.CustomerRepository;
import com.discover.harmony.elastic.api.CustomerRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
//#Configuration
#Component
public class Loaders {
#Autowired
private CustomerRepository repository;
#PostConstruct
#Transactional
public void loadAll(){
this.repository.deleteAll();
saveCustomers();
fetchAllCustomers();
fetchIndividualCustomers();
}
private void saveCustomers() {
this.repository.save(new Customer("Alice", "Smith"));
this.repository.save(new Customer("Bob", "Smith"));
}
private void fetchAllCustomers() {
System.out.println("Customers found with findAll():");
System.out.println("-------------------------------");
for (Customer customer : this.repository.findAll()) {
System.out.println(customer);
}
System.out.println();
}
private void fetchIndividualCustomers() {
System.out.println("Customer found with findByFirstName('Alice'):");
System.out.println("--------------------------------");
System.out.println(this.repository.findByFirstName("Alice"));
System.out.println("Customers found with findByLastName('Smith'):");
System.out.println("--------------------------------");
for (Customer customer : this.repository.findByLastName("Smith")) {
System.out.println(customer);
}
}
private List<BusinessMetadata> getData() {
List<BusinessMetadata> metadata = new ArrayList<>();
metadata.add(new BusinessMetadata((long)1,"TradeLine"));
metadata.add(new BusinessMetadata((long)2,"Credit Line"));
metadata.add(new BusinessMetadata((long)3,"Other Line"));
return metadata;
}
}
What should I change, to make the #Autowire work as expected here?
The problem is that your example is not complete on implementing the ElasticSearch. To proof this, turn your CustomerRepository into a class and remove ElasticsearchRepository<Customer, String> then everything goes fine.
What you need to do is adding a new Configuration class, with #EnableElasticsearchRepositories(basePackages = "com.discover.harmony.elastic.api.CustomerRepository") to scan the provided package for Spring Data repositories.
You can find a complete example here.

Autowiring a interface work without annotating it

I am working on Spring and hibernate project. For database communication we have conventional two layered implementation (i.e DAO layer and Service layer). I have following files:
DemoDao.java
package net.dao;
import java.util.List;
import net.domain.Demo;
public interface DemoDao
{
public List<Demo> get();
}
DemoDaoImpl.java
package net.dao;
import java.util.List;
import net.domain.Demo;
import org.hibernate.SessionFactory;
import org.hibernate.classic.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
#Repository
public class DemoDaoImpl implements DemoDao
{
#Autowired
SessionFactory sessionFactory;
public List<Demo> get()
{
Session session=sessionFactory.openSession();
List<Demo> list=session.createQuery("from Demo").list();
session.close();
return list;
}
}
That was DAO layer
Follwing is from service layer:
DemoManager.java
package net.service;
import java.util.List;
import net.domain.Demo;
public interface DemoManager
{
public List<Demo> get();
}
DemoManagerImpl.java
package net.service;
import java.util.List;
import net.dao.DemoDao;
import net.domain.Demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class DemoManagerImpl implements DemoManager
{
#Autowired
DemoDao demoDao;
public List<Demo> get()
{
List<Demo> list=demoDao.get();
return list;
}
}
Follwing is my controller
FromDualLayerView.java
package net.spring;
import java.util.List;
import net.domain.Demo;
import net.service.DemoManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
#Controller
public class FromDualLayerView
{
#Autowired
DemoManager demoManager;
#RequestMapping("/dualLayer")
public ModelAndView toResult(ModelMap map)
{
List<Demo> list=demoManager.get();
map.addAttribute("listData", list);
return new ModelAndView("result");
}
}
My Question
Actually everything works fine, but my question over here is that i am not annotating the DemoDao and DemoManager interface, but i am autowiring them. According to the autowiring definition the entities which are annotated are injected.
The how come the dependency is injected by Spring container?
And how does it work like an Impl class?
Thanks in advance.
DemoManagerImpl is annotated as a service and is the only qualifying bean to be injected in the FromDualLayerView class, as it's the only component which is instance of DemoManager. I suppose you have the component scan turned on as well.
The #Repository annotation and the #Service annotation mean you are annotating them. It's actually a spring best practice to annotate the implementations and not the interfaces.
Your spring config file is scanning the classpath, thus those beans are detected. Turn spring logging up to TRACE and you'll probably see output along the lines of:
"scanning classpath, found target DemoDaoImpl"

Categories

Resources