Wednesday, September 9, 2009

RMI client callbacks

In a project that I have worked for in the past, the RMI clients could call asynchronous methods on the RMI server. After making these calls the client could return to whatever it is doing. The RMI server would run the method/tasks on seperate threads which would take a long time to complete. Once finished the RMI server would send back the reponse to the RMIClient. In order to send the response, the RMI server needs to make remote calls to its clients. So the RMI client has to act like a RMI server. To accomplish this, a RMI client must be a remote object and it must be able to accept incoming calls from others. This is achieved on the RMI client by calling the following static method:


UnicastRemoteObject.exportObject (remote_object)

The exportObject() method returns a stub which can be cast to the remote interface that the client implements. Here is an example which simulates this.

I have the following pieces of code:

  • AttractionListener.java - The remote interface which the client will implement. It has a callback method attractionAdded() which the RMI server will invoke on completion of a long running task.
  • CallbackClient.java - The client code which invokes the long running method addAttraction() on the RMI server.
  • Attractions.java - The remote interface which will be implemented by the RMI Server. It has a method addAttractionListener() which lets the client register itself with the server.
  • AttractionsImpl.java - The RMI server which implements Attractions interface. It runs the long running task on a seperate thread.
  • ServerRMI.java - The code which binds the RMI server to the rmi registry.
AttractionListener .java


import java.rmi.Remote;
import java.rmi.RemoteException;

public interface AttractionListener extends Remote {
public void attractionAdded(String attraction) throws RemoteException;
}


CallbackClient.java


import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.Scanner;


public class CallbackClient implements AttractionListener {


public void attractionAdded(String attraction)
throws RemoteException {
System.out.println("Attraction Added:" + attraction);
}

public static void main(String args[]) {
try {
AttractionListener client = new CallbackClient();
System.out.println("Exporting the client");
UnicastRemoteObject.exportObject(client);
String serverURL = "rmi://127.0.0.1:1099/ServerRMI";
Attractions server =
(Attractions)Naming.lookup(serverURL);
server.addAttractionListener(client);
String s;
while (true) {
System.out.println("Enter new attraction:");
Scanner sc = new Scanner(System.in);
s = sc.next();
if (s != null) {
server.addAttraction(s);
}
}

} catch (Exception e) {
System.out.println("Exception occured " +
"while adding attraction: " +
"\n" + e.getMessage());
}
}
}



Attractions.java

import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.List;


public interface Attractions extends Remote {
public void addAttraction(String name) throws RemoteException;
public List<String> showAttractions() throws RemoteException;
public void addAttractionListener(AttractionListener listener) throws RemoteException;
}



AttractionsImpl.java

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.List;


public class AttractionsImpl extends UnicastRemoteObject implements Attractions {

private static final long serialVersionUID = 1L;
private List<String> attractions = new ArrayList<String>();
private AttractionListener listener;

protected AttractionsImpl() throws RemoteException {
super();
}

@Override
public void addAttraction(String name) throws RemoteException {
if (name != null) {
verifyAttraction(name);
}
}

@Override
public List<String> showAttractions() throws RemoteException {
List<String> a = new ArrayList<String>();
a.addAll(attractions);
return attractions;
}

@Override
public void addAttractionListener(
AttractionListener listener) throws RemoteException {
this.listener = listener;
}

private void verifyAttraction(String name) {
Runnable t = new VerifyThread(name);
new Thread(t).start();
System.out.println("Verify Thread started");
}

private class VerifyThread implements Runnable {

private String name;

VerifyThread(String name) {
this.name = name;
}

@Override
public void run() {
try {
Thread.sleep(2000);
System.out.println("Finished verifying");
attractions.add(name);
if (listener!= null)
listener.attractionAdded(name);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
}

}


}

}



ServerRMI.java


import java.rmi.Naming;


public class ServerRMI {

public static void main (String args[] ) {
try {
Attractions attractions = new AttractionsImpl();
Naming.rebind("ServerRMI", attractions);
System.out.println("Server started!");
}
catch (Exception e) {
System.out.println("Exception: " + e);
}
}

}




Here are steps for getting the code working:

Compile the code
run rmic on the CallbackClient
start the rmiregistry
start the server
start the client

Here is a sample output:

Running the client:
Exporting the client
Enter new attraction:
tt
Enter new attraction:
rr
Attraction Added:tt
Attraction Added:rr

Server Output:
Server started!
Verify Thread started
Finished verifying
Verify Thread started
Finished verifying

I have kept the code simple to illustrate RMI callbacks. Usually the server has a List of listeners as there will be multiple clients. Also since RMI server handles each request in separate thread for calls originating from different connections, you will need to synchronize the code i.e. make the server-side code thread-safe.

Thursday, September 3, 2009

InetAddress and Factory Design Pattern

I was recently working on a project which required me to check if a server is reachable or not. I started looking at java.net.InetAddress.isReachable(int) to solve my problem. The javadoc was not very clear and so I went in to see how it was actually implemented. In the java file I came across Factory design pattern for creating Internet address(InetAddress), so I decided to blog about it.

One cannot create the InetAddress objects by invoking the constructor. One has to use static methods like getLocalHost() etc. Based on the type of IP address of the host i.e. whether it is version4 or version6 IP address, a Inet4Address or Inet6Address is returned by the factory. Both these classes extend InetAddress. This is transparent to the client, so the client need not worry about which type of InetAddress to create.

In brief, the factory design pattern delegates the responsibility of creating the correct object to the factory. The factory makes the decision of which class of object to construct based on the user input or some other implicit criteria(here it was IP address type).

Here is the snippet from the code in InetAddress.java which uses Factory Design Pattern to acheive it. In this code the factory is InetAddressImplFactory which makes the decision to either load(call constructor of) the Inet4Address class or Inet6Address class.

public class InetAddress implements java.io.Serializable {

............
static {

...............
impl = (new InetAddressImplFactory()).create();
...........
}

.........
}


class InetAddressImplFactory {

//create v6 or v4 address
static InetAddressImpl create() {
Object o;
if (isIPv6Supported()) {
o = InetAddress.loadImpl("Inet6AddressImpl");
} else {
o = InetAddress.loadImpl("Inet4AddressImpl");
}
return (InetAddressImpl)o;
}

............

}



