Total Pageviews

2018/12/15

[Java] [MapStruct] How to convert Enumeration to String in MapStruct?

Problem
Assume I have an Employee POJO:
package com.example.demo.vo;

import com.example.demo.enumeration.Gender;
import com.example.demo.enumeration.YesOrNoType;

import lombok.Data;
import lombok.ToString;

@Data
@ToString
public class Employee {

    /**
     * 員工編號
     */
    private Integer id;

    /**
     * 員工姓名
     */
    private String name;

    /**
     * 員工性別
     */
    private Gender gender;

    /**
     * 是否離職
     */
    private YesOrNoType quit;
    

}

and an EmployeeDto POJO:
package com.example.demo.vo;

import lombok.Data;

@Data
public class EmployeeDto {

    /**
     * 員工編號
     */
    private String id;

    /**
     * 員工姓名
     */
    private String name;

    /**
     * 員工性別
     */
    private String gender;

    /**
     * 是否離職
     */
    private String quit; 
    
}

Gender Enumeration:
package com.example.demo.enumeration;

public enum Gender {
    
    MALE("M", "男"), FEMALE("F", "女");

    private final String value;

    private final String description;

    Gender(String value, String description) {
        this.value = value;
        this.description = description;
    }

    public String getValue() {
        return value;
    }

    public String getDescription() {
        return description;
    }

}


YesOrNoType Enumeration:
package com.example.demo.enumeration;

public enum YesOrNoType {
    
    YES("Y", "是"), NO("N", "否");

    private final String value;

    private final String description;

    YesOrNoType(String value, String description) {
        this.value = value;
        this.description = description;
    }

    public String getValue() {
        return value;
    }

    public String getDescription() {
        return description;
    }
}


If I would like to convert Employee to EmployeeDTO, and convert gender and quit attributes to description, how to do it?

How-To
Add the following configurations in your pom.xml
    <properties>
        <org.mapstruct.version>1.2.0.Final</org.mapstruct.version>
    </properties>
 
    <dependencies>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId> <!-- use mapstruct-jdk8 for Java 8 or higher -->
            <version>${org.mapstruct.version}</version>
        </dependency>
 </dependencies>
 
  <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>1.8</source> <!-- or higher, depending on your project -->
                    <target>1.8</target> <!-- or higher, depending on your project -->
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>${org.mapstruct.version}</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>


Create an EmployeeMapper:
package com.example.demo.mapStruct;

import org.mapstruct.DecoratedWith;
import org.mapstruct.Mapper;

import com.example.demo.vo.Employee;
import com.example.demo.vo.EmployeeDto;

@Mapper
@DecoratedWith(EmployeeDecorator.class)
public interface EmployeeMapper {

    EmployeeDto toDto(Employee employee);
    
}


Create an EmployeeDecorator:
package com.example.demo.mapStruct;

import com.example.demo.vo.Employee;
import com.example.demo.vo.EmployeeDto;

public class EmployeeDecorator implements EmployeeMapper {

    private EmployeeMapper delegate;

    public EmployeeDecorator(EmployeeMapper delegate) {
        super();
        this.delegate = delegate;
    }

    @Override
    public EmployeeDto toDto(Employee employee) {
        EmployeeDto dto = delegate.toDto(employee);
        dto.setId(employee.getId().toString());
        dto.setGender(employee.getGender().getDescription());
        dto.setQuit(employee.getQuit().getDescription());

        return dto;
    }

}


Create a test class:
package com.example.demo;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.mapstruct.factory.Mappers;

