UnsatisfiedDependencyException, Error creating bean with name - spring-boot

when I'm trying to start the application I get the following message:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'productServiceImpl' defined in file
[C:\Users\Acasa\0 SDA\0 Proiecte
practice\attentive2details\target\classes\com\example\attentive2details\Service\ProductServiceImpl.class]:
Unsatisfied dependency expressed through constructor parameter 0;
nested exception is
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'productRepository' defined in
com.example.attentive2details.repositories.ProductRepository defined
in #EnableJpaRepositories declared on
JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration:
Invocation of init method failed; nested exception is
org.springframework.data.repository.query.QueryCreationException:
Could not create query for public abstract java.util.List
com.example.attentive2details.repositories.ProductRepository.findByNameStartingWith(java.util.List)!
No property name found for type Produs!
This is happening since I have added a new method List<Produs> findByNameStartingWith(List<Produs> string) into the ProductRepository.
The application code is:
#Data
#Table
#Entity
#AllArgsConstructor
#NoArgsConstructor
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column
private String produs;
#Column
private Float calories;
}
#Repository
public interface ProductRepository extends JpaRepository<Product, Integer> {
List<Product> findByNameStartingWith(List<Product> string);
}
public interface ProductService {
List<Product> findByNameStartingWith(List<Product> string);
}
#Service
public class ProductServiceImpl implements ProductService {
ProductRepository productRepository;
public ProductServiceImpl(ProductRepository productRepository) {
this.productRepository = productRepository;
}
#Override
public List<Product> findByNameStartingWith(List<Product> string) {
return productRepository.findByNameStartingWith(string);
}
}
#RequestMapping("/api")
#RestController
public class ProductController {
private final ProductService productService;
public ProductController(ProductService productService) {
this.productService = productService;
}
#GetMapping("findProductbyNameStartingWith/produs")
#Query("FROM Product p WHERE p.produs LIKE %:name%")
public List<Product> findProductsbyNameStartingWith(#Param("name") String beginswith) {
List<Product> allproducts = new ArrayList<>( productService.findAll());
List<Product> productsListBeginWith = new ArrayList<>();
for (Product product : allproducts) {
if(product.getProdus().startsWith(String.valueOf(beginswith))){
productsListBeginWith.add(product);
}
}
return productService.findByNameStartingWith(productsListBeginWith);
}
}
the application structure

As your log mention
com.example.attentive2details.repositories.ProductRepository.findByNameStartingWith(java.util.List)!
No property name found for type Produs!
You wrote findByNameStartingWith but you don't have name field in your model. Jpa couldn't find this property in your entity class. You should put the name property in your model or change the query to another field for example findByProdusStartingWith or findByCaloriesStartingWith.

