Spring boot circular dependency issue when using gh-cache - spring-boot

I am using spring boot and i want to cache some data here is my entity and repository classes
Places entity class:
#Entity
#Table(name = "PLACE_MASTER")
#Getter
#Setter
#NoArgsConstructor
#EqualsAndHashCode(callSuper = true)
#Component
public class PlaceMaster extends BaseEntity{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "PLACE_MASTER_ID")
#JsonView(View.Place.class)
private long placeMasterId;
#Column(name = "PLACE_NAME")
#JsonView(View.Place.class)
private String placeName;
#Column(name = "ALT_PLACE_NAME")
private String alternatePlaceName;
#Column(name = "PINCODE")
private String pinCode;
#Column(name="DISTRICT_NAME")
private String districtName;
#ManyToOne (cascade = CascadeType.ALL)
#JoinColumn(name = "STATE_MASTER_ID")
private StateMaster stateMaster;
}
state entity class:
#Entity
#Table(name = "STATE_MASTER")
#Getter
#Setter
#NoArgsConstructor
#EqualsAndHashCode(callSuper = true)
//#ToString
public class StateMaster extends BaseEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "STATE_MASTER_ID")
private long stateMasterId;
#Column(name = "STATE_NAME")
private String stateName;
#Column(name = "STATE_CODE")
private String stateCode;
#OneToMany(mappedBy = "stateMaster", cascade = CascadeType.ALL)
private List<PlaceMaster> placeMaster = new ArrayList<PlaceMaster>();
}
public interface PlaceMasterRepository extends JpaRepository<PlaceMaster, Long> {
#Override
#Cacheable("places")
public List<PlaceMaster> findAll();
}
bootstrap application class:
#SpringBootApplication
#EnableCaching
#EnableAsync
#EnableTransactionManagement
public class myApplication {
#Autowired
private PlaceMasterRepository placeMasterRepository;
public static void main(String[] args) throws Throwable {
SpringApplication.run(GoyaanaApplication.class, args);
}
}
when i run the the spring boot application i am getting the below error. Is it due to biderectional dependency. Please help
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'entityManagerFactory': Requested bean is currently in creation: Is there an unresolvable circular reference?
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:347)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351)

It is generally best to avoid circular dependencies between your bean, e.g. by moving #EnableCaching, #EnableAsync, #EnableTransactionManagement to separate #Configuration class.
In cases where it is not possible, you can get around this by adding a #Lazy annotation on the #Autowired bean. This will create a lazy proxy that will get resolved at runtime. This comes with a caveat - you can't be sure at the start of the application if it is wired up correctly.
#Lazy
#Autowired
private PlaceMasterRepository placeMasterRepository;
For details see Spring documentation.

Related

Consider defining a bean of type 'int' in your configuration[SpringBoot]