Thursday, August 27, 2009

Java EE and Cloud Computing

I would like to share this interesting article on Java EE and Cloud Computing.

Monday, August 10, 2009

JUnit 4.0

Junit 4.0 is very different from its previous versions. I present the features followed by examples.


JUnit 4.0 features:

  • Uses annotations and makes life very easy.
  • Test Class DOES NOT have to extend TestCase.
  • Need to manually do "import static org.junit.Assert.*" to get all the methods like AssertFalse and AssertTrue as the Test class does not extend TestCase.
  • All methods that needed to be tested should be decorated with @org.junit.Test annotation and you can use any method name.
  • @Test notatation takes an expected parameter which can be used to specify the exception the method should throw.eg: @Test(expected=IndexOutOfBoundsException.class) The test fails if the expected exception is not thrown.
  • To not test a particular method , decorate it with the annotation @org.junit.Ignore
  • Can specify a timeout for a method, if the method runs for a longer time, it fails. eg: @Test(timeout=1)- AssertEquals can test arrays, so we don't need to iterate over contents of array.
  • Can use annotations to specify test fixtures.
  • There are 2 Class level fixtures: @BeforeClass and @AfterClass. These are run only once before or after the tests in the class are run. Note: Can create multiple @BeforeClass fixtures though the order of running them cannot be currently
    specified.
  • There are 2 Method level fixtures: @Before and @After. These are run before or after running every test (method) in the class.
  • Can use annotations to specify test suites.
    @RunWith(Suite.class)
    @Suite.SuiteClasses( { <YourTestClass1>.class,[<YourTestClass2>.class] })
    public class <SuiteName> {
    }
  • Introduces a new runner called Parameterized. It allows the same tests to be run with different data. One of the examples below shows how to run Parameterized test. To enable this do the following:
    • Have the annotation @RunWith(value = Parameterized.class) for the Test Class
    • Have a public static method that returns a Collection for data. Each element of the collection must be an Array of the various paramters used for the test.
    • Provide a public constructor for the test class that uses the parameters.

Examples:

Java code on which the tests have to be run


import java.util.HashMap;
import java.util.Map;

public class SimpleExample {

private Map<Integer, Employee> emp;

public SimpleExample() {
emp = new HashMap<Integer, Employee>();
}

public void addEmployee(String name, int id) {
Employee e = new Employee(name,id);
emp.put(id, e);
}

public String getEmployeeName(int id) throws EmployeeException{
if (!emp.containsKey(id)) {
throw new EmployeeException("No Employee with the id " + id);
}
return emp.get(id).getEmpName();
}

public int getNumberofEmployees(){
return emp.size();
}


}

class Employee {
private String empName;
private int empID;

Employee(String name, int id) {
empName = name;
empID = id;
}

public String getEmpName() {
return empName;
}

public int getEmpID() {
return empID;
}
}

public class EmployeeException extends Exception {

private static final long serialVersionUID = 1L;

EmployeeException(String ex) {
super(ex);
}

}


Example 1: JUnit 4.0 test cases for the above class


import static org.junit.Assert.*;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;

public class SimpleExampleJUnitTest {

private static SimpleExample se;
private static final String NAME1 = "foo";
private static final String NAME2 = "bar";

@BeforeClass
public static void setUpBeforeClass() throws Exception {
System.out.println("setUpBeforeClass: run only once");
se = new SimpleExample();
se.addEmployee(NAME1, 1);
}

@AfterClass
public static void tearDownAfterClass() throws Exception {
System.out.println("tearDownAfterClass: run only once");
se = null;
}

@Before
public void setUp() throws Exception {
}

@After
public void tearDown() throws Exception {
}

@Test
public void addEmployeetTest() {
se.addEmployee(NAME2, 2);
assertEquals(se.getNumberofEmployees(),2);
}

@Test
public void getExisitingEmployeeNameTest()
throws EmployeeException {
assertEquals(se.getEmployeeName(1),NAME1);
}

@Test(expected=EmployeeException.class)
public void getNonExisitngEmployeeNameTest() throws EmployeeException {
se.getEmployeeName(10);
}

@Ignore
public void getAllEmployeesTest() {
//Not yet implemented.
}
}


Example 2: Parameterized JUnit 4.0 test case


import static org.junit.Assert.*;

import java.util.Arrays;
import java.util.Collection;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(value = Parameterized.class)
public class SimpleExampleParameterizedJUnitTest {

private SimpleExample se;
private String name;
private int id;

public SimpleExampleParameterizedJUnitTest(String name,int id) {
this.name = name;
this.id = id;
}

@SuppressWarnings("unchecked")
@Parameters
public static Collection data() {
Object[][] data = new Object[][] {
{ "foo", 1}, {"bar",2},{"foobar",3}};
return Arrays.asList(data);
}

@BeforeClass
public static void setUpBeforeClass() throws Exception {
System.out.println("setUpBeforeClass: run only once");
}

@AfterClass
public static void tearDownAfterClass() throws Exception {
System.out.println("tearDownAfterClass: run only once");
}

@Before
public void setUp() throws Exception {
System.out.println("setUp: run before every test");
se = new SimpleExample();
}

@After
public void tearDown() throws Exception {
System.out.println("teatDown: run after every test");
se = null;
}

@Test
public void addEmployeetTest() {
se.addEmployee(name,id);
assertEquals(se.getNumberofEmployees(),1);
}

@Test
public void getExisitingEmployeeNameTest()
throws EmployeeException {
se.addEmployee(name,id);
assertEquals(se.getEmployeeName(id),name);
}

@Test(expected=EmployeeException.class)
public void getNonExisitngEmployeeNameTest() throws EmployeeException {
se.getEmployeeName(id+1);
}

@Ignore
public void getAllEmployeesTest() {
//Not yet implemented.
}
}

Tuesday, July 28, 2009

Getting references to outer classes

Sometimes it is necessary to get references to the outer classes of an inner class. From within the inner class it is pretty straightforward to obtain the reference to the outer class. Just precede the keyword this with the outer class name. Here is a simple example:

public class OuterThis {
private String me = "OuterThis";
public class Inner1 {
private String me = "Inner1";
public class Inner2{
public void getEnclosingClasses() {
System.out.println(Inner1.this.me);
System.out.println(OuterThis.this.me);
}
}
}

public static void main(String[] args) {
OuterThis.Inner1.Inner2 in2 = new OuterThis().new Inner1().new Inner2();
in2.getEnclosingClasses();
}

}


