Spring Boot & Couchbase Stack Overflow - java

Hi I have 2 simple classes in a bidirectional relationship which are causing infinite recursion resulting in an eventual stack overflow when serialising into JSON. I am using the Spring Boot 2.2.2 starter project for Couchbase and Spring Web dependencies. My maven pom.xml file is as follows:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>org.stevie</groupId>
<artifactId>stack-overflow-error</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>stack-overflow-error</name>
<description>Reproduce Couchbase API Failure</description>
<properties>
<java.version>13</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-couchbase</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
My domain classes are as follows:
Household.java
import org.springframework.data.couchbase.core.mapping.Document;
import com.couchbase.client.java.repository.annotation.Field;
import com.couchbase.client.java.repository.annotation.Id;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
#Document
#JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "#id")
public final class Household {
#Id
private final String key;
#Field
private String type = "household";
#Field
private final String headSurname;
#Field
private final String headForename;
#Field
private final List<Member> members;
public static Household of(String key, String headSurname, String headForename) {
return new Household(key, headSurname, headForename);
}
Household(String key, String headSurname, String headForename) {
super();
this.key = key;
this.headSurname = headSurname;
this.headForename = headForename;
this.members = new ArrayList<>();
}
public String getKey() {
return key;
}
public String getHeadSurname() {
return headSurname;
}
public String getHeadForename() {
return headForename;
}
#JsonManagedReference
public List<Member> getMembers() {
return members;
}
#Override
public String toString() {
return String.format("Household [key=%s, headSurname=%s, headForename=%s]", key,
headSurname, headForename);
}
}
Member.java
import org.springframework.data.couchbase.core.mapping.Document;
import com.couchbase.client.java.repository.annotation.Field;
import com.couchbase.client.java.repository.annotation.Id;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
#Document
#JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "#id")
public final class Member {
#Id
private final String key;
#Field
private final String name;
#Field
private final Household household;
public static Member of(String key, String name, Household household) {
return new Member(key, name, household);
}
Member(String key, String name, Household household) {
super();
this.key = key;
this.name = name;
this.household = household;
}
public String getKey() {
return key;
}
public String getName() {
return name;
}
#JsonBackReference
public Household getHousehold() {
return household;
}
#Override
public String toString() {
return String.format(
"Member [key=%s, name=%s]", key, name);
}
}
My unit test (JUnit 5) is
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.couchbase.core.CouchbaseTemplate;
import org.stevie.overflow.StackOverflowErrorApplication;
import org.stevie.overflow.domain.Household;
import org.stevie.overflow.domain.Member;
import com.couchbase.client.java.Bucket;
#SpringBootTest(classes = StackOverflowErrorApplication.class)
class HouseholdRepositoryTest {
#Autowired
private HouseholdRepository repo;
#Autowired
private CouchbaseTemplate template;
#BeforeAll
static void setUpBeforeClass() throws Exception {
}
#AfterAll
static void tearDownAfterClass() throws Exception {
}
#BeforeEach
void setUp() throws Exception {
}
#AfterEach
void tearDown() throws Exception {
}
#Test
void throwsStackOverflowExceptionTest() {
String key = manuallyGenerateKey("household");
Household house = Household.of(key, "BLOGGS", "Joe");
key = manuallyGenerateKey("member");
Member m1 = Member.of(key, "Joe Bloggs", house);
house.getMembers().add(m1);
/** Following code throws Stack overflow exception!!!!! **/
house = repo.save(house);
}
private String manuallyGenerateKey(String prefix) {
Bucket bucket = template.getCouchbaseBucket();
Long nextId = bucket.counter("counter::" + prefix, 1, 100).content();
String key = prefix + "::" + nextId;
return key;
}
}
I want the JSON for the household to contain its member objects and the member to contain its household object. I have tried Jackson annotations such as #JsonManagedReference and #JsonIdentityInfo but Spring appears to ignore them. Thanks.

