I have a Base dto and a dto which extends it
public abstract class AbstractItem {
private String upc;
private String quantity;
//getter and setter for upc and quantity
}
public class OrderedItem extends AbstractItem {
private String orderId;
// getter and setter for orderId
}
Then I have a modal which I want to convert from OrderedItem. This modal extends a base modal
public abstract class AbstractModal {
private String qty;
public void setQty(String qty) {
this.qty = qty;
}
public String getQty() {
return qty;
}
}
public class ItemModal extends AbstractModal {
private String orderNbr;
private String upcNbr;
// getter and setter for orderNbr and upcNbr;
}
this is my mapper function using Mapstruct
#Mapper
public interface DtoMapper {
#Mappings({
#Mapping(source = "orderedItem.orderId" target = "orderNbr"),
#Mapping(source = "orderedItem.upc" target = "upcNbr"),
#Mapping(source = "orderedItem.quantity" target = "qty")
})
ItemModal convert(OrderedItem orderedItem);
}
During compilation I get an error Unknown property "qty" in result type test.modal.ItemModal.
Does Mapstruct support mapping fields of base class?
If yes, can you please tell me what is wrong with my code?
I am using java 8 and mapstruct 1.2.0
Edit: added getter and setter for qty in AbstractModal
Related
I have a Entity class something like this:
#Entity
public class Website {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
private String url;
public Website() {
//Constructor
//getters and setters
}
here is the DTO class:
public class WebsiteDto {
private Integer id;
private String name;
private String url;
public WebsiteVo() {
//Constructor
//getters and setters
}
I have the WebsiteMapper something like this:
#Component
public class WebsiteMapper {
public List<WebsiteDto> getWebsiteList() {
return repository.findAll().stream().map(w -> {
WebsiteDto dto = new WebsiteVo(w.getId(), w.getName(), w.getUrl());
return dto;
}).collect(Collectors.toList());
I also have Repository Interface:
public interface WebsiteRepository extends JpaRepository<Website, Integer> {
}
I want now to convert DTO to entity using my class WebsiteMapper. Because I did the conversion in this class. How I can do it?
How about using BeanUtils provided by spring org.springframework.beans.BeanUtils, something like this
public List<WebsiteDto> getWebsiteList() {
return repository.findAll().stream().map(w -> {
WebsiteDto dto = new WebsiteVo();
BeanUtils.copyProperties(w, dto); // copys all variables with same name and type
return dto;
})
.collect(Collectors.toList());
}
Hi I guess you wish to converting your entity to DTO. It's quite simple. Create static methods in your DTO class or any util class. The return type should be your DTO type.
e.g.
public class WebsiteDto {
private Integer id;
private String name;
private String url;
public static WebsiteDto export(Website website) {
// Return a new instance of your website DTO
return new WebsiteDto(
website.getId(),
website.getName(),
website.getUrl()
);
}
public static List<WebsiteDto> export(List<Website> websites) {
// Return a new instance of your website DTO list
return websites.stream().map(website -> {
return new WebsiteDto(
website.getName(),
website.getUrl()
}).collect(Collectors.toList());
}
}
NOTE You can also convert your DTO to entity using similar method.
Given the Source class as defined below:
class Source{
private String name;
private int age;
private List<Phone> phones;
// getters and setters
}
and the Phone class as defined below:
class Phone{
private Long id;
private String phoneNumber;
// getters and setters
}
and the Target class as defined below:
class Target{
private String name;
private int age;
private List<Long> idsPhones;
// getters and setters
}
I have an interface is:
#Mapper
interface MyMapper{
Target toTarget(Source source);
Source toSource(Target target);
}
How can I map the List of Phones from the Source class to a List of idsPhones in the Target Class and vice versa?
In order to achieve this you need to help MapStruct a bit by telling how to map from Phone into Long. And the reverse as well.
Your mapper needs to look something like:
#Mapper(uses = PhoneRepository.class)
interface MyMapper {
#Mapping(target = "idsPhones", source = "phones")
Target toTarget(Source source);
#InheritInverseMapping
Source toSource(Target target);
default Long fromPhone(Phone phone) {
return phone.getId();
}
}
If your PhoneRepository contains a method that accepts a Long and returns Phone then MapStruct will automatically know what to do and invoke that method.
I got 2 POJOs that are being passed to a HttpEntity and converted to json.
Before passing them i need a variable which is in both of the POJOs with different names because of the needs of the API so i cant change them.
What is the best way without casting and in terms of OOP also within the POJO definition like mentioned in Wikipedia?
Abstract pojo
public abstract class Pojo{
//some common variables
//setter getters
}
PojoOne
public class PojoOne extends Pojo{
private String id;
//setter getter for id
}
PojoTwo
public class PojoTwo extends Pojo{
private String identifier;
// setter getter for identifier
}
Class that
public class SomeOtherClass {
public void getIdForUse(Pojo pojo){
String s = pojo. // How should this be to have ability to get both id and identifier
}
}
Add a common method to the common superclass:
public abstract class Pojo {
public abstract String getId();
// some common variables
// setter getters
}
public class PojoOne extends Pojo {
private String id;
#Override
public String getId() {
return id;
}
//setter for id
}
public class PojoTwo extends Pojo {
private String identifier;
// setter getter for identifier
#Override
public String getId() {
return identifier;
}
}
I am using an implementation of an interface in Java.
For eg: There can be many PaymentTypes like Credit Card, Mobile etc.
I am making a REST API which contains an interface- how do I map this in JAXB, currently it gives me JAXBException occurred : 2 counts of IllegalAnnotationExceptions.
Currently I am using Apache-CXF and JAXb
#XmlRootElement
public class Payment {
#XmlElement
private PaymentType paymentType;
#XmlElement
private long price;
public Payment() {
}
public Payment(final PaymentType paymentType, final long price) {
super();
this.paymentType = paymentType;
this.price = price;
}
}
#Path("/trial")
public class TrialService {
#GET
#Produces(MediaType.APPLICATION_JSON)
public List<Payment> getPayments() {
final List<Payment> payments = new LinkedList<Payment>();
final CreditCardDetails creditCard = new CreditCardDetails(
"8767798778", "123", 12, 2016);
final Payment payment = new Payment(creditCard, 10);
payments.add(payment);
return payments;
}
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public PaymentDetails startPayment(final PaymentDetails paymentDetails) {
return paymentDetails;
}
}
public class CreditCardDetails implements PaymentType {
#XmlElement
private String creditCardNumber;
#XmlElement
private String cvv;
#XmlElement
private int expirationMonth;
#XmlElement
private int expirationYear;
public CreditCardDetails() {
}
#SuppressWarnings("javadoc")
public CreditCardDetails(
// final BillingAddress billingAddress,
final String creditCardNumber, final String cvv,
final int expirationMonth, final int expirationYear) {
super();
this.creditCardNumber = creditCardNumber;
this.cvv = cvv;
setExpirationMonth(expirationMonth);
setExpirationYear(expirationYear);
}
}
How should I be mapping this or should I be using an entirely different approach?
Edits:
For the POST method I am receiving a payment. Payment could contain any object CreditCard, Wallet etc. What annotation should I provide so that it is desirialized correctly.
Currently it throws a JAXB exception.
The full error message which you've got is:
Caused by: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions PaymentType is an interface, and JAXB can't handle interfaces.
You need to use concreate class for your elements or point it in type attribute of #XmlElement annotation:
#XmlElement(type = CreditCardDetails.class)
private PaymentType paymentType;
If you have more classes that uses PaymentType interface then you may use the following solution:
#XmlAnyElement
#XmlElementRefs({
#XmlElementRef(type=CreditCardDetails.class),
#XmlElementRef(type=Wallet.class)
})
PaymentType paymentType;
The list of #XmlElementRefs can have any number of elements but all possibilities must be listed. CreditCardDetails and Wallet must be annotated with #XmlRootElement.
You can skip #XmlElementRefs annotation:
#XmlAnyElement(lax=true)
PaymentType paymentType;
but in that case make sure you have any required class in JAXB context, if you do not use registry annotate your class with PaymentType field with #XmlSeeAlso({CreditCardDetails.class, Wallet.class}).
I need to implement custom conversion for ID field in Company and Employee classes. I have already implemented custom converter extended from StrutsTypeConverter and it is successfully used to convert Company.ID field, but it does not work for Employee.ID.
Seems like the main problem is in conversion properties file. How should I specify converter class for employee ID field in conversion properties file?
MyAction-conversion.properties:
company.id = com.struts2.convertors.MyCustomConverter
company.??????.id = com.struts2.convertors.MyCustomConverter
MyAction:
public class MyAction extends ActionSupport {
private Company company;
public Company getCompany () {
return company;
}
public void setCompany (Company company) {
this.company= company;
}
#Override
public String execute() {
return SUCCESS;
}
}
Company:
public class Company {
private ID id;
private List<Employee> employees;
// getters and setters
}
Employee
public class Employee{
private ID id;
private String name;
// getters and setters
}
TypeConversion Annotation:
This annotation is used for class and application wide conversion rules.
The TypeConversion annotation can be applied at property and method level.
#TypeConversion(converter = “com.test.struts2.MyConverter”)
public void setAmount(String amount)
{
this.amount = amount;
}
This annotation specifies the location of one of my converters. literally, by using this annotation, I register my class com.test.struts2.MyConverter as a converter, and gets executed every time when setAmount(String amount) method is invoked.
Try the following by adding a converter for the ID type to the xwork-conversion.properties file
com.struts2.ID = com.struts2.convertors.MyCustomConverter