Cannot map nested #Data with MapStruct - spring-boot

When trying to map nested Object using #Data and #Builder, mapStruct throw the following errors: "No read accessor found for property "profile" in target type."
#Mapper(componentModel = "spring")
public interface AuthMapper {
// only for testing mapping is working
#Mapping(target = "profile.organization", source = "organization")
RequestCreateOktaUser toEntity(Integer organization);
// only for testing mapping is working
#Mapping(target = "profile.login", source = "request.profile.email")
RequestCreateOktaUser toEntity(RequestMobilePreRegisterLocation.User request);
// Throw error "No read accessor found for property "profile" in target type" at compile time
#Mapping(target = "profile.organization", source = "organization")
#Mapping(target = "profile.login", source = "request.profile.email")
RequestCreateOktaUser toEntity(RequestMobilePreRegisterLocation.User request, Integer organization);
}
Model using Lombok simplified for simplicity
#Data
#NoArgsConstructor
#AllArgsConstructor(access = AccessLevel.PRIVATE)
#Builder
public class RequestCreateOktaUser {
private Profile profile;
#Data
#NoArgsConstructor
#AllArgsConstructor(access = AccessLevel.PRIVATE)
#Builder
public static class Profile {
private String login;
private String email;
private Integer organization;
}
}
#Data
#NoArgsConstructor
#AllArgsConstructor(access = AccessLevel.PRIVATE)
#Builder
public class RequestMobilePreRegisterUser {
#Valid
private User user;
#Data
#NoArgsConstructor
#AllArgsConstructor(access = AccessLevel.PRIVATE)
#Builder
public static class User {
#Valid
private Profile profile;
#Data
#NoArgsConstructor
#AllArgsConstructor(access = AccessLevel.PRIVATE)
#Builder
public static class Profile {
#NotEmpty
#Email
private String email;
}
}
The two first Mapping are working as expected, but when trying to combine the two the following errors is being thrown at compile time "No read accessor found for property "profile" in target type."
If someone could help me on this one I would really appreciate.
Thanks a lot,
Jonathan.

solution:
#Mapper(componentModel = "spring", builder = #Builder(disableBuilder = true))

Related

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

How to solve org.springframework.core.convert.ConversionFailedException while fetching the data from DB using spring data jpa

Domain Classes
#Data
#NoArgsConstructor
#AllArgsConstructor
#Entity
#Table(name = "SAMPLE_DATA")
#TypeDefs({
#TypeDef(name = "json", typeClass = JsonStringType.class),
#TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
})
public class Sample implements Serializable {
private static final long serialVersionUID = 1719868663566734198L;
#Id
private Long Id;
#Type(type = "json")
#Column(columnDefinition = "json",name = "person")
private Person personObj;
private String sampledata;
private String createdBy;
}
#Data
#NoArgsConstructor
#AllArgsConstructor
public class Person implements Serializable {
private static final long serialVersionUID = -5427425033242474312L;
private String firstName;
private String lastName;
}
Repository Class
#Repository
public interface SampleRepository extends JpaRepository<Sample, Long> {
#Query(value = "select s.personObj,s.sampledata from Sample s where s.Id=:Id")
List<Sample> findPersonById(Long Id);
}
To map to map JSON object types i m using
<dependency>
<groupId>com.vladmihalcea</groupId>
<artifactId>hibernate-types-52</artifactId>
<version>${hibernate-types.version}</version>
</dependency>
when I am trying to fetch the list of Sample object I am getting the following exception
org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.Object[]] to type [#org.springframework.data.jpa.repository.Query com.domain.Sample] for value '[Person(firstName=abc, lastName=test)]'; nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [com.domain.Person] to type [#org.springframework.data.jpa.repository.Query com.domain.Sample]
.........
Caused by: org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [com.domain.Person] to type [#org.springframework.data.jpa.repository.Query com.domain.Sample]
You don't have to select the distinct columns. You must select the Entity:
#Repository
public interface SampleRepository extends JpaRepository<Sample, Long> {
#Query(value = "select s from Sample s where s.Id=:Id")
List<Sample> findPersonById(Long Id);
}

LOMBOK default field value doesn't work with ORIKA-MAPPER

My contract class
#JsonIgnoreProperties(ignoreUnknown = true)
#Data
#Builder
#NoArgsConstructor
#AllArgsConstructor
public class PaginationRequest {
private String sortBy;
}
My service class
#JsonIgnoreProperties(ignoreUnknown = true)
#Data
#Builder
#NoArgsConstructor
#AllArgsConstructor
public class PaginationRequest {
#Default private String sortBy = "publishDate";
}
After Orika-mapper converting I get sortBy with null value.
When user submit nothing, how can we have sortBy come with its default value?
I end up having my contract class added the default constructor with default field value:
public PaginationRequest() {
sortBy = "publishDate";
}
Because it can't help even I tried to have #Default private String sortBy = "publishDate"; with my contract field

How to create sub resource with #RestRepositoryResource

We are working on a Spring Boot API.
We use #RestRepositoryResource annotation to generate endpoints.
#RepositoryRestResource(collectionResourceRel = "datarow", path = "datarow")
public interface DataRowRepository extends MongoRepository<DataRow, String>
}
In the previous example, we create a endpoint /api/datarow.
But we want to change resource path like this : /api/dataset/{id}/datarow. Is it possible with #RestRepositoryResource ?
See our model :
public class Datarow {
#Getter #Setter
private String id;
#Getter #Setter
private String datasetId;
#Getter #Setter
private Address address;
}
public class Dataset {
#Getter #Setter
private String id;
#Getter #Setter
private String name;
#Getter #Setter
private String filePath;
#Getter #Setter
private Date uploadDate;
}
See our repository :
#RepositoryRestResource(collectionResourceRel = "datarow", path = "datarow")
public interface DatarowRepository extends MongoRepository<Datarow, String> {
}
Thanks !

Resources