Related

Issue with Spring Boot Validation with version 2.5.5

I am fairly new to Spring Boot and it's various libraries. I am particularly trying Validation. I have added Validation annotations to UserDto class. When I send createUser request with invalid email, I get success. None of the validations work.
I have tried using Hibernate-Validator dependancy as well.
See below the code.
The UserDto class:
import javax.validation.constraints.Email;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
public class UserDto {
#NotNull
#Min(value=5)
#Max(value=10)
private String name;
#NotNull
#Min(value=3)
#Max(value=50)
private String password;
#Email
private String email;
public UserDto(String name, String password, String email) {
super();
this.name = name;
this.password = password;
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
The UserCotroller:
import javax.validation.Valid;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.user.test.dto.UserDto;
#RestController
#RequestMapping("/users")
public class UserController {
#PostMapping
public ResponseEntity<String> createUser(#Valid #RequestBody UserDto userDto, Errors errors){
System.out.println(userDto.toString());
System.out.println(errors.toString());
String response = "success";
return ResponseEntity.ok(response);
}
}
Driver Class:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.user</groupId>
<artifactId>test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>test</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Here is the Postman Request, which gives "success".
{
"name": "Username",
"password":"username#123",
"email":"username"
}
I could find two issues in your code:
The #Min/#Max annotations are for numeric values, to set the range of numeric values (not the number of strings); so these do not work for Strings. Please remove them and find alternatives (e.g. #Size).
You need to map the userDto object to the model in your controller with the #ModelAttribute annotation.
Controller (further edited to accommodate different responses)
#PostMapping
public ResponseEntity<String> createUser(#ModelAttribute #Valid #RequestBody UserDto userDto,Errors errors){
System.out.println(userDto.toString());
System.out.println(errors.toString());
if (errors.hasErrors()) {
return ResponseEntity.badRequest().body("Errors exist");
}
return ResponseEntity.ok("Success");
}
}
UserDto
public class UserDto {
#NotNull
#Size(min=5, max= 10)
private String name;
#NotNull
#Size(min=3, max= 50)
private String password;
#Email
private String email;
// rest of the code
}
Tests for controller
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.hamcrest.Matchers.containsString;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
#SpringBootTest
#ExtendWith(MockitoExtension.class)
class UserControllerTest {
MockMvc mockMvc;
#Autowired
UserController userController;
#BeforeEach
void setUp() {
mockMvc = MockMvcBuilders.standaloneSetup(userController).build();
}
#Test
void emailInvalid() throws Exception {
mockMvc.perform(post("/users").param("name", "uname")
.param( "password", "LongPasswordHere")
.param( "email", "email")).andExpect(status().isBadRequest())
.andExpect(content().string(containsString("Errors exist")));
}
#Test
void emailValid() throws Exception {
mockMvc.perform(post("/users").param("name", "uname")
.param( "password", "LongPasswordHere")
.param( "email", "email#gmail.com")).andExpect(status().isOk())
.andExpect(content().string(containsString("Success")));
}
}

Spring Boot - “Error creating bean with name 'entityManagerFactory'” - Start

I have seen a lot of questions but the answers are not satisfying my problem...
I generate my project with Spring initialzr
I tried with the 3 java versions 14, 11, 8.
This is my project structure.
GardenApplication.java. I include all anottations even spring doc says that with #SpringBootApplication is enough. Before this error #Repository couldn't be found and I include #EnableJpaRepositories
package com.garden.garden;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
#SpringBootApplication
#EnableAutoConfiguration
#ComponentScan({"com.garden.garden.controller", "com.garden.garden.service.impl"})
#EnableJpaRepositories(basePackages = {"com.garden.garden.repository"})
#EntityScan(basePackages = {"com.garden.garden.model"})
public class GardenApplication {
public static void main(String[] args) {
SpringApplication.run(GardenApplication.class, args);
}
}
VegetableController.java
package com.garden.garden.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.garden.garden.model.Vegetable;
import com.garden.garden.service.VegetableService;
#Controller
#RequestMapping
public class VegetableController {
#Autowired
private VegetableService vegetableService;
#GetMapping("/vegetableList")
public String list(Model model) {
List<Vegetable> listVegetables = vegetableService.list();
model.addAttribute("vegetables", listVegetables);
return "index";
}
}
VegetableServiceImpl.java
package com.garden.garden.service.impl;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.garden.garden.model.Vegetable;
import com.garden.garden.repository.VegetableRepository;
import com.garden.garden.service.VegetableService;
#Service
public class VegetableServiceImpl implements VegetableService {
#Autowired
private VegetableRepository vegetableRepository;
#Override
public List<Vegetable> list() {
return (List<Vegetable>) vegetableRepository.findAll();
}
#Override
public Optional<Vegetable> listById(int id) {
// TODO Auto-generated method stub
return null;
}
#Override
public int save(Vegetable vegetable) {
// TODO Auto-generated method stub
return 0;
}
#Override
public void delete(int id) {
// TODO Auto-generated method stub
}
}
VegetableService.java
package com.garden.garden.service;
import java.util.List;
import java.util.Optional;
import com.garden.garden.model.Vegetable;
public interface VegetableService {
public List<Vegetable> list();
public Optional<Vegetable> listById(int id);
public int save(Vegetable vegetable);
public void delete(int id);
}
VegetableRepository.java
package com.garden.garden.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.garden.garden.model.Vegetable;
#Repository
public interface VegetableRepository extends JpaRepository<Vegetable, Integer> {
}
Vegetable.java
package com.garden.garden.model;
import java.math.BigDecimal;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "vegetable")
public class Vegetable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
private String family;
private int daysOnNursery;
private int daysToGrow;
private int daysHarvesting;
private java.math.BigDecimal plantsPerSquare;
private java.math.BigDecimal price;
private java.math.BigDecimal weight;
public Vegetable(int id, String name, String family, int daysOnNursery, int daysToGrow, int daysHarvesting,
BigDecimal plantsPerSquare, BigDecimal price, BigDecimal weight) {
super();
this.id = id;
this.name = name;
this.family = family;
this.daysOnNursery = daysOnNursery;
this.daysToGrow = daysToGrow;
this.daysHarvesting = daysHarvesting;
this.plantsPerSquare = plantsPerSquare;
this.price = price;
this.weight = weight;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getFamily() {
return family;
}
public void setFamily(String family) {
this.family = family;
}
public int getDaysOnNursery() {
return daysOnNursery;
}
public void setDaysOnNursery(int daysOnNursery) {
this.daysOnNursery = daysOnNursery;
}
public int getDaysToGrow() {
return daysToGrow;
}
public void setDaysToGrow(int daysToGrow) {
this.daysToGrow = daysToGrow;
}
public int getDaysHarvesting() {
return daysHarvesting;
}
public void setDaysHarvesting(int daysHarvesting) {
this.daysHarvesting = daysHarvesting;
}
public java.math.BigDecimal getPlantsPerSquare() {
return plantsPerSquare;
}
public void setPlantsPerSquare(java.math.BigDecimal plantsPerSquare) {
this.plantsPerSquare = plantsPerSquare;
}
public java.math.BigDecimal getPrice() {
return price;
}
public void setPrice(java.math.BigDecimal price) {
this.price = price;
}
public java.math.BigDecimal getWeight() {
return weight;
}
public void setWeight(java.math.BigDecimal weight) {
this.weight = weight;
}
}
I also try to solve the problem adding this dependency:
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.garden</groupId>
<artifactId>garden</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>garden</name>
<description>Market garden web application</description>
<properties>
<java.version>14</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.properties
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
spring.datasource.url=jdbc:mysql://localhost:3306/garden
spring.datasource.username=root
spring.datasource.password=admin
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.hibernate.ddl-auto=create
Please remove the exclusion of the auto configuration in your application.properties and add an hibernate-dialect, i.e. update your application.properties as follows:
spring.datasource.url=jdbc:mysql://localhost:3306/garden
spring.datasource.username=root
spring.datasource.password=admin
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.hibernate.ddl-auto=create
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
In addition you can simplify GardenApplication to
package com.garden.garden;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
#SpringBootApplication
#EnableJpaRepositories
#EntityScan
public class GardenApplication {
public static void main(String[] args) {
SpringApplication.run(GardenApplication.class, args);
}
}
and remove tomcat dependency from your pom (it comes in transitively with spring-boot-starter-web).
Besides, having lombok in your dependencies, you can annotate Vegetable with #Data and remove Getters, Setters and the constructor.