You can also get the outer class reference through reflection. The this reference is encoded as this$n where n is an int specifying the level of the class. In the example above, this$0 is the outer class "OuterThis" while this$1 refers to "Inner1". So in the code above just do the following to get the enclosing class "Inner1" through reflection in the method getEnclosingClasses().
Inner1 in1 = (Inner1)getClass().getDeclaredField("this$1").get(this);

Reflection to obtain the outer class reference is usually used when you are outside the inner class. The following example illustrates it.

import java.util.ArrayList;

public class ExposeThis {
private String exposeThis = "Just Expose This";

public static void main(String[] args) throws
IllegalArgumentException, SecurityException, NoSuchFieldException,
IllegalAccessException {
Client cl = new Client();
new ExposeThis().registerMe(cl);
cl.printThis();
}

public void registerMe(Client client) {
client.addListener(new ClientListener(){});
}

public String toString() {
return exposeThis;
}

}

interface ClientListener {
}

class Client {
private ArrayList<ClientListener> clients = new ArrayList<ClientListener>();

public void addListener(ClientListener cl) {
clients.add(cl);
}

public void printThis() throws
NoSuchFieldException, IllegalArgumentException,
SecurityException, IllegalAccessException{
for (ClientListener cl: clients) {
//Get handle to OuterClass this by reflection
ExposeThis et =
(ExposeThis)cl.getClass().getDeclaredField("this$0").get(cl);
System.out.println(et);
}
}
}





Note:
Since it is possible to obtain references to enclosing classes by getting a handle to the inner class, one has to be very careful while working with inner classes.

Wednesday, July 22, 2009

Checked collections

The generics mechanism provides compile-time type checking. So generic collections are mostly type-safe. I did not say they will "always" be safe because it is possible to add wrong types into generic collections using unchecked casts. For instance mixing generic and non-generic code results in unchecked casts. The compiler will issue warnings when there are unchecked casts but the compilation does not fail. Also at runtime, when a wrong type is added to the parameterized collection no ClassCastException is thrown because the runtime has no knowledge of type parameters due to type erasure. So now, the wrong type is happily added to the collection. The problem of wrong type in the collection does not get discovered until much later. And when the problem is discovered, the runtime exception makes it quite impossible to discover the source of the problem i.e. where exactly the unsafe type got added. Here is a simple example followed by the runtime exception that the program throws when it runs.

import java.util.ArrayList;
import java.util.Collection;

public class UnsafeCollectionOperation {

public static void unsafeAdd(Collection c) {
c.add(new Integer(1));
}

public static void main(String[] args) {
Collection<String> c = new ArrayList<String>();
c.add("One");
c.add("Two");
unsafeAdd(c);
for (String s: c) {
System.out.println(s);
}

}

}




Here is what happens at runtime:
One
Two

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer
at UnsafeCollectionOperation.main(UnsafeCollectionOperation.java:17)


As you see from the exception above, the runtime exception does not offer any information on where exactly the unsafe type was added. My code is so small, so we can easily deduce where we went wrong, but when we deal with a lot of code, this task becomes very cumbersome. One way to deal with this problem is to use checked collection(see java.util.Collections). Checked collections are dynamically type safe views of collections. They perform a runtime type check every time an element is inserted into the collection. Any attempt to insert a wrong type will immediately result in ClassCastException. So we know exactly where we went wrong. Here is an example:

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;

public class CheckedCollection {

public static void safeAdd(Collection c) {
c.add("three");
}

public static void unsafeAdd(Collection c) {
c.add(new Integer(1));
}

public static void main(String[] args) {
Collection<String> c = new ArrayList<String>();
c.add("One");
c.add("Two");
Collection<String> checkedCollection =
Collections.checkedCollection(c, String.class);
safeAdd(checkedCollection);
unsafeAdd(checkedCollection);
for (String s: checkedCollection) {
System.out.println(s);
}

}

}



Running the program produces:
Exception in thread "main" java.lang.ClassCastException: Attempt to insert class java.lang.Integer element into collection with element type class java.lang.String
at java.util.Collections$CheckedCollection.typeCheck(Collections.java:2206)
at java.util.Collections$CheckedCollection.add(Collections.java:2247)
at CheckedCollection.unSafeAdd(CheckedCollection.java:14)
at CheckedCollection.main(CheckedCollection.java:23)


From the exception above we know exactly where we went wrong.
Couple of note worthy points are:
- When a checked collection view is created using an existing collection, it will NOT discover incorrectly typed elements, if they already exist in the collection prior to creating the view.
- After creating the checked collection view, if any access happens through the original collection and not through the checked collection, it cannot ensure type safety.
- There is a performance overhead of a runtime type check every time an element is inserted into the collection.

Saturday, July 18, 2009

Accessing local variables in local classes

In Java, local classes can access any members of the containing class. However when it comes to local variables and method parameters they can use only the ones marked final.  The reason is that the instances of the class can live longer than the method.  And since local variables and method parameters live on the stack, they may be long gone before the instance actually uses them.  So if the local classes want to use local variables, they must have a private copy of all the local variables they use. The compiler automatically makes a private internal copy for the local class. However the value of the local variable can change during the lifetime of the method. So someone has to keep the private local variable of the local class in sync with the actual local variable. There are many issues involved in doing it (like when or how often should the sync take place etc). The safest and perhaps the easiest way to guarantee that the local and the private copy are same is to mark the local variable final.  Hence the local classes cannot use local variables and method parameters that are not marked final.  Here is an example of how an instance of a local class can save the scope and use it at a later point in time:





public class LocalClass {

private int instanceVariable = 0;
private interface LocalClassHolder{
int getInstanceVariable();
int getLocalVariable();
}

public LocalClassHolder testLocalClass() {

final int localVariable = 1;
LocalClassHolder lch;
int changingLocalVariable = 0; //not possible to use this in local class

class InnerLocalClass implements LocalClassHolder {
//return instance variable
public int getInstanceVariable() {
return instanceVariable;
}

//return local variable
public int getLocalVariable() {
return localVariable;
}
}
lch = new InnerLocalClass();
changingLocalVariable = 1000;
return lch;

}

public static void main(String[] args) {
LocalClass lc = new LocalClass();
LocalClassHolder ch = lc.testLocalClass();
int instance = ch.getInstanceVariable();
int local = ch.getLocalVariable();
System.out.println("Instance: " + instance + " " + "Local: " + local);

}

}


