Sunday, November 09, 2014

Java Generics Covariant and Contravariant

Introduction

Here the getter method

( ) => A

Covariant

A <: B

( ) => A <: ( ) => B

If a A is subtype of B, then getter or A is subtype of getter of B.

Here the setter method

A => ( )

Contravariant

B => ( ) <: A => ( )

Above Covariant and Contravariant can be explained from the following code:

Say A is Animal

public class Animal {
@Override
public String toString(){
return "I am a Animal";
}
}

Say B is Bear as follows

public class Bear extends Animal {
@Override
public String toString(){
return "I am a Bear";
}
}
 

As shown in the above code Bear is subtype of Animal.

Here the Zookeeper class where getter and setter methods are

public class Zookeeper {
private Animal animal;
public void setFeed(Animal animal){
this.animal =animal;
}

public Animal getFed(){
return this.animal;
}
}

As shown in the above Zookeeper class, there is no indication of Bear, but in the following Zoo client code

public class Zoo {
public static void main(String ...args){

Zookeeper zookeeper = new Zookeeper();
Bear bear = new Bear();
zookeeper.setFeed(bear);
Bear retCat = (Bear) zookeeper.getFed();
System.out.println(retCat);

}
}

In the method setFeed you can pass the Bear instance according to the contravariant subtyping, and in the getter method getFed returns the Bear instance as a reference of Animal that is because getters support covariant subtyping.

Invariant

But how to explain this concept. See the Bearkeeper class which is subtype of Zookeeper

/**
* Created by Ojitha on 9/11/2014.
*/
public class Zookeeper {
private Animal animal;
public void setFeed(Animal animal){
this.animal =animal;
}

public Animal getFed(){
return this.animal;
}
}

class BearKeeper extends Zookeeper{
Bear bear;

@Override
public void setFeed(Animal animal) {
this.bear = (Bear)animal;
}

public void setFeed(Bear bear){
this.bear = bear;
}

@Override
public Animal getFed() {
return this.bear;
}
}

As show in the above code, void setFeed(Animal animal)  override the method in the Zookeeper because subclass return the covariant of super return , while overloading with the method void setFeed(Bear bear) method because of invariants of setter methods in Java although Bear is subclass of Animal.

Arrays

Java Arrays support covariant but this is not a good idea. This made Java to throws the bad runtime exception java.lang.ArrayStoreException in the following code:

        Animal[] animals = new Animal[]{new Animal(), new Animal(), new Bear()};
Bear[] bears = new Bear[]{new Bear(), new Bear()};
animals = bears;
animals[1] = new Animal();

As shown in the above code, last line java.lang.ArrayStoreException has thrown to indicate that Animal instance is not a valid instance anymore because animals reference became a Bear type after the animals = bears assignment.

Array doesn’t support contravariant subtyping Sad smile.

Generics

In term of generic, array subtyping covariant means that type S[] is considered to be subtype of T[] wherever S is subtype of T.  Other hand, the subtyping relation for generics is invariant: List<S> is not considered to be subtype of List<T>. Therefore, wildcards present the covariant subtyping for the generics: List<S> is subtype of the List<? extends T> where S <: T. Wildcards introduce contravariant subtyping as well. For example, List<T> is subtype of List<? super S>.

Here the example for congtravariant

        List<Object> objs = new ArrayList<Object>();
objs.add(1);
objs.add(1.23);
List<? super Integer> integers = objs;
Object o = integers.get(1);
//Integer i = integers.get(0);

As shown in the above,  Object is a supper class of the Integer. Even Integer as well as Double has been added. The values are read as Object only. It is impossible to read as Integers. The is where GET/PUT principal comes to the play, that says “use extend if you are reading from the structure, as well as use super if you writing to the structure.

Monday, October 27, 2014

Configure Google Analytics access from Tomcat SSL