Need Help! Spring Boot error: Unsatisfied DependancyException: Error creating bean with name ''

I can not figure out this error:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'restapiApplication': Unsatisfied dependency expressed through method 'productRepository' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'productRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Failed to create query for method public abstract com.murphy.demo.model.Product com.murphy.demo.repository.ProductRepository.findOne(java.lang.String)! No property findOne found for type Product!
Here is my Repository in package:
package com.murphy.demo.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import com.murphy.demo.model.Product;
#Repository
public interface ProductRepository extends JpaRepository<Product,String> {
Product findOne(String id);
}
package com.murphy.demo.Controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.murphy.demo.model.Product;
import com.murphy.demo.repository.ProductRepository;
#RestController
#RequestMapping(path ="/api/products/" )
public class ProductsController {
private ProductRepository productRepository;
#Autowired
public void productRepository(ProductRepository productRepository) {
this.productRepository = productRepository;
}
#RequestMapping(path ="{id}", method = RequestMethod.GET)
public Product getProduct(#PathVariable(name = "id") String id) {
return productRepository.findOne(id);
}
}
Product.java in package
package com.murphy.demo.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import org.hibernate.annotations.GenericGenerator;
#Entity
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator ="system-uuid")
#GenericGenerator(name ="system-uuid",strategy ="uuid")
private String id;
private String name;
private String description;
private String category;
private String type;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
main application:
package com.murphy.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import com.murphy.demo.model.Product;
import com.murphy.demo.repository.ProductRepository;
#SpringBootApplication
public class RestapiApplication implements CommandLineRunner{
private ProductRepository productRepository;
#Autowired
public void productRepository(ProductRepository productRepository) {
this.productRepository = productRepository;
}
public static void main(String[] args) {
SpringApplication.run(RestapiApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
Product test = new Product();
test.setName("test");
test.setDescription("test");
test.setCategory("general");
test.setType("null");
productRepository.save(test);
}
}
Pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.murphy.demo</groupId>
<artifactId>restapi</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>restapi</name>
<description> project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Application.properites is as follows:
spring.h2.console.enabled=true
spring.datasource.url=jdbc:h2:file:~/Products;IFEXISTS=FALSE;DB_CLOSE_DELAY=-1
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.path=/h2-console
spring.jpa.show-sql= true
Ive tried everything I can think of, Any suggestions at all will be helpful.
Thanks!
By naming your method "findOne" the Spring Data JPA is trying to create a query to search by for the property "findOne" in your Product Class, which doesn't exist, hence the error "No property findOne found for type Product". You should specify the name of the property you are searching for. In your case: findOneById (String id) will create a query to find one object by the Id property.
For more information on how to name your methods to create the correct queries you can read the documentation about this topic.
Why don't you use CrudRepository instead of JpaRepository? findOne(id) will be automatically available. That way your repository interface whould just be empty.
https://docs.spring.io/spring-data/data-commons/docs/1.6.1.RELEASE/reference/html/repositories.html

spring boot data jpa mysql could not create database

I am new in spring
I will post my code,
that the application.properties
spring.datasource.url=jdbc:mysql://localhost/spring
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
spring.jpa.hibernate.ddl-auto=update
and this my entity
package model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
private String phone;
private String adresse;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getAdresse() {
return adresse;
}
public void setAdresse(String adresse) {
this.adresse = adresse;
}
public Person(long id, String name, String phone, String adresse) {
super();
this.id = id;
this.name = name;
this.phone = phone;
this.adresse = adresse;
}
public Person() {
super();
}
}
and this is the repository
package repositry;
import org.springframework.data.jpa.repository.JpaRepository;
import model.Person;
public interface PersonRespositry extends JpaRepository<Person, Long> {
}
and my controller
package contoller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import model.Person;
import repositry.PersonRespositry;
#RestController
public class PersonController {
PersonRespositry rp;
#Autowired
public PersonController(PersonRespositry rp) {
// TODO Auto-generated constructor stub
this.rp=rp;
}
#RequestMapping("/find")
public Person find(long id){
return rp.findOne(id);
}
#RequestMapping("/findall")
public List<Person> findall(){
return rp.findAll();
}
#RequestMapping(value="/hello")
public String Demo(){
return "Hello world !!";
}
#RequestMapping(value="/create", method=RequestMethod.GET)
public String create(){
Person p=new Person();
p.setName("med");
p.setPhone("233888");
p.setAdresse("rue ");
rp.save(p);
return " success";
}
}
This is the architect of the project:
When I run the application the database does not generate and only the
localhost:8080 is running.
Your problem is the location of the Application.java.
#ComponentScanlooks for Spring beans inside the package of the class annotated with (#SpringBootApplication contains #ComponentScan) and in subpackages of this package.
I already provided an example to a very similar setup.
Please have a look here: https://stackoverflow.com/a/27983870/2576531
Furthermore the hint of Robert Moskal is correct. The database itself has to exist already. Only the tables will be created automatically.
If you want the data to be created you need to use create or create-drop. If you are using something like mysql you'll need to have created at least the database. The tables will be created for you.
I be very careful about doing this against a production database instance.
Otherwise for me it dosen't work with #componentScan but it works now with #EntityScan(basePackages = { "com.jwt.entites" }) in the main class to scan entity classes ..
This is not the answer but this is a sample. I think this will help you
//Pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.wisdom.spring.myjdbc</groupId>
<artifactId>spring_boot_jpa</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring_boot_jpa</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
//application Config
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost/wisdom
spring.datasource.username=root
spring.datasource.password=8855
spring.jpa.generate-ddl=true
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
server.port = 8585
package com.wisdom.spring.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.wisdom.spring.model.students;
import com.wisdom.spring.repo.students_repo;
#RestController
#RequestMapping("/students")
public class studentController {
#Autowired
students_repo STDRepo;
#GetMapping(value = "/a")
public String a() {
return "hello";
}
#GetMapping(value = "/save")
public List<students> getStudents(){
System.out.println("Data returned");
return STDRepo.findAll();
}
#PostMapping(value = "/savestd")
public void saveBurger(students student) {
STDRepo.save(student);
}
}
package com.wisdom.spring.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
#Entity
public class students {
#Id
#Column
private int s_id;
#Column
private String name;
#Column
private String address;
public students() {
}
public students(int s_id, String name, String address) {
this.s_id = s_id;
this.name = name;
this.address = address;
}
public int getS_id() {
return s_id;
}
public void setS_id(int s_id) {
this.s_id = s_id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
package com.wisdom.spring.repo;
import org.springframework.data.jpa.repository.JpaRepository;
import com.wisdom.spring.model.students;
public interface students_repo extends JpaRepository<students,String> {
}
package com.wisdom.spring;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class SpringBootJpaApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootJpaApplication.class, args);
}
}