Sunday, July 12, 2009

Method overloading with Widening, Boxing and Varargs

With the introduction of boxing and varargs in Java 1.5, there are new rules to remember wrt overloaded methods that include widening, boxing and varargs. Key rule to remember is widening always wins over boxing and varargs when present individually. So mathematically, widening > boxing > varargs in that order. There is a catch with widening reference variables. The reference variable widening should satisy the IS-A test. Here is a simple example:



public class BoxWidenVarArgs {

public static void pickMe(Integer i) {
System.out.println("Integer ");
}
public static void pickMe(int... i) {
System.out.println("varargs int ");
}
public static void pickMe(short i) {
System.out.println("short");
}
public static void pickMe(Byte i) {
System.out.println("Byte ");
}
public static void pickMe(byte... i) {
System.out.println("varargs byte");
}
public static void onlyInteger(Integer i) {
System.out.println("Integer");
}

public static void main(String[] args) {
byte b = 1;
pickMe(b); //picks widening over boxing and varargs
int i = 10;
pickMe(i); //As no widening is present, picks boxing over varargs
/**
* compilation error, cannot widen from Byte to Integer as Byte
* is not a Integer, IS-A test fails!
*/
//onlyInteger(new Byte(b));
}

}




Ouput:
short
Integer

Here are possible combinations of Widening, boxing and varargs:

Combining Widening and Boxing:
Can we widen and box, is this allowed? The rule to remember is that first widening then boxing ( i.e. Widen+Box) is not allowed. So a short can be widened to an int but a short cannot be widened and boxed to an Integer.


public class WidenAndBox {

public static void pickMe(Integer i) {
System.out.println("Integer");
}
public static void main(String[] args) {
short s = 2;
//Compilation error. Not allowed.
//pickMe(s);

}

}




Combining Boxing and Widening:
First boxing and then widening is allowed provided the widening satisfies the IS-A relationship. So a short can be boxed to a Short and then widened to a Number or Object but a short cannot be boxed to a Short and then widened to a Integer or String because it does not satisfy the IS-A relation.

Combining varargs with widening/boxing:
You can widen and then combine varargs. You can box and combine with varargs. However you cannot have overloaded methods that has widening+varargs and boxing+varargs. You can combine varargs with either widening or boxing.


public class LegalCombinations {

public static void pickMe(Number n) {
System.out.println("Number");
}
public static void wideningVarArgs(Integer... i) {
System.out.println("Integer...");
}
public static void boxingVarArgs(long... i) {
System.out.println("long...");
}

public static void main(String[] args) {
short s = 2;
pickMe(s); //Boxing and Widening
int i = 1;
wideningVarArgs(i); //combination of widening and varargs
boxingVarArgs(i); //combination of boxing and varargs
}

}



The following causes compilation error as discussed above:
public class IllegalCombinations {

public static void withVarArgs(Integer... i) {
System.out.println("Integer...");
}
public static void withVarArgs(long... i) {
System.out.println("long...");
}

public static void main(String[] args) {
int i = 1;
/**
* Compilation error. Cannot have 2 overloaded methods one using
* boxing+varargs and another using widening+varargs.
* Can have one or the other.
*/
//withVarArgs(i);
}

}

Also remember varargs are always chosen last. So if you have 2 overloaded methods one with boxing + widening and and one with varargs, compiler will choose boxing+widening over varargs.

Summary
:
  • used individually, widening > boxing > varargs
  • varargs are always chosen last, they always lose.
  • reference variables have to satisfy IS-A test while widening
  • widening then boxing is not permitted. 
  • boxing then widening is permitted.
  • varargs can be combined with wither boxing or widening.

Monday, July 6, 2009

Shadowing final variables

In Java, final variables can be shadowed. They follow the same rules of shadow variables and static methods which I had discussed in my earlier post. The key point to remember is that while resolving a shadow variable or shadow static method, the reference type and NOT the reference object (i.e. object pointed to by the reference type) is used. Here is a simple example:

class Super {
public final String y = "SUPER";
public static final int z = 0;
}

class Sub extends Super {

//Shadowing a final variable
public final String y = "SUB";

//Shadowing a final variable and also changing type and access modifier's
char z = '1';

}

public class ShadowingFinalVariables {


public static void main(String[] args) {
Sub sub = new Sub();
Super supr = sub;


print(sub.y); //yields SUB
print(supr.y); //yields SUPER
print(((Super)sub).y); //Due to casting, yields SUPER
print(((Sub)supr).y); //Due to casting, yields SUB
print(sub.z); //yields 1
print(supr.z); //yields 0
print(((Super)sub).z); //Due to casting, yields 0
print(((Sub)supr).z);//Due to casting yields 1

}


public static <T> void print(T t) {
System.out.println(t);
}

}

Wednesday, July 1, 2009

Task Scheduling in Java


In Java, the Timer class helps you to schedule tasks to run at some time in the future. The tasks can be run either once or repeatedly like a batch job. 


Tasks can be scheduled to run in the following way:

  • Create Timers using a simple constructor of the Timer class. This creates a Timer Thread.
  • Subclass the TaskTimer class to represent your task. Implement the run() method and put your task implementation details here.
  • Schedule the task using one of the schedule() methods of the Timer class.


Types of Schedule

There are 3 types of schedules:

  • One time schedule

This runs the task once after the delay time specified. Here is an example:



import java.util.Timer;

import java.util.TimerTask;


public class MyTimer {

public static void main(String[] args) {

Timer timer = new Timer();

TimerTask task = new TimerTask() {

public void run() {

System.out.println("Scheduled Task");

}

};

//Execute this task after 0 milliseconds i.e. immediately

timer.schedule(task,0);

}


}

  • Fixed-delay schedule

This runs the task repeatedly after the initial delay time specified. The time between the subsequent executions is specified by a period time. This schedule ensures that the period time elapses between invocations. Here is one example:


long oneday = 24*60*60*1000;

//Execute this task every day starting immediately. Make sure

