Monday, 8 May 2017

Java Reflection, Synthetic Members and Unit Testing.

Recently I was working on developing a Custom Serializer With Custom Annotation using Java reflection you can find more about the same here. Everything seems to be good at the end. But, while extending the project with adding Unit Test cases things seems to be screwing up badly for unknown reason. While debugging UT's I found that the issue seems to be because of Synthetic members that is been define in the class. I had no clues about it. So I dig further to understand the world of Synthetic Members in Java world.

What is Synthetic Members?
Any constructs introduced by the compiler that do not have a corresponding construct in the source code must be marked as synthetic, except for default constructors and the class initialization method.

Why Synthetic Members issues occurring in Junit?  
To collect execution data JaCoCo instruments the classes under test which adds two members to the classes: A private static field $jacocoData and a private static method $jacocoInit(). Both members are marked as synthetic. Since, these members are added to the class and the Serializer that is been developed included those two fields as part of Serialization and test cases failed in the end.

How to fix Synthetic Members issues?  
As a general or good practice we should ignore Synthetic members particularly while dealing with reflection. As per Java Doc we can identify a member whether it's Synthetic or not through isSynthetic() method. By adding a check to the Serialize method the issue is solved and the following is code after the change.
 
public void serialize(Object o, JsonGenerator jsonGenerator, 
SerializerProvider serializerProvider) throws IOException {

    jsonGenerator.writeStartObject();
    jsonGenerator.writeStringField("name", o.getClass()
                .getSimpleName());
    jsonGenerator.writeArrayFieldStart("definition");

    Field[] fields = o.getClass().getDeclaredFields();
    for (Field field : fields) {
        if (!field.isSynthetic()) {
            jsonGenerator.writeStartObject();
            jsonGenerator.writeStringField("name",
            StringUtils.join(StringUtils
             .splitByCharacterTypeCamelCase(field.getName()), '-')
             .toString().toLowerCase());
            addAnnotationInJson(field, jsonGenerator);
            try {
                addTypeInJson(field, jsonGenerator);
            }
            catch (Exception e) {
                //log.info(e.getMessage());            }
            jsonGenerator.writeEndObject();
        }
    }
    jsonGenerator.writeEndArray();
    jsonGenerator.writeEndObject();
} 

 

Friday, 5 May 2017

Generate Java Client Library For NodeJS using Swagger Codegen


This blog will give you a overview on generating Java client library for NodeJS project using Swagger Codegen.

Step-by-step guide

Add the steps involved:
  1. Install Swagger Codegen in your machine as detailed in page
  2. Make sure that we have endpoint in NodeJS project that exposes Swagger JSON Definition (/api-docs is exposed with Swagger Definition)
  3. Validate the Swagger Definition with help of Swagger Editor 
  4. Invoke Code using the following command:
    • swagger-codegen generate -i http://localhost:18138/api-docs -l java -o flex/executionconfig -c config.json --api-package com.ooyala.flex --artifact-id executionConfiguration --artifact-version 0.0.1
  5.  Swagger Codegen options that is been used are described as follows:
    • -i --> Spec file (JSON in our case)
    • -l --> language for which the client library has to generated
    • -o --> output directory
    • -c --> custom configuration file location
    • --api-package --> respective package name
    • --artifact-id --> respective artifact ID
    • --artifact-version --> version for the client      
  6.  The following custom config.json file that is used
    {
      "library":"feign",
    }
  7. codegen will create a src for client library similar to the following:
  8. Generated code will have README.md which will help us with the next steps
  9. To generate java client library and deploy to repository use any of the following based on the need
    • mvn install
    • man deploy
  10. Once the package/library is created we can use it in our java project by injecting the dependency

Custom Java Serializer for a POJO with Custom Annotation

Main goal that this blog gonna detail about writing a Custom Serializer for a POJO which has a Custom Annotation attributes. As a prerequisites would request users to have quick brushing on how to implement a Custom Annotation and write a Custom Serializer.  The following are few links that will give you quick overview on Custom Annotation and Custom Serializer respectively:
 The Main requirement that's been given to me is to develop a custom serializer and the class will have the following different kind of attributes:

  • String attribute with & without custom annotation
  • Primitive attribute with & without custom annotation
  • Primitive Wrapper attribute with & without custom annotation
  • POJO attribute with & without custom annotation 
The following is the Class that is been used to implement the Serializer:

public class CustomAnnotation {

    //String attribute with Annotation 
    @ConfigField(displayName = "AnnotationForString"
    description = "config field anotation Test", required = true,
    multiplicity = Multiplicity.ZERO_TO_MANY, expressionEnabled = false)
    private String testField = "something";

    //primitive attribute with Annotation     
    @ConfigField(displayName = "Long-field-test"
    description = "config field long", required = true,
    multiplicity = Multiplicity.ONE_TO_MANY,expressionEnabled = true)
    private long longField;

    //String attribute without Annotation 
    private String stringNoAnnotation;

    //no Annotation for primitive attribute     
    private long longFieldNoAnnotation;

    //Primitive Wrapper with Annotation     
    @ConfigField(displayName = "AnnotationForPrimitiveWrapper"
    description = "config field with primitive Wrapper"
    required = true, multiplicity = Multiplicity.ONE_TO_MANY,expressionEnabled = true)
    private Integer intField;

    //PrimitveWrapper without Annotation     
    private Integer primitiveWrapperNoAnnotation;

    //POJO with Annotation 
    @ConfigField(displayName = "pojo-annotation"
    description = "config field POJO", required = true,
    multiplicity = Multiplicity.SINGLE,expressionEnabled = false)
    private CustomChild customChild;

    //POJO with out Annotation     
    private CustomChild customChildNoAnnotation;

}

In the above code @ConfigField is a the Custom Annotation that is been developed and the following is the implementation of the same:

@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface ConfigField {
    String displayName() default "";

    String description() default "";

    boolean required() default false;

    Multiplicity multiplicity() default SINGLE;

    boolean expressionEnabled() default false;
}

In the above code Multiplicity is a enum and it has the following definition:

public enum Multiplicity {
    SINGLE("1"),
    ZERO_TO_ONE("0..1"),
    ZERO_TO_MANY("0..*"),
    ONE_TO_MANY("1..*");

    private String value;

    public String getValue() {
        return value;
    }

    private Multiplicity(String value) {
        this.value = value;
    }
}
 
The following is the POJO(CustomChild) that is been used in the CustomAnnotation class:
 
public class CustomChild {

    private Integer childName;

    @ConfigField(displayName = "Custom child Annotation int"
    description = "Custom Child attribute with Annotation", required = false,
    multiplicity = Multiplicity.ZERO_TO_MANY,expressionEnabled = true)
    private int childInt;
}
 
Now we move on to the core part on how the custom Serializer is been implemented.
 
I have used jackson StdSerializer for writing the custom Serializer. 
I have leveraged reflection to get the declared fields of the class. And further used 
reflection to get the annoation and it's field.
 
The following is the code snippet for the same:
 
public void serialize(Object o, JsonGenerator jsonGenerator, 
SerializerProvider serializerProvider) throws IOException {

    jsonGenerator.writeStartObject();
    jsonGenerator.writeStringField("name", o.getClass().getSimpleName());
    jsonGenerator.writeArrayFieldStart("definition");

    Field[] fields = o.getClass().getDeclaredFields();
    for(Field field : fields) {
        jsonGenerator.writeStartObject();
        jsonGenerator.writeStringField("name"
        StringUtils.join(StringUtils.splitByCharacterTypeCamelCase(field.getName()), '-')
             .toString().toLowerCase());
        addAnnotationInJson(field, jsonGenerator);
        try {
            addTypeInJson(field, jsonGenerator);
        } catch (Exception e) {

        }
        jsonGenerator.writeEndObject();
    }
    jsonGenerator.writeEndArray();
    jsonGenerator.writeEndObject();

} 

private void addTypeInJson(Field field, JsonGenerator jsonGenerator) throws IOException, ClassNotFoundException {
    if(!ClassUtils.isPrimitiveOrWrapper(field.getType()) && !field.getType().getSimpleName().equalsIgnoreCase
            ("string")) {
        jsonGenerator.writeStringField("type", "complex");
        jsonGenerator.writeFieldName("children");
        jsonGenerator.writeStartArray();
        addChildInJson(field, jsonGenerator);
        jsonGenerator.writeEndArray();
    } else {
        jsonGenerator.writeStringField("type", field.getType().getSimpleName());
    }
}
 
 
With these code in place the following the Seralized output for the class that we have seen:
 
{
  "name" : "CustomAnnotation",
  "definition" : [ {
    "name" : "test-field",
    "displayName" : "AnnotationForString",
    "description" : "config field anotation Test",
    "required" : true,
    "multiplicity" : "0..*",
    "expressionEnabled" : false,
    "type" : "String"
  }, {
    "name" : "long-field",
    "displayName" : "Long-field-test",
    "description" : "config field long",
    "required" : true,
    "multiplicity" : "1..*",
    "expressionEnabled" : true,
    "type" : "long"
  }, {
    "name" : "string-no-annotation",
    "displayName" : "string no annotation",
    "type" : "String"
  }, {
    "name" : "long-field-no-annotation",
    "displayName" : "long field no annotation",
    "type" : "long"
  }, {
    "name" : "int-field",
    "displayName" : "AnnotationForPrimitiveWrapper",
    "description" : "config field with primitive Wrapper",
    "required" : true,
    "multiplicity" : "1..*",
    "expressionEnabled" : true,
    "type" : "Integer"
  }, {
    "name" : "primitive-wrapper-no-annotation",
    "displayName" : "primitive wrapper no annotation",
    "type" : "Integer"
  }, {
    "name" : "custom-child",
    "displayName" : "pojo-annotation",
    "description" : "config field POJO",
    "required" : true,
    "multiplicity" : "1",
    "expressionEnabled" : false,
    "type" : "complex",
    "children" : [ {
      "name" : "child-name",
      "displayName" : "child name",
      "type" : "Integer"
    }, {
      "name" : "child-int",
      "displayName" : "Custom child Annotation int",
      "description" : "Custom Child attribute with Annotation",
      "required" : false,
      "multiplicity" : "0..*",
      "expressionEnabled" : true,
      "type" : "int"
    } ]
  }, {
    "name" : "custom-child-no-annotation",
    "displayName" : "custom child no annotation",
    "type" : "complex",
    "children" : [ {
      "name" : "child-name",
      "displayName" : "child name",
      "type" : "Integer"
    }, {
      "name" : "child-int",
      "displayName" : "Custom child Annotation int",
      "description" : "Custom Child attribute with Annotation",
      "required" : false,
      "multiplicity" : "0..*",
      "expressionEnabled" : true,
      "type" : "int"
    } ]
  } ]
} 
 
 Working code can be found in https://github.com/vivek-dhayalan/customSerializer/