Pages

Showing posts with label JAVA. Show all posts
Showing posts with label JAVA. Show all posts

Tuesday, July 31, 2012

Spring - Making a self configurable project

In my projects I prefer having self configurable solutions and avoid any additional involvement for deploying an enterprise application (EAR file).  For example, if the project needs to call some web services but the host address depends of the environment where the deploying is occurring (i.e. DEV, QAT, UAT, PROD).  Or you might need specific settings in each environment like DEV where you want to have more traces and debug information.  Imagine having to configure each setting every time you deploy...  plus this is prone to errors.


So how to make the solution self configurable?

In my case I use a combination of the JAVA env variable and Spring.

Set ENV Variable

Configure the JVM which hosts your application and set the vm argument:  -Denv <name>.

For example if using Geronimo application server, I will set this in the Launch Configuration where the VM arguments are configured.

-javaagent:"$(GERONIMO_HOME)/lib/agent/transformer.jar" -Djava.ext.dirs="$(GERONIMO_HOME)/lib/ext;$(JRE_HOME)/lib/ext" -Djava.endorsed.dirs="$(GERONIMO_HOME)/lib/endorsed;$(JRE_HOME)/lib/endorsed" -Xms512m -Xmx1024m -XX:MaxPermSize=512m -Dorg.apache.geronimo.home.dir="$(GERONIMO_HOME)" -Dkaraf.home="$(GERONIMO_HOME)" -Dkaraf.base="$(GERONIMO_HOME)" -Djava.util.logging.config.file="$(GERONIMO_HOME)/etc/java.util.logging.properties" -Dkaraf.startLocalConsole=false -Dkaraf.startRemoteShell=false -Denv=dev

Spring - ENV Configuration

I use Spring Framework to handle many of the dynamic characteristics of the project.  With Spring I can read the JVM env variable and do the following inside the applicationContext.xml file to achieve a self-configurable solution.

Spring - ApplicationContext.xml

This file is used by Spring to configure the application being loaded.  In the configuration I list two files:  application.properties and application.${env}.properties.  Notice the property files are bundle in the compiled JAR, so they are not easily visible nor accessible.  Plus you don't have to worry about the physical path since the files will be in the classpath.  The reason for having two files is that I can use one for all the general properties and another for environment specific settings.  Be careful that the order of the property files is important in the applicationContext.xml for how values are overridden.


    
    classpath:com/jonnazario/myapp/properties/application.properties
    classpath:com/jonnazario/myapp/properties/application.${env}.properties
    






    
    
    

For my preference I have a SystemProperties class which I load with values that are important for the application (i.e. Version, DevModeEnabled, HostName). For this I pass the property values as arguments to the constructor and if they are not defined in the property files, I still set the default values within the applicationContext.xml file.

Properties file

These are example values for the general and environment specific application properties files.  See how some properties are overridden while other are not defined at all.

Configuration - General
# -- General Properties
app.Version=2012.07.01.00
app.devModeEnabled=false

Configuration - DEV
# -- DEV Properties
app.Version=work.in.progress
app.devModeEnabled=true

Configuration - PROD
# -- PROD Properties
app.hostname=www.myapp.com


Hope this helps.

Thursday, June 28, 2012

JAVA - Generics and design

What is generics?

Is a programming functionality which allows a type or method to operate on objects of various types while providing compile-time type safety. [1]  Generics add stability to your code by making more of your bugs detectable at compile time. [2]

The basic syntax in JAVA is <T extends MyClass>, where T is the generic variable to be used in the function implementation which in this case it will handle MyClass and all subclasses.  Imagine you need a function to sort objects of MyClass type and all their subclasses.  Without generics you will need a function per type.  But thanks to generics you can have only one function to handle all subclasses.


Example:  
Non-Generic Generic
public void MyFunction(MyClass aClass);
public void MyFunction2(AnotherClass aClass);
....
public <T extends MyClass> void MyFunction(T aClass);
Duplicate code to handle each subclass Only one function can handle all classes derived from MyClass


For detail implementaion information:

http://docs.oracle.com/javase/tutorial/java/generics/index.html


Generics are useful for...

The power of generics can be appreciated when designing components that other developers will use.  I find this specially important when you need to constrain the domain, but leaving it generic enough.  So why constrain the domain if we are talking about generics usage?  Because in my experience, developers take nasty shortcuts (supposedly to save time...) and use arguments type of strings or objects, or any wtfClass to hack there needs. Having a well define generic function will help other developers understand better the input of a method and avoid errors.


