Sunday, November 19, 2017

Serialize & Deserialize exactly same as JAX-RS server

The following code sample show a way to serialize and deserialize exactly same as the JAX-RS server. The code used the same MessageBodyReader  and  MessageBodyWriter used while Jersey frameworks converts request and response body.

The annotation javax.ws.rs.core.Context  is the key. The Providers used by the framework can be fetched from the context.

I have used this technique to improve the performance of the GET call. There are no serialization and deserialization during the GET call. It helps in improving the performance



import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.MessageBodyWriter;

import org.springframework.stereotype.Component;

@Path("/emp")
@Produces({ MediaType.APPLICATION_JSON })
@Component
public class EmpResource {
    
    @Context
    javax.ws.rs.ext.Providers providers;
    
    @POST
    public Employee post(Employee emp) {
        //convert POJO to String
        MessageBodyWriter writer = providers.getMessageBodyWriter(Employee.class,
                Employee.class, null, MediaType.APPLICATION_JSON_TYPE);
        String jsonString = null;
        try {
            ByteArrayOutputStream entityStream = new ByteArrayOutputStream();
            writer.writeTo(emp, Employee.class, Employee.class, null,
                    MediaType.APPLICATION_JSON_TYPE, null, entityStream);
            jsonString = entityStream.toString();
            // Business logic
            //Store jsonString to back end
        } catch (IOException e) {}
        
        //convert String to POJO
        MessageBodyReader reader = providers.getMessageBodyReader(Employee.class,
                Employee.class, null, MediaType.APPLICATION_JSON_TYPE);
        Employee emp2 = null;
        try {
            emp2 = reader.readFrom(Employee.class, Employee.class, null,
                    MediaType.APPLICATION_JSON_TYPE, null,
                    new ByteArrayInputStream(jsonString.getBytes()));
        } catch (Exception e) {}
        
        return emp2;
    }
    
    @GET
    public String get(@QueryParam("id") String id) {
        //Read from backend
        String jsonString = null;

        //Performance improvement: Avoiding String-POJO-String conversion
        return jsonString;
    }
    
}




Sunday, August 20, 2017

Java stream: Logging before filter

While iterating in Java Streams, we may need to log all the items processed by the stream. Especially when using filter in the stream. We can use Peek api for achieving the same.

The following ready to run code will help try out.

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class LogStream {
    public static void main(String[] args) {
        System.out.println("Log");
        List result = data().stream()
                .peek(e -> System.out.println(e.getSalary()))
                .filter(e -> e.getSalary()
                        .doubleValue() < 2)
                .collect(Collectors.toList());
        System.out.println("Result");
        result.forEach(e -> System.out.println(e.getSalary()));
    }
    
    static class Emp {
        public Emp(String name, String dept, BigDecimal salary) {
            super();
            this.name = name;
            this.dept = dept;
            this.salary = salary;
        }
        
        private String name;
        private String dept;
        private BigDecimal salary;
        
        public String getName() {
            return name;
        }
        
        public String getDept() {
            return dept;
        }
        
        public BigDecimal getSalary() {
            return salary;
        }
    }
    
    private static List data() {
        Emp e1 = new Emp("e1", "dept1", BigDecimal.valueOf(1.1));
        Emp e2 = new Emp("e2", "dept1", BigDecimal.valueOf(1.1));
        Emp e3 = new Emp("e3", "dept2", BigDecimal.valueOf(2.1));
        Emp e4 = new Emp("e4", "dept2", BigDecimal.valueOf(1.9));
        return Arrays.asList(e1, e2, e3, e4);
    }
    
}


Monday, February 20, 2017

Java 8 stream - GroupingBy sum BigDecimal - summarizingBigDecimal

Java 8 stream - GroupingBy and summing a BigDecimal field

 import java.math.BigDecimal;  
 import java.util.Arrays;  
 import java.util.List;  
 import java.util.Map;  
 import java.util.stream.Collectors;  
 public class C1 {  
      public static void main(String[] arg){  
           Map<String, BigDecimal> result = data().stream()
               .collect(Collectors.groupingBy(Emp::getDept, 
                        Collectors.mapping(Emp::getSalary, Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))));  
           System.out.println(result);  
      }  
      static class Emp{  
           public Emp(String name, String dept, BigDecimal salary) {  
                super();  
                this.name = name;  
                this.dept = dept;  
                this.salary = salary;  
           }  
           private String name;  
           private String dept;  
           private BigDecimal salary;  
           public String getName() {  
                return name;  
           }  
           public String getDept() {  
                return dept;  
           }  
           public BigDecimal getSalary() {  
                return salary;  
           }  
      }  
      private static List<Emp> data(){  
           Emp e1 = new Emp("e1", "dept1", BigDecimal.valueOf(1.1));  
           Emp e2 = new Emp("e2", "dept1", BigDecimal.valueOf(1.1));  
           Emp e3 = new Emp("e3", "dept2", BigDecimal.valueOf(2.1));  
           Emp e4 = new Emp("e4", "dept2", BigDecimal.valueOf(1.9));  
           return Arrays.asList(e1, e2, e3, e4);  
      }  
 }  

If Salary is Integer or Long or Double, Collectors class provides direct method for summing. Eg: summarizingInt, summarizingLong, summarizingDouble. Always prefer to use methods from JDK instead of writing your own code.