import com.example.demo.enumeration.Gender;
import com.example.demo.enumeration.YesOrNoType;
import com.example.demo.mapStruct.EmployeeMapper;
import com.example.demo.vo.Employee;
import com.example.demo.vo.EmployeeDto;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class MapStructTest {

    private static List<Employee> employees = new ArrayList<>();

    static {
        Employee albert = new Employee();
        albert.setId(1);
        albert.setName("Albert");
        albert.setGender(Gender.MALE);
        albert.setQuit(YesOrNoType.NO);

        Employee mandy = new Employee();
        mandy.setId(2);
        mandy.setName("Mandy");
        mandy.setGender(Gender.FEMALE);
        mandy.setQuit(YesOrNoType.NO);

        Employee peter = new Employee();
        peter.setId(3);
        peter.setName("Peter");
        peter.setGender(Gender.MALE);
        peter.setQuit(YesOrNoType.YES);

        employees = Arrays.asList(albert, mandy, peter);

    }

    public static void main(String[] args) {
        EmployeeMapper mapper = Mappers.getMapper(EmployeeMapper.class);
        for (Employee employee : employees) {
            EmployeeDto dto = mapper.toDto(employee);
            log.debug("employee: " + employee.toString() + ", dto : " + dto.toString());
        }
    }

}



10:51:10.018 [main] DEBUG com.example.demo.MapStructTest - employee: Employee(id=1, name=Albert, gender=MALE, quit=NO), dto : EmployeeDto(id=1, name=Albert, gender=, quit=)
10:51:10.020 [main] DEBUG com.example.demo.MapStructTest - employee: Employee(id=1, name=Mandy, gender=FEMALE, quit=NO), dto : EmployeeDto(id=2, name=Mandy, gender=, quit=)
10:51:10.020 [main] DEBUG com.example.demo.MapStructTest - employee: Employee(id=3, name=Peter, gender=MALE, quit=YES), dto : EmployeeDto(id=3, name=Peter, gender=, quit=)




2018/12/14

[SQL Developer] How to configure SQL Developer to connect to Sybase database?

Problem
How to configure SQL Developer to connect to Sybase database?


How-To
1. Download jTDS from https://sourceforge.net/projects/jtds/files/

2. Launch SQL Devloper, Tools => Preferences

3. Choose Database => Third Party JDBC Drivers, and add jTDS jar file


4. Close and re-launch SQL Developer. Then you can see SQLServer and Sybase tab in New Database Connection dialog.





2018/12/13

[SQL Developer] How to change language to English in SQL Developer?

Problem
I downloaded SQL Developer from http://www.oracle.com/technetwork/developer-tools/sql-developer/downloads/index.html

As I launch SQL Developer, the default language is Traditional Chinese:



How-To
Close SQL Developer and edit ide.conf which will be found in \sqldeveloper\ide\bin

Add the following configuration at the end of ide.conf and save it.
# Set language to en
AddVMOption -Duser.language=en

Launch SQL Developer again


Reference
[1] https://stackoverflow.com/questions/7768313/how-can-i-change-the-language-to-english-in-oracle-sql-developer

2018/12/12

[Spring Boot] An example to build a SOAP Web Service Provider

Here has the steps to build a SOAP web service provider:

Step 1. Go to https://start.spring.io/ download spring boot project

Step 2. Import spring boot project into your eclipse


Step 3. Add web services-related dependency into pom.xml
    <dependency>
        <groupId>wsdl4j</groupId>
        <artifactId>wsdl4j</artifactId>
    </dependency>

    <dependency>
        <groupId>org.apache.ws.xmlschema</groupId>
        <artifactId>xmlschema-core</artifactId>
        <version>2.0.1</version>
    </dependency>

Step 4. Create two XML schema files
countries.xsd
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:tns="http://ws/oi2/test/country"
    targetNamespace="http://ws/oi2/test/country"
    elementFormDefault="qualified">

    <xs:element name="getCountryRequest">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="name" type="xs:string" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:element name="getCountryResponse">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="country" type="tns:country" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:complexType name="country">
        <xs:sequence>
            <xs:element name="name" type="xs:string" />
            <xs:element name="capital" type="xs:string" />
        </xs:sequence>
    </xs:complexType>
    
</xs:schema>