//that there is a 24 hr delay between the invocations. So if the

//last invocation was delayed for some reason, the delay carries

//forward.

timer.schedule(task, 0, oneday);


  • Fixed-rate schedule


This runs the task repeatedly after the initial delay time specified. The time between the subsequent executions is specified by a period time. This schedule ensures that the task runs during their scheduled time .i.e it is not affected by the time of its previous invocation. Example:

//Way to setup a cron or batch job. Make sure that the task 

//runs at the fixed time every 24 hrs. If the last invocation

//was delayed due to some reason, the delay is not reflected in the

//next invocation.

timer.scheduleAtFixedRate(task,0,oneday);


Some interesting facts:

  • Each Timer object runs only one background thread. So if multiple tasks are assigned to the same Timer object, they will be run sequentially. To run them in parallel you have to create multiple Timer objects. 
  • The class is thread-safe.
  • There is no mechanism to cancel the currently executing task. There is a cancel method which terminates the Timer thread and thereby discards any scheduled tasks but does not affect the currently executing task.


Tuesday, June 23, 2009

Case constants and compile time constants.

In Java, case constants in switch statements have to be compile time constants and ofcourse be byte, short, char, int or enum. Compile time constants' values are known at compile time. They are the static finals like 

static final int ME = 1;

static final byte BE = 1;

static final int US = ME*2;

whose values are known or can be computed at compile time. 


Not all static finals can be computed or known at compile time. For example the following cannot be computed at compile time:

static final int CURRENT_TIME = (int)System.currentTimeMillis()*24*60*60;

So it cannot be used as a case constant.


Now how about wrappers? Can the following be used as a case constant?

static final Integer CONSTANT = new Integer(1);

Wrappers are immutable and since it is declared as static final, the variable CONSTANT  is actually a constant, and since it can be auto unboxed, it can be used as a switch constant, right? Wrong! It turns out that it is not a compile time constant. Auto unboxing converts the Integer wrapper to a primitive int as follows:

CONSTANT.intValue(); 

So the value cannot be computed at compile time. In effect due to this conversion that needs to happen (eventhough it happens implicitly), wrappers cannot be compile time constants.

Tuesday, June 16, 2009

Simply hashcode

In Java, here are the key things to remember about hashcode:
  • If you override equals method also override hashcode method. The default implementation of hashcode returns the 32-bit internal JVM address of the object. So if you do not override hashcode, the object cannot be used in data structures that use hashing mechanism. 
  • If two objects are equal, their hashcodes must be equal. However the reverse is not true i.e. if the hashcodes are equal, the objects may or may not be equal/same.
  • If hashcodes of 2 objects are NOT same, the two objects are NOT equal.
  • If both equals and hashcode are overridden, they must use the same set of fields. Equals may use more fields than hashcode uses but it must use all the fields that hashcode uses. The fields must be final i.e. immutable. If the fields are changeable, you may not get accurate results.
  • Hashcode DOES NOT provide a unique identifier for an object.
  • Hashcodes can be negative.

Saturday, June 13, 2009

Restoring files in Eclipse

Restoring deleted files
Restoring deleted files in Eclipse IDE is very simple, just do the following:
- Select the project in which o restore the file.
- From the pop-up menu select 'Restore from local history' option. (In case of mac os, hold the ctrl key and click on the project to invoke the pop-up)

- Select the file to restore. Select the edition of the file to restore.

- Click on restore.

Restoring a different version of the file
- Select the file to restore.
- From the pop-up menu select 'show in'. Select 'history'.

- It opens the history perspective.
- Select the version to be restored. To compare the version just choose 'Compare current with local' from the pop-up menu.


- Double click on the version to restore it.

Wednesday, June 10, 2009

Graphical Resume

Very creative resume for creative jobs! And here is the explanation. Enjoy.

Wednesday, May 27, 2009

How to achieve covariance in method parameters

Consider the following example:


public interface Toy {
public String getName();
}

public class SuperHeroes implements Toy {
public String getName() {
return "Spiderman";
}
}

public class Dolls implements Toy{
public String getName() {
return "Barbie";
}
}

public interface ChildrenAtPlay{
public void play(Toy toy);
}

public class Boys implements ChildrenAtPlay{
public void play(Toy toy) {
}
}

public class Girls implements ChildrenAtPlay{
public void play(Toy toy) {
}
}


Children play with toys but lets assume boys and girls play with different types of toys. The problem with the code above is that it allows boys to play with Dolls and girls to play with superheroes. If you attempt to change the code and make the play method in Boys to accept a parameter of type SuperHeroes, code will not compile, because the ChildrenAtPlay interface contract is not satisfied. So how can we provide a narrower type for a method parameter. Is it possible to have covariant parameters just like Covariant return types?
DISCLAIMER: This is only an example to illustrate a point about covariant return types. I dont subscibe to the views that boys cannot play with dolls or girls cannot play with super heroes.


You can achieve a covariant parameter using generics. Modify the interface ChildrenAtPlay to actually take a type parameter T extends Toy. Then modify the play method to accept any type of Toy. Then while defining the Boys and Girls classes specify the Toys they can play with.

Here is the code to achieve this:
    public interface ChildrenAtPlay <T extends Toy> {
public void play(T toy);
}

public class Boys implements ChildrenAtPlay <SuperHeroes> {
public void play(SuperHeroes toy) {
}
}

public class Girls implements ChildrenAtPlay <Dolls>{
public void play(Dolls toy) {
}
}

Friday, May 15, 2009

Arrays and final qualifier

One has to be careful regarding arrays which are declared final. It only means that the whole array reference itself cannot be changed to point to a different array. Individual elements of the array can be modified. I have an example below to depict this:

public class TestFinalArray {

final StringBuilder[] array;

TestFinalArray(int size, String... records) {
//Initialize final array
array = new StringBuilder[size];
for (int i = 0; i < size; i++) {
array[i] = new StringBuilder(records[i]);
}

}

public static void main(String[] args) {
TestFinalArray tfa =
new TestFinalArray(3, new String[] {"1","2", "3"});
print("Original array", tfa.array);
//Modify elements of the array
tfa.array[0] = new StringBuilder("Hello");
tfa.array[1] = tfa.array[1].append("World");
print("After Modification", tfa.array);

}

public static void print(String s, StringBuilder[] array) {
if (s != null) {
System.out.println(s);
}
for (StringBuilder elem: array) {
System.out.println(elem);
}
}

}