In addition to #Faramarz Afzali answer (which is actually correct), please note that the following #Query have no effect:
#RequestMapping("/api")
#RestController
public class ProductController {
(...)
#GetMapping("findProductbyNameStartingWith/produs")
#Query("FROM Product p WHERE p.produs LIKE %:name%")
public List<Product> findProductsbyNameStartingWith(#Param("name") String beginswith)
(...)
}
#Query must be used in Repository methods, not on a Controller or Service.

Related

Instructing Sping Data MongoDB to use correct mapping between ObjectId and its class

I cannot retrieve the 2nd level nested objects in Spring Data MongoDB
I have nested collection in MongoDB to retrieve with Spring. Imagine this schema
#Data
#Builder
#Document(collection = "emitted")
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Emitter{
#Id
private String id;
#Field("installation")
#DocumentReference(lazy = true)
private Installaton installation;
// other fields
#Data
#Builder
#Document(collection = "installation")
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Installation {
#Id
private String id;
#Field("subject")
#DocumentReference(lazy = true)
private Subject subject;
// other fields
#Data
#Builder
#Document(collection = "subject")
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Subject {
#Id
private String id;
// other fields
Plus, I have MapStruct to map nested object field to string, for the purpose of avoiding cyclic reference introducing the search by id of the collection:
#ObjectFactory
public <T> T map(#NonNull final String id, #TargetType Class<T> type) {
return mongoTemplate.findById(id, type);
}
Everything works at first level, but at nested level I have this error:
Caused by: org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [org.bson.types.ObjectId] to type [com.package.collections.Subject]
at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:322)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:195)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:175)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.doConvert(MappingMongoConverter.java:1826)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.doConvert(MappingMongoConverter.java:1818)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.getPotentiallyConvertedSimpleRead(MappingMongoConverter.java:1337)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.getPotentiallyConvertedSimpleRead(MappingMongoConverter.java:1311)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter$DefaultConversionContext.convert(MappingMongoConverter.java:2371)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter$ConversionContext.convert(MappingMongoConverter.java:2174)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter$MongoDbPropertyValueProvider.getPropertyValue(MappingMongoConverter.java:1936)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.readProperties(MappingMongoConverter.java:638)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.populateProperties(MappingMongoConverter.java:549)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:527)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.readDocument(MappingMongoConverter.java:491)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:427)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:423)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:120)
at org.springframework.data.mongodb.core.MongoTemplate$ReadDocumentCallback.doWith(MongoTemplate.java:3326)
at org.springframework.data.mongodb.core.MongoTemplate.executeFindOneInternal(MongoTemplate.java:2940)
at org.springframework.data.mongodb.core.MongoTemplate.doFindOne(MongoTemplate.java:2618)
at org.springframework.data.mongodb.core.MongoTemplate.doFindOne(MongoTemplate.java:2588)
at org.springframework.data.mongodb.core.MongoTemplate.findById(MongoTemplate.java:922)
at com.package.myapp.services.mapper.ReferenceMapper.map(ReferenceMapper.java:26)
at com.package.myapp.services.mapper.InstallationMapperImpl.toEntity(InstallationMapperImpl.java:102)
When asking the conversion, the findById works correctly and retrieve the object and the nested one. It fails when the request is for 2nd level nested object, where the ObjectId is retrieved but cannot be converted and fails.
I'm answering myself because I found a solution suited for my problem.
I only needed the entity object with the id, so I wrote a converter:
public class ObjectIdToSubjectConverter implements Converter<ObjectId, Subject> {
#Override
public Subject convert(ObjectId source) {
return Subject.builder().id(source.toString()).build();
}
}
And register it as a bean:
#Configuration
public class MongoConfig {
#Bean
public MongoCustomConversions mongoCustomConversions() {
return new MongoCustomConversions(Collections.singletonList(new ObjectIdToSubjectConverter());
}
}

How to do a Findby In Springboot Mongo repository for Nested Objects

Need your help here in a Spring Data CrudRepository on how to do a findby of nested fields.
My class is of following structure and I need to query using truckId which is of the nested objects
#Document(collection = "unt-truck")
public class TruckModelDTO {
private String type;
private TestDTO testDTO;
}
Class TestDTO.java
public class TestDTO{
private TruckDTO truckDTO;
Private String version;
}
Class TruckDTO.java
public class TruckDTO {
private String truckId;
private String legacySystem;
}
Class TruckRepository.java
#Repository
public interface TruckRepository extends MongoRepository<TruckModelDTO, String> {
// TruckModelDTO findByTruckId(String truckid);
}
So how should I use findby for truckId which is inside a nested class?
You can use with either Entity or DTO as response. but you have to mention the relation between two or three Entity based on you requirement.
I have created Entity. you have to create DTO with same based on entity then apply main DTO as return type in JPA Repository query.
1.Entity
#Entity
public class TruckModel {
private String type;
// mention the relation based on your requirement
private Test test;
}
Entity
#Entity
public class Test {
// here mention the relation based on you requirement
private Truck truck;
Private String version;
}
3.Entity
#Entity
public class Truck {
private String truckId;
private String legacySystem;
}
Repository
#Repository
public interface TruckModelRepository extends MongoRepository<TruckModel, String> {
TruckModelDTO findByTestTruckTruckId(String truckid);
}

Spring Jpa Specification unable to locate attribute in sub classes

so I have following hierarchy of entities:
#MappedSuperClass
public abstract class BaseEntity {
private Long id;
private Date createAt;
private Date updateAt;
}
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Post extends BaseEntity {
private String creatorId;
private String title;
private String content;
}
#Entity
public class Article extends Post {
private String category; // article has category
}
#Entity
public class Journal extends Post {
private Date expiration; // journal has expiration
}
now when I use Spring Jpa Specification to query for articles with certain category, it won't work:
// define specification
public class ArticleSpecifications {
public static Specification<Article> withCategory(String category) {
(root, query, criteriaBuilder) ->
criteriaBuilder.equal(root.get("category"), category)
}
}
// repository
public interface PostRepository<T extends Post> extends JpaRepository<T, Long>, JpaSpecificationExecutor<T> { ... }
// usage: in some service class
#Autowired
private PostRepository<Article> articleRepository;
...
public void someMethod {
...
// error here
articleRepository.findAll(ArticleSpecifications.withCategory("news"), pageable);
...
}
Error message:
java.lang.IllegalArgumentException: Unable to locate Attribute with the the given name [category] on this ManagedType [com.gladdev.galahad.base.BaseEntity]
Just trying to understand here why it tries to look up "category" in BaseEntity.
Every Specification accessing attributes defined in Post works just fine.
Is it some spring jpa specification bug or I missed something?
You can use the CriteriaBuilder.treat() method.
In Criteria API, downcasting an entity to a subclass entity can be performed by using one of the CriteriaBuilder.treat() methods:
See https://docs.oracle.com/javaee/7/api/javax/persistence/criteria/CriteriaBuilder.html#treat-javax.persistence.criteria.Root-java.lang.Class-
public static Specification<Article> withCategory(String category) {
return (root, query, criteriaBuilder) -> {
Root<Article> article = criteriaBuilder.treat(root, Article.class);
return criteriaBuilder.equal(article.get("category"), category);
};
}

Multiple JPA Repositories with multiple Entity Mapping conflict

I am creating a simple one to many relationship using JPA and Spring Data Rest. But i am getting this error
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'designationRepository' defined in com.example.relational.BootRelations.repository.DesignationRepository defined in #EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Cannot resolve reference to bean 'jpaMappingContext' while setting bean property 'mappingContext'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaMappingContext': Invocation of init method failed; nested exception is org.hibernate.AnnotationException: No identifier specified for entity: com.example.relational.BootRelations.models.Designation
That is because I have #Entity classes like Designation and Employee, the code follows like:
#Entity
public class Designation {
private String Designation;
private float Salary;
#OneToMany(targetEntity=Employee.class, mappedBy="designation", fetch=FetchType.LAZY, cascade=CascadeType.ALL)
#JoinColumn(name="Emp_Id")
private Set<Employee> employee;
// Getter & Setter and Constructors
}
Now Employee class:
#Entity
#Table(name="Employee")
public class Employee {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="Emp_Id")
private int Emp_Id;
#Column(name="Emp_Name")
private String Emp_Name;
#Column(name="Emp_Email")
private String Emp_Email;
#OneToOne(targetEntity=Designation.class, mappedBy="employee", fetch=FetchType.LAZY, cascade=CascadeType.ALL)
private Designation designation;
// // Getter & Setter and Constructors
}
The repositories are:
public interface DesignationRepository extends JpaRepository<Designation, Integer> {}
public interface EmployeeRepository extends JpaRepository<Employee, Integer> {}
Services:
#Service
public class DesignationServiceImpl implements DesignationService {
private DesignationRepository designationRepository;
#Autowired
public DesignationServiceImpl(DesignationRepository designationRepository) {
this.designationRepository = designationRepository;
}
#Override
public List<Designation> findAllDesignation() {
return designationRepository.findAll();
}
}
public class EmployeeServiceImpl implements EmployeeService {
private EmployeeRepository employeeRepository;
#Autowired
public EmployeeServiceImpl(#Qualifier("employeeJPAImpl") EmployeeRepository employeeRepository) {
this.employeeRepository = employeeRepository;
}
}
#Service
public class DesignationServiceImpl implements DesignationService {
private DesignationRepository designationRepository;
#Autowired
public DesignationServiceImpl(#Qualifier("DesignationRepository") DesignationRepository designationRepository) {
this.designationRepository = designationRepository;
}
#Override
public List<Designation> findAllDesignation() {
return designationRepository.findAll();
}
}
As I had two entities I had two controllers:
#RestController
#RequestMapping("/api")
public class DesignationController {
private DesignationService designationService;
#Autowired
public DesignationController(DesignationService designationService) {
this.designationService = designationService;
}
#GetMapping("/designation")
public List<Designation> getAllDesignation(){
return designationService.findAllDesignation();
}
}
and
#RestController
#RequestMapping("/api")
public class EmployeeController {
private EmployeeService employeeService;
#Autowired
public EmployeeController(EmployeeService employeeService) {
this.employeeService = employeeService;
}
// Mappings
}
Can anyone help me solve this issue? Until I had one entity it was working fine; as soon as I added another one it failed to start, with the error. Please help me fix the issue.
In Employee class make this changes.
#Entity
#Table
public class Employee {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column
private Long empId;
#Column
private String Name;
#Column
private String Email;
#OneToMany(targetEntity=Designation.class, fetch=FetchType.LAZY, cascade=CascadeType.ALL)
private Designation designation;
// // Getter & Setter and Constructors
}
In the Designation class, make this changes..
#Entity
public class Designation {
#Id
private Long id;
private String role;
private float salary;
#ManyToOne(targetEntity=Employee.class, fetch=FetchType.LAZY, cascade=CascadeType.ALL)
#JoinColumn
private Set<Employee> employee;
// Getter & Setter and Constructors
}
This will result in a table structure like this.
Employee
EMP_ID
NAME
EMAIL
Designation
ID
ROLE
SALARY
EMPLOYEE_ID
In OneToMany and ManyToOne association, we must keep a note that, which class is holding the Many side. That side is known as the owning side. As that class will contain the foreign key. Here, our designation class is containing the Many side. So, it will create a foreign key automatically.
If we give the #JoinColumn in the Employee class. Still we will get the Designation class as the Owning class.
You can refer this article, for more details.
Rather than this, let me tell you some of your major mistakes.
Do not give the variables name same as your class name.
By writing variables name as empId in java file, it will result EMP_ID in database.
If a column name or a table name is same your variable name, you can avoid re-mentioning it.
means, if my entity class name is Employee. And I want my database Table name should also be EMPLOYEE. I can avoid specifying #Table(name="EMPLOYEE").
I hope it would be helpful !!

Spring: Method Injection Lookup How to use it?

Can I use Method Injection Lookup -- with a entity class?.I use Spring+JPA+Hibernate. This allow to inject a prototype bean into a singleton bean.Is this also possible with entity beans?A is prototype scoped bean.I want to put A(#Entity) into a class B (ex. DAO) with scope=singleton.Thanks
#Entity
public class A(){
private String name;
private String surname;
...//get and set
}//A
public interface DAO{
public void method();
}//DAO
public class DAOImpl implements DAO{
private A object_a;
public void method(){
//In this method I use everytime a new istance of A
}//method
}//DAOImpl
You can use #Embedded to include your sub bean, and use in your sql.
#Entity
public class User(){
private String name;
#Embedded
private Address address;
#Bean(scope=DefaultScopes.PROTOTYPE)
public User() {
}
...//get and set
}
#Entity
public class Address(){
private String name;
...//get and set
}
public interface UserRepository extends JpaRepository<User, Long> {
#Query(value = "select u from users u where u.address.name = :addressName")
List<Blog> findUserByAddress(#Param("addressName") String addressName);
}

Resources