Entity mapping via MapStruct in CDI context

Here we go again implementing a JAX-RS Service.
This service contains a fine working persistence layer with JPA, a small business logic and, of course, our Rest Service.

Our entity contains a few attributes and is designed as follows

package com.javadevcorner.entity;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;

/**
 *
 *
 * @author com.javadevcorner
 */
@Entity
@NamedQueries({
    @NamedQuery(name = Customer.ALL_CUSTOMER, query = "SELECT c FROM Customer c")
})
public class Customer implements Serializable{

    public static final String ALL_CUSTOMER = "ALL_CUSTOMER";

    @Id
    @Column(name = "id")
    private long technicalId;
    private String name;
    private int age;

    //default construct, setter and getter
}

So now we publish this Entity in our GET-Method via http

package com.javadevcorner.boundary;

import com.javadevcorner.entity.Customer;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

/**
 *
 *
* @author com.javadevcorner
 */
@Path("customer")
public class CustomerBoundary {

    @PersistenceContext
    private EntityManager em;

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("allCustomer")
    public Response getAllCustomer() {

        List customers = em.createNamedQuery(Customer.ALL_CUSTOMER).getResultList();

        return Response.status(Response.Status.OK).entity(customers).build();
    }
}

Don´t forget the JAXRSConfiguration class 😉

So what have we done now? We just publish all information of our Customer as they are via http. The result in a formatted JSON would look like this:

But the technialId is nothing the Frontend needs to know. It´s just needed by our database and nothing more. So we´ll modify our Entity before we publish it. For this we use MapStruct. It is a simple and easy Framework to handle exactly what we want to

Implement the MapStruct

Configure the Maven Dependencies

At first we need to import the dependencies in our pom.xml 

<dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>1.2.0.Final</version>
</dependency>
<dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>1.2.0.Final</version>
</dependency>
<dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-jdk8</artifactId>
            <version>1.2.0.Final</version>
</dependency>

Create the CustomerDTO

Of course we need the DTO Class. For this we create a package called dto with the following class

package com.javadevcorner.dto;

import java.io.Serializable;

/**
 *
 *
 * @author com.javadevcorner.com
 */
public class CustomerDTO implements Serializable{
    
    private String name; 
    private int age; 
    
    //setter and getter

}

Implement our Mapper Interface

Now we start to implement our CustomerMapper. For this create a package with a meaningful name. In this package put the following interface

package com.javadevcorner.entityMapper;

import com.javadevcorner.dto.CustomerDTO;
import com.javadevcorner.entity.Customer;
import java.util.List;
import org.mapstruct.Mapper;

/**
 *
 *
 * @author com.javadevcorner.com
 */
@Mapper(componentModel = "cdi")
public interface CustomerMapper {
    
    List mapCustomerToCustomerDTOs(List customer);
}

Please pay Attention to the @Mapper(componentModel = “cdi”) Annotation. This marks the Interface CustomerMapper to be injectable. 

Refactor our GET-Method with the Mapper

@PersistenceContext
private EntityManager em;

@Inject
private CustomerMapper customerMapper;

@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("allCustomer")
public Response getAllCustomer() {

    List customers = customerMapper.mapCustomerToCustomerDTOs(em.createNamedQuery(Customer.ALL_CUSTOMER, Customer.class).getResultList());

    return Response.status(Response.Status.OK).entity(customers).build();
}

we just inject the Mapper and use it´s method. The instantiation and execution are done by the CDI Container and Mapstruct itself. Now call your JAX-RS again, and the id won´t be shown again

Thanks for reading and have fun using MapStruct

Feel free to share

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.