its my first time crating api in spring boot, i'm trying to create transaction api. when i'm running the application i'm getting this error
Description:
Parameter 0 of constructor in TransactionService.transactionService.modal.TransactionRequest required a bean of type 'int' that could not be found.
Action:
Consider defining a bean of type 'int' in your configuration.
Modal package:
TransactionEntity
#Getter
#Setter
#Builder
#Entity
public class TransactionEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int transactionId;
#NotNull
#Column(unique = true)
private UUID externalId;
#NotNull
private int userId;
#NotNull
private int merchantId;
#NotNull
private int clientReferenceId;
#NotNull
private double amount;
#Enumerated(EnumType.STRING)
#NotNull
private TransactionStatus status;
#NotNull
private String createdBy;
private String updatedBy;
#NotNull
private LocalDateTime createdAt;
#NotNull
private LocalDateTime updatedAt;
}
TransactionRequest
#Component
#Data
#Builder
public class TransactionRequest {
private int userId;
private int merchantId;
private int clientReferenceId;
private double amount;
private String createdBy;
}
TransactionResponse
#Component
#Data
#Builder
public class TransactionResponse {
private int userId;
private int merchantId;
private int clientReferenceId;
private double amount;
private LocalDateTime createdAt;
private TransactionStatus status;
}
TransactionDao
#Component
// Dao class
public class TransactionDao {
#Autowired
TransactionRepository transactionRepository;
TransactionEntity transactionEntity;
public TransactionResponse createTransaction(TransactionRequest transactionRequest){
LocalDateTime cuurentTime = LocalDateTime.now();
transactionEntity.builder().userId(transactionRequest.getUserId())
.merchantId(transactionRequest.getMerchantId())
.clientReferenceId(transactionRequest.getClientReferenceId())
.amount(transactionRequest.getAmount())
.createdBy(transactionRequest.getCreatedBy())
.createdAt(cuurentTime)
.updatedAt(cuurentTime)
.externalId(UUID.randomUUID())
.status(TransactionStatus.CREATED);
transactionRepository.save(transactionEntity);
return TransactionResponse.builder().status(transactionEntity.getStatus())
.createdAt(transactionEntity.getCreatedAt()).build();
}
}
TransactionService
#Service
public class TransactoinService {
#Autowired
public TransactionDao transactionDao;
public TransactionResponse createTransaction(TransactionRequest transactionRequest){
return transactionDao.createTransaction(transactionRequest);
}
}
TransactionController
#RestController
public class TransactionController {
#Autowired
TransactoinService transactoinService;
#PostMapping
TransactionResponse createTransaction(#RequestBody TransactionRequest transactionRequest){
return transactoinService.createTransaction(transactionRequest);
}
}
The TransactionRequest is annotated as #Component so spring boot autoscan will try to create a #Bean out that class.
It is also annotated with #Data so at the time of creating the bean Spring boot is trying to inject other beans as arguments into the all args constructor, and it is not finding an "int" bean to inject into the constructor.
I am guessing that the transaction response should not be a #Component or at least not a Singleton bean.
You should not create your POJO classes as a Spring Bean. Remove #Component annotation in your TransactionRequest and TransactionResponse POJO classes.

Spring data JPA: embedded ID error when saving the entity

I have the following entity classes:
#Embeddable
#Getter
#Setter
public class OrganizationCyclePlageKey implements Serializable {
#Column(name = "organization_id")
Long organizationId;
#Column(name = "cycle_plages_id")
Long cyclePlagesId;
...
equals() and hashCode() methods come here
#Entity
#Table(name = "organization_cycle_plages")
#Getter
#Setter
public class OrganizationCyclePlage {
#EmbeddedId
private OrganizationCyclePlageKey id;
#ManyToOne
#MapsId("organizationId")
#JoinColumn(name = "organization_id")
Organization organization;
#ManyToOne
#MapsId("cyclePlagesId")
#JoinColumn(name = "cycle_plages_id")
CyclePlage cyclePlage;
...
other attributes
}
#Entity
#Getter
#Setter
public class CyclePlage extends AbstractEntity {
#OneToMany(mappedBy = "cyclePlage")
private Set<OrganizationCyclePlage> organizationCyclePlages;
...
}
#Entity
#DynamicUpdate
#Getter
#Setter
public class Organization extends AbstractEntity {
#OneToMany(mappedBy = "organization")
private Set<OrganizationCyclePlage> organizationCyclePlages = new HashSet<>();
...
}
SpringBoot app starts up normally without errors.
But when I try to save an instance of OrganizationCyclePlage:
OrganizationCyclePlage ocp = new OrganizationCyclePlage();
ocp.setOrganization(organization);
ocp.setCyclePlage(cyclePlage);
organizationCyclePlageRepository.save(ocp);
it raises the error when calling organizationCyclePlageRepository.save(ocp):
org.hibernate.PropertyAccessException: Could not set field value [361] value by reflection : [class com.XXXX.OrganizationCyclePlageKey.cyclePlagesId] setter of com.XXXX.OrganizationCyclePlageKey.cyclePlagesId
What's wrong with these relations?
I had to add the constructor into the OrganizationCyclePlageKey class to init the foreign keys values as well a default constructor via #NoArgsConstructor annotation:
public OrganizationCyclePlageKey(Long organizationId, Long cyclePlagesId) {
this.organizationId = organizationId;
this.cyclePlagesId = cyclePlagesId;
}
and init the OrganizationCyclePlageKey instance in the OrganizationCyclePlage class:
public class OrganizationCyclePlage {
private OrganizationCyclePlageKey id = new OrganizationCyclePlageKey();
...
}

Embeddable is creating 2 tables jpa springs

I have below entites
AbstractOrderEntry :
#Getter #Setter
public class AbstractOrderEntry implements Serializable
{
#ElementCollection
private List<DiscountValue> discountValues = new ArrayList<>();}
}
CartEntry extending AbstractOrderEntry
#Entity
#EntityListeners(value = AuditListener.class)
#Table(name = "cartentry")
#Getter #Setter
public class CartEntry extends AbstractOrderEntry implements Serializable,Cloneable,Auditable
{
#Id
#Column(name="CartEntryID",nullable = false)
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
}
DiscountValueEntity:
#Embeddable
#Getter #Setter
public class DiscountValue {
private String code;
private BigDecimal value;
private BigDecimal appliedValue;
}
When I start the server it is generating to tables like
cart_discountValue
cart_discountvalue
one with camelcase and other is with lowercase.
We are also extending AbstractOrderEntry for order entity as well hence for order also 2 tables are getting created.
How can overcome this issue.Because of this issue table data is not properly persisting.
Thanks , Inadvance.
Sree