Output:
Original array
1
2
3
After Modification
Hello
2World
3

Tuesday, May 5, 2009

Nice article...

Today, I was really happy to come across this essay "Teach yourself programming in ten years" by Peter Norvig. He makes very good points, the gist being it takes atleast 10 years and not X days to become an expert in programming in a language - Expert meaning not just understanding how to program but understanding the design aspects and the consequences of writing programs in different ways. I, myself, have been programming in an OO environment for a long time and am still learning.

I have to admit that I have browsed books like "Teach yourself X in Y days" but it is not with the intent of becoming an expert in X. Sometimes one needs to interface with languages and tools in which one lack's expertise especially when one has to customize some small piece of the one's product with customer's code. In such cases, such books help provide relief as they provide just the essentials. With deadlines looming and customers waiting, there is sometimes a rush! But even in the rush, if one has been programming for sometime, hopefully depending on the environment, one is able to make wise choices wrt design and performance.

Anyways the fact remains that, to become an expert in a programming language one has to have the passion, work hard and ofcourse, enjoy. Take it easy!

Monday, May 4, 2009

Preventing serialization of objects

In Java if the parent class is serializable then the child automatically is serializable. If for some reason you don't want the child to be serializable then you have to override the private methods readObject and writeObject to throw NotSerializableException. These are the same private methods which were used to customize serialization in my earlier post.

Example code on how to prevent serialization:
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

//Serializable class
class Animal implements Serializable {

private static final long serialVersionUID = 1L;
private String name;

public Animal(String name) {
this.name = name;
}

public String getName() {
return name;
}
}

//Does not want to be serializable
class Cat extends Animal {

private static final long serialVersionUID = 1L;
private String breed;
private static final String NOT_SERIALIZABLE = "Cat cannot be serialized";

public Cat (String name, String breed) {
super(name);
this.breed = breed;
}

public String getBreed() {
return breed;
}

//To prevent serialization, override this method to throw exception
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
throw new NotSerializableException(NOT_SERIALIZABLE);
}

//To prevent serialization, override this method to throw exception
private void writeObject(ObjectOutputStream oos) throws IOException {
throw new NotSerializableException(NOT_SERIALIZABLE);
}
}

//Test it
public class MyNonSerializableTest {

public static void main(String[] args) throws FileNotFoundException, IOException {
Animal a = new Animal("Cow");
System.out.println("Serializing animal object");
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("animal.ser"));
out.writeObject(a);
Cat c = new Cat("bo", "Taby cat");
System.out.println("Serializing cat object");
ObjectOutputStream ous = new ObjectOutputStream(new FileOutputStream("cat.ser"));
ous.writeObject(c);
}
}


The output:
Serializing animal object
Serializing cat object
Exception in thread "main" java.io.NotSerializableException: Cat cannot be serialized
....blah blah blah.....

Friday, May 1, 2009

Analysis of McKinsey's report on cloud computing

Last month McKinsey released a report called "Clearing the air on cloud computing" in which they conclude that corporations with large data center's could lose money if they move to the cloud. As per the report, the current cloud offerings are best suited for small and medium sized companies. Obviously these conclusions are based on some assumptions which unfortunately seem to be incorrect. Here are the detailed analysis(read rebuttal) of this report by James Hamilton and Lydia Leong. Very interesting reads.

Thursday, April 30, 2009

Reversing String in Java

This post is about String manipulation. I have provided solutions to some problems/teasers such as how to reverse a String without using the reverse method, how to reverse individual words in a sentence without reversing the sentence and how to reverse a sentence without reversing the words in it. There are many ways to do it and I have presented one or two. It was pure fun doing this exercise.

And remember unless there is a real need to rewrite core functionality don't do it.

import java.util.Stack;
import java.util.StringTokenizer;