employees.xsd
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:tns="http://ws/oi2/test/emp"
    targetNamespace="http://ws/oi2/test/emp"
    elementFormDefault="qualified">

   <xs:element name="getEmployeeByIdRequest">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="id" type="xs:int" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:element name="getEmployeeRequest">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="name" type="xs:string" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:element name="getEmployeeResponse">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="employee" type="tns:employee" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:complexType name="employee">
        <xs:sequence>
            <xs:element name="id" type="xs:int" />
            <xs:element name="name" type="xs:string" />
        </xs:sequence>
    </xs:complexType>
    
</xs:schema>

Step 4. Add plugin into pom.xml to generate domain class from XML schema
    <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>jaxb2-maven-plugin</artifactId>
        <version>1.6</version>
        <executions>
            <execution>
        <id>xjc</id>
        <goals>
            <goal>xjc</goal>
        </goals>
            </execution>
        </executions>
        <configuration>
            <schemaDirectory>${project.basedir}/src/main/resources/xsd</schemaDirectory>
            <outputDirectory>${project.basedir}/src/main/java</outputDirectory>
            <clearOutputDir>false</clearOutputDir>
        </configuration>
    </plugin>

Step 5. execute mvn install to generate domain classes


Step 6. create employee / country repository classes
CountryRepository:
package com.example.soapWsDemo.repository;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.annotation.PostConstruct;

import org.springframework.stereotype.Component;

import ws.oi2.test.country.Country;

@Component
public class CountryRepository {
    
    public List<Country> countries = new ArrayList<>();
    
    @PostConstruct
    public void createCountries() {
        Country taiwan = new Country();
        taiwan.setName("台灣");
        taiwan.setCapital("台北");

        Country japan = new Country();
        japan.setName("日本");
        japan.setCapital("東京");

        Country sKorea = new Country();
        sKorea.setName("韓國");
        sKorea.setCapital("首爾");

        countries = Arrays.asList(taiwan, japan, sKorea);
    }
    
    public Country findCountry(String name) {
        if (name == null || "".equals(name)) {
            throw new IllegalArgumentException("請提供國家名稱");
        }

        Country result = null;
        for (int i = 0; i < countries.size(); i++) {
            Country c = countries.get(i);
            if (c.getName().equals(name)) {
                result = c;
                break;
            }
        }
        
        if(result == null) {
            throw new IllegalArgumentException("查無資料");
        }
        return result;
    }
    
}


EmployeeRepository:

package com.example.soapWsDemo.repository;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.annotation.PostConstruct;

import org.springframework.stereotype.Component;

import ws.oi2.test.emp.Employee;

@Component
public class EmployeeRepository {
    public List<Employee> employees = new ArrayList<>();

    @PostConstruct
    public void createEmployees() {
        Employee albert = new Employee();
        albert.setId(1);
        albert.setName("Albert");

        Employee mandy = new Employee();
        mandy.setId(2);
        mandy.setName("Mandy");

        employees = Arrays.asList(albert, mandy);
    }

    public Employee getEmployee(String name) {
        if (name == null || "".equals(name)) {
            throw new IllegalArgumentException("姓名不可為空");
        }

        Employee emp = null;

        for (int i = 0; i < employees.size(); i++) {
            Employee rs = employees.get(i);
            if (rs.getName().equals(name)) {
                emp = rs;
                break;
            }
        }

        if (emp == null) {
            throw new IllegalArgumentException("查無此人");
        }

        return emp;
    }

    public Employee getEmployee(Integer id) {
        if (id == null) {
            throw new IllegalArgumentException("id 不可為空");
        }

        Employee emp = null;

        for (int i = 0; i < employees.size(); i++) {
            Employee rs = employees.get(i);
            if (rs.getId() == id) {
                emp = rs;
                break;
            }
        }

        if (emp == null) {
            throw new IllegalArgumentException("查無此人");
        }

        return emp;
    }
}


Step 7. Create service endpoint

CountryEndPoint:
package com.example.soapWsDemo.endPoint;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import org.springframework.ws.server.endpoint.annotation.RequestPayload;
import org.springframework.ws.server.endpoint.annotation.ResponsePayload;