POJO classes has a spring component

How do I make my pojo classes as components, so that I can autowire wherever I want? What will be the steps to do? Is this the right way for a spring boot application?
In my application iam using lombok for getters and setters. Here is my pojo:
#Accessors(chain = true)
#NoArgsConstructor
#Getter
#Setter
#ToString
#JsonIgnoreProperties(ignoreUnknown = true)
#SuppressWarnings("all")
public class Qei implements Serializable {
private static final long serialVersionUID = 2902444063726917000L;
private Integer qeiMasterId;
private String qeiId;
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = NMTCConstants.DATEFORMAT)
private Date originalDate;
private BigDecimal amount;
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = NMTCConstants.DATEFORMAT)
private Date complianceEndDate;
private BigDecimal perAllocAgreementPercent;
private BigDecimal minRequiredPercent;
private Integer allocationYear;
private DealDetail dealDetail;// other class
private List<Qlici> qliciInfo;//other class
}
In order to use this class, can it be spring component?

Spring Data JPA repository findAll() method returns null List

I am using Spring Data JPA:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.7.1.RELEASE</version>
</dependency>
with Spring 4.3.7.RELEASE and Hibernate 5.2.9.Final.
When I query using findAll, the List returns contains null values.
Entity:
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#EqualsAndHashCode
#Entity
public class Etudiant implements Serializable {
/**
* Serial version UID
*/
private static final long serialVersionUID = -1982480763983112005L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "idEtudiant")
private Integer idEtudiant;
#Column(name = "nomEtudiant")
private String nomEtudiant;
#Column(name = "prenomEtudiant")
private String prenomEtudiant;
#Column(name = "adresse")
private String adresse;
#Column(name = "dateNaissance")
private Date dateNaissance;
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "etudiant_cours", joinColumns = #JoinColumn(name = "idEtudiant", referencedColumnName = "idEtudiant"), inverseJoinColumns =
#JoinColumn(name = "idCours", referencedColumnName = "idCours"))
private List<Cours> cours;
}
NB: Note that the problem is not from lombock, I had tested with getters and setters.
Repository:
#Repository
public interface EtudiantRepository extends JpaRepository<Etudiant, Integer> {
}
Service:
#Service
public class EtudiantServiceImpl {
#Autowired
EtudiantRepository etudiantRepository;
List<Etudiant> lst = new ArrayList<Etudiant>();
public List<Etudiant> getAllEtudiant() {
lst = this.etudiantRepository.findAll();
return lst;
}
}
In debug screenshot, it can be seen that etudiantRepository is null.
Maybe you are missing #EnableJpaRepositories annotation in your Configuration.
EtudiantServiceImpl is being instantiated using Dependency Injection or with the new keyword?
Finally I found the solution :
change spring version from 4.3.7.RELEASE to 4.3.10.RELEASE
you need to use context:component-scan annotation into xml configuration for scanning base package and repository package, you can find code below :
<jpa:repositories base-package="com.demo.test.repository" />
<context:component-scan annotation-config="true"
base-package="com.demo.test" />
and if findall() return null value that means table dose not having data, it is normal behavior.
and also check your datasource and entity manager connection

Resources