Getting the error : Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException

I am new to spring and I wanted to communicate with mongodb via spring. I tried and tested the following code on SPRING TOOL SUITE but I am getting the following error:
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [hello.PersonRepository] is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:371)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:331)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:968)
at hello.Runhere.main(Runhere.java:19)
Kindly tell me where is the problem.
Here is Person.java class
package hello;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
#Document
public class Person {
#Id
private String personId;
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getPersonId() {
return personId;
}
public void setPersonId(final String personId) {
this.personId = personId;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(final int age) {
this.age = age;
}
#Override
public String toString() {
return "Person [id=" + personId + ", name=" + name + ", age=" + age
+ "]";
}
}
Here is my PersonRepository.java file
package hello;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Repository;
#Repository
public class PersonRepository {
#Autowired
MongoTemplate mongoTemplate;
public void countUnderAge() {
List<Person> results = null;
Query query = new Query();
Criteria criteria = new Criteria();
criteria = criteria.and("age").lte(21);
query.addCriteria(criteria);
results = mongoTemplate.find(query, Person.class);
System.out.println(results.size());
}
public void countAllPersons() {
List<Person> results = mongoTemplate.findAll(Person.class);
System.out.println("The total number of players " + results.size());
}
public void insertPersonWithNameAayushAndRandomAge() {
double age = Math.ceil(Math.random() * 100);
Person p = new Person("Aayush", (int) age);
mongoTemplate.insert(p);
}
public void createPersonCollection() {
if (!mongoTemplate.collectionExists(Person.class)) {
mongoTemplate.createCollection(Person.class);
}
}
public void dropPersonCollection() {
if (mongoTemplate.collectionExists(Person.class)) {
mongoTemplate.dropCollection(Person.class);
}
}
}
Here is my springconfig.java file:
package hello;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
import com.mongodb.Mongo;
#Configuration
#EnableMongoRepositories
#Import(RepositoryRestMvcConfiguration.class)
#EnableAutoConfiguration
public class springconfig extends AbstractMongoConfiguration {
#Override
protected String getDatabaseName() {
return "demo";
}
#SuppressWarnings("deprecation")
#Override
public Mongo mongo() throws Exception {
return new Mongo();
}
}
Here is my class which contains the main method :
package hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Runhere {
public static void main(String[] args) {
#SuppressWarnings("resource")
ApplicationContext context = new AnnotationConfigApplicationContext(springconfig.class);
PersonRepository personRepository = context.getBean(PersonRepository.class);
personRepository.dropPersonCollection();
personRepository.createPersonCollection();
for (int i = 0; i < 10000; i++) {
personRepository.insertPersonWithNameAayushAndRandomAge();
}
personRepository.countAllPersons();
personRepository.countUnderAge();
}
}
And finally here is my pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.test</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>integration_with_mongo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.1.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<start-class>demo.IntegrationWithMongoApplication</start-class>
<java.version>1.7</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-rest-repository</artifactId>
<version>1.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-rest-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.webflow</groupId>
<artifactId>spring-webflow</artifactId>
<version>2.4.1.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
try to add bean in the application config.xml
<mvc:resources mapping="" location="" />
<bean id="PersonRepository" class="(complete package path)hello.PersonRepository" />
SpringBoot - In hope it will help any SpringBoot developer
This error mostly hits when the bean you are calling from another package.
Specifically for Spring boot, you can try an annotation for it, to scan the component you want to get bean of it.
#ComponentScan("your package")
place the #Componentscan annotation in the main class where you are getting the bean.
Example
#ComponentScan("com.spring.crud.controller")
public class SpringCrudApplication {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(SpringCrudApplication.class, args);
HomeController bean1 = context.getBean(HomeController.class);
System.out.println(bean1.HomePage());
}
}
so, in the above example I am taking controller bean which I created in the package of com.spring.crud.controller
if you are interested in explanation see this article:
https://baidar-sabaoon.medium.com/how-to-handle-nosuchbeandefinitionexception-in-spring-boot-7255170d702c

Categories

Resources