import com.example.soapWsDemo.repository.CountryRepository;

import ws.oi2.test.country.GetCountryRequest;
import ws.oi2.test.country.GetCountryResponse;

@Endpoint
public class CountryEndPoint {

    private static final String NAMESPACE_URI = "http://ws/oi2/test/country";

    @Autowired
    private CountryRepository countryRepo;

    @PayloadRoot(namespace = NAMESPACE_URI, localPart = "getCountryRequest")
    @ResponsePayload
    public GetCountryResponse getCountryRequest(@RequestPayload GetCountryRequest request) {
        String name = request.getName();

        GetCountryResponse response = new GetCountryResponse();
        response.setCountry(countryRepo.findCountry(name));

        return response;
    }

}

EmployeeEndPoint:
package com.example.soapWsDemo.endPoint;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import org.springframework.ws.server.endpoint.annotation.RequestPayload;
import org.springframework.ws.server.endpoint.annotation.ResponsePayload;

import com.example.soapWsDemo.repository.EmployeeRepository;

import ws.oi2.test.emp.GetEmployeeByIdRequest;
import ws.oi2.test.emp.GetEmployeeRequest;
import ws.oi2.test.emp.GetEmployeeResponse;

@Endpoint
public class EmployeeEndPoint {

    private static final String NAMESPACE_URI = "http://ws/oi2/test/emp";
    
    @Autowired
    private EmployeeRepository empRepo;
    
    @PayloadRoot(namespace = NAMESPACE_URI, localPart = "getEmployeeRequest")
    @ResponsePayload
    public GetEmployeeResponse getEmployee(@RequestPayload GetEmployeeRequest request) {
        String name = request.getName();

        GetEmployeeResponse response = new GetEmployeeResponse();
        response.setEmployee(empRepo.getEmployee(name));

        return response;
    }

    @PayloadRoot(namespace = NAMESPACE_URI, localPart = "getEmployeeByIdRequest")
    @ResponsePayload
    public GetEmployeeResponse getEmployeeByIdRequest(@RequestPayload GetEmployeeByIdRequest request) {
        Integer id = request.getId();

        GetEmployeeResponse response = new GetEmployeeResponse();
        response.setEmployee(empRepo.getEmployee(id));

        return response;
    }
}


Step 8. Create a new class with Spring WS related beans configuration:
package com.example.soapWsDemo.config;

import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.ws.config.annotation.EnableWs;
import org.springframework.ws.config.annotation.WsConfigurerAdapter;
import org.springframework.ws.transport.http.MessageDispatcherServlet;
import org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition;
import org.springframework.xml.xsd.XsdSchemaCollection;
import org.springframework.xml.xsd.commons.CommonsXsdSchemaCollection;

@EnableWs
@Configuration
public class WebServiceConfig extends WsConfigurerAdapter {
    
    @Bean
    public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
        MessageDispatcherServlet servlet = new MessageDispatcherServlet();
        servlet.setApplicationContext(applicationContext);
        servlet.setTransformWsdlLocations(true);
        return new ServletRegistrationBean(servlet, "/ws/*");
    }

    @Bean
    public DefaultWsdl11Definition employees() throws Exception {
        DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
        wsdl11Definition.setPortTypeName("WebServicePort");
        wsdl11Definition.setLocationUri("/ws");
        wsdl11Definition.setTargetNamespace("http://ws/oi2/test");
        wsdl11Definition.setSchemaCollection(getXsds());
        return wsdl11Definition;
    }

    @Bean
    public XsdSchemaCollection getXsds() throws Exception {
        CommonsXsdSchemaCollection xsds = new CommonsXsdSchemaCollection(new ClassPathResource("/xsd/employees.xsd"),
                new ClassPathResource("/xsd/countries.xsd"));
        xsds.setInline(true);
        return xsds;
    }
    
}



Step 9. launch spring boot application and use SOAP UI to do test