public class MyStringTests {

/**
* Reverses word and if a sentence is provided, reverses
* the sentence and all words in the sentence.
* @param s is the input string
* @return the modified string
* eg:
* HELLOO WORLD
* becomes
* DLROW OOLLEH
* eg:
* HELOO becomes
* OOLEH
*/
public static String reverseWord(String s) {
if (s == null || s.length() <= 1) return s;
char[] a = s.toCharArray();
int len = a.length - 1;
char temp;
for(int i = 0, j = len; i <= j; i++,j--) {
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
return new String(a);
}

/**
* Ideal way to reverse a string in Java is to use
* the reverse method of StringBuffer. Unless there
* is a real need to rewrite core functionality don't
* do it.
* @param s is the input string
* @return the modified string
* eg:
* HELLOO WORLD
* becomes
* DLROW OOLLEH
* eg:
* HELOO becomes
* OOLEH
*/
public static String reverseWordUsingReverse(String s) {
if (s == null || s.length() <= 1) return s;
StringBuffer sb = new StringBuffer(s);
return sb.reverse().toString();
}

/**
* Reverses a sentence without reversing individual
* words in it
* @param s is the input string
* @return the modified string
* eg:
* HELLOO WORLD
* becomes
* WORLD HELLO
*/
public static String reverseSentence(String s) {
if (s == null || s.length() <= 1) return s;
StringTokenizer strtok = new StringTokenizer(s);
if (strtok.countTokens() <= 1) return s;
Stack<String> stack = new Stack<String>();
while (strtok.hasMoreTokens()) {
stack.push((String)strtok.nextToken());
}
StringBuffer sb = new StringBuffer();
while (!stack.isEmpty()) {
sb.append(stack.pop());
sb.append(" ");
}
return sb.toString();
}

/**
* Reverses a sentence without reversing individual
* words in it
* @param s is the input string
* @return the modified string
* eg:
* HELLOO WORLD
* becomes
* WORLD HELLO
*/
public static String reverseSentenceUsingSplit(String s) {
if (s == null || s.length() <= 1) return s;
String[] sa = s.split(" ");
if (sa.length <= 1) return s;
StringBuffer newString = new StringBuffer();
for(int i = 0, j = (sa.length - 1); i <= j; i++,j--) {
newString.append(sa[j]).append(" ").append(sa[i]);
}
return newString.toString();
}

/**
* Reverses each word in a sentence but not the
* sentence
* @param s is the input string
* @return the modified string
* eg:
* HELLOO WORLD
* becomes
* OOLLEH DLROW
*/
public static String reverseWordInSentence(String s) {
if (s == null || s.length() <= 1) return s;
StringTokenizer strtok = new StringTokenizer(s);
StringBuffer sb = new StringBuffer();
while (strtok.hasMoreTokens()) {
sb.append(reverseWord(
(String)strtok.nextToken()));
sb.append(" ");
}
return sb.toString();
}


public static void main(String[] args) {
//Test
String s = "HELLOO WORLD";
print(s);
print(reverseWord(s));
print(reverseWordUsingReverse(s));
print(reverseSentence(s));
print(reverseSentenceUsingSplit(s));
print(reverseWordInSentence(s));
}

//Helper print method
public static <T> void print(T s) {
System.out.println(s);
}


}



The output is:
HELLOO WORLD
DLROW OOLLEH
DLROW OOLLEH
WORLD HELLOO
WORLD HELLOO
OOLLEH DLROW

Friday, April 24, 2009

Serializing non-serializable objects using readObject and writeObject

Basic serialization is pretty straightforward, just make the class implement the Serializable interface. Serializable is a marker interface, so pretty much it involves nothing i.e. implementing no methods. Also if one of the super classes of the class is serializable then the class is automatically serializable. Here the basic assumption is that all the member variables of the class are serializable. However that isn't always the case. Class sometimes contains one or more member variables that are not serializable. In such cases, one of the mechanisms to make the class serializable is to do the following:
- Mark the non-serializable fields transient. So these are not saved as part of the object state.
- Implement the following methods in the class:
private void writeObject(ObjectOutputStream out) throws IOException;
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException;

When the above methods are implemented first call the defaultReadObject/defaultWriteObject to save the state of the serializable member fields and then proceed to read/write the transient variables. Here is an example:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class MySerializationTest implements Serializable{

private static final long serialVersionUID = 1L;
transient Color color;
int length;

public MySerializationTest(String color, int length) {
this.color = new Color(color);
this.length = length;
}

//Deserialization
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ois.defaultReadObject();
color = new Color((String)ois.readObject());
}

//Serialization
private void writeObject(ObjectOutputStream oos) throws IOException {
oos.defaultWriteObject();
oos.writeObject(color.getColor());
}

@Override
public String toString() {
StringBuffer str = new StringBuffer();
str.append("Color:" + color.getColor());
str.append(" length:" + length);
return str.toString();
}

public static void main(String[] args) throws IOException, ClassNotFoundException {
String filename = "Ser.ser";
MySerializationTest mySer = new MySerializationTest("Green", 20), mySer2;
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
try {
oos = new ObjectOutputStream(new FileOutputStream(filename));
//Write serialized object to file
oos.writeObject(mySer);
ois = new ObjectInputStream(new FileInputStream(filename));
//read the serialized object
mySer2 = (MySerializationTest)ois.readObject();
System.out.println(mySer2);
} finally {
oos.close();
ois.close();
}


}

}

//Non serialized class
class Color {

private String color;

public Color(String color) {
this.color = color;
}

public void setColor(String color) {
this.color = color;
}

public String getColor() {
return color;
}

}


Output:
Color:Green length:20

Tuesday, April 21, 2009

Oracle buys Sun Microsystems

There has been a lot of articles discussing Oracle buying Sun. It was discussed by Michael Krasny in forum yesterday. It was quite good and so I am posting a link to the recording here.

Sunday, April 19, 2009

Interesting article about Google App Engine

Here is a very nice article by Dion Hinchcliffe. In this post, Dion summarizes the offerings and the missing pieces of GAE. If you are interested in cloud computing, specially GAE it is worth reading.

Wednesday, April 15, 2009

Chaining Properties file

In Java, one way of instantiating a Properties object is with Properties(Properties defaults) constructor. The "defaults" parameter allows property files to be stacked together and it is searched only when a particular property is not found. This feature is quite useful during development and testing when we often have conflicting settings. In such cases, editing a single properties file proves to be error-prone and inefficient. Having more than 1 properties file with only properties that need to be different and chaining them together proves to be more safe and easy. Here is an example:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;

public class LayeringProperties {

public static final String appPropFile = "Props";
public static final String userPropFile = "UserProperties";

public static void main(String[] args) throws IOException{

try {
//Load application's properties from a file
Properties myProps = new Properties();
myProps.load(new FileInputStream(appPropFile));

//Load the user's properties from a file
Properties userProps = new Properties(myProps);
userProps.load(new FileInputStream(userPropFile));

//List the user properties as key=value pairs
System.out.println("User properties");
userProps.list(System.out);

//List the application's properties
System.out.println("Application properties");
myProps.list(System.out);

} catch (FileNotFoundException fe) {
fe.printStackTrace();
} catch (IOException ie) {
ie.printStackTrace();
}
}
}


Here is the output. Notice how the property value for property "admin.name" is different in the 2 Properties object.
User properties
-- listing properties --
admin.contact=phone email
application.name=My Properties
application.version=1.0
admin.name=akku
Application properties
-- listing properties --
application.name=My Properties
application.version=1.0
admin.name=Kutty

Friday, April 10, 2009

Java support for Google App Engine

On the morning of april 7, 2009, Google announced Java support for App Engine. There is a catch, only a list of core Java classes are supported so there is bound to be a debate about it.

I was very excited to hear this news. Google restricted access to the first 10,000 developers who sign up. I wanted to test drive it so I signed up for an account on 7th evening. I was actually surprised to get my account approved the next day. I thought I was late in signing up but looks like I was not.

I downloaded the AppEngine Java SDK and the Google plugin for Eclipse on my Windows laptop. I am a heavy Eclipse user, so was very happy to see the plugin. I followed the directions for installation and setup. It was pretty straightforward unlike some problems I ran into with the Python App Engine installation and setup on Mac last time. I wanted to do it on my mac but it was indisposed at that time. I went ahead and created a project with a simple servlet as per the instructions, uploaded it to my account and everything worked like a charm.

Google also has a running list of frameworks, lanaguages and libraries which will run on the App Engine. Lot of JVM based languages like Jython, Groovy etc are supported. So now a wider community will embrace Google App Engine.