Example:  Generics and Design

In this example application we have an Activity which processes a ResultRes container.  The only purpose of an Activity is to modify the values of the ResultRes object.  You will see how using generics avoids unexpected errors and help developers understand better the classes needed to interact with an activity.

Download:  Source Code
Read the comments in the code for insight about the demonstration...

Parts of the application:

  • ResultRes - is the generic results container.
  • IntegerRes & StringRes - are sub-classes of ResultRes with different value types. 
  • ExecTemplate - is the generic class for activity execution.
    Notice how the template definition is the main issue in the design.
  • ActivityInt & ActivityString - are implementations of the ExecTemplate.
  • ExecGenerics - is just the Main() for testing the project. 

Main Program - usage of generics...

package generics.main;
public class ExecGenerics {

 /**
  * Example application about design and usage of generics.
  * The functionality is just to present how a background processing 
  * can cause exceptions due to bad design implementation which could
  * been avoided.
  */
 public static void main(String[] args) {
  
  boolean isUsingOriginal = true;
  
  // Set starter values...
  // This value will be modified by execute()
  IntegerRes i = new IntegerRes();
  i.setFieldValue(123);   
  StringRes s = new StringRes();
  s.setFieldValue("123");

  // print original values
  System.out.println(i.getFieldValue());
  System.out.println(s.getFieldValue());
 
  if (isUsingOriginal) {
   new generics.original.ActivityInt().execute(i);
   new generics.original.ActivityInt().execute(s); 
   // -- ^^^ this is LEGAL & PROBLEM.. execution will fail!
   new generics.original.ActivityString().execute(s);
  }
  else {
   new generics.improved.ActivityInt().execute(i); 
   // -- ^^^ watch how the helper shows the correct input class 
   // -- ^^^ (Ctrl+Space) inside parenthesis
   // new generics.improved.ActivityInt().execute(s); 
   // -- ^^^  this is NOT LEGAL NOW.. (won't compile)
   new generics.improved.ActivityString().execute(s); 
   // -- ^^^  watch how the helper shows the correct input class 
   // -- ^^^  (Ctrl+Space) inside parenthesis
  }
 
  // print values after processing
  System.out.println(i.getFieldValue());
  System.out.println(s.getFieldValue());  
 }
}


Execution Results

original (isUsingOriginal = true)
123
123
EXEC:  START    - class generics.original.ActivityInt
EXEC:  COMPLETE - class generics.original.ActivityInt
EXEC:  START    - class generics.original.ActivityInt
Exception in thread "main" java.lang.ClassCastException:
 generics.shared.StringRes cannot be cast to generics.shared.IntegerRes
 at generics.original.ActivityInt.performAction(ActivityInt.java:10)
 at generics.original.ExecTemplate.execute(ExecTemplate.java:11)
 at generics.main.ExecGenerics.main(ExecGenerics.java:32)
improved (isUsingOriginal = false)
123
123
EXEC:  START    - class generics.improved.ActivityInt
EXEC:  COMPLETE - class generics.improved.ActivityInt
EXEC:  START    - class generics.improved.ActivityString
EXEC:  COMPLETE - class generics.improved.ActivityString
999
999

Execute Template - Generic template design...

original
package generics.original;
public abstract class ExecTemplate {

 protected abstract void performAction(ResultRes res);
 
 public void execute(ResultRes res) {
   System.out.println("EXEC:  START    - " + this.getClass().toString());
   this.performAction(res);
   System.out.println("EXEC:  COMPLETE - " + this.getClass().toString());  
 }
}
improved
package generics.improved;
public abstract class ExecTemplate<T extends ResultRes> {

 protected abstract void performAction(T res);
 
 public void execute(T res) {
   System.out.println("EXEC:  START    - " + this.getClass().toString());
   this.performAction(res);
   System.out.println("EXEC:  COMPLETE - " + this.getClass().toString());  
 }
}

Activity - No casting needed when well designed...

original
package generics.original;
public class ActivityInt extends ExecTemplate {

 @Override
 protected void performAction(ResultRes res) {
  IntegerRes r = (IntegerRes) res;  // <-- Casting is required and not safe...
  r.setFieldValue(999);
 }
}
improved
package generics.improved;
public class ActivityInt extends ExecTemplate<IntegerRes> {

 @Override
 protected void performAction(IntegerRes res) {
  res.setFieldValue(999);  // <-- No casting required and enforces type
 }
}