My recent web application had a requirement to publish the user requests to Google Analytics (GA) who has confirmed the registration. This is because there can be users who have visited the registration page but not confirm the registration or end up with errors even they click the registration button. Fortunately, this web application is using Spring Web Flow therefore I managed to implement the helper method that will send the confirmation information to the GA as a very last even.
I've used the Apache HTTP Client to send a http request to GA using Google Measurement Protocol. In my case, I don't use Java general security store, instead use the custom keystore for Tomcat. This situation is very common when you need to configure the developer environment for the secure web applications development.
First you have to enter the following URL to the Firfox browser. Then click the upper left corner pad lock icon: you will get the More information button.


In the next window, click the button "View Certificate".
As shown in the above screenshot, you have to find the value of the Serial Number. This number is very important. In the certificate hierarchy, each tree item has different serial number. Here we select the top one in the chain.

Importing Certificate from general key store

Now the time to find the certificate in the java general certificate store. First you need to change to the certificate store. Generally that is c:\Program Files...\java\jre\lib\security and the keystore is cacerts.
You have to execute the following command to get the certificate information to the t.txt text file:

keytool -list -v -keystore cacerts > t.txt


Open the t.txt file in the notepad.exe and look for the 35def4cf that is the number where all the colons are removed.
Now export the certificate using following keytool command.

keytool -export -keystore cacerts -alias equifaxsecureca -file equifaxsecureca.cer


Use the following command to import this certificate to your keystore.

keytool -import -trustcacerts -alias equifaxsecureca  -file equifaxsecureca.cer -keystore truststore.jks


Truststore is the one used to store all the third party certificates in the tomcat.

Direct import

This is the easiest if you follow the above steps correctly. Again, select the top of the certificate chain (verify by the serial number) as shown in the above screenshot and click the "Export" button to export directly from the FireFox. I've exported the certificate as ga.crt in this case instead of equifaxsecureca.cer file. And import as alias ga as well:
keytool -import -trustcacerts -alias ga  -file ga.crt -keystore truststore.jks


Using above command import the ga.crt.

NOTE:
keytool -list  -v -keystore truststore.jks -alias ga > n.txt
If you have use the above command to extract the certificates, you will find both the way same certificate is imported.

Friday, May 02, 2014

Java Trick: Generic Array Converter

I had a problem of increasing size of the array. Of course I have to copy the array. But it is not easy with java Generics, because of the following problem:

public class ArrayUtils<T>{
 public T[] resizeArray(T[] source, int offset){
  int length = source.length+offset;
  Object[] aNew = new Object[length];
  System.arraycopy(source, 0, aNew, 0, source.length);
  return (T[])aNew;
 }
}

Of course you can compile the ArrayUtils class, but you cannot use this method as shown in the following code segment:
 public static void main(String[] args){
  Integer[] ints = new Integer[2];
  ints[0]=0;
  ints[1]=1;
  Integer[] newInts =  new ArrayUtils<integer>().resizeArray(ints, 3);
  System.out.println(newInts.length);
 }

Here the error:

Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer;
 at net.au.abc.abcid.test.ArrayCopyTest.main(ArrayCopyTest.java:9)

the problem, aNew never is possible to cast to the type T because it is created as an Object type. I found a very good answer with help of the book: Core Java: Volume I—Fundamentals, Ninth Edition. It is easy with java reflections as shown in the line# 7 to 9. getClass().getComponentType() return the type of the array elements.

import java.lang.reflect.Array;

public class ArrayUtils<T>{
 public T[] resizeArray(T[] source, int offset){
  int length = source.length+offset;
  
  Class arrayClass =  source.getClass();
  Class elementType =  arrayClass.getComponentType();
  Object aNew = Array.newInstance(elementType, length);
  System.arraycopy(source, 0, aNew, 0, source.length);
  return (T[])aNew;
 }
}

If you need you can make the method static by changing it signature to
public <t> T[] resizeArray(T[] source, int offset){ 
.