Friday, April 3, 2009

Tim Bray on what's next in Java Web development

I recently listened to a very interesting podcast on the future of Java Web development by Tim Bray who is the Director of Web Technologies at Sun. Tim Bray talks about cloud computing, concurrency challenges, running dynamic languages like Jython on JVM, REST and other emerging Web technologies.

I think it is a nice podcast and if you are interested in these technologies, you might find the talk interesting too.

Tuesday, March 31, 2009

Using Java I/O API to read and write integers as bytes to a binary file

Java I/O API is very vast. I have shown how to use BufferedInputStream and BufferedOutput stream to read and write integers as bytes to a file.My test case only involves 5 integers but the program is meant for a large number of integers.

BufferedInputStream:
My input stream is binary and not character. So I have used the stream type BufferedInputStream. I have wrapped the plain FieInputStream with the BufferedInputStream so that the input can be buffered. Then I have used the following method int read(byte[] b,int off,int len) to read up to len bytes of data from the stream into an array of bytes, thereby, improving performance.

BufferedOutputStream:
I have used the BufferedOutputStream to write all the bytes at once instead of using the plain FileOutputStream.

Efficient way to read integers from a file of bytes

import java.io.*;

public class ReadFile {

private static final int numOfBytesInInt = 4;

/**
* This method reads bytes from a file and converts them to integers.
* @param name filename
* @param numOfBytes Number of bytes to read
* @return Integer array
*/
public static int[] getIntegersStoredAsBytesFromFile(String name, int numOfBytes) throws IOException {
byte[] b = readBytesFromFile(name,numOfBytes);
return convertBytesToInteger(b);
}

/**
* This method actually reads bytes from a file in one shot(hopefully).
* It is more efficient than reading 1 integer or byte at a time in a file.
* @param name filename
* @param numOfBytes Number of bytes to read
*/
public static byte[] readBytesFromFile(String name, int numOfBytes) throws IOException {
BufferedInputStream bis = null;
byte[] b = new byte[numOfBytes];
try {
bis = new BufferedInputStream(new FileInputStream(name));
bis.read(b);
return b;
} finally {
bis.close();
}
}

/**
* This helper method actually converts each 4 bytes into an integer.
* There is also another way of doing it through bit manipulation.
* @param b The byte array to convert to int
* @return The array of ints
*/
public static int[] convertBytesToInteger(byte[] b) throws IOException{
ByteArrayInputStream bai = new ByteArrayInputStream(b);
DataInputStream dis = new DataInputStream(bai);
int len = b.length;
int[] ints = new int[len/numOfBytesInInt]; //4 bytes = 1 int
for (int i = 0,j = 0; i < len; i += numOfBytesInInt, j++) {
ints[j] = dis.readInt();
}
return ints;
}

}


 

Efficient way to write integers as bytes to a file

import java.io.*;
import java.util.Random;

public class WriteFile {

private static final int numOfBytesInInt = 4;

/**
* This method generates integers using random number
* generator, converts each integer to 4 bytes and
* writes it to a file
* @param name filename
* @param numOfBytes Number of bytes to write
*/
public static void generateIntegersAndStoreInFileAsBytes(
String name, int numOfBytes) throws IOException {
//Generate a byte[] of integers
byte[] b = generateIntegersAsBytes(numOfBytes);
//Write them to the file
writeBytesToFile(name,b);
}

/**
* This helper method actually generates the integers
* using random number generator and converts
* each integer to 4 bytes
* @param numOfBytes Number of bytes to generate
* @return Array of bytes
*/
public static byte[] generateIntegersAsBytes(int numOfBytes) throws IOException {
byte[] b = new byte[numOfBytes];
int randomNumber = 0;
Random r = new Random();
for (int offset = 0; offset < b.length; offset += numOfBytesInInt) {
//Generate random int
randomNumber = r.nextInt();
//Just have it here to show what is written into the file
//is what we are reading later..
System.out.println(randomNumber);
//convert int to bytes
intToByte(randomNumber, b, offset);
}
return b;
}

/**
* This method writes all the bytes to a file in a one shot(hopefully without blocking).
* It is more efficient than writing 1 integer at a time in a file.
* @param name filename
* @param b Array of bytes to write
*/
public static void writeBytesToFile(String name, byte[] b) throws IOException{
BufferedOutputStream bos = null;
try {
bos = new BufferedOutputStream(new FileOutputStream(name));
bos.write(b);
bos.flush();
} finally {
bos.close();
}
}

/**
* This helper method actually converts each integer to 4 bytes.
* See the next method for another way to do the same thing.
* @param integer Integer to be converted to bytes
* @param b The byte array into which the bytes have to be stored
* @param offset The start offset in b
*/
public static void intToByte(int integer, byte[] b, int offset) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
dos.writeInt(integer);
dos.flush();
System.arraycopy(bos.toByteArray(), 0, b, offset, numOfBytesInInt);
}


/* Instead of using the intToByte method, one could also manually convert
* the integer to an array of bytes using bit arithmetic.
* Here is a way to do it. To use this method, just replace the call
* to the method intToByte() with generateByte() above
*
* private static void generateByte(int integer, byte[] b, int offset) {
b[offset]=(byte)((integer & 0xff000000)>>>24);
b[offset+1]=(byte)((integer & 0x00ff0000)>>>16);
b[offset+2]=(byte)((integer & 0x0000ff00)>>>8);
b[offset+3]=(byte)((integer & 0x000000ff));
}*/

}

 

Test It

import java.io.*;
import static java.lang.System.out;

public class TestingFiles {

private static final String filename = "INPUTBYTES";

/*
* I am just testing with 5 integers but you can practically
* use any number which is a multiple of 4.
*/
private static final int numOfBytes = 20;

public static void main(String[] args) throws IOException{
out.println("Writing to File");
WriteFile.generateIntegersAndStoreInFileAsBytes(filename,numOfBytes);
out.println("Reading from File");
int[] ints = ReadFile.getIntegersStoredAsBytesFromFile(filename,numOfBytes);
for (int i: ints) {
out.println(i);
}
}


}


Here is the output:
Writing to File
931158145
189423544
641759623
-1731070039
1477642147
Reading from File
931158145
189423544
641759623
-1731070039
1477642147